5 V4.98 13 Feb 2008 (c) 2000-2008 John Lim (jlim#natsoft.com.my). 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.
22 CREATE TABLE SESSIONS2
24 SESSKEY VARCHAR2(48 BYTE) NOT NULL,
26 EXPIREREF VARCHAR2(200 BYTE),
27 CREATED DATE NOT NULL,
28 MODIFIED DATE NOT NULL,
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);
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 )
58 if (!defined('_ADODB_LAYER')) {
59 require realpath(dirname(__FILE__
) . '/../adodb.inc.php');
62 if (defined('ADODB_SESSION')) return 1;
64 define('ADODB_SESSION', dirname(__FILE__
));
65 define('ADODB_SESSION2', ADODB_SESSION
);
68 Unserialize session data manually. See http://phplens.com/lens/lensforum/msgs.php?id=9821
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:
76 function adodb_unserialize( $serialized_string )
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] );
87 Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1
90 function adodb_session_regenerate_id()
92 $conn =& ADODB_Session
::_conn();
93 if (!$conn) return false;
95 $old_id = session_id();
96 if (function_exists('session_regenerate_id')) {
97 session_regenerate_id();
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']);
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));
107 /* it is possible that the update statement fails due to a collision */
110 if (empty($ck)) $ck = session_get_cookie_params();
111 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
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
124 function adodb_session_create_table($schemaFile=null,$conn = null)
126 // set default values
127 if ($schemaFile===null) $schemaFile = ADODB_SESSION
. '/session_schema2.xml';
128 if ($conn===null) $conn =& ADODB_Session
::_conn();
130 if (!$conn) return 0;
132 $schema = new adoSchema($conn);
133 $schema->ParseSchema($schemaFile);
134 return $schema->ExecuteSchema();
140 class ADODB_Session
{
141 /////////////////////
142 // getter/setter methods
143 /////////////////////
147 function Lock($lock=null)
149 static $_lock = false;
151 if (!is_null($lock)) $_lock = $lock;
157 function driver($driver = null)
159 static $_driver = 'mysql';
162 if (!is_null($driver)) {
163 $_driver = trim($driver);
166 // backwards compatibility
167 if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {
168 return $GLOBALS['ADODB_SESSION_DRIVER'];
177 function host($host = null) {
178 static $_host = 'localhost';
181 if (!is_null($host)) {
182 $_host = trim($host);
185 // backwards compatibility
186 if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {
187 return $GLOBALS['ADODB_SESSION_CONNECT'];
196 function user($user = null)
198 static $_user = 'root';
201 if (!is_null($user)) {
202 $_user = trim($user);
205 // backwards compatibility
206 if (isset($GLOBALS['ADODB_SESSION_USER'])) {
207 return $GLOBALS['ADODB_SESSION_USER'];
216 function password($password = null)
218 static $_password = '';
221 if (!is_null($password)) {
222 $_password = $password;
225 // backwards compatibility
226 if (isset($GLOBALS['ADODB_SESSION_PWD'])) {
227 return $GLOBALS['ADODB_SESSION_PWD'];
236 function database($database = null)
238 static $_database = '';
241 if (!is_null($database)) {
242 $_database = trim($database);
245 // backwards compatibility
246 if (isset($GLOBALS['ADODB_SESSION_DB'])) {
247 return $GLOBALS['ADODB_SESSION_DB'];
255 function persist($persist = null)
257 static $_persist = true;
259 if (!is_null($persist)) {
260 $_persist = trim($persist);
268 function lifetime($lifetime = null)
273 if (!is_null($lifetime)) {
274 $_lifetime = (int) $lifetime;
277 // backwards compatibility
278 if (isset($GLOBALS['ADODB_SESS_LIFE'])) {
279 return $GLOBALS['ADODB_SESS_LIFE'];
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>";
296 function debug($debug = null)
298 static $_debug = false;
301 if (!is_null($debug)) {
302 $_debug = (bool) $debug;
304 $conn = ADODB_Session
::_conn();
306 $conn->debug
= $_debug;
310 // backwards compatibility
311 if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {
312 return $GLOBALS['ADODB_SESS_DEBUG'];
321 function expireNotify($expire_notify = null)
323 static $_expire_notify;
326 if (!is_null($expire_notify)) {
327 $_expire_notify = $expire_notify;
330 // backwards compatibility
331 if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {
332 return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];
336 return $_expire_notify;
341 function table($table = null)
343 static $_table = 'sessions2';
346 if (!is_null($table)) {
347 $_table = trim($table);
350 // backwards compatibility
351 if (isset($GLOBALS['ADODB_SESSION_TBL'])) {
352 return $GLOBALS['ADODB_SESSION_TBL'];
361 function optimize($optimize = null)
363 static $_optimize = false;
366 if (!is_null($optimize)) {
367 $_optimize = (bool) $optimize;
370 // backwards compatibility
371 if (defined('ADODB_SESSION_OPTIMIZE')) {
381 function syncSeconds($sync_seconds = null) {
382 //echo ("<p>WARNING: ADODB_SESSION::syncSeconds is longer used, please remove this function for your code</p>");
389 function clob($clob = null) {
390 static $_clob = false;
393 if (!is_null($clob)) {
394 $_clob = strtolower(trim($clob));
397 // backwards compatibility
398 if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {
399 return $GLOBALS['ADODB_SESSION_USE_LOBS'];
408 function dataFieldName($data_field_name = null) {
409 //echo ("<p>WARNING: ADODB_SESSION::dataFieldName() is longer used, please remove this function for your code</p>");
415 function filter($filter = null) {
416 static $_filter = array();
418 if (!is_null($filter)) {
419 if (!is_array($filter)) {
420 $filter = array($filter);
430 function encryptionKey($encryption_key = null) {
431 static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';
433 if (!is_null($encryption_key)) {
434 $_encryption_key = $encryption_key;
437 return $_encryption_key;
440 /////////////////////
442 /////////////////////
446 function &_conn($conn=null)
448 if (isset($GLOBALS['ADODB_SESS_CONN'])) {
449 $conn =& $GLOBALS['ADODB_SESS_CONN'];
458 function _crc($crc = null) {
459 static $_crc = false;
461 if (!is_null($crc)) {
471 session_module_name('user');
472 session_set_save_handler(
473 array('ADODB_Session', 'open'),
474 array('ADODB_Session', 'close'),
475 array('ADODB_Session', 'read'),
476 array('ADODB_Session', 'write'),
477 array('ADODB_Session', 'destroy'),
478 array('ADODB_Session', 'gc')
485 function _sessionKey() {
486 // use this function to create the encryption key for crypted sessions
487 // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt
488 return crypt(ADODB_Session
::encryptionKey(), session_id());
493 function _dumprs($rs) {
494 $conn =& ADODB_Session
::_conn();
495 $debug = ADODB_Session
::debug();
506 echo "<br />\$rs is null or false<br />\n";
510 //echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";
512 if (!is_object($rs)) {
516 require_once ADODB_SESSION
.'/../tohtml.inc.php';
520 /////////////////////
522 /////////////////////
524 function config($driver, $host, $user, $password, $database=false,$options=false)
526 ADODB_Session
::driver($driver);
527 ADODB_Session
::host($host);
528 ADODB_Session
::user($user);
529 ADODB_Session
::password($password);
530 ADODB_Session
::database($database);
532 if ($driver == 'oci8' ||
$driver == 'oci8po') $options['lob'] = 'CLOB';
534 if (isset($options['table'])) ADODB_Session
::table($options['table']);
535 if (isset($options['lob'])) ADODB_Session
::clob($options['lob']);
536 if (isset($options['debug'])) ADODB_Session
::debug($options['debug']);
540 Create the connection to the database.
542 If $conn already exists, reuse that connection
544 function open($save_path, $session_name, $persist = null)
546 $conn =& ADODB_Session
::_conn();
552 $database = ADODB_Session
::database();
553 $debug = ADODB_Session
::debug();
554 $driver = ADODB_Session
::driver();
555 $host = ADODB_Session
::host();
556 $password = ADODB_Session
::password();
557 $user = ADODB_Session
::user();
559 if (!is_null($persist)) {
560 ADODB_Session
::persist($persist);
562 $persist = ADODB_Session
::persist();
565 # these can all be defaulted to in php.ini
566 # assert('$database');
570 $conn =& ADONewConnection($driver);
574 ADOConnection
::outp( " driver=$driver user=$user db=$database ");
580 case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
581 case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
582 case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
585 $ok = $conn->Connect($host, $user, $password, $database);
588 if ($ok) $GLOBALS['ADODB_SESS_CONN'] =& $conn;
590 ADOConnection
::outp('<p>Session: connection failed</p>', false);
602 $conn =& ADODB_Session::_conn();
603 if ($conn) $conn->Close();
609 Slurp in the session variables and return the serialized string
613 $conn =& ADODB_Session
::_conn();
614 $filter = ADODB_Session
::filter();
615 $table = ADODB_Session
::table();
623 $qkey = $conn->quote($key);
624 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
626 $sql = "SELECT sessdata FROM $table WHERE sesskey = $binary $qkey AND expiry >= " . $conn->sysTimeStamp
;
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... :(
630 #if (ADODB_Session::Lock())
631 # $rs =& $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), sessdata);
634 $rs =& $conn->Execute($sql);
635 //ADODB_Session::_dumprs($rs);
640 $v = reset($rs->fields
);
641 $filter = array_reverse($filter);
642 foreach ($filter as $f) {
644 $v = $f->read($v, ADODB_Session
::_sessionKey());
647 $v = rawurldecode($v);
652 ADODB_Session
::_crc(strlen($v) . crc32($v));
660 Write the serialized data to a database.
662 If the data has not been modified since the last read(), we do not write.
664 function write($key, $val)
666 global $ADODB_SESSION_READONLY;
668 if (!empty($ADODB_SESSION_READONLY)) return;
670 $clob = ADODB_Session
::clob();
671 $conn =& ADODB_Session
::_conn();
672 $crc = ADODB_Session
::_crc();
673 $debug = ADODB_Session
::debug();
674 $driver = ADODB_Session
::driver();
675 $expire_notify = ADODB_Session
::expireNotify();
676 $filter = ADODB_Session
::filter();
677 $lifetime = ADODB_Session
::lifetime();
678 $table = ADODB_Session
::table();
684 $sysTimeStamp = $conn->sysTimeStamp
;
688 $expiry = $conn->OffsetDate($lifetime/(24*3600),$sysTimeStamp);
690 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
692 // crc32 optimization since adodb 2.1
693 // now we only update expiry date, thx to sebastian thom in adodb 2.32
694 if ($crc !== false && $crc == (strlen($val) . crc32($val))) {
696 echo '<p>Session: Only updating date - crc32 not changed</p>';
700 if ($expire_notify) {
701 $var = reset($expire_notify);
709 $sql = "UPDATE $table SET expiry = $expiry ,expireref=".$conn->Param('0').", modified = $sysTimeStamp WHERE $binary sesskey = ".$conn->Param('1')." AND expiry >= $sysTimeStamp";
710 $rs =& $conn->Execute($sql,array($expirevar,$key));
713 $val = rawurlencode($val);
714 foreach ($filter as $f) {
716 $val = $f->write($val, ADODB_Session
::_sessionKey());
721 if ($expire_notify) {
722 $var = reset($expire_notify);
729 if (!$clob) { // no lobs, simply use replace()
730 $rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
731 if ($rs) $rs->Close();
733 if ($rs && reset($rs->fields
) > 0) {
734 $sql = "UPDATE $table SET expiry=$expiry, sessdata=".$conn->Param(0).", expireref= ".$conn->Param(1).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param('2');
737 $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified)
738 VALUES ($expiry,".$conn->Param('0').", ". $conn->Param('1').", ".$conn->Param('2').", $sysTimeStamp, $sysTimeStamp)";
742 $rs =& $conn->Execute($sql,array($val,$expireref,$key));
745 // what value shall we insert/update for lob row?
747 // empty_clob or empty_lob for oracle dbs
752 $lob_value = sprintf('empty_%s()', strtolower($clob));
755 // null for all other
763 $rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key));
764 if ($rs) $rs->Close();
766 if ($rs && reset($rs->fields
) > 0) {
767 $sql = "UPDATE $table SET expiry=$expiry, sessdata=$lob_value, expireref= ".$conn->Param(0).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param('1');
770 $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified)
771 VALUES ($expiry,$lob_value, ". $conn->Param('0').", ".$conn->Param('1').", $sysTimeStamp, $sysTimeStamp)";
774 $rs =& $conn->Execute($sql,array($expireref,$key));
776 $qkey = $conn->qstr($key);
777 $rs2 = $conn->UpdateBlob($table, 'sessdata', $val, " sesskey=$qkey", strtoupper($clob));
778 $rs = @$conn->CompleteTrans();
784 ADOConnection
::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);
787 // bug in access driver (could be odbc?) means that info is not committed
788 // properly unless select statement executed in Win2000
789 if ($conn->databaseType
== 'access') {
790 $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
791 $rs =& $conn->Execute($sql);
792 ADODB_Session
::_dumprs($rs);
798 if (ADODB_Session::Lock()) {
799 $conn->CommitTrans();
801 return $rs ?
true : false;
806 function destroy($key) {
807 $conn =& ADODB_Session
::_conn();
808 $table = ADODB_Session
::table();
809 $expire_notify = ADODB_Session
::expireNotify();
817 $qkey = $conn->quote($key);
818 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
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);
832 $ref = $rs->fields
[0];
833 $key = $rs->fields
[1];
841 $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";
842 $rs =& $conn->Execute($sql);
843 ADODB_Session
::_dumprs($rs);
848 return $rs ?
true : false;
853 function gc($maxlifetime)
855 $conn =& ADODB_Session
::_conn();
856 $debug = ADODB_Session
::debug();
857 $expire_notify = ADODB_Session
::expireNotify();
858 $optimize = ADODB_Session
::optimize();
859 $table = ADODB_Session
::table();
867 $time = $conn->sysTimeStamp
;
868 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
870 if ($expire_notify) {
871 reset($expire_notify);
872 $fn = next($expire_notify);
873 $savem = $conn->SetFetchMode(ADODB_FETCH_NUM
);
874 $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time";
875 $rs =& $conn->Execute($sql);
876 ADODB_Session
::_dumprs($rs);
877 $conn->SetFetchMode($savem);
882 $ref = $rs->fields
[0];
883 $key = $rs->fields
[1];
885 $del = $conn->Execute("DELETE FROM $table WHERE sesskey=".$conn->Param('0'),array($key));
890 $conn->CompleteTrans();
895 $sql = "SELECT sesskey FROM $table WHERE expiry < $time";
896 $arr =& $conn->GetAll($sql);
897 foreach ($arr as $row) {
898 $sql2 = "DELETE FROM $table WHERE sesskey=".$conn->Param('0');
899 $conn->Execute($sql2,array($row[0]));
902 $sql = "DELETE FROM $table WHERE expiry < $time";
903 $rs =& $conn->Execute($sql);
904 ADODB_Session
::_dumprs($rs);
905 if ($rs) $rs->Close();
908 ADOConnection
::outp("<p><b>Garbage Collection</b>: $sql</p>");
912 // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
914 $driver = ADODB_Session
::driver();
916 if (preg_match('/mysql/i', $driver)) {
917 $sql = "OPTIMIZE TABLE $table";
919 if (preg_match('/postgres/i', $driver)) {
920 $sql = "VACUUM $table";
923 $conn->Execute($sql);
932 ADODB_Session
::_init();
933 if (empty($ADODB_SESSION_READONLY))
934 register_shutdown_function('session_write_close');
936 // for backwards compatability only
937 function adodb_sess_open($save_path, $session_name, $persist = true) {
938 return ADODB_Session
::open($save_path, $session_name, $persist);
941 // for backwards compatability only
942 function adodb_sess_gc($t)
944 return ADODB_Session
::gc($t);