5 V4.92a 29 Aug 2006 (c) 2000-2006 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.
14 You may want to rename the 'data' field to 'session_data' as
15 'data' appears to be a reserved word for one or more of the following:
22 If you do, then execute:
24 ADODB_Session::dataFieldName('session_data');
28 if (!defined('_ADODB_LAYER')) {
29 require realpath(dirname(__FILE__
) . '/../adodb.inc.php');
32 if (defined('ADODB_SESSION')) return 1;
34 define('ADODB_SESSION', dirname(__FILE__
));
38 Unserialize session data manually. See http://phplens.com/lens/lensforum/msgs.php?id=9821
40 From Kerr Schere, to unserialize session data stored via ADOdb.
41 1. Pull the session data from the db and loop through it.
42 2. Inside the loop, you will need to urldecode the data column.
43 3. After urldecode, run the serialized string through this function:
46 function adodb_unserialize( $serialized_string )
48 $variables = array( );
49 $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
50 for( $i = 0; $i < count( $a ); $i = $i+
2 ) {
51 $variables[$a[$i]] = unserialize( $a[$i+
1] );
57 Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1
60 function adodb_session_regenerate_id()
62 $conn =& ADODB_Session
::_conn();
63 if (!$conn) return false;
65 $old_id = session_id();
66 if (function_exists('session_regenerate_id')) {
67 session_regenerate_id();
69 session_id(md5(uniqid(rand(), true)));
70 $ck = session_get_cookie_params();
71 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
74 $new_id = session_id();
75 $ok =& $conn->Execute('UPDATE '. ADODB_Session
::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id));
77 /* it is possible that the update statement fails due to a collision */
80 if (empty($ck)) $ck = session_get_cookie_params();
81 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
89 Generate database table for session data
90 @see http://phplens.com/lens/lensforum/msgs.php?id=12280
91 @return 0 if failure, 1 if errors, 2 if successful.
92 @author Markus Staab http://www.public-4u.de
94 function adodb_session_create_table($schemaFile=null,$conn = null)
97 if ($schemaFile===null) $schemaFile = ADODB_SESSION
. '/session_schema.xml';
98 if ($conn===null) $conn =& ADODB_Session
::_conn();
100 if (!$conn) return 0;
102 $schema = new adoSchema($conn);
103 $schema->ParseSchema($schemaFile);
104 return $schema->ExecuteSchema();
110 class ADODB_Session
{
111 /////////////////////
112 // getter/setter methods
113 /////////////////////
117 function Lock($lock=null)
119 static $_lock = false;
121 if (!is_null($lock)) $_lock = $lock;
127 function driver($driver = null) {
128 static $_driver = 'mysql';
131 if (!is_null($driver)) {
132 $_driver = trim($driver);
135 // backwards compatibility
136 if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {
137 return $GLOBALS['ADODB_SESSION_DRIVER'];
146 function host($host = null) {
147 static $_host = 'localhost';
150 if (!is_null($host)) {
151 $_host = trim($host);
154 // backwards compatibility
155 if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {
156 return $GLOBALS['ADODB_SESSION_CONNECT'];
165 function user($user = null) {
166 static $_user = 'root';
169 if (!is_null($user)) {
170 $_user = trim($user);
173 // backwards compatibility
174 if (isset($GLOBALS['ADODB_SESSION_USER'])) {
175 return $GLOBALS['ADODB_SESSION_USER'];
184 function password($password = null) {
185 static $_password = '';
188 if (!is_null($password)) {
189 $_password = $password;
192 // backwards compatibility
193 if (isset($GLOBALS['ADODB_SESSION_PWD'])) {
194 return $GLOBALS['ADODB_SESSION_PWD'];
203 function database($database = null) {
204 static $_database = 'xphplens_2';
207 if (!is_null($database)) {
208 $_database = trim($database);
211 // backwards compatibility
212 if (isset($GLOBALS['ADODB_SESSION_DB'])) {
213 return $GLOBALS['ADODB_SESSION_DB'];
222 function persist($persist = null)
224 static $_persist = true;
226 if (!is_null($persist)) {
227 $_persist = trim($persist);
235 function lifetime($lifetime = null) {
239 if (!is_null($lifetime)) {
240 $_lifetime = (int) $lifetime;
243 // backwards compatibility
244 if (isset($GLOBALS['ADODB_SESS_LIFE'])) {
245 return $GLOBALS['ADODB_SESS_LIFE'];
249 $_lifetime = ini_get('session.gc_maxlifetime');
250 if ($_lifetime <= 1) {
251 // bug in PHP 4.0.3 pl 1 -- how about other versions?
252 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $lifetime</h3>";
262 function debug($debug = null) {
263 static $_debug = false;
266 if (!is_null($debug)) {
267 $_debug = (bool) $debug;
269 $conn = ADODB_Session
::_conn();
271 $conn->debug
= $_debug;
275 // backwards compatibility
276 if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {
277 return $GLOBALS['ADODB_SESS_DEBUG'];
286 function expireNotify($expire_notify = null) {
287 static $_expire_notify;
290 if (!is_null($expire_notify)) {
291 $_expire_notify = $expire_notify;
294 // backwards compatibility
295 if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {
296 return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];
300 return $_expire_notify;
305 function table($table = null) {
306 static $_table = 'sessions';
309 if (!is_null($table)) {
310 $_table = trim($table);
313 // backwards compatibility
314 if (isset($GLOBALS['ADODB_SESSION_TBL'])) {
315 return $GLOBALS['ADODB_SESSION_TBL'];
324 function optimize($optimize = null) {
325 static $_optimize = false;
328 if (!is_null($optimize)) {
329 $_optimize = (bool) $optimize;
332 // backwards compatibility
333 if (defined('ADODB_SESSION_OPTIMIZE')) {
343 function syncSeconds($sync_seconds = null) {
344 static $_sync_seconds = 60;
347 if (!is_null($sync_seconds)) {
348 $_sync_seconds = (int) $sync_seconds;
351 // backwards compatibility
352 if (defined('ADODB_SESSION_SYNCH_SECS')) {
353 return ADODB_SESSION_SYNCH_SECS
;
357 return $_sync_seconds;
362 function clob($clob = null) {
363 static $_clob = false;
366 if (!is_null($clob)) {
367 $_clob = strtolower(trim($clob));
370 // backwards compatibility
371 if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {
372 return $GLOBALS['ADODB_SESSION_USE_LOBS'];
381 function dataFieldName($data_field_name = null) {
382 static $_data_field_name = 'data';
384 if (!is_null($data_field_name)) {
385 $_data_field_name = trim($data_field_name);
388 return $_data_field_name;
393 function filter($filter = null) {
394 static $_filter = array();
396 if (!is_null($filter)) {
397 if (!is_array($filter)) {
398 $filter = array($filter);
408 function encryptionKey($encryption_key = null) {
409 static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';
411 if (!is_null($encryption_key)) {
412 $_encryption_key = $encryption_key;
415 return $_encryption_key;
418 /////////////////////
420 /////////////////////
424 function &_conn($conn=null) {
425 return $GLOBALS['ADODB_SESS_CONN'];
430 function _crc($crc = null) {
431 static $_crc = false;
433 if (!is_null($crc)) {
443 session_module_name('user');
444 session_set_save_handler(
445 array('ADODB_Session', 'open'),
446 array('ADODB_Session', 'close'),
447 array('ADODB_Session', 'read'),
448 array('ADODB_Session', 'write'),
449 array('ADODB_Session', 'destroy'),
450 array('ADODB_Session', 'gc')
457 function _sessionKey() {
458 // use this function to create the encryption key for crypted sessions
459 // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt
460 return crypt(ADODB_Session
::encryptionKey(), session_id());
465 function _dumprs($rs) {
466 $conn =& ADODB_Session
::_conn();
467 $debug = ADODB_Session
::debug();
478 echo "<br />\$rs is null or false<br />\n";
482 //echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";
484 if (!is_object($rs)) {
488 require_once ADODB_SESSION
.'/../tohtml.inc.php';
492 /////////////////////
494 /////////////////////
496 function config($driver, $host, $user, $password, $database=false,$options=false)
498 ADODB_Session
::driver($driver);
499 ADODB_Session
::host($host);
500 ADODB_Session
::user($user);
501 ADODB_Session
::password($password);
502 ADODB_Session
::database($database);
504 if ($driver == 'oci8' ||
$driver == 'oci8po') $options['lob'] = 'CLOB';
506 if (isset($options['table'])) ADODB_Session
::table($options['table']);
507 if (isset($options['lob'])) ADODB_Session
::clob($options['lob']);
508 if (isset($options['debug'])) ADODB_Session
::debug($options['debug']);
512 Create the connection to the database.
514 If $conn already exists, reuse that connection
516 function open($save_path, $session_name, $persist = null)
518 $conn =& ADODB_Session
::_conn();
524 $database = ADODB_Session
::database();
525 $debug = ADODB_Session
::debug();
526 $driver = ADODB_Session
::driver();
527 $host = ADODB_Session
::host();
528 $password = ADODB_Session
::password();
529 $user = ADODB_Session
::user();
531 if (!is_null($persist)) {
532 ADODB_Session
::persist($persist);
534 $persist = ADODB_Session
::persist();
537 # these can all be defaulted to in php.ini
538 # assert('$database');
542 $conn =& ADONewConnection($driver);
546 // ADOConnection::outp( " driver=$driver user=$user pwd=$password db=$database ");
552 case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
553 case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
554 case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
557 $ok = $conn->Connect($host, $user, $password, $database);
560 if ($ok) $GLOBALS['ADODB_SESS_CONN'] =& $conn;
562 ADOConnection
::outp('<p>Session: connection failed</p>', false);
574 $conn =& ADODB_Session::_conn();
575 if ($conn) $conn->Close();
581 Slurp in the session variables and return the serialized string
585 $conn =& ADODB_Session
::_conn();
586 $data = ADODB_Session
::dataFieldName();
587 $filter = ADODB_Session
::filter();
588 $table = ADODB_Session
::table();
596 $qkey = $conn->quote($key);
597 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
599 $sql = "SELECT $data FROM $table WHERE sesskey = $binary $qkey AND expiry >= " . time();
600 /* Lock code does not work as it needs to hold transaction within whole page, and we don't know if
601 developer has commited elsewhere... :(
603 #if (ADODB_Session::Lock())
604 # $rs =& $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), $data);
607 $rs =& $conn->Execute($sql);
608 //ADODB_Session::_dumprs($rs);
613 $v = reset($rs->fields
);
614 $filter = array_reverse($filter);
615 foreach ($filter as $f) {
617 $v = $f->read($v, ADODB_Session
::_sessionKey());
620 $v = rawurldecode($v);
625 ADODB_Session
::_crc(strlen($v) . crc32($v));
633 Write the serialized data to a database.
635 If the data has not been modified since the last read(), we do not write.
637 function write($key, $val)
639 global $ADODB_SESSION_READONLY;
641 if (!empty($ADODB_SESSION_READONLY)) return;
643 $clob = ADODB_Session
::clob();
644 $conn =& ADODB_Session
::_conn();
645 $crc = ADODB_Session
::_crc();
646 $data = ADODB_Session
::dataFieldName();
647 $debug = ADODB_Session
::debug();
648 $driver = ADODB_Session
::driver();
649 $expire_notify = ADODB_Session
::expireNotify();
650 $filter = ADODB_Session
::filter();
651 $lifetime = ADODB_Session
::lifetime();
652 $table = ADODB_Session
::table();
657 $qkey = $conn->qstr($key);
661 $expiry = time() +
$lifetime;
663 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
665 // crc32 optimization since adodb 2.1
666 // now we only update expiry date, thx to sebastian thom in adodb 2.32
667 if ($crc !== false && $crc == (strlen($val) . crc32($val))) {
669 echo '<p>Session: Only updating date - crc32 not changed</p>';
673 if ($expire_notify) {
674 $var = reset($expire_notify);
682 $sql = "UPDATE $table SET expiry = ".$conn->Param('0').",expireref=".$conn->Param('1')." WHERE $binary sesskey = ".$conn->Param('2')." AND expiry >= ".$conn->Param('3');
683 $rs =& $conn->Execute($sql,array($expiry,$expirevar,$key,time()));
686 $val = rawurlencode($val);
687 foreach ($filter as $f) {
689 $val = $f->write($val, ADODB_Session
::_sessionKey());
693 $arr = array('sesskey' => $key, 'expiry' => $expiry, $data => $val, 'expireref' => '');
694 if ($expire_notify) {
695 $var = reset($expire_notify);
698 $arr['expireref'] = $
$var;
702 if (!$clob) { // no lobs, simply use replace()
703 $arr[$data] = $conn->qstr($val);
704 $rs = $conn->Replace($table, $arr, 'sesskey', $autoQuote = true);
707 // what value shall we insert/update for lob row?
709 // empty_clob or empty_lob for oracle dbs
714 $lob_value = sprintf('empty_%s()', strtolower($clob));
717 // null for all other
724 $expiryref = $conn->qstr($arr['expireref']);
725 // do we insert or update? => as for sesskey
726 $rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = $qkey");
727 if ($rs && reset($rs->fields
) > 0) {
728 $sql = "UPDATE $table SET expiry = $expiry, $data = $lob_value, expireref=$expiryref WHERE sesskey = $qkey";
730 $sql = "INSERT INTO $table (expiry, $data, sesskey,expireref) VALUES ($expiry, $lob_value, $qkey,$expiryref)";
732 if ($rs)$rs->Close();
736 $rs1 =& $conn->Execute($sql);
737 if (!$rs1) $err = $conn->ErrorMsg()."\n";
739 $rs2 =& $conn->UpdateBlob($table, $data, $val, " sesskey=$qkey", strtoupper($clob));
740 if (!$rs2) $err .= $conn->ErrorMsg()."\n";
742 $rs = ($rs && $rs2) ?
true : false;
743 $conn->CompleteTrans();
747 ADOConnection
::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);
750 // bug in access driver (could be odbc?) means that info is not committed
751 // properly unless select statement executed in Win2000
752 if ($conn->databaseType
== 'access') {
753 $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
754 $rs =& $conn->Execute($sql);
755 ADODB_Session
::_dumprs($rs);
761 if (ADODB_Session::Lock()) {
762 $conn->CommitTrans();
764 return $rs ?
true : false;
769 function destroy($key) {
770 $conn =& ADODB_Session
::_conn();
771 $table = ADODB_Session
::table();
772 $expire_notify = ADODB_Session
::expireNotify();
780 $qkey = $conn->quote($key);
781 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
783 if ($expire_notify) {
784 reset($expire_notify);
785 $fn = next($expire_notify);
786 $savem = $conn->SetFetchMode(ADODB_FETCH_NUM
);
787 $sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey";
788 $rs =& $conn->Execute($sql);
789 ADODB_Session
::_dumprs($rs);
790 $conn->SetFetchMode($savem);
795 $ref = $rs->fields
[0];
796 $key = $rs->fields
[1];
804 $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";
805 $rs =& $conn->Execute($sql);
806 ADODB_Session
::_dumprs($rs);
808 return $rs ?
true : false;
813 function gc($maxlifetime)
815 $conn =& ADODB_Session
::_conn();
816 $debug = ADODB_Session
::debug();
817 $expire_notify = ADODB_Session
::expireNotify();
818 $optimize = ADODB_Session
::optimize();
819 $sync_seconds = ADODB_Session
::syncSeconds();
820 $table = ADODB_Session
::table();
828 $binary = $conn->dataProvider
=== 'mysql' ?
'/*! BINARY */' : '';
830 if ($expire_notify) {
831 reset($expire_notify);
832 $fn = next($expire_notify);
833 $savem = $conn->SetFetchMode(ADODB_FETCH_NUM
);
834 $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time";
835 $rs =& $conn->Execute($sql);
836 ADODB_Session
::_dumprs($rs);
837 $conn->SetFetchMode($savem);
842 $ref = $rs->fields
[0];
843 $key = $rs->fields
[1];
845 $del = $conn->Execute("DELETE FROM $table WHERE sesskey=".$conn->Param('0'),array($key));
850 $conn->CompleteTrans();
855 $sql = "SELECT sesskey FROM $table WHERE expiry < $time";
856 $arr =& $conn->GetAll($sql);
857 foreach ($arr as $row) {
858 $sql2 = "DELETE FROM $table WHERE sesskey=".$conn->Param('0');
859 $conn->Execute($sql2,array($row[0]));
862 $sql = "DELETE FROM $table WHERE expiry < $time";
863 $rs =& $conn->Execute($sql);
864 ADODB_Session
::_dumprs($rs);
865 if ($rs) $rs->Close();
868 ADOConnection
::outp("<p><b>Garbage Collection</b>: $sql</p>");
872 // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
874 $driver = ADODB_Session
::driver();
876 if (preg_match('/mysql/i', $driver)) {
877 $sql = "OPTIMIZE TABLE $table";
879 if (preg_match('/postgres/i', $driver)) {
880 $sql = "VACUUM $table";
883 $conn->Execute($sql);
889 if ($conn->dataProvider
=== 'oci8') {
890 $sql .= "TO_CHAR({$conn->sysTimeStamp}, 'RRRR-MM-DD HH24:MI:SS')";
892 $sql .= $conn->sysTimeStamp
;
894 $sql .= " FROM $table";
896 $rs =& $conn->SelectLimit($sql, 1);
897 if ($rs && !$rs->EOF
) {
898 $dbts = reset($rs->fields
);
900 $dbt = $conn->UnixTimeStamp($dbts);
903 if (abs($dbt - $t) >= $sync_seconds) {
905 ": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: " .
906 " database=$dbt ($dbts), webserver=$t (diff=". (abs($dbt - $t) / 60) . ' minutes)';
909 ADOConnection
::outp("<p>$msg</p>");
919 ADODB_Session
::_init();
920 if (empty($ADODB_SESSION_READONLY))
921 register_shutdown_function('session_write_close');
923 // for backwards compatability only
924 function adodb_sess_open($save_path, $session_name, $persist = true) {
925 return ADODB_Session
::open($save_path, $session_name, $persist);
928 // for backwards compatability only
929 function adodb_sess_gc($t)
931 return ADODB_Session
::gc($t);