Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
<?php
2
/*
3
V4.80 8 Mar 2006  (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
4
  Released under both BSD license and Lesser GPL library license. 
5
  Whenever there is any discrepancy between the two licenses, 
6
  the BSD license will take precedence.
7
	  Set tabs to 4 for best viewing.
8
 
9
  Latest version of ADODB is available at http://php.weblogs.com/adodb
10
  ======================================================================
11
 
12
 This file provides PHP4 session management using the ADODB database
13
wrapper library.
14
 
15
 Example
16
 =======
17
 
18
	include('adodb.inc.php');
19
	include('adodb-session.php');
20
	session_start();
21
	session_register('AVAR');
22
	$_SESSION['AVAR'] += 1;
23
	print "
24
-- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
25
 
26
To force non-persistent connections, call adodb_session_open first before session_start():
27
 
28
	include('adodb.inc.php');
29
	include('adodb-session.php');
30
	adodb_sess_open(false,false,false);
31
	session_start();
32
	session_register('AVAR');
33
	$_SESSION['AVAR'] += 1;
34
	print "
35
-- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>";
36
 
37
 
38
 Installation
39
 ============
40
 1. Create this table in your database (syntax might vary depending on your db):
41
 
42
  create table sessions (
43
	   SESSKEY char(32) not null,
44
	   EXPIRY int(11) unsigned not null,
45
	   EXPIREREF varchar(64),
46
	   DATA text not null,
47
	  primary key (sesskey)
48
  );
49
 
50
  For oracle:
51
    create table sessions (
52
	   SESSKEY char(32) not null,
53
	   EXPIRY DECIMAL(16)  not null,
54
	   EXPIREREF varchar(64),
55
	   DATA varchar(4000) not null,
56
	  primary key (sesskey)
57
  );
58
 
59
 
60
  2. Then define the following parameters. You can either modify
61
     this file, or define them before this file is included:
62
 
63
  	$ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
64
	$ADODB_SESSION_CONNECT='server to connect to';
65
	$ADODB_SESSION_USER ='user';
66
	$ADODB_SESSION_PWD ='password';
67
	$ADODB_SESSION_DB ='database';
68
	$ADODB_SESSION_TBL = 'sessions'
69
 
70
  3. Recommended is PHP 4.1.0 or later. There are documented
71
	 session bugs in earlier versions of PHP.
72
 
73
  4. If you want to receive notifications when a session expires, then
74
  	 you can tag a session with an EXPIREREF, and before the session
75
	 record is deleted, we can call a function that will pass the EXPIREREF
76
	 as the first parameter, and the session key as the second parameter.
77
 
78
	 To do this, define a notification function, say NotifyFn:
79
 
80
	 	function NotifyFn($expireref, $sesskey)
81
	 	{
82
	 	}
83
 
84
	 Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
85
	 This is an array with 2 elements, the first being the name of the variable
86
	 you would like to store in the EXPIREREF field, and the 2nd is the 
87
	 notification function's name.
88
 
89
	 In this example, we want to be notified when a user's session 
90
	 has expired, so we store the user id in the global variable $USERID, 
91
	 store this value in the EXPIREREF field:
92
 
93
	 	$ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
94
 
95
	Then when the NotifyFn is called, we are passed the $USERID as the first
96
	parameter, eg. NotifyFn($userid, $sesskey).
97
*/
98
 
99
if (!defined('_ADODB_LAYER')) {
100
	include (dirname(__FILE__).'/adodb.inc.php');
101
}
102
 
103
if (!defined('ADODB_SESSION')) {
104
 
105
 define('ADODB_SESSION',1);
106
 
107
 /* if database time and system time is difference is greater than this, then give warning */
108
 define('ADODB_SESSION_SYNCH_SECS',60); 
109
 
110
 /*
111
	Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1
112
*/
113
function adodb_session_regenerate_id() 
114
{
115
	$conn =& ADODB_Session::_conn();
116
	if (!$conn) return false;
117
 
118
	$old_id = session_id();
119
	if (function_exists('session_regenerate_id')) {
120
		session_regenerate_id();
121
	} else {
122
		session_id(md5(uniqid(rand(), true)));
123
		$ck = session_get_cookie_params();
124
		setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
125
		//@session_start();
126
	}
127
	$new_id = session_id();
128
	$ok =& $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id));
129
 
130
	/* it is possible that the update statement fails due to a collision */
131
	if (!$ok) {
132
		session_id($old_id);
133
		if (empty($ck)) $ck = session_get_cookie_params();
134
		setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
135
		return false;
136
	}
137
 
138
	return true;
139
}
140
 
141
/****************************************************************************************\
142
	Global definitions
143
\****************************************************************************************/
144
GLOBAL 	$ADODB_SESSION_CONNECT, 
145
	$ADODB_SESSION_DRIVER,
