rewritten: sessions management

(Session, SessionContainer, SessionManager)
           now a Session object don't copy all fields in its copy constructor (only id)
           the rest fields are set after the object is inserted in SessionContainer
added:     after successfully login a session id is changed
added:     plugin.Call() methods with a first argument a pointer to a Session object



git-svn-id: svn://ttmath.org/publicrep/winix/trunk@823 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2012-03-17 05:11:23 +00:00
parent 70421b7bd1
commit e83fd91423
25 changed files with 444 additions and 183 deletions

View File

@ -158,7 +158,7 @@ bool App::Init()
post_parser.LogValueSize(config.log_post_value_size);
// post_multi_parser has a pointer to the config
plugin.Call(WINIX_PLUGIN_INIT);
plugin.Call((Session*)0, WINIX_PLUGIN_INIT);
return true;
}

View File

@ -323,12 +323,12 @@ bool moved = false;
item_work.file.has_thumb = true;
db->EditHasThumbById(true, item_work.file.id);
log << log3 << "Image: generated a thumbnail: " << dst_path << logend;
plugin.Call(WINIX_CREATED_THUMB, &item_work.file);
plugin.Call((Session*)0, WINIX_CREATED_THUMB, &item_work.file);
}
else
{
log << log3 << "Image: image resized: " << dst_path << logend;
plugin.Call(WINIX_IMAGE_RESIZED, &item_work.file);
plugin.Call((Session*)0, WINIX_IMAGE_RESIZED, &item_work.file);
}
moved = true;

View File

@ -107,6 +107,13 @@ LastTab::iterator i = FindNotLoggedOut(user_id, session_id);
}
else
{
log << log4 << "LC: there is no such a user to log out" << logend;
/*
!! IMPROVE ME
users read from the session file (at boot time)
are not added to LastContainer
*/
log << log4 << "LC: there is no such a user to log out: user_id: "
<< user_id << " ses_id: " << session_id << logend;
}
}

View File

@ -70,7 +70,7 @@ void Mounts::CreateMounts()
CreateMountFs();
CreateMountPar();
plugin.Call(WINIX_ADD_MOUNTS);
plugin.Call((Session*)0, WINIX_ADD_MOUNTS);
empty_mount.param.resize(mount_par_tab.size());
empty_mount.ClearParams();
@ -191,7 +191,7 @@ void Mounts::ReadMounts(const std::wstring & mounts)
mount_parser.Parse(mounts, mount_tab);
CalcCurMount();
plugin.Call(WINIX_FSTAB_CHANGED);
plugin.Call((Session*)0, WINIX_FSTAB_CHANGED);
}

View File

