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, using Oracle CLOB's to store data. Contributed by achim.gosse@ddd.de.
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_session_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 CLOB,
47
	  primary key (sesskey)
48
  );
49
 
50
 
51
  2. Then define the following parameters in this file:
52
  	$ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
53
	$ADODB_SESSION_CONNECT='server to connect to';
54
	$ADODB_SESSION_USER ='user';
55
	$ADODB_SESSION_PWD ='password';
56
	$ADODB_SESSION_DB ='database';
57
	$ADODB_SESSION_TBL = 'sessions'
58
	$ADODB_SESSION_USE_LOBS = false; (or, if you wanna use CLOBS (= 'CLOB') or ( = 'BLOB')
59
 
60
  3. Recommended is PHP 4.1.0 or later. There are documented
61
	 session bugs in earlier versions of PHP.
62
 
63
  4. If you want to receive notifications when a session expires, then
64
  	 you can tag a session with an EXPIREREF, and before the session
65
	 record is deleted, we can call a function that will pass the EXPIREREF
66
	 as the first parameter, and the session key as the second parameter.
67
 
68
	 To do this, define a notification function, say NotifyFn:
69
 
70
	 	function NotifyFn($expireref, $sesskey)
71
	 	{
72
	 	}
73
 
74
	 Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
75
	 This is an array with 2 elements, the first being the name of the variable
76
	 you would like to store in the EXPIREREF field, and the 2nd is the 
77
	 notification function's name.
78
 
79
	 In this example, we want to be notified when a user's session 
80
	 has expired, so we store the user id in the global variable $USERID, 
81
	 store this value in the EXPIREREF field:
82
 
83
	 	$ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
84
 
85
	Then when the NotifyFn is called, we are passed the $USERID as the first
86
	parameter, eg. NotifyFn($userid, $sesskey).
87
*/
88
 
89
if (!defined('_ADODB_LAYER')) {
90
	include (dirname(__FILE__).'/adodb.inc.php');
91
}
92
 
93
if (!defined('ADODB_SESSION')) {
94
 
95
 define('ADODB_SESSION',1);
96
 
97
 /* if database time and system time is difference is greater than this, then give warning */
98
 define('ADODB_SESSION_SYNCH_SECS',60); 
99
 
100
/****************************************************************************************\
101
	Global definitions
102
\****************************************************************************************/
103
GLOBAL 	$ADODB_SESSION_CONNECT, 
104
	$ADODB_SESSION_DRIVER,
105
	$ADODB_SESSION_USER,
106
	$ADODB_SESSION_PWD,
107
	$ADODB_SESSION_DB,
108
	$ADODB_SESS_CONN,
109
	$ADODB_SESS_LIFE,
110
	$ADODB_SESS_DEBUG,
111
	$ADODB_SESSION_EXPIRE_NOTIFY,
112
	$ADODB_SESSION_CRC,
113
	$ADODB_SESSION_USE_LOBS,
114
	$ADODB_SESSION_TBL;
115
 
116
	if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB';
117
 
118
	$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
119
	if ($ADODB_SESS_LIFE <= 1) {
120
	 // bug in PHP 4.0.3 pl 1  -- how about other versions?
121
	 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
122
	 	$ADODB_SESS_LIFE=1440;
123
	}
124
	$ADODB_SESSION_CRC = false;
125
	//$ADODB_SESS_DEBUG = true;
126
 
127
	//////////////////////////////////
128
	/* SET THE FOLLOWING PARAMETERS */
129
	//////////////////////////////////
130
 
131
	if (empty($ADODB_SESSION_DRIVER)) {
132
		$ADODB_SESSION_DRIVER='mysql';
133
		$ADODB_SESSION_CONNECT='localhost';
134
		$ADODB_SESSION_USER ='root';
135
		$ADODB_SESSION_PWD ='';
136
		$ADODB_SESSION_DB ='xphplens_2';
137
	}
138
 
139
	if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
140
		$ADODB_SESSION_EXPIRE_NOTIFY = false;
141
	}
142
	//  Made table name configurable - by David Johnson djohnson@inpro.net
143
	if (empty($ADODB_SESSION_TBL)){
144
		$ADODB_SESSION_TBL = 'sessions';
145
	}
146
 
147
 
148
	// defaulting $ADODB_SESSION_USE_LOBS
149
	if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) {
150
		$ADODB_SESSION_USE_LOBS = false;
151
	}
152
 
