]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/session/adodb-session2.php
Upgrade adodb
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / session / adodb-session2.php
1 <?php
2
3
4 /*
5 V5.18 3 Sep 2012  (c) 2000-2012 John Lim (jlim#natsoft.com). All rights reserved.
6          Contributed by Ross Smith (adodb@netebb.com). 
7   Released under both BSD license and Lesser GPL library license.
8   Whenever there is any discrepancy between the two licenses,
9   the BSD license will take precedence.
10           Set tabs to 4 for best viewing.
11           
12
13 */
14
15 /*
16
17 CREATE Table SCripts
18
19 Oracle
20 ======
21
22 CREATE TABLE SESSIONS2
23 (
24   SESSKEY    VARCHAR2(48 BYTE)                  NOT NULL,
25   EXPIRY     DATE                               NOT NULL,
26   EXPIREREF  VARCHAR2(200 BYTE),
27   CREATED    DATE                               NOT NULL,
28   MODIFIED   DATE                               NOT NULL,
29   SESSDATA   CLOB,
30   PRIMARY KEY(SESSKEY)
31 );
32
33
34 CREATE INDEX SESS2_EXPIRY ON SESSIONS2(EXPIRY);
35 CREATE UNIQUE INDEX SESS2_PK ON SESSIONS2(SESSKEY);
36 CREATE INDEX SESS2_EXP_REF ON SESSIONS2(EXPIREREF);
37
38
39  
40  MySQL
41  =====
42  
43 CREATE TABLE sessions2(
44         sesskey VARCHAR( 64 ) NOT NULL DEFAULT '',
45         expiry TIMESTAMP NOT NULL ,
46         expireref VARCHAR( 250 ) DEFAULT '',
47         created TIMESTAMP NOT NULL ,
48         modified TIMESTAMP NOT NULL ,
49         sessdata LONGTEXT DEFAULT '',
50         PRIMARY KEY ( sesskey ) ,
51         INDEX sess2_expiry( expiry ),
52         INDEX sess2_expireref( expireref )
53 )
54
55
56 */
57
58 if (!defined('_ADODB_LAYER')) {
59         require realpath(dirname(__FILE__) . '/../adodb.inc.php');
60 }
61
62 if (defined('ADODB_SESSION')) return 1;
63
64 define('ADODB_SESSION', dirname(__FILE__));
65 define('ADODB_SESSION2', ADODB_SESSION);
66
67 /* 
68         Unserialize session data manually. See http://phplens.com/lens/lensforum/msgs.php?id=9821 
69         
70         From Kerr Schere, to unserialize session data stored via ADOdb. 
71         1. Pull the session data from the db and loop through it. 
72         2. Inside the loop, you will need to urldecode the data column. 
73         3. After urldecode, run the serialized string through this function:
74
75 */
76 function adodb_unserialize( $serialized_string ) 
77 {
78         $variables = array( );
79         $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
80         for( $i = 0; $i < count( $a ); $i = $i+2 ) {
81                 $variables[$a[$i]] = unserialize( $a[$i+1] );
82         }
83         return( $variables );
84 }
85
86 /*
87         Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1
88         Since adodb 4.61.
89 */
90 function adodb_session_regenerate_id() 
91 {
92         $conn = ADODB_Session::_conn();
93         if (!$conn) return false;
94
95         $old_id = session_id();
96         if (function_exists('session_regenerate_id')) {
97                 session_regenerate_id();
98         } else {
99                 session_id(md5(uniqid(rand(), true)));
100                 $ck = session_get_cookie_params();
101                 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
102                 //@session_start();
103         }
104         $new_id = session_id();
105         $ok = $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id));
106         
107         /* it is possible that the update statement fails due to a collision */
108         if (!$ok) {
109                 session_id($old_id);
110                 if (empty($ck)) $ck = session_get_cookie_params();
111                 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
112                 return false;
113         }
114         
115         return true;
116 }
117
118 /*
119     Generate database table for session data
120     @see http://phplens.com/lens/lensforum/msgs.php?id=12280
121     @return 0 if failure, 1 if errors, 2 if successful.
122         @author Markus Staab http://www.public-4u.de
123 */
124 function adodb_session_create_table($schemaFile=null,$conn = null)
125 {
126     // set default values
127     if ($schemaFile===null) $schemaFile = ADODB_SESSION . '/session_schema2.xml';
128     if ($conn===null) $conn = ADODB_Session::_conn();
129
130         if (!$conn) return 0;
131
132     $schema = new adoSchema($conn);
133     $schema->ParseSchema($schemaFile);
134     return $schema->ExecuteSchema();
135 }
136
137 /*!
138         \static
139 */
140 class ADODB_Session {
141         /////////////////////
142         // getter/setter methods
143         /////////////////////
144         
145         /*
146         
147         function Lock($lock=null)
148         {
149         static $_lock = false;
150         
151                 if (!is_null($lock)) $_lock = $lock;
152                 return $lock;
153         }
154         */
155         /*!
156         */
157         static function driver($driver = null) 
158         {
159                 static $_driver = 'mysql';
160                 static $set = false;
161
162                 if (!is_null($driver)) {
163                         $_driver = trim($driver);
164                         $set = true;
165                 } elseif (!$set) {
166                         // backwards compatibility
167                         if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {
168                                 return $GLOBALS['ADODB_SESSION_DRIVER'];
169                         }
170                 }
171
172                 return $_driver;
173         }
174
175         /*!
176         */
177         static function host($host = null) {
178                 static $_host = 'localhost';
179                 static $set = false;
180
181                 if (!is_null($host)) {
182                         $_host = trim($host);
183                         $set = true;
184                 } elseif (!$set) {
185                         // backwards compatibility
186                         if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {
187                                 return $GLOBALS['ADODB_SESSION_CONNECT'];
188                         }
189                 }
190
191                 return $_host;
192         }
193
194         /*!
195         */
196         static function user($user = null) 
197         {
198                 static $_user = 'root';
199                 static $set = false;
200
201                 if (!is_null($user)) {
202                         $_user = trim($user);
203                         $set = true;
204                 } elseif (!$set) {
205                         // backwards compatibility
206                         if (isset($GLOBALS['ADODB_SESSION_USER'])) {
207                                 return $GLOBALS['ADODB_SESSION_USER'];
208                         }
209                 }
210
211                 return $_user;
212         }
213
214         /*!
215         */
216         static function password($password = null) 
217         {
218                 static $_password = '';
219                 static $set = false;
220
221                 if (!is_null($password)) {
222                         $_password = $password;
223                         $set = true;
224                 } elseif (!$set) {
225                         // backwards compatibility
226                         if (isset($GLOBALS['ADODB_SESSION_PWD'])) {
227                                 return $GLOBALS['ADODB_SESSION_PWD'];
228                         }
229                 }
230
231                 return $_password;
232         }
233
234         /*!
235         */
236         static function database($database = null) 
237         {
238                 static $_database = '';
239                 static $set = false;
240                 
241                 if (!is_null($database)) {
242                         $_database = trim($database);
243                         $set = true;
244                 } elseif (!$set) {
245                         // backwards compatibility
246                         if (isset($GLOBALS['ADODB_SESSION_DB'])) {
247                                 return $GLOBALS['ADODB_SESSION_DB'];
248                         }
249                 }
250                 return $_database;
251         }
252
253         /*!
254         */
255         static function persist($persist = null) 
256         {
257                 static $_persist = true;
258
259                 if (!is_null($persist)) {
260                         $_persist = trim($persist);
261                 }
262
263                 return $_persist;
264         }
265
266         /*!
267         */
268         static function lifetime($lifetime = null) 
269         {
270                 static $_lifetime;
271                 static $set = false;
272
273                 if (!is_null($lifetime)) {
274                         $_lifetime = (int) $lifetime;
275                         $set = true;
276                 } elseif (!$set) {
277                         // backwards compatibility
278                         if (isset($GLOBALS['ADODB_SESS_LIFE'])) {
279                                 return $GLOBALS['ADODB_SESS_LIFE'];
280                         }
281                 }
282                 if (!$_lifetime) {
283                         $_lifetime = ini_get('session.gc_maxlifetime');
284                         if ($_lifetime <= 1) {
285                                 // bug in PHP 4.0.3 pl 1  -- how about other versions?
286                                 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $lifetime</h3>";
287                                 $_lifetime = 1440;
288                         }
289                 }
290
291                 return $_lifetime;
292         }
293
294         /*!
295         */
296         static function debug($debug = null) 
297         {
298                 static $_debug = false;
299                 static $set = false;
300
301                 if (!is_null($debug)) {
302                         $_debug = (bool) $debug;
303
304                         $conn = ADODB_Session::_conn();
305                         if ($conn) {
306                                 #$conn->debug = $_debug;
307                         }
308                         $set = true;
309                 } elseif (!$set) {
310                         // backwards compatibility
311                         if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {
312                                 return $GLOBALS['ADODB_SESS_DEBUG'];
313                         }
314                 }
315
316                 return $_debug;
317         }
318
319         /*!
320         */
321         static function expireNotify($expire_notify = null) 
322         {
323                 static $_expire_notify;
324                 static $set = false;
325
326                 if (!is_null($expire_notify)) {
327                         $_expire_notify = $expire_notify;
328                         $set = true;
329                 } elseif (!$set) {
330                         // backwards compatibility
331                         if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {
332                                 return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];
333                         }
334                 }
335
336                 return $_expire_notify;
337         }
338
339         /*!
340         */
341         static function table($table = null) 
342         {
343                 static $_table = 'sessions2';
344                 static $set = false;
345
346                 if (!is_null($table)) {
347                         $_table = trim($table);
348                         $set = true;
349                 } elseif (!$set) {
350                         // backwards compatibility
351                         if (isset($GLOBALS['ADODB_SESSION_TBL'])) {
352                                 return $GLOBALS['ADODB_SESSION_TBL'];
353                         }
354                 }
355
356                 return $_table;
357         }
358
359         /*!
360         */
361         static function optimize($optimize = null) 
362         {
363                 static $_optimize = false;
364                 static $set = false;
365
366                 if (!is_null($optimize)) {
367                         $_optimize = (bool) $optimize;
368                         $set = true;
369                 } elseif (!$set) {
370                         // backwards compatibility
371                         if (defined('ADODB_SESSION_OPTIMIZE')) {
372                                 return true;
373                         }
374                 }
375
376                 return $_optimize;
377         }
378
379         /*!
380         */
381         static function syncSeconds($sync_seconds = null) {
382                 //echo ("<p>WARNING: ADODB_SESSION::syncSeconds is longer used, please remove this function for your code</p>");
383                 
384                 return 0;
385         }
386
387         /*!
388         */
389         static function clob($clob = null) {
390                 static $_clob = false;
391                 static $set = false;
392
393                 if (!is_null($clob)) {
394                         $_clob = strtolower(trim($clob));
395                         $set = true;
396                 } elseif (!$set) {
397                         // backwards compatibility
398                         if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {
399                                 return $GLOBALS['ADODB_SESSION_USE_LOBS'];
400                         }
401                 }
402
403                 return $_clob;
404         }
405
406         /*!
407         */
408         static function dataFieldName($data_field_name = null) {
409                 //echo ("<p>WARNING: ADODB_SESSION::dataFieldName() is longer used, please remove this function for your code</p>");
410                 return '';
411         }
412
413         /*!
414         */
415         static function filter($filter = null) {
416                 static $_filter = array();
417
418                 if (!is_null($filter)) {
419                         if (!is_array($filter)) {
420                                 $filter = array($filter);
421                         }
422                         $_filter = $filter;
423                 }
424
425                 return $_filter;
426         }
427
428         /*!
429         */
430         static function encryptionKey($encryption_key = null) {
431                 static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';
432
433                 if (!is_null($encryption_key)) {
434                         $_encryption_key = $encryption_key;
435                 }
436
437                 return $_encryption_key;
438         }
439
440         /////////////////////
441         // private methods
442         /////////////////////
443
444         /*!
445         */
446         static function _conn($conn=null) {
447                 return isset($GLOBALS['ADODB_SESS_CONN']) ? $GLOBALS['ADODB_SESS_CONN'] : false;
448         }
449
450         /*!
451         */
452         static function _crc($crc = null) {
453                 static $_crc = false;
454
455                 if (!is_null($crc)) {
456                         $_crc = $crc;
457                 }
458
459                 return $_crc;
460         }
461
462         /*!
463         */
464         static function _init() {
465                 session_module_name('user');
466                 session_set_save_handler(
467                         array('ADODB_Session', 'open'),
468                         array('ADODB_Session', 'close'),
469                         array('ADODB_Session', 'read'),
470                         array('ADODB_Session', 'write'),
471                         array('ADODB_Session', 'destroy'),
472                         array('ADODB_Session', 'gc')
473                 );
474         }
475
476
477         /*!
478         */
479         static function _sessionKey() {
480                 // use this function to create the encryption key for crypted sessions
481                 // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt
482                 return crypt(ADODB_Session::encryptionKey(), session_id());
483         }
484
485         /*!
486         */
487         static function _dumprs(&$rs) {
488                 $conn   = ADODB_Session::_conn();
489                 $debug  = ADODB_Session::debug();
490
491                 if (!$conn) {
492                         return;
493                 }
494
495                 if (!$debug) {
496                         return;
497                 }
498
499                 if (!$rs) {
500                         echo "<br />\$rs is null or false<br />\n";
501                         return;
502                 }
503
504                 //echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";
505
506                 if (!is_object($rs)) {
507                         return;
508                 }
509                 $rs = $conn->_rs2rs($rs);
510                 
511                 require_once ADODB_SESSION.'/../tohtml.inc.php';
512                 rs2html($rs);
513                 $rs->MoveFirst();
514         }
515
516         /////////////////////
517         // public methods
518         /////////////////////
519         
520         static function config($driver, $host, $user, $password, $database=false,$options=false)
521         {
522                 ADODB_Session::driver($driver);
523                 ADODB_Session::host($host);
524                 ADODB_Session::user($user);
525                 ADODB_Session::password($password);
526                 ADODB_Session::database($database);
527                 
528                 if ($driver == 'oci8' || $driver == 'oci8po') $options['lob'] = 'CLOB';
529                 
530                 if (isset($options['table'])) ADODB_Session::table($options['table']);
531                 if (isset($options['lob'])) ADODB_Session::clob($options['lob']);
532                 if (isset($options['debug'])) ADODB_Session::debug($options['debug']);
533         }
534
535         /*!
536                 Create the connection to the database.
537
538                 If $conn already exists, reuse that connection
539         */
540         static function open($save_path, $session_name, $persist = null) 
541         {
542                 $conn = ADODB_Session::_conn();
543
544                 if ($conn) {
545                         return true;
546                 }
547
548                 $database       = ADODB_Session::database();
549                 $debug          = ADODB_Session::debug();
550                 $driver         = ADODB_Session::driver();
551                 $host           = ADODB_Session::host();
552                 $password       = ADODB_Session::password();
553                 $user           = ADODB_Session::user();
554
555                 if (!is_null($persist)) {
556                         ADODB_Session::persist($persist);
557                 } else {
558                         $persist = ADODB_Session::persist();
559                 }
560
561 # these can all be defaulted to in php.ini
562 #               assert('$database');
563 #               assert('$driver');
564 #               assert('$host');
565
566                 $conn = ADONewConnection($driver);
567
568                 if ($debug) {
569                         $conn->debug = true;            
570                         ADOConnection::outp( " driver=$driver user=$user db=$database ");
571                 }
572                 
573                 if (empty($conn->_connectionID)) { // not dsn
574                         if ($persist) {
575                                 switch($persist) {
576                                 default:
577                                 case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
578                                 case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
579                                 case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
580                                 }
581                         } else {
582                                 $ok = $conn->Connect($host, $user, $password, $database);
583                         }
584                 }
585
586                 if ($ok) $GLOBALS['ADODB_SESS_CONN'] = $conn;
587                 else
588                         ADOConnection::outp('<p>Session: connection failed</p>', false);
589                 
590
591                 return $ok;
592         }
593
594         /*!
595                 Close the connection
596         */
597         static function close() 
598         {
599 /*
600                 $conn = ADODB_Session::_conn();
601                 if ($conn) $conn->Close();
602 */
603                 return true;
604         }
605
606         /*
607                 Slurp in the session variables and return the serialized string
608         */
609         static function read($key) 
610         {
611                 $conn   = ADODB_Session::_conn();
612                 $filter = ADODB_Session::filter();
613                 $table  = ADODB_Session::table();
614
615                 if (!$conn) {
616                         return '';
617                 }
618
619                 //assert('$table');
620
621                 $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
622         
623                 global $ADODB_SESSION_SELECT_FIELDS;
624                 if (!isset($ADODB_SESSION_SELECT_FIELDS)) $ADODB_SESSION_SELECT_FIELDS = 'sessdata';            
625                 $sql = "SELECT $ADODB_SESSION_SELECT_FIELDS FROM $table WHERE sesskey = $binary ".$conn->Param(0)." AND expiry >= " . $conn->sysTimeStamp;              
626                 
627                 /* Lock code does not work as it needs to hold transaction within whole page, and we don't know if 
628                   developer has commited elsewhere... :(
629                  */
630                 #if (ADODB_Session::Lock())
631                 #       $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), sessdata);
632                 #else
633                         $rs = $conn->Execute($sql, array($key));
634                 //ADODB_Session::_dumprs($rs);
635                 if ($rs) {
636                         if ($rs->EOF) {
637                                 $v = '';
638                         } else {
639                                 $v = reset($rs->fields);
640                                 $filter = array_reverse($filter);
641                                 foreach ($filter as $f) {
642                                         if (is_object($f)) {
643                                                 $v = $f->read($v, ADODB_Session::_sessionKey());
644                                         }
645                                 }
646                                 $v = rawurldecode($v);
647                         }
648
649                         $rs->Close();
650
651                         ADODB_Session::_crc(strlen($v) . crc32($v));
652                         return $v;
653                 }
654
655                 return '';
656         }
657
658         /*!
659                 Write the serialized data to a database.
660
661                 If the data has not been modified since the last read(), we do not write.
662         */
663         static function write($key, $oval) 
664         {
665         global $ADODB_SESSION_READONLY;
666         
667                 if (!empty($ADODB_SESSION_READONLY)) return;
668                 
669                 $clob                   = ADODB_Session::clob();
670                 $conn                   = ADODB_Session::_conn();
671                 $crc                    = ADODB_Session::_crc();
672                 $debug                  = ADODB_Session::debug();
673                 $driver                 = ADODB_Session::driver();
674                 $expire_notify  = ADODB_Session::expireNotify();
675                 $filter                 = ADODB_Session::filter();
676                 $lifetime               = ADODB_Session::lifetime();
677                 $table                  = ADODB_Session::table();
678         
679                 if (!$conn) {
680                         return false;
681                 }
682                 if ($debug) $conn->debug = 1;
683                 $sysTimeStamp = $conn->sysTimeStamp;
684                 
685                 //assert('$table');
686
687                 $expiry = $conn->OffsetDate($lifetime/(24*3600),$sysTimeStamp);
688
689                 $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
690
691                 // crc32 optimization since adodb 2.1
692                 // now we only update expiry date, thx to sebastian thom in adodb 2.32
693                 if ($crc !== '00' && $crc !== false && $crc == (strlen($oval) . crc32($oval))) {
694                         if ($debug) {
695                                 echo '<p>Session: Only updating date - crc32 not changed</p>';
696                         }
697                         
698                         $expirevar = '';
699                         if ($expire_notify) {
700                                 $var = reset($expire_notify);
701                                 global $$var;
702                                 if (isset($$var)) {
703                                         $expirevar = $$var;
704                                 }
705                         }
706                         
707                         
708                         $sql = "UPDATE $table SET expiry = $expiry ,expireref=".$conn->Param('0').", modified = $sysTimeStamp WHERE $binary sesskey = ".$conn->Param('1')." AND expiry >= $sysTimeStamp";
709                         $rs = $conn->Execute($sql,array($expirevar,$key));
710                         return true;
711                 }
712                 $val = rawurlencode($oval);
713                 foreach ($filter as $f) {
714                         if (is_object($f)) {
715                                 $val = $f->write($val, ADODB_Session::_sessionKey());
716                         }
717                 }
718
719                 $expireref = '';
720                 if ($expire_notify) {
721                         $var = reset($expire_notify);
722                         global $$var;
723                         if (isset($$var)) {
724                                 $expireref = $$var;
725                         }
726                 } 
727
728                 if (!$clob) {   // no lobs, simply use replace()
729                         $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
730                         if ($rs) $rs->Close();
731                                         
732                         if ($rs && reset($rs->fields) > 0) {
733                                 $sql = "UPDATE $table SET expiry=$expiry, sessdata=".$conn->Param(0).", expireref= ".$conn->Param(1).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param(2);
734                                 
735                         } else {
736                                 $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified) 
737                                         VALUES ($expiry,".$conn->Param('0').", ". $conn->Param('1').", ".$conn->Param('2').", $sysTimeStamp, $sysTimeStamp)";
738                         }
739                         
740         
741                         $rs = $conn->Execute($sql,array($val,$expireref,$key));
742                         
743                 } else {
744                         // what value shall we insert/update for lob row?
745                         switch ($driver) {
746                                 // empty_clob or empty_lob for oracle dbs
747                                 case 'oracle':
748                                 case 'oci8':
749                                 case 'oci8po':
750                                 case 'oci805':
751                                         $lob_value = sprintf('empty_%s()', strtolower($clob));
752                                         break;
753
754                                 // null for all other
755                                 default:
756                                         $lob_value = 'null';
757                                         break;
758                         }
759                         
760                         $conn->StartTrans();
761                         
762                         $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
763                                         
764                         if ($rs && reset($rs->fields) > 0) {
765                                 $sql = "UPDATE $table SET expiry=$expiry, sessdata=$lob_value, expireref= ".$conn->Param(0).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param('1');
766                                 
767                         } else {
768                                 $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified) 
769                                         VALUES ($expiry,$lob_value, ". $conn->Param('0').", ".$conn->Param('1').", $sysTimeStamp, $sysTimeStamp)";
770                         }
771                         
772                         $rs = $conn->Execute($sql,array($expireref,$key));
773                         
774                         $qkey = $conn->qstr($key);
775                         $rs2 = $conn->UpdateBlob($table, 'sessdata', $val, " sesskey=$qkey", strtoupper($clob));
776                         if ($debug) echo "<hr>",htmlspecialchars($oval), "<hr>";
777                         $rs = @$conn->CompleteTrans();
778                         
779                         
780                 }
781
782                 if (!$rs) {
783                         ADOConnection::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);
784                         return false;
785                 }  else {
786                         // bug in access driver (could be odbc?) means that info is not committed
787                         // properly unless select statement executed in Win2000
788                         if ($conn->databaseType == 'access') {
789                                 $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
790                                 $rs = $conn->Execute($sql);
791                                 ADODB_Session::_dumprs($rs);
792                                 if ($rs) {
793                                         $rs->Close();
794                                 }
795                         }
796                 }/*
797                 if (ADODB_Session::Lock()) {
798                         $conn->CommitTrans();
799                 }*/
800                 return $rs ? true : false;
801         }
802
803         /*!
804         */
805         static function destroy($key) {
806                 $conn                   = ADODB_Session::_conn();
807                 $table                  = ADODB_Session::table();
808                 $expire_notify  = ADODB_Session::expireNotify();
809
810                 if (!$conn) {
811                         return false;
812                 }
813                 $debug                  = ADODB_Session::debug();
814                 if ($debug) $conn->debug = 1;
815                 //assert('$table');
816
817                 $qkey = $conn->quote($key);
818                 $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
819
820                 if ($expire_notify) {
821                         reset($expire_notify);
822                         $fn = next($expire_notify);
823                         $savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
824                         $sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey";
825                         $rs = $conn->Execute($sql);
826                         ADODB_Session::_dumprs($rs);
827                         $conn->SetFetchMode($savem);
828                         if (!$rs) {
829                                 return false;
830                         }
831                         if (!$rs->EOF) {
832                                 $ref = $rs->fields[0];
833                                 $key = $rs->fields[1];
834                                 //assert('$ref');
835                                 //assert('$key');
836                                 $fn($ref, $key);
837                         }
838                         $rs->Close();
839                 }
840
841                 $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";
842                 $rs = $conn->Execute($sql);
843                 if ($rs) {
844                         $rs->Close();
845                 }
846
847                 return $rs ? true : false;
848         }
849
850         /*!
851         */
852         static function gc($maxlifetime) 
853         {
854                 $conn                   = ADODB_Session::_conn();
855                 $debug                  = ADODB_Session::debug();
856                 $expire_notify  = ADODB_Session::expireNotify();
857                 $optimize               = ADODB_Session::optimize();
858                 $table                  = ADODB_Session::table();
859
860                 if (!$conn) {
861                         return false;
862                 }
863
864
865                 $debug                  = ADODB_Session::debug();
866                 if ($debug) {
867                         $conn->debug = 1;
868                         $COMMITNUM = 2;
869                 } else {
870                         $COMMITNUM = 20;
871                 }
872                 
873                 //assert('$table');
874
875                 $time = $conn->OffsetDate(-$maxlifetime/24/3600,$conn->sysTimeStamp);
876                 $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
877
878                 if ($expire_notify) {
879                         reset($expire_notify);
880                         $fn = next($expire_notify);
881                 } else {
882                         $fn = false;
883                 }
884                 
885                 $savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
886                 $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time ORDER BY 2"; # add order by to prevent deadlock
887                 $rs = $conn->SelectLimit($sql,1000);
888                 if ($debug) ADODB_Session::_dumprs($rs);
889                 $conn->SetFetchMode($savem);
890                 if ($rs) {
891                         $tr = $conn->hasTransactions;
892                         if ($tr) $conn->BeginTrans();
893                         $keys = array();
894                         $ccnt = 0;
895                         while (!$rs->EOF) {
896                                 $ref = $rs->fields[0];
897                                 $key = $rs->fields[1];
898                                 if ($fn) $fn($ref, $key);
899                                 $del = $conn->Execute("DELETE FROM $table WHERE sesskey=".$conn->Param('0'),array($key));
900                                 $rs->MoveNext();
901                                 $ccnt += 1;
902                                 if ($tr && $ccnt % $COMMITNUM == 0) {
903                                         if ($debug) echo "Commit<br>\n";
904                                         $conn->CommitTrans();
905                                         $conn->BeginTrans();
906                                 }
907                         }
908                         $rs->Close();
909                         
910                         if ($tr) $conn->CommitTrans();
911                 }
912                 
913
914                 // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
915                 if ($optimize) {
916                         $driver = ADODB_Session::driver();
917
918                         if (preg_match('/mysql/i', $driver)) {
919                                 $sql = "OPTIMIZE TABLE $table";
920                         }
921                         if (preg_match('/postgres/i', $driver)) {
922                                 $sql = "VACUUM $table";
923                         }
924                         if (!empty($sql)) {
925                                 $conn->Execute($sql);
926                         }
927                 }
928
929                 
930                 return true;
931         }
932 }
933
934 ADODB_Session::_init();
935 if (empty($ADODB_SESSION_READONLY))
936         register_shutdown_function('session_write_close');
937
938 // for backwards compatability only
939 function adodb_sess_open($save_path, $session_name, $persist = true) {
940         return ADODB_Session::open($save_path, $session_name, $persist);
941 }
942
943 // for backwards compatability only
944 function adodb_sess_gc($t)
945 {       
946         return ADODB_Session::gc($t);
947 }
948
949 ?>