@ -251,16 +251,17 @@ bool Plugin::HasMessage(int message)
}
void Plugin::Call(int message, Slots::iterator & slot, PluginInfo & info)
void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info)
{
if( !SetPointers(info) )
return;
current_plugin = slot->second.index;
info.plugin_id = current_plugin;
info.session = ses;
if( current_plugin != -1 )
info.plugin_data_base = cur->session->plugin_data.Get(current_plugin);
if( current_plugin != -1 && ses )
info.plugin_data_base = ses->plugin_data.Get(current_plugin);
else
info.plugin_data_base = 0;
@ -295,7 +296,7 @@ void Plugin::Call(int message, Slots::iterator & slot, PluginInfo & info)
void Plugin::Call(int message, void * p1_, void * p2_, long l1_, long l2_)
void Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_)
{
// how many plugins return 'false' and 'true'
// we are using local variables because Call() method can be called
@ -315,7 +316,7 @@ PluginInfo info;
info.l1 = l1_;
info.l2 = l2_;
Call(message, i, info);
Call(ses, message, i, info);
if( info.res )
++ret_true_loc;
@ -331,52 +332,104 @@ PluginInfo info;
void Plugin::Call(int message)
{
Call(message, 0, 0, 0, 0);
Call(cur->session, message, 0, 0, 0, 0);
}
void Plugin::Call(int message, void * p1_)
{
Call(message, p1_, 0, 0, 0);
Call(cur->session, message, p1_, 0, 0, 0);
}
void Plugin::Call(int message, void * p1_, void * p2_)
{
Call(message, p1_, p2_, 0, 0);
Call(cur->session, message, p1_, p2_, 0, 0);
}
void Plugin::Call(int message, long l1_)
{
Call(message, 0, 0, l1_, 0);
Call(cur->session, message, 0, 0, l1_, 0);
}
void Plugin::Call(int message, long l1_, long l2_)
{
Call(message, 0, 0, l1_, l2_);
Call(cur->session, message, 0, 0, l1_, l2_);
}
void Plugin::Call(int message, void * p1_, long l1_)
{
Call(message, p1_, 0, l1_, 0);
Call(cur->session, message, p1_, 0, l1_, 0);
}
void Plugin::Call(int message, void * p1_, long l1_, long l2_)
{
Call(message, p1_, 0, l1_, l2_);
Call(cur->session, message, p1_, 0, l1_, l2_);
}
void Plugin::Call(int message, void * p1_, void * p2_, long l1_)
{
Call(message, p1_, p2_, l1_, 0);
Call(cur->session, message, p1_, p2_, l1_, 0);
}
void Plugin::Call(Session * ses, int message)
{
Call(ses, message, 0, 0, 0, 0);
}
void Plugin::Call(Session * ses, int message, void * p1_)
{
Call(ses, message, p1_, 0, 0, 0);
}
void Plugin::Call(Session * ses, int message, void * p1_, void * p2_)
{
Call(ses, message, p1_, p2_, 0, 0);
}
void Plugin::Call(Session * ses, int message, long l1_)
{
Call(ses, message, 0, 0, l1_, 0);
}
void Plugin::Call(Session * ses, int message, long l1_, long l2_)
{
Call(ses, message, 0, 0, l1_, l2_);
}
void Plugin::Call(Session * ses, int message, void * p1_, long l1_)
{
Call(ses, message, p1_, 0, l1_, 0);
}
void Plugin::Call(Session * ses, int message, void * p1_, long l1_, long l2_)
{
Call(ses, message, p1_, 0, l1_, l2_);
}
void Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_)
{
Call(ses, message, p1_, p2_, l1_, 0);
}
size_t Plugin::Size()
{
return plugins.size();

View File

@ -67,8 +67,17 @@ struct PluginInfo
Synchro * synchro;
SessionManager * session_manager;
// pointer to the plugin session (can be null if not set by the plugin)
// you should use WINIX_SESSION_CREATED and WINIX_SESSION_REMOVE
// a session
// some messages are sent in a session's context e.g. logging a user
// this pointer in not always the same as cur->session, it is preferred
// to use this pointer instead of cur->session
// (cur->session can point at a temporary object)
// this pointer can be null
Session * session;
// pointer to the plugin session (can be null if not set by the plugin or if session is null)
// this is taken from session->plugin_data.Get()
// you should use WINIX_SESSION_CREATED and WINIX_PLUGIN_SESSION_DATA_REMOVE
// to create your plugin's session data
PluginDataBase * plugin_data_base; // !! zmienic nazwe na plugin_session_base ? a moze session_base; a moze plugin_session?
@ -86,8 +95,9 @@ struct PluginInfo
l1 = 0;
l2 = 0;
plugin_id = -1;
plugin_data_base = 0;
plugin_id = -1;
session = 0;
plugin_data_base = 0;
res = false;
}
@ -166,8 +176,17 @@ public:
void Call(int message, void * p1_, long l1_);
void Call(int message, void * p1_, long l1_, long l2_);
void Call(int message, void * p1_, void * p2_, long l1_);
void Call(int message, void * p1_, void * p2_, long l1_, long l2_);
void Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_);
void Call(Session * ses, int message);
void Call(Session * ses, int message, void * p1_);
void Call(Session * ses, int message, void * p1_, void * p2_);
void Call(Session * ses, int message, long l1_);
void Call(Session * ses, int message, long l1_, long l2_);
void Call(Session * ses, int message, void * p1_, long l1_);
void Call(Session * ses, int message, void * p1_, long l1_, long l2_);
void Call(Session * ses, int message, void * p1_, void * p2_, long l1_);
// how many plugins there are
size_t Size();
@ -211,7 +230,7 @@ private:
std::string afilename;
void * LoadInitFun(const char * filename, Fun1 & fun_init);
void Call(int message, Slots::iterator & slot, PluginInfo & info);
void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info);
bool SetPointers(PluginInfo & info);
};

