PageRenderTime 44ms CodeModel.GetById 13ms app.highlight 24ms RepoModel.GetById 2ms app.codeStats 0ms

/php/extlib/adodb5/session/adodb-session2.php

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