]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/session/old/adodb-session.php
Upgrade adodb
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / session / old / adodb-session.php
1 <?php
2 /*
3 V4.93 10 Oct 2006  (c) 2000-2012 John Lim (jlim#natsoft.com). All rights reserved.
4   Released under both BSD license and Lesser GPL library license. 
5   Whenever there is any discrepancy between the two licenses, 
6   the BSD license will take precedence.
7           Set tabs to 4 for best viewing.
8   
9   Latest version of ADODB is available at http://php.weblogs.com/adodb
10   ======================================================================
11   
12  This file provides PHP4 session management using the ADODB database
13 wrapper library.
14  
15  Example
16  =======
17  
18         include('adodb.inc.php');
19         include('adodb-session.php');
20         session_start();
21         session_register('AVAR');
22         $_SESSION['AVAR'] += 1;
23         print "
24 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
25         
26 To force non-persistent connections, call adodb_session_open first before session_start():
27
28         include('adodb.inc.php');
29         include('adodb-session.php');
30         adodb_sess_open(false,false,false);
31         session_start();
32         session_register('AVAR');
33         $_SESSION['AVAR'] += 1;
34         print "
35 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
36
37  
38  Installation
39  ============
40  1. Create this table in your database (syntax might vary depending on your db):
41  
42   create table sessions (
43            SESSKEY char(32) not null,
44            EXPIRY int(11) unsigned not null,
45            EXPIREREF varchar(64),
46            DATA text not null,
47           primary key (sesskey)
48   );
49   
50   For oracle:
51     create table sessions (
52            SESSKEY char(32) not null,
53            EXPIRY DECIMAL(16)  not null,
54            EXPIREREF varchar(64),
55            DATA varchar(4000) not null,
56           primary key (sesskey)
57   );
58
59
60   2. Then define the following parameters. You can either modify
61      this file, or define them before this file is included:
62          
63         $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
64         $ADODB_SESSION_CONNECT='server to connect to';
65         $ADODB_SESSION_USER ='user';
66         $ADODB_SESSION_PWD ='password';
67         $ADODB_SESSION_DB ='database';
68         $ADODB_SESSION_TBL = 'sessions'
69         
70   3. Recommended is PHP 4.1.0 or later. There are documented
71          session bugs in earlier versions of PHP.
72
73   4. If you want to receive notifications when a session expires, then
74          you can tag a session with an EXPIREREF, and before the session
75          record is deleted, we can call a function that will pass the EXPIREREF
76          as the first parameter, and the session key as the second parameter.
77          
78          To do this, define a notification function, say NotifyFn:
79          
80                 function NotifyFn($expireref, $sesskey)
81                 {
82                 }
83          
84          Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
85          This is an array with 2 elements, the first being the name of the variable
86          you would like to store in the EXPIREREF field, and the 2nd is the 
87          notification function's name.
88          
89          In this example, we want to be notified when a user's session 
90          has expired, so we store the user id in the global variable $USERID, 
91          store this value in the EXPIREREF field:
92          
93                 $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
94                 
95         Then when the NotifyFn is called, we are passed the $USERID as the first
96         parameter, eg. NotifyFn($userid, $sesskey).
97 */
98
99 if (!defined('_ADODB_LAYER')) {
100         include (dirname(__FILE__).'/adodb.inc.php');
101 }
102
103 if (!defined('ADODB_SESSION')) {
104
105  define('ADODB_SESSION',1);
106  
107  /* if database time and system time is difference is greater than this, then give warning */
108  define('ADODB_SESSION_SYNCH_SECS',60); 
109
110  /*
111         Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1
112 */
113 function adodb_session_regenerate_id() 
114 {
115         $conn = ADODB_Session::_conn();
116         if (!$conn) return false;
117
118         $old_id = session_id();
119         if (function_exists('session_regenerate_id')) {
120                 session_regenerate_id();
121         } else {
122                 session_id(md5(uniqid(rand(), true)));
123                 $ck = session_get_cookie_params();
124                 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
125                 //@session_start();
126         }
127         $new_id = session_id();
128         $ok = $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id));
129         
130         /* it is possible that the update statement fails due to a collision */
131         if (!$ok) {
132                 session_id($old_id);
133                 if (empty($ck)) $ck = session_get_cookie_params();
134                 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
135                 return false;
136         }
137         
138         return true;
139 }
140
141 /****************************************************************************************\
142         Global definitions
143 \****************************************************************************************/
144 GLOBAL  $ADODB_SESSION_CONNECT, 
145         $ADODB_SESSION_DRIVER,
146         $ADODB_SESSION_USER,
147         $ADODB_SESSION_PWD,
148         $ADODB_SESSION_DB,
149         $ADODB_SESS_CONN,
150         $ADODB_SESS_LIFE,
151         $ADODB_SESS_DEBUG,
152         $ADODB_SESSION_EXPIRE_NOTIFY,
153         $ADODB_SESSION_CRC,
154         $ADODB_SESSION_TBL;
155         
156         
157         $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
158         if ($ADODB_SESS_LIFE <= 1) {
159          // bug in PHP 4.0.3 pl 1  -- how about other versions?
160          //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
161                 $ADODB_SESS_LIFE=1440;
162         }
163         $ADODB_SESSION_CRC = false;
164         //$ADODB_SESS_DEBUG = true;
165         
166         //////////////////////////////////
167         /* SET THE FOLLOWING PARAMETERS */
168         //////////////////////////////////
169         
170         if (empty($ADODB_SESSION_DRIVER)) {
171                 $ADODB_SESSION_DRIVER='mysql';
172                 $ADODB_SESSION_CONNECT='localhost';
173                 $ADODB_SESSION_USER ='root';
174                 $ADODB_SESSION_PWD ='';
175                 $ADODB_SESSION_DB ='xphplens_2';
176         }
177         
178         if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
179                 $ADODB_SESSION_EXPIRE_NOTIFY = false;
180         }
181         //  Made table name configurable - by David Johnson djohnson@inpro.net
182         if (empty($ADODB_SESSION_TBL)){
183                 $ADODB_SESSION_TBL = 'sessions';
184         }
185         
186         /*
187         $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
188         $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
189         $ADODB_SESS['user'] = $ADODB_SESSION_USER;
190         $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
191         $ADODB_SESS['db'] = $ADODB_SESSION_DB;
192         $ADODB_SESS['life'] = $ADODB_SESS_LIFE;
193         $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
194         
195         $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
196         $ADODB_SESS['table'] = $ADODB_SESS_TBL;
197         */
198         
199 /****************************************************************************************\
200         Create the connection to the database. 
201         
202         If $ADODB_SESS_CONN already exists, reuse that connection
203 \****************************************************************************************/
204 function adodb_sess_open($save_path, $session_name,$persist=true) 
205 {
206 GLOBAL $ADODB_SESS_CONN;
207         if (isset($ADODB_SESS_CONN)) return true;
208         
209 GLOBAL  $ADODB_SESSION_CONNECT, 
210         $ADODB_SESSION_DRIVER,
211         $ADODB_SESSION_USER,
212         $ADODB_SESSION_PWD,
213         $ADODB_SESSION_DB,
214         $ADODB_SESS_DEBUG;
215         
216         // cannot use & below - do not know why...
217         $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
218         if (!empty($ADODB_SESS_DEBUG)) {
219                 $ADODB_SESS_CONN->debug = true;
220                 ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
221         }
222         if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
223                         $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
224         else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
225                         $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
226         
227         if (!$ok) ADOConnection::outp( "
228 -- Session: connection failed</p>",false);
229 }
230
231 /****************************************************************************************\
232         Close the connection
233 \****************************************************************************************/
234 function adodb_sess_close() 
235 {
236 global $ADODB_SESS_CONN;
237
238         if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
239         return true;
240 }
241
242 /****************************************************************************************\
243         Slurp in the session variables and return the serialized string
244 \****************************************************************************************/
245 function adodb_sess_read($key) 
246 {
247 global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
248
249         $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
250         if ($rs) {
251                 if ($rs->EOF) {
252                         $v = '';
253                 } else 
254                         $v = rawurldecode(reset($rs->fields));
255                         
256                 $rs->Close();
257                 
258                 // new optimization adodb 2.1
259                 $ADODB_SESSION_CRC = strlen($v).crc32($v);
260                 
261                 return $v;
262         }
263         
264         return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
265 }
266
267 /****************************************************************************************\
268         Write the serialized data to a database.
269         
270         If the data has not been modified since adodb_sess_read(), we do not write.
271 \****************************************************************************************/
272 function adodb_sess_write($key, $val) 
273 {
274         global
275                 $ADODB_SESS_CONN, 
276                 $ADODB_SESS_LIFE, 
277                 $ADODB_SESSION_TBL,
278                 $ADODB_SESS_DEBUG, 
279                 $ADODB_SESSION_CRC,
280                 $ADODB_SESSION_EXPIRE_NOTIFY;
281
282         $expiry = time() + $ADODB_SESS_LIFE;
283         
284         // crc32 optimization since adodb 2.1
285         // now we only update expiry date, thx to sebastian thom in adodb 2.32
286         if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
287                 if ($ADODB_SESS_DEBUG) echo "
288 -- Session: Only updating date - crc32 not changed</p>";
289                 $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
290                 $rs = $ADODB_SESS_CONN->Execute($qry);  
291                 return true;
292         }
293         $val = rawurlencode($val);
294         
295         $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
296         if ($ADODB_SESSION_EXPIRE_NOTIFY) {
297                 $var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
298                 global $$var;
299                 $arr['expireref'] = $$var;
300         }
301         $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr,
302         'sesskey',$autoQuote = true);
303         
304         if (!$rs) {
305                 ADOConnection::outp( '
306 -- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
307         }  else {
308                 // bug in access driver (could be odbc?) means that info is not commited
309                 // properly unless select statement executed in Win2000
310                 if ($ADODB_SESS_CONN->databaseType == 'access') 
311                         $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
312         }
313         return !empty($rs);
314 }
315
316 function adodb_sess_destroy($key) 
317 {
318         global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
319         
320         if ($ADODB_SESSION_EXPIRE_NOTIFY) {
321                 reset($ADODB_SESSION_EXPIRE_NOTIFY);
322                 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
323                 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
324                 $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
325                 $ADODB_SESS_CONN->SetFetchMode($savem);
326                 if ($rs) {
327                         $ADODB_SESS_CONN->BeginTrans();
328                         while (!$rs->EOF) {
329                                 $ref = $rs->fields[0];
330                                 $key = $rs->fields[1];
331                                 $fn($ref,$key);
332                                 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
333                                 $rs->MoveNext();
334                         }
335                         $ADODB_SESS_CONN->CommitTrans();
336                 }
337         } else {
338                 $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
339                 $rs = $ADODB_SESS_CONN->Execute($qry);
340         }
341         return $rs ? true : false;
342 }
343
344 function adodb_sess_gc($maxlifetime) 
345 {
346         global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
347         
348         if ($ADODB_SESSION_EXPIRE_NOTIFY) {
349                 reset($ADODB_SESSION_EXPIRE_NOTIFY);
350                 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
351                 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
352                 $t = time();
353                 $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
354                 $ADODB_SESS_CONN->SetFetchMode($savem);
355                 if ($rs) {
356                         $ADODB_SESS_CONN->BeginTrans();
357                         while (!$rs->EOF) {
358                                 $ref = $rs->fields[0];
359                                 $key = $rs->fields[1];
360                                 $fn($ref,$key);
361                                 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
362                                 $rs->MoveNext();
363                         }
364                         $rs->Close();
365                         
366                         $ADODB_SESS_CONN->CommitTrans();
367                         
368                 }
369         } else {
370                 $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
371                 $ADODB_SESS_CONN->Execute($qry);
372         
373                 if ($ADODB_SESS_DEBUG) ADOConnection::outp("
374 -- <b>Garbage Collection</b>: $qry</p>");
375         }
376         // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
377         if (defined('ADODB_SESSION_OPTIMIZE')) {
378         global $ADODB_SESSION_DRIVER;
379         
380                 switch( $ADODB_SESSION_DRIVER ) {
381                         case 'mysql':
382                         case 'mysqlt':
383                                 $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
384                                 break;
385                         case 'postgresql':
386                         case 'postgresql7':
387                                 $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;        
388                                 break;
389                 }
390                 if (!empty($opt_qry)) {
391                         $ADODB_SESS_CONN->Execute($opt_qry);
392                 }
393         }
394         if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select  TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
395         else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
396         
397         $rs = $ADODB_SESS_CONN->SelectLimit($sql,1);
398         if ($rs && !$rs->EOF) {
399         
400                 $dbts = reset($rs->fields);
401                 $rs->Close();
402                 $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
403                 $t = time();
404         
405                 if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
406                 
407                         $msg = 
408                         __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
409                         error_log($msg);
410                         if ($ADODB_SESS_DEBUG) ADOConnection::outp("
411 -- $msg</p>");
412                 }
413         }
414         
415         return true;
416 }
417
418 session_module_name('user'); 
419 session_set_save_handler(
420         "adodb_sess_open",
421         "adodb_sess_close",
422         "adodb_sess_read",
423         "adodb_sess_write",
424         "adodb_sess_destroy",
425         "adodb_sess_gc");
426 }
427
428 /*  TEST SCRIPT -- UNCOMMENT */
429
430 if (0) {
431
432         session_start();
433         session_register('AVAR');
434         $_SESSION['AVAR'] += 1;
435         ADOConnection::outp( "
436 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false);
437 }
438
439 ?>