View File

@ -10,10 +10,49 @@
#include "plugindata.h"
#include "plugin.h"
#include "log.h"
#include "session.h"
PluginData::PluginData()
{
session = 0;
}
PluginData::PluginData(const PluginData & p)
{
operator=(p);
}
PluginData & PluginData::operator=(const PluginData & p)
{
// we don't copy all pointers - only resize the table
// pointers will be set to zero
Resize(p.Size());
session = 0;
return *this;
}
PluginData::~PluginData()
{
DeleteAll();
}
void PluginData::SetSession(Session * ses)
{
session = ses;
}
void PluginData::Assign(size_t index, PluginDataBase * data)
{
@ -62,44 +101,37 @@ return Get(plugin.current_plugin);
void PluginData::DeleteAll()
{
if( table.empty() )
return;
bool all_null = true;
/*
when we copy a session's object (and this object then)
we resize the table and there are only null pointers there
consequently if all pointers are null there is no sens
to send WINIX_PLUGIN_SESSION_DATA_REMOVE
*/
for(size_t i=0 ; i<table.size() ; ++i)
{
if( table[i] != 0 )
{
all_null = false;
break;
}
}
/*
in the future this message may be removed
and we directly 'delete' the pointers
*/
if( !all_null )
plugin.Call(session, WINIX_PLUGIN_SESSION_DATA_REMOVE);
plugin.Call(WINIX_SESSION_REMOVE);
table.clear();
}
PluginData::PluginData()
{
}
PluginData::PluginData(const PluginData & p)
{
operator=(p);
}
PluginData & PluginData::operator=(const PluginData & p)
{
// we don't copy all pointers - only resize the table
// pointers will be set to zero
Resize(p.Size());
return *this;
}
PluginData::~PluginData()
{
DeleteAll();
}
size_t PluginData::Size() const

View File

@ -13,7 +13,7 @@
#include <vector>
class Session;
struct PluginDataBase
@ -21,9 +21,12 @@ struct PluginDataBase
virtual ~PluginDataBase() {}
/*
!! CHECK ME
it is still in use?
when deleting sessions we first call Clear() method
consequently the destructor has nothing to do
(and it doesn not throw an exception)
(and it does not throw an exception)
*/
virtual void Clear() {}
};
@ -35,6 +38,13 @@ class PluginData
{
public:
PluginData();
PluginData(const PluginData & p);
PluginData & operator=(const PluginData & p);
~PluginData();
void SetSession(Session * ses);
void Assign(size_t index, PluginDataBase * data);
void Assign(PluginDataBase * data);
@ -43,17 +53,13 @@ public:
void DeleteAll();
PluginData();
PluginData(const PluginData & p);
PluginData & operator=(const PluginData & p);
~PluginData();
size_t Size() const;
void Resize(size_t new_size);
private:
Session * session;
std::vector<PluginDataBase*> table;
};

View File

