winix/core/sessionmanager.cpp

235 lines
4.1 KiB
C++
Executable File

/*
* 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 <sys/stat.h>
#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;
}