/* * This file is a part of CMSLU -- Content Management System like Unix * and is not publicly distributed * * Copyright (c) 2008-2009, Tomasz Sowa * All rights reserved. * */ #include #include "sessionmanager.h" #include "request.h" #include "log.h" #include "data.h" #include "session.h" #include "sessionparser.h" SessionManager::SessionManager() { session_checker = 0; } bool SessionManager::IsSession(long id) { if( session_table.FindById(id) == session_table.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_table.FindById( 0 ); if( i == session_table.End() ) { Session s; s.id = 0; session_table.PushBack(s); request.session = &session_table.Back(); } else { request.session = &(*i); } } void SessionManager::CreateSession() { Session s; int attempts = 100; for( ; attempts > 0 ; --attempts ) { s.id = CreateSessionId(); bool added = session_table.PushBack(s); if( added ) { request.session = &session_table.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; } void SessionManager::SetSession() { CookieTable::iterator i = request.cookie_table.find(data.http_session_id_name); if( i == request.cookie_table.end() ) { CreateSession(); } else { long id = atol(i->second.c_str()); SessionContainer::Iterator s = session_table.FindById(id); if( s != session_table.End() ) { // that session is in the table request.session = &(*s); request.session->new_session = false; session_table.UpdateLastTime(s, std::time(0)); 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; } else { // there is no such a session // deleting the old cookie request.cookie_table.erase(i); // and creating a new one CreateSession(); } } // request.session is set now } SessionContainer::Iterator SessionManager::SessionBegin() { return session_table.Begin(); } SessionContainer::Iterator SessionManager::SessionEnd() { return session_table.End(); } void SessionManager::DeleteOldSessions() { session_table.DelFirstByTimeInterval(data.session_max_iddle); 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_table.DelFirstByTimeInterval(data.session_remember_max_iddle, false); } } void SessionManager::LoadSessions() { SessionParser sp; sp.Parse(data.session_file, session_table); } void SessionManager::SaveSessions() { if( data.session_file.empty() ) return; std::ofstream file(data.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_table.Begin(); for( ; i!=session_table.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(data.session_file.c_str(), 0600); log << log2 << "SM: saved " << len << " session(s)" << logend; }