@ -11,8 +11,10 @@
#ifndef headerfile_winix_core_pluginmsg
#define headerfile_winix_core_pluginmsg
// here you can add your own EZC functions ([function])
// PluginInfo.p1 is a pointer to Ezc::Functions object
// session pointer is null
#define WINIX_TEMPLATES_CREATEFUNCTIONS 999
// here you can add your own EZC functions to notify system
@ -24,6 +26,7 @@
// Ezc::Functions<NotifyStream> ezc_functions;
// and Notify Stream is:
// typedef TextStream<std::wstring> NotifyStream;
// session pointer is null
#define WINIX_NOTIFY_TEMPLATES_CREATEFUNCTIONS 998
// winix function and parameters have been parsed
@ -48,13 +51,22 @@
// here you should remove your session data
// this message can be sent even if you don't assing your plugin data
#define WINIX_SESSION_REMOVE 30010
#define WINIX_PLUGIN_SESSION_DATA_REMOVE 30010
// when a session is changed (you can save a pointer to your data here)
// 'session changed' means that there is a new request
// !! IMPROVE ME it has to be changed to a better name
#define WINIX_SESSION_CHANGED 30020
// a session has changed its id
// it is typically when you are logging in
// 'login' winix function will change the session id (for security reasons)
// in l1 you have the old id, in l2 you have the new id
#define WINIX_SESSION_CHANGED_ID 30025
// the winix is closing
// there is not any sessions available (cur->session is null)
// session pointer is null
#define WINIX_CLOSE 30040
// preparing to remove a file (rm function)
@ -84,14 +96,17 @@
// winix is initialized,
// now you can initialize your plugin
// session pointer is null
#define WINIX_PLUGIN_INIT 30080
// here you can add your own mount point, file systems, mount parameters
// for adding a new mount type call: system->mounts.AddMountType("new_mount_name")
// session pointer is null
#define WINIX_ADD_MOUNTS 30090
// add plugin functions (winix functions) here
// call info.functions->Add() to add a function
// session pointer is null
#define WINIX_CREATE_FUNCTIONS 30100
// choose a default function
@ -100,11 +115,13 @@
// /etc/fstab has been changed
// now we have new mount points
// session pointer is null
#define WINIX_FSTAB_CHANGED 30120
// here you add your own template to notification system
// call system->notify.AddTemplate() method
// with a template file name
// session pointer is null
#define WINIX_NOTIFY_ADD_TEMPLATE 30130
// the request is being ended
@ -143,14 +160,16 @@
// a thumbnail was created
// this message is called from another thread
// the thread is called Lock() before sending this message
// the thread called Lock() before sending this message
// in p1 you have a pointer to the Item struct
// session pointer is null
#define WINIX_CREATED_THUMB 30500
// an image has been resized
// this message is called from another thread
// the thread is called Lock() before sending this message
// the thread called Lock() before sending this message
// in p1 you have a pointer to the Item struct
// session pointer is null
#define WINIX_IMAGE_RESIZED 30520
// content of a directory was sorted
@ -165,6 +184,8 @@
// a WINIX_USER_LOGGED is sent
// in p1 you have a pointer to User struct
// (if at least one plugin returns false then the user will not be logged)
// this message is not sent when winix starts and sessions are read from a sessions file
// in such a case only WINIX_USER_LOGGED will be sent
#define WINIX_PREPARE_USER_TO_LOGIN 30550
// a user has been logged
@ -175,6 +196,9 @@
// a user is going to logout
// in p1 you have a pointer to User struct
// the message is also sent from the session GC (special thread for deleting sessions)
// in such a case is sent with Lock() and Unlock()
// so *don't* use Lock() in your procedure
#define WINIX_PREPARE_USER_TO_LOGOUT 30610
// here you add your own html templates
@ -185,6 +209,7 @@
// the message will be sent too whenever 'reload/templates' winix function is called
// templates you should add only in this message
// in other cases after 'reload' function the indexes would be wrong
// session pointer is null
#define WINIX_ADD_TEMPLATE 31000
// a user will be removed

View File

