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