Hello,
I think we have uncovered a bug in the core related to session garbage collection when custom sessions are enabled (ie: when using a custom session name in the preferences).
The session class in the kernel contains this function for handling session garbage collection:
function gc($expire)
{
$mintime = time() - intval($expire);
$sql = sprintf('DELETE FROM %s WHERE sess_updated < %u', $this->db->prefix('session'), $mintime);
return $this->db->queryF($sql);
}
As far as I can tell, that function is called by PHP itself on a random basis, based on certain settings in the PHP ini file (by default once out of every 100 page loads). The $expire time that gets passed to it is also set in the PHP ini file (session.gc_maxlifetime). By default that time is 1440 seconds, or 24 minutes.
So, if I'm correct about that, then this function causes a problem when you have custom session settings in effect, in particular a custom expiry time.
Suppose you have a custom session expiry time of 60 minutes. Suppose you have a user who is logged in and filling in a form for a long period of time, maybe a long and complicated forum posting, maybe a data entry form in Formulize. Now imagine that they spend more than 24 minutes sitting in front of the form typing (or maybe even not that long, but they got up in the middle to go to the bathroom, get a coffee, whatever).
So after 24 minutes goes by, their session is now vulnerable to being killed by the garbage collector, even though the custom session expiry time is 60 minutes. After 24 minutes, there is a 1 in 100 chance (according to the default settings) that each page load on the server will trigger the garbage collector, which will kill all sessions older than 24 minutes (again, according to the default setting).
So suppose that this user has their session killed by the garbage collector, then when they submit the form, they are told that they are logged out and/or don't have permission for the page they are viewing, their information from the form is not saved and they are booted back to the login screen.
Not a nice user experience!
I suggest that the garbage collection function be modified so that it checks whether a custom session name and expiry time is in effect, and if so, then that time is used by the garbage collection routine instead. Something like this:
function gc($expire)
{
global $xoopsConfig;
$expire = ($xoopsConfig['use_mysession'] && $xoopsConfig['session_name'] != '') ? $xoopsConfig['session_expire'] : $expire;
$mintime = time() - intval($expire);
$sql = sprintf('DELETE FROM %s WHERE sess_updated < %u', $this->db->prefix('session'), $mintime);
return $this->db->queryF($sql);
}
Any thoughts? Thanks very much,
--Julian
P.S. My session was killed while I was writing this (ironically enough!). Fortunately, clicking Back in Firefox remembers what I typed. If I were using IE, I might be totally screwed, if this page were generated by a $_POST request.