@ -17,9 +17,34 @@ Session::Session()
{
SetTimeToNow();
Clear();
plugin_data.SetSession(this);
}
Session::Session(const Session & ses)
{
operator=(ses);
}
Session & Session::operator=(const Session & ses)
{
/*
we can only copy ses.id because it is needen in SessionContainer
it have indexes to id
*/
Clear();
id = ses.id;
plugin_data.SetSession(this);
return *this;
}
void Session::SetTimeToNow()
{
time = std::time(0);
@ -34,10 +59,9 @@ void Session::SetTimeToNow()
// this doesn't clear times
void Session::Clear()
void Session::Clear(bool clear_plugin_data)
{
id = 0;
time = 0;
puser = 0;
rebus_item = 0;
rebus_checked = false;
@ -45,7 +69,9 @@ void Session::Clear()
new_session = true;
spam_score = 0;
remove_me = false;
plugin_data.Resize(0);
if( clear_plugin_data )
plugin_data.Resize(0);
}

View File

@ -21,12 +21,17 @@
#include "textstream.h"
// when deleting Sessions you should set request.session into the session object as well
// this allows to delete plugins session data
// because a session object has plugin_data object
// and in its destructor the plugin.Call(WINIX_SESSION_REMOVE) is called
struct Session
{
Session();
Session(const Session & ses);
Session & operator=(const Session & ses);
void SetTimeToNow();
void Clear(bool clear_plugin_data = true);
// 0 - means that there is a temporary session
long id;
@ -75,9 +80,6 @@ struct Session
// used by some javascript wysiwyg editors (ckeditor, tinymce)
std::vector<std::wstring> last_css;
Session();
void SetTimeToNow();
void Clear();
};

View File

@ -44,43 +44,52 @@ Table::iterator i = table.begin();
log << log3 << "SC: deleting all sessions" << logend;
cur->session = tmp_session;
// don't use table.clear();
// because plugins session data would not be erased
// we must set cur->session for each session and then delete it
while( i != table.end() )
{
cur->session = &(*i);
cur->session->plugin_data.DeleteAll(); // it's better to call it here instead of the destructor
i->plugin_data.DeleteAll(); // it's better to call it here instead in the destructor
table.erase(i++);
}
// erasing indexes
index_id.clear();
table_size = 0;
cur->session = tmp_session;
}
void SessionContainer::EraseById(IdIterator i)
void SessionContainer::EraseById(long id)
{
Session * old_session = tmp_session;
IndexId::iterator i = index_id.find(id);
if( cur->session != &(*i->second) )
old_session = cur->session;
if( i != index_id.end() )
{
Session * old_session = tmp_session;
cur->session = &(*i->second);
if( cur->session != &(*i->second) )
old_session = cur->session;
log << log4 << "SC: deleting session, id: " << i->second->id << logend;
cur->session = &(*i->second);
// call first DeleteAll() because if not then it would be called from the desctructor
// and there'll be a problem if it throws an exception there
i->second->plugin_data.DeleteAll();
table.erase(i->second);
index_id.erase(i);
table_size -= 1;
log << log4 << "SC: deleting session, id: " << i->second->id << logend;
cur->session = old_session;
// call first DeleteAll() because if not then it would be called from the destructor
// and there'll be a problem if it throws an exception there
i->second->plugin_data.DeleteAll();
table.erase(i->second);
index_id.erase(i);
table_size -= 1;
cur->session = old_session;
}
else
{
log << log1 << "SC: I cannot delete a session with id: " << id
<< " (there is no such a session)" << logend;
}
}
@ -123,23 +132,24 @@ SessionContainer::IdIterator SessionContainer::IdEnd()
bool SessionContainer::PushBack(const Session & session)
SessionContainer::Iterator SessionContainer::AddSession(long id)
{
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(session.id, table.end()) );
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(id, table.end()) );
if( !index_id_res.second )
{
// that element already exists (was not inserted now)
return false;
return End();
}
Iterator last = table.insert(table.end(), session);
Iterator last = table.insert(table.end(), empty_session);
last->id = id;
index_id_res.first->second = last;
table_size += 1;
log << log3 << "SC: added session, id: " << session.id << logend;
log << log3 << "SC: added session, id: " << id << logend;
return true;
return last;
}
@ -158,6 +168,41 @@ return i->second;
}
bool SessionContainer::ChangeSessionId(SessionContainer::Iterator ses, long new_id)
{
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(new_id, ses) );
if( !index_id_res.second )
{
log << log1 << "SC: session with id: " << new_id << " already exists" << logend;
return false;
}
long old_id = ses->id;
index_id.erase(old_id); // remove the old index
ses->id = new_id;
log << log3 << "SC: changed session id from: " << old_id << " to " << new_id << logend;
return true;
}
bool SessionContainer::ChangeSessionId(long old_id, long new_id)
{
IndexId::iterator i = index_id.find(old_id);
if( i != index_id.end() )
{
return ChangeSessionId(i->second, new_id);
}
else
{
log << log2 << "SC: there is no a session with id: " << old_id << logend;
}
return false;
}

View File

