root/releases/elgg0.8rc2/lib/adodb/adodb-session-clob.php

Revision 269, 14.0 kB (checked in by ben, 3 years ago)

--

  • Property svn:eol-style set to native
Line 
1 <?php
2 /*
3   V4.01 23 Oct 2003  (c) 2000-2003 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      GLOBAL $HTTP_SESSION_VARS;
19     include('adodb.inc.php');
20     include('adodb-session.php');
21     session_start();
22     session_register('AVAR');
23     $HTTP_SESSION_VARS['AVAR'] += 1;
24     print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
25     
26 To force non-persistent connections, call adodb_session_open first before session_start():
27
28      GLOBAL $HTTP_SESSION_VARS;
29     include('adodb.inc.php');
30     include('adodb-session.php');
31     adodb_session_open(false,false,false);
32     session_start();
33     session_register('AVAR');
34     $HTTP_SESSION_VARS['AVAR'] += 1;
35     print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['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.0.6 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     
115     if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB';
116     
117     $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
118     if ($ADODB_SESS_LIFE <= 1) {
119      // bug in PHP 4.0.3 pl 1  -- how about other versions?
120      //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
121          $ADODB_SESS_LIFE=1440;
122     }
123     $ADODB_SESSION_CRC = false;
124     //$ADODB_SESS_DEBUG = true;
125     
126     //////////////////////////////////
127     /* SET THE FOLLOWING PARAMETERS */
128     //////////////////////////////////
129     
130     if (empty($ADODB_SESSION_DRIVER)) {
131         $ADODB_SESSION_DRIVER='mysql';
132         $ADODB_SESSION_CONNECT='localhost';
133         $ADODB_SESSION_USER ='root';
134         $ADODB_SESSION_PWD ='';
135         $ADODB_SESSION_DB ='xphplens_2';
136     }
137     
138     if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
139         $ADODB_SESSION_EXPIRE_NOTIFY = false;
140     }
141     //  Made table name configurable - by David Johnson djohnson@inpro.net
142     if (empty($ADODB_SESSION_TBL)){
143         $ADODB_SESSION_TBL = 'sessions';
144     }
145     
146
147     // defaulting $ADODB_SESSION_USE_LOBS
148     if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) {
149         $ADODB_SESSION_USE_LOBS = false;
150     }
151
152     /*
153     $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
154     $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
155     $ADODB_SESS['user'] = $ADODB_SESSION_USER;
156     $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
157     $ADODB_SESS['db'] = $ADODB_SESSION_DB;
158     $ADODB_SESS['life'] = $ADODB_SESS_LIFE;
159     $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
160     
161     $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
162     $ADODB_SESS['table'] = $ADODB_SESS_TBL;
163     */
164     
165 /****************************************************************************************\
166     Create the connection to the database.
167     
168     If $ADODB_SESS_CONN already exists, reuse that connection
169 \****************************************************************************************/
170 function adodb_sess_open($save_path, $session_name,$persist=true)
171 {
172 GLOBAL $ADODB_SESS_CONN;
173     if (isset($ADODB_SESS_CONN)) return true;
174     
175 GLOBAL     $ADODB_SESSION_CONNECT,
176     $ADODB_SESSION_DRIVER,
177     $ADODB_SESSION_USER,
178     $ADODB_SESSION_PWD,
179     $ADODB_SESSION_DB,
180     $ADODB_SESS_DEBUG;
181     
182     // cannot use & below - do not know why...
183     $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
184     if (!empty($ADODB_SESS_DEBUG)) {
185         $ADODB_SESS_CONN->debug = true;
186         ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
187     }
188     if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
189             $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
190     else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
191             $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
192     
193     if (!$ok) ADOConnection::outp( "<p>Session: connection failed</p>",false);
194 }
195
196 /****************************************************************************************\
197     Close the connection
198 \****************************************************************************************/
199 function adodb_sess_close()
200 {
201 global $ADODB_SESS_CONN;
202
203     if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
204     return true;
205 }
206
207 /****************************************************************************************\
208     Slurp in the session variables and return the serialized string
209 \****************************************************************************************/
210 function adodb_sess_read($key)
211 {
212 global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
213
214     $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
215     if ($rs) {
216         if ($rs->EOF) {
217             $v = '';
218         } else
219             $v = rawurldecode(reset($rs->fields));
220             
221         $rs->Close();
222         
223         // new optimization adodb 2.1
224         $ADODB_SESSION_CRC = strlen($v).crc32($v);
225         
226         return $v;
227     }
228     
229     return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
230 }
231
232 /****************************************************************************************\
233     Write the serialized data to a database.
234     
235     If the data has not been modified since adodb_sess_read(), we do not write.
236 \****************************************************************************************/
237 function adodb_sess_write($key, $val)
238 {
239     global
240         $ADODB_SESS_CONN,
241         $ADODB_SESS_LIFE,
242         $ADODB_SESSION_TBL,
243         $ADODB_SESS_DEBUG,
244         $ADODB_SESSION_CRC,
245         $ADODB_SESSION_EXPIRE_NOTIFY,
246         $ADODB_SESSION_DRIVER,            // added
247         $ADODB_SESSION_USE_LOBS;        // added
248
249     $expiry = time() + $ADODB_SESS_LIFE;
250     
251     // crc32 optimization since adodb 2.1
252     // now we only update expiry date, thx to sebastian thom in adodb 2.32
253     if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
254         if ($ADODB_SESS_DEBUG) echo "<p>Session: Only updating date - crc32 not changed</p>";
255         $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
256         $rs = $ADODB_SESS_CONN->Execute($qry);   
257         return true;
258     }
259     $val = rawurlencode($val);
260     
261     $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
262     if ($ADODB_SESSION_EXPIRE_NOTIFY) {
263         $var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
264         global $$var;
265         $arr['expireref'] = $$var;
266     }
267
268     
269     if ($ADODB_SESSION_USE_LOBS === false) {    // no lobs, simply use replace()
270         $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true);
271         if (!$rs) {
272             $err = $ADODB_SESS_CONN->ErrorMsg();
273         }
274     } else {
275         // what value shall we insert/update for lob row?
276         switch ($ADODB_SESSION_DRIVER) {
277             // empty_clob or empty_lob for oracle dbs
278             case "oracle":
279             case "oci8":
280             case "oci8po":
281             case "oci805":
282                 $lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS));
283                 break;
284
285             // null for all other
286             default:
287                 $lob_value = "null";
288                 break;
289         }
290
291         // do we insert or update? => as for sesskey
292         $res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'");
293         if ($res && reset($res->fields) > 0) {
294             $qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key);
295         } else {
296             // insert
297             $qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value);
298         }
299
300         $err = "";
301         $rs1 = $ADODB_SESS_CONN->Execute($qry);
302         if (!$rs1) {
303             $err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
304         }
305         $rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS));
306         if (!$rs2) {
307             $err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
308         }
309         $rs = ($rs1 && $rs2) ? true : false;
310     }
311
312     if (!$rs) {
313         ADOConnection::outp( '<p>Session Replace: '.nl2br($err).'</p>',false);
314     }  else {
315         // bug in access driver (could be odbc?) means that info is not commited
316         // properly unless select statement executed in Win2000
317         if ($ADODB_SESS_CONN->databaseType == 'access')
318             $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
319     }
320     return !empty($rs);
321 }
322
323 function adodb_sess_destroy($key)
324 {
325     global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
326     
327     if ($ADODB_SESSION_EXPIRE_NOTIFY) {
328         reset($ADODB_SESSION_EXPIRE_NOTIFY);
329         $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
330         $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
331         $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
332         $ADODB_SESS_CONN->SetFetchMode($savem);
333         if ($rs) {
334             $ADODB_SESS_CONN->BeginTrans();
335             while (!$rs->EOF) {
336                 $ref = $rs->fields[0];
337                 $key = $rs->fields[1];
338                 $fn($ref,$key);
339                 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
340                 $rs->MoveNext();
341             }
342             $ADODB_SESS_CONN->CommitTrans();
343         }
344     } else {
345         $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
346         $rs = $ADODB_SESS_CONN->Execute($qry);
347     }
348     return $rs ? true : false;
349 }
350
351 function adodb_sess_gc($maxlifetime)
352 {
353     global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
354     
355     if ($ADODB_SESSION_EXPIRE_NOTIFY) {
356         reset($ADODB_SESSION_EXPIRE_NOTIFY);
357         $fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
358         $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
359         $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < " . time());
360         $ADODB_SESS_CONN->SetFetchMode($savem);
361         if ($rs) {
362             $ADODB_SESS_CONN->BeginTrans();
363             while (!$rs->EOF) {
364                 $ref = $rs->fields[0];
365                 $key = $rs->fields[1];
366                 $fn($ref,$key);
367                 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
368                 $rs->MoveNext();
369             }
370             $ADODB_SESS_CONN->CommitTrans();
371         }
372     } else {
373         $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
374         $ADODB_SESS_CONN->Execute($qry);
375     
376         if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p><b>Garbage Collection</b>: $qry</p>");
377     }
378     // suggested by Cameron, "GaM3R" <gamr@outworld.cx>
379     if (defined('ADODB_SESSION_OPTIMIZE')) {
380     global $ADODB_SESSION_DRIVER;
381     
382         switch( $ADODB_SESSION_DRIVER ) {
383             case 'mysql':
384             case 'mysqlt':
385                 $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
386                 break;
387             case 'postgresql':
388             case 'postgresql7':
389                 $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;   
390                 break;
391         }
392         if (!empty($opt_qry)) {
393             $ADODB_SESS_CONN->Execute($opt_qry);
394         }
395     }
396     if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select  TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
397     else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
398     
399     $rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
400     if ($rs && !$rs->EOF) {
401     
402         $dbts = reset($rs->fields);
403         $rs->Close();
404         $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
405         $t = time();
406         if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
407         global $HTTP_SERVER_VARS;
408             $msg =
409             __FILE__.": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
410             error_log($msg);
411             if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p>$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 GLOBAL $HTTP_SESSION_VARS;
432
433     session_start();
434     session_register('AVAR');
435     $HTTP_SESSION_VARS['AVAR'] += 1;
436     ADOConnection::outp( "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>",false);
437 }
438
439 ?>
440
Note: See TracBrowser for help on using the browser.