PageRenderTime 76ms CodeModel.GetById 43ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 0ms

/source/libs/adodb/session/adodb-session.php

https://github.com/yfg2014/ddim
PHP | 841 lines | 565 code | 134 blank | 142 comment | 103 complexity | f5d57388fe6dd13ca927e7ddf486ede2 MD5 | raw file
  1<?php
  2
  3
  4/*
  5V4.01 23 Oct 2003  (c) 2000-2005 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.
 11*/
 12
 13/*
 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:
 16		ANSI SQL
 17		IBM DB2
 18		MS SQL Server
 19		Postgres
 20		SAP
 21
 22	If you do, then execute:
 23
 24		ADODB_Session::dataFieldName('session_data');
 25
 26*/
 27
 28if (!defined('_ADODB_LAYER')) {
 29	require_once realpath(dirname(__FILE__) . '/../adodb.inc.php');
 30}
 31
 32if (defined('ADODB_SESSION')) return 1;
 33
 34define('ADODB_SESSION', dirname(__FILE__));
 35
 36
 37/* 
 38	Unserialize session data manually. See http://phplens.com/lens/lensforum/msgs.php?id=9821 
 39	
 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:
 44
 45*/
 46function adodb_unserialize( $serialized_string ) 
 47{
 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] );
 52	}
 53	return( $variables );
 54}
 55
 56/*!
 57	\static
 58*/
 59class ADODB_Session {
 60	/////////////////////
 61	// getter/setter methods
 62	/////////////////////
 63
 64	/*!
 65	*/
 66	function driver($driver = null) {
 67		static $_driver = 'mysql';
 68		static $set = false;
 69
 70		if (!is_null($driver)) {
 71			$_driver = trim($driver);
 72			$set = true;
 73		} elseif (!$set) {
 74			// backwards compatibility
 75			if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {
 76				return $GLOBALS['ADODB_SESSION_DRIVER'];
 77			}
 78		}
 79
 80		return $_driver;
 81	}
 82
 83	/*!
 84	*/
 85	function host($host = null) {
 86		static $_host = 'localhost';
 87		static $set = false;
 88
 89		if (!is_null($host)) {
 90			$_host = trim($host);
 91			$set = true;
 92		} elseif (!$set) {
 93			// backwards compatibility
 94			if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {
 95				return $GLOBALS['ADODB_SESSION_CONNECT'];
 96			}
 97		}
 98
 99		return $_host;
100	}
101
102	/*!
103	*/
104	function user($user = null) {
105		static $_user = 'root';
106		static $set = false;
107
108		if (!is_null($user)) {
109			$_user = trim($user);
110			$set = true;
111		} elseif (!$set) {
112			// backwards compatibility
113			if (isset($GLOBALS['ADODB_SESSION_USER'])) {
114				return $GLOBALS['ADODB_SESSION_USER'];
115			}
116		}
117
118		return $_user;
119	}
120
121	/*!
122	*/
123	function password($password = null) {
124		static $_password = '';
125		static $set = false;
126
127		if (!is_null($password)) {
128			$_password = $password;
129			$set = true;
130		} elseif (!$set) {
131			// backwards compatibility
132			if (isset($GLOBALS['ADODB_SESSION_PWD'])) {
133				return $GLOBALS['ADODB_SESSION_PWD'];
134			}
135		}
136
137		return $_password;
138	}
139
140	/*!
141	*/
142	function database($database = null) {
143		static $_database = 'xphplens_2';
144		static $set = false;
145
146		if (!is_null($database)) {
147			$_database = trim($database);
148			$set = true;
149		} elseif (!$set) {
150			// backwards compatibility
151			if (isset($GLOBALS['ADODB_SESSION_DB'])) {
152				return $GLOBALS['ADODB_SESSION_DB'];
153			}
154		}
155
156		return $_database;
157	}
158
159	/*!
160	*/
161	function persist($persist = null) 
162	{
163		static $_persist = true;
164
165		if (!is_null($persist)) {
166			$_persist = trim($persist);
167		}
168
169		return $_persist;
170	}
171
172	/*!
173	*/
174	function lifetime($lifetime = null) {
175		static $_lifetime;
176		static $set = false;
177
178		if (!is_null($lifetime)) {
179			$_lifetime = (int) $lifetime;
180			$set = true;
181		} elseif (!$set) {
182			// backwards compatibility
183			if (isset($GLOBALS['ADODB_SESS_LIFE'])) {
184				return $GLOBALS['ADODB_SESS_LIFE'];
185			}
186		}
187		if (!$_lifetime) {
188			$_lifetime = ini_get('session.gc_maxlifetime');
189			if ($_lifetime <= 1) {
190				// bug in PHP 4.0.3 pl 1  -- how about other versions?
191				//print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $lifetime</h3>";
192				$_lifetime = 1440;
193			}
194		}
195
196		return $_lifetime;
197	}
198
199	/*!
200	*/
201	function debug($debug = null) {
202		static $_debug = false;
203		static $set = false;
204
205		if (!is_null($debug)) {
206			$_debug = (bool) $debug;
207
208			$conn = ADODB_Session::_conn();
209			if ($conn) {
210				$conn->debug = $_debug;
211			}
212			$set = true;
213		} elseif (!$set) {
214			// backwards compatibility
215			if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {
216				return $GLOBALS['ADODB_SESS_DEBUG'];
217			}
218		}
219
220		return $_debug;
221	}
222
223	/*!
224	*/
225	function expireNotify($expire_notify = null) {
226		static $_expire_notify;
227		static $set = false;
228
229		if (!is_null($expire_notify)) {
230			$_expire_notify = $expire_notify;
231			$set = true;
232		} elseif (!$set) {
233			// backwards compatibility
234			if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {
235				return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];
236			}
237		}
238
239		return $_expire_notify;
240	}
241
242	/*!
243	*/
244	function table($table = null) {
245		static $_table = 'sessions';
246		static $set = false;
247
248		if (!is_null($table)) {
249			$_table = trim($table);
250			$set = true;
251		} elseif (!$set) {
252			// backwards compatibility
253			if (isset($GLOBALS['ADODB_SESSION_TBL'])) {
254				return $GLOBALS['ADODB_SESSION_TBL'];
255			}
256		}
257
258		return $_table;
259	}
260
261	/*!
262	*/
263	function optimize($optimize = null) {
264		static $_optimize = false;
265		static $set = false;
266
267		if (!is_null($optimize)) {
268			$_optimize = (bool) $optimize;
269			$set = true;
270		} elseif (!$set) {
271			// backwards compatibility
272			if (defined('ADODB_SESSION_OPTIMIZE')) {
273				return true;
274			}
275		}
276
277		return $_optimize;
278	}
279
280	/*!
281	*/
282	function syncSeconds($sync_seconds = null) {
283		static $_sync_seconds = 60;
284		static $set = false;
285
286		if (!is_null($sync_seconds)) {
287			$_sync_seconds = (int) $sync_seconds;
288			$set = true;
289		} elseif (!$set) {
290			// backwards compatibility
291			if (defined('ADODB_SESSION_SYNCH_SECS')) {
292				return ADODB_SESSION_SYNCH_SECS;
293			}
294		}
295
296		return $_sync_seconds;
297	}
298
299	/*!
300	*/
301	function clob($clob = null) {
302		static $_clob = false;
303		static $set = false;
304
305		if (!is_null($clob)) {
306			$_clob = strtolower(trim($clob));
307			$set = true;
308		} elseif (!$set) {
309			// backwards compatibility
310			if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {
311				return $GLOBALS['ADODB_SESSION_USE_LOBS'];
312			}
313		}
314
315		return $_clob;
316	}
317
318	/*!
319	*/
320	function dataFieldName($data_field_name = null) {
321		static $_data_field_name = 'data';
322
323		if (!is_null($data_field_name)) {
324			$_data_field_name = trim($data_field_name);
325		}
326
327		return $_data_field_name;
328	}
329
330	/*!
331	*/
332	function filter($filter = null) {
333		static $_filter = array();
334
335		if (!is_null($filter)) {
336			if (!is_array($filter)) {
337				$filter = array($filter);
338			}
339			$_filter = $filter;
340		}
341
342		return $_filter;
343	}
344
345	/*!
346	*/
347	function encryptionKey($encryption_key = null) {
348		static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';
349
350		if (!is_null($encryption_key)) {
351			$_encryption_key = $encryption_key;
352		}
353
354		return $_encryption_key;
355	}
356
357	/////////////////////
358	// private methods
359	/////////////////////
360
361	/*!
362	*/
363	function &_conn($conn=null) {
364		return $GLOBALS['ADODB_SESS_CONN'];
365	}
366
367	/*!
368	*/
369	function _crc($crc = null) {
370		static $_crc = false;
371
372		if (!is_null($crc)) {
373			$_crc = $crc;
374		}
375
376		return $_crc;
377	}
378
379	/*!
380	*/
381	function _init() {
382		session_module_name('user');
383		session_set_save_handler(
384			array('ADODB_Session', 'open'),
385			array('ADODB_Session', 'close'),
386			array('ADODB_Session', 'read'),
387			array('ADODB_Session', 'write'),
388			array('ADODB_Session', 'destroy'),
389			array('ADODB_Session', 'gc')
390		);
391	}
392
393
394	/*!
395	*/
396	function _sessionKey() {
397		// use this function to create the encryption key for crypted sessions
398		// crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt
399		return crypt(ADODB_Session::encryptionKey(), session_id());
400	}
401
402	/*!
403	*/
404	function _dumprs($rs) {
405		$conn	=& ADODB_Session::_conn();
406		$debug	= ADODB_Session::debug();
407
408		if (!$conn) {
409			return;
410		}
411
412		if (!$debug) {
413			return;
414		}
415
416		if (!$rs) {
417			echo "<br />\$rs is null or false<br />\n";
418			return;
419		}
420
421		//echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";
422
423		if (!is_object($rs)) {
424			return;
425		}
426
427		require_once ADODB_SESSION.'/../tohtml.inc.php';
428		rs2html($rs);
429	}
430
431	/////////////////////
432	// public methods
433	/////////////////////
434
435	/*!
436		Create the connection to the database.
437
438		If $conn already exists, reuse that connection
439	*/
440	function open($save_path, $session_name, $persist = null) {
441		$conn =& ADODB_Session::_conn();
442
443		if ($conn) {
444			return true;
445		}
446
447		$database	= ADODB_Session::database();
448		$debug		= ADODB_Session::debug();
449		$driver		= ADODB_Session::driver();
450		$host		= ADODB_Session::host();
451		$password	= ADODB_Session::password();
452		$user		= ADODB_Session::user();
453
454		if (!is_null($persist)) {
455			ADODB_Session::persist($persist);
456		} else {
457			$persist = ADODB_Session::persist();
458		}
459
460# these can all be defaulted to in php.ini
461#		assert('$database');
462#		assert('$driver');
463#		assert('$host');
464
465		// cannot use =& below - do not know why...
466		$conn =& ADONewConnection($driver);
467
468		if ($debug) {
469			$conn->debug = true;
470//			ADOConnection::outp( " driver=$driver user=$user pwd=$password db=$database ");
471		}
472
473		if ($persist) {
474			switch($persist) {
475			default:
476			case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
477			case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
478			case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
479			}
480		} else {
481			$ok = $conn->Connect($host, $user, $password, $database);
482		}
483
484		if ($ok) $GLOBALS['ADODB_SESS_CONN'] =& $conn;
485		else
486			ADOConnection::outp('<p>Session: connection failed</p>', false);
487		
488
489		return $ok;
490	}
491
492	/*!
493		Close the connection
494	*/
495	function close() {
496		$conn =& ADODB_Session::_conn();
497
498		if ($conn) {
499			$conn->Close();
500		}
501
502		return true;
503	}
504
505	/*
506		Slurp in the session variables and return the serialized string
507	*/
508	function read($key) {
509		$conn	=& ADODB_Session::_conn();
510		$data	= ADODB_Session::dataFieldName();
511		$filter	= ADODB_Session::filter();
512		$table	= ADODB_Session::table();
513
514		if (!$conn) {
515			return '';
516		}
517
518		assert('$table');
519
520		$qkey = $conn->quote($key);
521		$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
522
523		$sql = "SELECT $data FROM $table WHERE $binary sesskey = $qkey AND expiry >= " . time();
524		$rs =& $conn->Execute($sql);
525		//ADODB_Session::_dumprs($rs);
526		if ($rs) {
527			if ($rs->EOF) {
528				$v = '';
529			} else {
530				$v = reset($rs->fields);
531				$filter = array_reverse($filter);
532				foreach ($filter as $f) {
533					if (is_object($f)) {
534						$v = $f->read($v, ADODB_Session::_sessionKey());
535					}
536				}
537				$v = rawurldecode($v);
538			}
539
540			$rs->Close();
541
542			ADODB_Session::_crc(strlen($v) . crc32($v));
543			return $v;
544		}
545
546		return '';
547	}
548
549	/*!
550		Write the serialized data to a database.
551
552		If the data has not been modified since the last read(), we do not write.
553	*/
554	function write($key, $val) {
555		$clob			= ADODB_Session::clob();
556		$conn			=& ADODB_Session::_conn();
557		$crc			= ADODB_Session::_crc();
558		$data			= ADODB_Session::dataFieldName();
559		$debug			= ADODB_Session::debug();
560		$driver			= ADODB_Session::driver();
561		$expire_notify	= ADODB_Session::expireNotify();
562		$filter			= ADODB_Session::filter();
563		$lifetime		= ADODB_Session::lifetime();
564		$table			= ADODB_Session::table();
565
566		if (!$conn) {
567			return false;
568		}
569
570		assert('$table');
571
572		$expiry = time() + $lifetime;
573
574		$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
575
576		// crc32 optimization since adodb 2.1
577		// now we only update expiry date, thx to sebastian thom in adodb 2.32
578		if ($crc !== false && $crc == (strlen($val) . crc32($val))) {
579			if ($debug) {
580				echo '<p>Session: Only updating date - crc32 not changed</p>';
581			}
582			$sql = "UPDATE $table SET expiry = ".$conn->Param('0')." WHERE $binary sesskey = ".$conn->Param('1')." AND expiry >= ".$conn->Param('2');
583			$rs =& $conn->Execute($sql,array($expiry,$key,time()));
584			ADODB_Session::_dumprs($rs);
585			if ($rs) {
586				$rs->Close();
587			}
588			return true;
589		}
590		$val = rawurlencode($val);
591		foreach ($filter as $f) {
592			if (is_object($f)) {
593				$val = $f->write($val, ADODB_Session::_sessionKey());
594			}
595		}
596
597		$arr = array('sesskey' => $key, 'expiry' => $expiry, $data => $val, 'expireref' => '');
598		if ($expire_notify) {
599			$var = reset($expire_notify);
600			global $$var;
601			if (isset($$var)) {
602				$arr['expireref'] = $$var;
603			}
604		}
605
606		if (!$clob) {	// no lobs, simply use replace()
607			$arr[$data] = $conn->qstr($val);
608			$rs = $conn->Replace($table, $arr, 'sesskey', $autoQuote = true);
609			ADODB_Session::_dumprs($rs);
610		} else {
611			// what value shall we insert/update for lob row?
612			switch ($driver) {
613				// empty_clob or empty_lob for oracle dbs
614				case 'oracle':
615				case 'oci8':
616				case 'oci8po':
617				case 'oci805':
618					$lob_value = sprintf('empty_%s()', strtolower($clob));
619					break;
620
621				// null for all other
622				default:
623					$lob_value = 'null';
624					break;
625			}
626
627			// do we insert or update? => as for sesskey
628			$rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = $qkey");
629			ADODB_Session::_dumprs($rs);
630			if ($rs && reset($rs->fields) > 0) {
631				$sql = "UPDATE $table SET expiry = $expiry, $data = $lob_value WHERE  sesskey = $qkey";
632			} else {
633				$sql = "INSERT INTO $table (expiry, $data, sesskey) VALUES ($expiry, $lob_value, $qkey)";
634			}
635			if ($rs) {
636				$rs->Close();
637			}
638
639			$err = '';
640			$rs1 =& $conn->Execute($sql);
641			ADODB_Session::_dumprs($rs1);
642			if (!$rs1) {
643				$err = $conn->ErrorMsg()."\n";
644			}
645			$rs2 =& $conn->UpdateBlob($table, $data, $val, " sesskey=$qkey", strtoupper($clob));
646			ADODB_Session::_dumprs($rs2);
647			if (!$rs2) {
648				$err .= $conn->ErrorMsg()."\n";
649			}
650			$rs = ($rs && $rs2) ? true : false;
651			if ($rs1) {
652				$rs1->Close();
653			}
654			if (is_object($rs2)) {
655				$rs2->Close();
656			}
657		}
658
659		if (!$rs) {
660			ADOConnection::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);
661			return false;
662		}  else {
663			// bug in access driver (could be odbc?) means that info is not committed
664			// properly unless select statement executed in Win2000
665			if ($conn->databaseType == 'access') {
666				$sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
667				$rs =& $conn->Execute($sql);
668				ADODB_Session::_dumprs($rs);
669				if ($rs) {
670					$rs->Close();
671				}
672			}
673		}
674		return $rs ? true : false;
675	}
676
677	/*!
678	*/
679	function destroy($key) {
680		$conn			=& ADODB_Session::_conn();
681		$table			= ADODB_Session::table();
682		$expire_notify	= ADODB_Session::expireNotify();
683
684		if (!$conn) {
685			return false;
686		}
687
688		assert('$table');
689
690		$qkey = $conn->quote($key);
691		$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
692
693		if ($expire_notify) {
694			reset($expire_notify);
695			$fn = next($expire_notify);
696			$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
697			$sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey";
698			$rs =& $conn->Execute($sql);
699			ADODB_Session::_dumprs($rs);
700			$conn->SetFetchMode($savem);
701			if (!$rs) {
702				return false;
703			}
704			if (!$rs->EOF) {
705				$ref = $rs->fields[0];
706				$key = $rs->fields[1];
707				//assert('$ref');
708				//assert('$key');
709				$fn($ref, $key);
710			}
711			$rs->Close();
712		}
713
714		$sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";
715		$rs =& $conn->Execute($sql);
716		ADODB_Session::_dumprs($rs);
717		if ($rs) {
718			$rs->Close();
719		}
720
721		return $rs ? true : false;
722	}
723
724	/*!
725	*/
726	function gc($maxlifetime) {
727		$conn			=& ADODB_Session::_conn();
728		$debug			= ADODB_Session::debug();
729		$expire_notify	= ADODB_Session::expireNotify();
730		$optimize		= ADODB_Session::optimize();
731		$sync_seconds	= ADODB_Session::syncSeconds();
732		$table			= ADODB_Session::table();
733
734		if (!$conn) {
735			return false;
736		}
737
738		assert('$table');
739
740		$time			= time();
741
742		$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
743
744		if ($expire_notify) {
745			reset($expire_notify);
746			$fn = next($expire_notify);
747			$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
748			$sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time";
749			$rs =& $conn->Execute($sql);
750			ADODB_Session::_dumprs($rs);
751			$conn->SetFetchMode($savem);
752			if ($rs) {
753				$conn->BeginTrans();
754				$keys = array();
755				while (!$rs->EOF) {
756					$ref = $rs->fields[0];
757					$key = $rs->fields[1];
758					$fn($ref, $key);
759					$del = $conn->Execute("DELETE FROM $table WHERE sesskey='$key'");
760					$rs->MoveNext();
761				}
762				$rs->Close();
763				
764				$conn->CommitTrans();
765			}
766		} else {
767			$sql = "DELETE FROM $table WHERE expiry < $time";
768			$rs =& $conn->Execute($sql);
769			ADODB_Session::_dumprs($rs);
770			if ($rs) {
771				$rs->Close();
772			}
773			if ($debug) {
774				ADOConnection::outp("<p><b>Garbage Collection</b>: $sql</p>");
775			}
776		}
777
778		// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
779		if ($optimize) {
780			$driver = ADODB_Session::driver();
781
782			if (preg_match('/mysql/i', $driver)) {
783				$sql = "OPTIMIZE TABLE $table";
784			}
785			if (preg_match('/postgres/i', $driver)) {
786				$sql = "VACUUM $table";
787			}
788			if (!empty($sql)) {
789				$conn->Execute($sql);
790			}
791		}
792
793		if ($sync_seconds) {
794			$sql = 'SELECT ';
795			if ($conn->dataProvider === 'oci8') {
796				$sql .= "TO_CHAR({$conn->sysTimeStamp}, 'RRRR-MM-DD HH24:MI:SS')";
797			} else {
798				$sql .= $conn->sysTimeStamp;
799			}
800			$sql .= " FROM $table";
801
802			$rs =& $conn->SelectLimit($sql, 1);
803			if ($rs && !$rs->EOF) {
804				$dbts = reset($rs->fields);
805				$rs->Close();
806				$dbt = $conn->UnixTimeStamp($dbts);
807				$t = time();
808
809				if (abs($dbt - $t) >= $sync_seconds) {
810					global $HTTP_SERVER_VARS;
811					$msg = __FILE__ .
812						": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: " .
813						" database=$dbt ($dbts), webserver=$t (diff=". (abs($dbt - $t) / 3600) . ' hours)';
814					error_log($msg);
815					if ($debug) {
816						ADOConnection::outp("<p>$msg</p>");
817					}
818				}
819			}
820		}
821
822		return true;
823	}
824
825}
826
827ADODB_Session::_init();
828
829
830// for backwards compatability only
831function adodb_sess_open($save_path, $session_name, $persist = true) {
832	return ADODB_Session::open($save_path, $session_name, $persist);
833}
834
835// for backwards compatability only
836function adodb_sess_gc($t)
837{	
838	return ADODB_Session::gc($t);
839}
840
841?>