@ -24,10 +24,6 @@ class SessionContainer
{
public:
// when deleting Sessions you should set cur->session into the session object
// this allows to delete plugins session data
// because a session object has plugin_data object
// and in its destructor the plugin.Call(WINIX_SESSION_REMOVE) is called
typedef std::list<Session> Table;
typedef Table::iterator Iterator;
typedef std::map<long, Iterator> IndexId;
@ -46,13 +42,16 @@ public:
Iterator Begin();
Iterator End();
Session & Back();
bool PushBack(const Session & session);
Iterator AddSession(long id);
Iterator FindById(long);
IdIterator IdBegin();
IdIterator IdEnd();
void EraseById(IdIterator i);
void EraseById(long id);
bool ChangeSessionId(Iterator ses, long new_id);
bool ChangeSessionId(long old_id, long new_id);
private:
@ -63,6 +62,8 @@ private:
Config * config;
Session * tmp_session;
Session empty_session;
// in FreeBSD implementation (GCC) list::size() has linear complexity
// so we use our own table_size with O(1)
size_t table_size;

View File

@ -108,18 +108,15 @@ return id;
void SessionManager::CreateSession()
{
int attempts = 100;
bool added = false;
new_session.SetTimeToNow();
new_session.Clear();
int attempts = 100;
SessionContainer::Iterator i = session_tab.End();
if( config->session_max == 0 || session_tab.Size() < config->session_max )
{
for( ; !added && attempts > 0 ; --attempts )
for( ; i == session_tab.End() && attempts > 0 ; --attempts )
{
new_session.id = CreateSessionId();
added = session_tab.PushBack(new_session);
long id = CreateSessionId();
i = session_tab.AddSession(id);
}
}
else
@ -127,10 +124,12 @@ bool added = false;
log << log2 << "SM: sessions limit exceeded (" << config->session_max << ")" << logend;
}
if( added )
if( i != session_tab.End() )
{
session = &session_tab.Back();
session = &(*i);
session->new_session = true;
session->SetTimeToNow();
log << log2 << "SM: created a new session: " << session->id << logend;
}
else
@ -138,8 +137,8 @@ bool added = false;
// there is a problem with generating a new session id
// we do not set a session cookie
session = &temporary_session;
session->Clear(false);
session->SetTimeToNow();
session->Clear(); // !! uwaga ten Clear wyczysci plugins data
session->new_session = false; // temporary session was initialized at the beginning
log << log1 << "SM: cannot create a session id (temporary used: with id 0)" << logend;
}
@ -226,8 +225,7 @@ void SessionManager::DeleteSessions()
{
if( i->puser && !i->remember_me )
{
cur->session = &(*i); // for correctly setting a session data in plugins
plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
}
}
@ -237,6 +235,41 @@ void SessionManager::DeleteSessions()
/*
don't change a session's id when a user is logged
the session id is in last_container and the user would not be
correctly removed from the container
*/
bool SessionManager::ChangeSessionId(long old_id)
{
int attempts = 100;
bool changed = false;
long new_id;
SessionContainer::Iterator i = session_tab.FindById(old_id);
if( i != session_tab.End() )
{
for( ; !changed && attempts > 0 ; --attempts )
{
new_id = CreateSessionId();
changed = session_tab.ChangeSessionId(i, new_id);
}
if( changed )
plugin.Call(&(*i), WINIX_SESSION_CHANGED_ID, old_id, new_id);
else
log << log1 << "SM: I cannot create a new session id (still uses old one)" << logend;
}
else
{
log << log2 << "SM: there is no a session with id: " << old_id << logend;
}
return changed;
}
void SessionManager::InitTmpSession()
{
Session * old_session = cur->session;
@ -256,7 +289,7 @@ void SessionManager::UninitTmpSession()
log << log4 << "SM: uninitializing temporary session" << logend;
cur->session = &temporary_session;
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_SESSION_REMOVE);
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_PLUGIN_SESSION_DATA_REMOVE);
cur->session->plugin_data.Resize(0);
cur->session = old_session;
@ -278,11 +311,15 @@ SessionContainer::Iterator i;
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
{
i->plugin_data.Resize(plugin.Size());
cur->session = &(*i);
plugin.Call(WINIX_SESSION_CREATED);
plugin.Call(&(*i), WINIX_SESSION_CREATED);
if( cur->session->puser )
plugin.Call(WINIX_USER_LOGGED);
/*
!! IMPROVE ME
we do not add it to the last_container (we don't have IP address stored yet)
*/
if( i->puser )
plugin.Call(&(*i), WINIX_USER_LOGGED);
}
cur->session = &temporary_session;
@ -347,14 +384,12 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
{
size_t how_many = 0;
SessionContainer::Iterator i;
Session * old_session = cur->session;
for(i=session_tab.Begin() ; i!=session_tab.End() ; ++i)
{
if( i->puser && i->puser->id == user_id )
{
cur->session = &(*i); // for correctly setting a session data in plugins
plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
i->remove_me = true;
i->puser = 0;
@ -362,8 +397,6 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
}
}
cur->session = old_session;
return how_many;
}
@ -374,18 +407,20 @@ return how_many;
*
*
* sessions gc (second thread)
*
* sessions are only removed here
* SessionContainer::IndexId can be removed from the other thread
* (when ChangeSessionId() method is called)
*
*/
void SessionManager::Work()
{
bool exit = false;
SessionContainer::IndexId::iterator i;
SessionContainer::Iterator i;
deleted = 0;
Lock();
i = session_tab.IdBegin();
i = session_tab.Begin();
Unlock();
while( !exit )
@ -401,11 +436,11 @@ SessionContainer::IndexId::iterator i;
// it's called from the other thread (with Lock and Unlock)
void SessionManager::CheckSession(SessionContainer::IndexId::iterator & i)
void SessionManager::CheckSession(SessionContainer::Iterator & i)
{
const int deleted_max_at_once = 10;
if( i == session_tab.IdEnd() )
if( i == session_tab.End() )
{
if( deleted > 0 )
{
@ -413,14 +448,16 @@ const int deleted_max_at_once = 10;
log << logsave;
}
i = session_tab.IdBegin();
i = session_tab.Begin();
WaitForSignalSleep(10);
}
else
{
if( i->second->remove_me || IsSessionOutdated(*i->second) )
if( i->remove_me || IsSessionOutdated(*i) )
{
DeleteSession(i++);
Session * ses = &(*i);
++i;
DeleteSession(ses);
++deleted;
}
else
@ -444,9 +481,13 @@ bool SessionManager::IsSessionOutdated(const Session & s) const
bool outdated;
if( s.remember_me )
{
outdated = s.last_time < std::time(0) - config->session_remember_max_idle;
}
else
{
outdated = s.last_time < std::time(0) - config->session_max_idle;
}
return outdated;
}
@ -454,14 +495,16 @@ return outdated;
// it's called from the other thread (with Lock and Unlock)
void SessionManager::DeleteSession(SessionContainer::IdIterator i)
void SessionManager::DeleteSession(Session * del_session)
{
Session * del_session = &(*i->second);
if( del_session->puser )
{
plugin.Call(del_session, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser);
last_container->UserLogout(del_session->puser->id, del_session->id);
del_session->puser = 0;
}
session_tab.EraseById(i);
session_tab.EraseById(del_session->id);
}

View File

@ -36,6 +36,7 @@ public:
void SetSession();
void DeleteSessions(); // deleting all sessions
bool ChangeSessionId(long old_id);
void InitTmpSession();
void UninitTmpSession();
@ -68,9 +69,6 @@ private:
// session with id 0
Session temporary_session;
// for adding a new session to the container
Session new_session;
bool IsSession(long s);
long CreateSessionId();
@ -81,9 +79,9 @@ private:
// second thread
int deleted;
virtual void Work();
void CheckSession(SessionContainer::IndexId::iterator & i);
void CheckSession(SessionContainer::Iterator & i);
bool IsSessionOutdated(const Session & s) const;
void DeleteSession(SessionContainer::IdIterator i);
void DeleteSession(Session * del_session);
};

View File

@ -51,33 +51,19 @@ bool SessionParser::Parse(SessionContainer & container)
file format, each rows:
session_id(long) user_id(long) remember_me(0|1) time(long) last_time(long)
*/
long user_id;
session.Clear();
last = file.get();
log << log2 << "SP: reading sessions from the session file" << logend;
while( true )
{
session.id = ReadLong();
long id = ReadLong();
if( file.eof() )
break;
user_id = ReadLong();
session.remember_me = ReadLong();
session.time = ReadLong();
session.last_time = ReadLong();
if( MakeSession(user_id) )
{
users->IncrementLoggedUsers();
container.PushBack(session);
log << log2 << "SP: read session id: " << session.id << " for user: " << session.puser->name << logend;
}
long user_id = ReadLong();
MakeSession(id, user_id, container);
SkipLine();
}
@ -87,22 +73,37 @@ return true;
}
bool SessionParser::MakeSession(long user_id)
void SessionParser::MakeSession(long id, long user_id, SessionContainer & container)
{
User * puser = users->GetUser(user_id);
if( !puser )
{
log << log1 << "SP: there is no a user with id: " << user_id << " (skipped)" << logend;
return false;
return;
}
session.puser = puser;
session.new_session = true;
session.tm_time = Time(session.time);
session.tm_last_time = Time(session.last_time);
SessionContainer::Iterator i = container.AddSession(id);
return true;
if( i != container.End() )
{
i->Clear();
i->id = id;
i->puser = puser;
i->new_session = true;
i->remember_me = ReadLong();
i->time = ReadLong();
i->last_time = ReadLong();
i->tm_time = Time(i->time);
i->tm_last_time = Time(i->last_time);
users->IncrementLoggedUsers();
log << log2 << "SP: read session id: " << id << " for user: " << puser->name << logend;
}
else
{
log << log1 << "SP: session with id: " << id << " already exists (skipping)" << logend;
}
}