153
	/*
154
	$ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
155
	$ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
156
	$ADODB_SESS['user'] = $ADODB_SESSION_USER;
157
	$ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
158
	$ADODB_SESS['db'] = $ADODB_SESSION_DB;
159
	$ADODB_SESS['life'] = $ADODB_SESS_LIFE;
160
	$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
161
 
162
	$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
163
	$ADODB_SESS['table'] = $ADODB_SESS_TBL;
164
	*/
165
 
166
/****************************************************************************************\
167
	Create the connection to the database. 
168
 
169
	If $ADODB_SESS_CONN already exists, reuse that connection
170
\****************************************************************************************/
171
function adodb_sess_open($save_path, $session_name,$persist=true) 
172
{
173
GLOBAL $ADODB_SESS_CONN;
174
	if (isset($ADODB_SESS_CONN)) return true;
175
 
176
GLOBAL 	$ADODB_SESSION_CONNECT, 
177
	$ADODB_SESSION_DRIVER,
178
	$ADODB_SESSION_USER,
179
	$ADODB_SESSION_PWD,
180
	$ADODB_SESSION_DB,
181
	$ADODB_SESS_DEBUG;
182
 
183
	// cannot use & below - do not know why...
184
	$ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
185
	if (!empty($ADODB_SESS_DEBUG)) {
186
		$ADODB_SESS_CONN->debug = true;
187
		ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
188
	}
189
	if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
190
			$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
191
	else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
192
			$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
193
 
194
	if (!$ok) ADOConnection::outp( "
195
-- Session: connection failed</p>",false);
196
}
197
 
198
/****************************************************************************************\
199
	Close the connection
200
\****************************************************************************************/
201
function adodb_sess_close() 
202
{
203
global $ADODB_SESS_CONN;
204
 
205
	if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
206
	return true;
207
}
208
 
209
/****************************************************************************************\
210
	Slurp in the session variables and return the serialized string
211
\****************************************************************************************/
212
function adodb_sess_read($key) 
213
{
214
global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
215
 
216
	$rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
217
	if ($rs) {
218
		if ($rs->EOF) {
219
			$v = '';
220
		} else 
221
			$v = rawurldecode(reset($rs->fields));
222
 
223
		$rs->Close();
224
 
225
		// new optimization adodb 2.1
226
		$ADODB_SESSION_CRC = strlen($v).crc32($v);
227
 
228
		return $v;
229
	}
230
 
231
	return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
232
}
233
 
234
/****************************************************************************************\
235
	Write the serialized data to a database.
236
 
237
	If the data has not been modified since adodb_sess_read(), we do not write.
238
\****************************************************************************************/
239
function adodb_sess_write($key, $val) 
240
{
241
	global
242
		$ADODB_SESS_CONN, 
243
		$ADODB_SESS_LIFE, 
244
		$ADODB_SESSION_TBL,
245
		$ADODB_SESS_DEBUG, 
246
		$ADODB_SESSION_CRC,
247
		$ADODB_SESSION_EXPIRE_NOTIFY,
248
		$ADODB_SESSION_DRIVER,			// added
249
		$ADODB_SESSION_USE_LOBS;		// added
250
 
251
	$expiry = time() + $ADODB_SESS_LIFE;
252
 
253
	// crc32 optimization since adodb 2.1
254
	// now we only update expiry date, thx to sebastian thom in adodb 2.32
255
	if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
256
		if ($ADODB_SESS_DEBUG) echo "
257
-- Session: Only updating date - crc32 not changed</p>";
258
		$qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
259
		$rs = $ADODB_SESS_CONN->Execute($qry);	
260
		return true;
261
	}
262
	$val = rawurlencode($val);
263
 
264
	$arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
265
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
266
		$var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
267
		global $$var;
268
		$arr['expireref'] = $$var;
269
	}
270
 
271
 
272
	if ($ADODB_SESSION_USE_LOBS === false) {	// no lobs, simply use replace()
273
		$rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true);
274
		if (!$rs) {
275
			$err = $ADODB_SESS_CONN->ErrorMsg();
276
		}
277
	} else {
278
		// what value shall we insert/update for lob row?
279
		switch ($ADODB_SESSION_DRIVER) {
280
			// empty_clob or empty_lob for oracle dbs
281
			case "oracle":
282
			case "oci8":
283
			case "oci8po":
284
			case "oci805":
285
				$lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS));
286
				break;
287
 
288
			// null for all other
289
			default:
290
				$lob_value = "null";
291
				break;
292
		}
293
 
294
		// do we insert or update? => as for sesskey
295
		$res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'");