146
	$ADODB_SESSION_USER,
147
	$ADODB_SESSION_PWD,
148
	$ADODB_SESSION_DB,
149
	$ADODB_SESS_CONN,
150
	$ADODB_SESS_LIFE,
151
	$ADODB_SESS_DEBUG,
152
	$ADODB_SESSION_EXPIRE_NOTIFY,
153
	$ADODB_SESSION_CRC,
154
	$ADODB_SESSION_TBL;
155
 
156
 
157
	$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
158
	if ($ADODB_SESS_LIFE <= 1) {
159
	 // bug in PHP 4.0.3 pl 1  -- how about other versions?
160
	 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
161
	 	$ADODB_SESS_LIFE=1440;
162
	}
163
	$ADODB_SESSION_CRC = false;
164
	//$ADODB_SESS_DEBUG = true;
165
 
166
	//////////////////////////////////
167
	/* SET THE FOLLOWING PARAMETERS */
168
	//////////////////////////////////
169
 
170
	if (empty($ADODB_SESSION_DRIVER)) {
171
		$ADODB_SESSION_DRIVER='mysql';
172
		$ADODB_SESSION_CONNECT='localhost';
173
		$ADODB_SESSION_USER ='root';
174
		$ADODB_SESSION_PWD ='';
175
		$ADODB_SESSION_DB ='xphplens_2';
176
	}
177
 
178
	if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
179
		$ADODB_SESSION_EXPIRE_NOTIFY = false;
180
	}
181
	//  Made table name configurable - by David Johnson djohnson@inpro.net
182
	if (empty($ADODB_SESSION_TBL)){
183
		$ADODB_SESSION_TBL = 'sessions';
184
	}
185
 
186
	/*
187
	$ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
188
	$ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
189
	$ADODB_SESS['user'] = $ADODB_SESSION_USER;
190
	$ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
191
	$ADODB_SESS['db'] = $ADODB_SESSION_DB;
192
	$ADODB_SESS['life'] = $ADODB_SESS_LIFE;
193
	$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
194
 
195
	$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
196
	$ADODB_SESS['table'] = $ADODB_SESS_TBL;
197
	*/
198
 
199
/****************************************************************************************\
200
	Create the connection to the database. 
201
 
202
	If $ADODB_SESS_CONN already exists, reuse that connection
203
\****************************************************************************************/
204
function adodb_sess_open($save_path, $session_name,$persist=true) 
205
{
206
GLOBAL $ADODB_SESS_CONN;
207
	if (isset($ADODB_SESS_CONN)) return true;
208
 
209
GLOBAL 	$ADODB_SESSION_CONNECT, 
210
	$ADODB_SESSION_DRIVER,
211
	$ADODB_SESSION_USER,
212
	$ADODB_SESSION_PWD,
213
	$ADODB_SESSION_DB,
214
	$ADODB_SESS_DEBUG;
215
 
216
	// cannot use & below - do not know why...
217
	$ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
218
	if (!empty($ADODB_SESS_DEBUG)) {
219
		$ADODB_SESS_CONN->debug = true;
220
		ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
221
	}
222
	if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
223
			$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
224
	else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
225
			$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
226
 
227
	if (!$ok) ADOConnection::outp( "
228
-- Session: connection failed</p>",false);
229
}
230
 
231
/****************************************************************************************\
232
	Close the connection
233
\****************************************************************************************/
234
function adodb_sess_close() 
235
{
236
global $ADODB_SESS_CONN;
237
 
238
	if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
239
	return true;
240
}
241
 
242
/****************************************************************************************\
243
	Slurp in the session variables and return the serialized string
244
\****************************************************************************************/
245
function adodb_sess_read($key) 
246
{
247
global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
248
 
249
	$rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
250
	if ($rs) {
251
		if ($rs->EOF) {
252
			$v = '';
253
		} else 
254
			$v = rawurldecode(reset($rs->fields));
255
 
256
		$rs->Close();
257
 
258
		// new optimization adodb 2.1
259
		$ADODB_SESSION_CRC = strlen($v).crc32($v);
260
 
261
		return $v;
262
	}
263
 
264
	return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
265
}
266
 
267
/****************************************************************************************\
268
	Write the serialized data to a database.
269
 
270
	If the data has not been modified since adodb_sess_read(), we do not write.
271
\****************************************************************************************/
272
function adodb_sess_write($key, $val) 
273
{
274
	global
275
		$ADODB_SESS_CONN, 
276
		$ADODB_SESS_LIFE, 
277
		$ADODB_SESSION_TBL,
278
		$ADODB_SESS_DEBUG, 
279
		$ADODB_SESSION_CRC,
280
		$ADODB_SESSION_EXPIRE_NOTIFY;
281
 
282
	$expiry = time() + $ADODB_SESS_LIFE;
283
 
284
	// crc32 optimization since adodb 2.1
285
	// now we only update expiry date, thx to sebastian thom in adodb 2.32
286
	if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
287
		if ($ADODB_SESS_DEBUG) echo "
288
-- Session: Only updating date - crc32 not changed</p>";
289
		$qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
290
		$rs = $ADODB_SESS_CONN->Execute($qry);	
291
		return true;
292
	}
293
	$val = rawurlencode($val);
294
 
295
	$arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
296
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
297
		$var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
298
		global $$var;
299
		$arr['expireref'] = $$var;
300
	}
