|
|
|
@ -43,6 +43,7 @@ class rcube_session
|
|
|
|
|
private $logging = false;
|
|
|
|
|
private $memcache;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Default constructor
|
|
|
|
|
*/
|
|
|
|
@ -117,6 +118,7 @@ class rcube_session
|
|
|
|
|
* Read session data from database
|
|
|
|
|
*
|
|
|
|
|
* @param string Session ID
|
|
|
|
|
*
|
|
|
|
|
* @return string Session vars
|
|
|
|
|
*/
|
|
|
|
|
public function db_read($key)
|
|
|
|
@ -144,6 +146,7 @@ class rcube_session
|
|
|
|
|
*
|
|
|
|
|
* @param string Session ID
|
|
|
|
|
* @param string Serialized session vars
|
|
|
|
|
*
|
|
|
|
|
* @return boolean True on success
|
|
|
|
|
*/
|
|
|
|
|
public function db_write($key, $vars)
|
|
|
|
@ -173,7 +176,8 @@ class rcube_session
|
|
|
|
|
base64_encode($newvars), $key);
|
|
|
|
|
}
|
|
|
|
|
else if ($ts - $this->changed > $this->lifetime / 2) {
|
|
|
|
|
$this->db->query("UPDATE ".$this->db->table_name('session')." SET changed=$now WHERE sess_id=?", $key);
|
|
|
|
|
$this->db->query("UPDATE ".$this->db->table_name('session')
|
|
|
|
|
." SET changed=$now WHERE sess_id=?", $key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@ -202,9 +206,10 @@ class rcube_session
|
|
|
|
|
$newvars = $this->serialize(array_merge(
|
|
|
|
|
(array)$a_oldvars, (array)$this->unserialize($vars)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
else {
|
|
|
|
|
$newvars = $vars;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->unsets = array();
|
|
|
|
|
return $newvars;
|
|
|
|
@ -221,7 +226,8 @@ class rcube_session
|
|
|
|
|
public function db_destroy($key)
|
|
|
|
|
{
|
|
|
|
|
if ($key) {
|
|
|
|
|
$this->db->query(sprintf("DELETE FROM %s WHERE sess_id = ?", $this->db->table_name('session')), $key);
|
|
|
|
|
$this->db->query(sprintf("DELETE FROM %s WHERE sess_id = ?",
|
|
|
|
|
$this->db->table_name('session')), $key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
@ -275,6 +281,7 @@ class rcube_session
|
|
|
|
|
*
|
|
|
|
|
* @param string Session ID
|
|
|
|
|
* @param string Serialized session vars
|
|
|
|
|
*
|
|
|
|
|
* @return boolean True on success
|
|
|
|
|
*/
|
|
|
|
|
public function mc_write($key, $vars)
|
|
|
|
@ -292,8 +299,10 @@ class rcube_session
|
|
|
|
|
|
|
|
|
|
$newvars = $oldvars !== null ? $this->_fixvars($vars, $oldvars) : $vars;
|
|
|
|
|
|
|
|
|
|
if ($newvars !== $oldvars || $ts - $this->changed > $this->lifetime / 2)
|
|
|
|
|
return $this->memcache->set($key, serialize(array('changed' => time(), 'ip' => $this->ip, 'vars' => $newvars)), MEMCACHE_COMPRESSED, $this->lifetime);
|
|
|
|
|
if ($newvars !== $oldvars || $ts - $this->changed > $this->lifetime / 2) {
|
|
|
|
|
return $this->memcache->set($key, serialize(array('changed' => time(), 'ip' => $this->ip, 'vars' => $newvars)),
|
|
|
|
|
MEMCACHE_COMPRESSED, $this->lifetime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -369,8 +378,9 @@ class rcube_session
|
|
|
|
|
*/
|
|
|
|
|
public function remove($var=null)
|
|
|
|
|
{
|
|
|
|
|
if (empty($var))
|
|
|
|
|
if (empty($var)) {
|
|
|
|
|
return $this->destroy(session_id());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->unsets[] = $var;
|
|
|
|
|
unset($_SESSION[$var]);
|
|
|
|
@ -412,11 +422,14 @@ class rcube_session
|
|
|
|
|
private function serialize($vars)
|
|
|
|
|
{
|
|
|
|
|
$data = '';
|
|
|
|
|
if (is_array($vars))
|
|
|
|
|
if (is_array($vars)) {
|
|
|
|
|
foreach ($vars as $var=>$value)
|
|
|
|
|
$data .= $var.'|'.serialize($value);
|
|
|
|
|
else
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$data = 'b:0;';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -438,12 +451,14 @@ class rcube_session
|
|
|
|
|
while ($p < $endptr) {
|
|
|
|
|
$q = $p;
|
|
|
|
|
while ($str[$q] != '|')
|
|
|
|
|
if (++$q >= $endptr) break 2;
|
|
|
|
|
if (++$q >= $endptr)
|
|
|
|
|
break 2;
|
|
|
|
|
|
|
|
|
|
if ($str[$p] == '!') {
|
|
|
|
|
$p++;
|
|
|
|
|
$has_value = false;
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$has_value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -456,49 +471,57 @@ class rcube_session
|
|
|
|
|
for (;;) {
|
|
|
|
|
$p = $q;
|
|
|
|
|
switch (strtolower($str[$q])) {
|
|
|
|
|
case 'n': /* null */
|
|
|
|
|
case 'b': /* boolean */
|
|
|
|
|
case 'i': /* integer */
|
|
|
|
|
case 'd': /* decimal */
|
|
|
|
|
case 'n': // null
|
|
|
|
|
case 'b': // boolean
|
|
|
|
|
case 'i': // integer
|
|
|
|
|
case 'd': // decimal
|
|
|
|
|
do $q++;
|
|
|
|
|
while ( ($q < $endptr) && ($str[$q] != ';') );
|
|
|
|
|
$q++;
|
|
|
|
|
$serialized .= substr($str, $p, $q - $p);
|
|
|
|
|
if ($level == 0) break 2;
|
|
|
|
|
if ($level == 0)
|
|
|
|
|
break 2;
|
|
|
|
|
break;
|
|
|
|
|
case 'r': /* reference */
|
|
|
|
|
case 'r': // reference
|
|
|
|
|
$q+= 2;
|
|
|
|
|
for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++) $id .= $str[$q];
|
|
|
|
|
for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++)
|
|
|
|
|
$id .= $str[$q];
|
|
|
|
|
$q++;
|
|
|
|
|
$serialized .= 'R:' . ($id + 1) . ';'; /* increment pointer because of outer array */
|
|
|
|
|
if ($level == 0) break 2;
|
|
|
|
|
// increment pointer because of outer array
|
|
|
|
|
$serialized .= 'R:' . ($id + 1) . ';';
|
|
|
|
|
if ($level == 0)
|
|
|
|
|
break 2;
|
|
|
|
|
break;
|
|
|
|
|
case 's': /* string */
|
|
|
|
|
case 's': // string
|
|
|
|
|
$q+=2;
|
|
|
|
|
for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++) $length .= $str[$q];
|
|
|
|
|
for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++)
|
|
|
|
|
$length .= $str[$q];
|
|
|
|
|
$q+=2;
|
|
|
|
|
$q+= (int)$length + 2;
|
|
|
|
|
$serialized .= substr($str, $p, $q - $p);
|
|
|
|
|
if ($level == 0) break 2;
|
|
|
|
|
if ($level == 0)
|
|
|
|
|
break 2;
|
|
|
|
|
break;
|
|
|
|
|
case 'a': /* array */
|
|
|
|
|
case 'o': /* object */
|
|
|
|
|
case 'a': // array
|
|
|
|
|
case 'o': // object
|
|
|
|
|
do $q++;
|
|
|
|
|
while ( ($q < $endptr) && ($str[$q] != '{') );
|
|
|
|
|
while ($q < $endptr && $str[$q] != '{');
|
|
|
|
|
$q++;
|
|
|
|
|
$level++;
|
|
|
|
|
$serialized .= substr($str, $p, $q - $p);
|
|
|
|
|
break;
|
|
|
|
|
case '}': /* end of array|object */
|
|
|
|
|
case '}': // end of array|object
|
|
|
|
|
$q++;
|
|
|
|
|
$serialized .= substr($str, $p, $q - $p);
|
|
|
|
|
if (--$level == 0) break 2;
|
|
|
|
|
if (--$level == 0)
|
|
|
|
|
break 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$serialized .= 'N;';
|
|
|
|
|
$q += 2;
|
|
|
|
|
}
|
|
|
|
@ -555,9 +578,10 @@ class rcube_session
|
|
|
|
|
*/
|
|
|
|
|
function set_cookiename($cookiename)
|
|
|
|
|
{
|
|
|
|
|
if ($cookiename)
|
|
|
|
|
if ($cookiename) {
|
|
|
|
|
$this->cookiename = $cookiename;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -570,8 +594,9 @@ class rcube_session
|
|
|
|
|
$this->cookie = $_COOKIE[$this->cookiename];
|
|
|
|
|
$result = $this->ip_check ? $_SERVER['REMOTE_ADDR'] == $this->ip : true;
|
|
|
|
|
|
|
|
|
|
if (!$result)
|
|
|
|
|
if (!$result) {
|
|
|
|
|
$this->log("IP check failed for " . $this->key . "; expected " . $this->ip . "; got " . $_SERVER['REMOTE_ADDR']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($result && $this->_mkcookie($this->now) != $this->cookie) {
|
|
|
|
|
$this->log("Session auth check failed for " . $this->key . "; timeslot = " . date('Y-m-d H:i:s', $this->now));
|
|
|
|
@ -588,8 +613,10 @@ class rcube_session
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$result)
|
|
|
|
|
$this->log("Session authentication failed for " . $this->key . "; invalid auth cookie sent; timeslot = " . date('Y-m-d H:i:s', $prev));
|
|
|
|
|
if (!$result) {
|
|
|
|
|
$this->log("Session authentication failed for " . $this->key
|
|
|
|
|
. "; invalid auth cookie sent; timeslot = " . date('Y-m-d H:i:s', $prev));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
@ -622,8 +649,8 @@ class rcube_session
|
|
|
|
|
*/
|
|
|
|
|
function log($line)
|
|
|
|
|
{
|
|
|
|
|
if ($this->logging)
|
|
|
|
|
if ($this->logging) {
|
|
|
|
|
rcube::write_log('session', $line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|