source: subversion/trunk/roundcubemail/program/include/session.inc @ 2472

Last change on this file since 2472 was 2472, checked in by alec, 4 years ago
  • speed up the whole session cleaning in kill_session()
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1<?php
2
3/*
4 +-----------------------------------------------------------------------+
5 | program/include/session.inc                                           |
6 |                                                                       |
7 | This file is part of the RoundCube Webmail client                     |
8 | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland                 |
9 | Licensed under the GNU GPL                                            |
10 |                                                                       |
11 | PURPOSE:                                                              |
12 |   Provide database supported session management                       |
13 |                                                                       |
14 +-----------------------------------------------------------------------+
15 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
16 +-----------------------------------------------------------------------+
17
18 $Id$
19
20*/
21
22
23function rcube_sess_open($save_path, $session_name)
24{
25  return true;
26}
27
28
29function rcube_sess_close()
30{
31  return true;
32}
33
34
35// read session data
36function rcube_sess_read($key)
37{
38  global $SESS_CHANGED, $SESS_CLIENT_IP;
39 
40  $DB = rcmail::get_instance()->get_dbh();
41 
42  $sql_result = $DB->query(
43    "SELECT vars, ip, " . $DB->unixtimestamp('changed') . " AS changed
44     FROM " . get_table_name('session') . "
45     WHERE  sess_id=?",
46    $key);
47
48  if ($sql_arr = $DB->fetch_assoc($sql_result)) {
49    $SESS_CHANGED = $sql_arr['changed'];
50    $SESS_CLIENT_IP = $sql_arr['ip'];
51
52    if (strlen($sql_arr['vars']))
53      return $sql_arr['vars'];
54  }
55
56  return false;
57}
58 
59
60// save session data
61function rcube_sess_write($key, $vars)
62{
63  $DB = rcmail::get_instance()->get_dbh();
64 
65  $now = $DB->fromunixtime(time());
66
67  if ($oldvars = rcube_sess_read($key)) {
68    $DB->query(
69      "UPDATE " . get_table_name('session') . "
70       SET    vars=?, changed= " . $now . "
71       WHERE  sess_id=?",
72      rcube_sess_serialize(array_merge(rcube_sess_unserialize($oldvars), rcube_sess_unserialize($vars))),
73      $key);
74  }
75  else {
76    $DB->query(
77      "INSERT INTO " . get_table_name('session') . "
78       (sess_id, vars, ip, created, changed)
79       VALUES (?, ?, ?, " . $now . ", " . $now .")",
80      $key,
81      $vars,
82      (string)$_SERVER['REMOTE_ADDR']);
83  }
84
85  return true;
86}
87
88
89// unset session variable
90function rcube_sess_unset($var=NULL)
91{
92  $DB = rcmail::get_instance()->get_dbh();
93
94  if (empty($var))
95    return rcube_sess_destroy(session_id());
96
97  $now = $DB->fromunixtime(time());
98
99  $sql_result = $DB->query(
100    "SELECT vars
101     FROM " . get_table_name('session') . "
102     WHERE  sess_id=?",
103     session_id());
104
105  if ($sql_arr = $DB->fetch_assoc($sql_result)) {
106    $vars = rcube_sess_unserialize($sql_arr['vars']);
107    if (isset($vars[$var])) {
108      unset($vars[$var]);
109      $DB->query(
110        "UPDATE " . get_table_name('session') . "
111         SET    vars=?, changed= " . $now . "
112         WHERE  sess_id=?",
113         rcube_sess_serialize($vars),
114         session_id());
115    }
116  }   
117
118  return true;
119}
120
121
122// serialize session data
123function rcube_sess_serialize($vars)
124{
125  $data = '';
126  if (is_array($vars))
127    foreach ($vars as $var=>$value)
128      $data .= $var.'|'.serialize($value);
129  else
130    $data = 'b:0;';
131  return $data;
132}
133
134
135// unserialize session data
136// http://www.php.net/manual/en/function.session-decode.php#56106
137function rcube_sess_unserialize($str)
138{
139  $str = (string)$str;
140  $endptr = strlen($str);
141  $p = 0;
142
143  $serialized = '';
144  $items = 0;
145  $level = 0;
146
147  while ($p < $endptr) {
148    $q = $p;
149    while ($str[$q] != '|')
150      if (++$q >= $endptr) break 2;
151
152    if ($str[$p] == '!') {
153      $p++;
154      $has_value = false;
155    } else {
156      $has_value = true;
157    }
158
159    $name = substr($str, $p, $q - $p);
160    $q++;
161
162    $serialized .= 's:' . strlen($name) . ':"' . $name . '";';
163
164    if ($has_value) {
165      for (;;) {
166        $p = $q;
167        switch (strtolower($str[$q])) {
168          case 'n': /* null */
169          case 'b': /* boolean */
170          case 'i': /* integer */
171          case 'd': /* decimal */
172            do $q++;
173            while ( ($q < $endptr) && ($str[$q] != ';') );
174            $q++;
175            $serialized .= substr($str, $p, $q - $p);
176            if ($level == 0) break 2;
177            break;
178          case 'r': /* reference  */
179            $q+= 2;
180            for ($id = ''; ($q < $endptr) && ($str[$q] != ';'); $q++) $id .= $str[$q];
181            $q++;
182            $serialized .= 'R:' . ($id + 1) . ';'; /* increment pointer because of outer array */
183            if ($level == 0) break 2;
184            break;
185          case 's': /* string */
186            $q+=2;
187            for ($length=''; ($q < $endptr) && ($str[$q] != ':'); $q++) $length .= $str[$q];
188            $q+=2;
189            $q+= (int)$length + 2;
190            $serialized .= substr($str, $p, $q - $p);
191            if ($level == 0) break 2;
192            break;
193          case 'a': /* array */
194          case 'o': /* object */
195            do $q++;
196            while ( ($q < $endptr) && ($str[$q] != '{') );
197            $q++;
198            $level++;
199            $serialized .= substr($str, $p, $q - $p);
200            break;
201          case '}': /* end of array|object */
202            $q++;
203            $serialized .= substr($str, $p, $q - $p);
204            if (--$level == 0) break 2;
205            break;
206          default:
207            return false;
208        }
209      }
210    } else {
211      $serialized .= 'N;';
212      $q+= 2;
213    }
214    $items++;
215    $p = $q;
216  }
217
218  return unserialize( 'a:' . $items . ':{' . $serialized . '}' );
219}
220
221
222// handler for session_destroy()
223function rcube_sess_destroy($key)
224{
225  $DB = rcmail::get_instance()->get_dbh();
226 
227  $DB->query("DELETE FROM " . get_table_name('session') . " WHERE sess_id=?", $key);
228
229  return true;
230}
231
232
233// garbage collecting function
234function rcube_sess_gc($maxlifetime)
235{
236  $rcmail = rcmail::get_instance();
237  $DB = $rcmail->get_dbh();
238
239  // just delete all expired sessions
240  $DB->query("DELETE FROM " . get_table_name('session') . "
241    WHERE changed < " . $DB->fromunixtime(time() - $maxlifetime));
242
243  if ($rcmail->config->get('enable_caching'))
244    rcmail_cache_gc();
245
246  rcmail_temp_gc();
247
248  return true;
249}
250
251
252function rcube_sess_regenerate_id()
253{
254  $randval = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
255
256  for ($random = "", $i=1; $i <= 32; $i++) {
257    $random .= substr($randval, rand(0,(strlen($randval) - 1)), 1);
258  }
259
260  // use md5 value for id or remove capitals from string $randval
261  $random = md5($random);
262
263  // delete old session record
264  rcube_sess_destroy(session_id());
265
266  session_id($random);
267
268  $cookie   = session_get_cookie_params();
269  $lifetime = $cookie['lifetime'] ? time() + $cookie['lifetime'] : 0;
270
271  rcmail::setcookie(session_name(), $random, $lifetime);
272
273  return true;
274}
275
276
277// set custom functions for PHP session management
278session_set_save_handler('rcube_sess_open', 'rcube_sess_close', 'rcube_sess_read', 'rcube_sess_write', 'rcube_sess_destroy', 'rcube_sess_gc');
279
280?>
Note: See TracBrowser for help on using the repository browser.