View File

@ -31,7 +31,7 @@ private:
Users * users;
bool Parse(SessionContainer & container);
bool MakeSession(long user_id);
void MakeSession(long id, long user_id, SessionContainer & container);
bool IsWhite(int c);
bool IsDigit(int c);
@ -42,7 +42,6 @@ private:
std::ifstream file;
int last; // last character
Session session;
};

View File

@ -231,6 +231,10 @@ bool Users::LoginUser(long user_id, bool remember_me, bool use_ses_log)
cur->session->spam_score = 0;
cur->session->remember_me = remember_me;
// change session id before last.UserLogin()
if( !cur->session->new_session )
session_manager->ChangeSessionId(cur->session->id);
last.UserLogin(user_id, cur->session->puser->name, inet_addr(cur->request->env_remote_addr), cur->session->id);
how_many_logged += 1;

View File

@ -217,7 +217,7 @@ void Functions::CreateFunctions()
Add(fun_who);
Add(fun_vim);
plugin.Call(WINIX_CREATE_FUNCTIONS);
plugin.Call((Session*)0, WINIX_CREATE_FUNCTIONS);
}

View File

@ -139,7 +139,7 @@ int main(int argv, char ** argc)
app.Start();
app.Lock();
plugin.Call(WINIX_CLOSE);
plugin.Call((Session*)0, WINIX_CLOSE);
app.Close();
// now all sessions are cleared
app.Unlock();