296
		if ($res && reset($res->fields) > 0) {
297
			$qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key);
298
		} else {
299
			// insert
300
			$qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value);
301
		}
302
 
303
		$err = "";
304
		$rs1 = $ADODB_SESS_CONN->Execute($qry);
305
		if (!$rs1) {
306
			$err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
307
		}
308
		$rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS));
309
		if (!$rs2) {
310
			$err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
311
		}
312
		$rs = ($rs1 && $rs2) ? true : false;
313
	}
314
 
315
	if (!$rs) {
316
		ADOConnection::outp( '
317
-- Session Replace: '.nl2br($err).'</p>',false);
318
	}  else {
319
		// bug in access driver (could be odbc?) means that info is not commited
320
		// properly unless select statement executed in Win2000
321
		if ($ADODB_SESS_CONN->databaseType == 'access') 
322
			$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
323
	}
324
	return !empty($rs);
325
}
326
 
327
function adodb_sess_destroy($key) 
328
{
329
	global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
330
 
331
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
332
		reset($ADODB_SESSION_EXPIRE_NOTIFY);
333
		$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
334
		$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
335
		$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
336
		$ADODB_SESS_CONN->SetFetchMode($savem);
337
		if ($rs) {
338
			$ADODB_SESS_CONN->BeginTrans();
339
			while (!$rs->EOF) {
340
				$ref = $rs->fields[0];
341
				$key = $rs->fields[1];
342
				$fn($ref,$key);
343
				$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
344
				$rs->MoveNext();
345
			}
346
			$ADODB_SESS_CONN->CommitTrans();
347
		}
348
	} else {
349
		$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
350
		$rs = $ADODB_SESS_CONN->Execute($qry);
351
	}
352
	return $rs ? true : false;
353
}
354
 
355
function adodb_sess_gc($maxlifetime) 
356
{
357
	global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
358
 
359
	if ($ADODB_SESSION_EXPIRE_NOTIFY) {
360
		reset($ADODB_SESSION_EXPIRE_NOTIFY);
361
		$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
362
		$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
363
		$t = time();
364
		$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
365
		$ADODB_SESS_CONN->SetFetchMode($savem);
366
		if ($rs) {
367
			$ADODB_SESS_CONN->BeginTrans();
368
			while (!$rs->EOF) {
369
				$ref = $rs->fields[0];
370
				$key = $rs->fields[1];
371
				$fn($ref,$key);
372
				$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
373
				$rs->MoveNext();
374
			}
375
			$rs->Close();
376
 
377
			//$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t");
378
			$ADODB_SESS_CONN->CommitTrans();
379
 
380
		}
381
	} else {
382
		$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time());
383
 
384
		if ($ADODB_SESS_DEBUG) ADOConnection::outp("
385
-- <b>Garbage Collection</b>: $qry</p>");
386
	}
387
	// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
388
	if (defined('ADODB_SESSION_OPTIMIZE')) {
389
	global $ADODB_SESSION_DRIVER;
390
 
391
		switch( $ADODB_SESSION_DRIVER ) {
392
			case 'mysql':
393
			case 'mysqlt':
394
				$opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
395
				break;
396
			case 'postgresql':
397
			case 'postgresql7':
398
				$opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;	
399
				break;
400
		}
401
		if (!empty($opt_qry)) {
402
			$ADODB_SESS_CONN->Execute($opt_qry);
403
		}
404
	}
405
	if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select  TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
406
	else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
407
 
408
	$rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
409
	if ($rs && !$rs->EOF) {
410
 
411
		$dbts = reset($rs->fields);
412
		$rs->Close();
413
		$dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
414
		$t = time();
415
		if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
416
			$msg = 
417
			__FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
418
			error_log($msg);
419
			if ($ADODB_SESS_DEBUG) ADOConnection::outp("
420
-- $msg</p>");
421
		}
422
	}
423
 
424
	return true;
425
}
426
 
427
session_module_name('user'); 
428
session_set_save_handler(
429
	"adodb_sess_open",
430
	"adodb_sess_close",
431
	"adodb_sess_read",
432
	"adodb_sess_write",
433
	"adodb_sess_destroy",
434
	"adodb_sess_gc");
435
}
436
 
437
/*  TEST SCRIPT -- UNCOMMENT */
438
 
439
if (0) {
440
 
441
	session_start();
442
	session_register('AVAR');
443
	$_SESSION['AVAR'] += 1;
444
	ADOConnection::outp( "
445
-- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false);
446
}
447
 
448
?>