/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include #include "sessionmanager.h" #include "request.h" #include "log.h" #include "session.h" #include "sessionparser.h" #include "plugin.h" SessionManager::SessionManager() { session_checker = 0; } void SessionManager::SetRequest(Request * prequest) { request = prequest; session_tab.SetRequest(prequest); } void SessionManager::SetConfig(Config * pconfig) { config = pconfig; } void SessionManager::SetSystem(System * psystem) { system = psystem; } void SessionManager::SetLastContainer(LastContainer * plast_container) { session_tab.SetLastContainer(plast_container); } size_t SessionManager::Size() { return session_tab.Size(); } bool SessionManager::IsSession(long id) { if( session_tab.FindById(id) == session_tab.End() ) return false; return true; } long SessionManager::CreateSessionId() { long id; // make sure to call std::srand() somewhere at the beginning // id must be != 0 (0 is reserved) do { if( sizeof(long) == 8 ) { id = ((unsigned long)std::rand()) << 32 + std::rand(); } else { id = std::rand(); } id += std::time(0); if( id < 0 ) id = -id; } while( id == 0 ); // 0 reserved for a temporary session return id; } void SessionManager::CreateTemporarySession() { SessionContainer::Iterator i = session_tab.FindById( 0 ); if( i == session_tab.End() ) { Session s; s.id = 0; session_tab.PushBack(s); request->session = &session_tab.Back(); } else { request->session = &(*i); } } void SessionManager::CreateSession() { Session s; int attempts = 100; for( ; attempts > 0 ; --attempts ) { s.id = CreateSessionId(); bool added = session_tab.PushBack(s); if( added ) { request->session = &session_tab.Back(); request->session->new_session = true; log << log2 << "SM: created a new session: " << request->session->id << logend; return; } } // there is a problem with generating a new session id // we do not set a session cookie CreateTemporarySession(); log << log1 << "SM: cannot create a session id (temporary used: with id 0)" << logend; } bool SessionManager::SetSessionFromCookie(const std::string & cookie) { long id = Tol(cookie.c_str()); SessionContainer::Iterator s = session_tab.FindById(id); if( s == session_tab.End() ) return false; // that session is in the table request->session = &(*s); request->session->new_session = false; session_tab.UpdateLastTime(s, std::time(0)); if( request->method == Request::get ) request->session->last_time_get = request->session->last_time; log << log2 << "SM: session: " << s->id; if( request->session->puser ) log << log2 << ", user: " << request->session->puser->name << ", id: " << request->session->puser->id; log << log2 << logend; return true; } void SessionManager::SetSession() { CookieTab::iterator i = request->cookie_tab.find(config->http_session_id_name); if( i == request->cookie_tab.end() ) { CreateSession(); } else { if( !SetSessionFromCookie(i->second) ) { // there is no such a session // deleting the old cookie request->cookie_tab.erase(i); // and creating a new one CreateSession(); } } // request->session is set now if( request->session->new_session ) { request->session->plugin_data.Resize(plugin.Size()); plugin.Call(WINIX_SESSION_CREATED); } plugin.Call(WINIX_SESSION_CHANGED); } SessionContainer::Iterator SessionManager::SessionBegin() { return session_tab.Begin(); } SessionContainer::Iterator SessionManager::SessionEnd() { return session_tab.End(); } void SessionManager::DeleteOldSessions() { session_tab.DelFirstByTimeInterval(config->session_max_idle); if( ++session_checker > 1000 ) { // we make the test after 1000 requests log << log3 << "SM: checking sessions which have 'remember me' flag set" << logend; session_checker = 0; session_tab.DelFirstByTimeInterval(config->session_remember_max_idle, false); } } void SessionManager::DeleteSessions() { // first we delete all plugins date /* SessionContainer::Iterator i = session_tab.Begin(); Session * old_session = request->session; for( ; i!=session_tab.End() ; ++i ) { request->session = &(*i); i->plugin_data.DeleteAll(); } request->session = old_session; */ // and now we delete all sessions session_tab.Clear(); } void SessionManager::LoadSessions() { SessionParser sp; SessionContainer::Iterator i; sp.SetUsers(&system->users); Session * old_session = request->session; sp.Parse(config->session_file, session_tab); i = session_tab.Begin(); for( ; i!=session_tab.End() ; ++i ) { i->plugin_data.Resize(plugin.Size()); request->session = &(*i); plugin.Call(WINIX_SESSION_CREATED); } request->session = old_session; } void SessionManager::SaveSessions() { if( config->session_file.empty() ) return; std::ofstream file(config->session_file.c_str()); if( !file ) { log << log1 << "SM: cannot open the session file for writing - sessions lost" << logend; return; } log << log2 << "SM: saving sessions" << logend; long len = 0; SessionContainer::Iterator i = session_tab.Begin(); for( ; i!=session_tab.End() ; ++i ) { if( i->id != 0 && i->puser ) { file << i->id << ' ' << i->puser->id << ' ' << i->remember_me << ' '; file << (long)i->time << ' ' << (long)i->last_time << std::endl; ++len; } } file.close(); chmod(config->session_file.c_str(), 0600); log << log2 << "SM: saved " << len << " session(s)" << logend; }