View File

@ -67,7 +67,7 @@ void Notify::Init()
notify_template_activate_account = AddTemplate(L"notify_confirm_account.txt");
notify_template_reset_password = AddTemplate(L"notify_reset_password.txt");
plugin.Call(WINIX_NOTIFY_ADD_TEMPLATE);
plugin.Call((Session*)0, WINIX_NOTIFY_ADD_TEMPLATE);
}

View File

@ -103,7 +103,7 @@ void CreateFunctions()
ezc_functions.Insert("notify_item_link", notify_item_link);
ezc_functions.Insert("notify_dir_link", notify_dir_link);
plugin.Call(WINIX_NOTIFY_TEMPLATES_CREATEFUNCTIONS, &ezc_functions);
plugin.Call((Session*)0, WINIX_NOTIFY_TEMPLATES_CREATEFUNCTIONS, &ezc_functions);
}

View File

@ -123,7 +123,7 @@ StatsSession * stats_session = 0;
void SessionCreated(PluginInfo & info)
{
StatsSession * d = new StatsSession();
info.cur->session->plugin_data.Assign(d);
info.session->plugin_data.Assign(d);
if( !info.cur->request->IsParam(nostat_param) )
{
@ -141,7 +141,7 @@ void RemoveSession(PluginInfo & info)
{
// temporarily for debug
// sometimes the pointer is null here
log << log1 << "Stats: why the info.plugin_data_base is zero? !!!!, ses_id: " << info.cur->session->id << logend;
log << log1 << "Stats: why the info.plugin_data_base is zero? !!!!, ses_id: " << info.session->id << logend;
return;
}
@ -200,7 +200,7 @@ using namespace Stats;