301
	$rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr,
302
    	'sesskey',$autoQuote = true);
303
 
304
	if (!$rs) {
305
		ADOConnection::outp( '
306
-- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
307
	}  else {
308
		// bug in access driver (could be odbc?) means that info is not commited
309
		// properly unless select statement executed in Win2000
310
		if ($ADODB_SESS_CONN->databaseType == 'access') 
311
			$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
312
	}
313
	return !empty($rs);
314
}
315
 
316
function adodb_sess_destroy($key) 
317
{
318
	global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
319
 
320
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
321
		reset($ADODB_SESSION_EXPIRE_NOTIFY);
322
		$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
323
		$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
324
		$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
325
		$ADODB_SESS_CONN->SetFetchMode($savem);
326
		if ($rs) {
327
			$ADODB_SESS_CONN->BeginTrans();
328
			while (!$rs->EOF) {
329
				$ref = $rs->fields[0];
330
				$key = $rs->fields[1];
331
				$fn($ref,$key);
332
				$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
333
				$rs->MoveNext();
334
			}
335
			$ADODB_SESS_CONN->CommitTrans();
336
		}
337
	} else {
338
		$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
339
		$rs = $ADODB_SESS_CONN->Execute($qry);
340
	}
341
	return $rs ? true : false;
342
}
343
 
344
function adodb_sess_gc($maxlifetime) 
345
{
346
	global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
347
 
348
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
349
		reset($ADODB_SESSION_EXPIRE_NOTIFY);
350
		$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
351
		$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
352
		$t = time();
353
		$rs =& $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
354
		$ADODB_SESS_CONN->SetFetchMode($savem);
355
		if ($rs) {
356
			$ADODB_SESS_CONN->BeginTrans();
357
			while (!$rs->EOF) {
358
				$ref = $rs->fields[0];
359
				$key = $rs->fields[1];
360
				$fn($ref,$key);
361
				$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
362
				$rs->MoveNext();
363
			}
364
			$rs->Close();
365
 
366
			$ADODB_SESS_CONN->CommitTrans();
367
 
368
		}
369
	} else {
370
		$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
371
		$ADODB_SESS_CONN->Execute($qry);
372
 
373
		if ($ADODB_SESS_DEBUG) ADOConnection::outp("
374
-- <b>Garbage Collection</b>: $qry</p>");
375
	}
376
	// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
377
	if (defined('ADODB_SESSION_OPTIMIZE')) {
378
	global $ADODB_SESSION_DRIVER;
379
 
380
		switch( $ADODB_SESSION_DRIVER ) {
381
			case 'mysql':
382
			case 'mysqlt':
383
				$opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
384
				break;
385
			case 'postgresql':
386
			case 'postgresql7':
387
				$opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;	
388
				break;
389
		}
390
		if (!empty($opt_qry)) {
391
			$ADODB_SESS_CONN->Execute($opt_qry);
392
		}
393
	}
394
	if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select  TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
395
	else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
396
 
397
	$rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
398
	if ($rs && !$rs->EOF) {
399
 
400
		$dbts = reset($rs->fields);
401
		$rs->Close();
402
		$dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
403
		$t = time();
404
 
405
		if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
406
 
407
			$msg = 
408
			__FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
409
			error_log($msg);
410
			if ($ADODB_SESS_DEBUG) ADOConnection::outp("
411
-- $msg</p>");
412
		}
413
	}
414
 
415
	return true;
416
}
417
 
418
session_module_name('user'); 
419
session_set_save_handler(
420
	"adodb_sess_open",
421
	"adodb_sess_close",
422
	"adodb_sess_read",
423
	"adodb_sess_write",
424
	"adodb_sess_destroy",
425
	"adodb_sess_gc");
426
}
427
 
428
/*  TEST SCRIPT -- UNCOMMENT */
429
 
430
if (0) {
431
 
432
	session_start();
433
	session_register('AVAR');
434
	$_SESSION['AVAR'] += 1;
435
	ADOConnection::outp( "
436
-- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false);
437
}
438
 
439
?>