Documentation TYPO3 par Ameos |
00001 <?php 00002 /* 00003 V4.93 10 Oct 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved. 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. 00007 Set tabs to 4 for best viewing. 00008 00009 Latest version of ADODB is available at http://php.weblogs.com/adodb 00010 ====================================================================== 00011 00012 This file provides PHP4 session management using the ADODB database 00013 wrapper library, using Oracle CLOB's to store data. Contributed by achim.gosse@ddd.de. 00014 00015 Example 00016 ======= 00017 00018 include('adodb.inc.php'); 00019 include('adodb-session.php'); 00020 session_start(); 00021 session_register('AVAR'); 00022 $_SESSION['AVAR'] += 1; 00023 print " 00024 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>"; 00025 00026 To force non-persistent connections, call adodb_session_open first before session_start(): 00027 00028 include('adodb.inc.php'); 00029 include('adodb-session.php'); 00030 adodb_session_open(false,false,false); 00031 session_start(); 00032 session_register('AVAR'); 00033 $_SESSION['AVAR'] += 1; 00034 print " 00035 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>"; 00036 00037 00038 Installation 00039 ============ 00040 1. Create this table in your database (syntax might vary depending on your db): 00041 00042 create table sessions ( 00043 SESSKEY char(32) not null, 00044 EXPIRY int(11) unsigned not null, 00045 EXPIREREF varchar(64), 00046 DATA CLOB, 00047 primary key (sesskey) 00048 ); 00049 00050 00051 2. Then define the following parameters in this file: 00052 $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; 00053 $ADODB_SESSION_CONNECT='server to connect to'; 00054 $ADODB_SESSION_USER ='user'; 00055 $ADODB_SESSION_PWD ='password'; 00056 $ADODB_SESSION_DB ='database'; 00057 $ADODB_SESSION_TBL = 'sessions' 00058 $ADODB_SESSION_USE_LOBS = false; (or, if you wanna use CLOBS (= 'CLOB') or ( = 'BLOB') 00059 00060 3. Recommended is PHP 4.1.0 or later. There are documented 00061 session bugs in earlier versions of PHP. 00062 00063 4. If you want to receive notifications when a session expires, then 00064 you can tag a session with an EXPIREREF, and before the session 00065 record is deleted, we can call a function that will pass the EXPIREREF 00066 as the first parameter, and the session key as the second parameter. 00067 00068 To do this, define a notification function, say NotifyFn: 00069 00070 function NotifyFn($expireref, $sesskey) 00071 { 00072 } 00073 00074 Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY. 00075 This is an array with 2 elements, the first being the name of the variable 00076 you would like to store in the EXPIREREF field, and the 2nd is the 00077 notification function's name. 00078 00079 In this example, we want to be notified when a user's session 00080 has expired, so we store the user id in the global variable $USERID, 00081 store this value in the EXPIREREF field: 00082 00083 $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn'); 00084 00085 Then when the NotifyFn is called, we are passed the $USERID as the first 00086 parameter, eg. NotifyFn($userid, $sesskey). 00087 */ 00088 00089 if (!defined('_ADODB_LAYER')) { 00090 include (dirname(__FILE__).'/adodb.inc.php'); 00091 } 00092 00093 if (!defined('ADODB_SESSION')) { 00094 00095 define('ADODB_SESSION',1); 00096 00097 /* if database time and system time is difference is greater than this, then give warning */ 00098 define('ADODB_SESSION_SYNCH_SECS',60); 00099 00100 /****************************************************************************************\ 00101 Global definitions 00102 \****************************************************************************************/ 00103 GLOBAL $ADODB_SESSION_CONNECT, 00104 $ADODB_SESSION_DRIVER, 00105 $ADODB_SESSION_USER, 00106 $ADODB_SESSION_PWD, 00107 $ADODB_SESSION_DB, 00108 $ADODB_SESS_CONN, 00109 $ADODB_SESS_LIFE, 00110 $ADODB_SESS_DEBUG, 00111 $ADODB_SESSION_EXPIRE_NOTIFY, 00112 $ADODB_SESSION_CRC, 00113 $ADODB_SESSION_USE_LOBS, 00114 $ADODB_SESSION_TBL; 00115 00116 if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB'; 00117 00118 $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime'); 00119 if ($ADODB_SESS_LIFE <= 1) { 00120 // bug in PHP 4.0.3 pl 1 -- how about other versions? 00121 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>"; 00122 $ADODB_SESS_LIFE=1440; 00123 } 00124 $ADODB_SESSION_CRC = false; 00125 //$ADODB_SESS_DEBUG = true; 00126 00128 /* SET THE FOLLOWING PARAMETERS */ 00130 00131 if (empty($ADODB_SESSION_DRIVER)) { 00132 $ADODB_SESSION_DRIVER='mysql'; 00133 $ADODB_SESSION_CONNECT='localhost'; 00134 $ADODB_SESSION_USER ='root'; 00135 $ADODB_SESSION_PWD =''; 00136 $ADODB_SESSION_DB ='xphplens_2'; 00137 } 00138 00139 if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) { 00140 $ADODB_SESSION_EXPIRE_NOTIFY = false; 00141 } 00142 // Made table name configurable - by David Johnson djohnson@inpro.net 00143 if (empty($ADODB_SESSION_TBL)){ 00144 $ADODB_SESSION_TBL = 'sessions'; 00145 } 00146 00147 00148 // defaulting $ADODB_SESSION_USE_LOBS 00149 if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) { 00150 $ADODB_SESSION_USE_LOBS = false; 00151 } 00152 00153 /* 00154 $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER; 00155 $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT; 00156 $ADODB_SESS['user'] = $ADODB_SESSION_USER; 00157 $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD; 00158 $ADODB_SESS['db'] = $ADODB_SESSION_DB; 00159 $ADODB_SESS['life'] = $ADODB_SESS_LIFE; 00160 $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; 00161 00162 $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; 00163 $ADODB_SESS['table'] = $ADODB_SESS_TBL; 00164 */ 00165 00166 /****************************************************************************************\ 00167 Create the connection to the database. 00168 00169 If $ADODB_SESS_CONN already exists, reuse that connection 00170 \****************************************************************************************/ 00171 function adodb_sess_open($save_path, $session_name,$persist=true) 00172 { 00173 GLOBAL $ADODB_SESS_CONN; 00174 if (isset($ADODB_SESS_CONN)) return true; 00175 00176 GLOBAL $ADODB_SESSION_CONNECT, 00177 $ADODB_SESSION_DRIVER, 00178 $ADODB_SESSION_USER, 00179 $ADODB_SESSION_PWD, 00180 $ADODB_SESSION_DB, 00181 $ADODB_SESS_DEBUG; 00182 00183 // cannot use & below - do not know why... 00184 $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER); 00185 if (!empty($ADODB_SESS_DEBUG)) { 00186 $ADODB_SESS_CONN->debug = true; 00187 ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB "); 00188 } 00189 if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT, 00190 $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); 00191 else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT, 00192 $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); 00193 00194 if (!$ok) ADOConnection::outp( " 00195 -- Session: connection failed</p>",false); 00196 } 00197 00198 /****************************************************************************************\ 00199 Close the connection 00200 \****************************************************************************************/ 00201 function adodb_sess_close() 00202 { 00203 global $ADODB_SESS_CONN; 00204 00205 if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close(); 00206 return true; 00207 } 00208 00209 /****************************************************************************************\ 00210 Slurp in the session variables and return the serialized string 00211 \****************************************************************************************/ 00212 function adodb_sess_read($key) 00213 { 00214 global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC; 00215 00216 $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time()); 00217 if ($rs) { 00218 if ($rs->EOF) { 00219 $v = ''; 00220 } else 00221 $v = rawurldecode(reset($rs->fields)); 00222 00223 $rs->Close(); 00224 00225 // new optimization adodb 2.1 00226 $ADODB_SESSION_CRC = strlen($v).crc32($v); 00227 00228 return $v; 00229 } 00230 00231 return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com 00232 } 00233 00234 /****************************************************************************************\ 00235 Write the serialized data to a database. 00236 00237 If the data has not been modified since adodb_sess_read(), we do not write. 00238 \****************************************************************************************/ 00239 function adodb_sess_write($key, $val) 00240 { 00241 global 00242 $ADODB_SESS_CONN, 00243 $ADODB_SESS_LIFE, 00244 $ADODB_SESSION_TBL, 00245 $ADODB_SESS_DEBUG, 00246 $ADODB_SESSION_CRC, 00247 $ADODB_SESSION_EXPIRE_NOTIFY, 00248 $ADODB_SESSION_DRIVER, // added 00249 $ADODB_SESSION_USE_LOBS; // added 00250 00251 $expiry = time() + $ADODB_SESS_LIFE; 00252 00253 // crc32 optimization since adodb 2.1 00254 // now we only update expiry date, thx to sebastian thom in adodb 2.32 00255 if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) { 00256 if ($ADODB_SESS_DEBUG) echo " 00257 -- Session: Only updating date - crc32 not changed</p>"; 00258 $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time(); 00259 $rs = $ADODB_SESS_CONN->Execute($qry); 00260 return true; 00261 } 00262 $val = rawurlencode($val); 00263 00264 $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val); 00265 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00266 $var = reset($ADODB_SESSION_EXPIRE_NOTIFY); 00267 global $$var; 00268 $arr['expireref'] = $$var; 00269 } 00270 00271 00272 if ($ADODB_SESSION_USE_LOBS === false) { // no lobs, simply use replace() 00273 $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true); 00274 if (!$rs) { 00275 $err = $ADODB_SESS_CONN->ErrorMsg(); 00276 } 00277 } else { 00278 // what value shall we insert/update for lob row? 00279 switch ($ADODB_SESSION_DRIVER) { 00280 // empty_clob or empty_lob for oracle dbs 00281 case "oracle": 00282 case "oci8": 00283 case "oci8po": 00284 case "oci805": 00285 $lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS)); 00286 break; 00287 00288 // null for all other 00289 default: 00290 $lob_value = "null"; 00291 break; 00292 } 00293 00294 // do we insert or update? => as for sesskey 00295 $res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'"); 00296 if ($res && reset($res->fields) > 0) { 00297 $qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key); 00298 } else { 00299 // insert 00300 $qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value); 00301 } 00302 00303 $err = ""; 00304 $rs1 = $ADODB_SESS_CONN->Execute($qry); 00305 if (!$rs1) { 00306 $err .= $ADODB_SESS_CONN->ErrorMsg()."\n"; 00307 } 00308 $rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS)); 00309 if (!$rs2) { 00310 $err .= $ADODB_SESS_CONN->ErrorMsg()."\n"; 00311 } 00312 $rs = ($rs1 && $rs2) ? true : false; 00313 } 00314 00315 if (!$rs) { 00316 ADOConnection::outp( ' 00317 -- Session Replace: '.nl2br($err).'</p>',false); 00318 } else { 00319 // bug in access driver (could be odbc?) means that info is not commited 00320 // properly unless select statement executed in Win2000 00321 if ($ADODB_SESS_CONN->databaseType == 'access') 00322 $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00323 } 00324 return !empty($rs); 00325 } 00326 00327 function adodb_sess_destroy($key) 00328 { 00329 global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; 00330 00331 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00332 reset($ADODB_SESSION_EXPIRE_NOTIFY); 00333 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); 00334 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); 00335 $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00336 $ADODB_SESS_CONN->SetFetchMode($savem); 00337 if ($rs) { 00338 $ADODB_SESS_CONN->BeginTrans(); 00339 while (!$rs->EOF) { 00340 $ref = $rs->fields[0]; 00341 $key = $rs->fields[1]; 00342 $fn($ref,$key); 00343 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00344 $rs->MoveNext(); 00345 } 00346 $ADODB_SESS_CONN->CommitTrans(); 00347 } 00348 } else { 00349 $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; 00350 $rs = $ADODB_SESS_CONN->Execute($qry); 00351 } 00352 return $rs ? true : false; 00353 } 00354 00355 function adodb_sess_gc($maxlifetime) 00356 { 00357 global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; 00358 00359 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00360 reset($ADODB_SESSION_EXPIRE_NOTIFY); 00361 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); 00362 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); 00363 $t = time(); 00364 $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t"); 00365 $ADODB_SESS_CONN->SetFetchMode($savem); 00366 if ($rs) { 00367 $ADODB_SESS_CONN->BeginTrans(); 00368 while (!$rs->EOF) { 00369 $ref = $rs->fields[0]; 00370 $key = $rs->fields[1]; 00371 $fn($ref,$key); 00372 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00373 $rs->MoveNext(); 00374 } 00375 $rs->Close(); 00376 00377 //$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t"); 00378 $ADODB_SESS_CONN->CommitTrans(); 00379 00380 } 00381 } else { 00382 $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time()); 00383 00384 if ($ADODB_SESS_DEBUG) ADOConnection::outp(" 00385 -- <b>Garbage Collection</b>: $qry</p>"); 00386 } 00387 // suggested by Cameron, "GaM3R" <gamr@outworld.cx> 00388 if (defined('ADODB_SESSION_OPTIMIZE')) { 00389 global $ADODB_SESSION_DRIVER; 00390 00391 switch( $ADODB_SESSION_DRIVER ) { 00392 case 'mysql': 00393 case 'mysqlt': 00394 $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL; 00395 break; 00396 case 'postgresql': 00397 case 'postgresql7': 00398 $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL; 00399 break; 00400 } 00401 if (!empty($opt_qry)) { 00402 $ADODB_SESS_CONN->Execute($opt_qry); 00403 } 00404 } 00405 if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL; 00406 else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL; 00407 00408 $rs =& $ADODB_SESS_CONN->SelectLimit($sql,1); 00409 if ($rs && !$rs->EOF) { 00410 00411 $dbts = reset($rs->fields); 00412 $rs->Close(); 00413 $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts); 00414 $t = time(); 00415 if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) { 00416 $msg = 00417 __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)"; 00418 error_log($msg); 00419 if ($ADODB_SESS_DEBUG) ADOConnection::outp(" 00420 -- $msg</p>"); 00421 } 00422 } 00423 00424 return true; 00425 } 00426 00427 session_module_name('user'); 00428 session_set_save_handler( 00429 "adodb_sess_open", 00430 "adodb_sess_close", 00431 "adodb_sess_read", 00432 "adodb_sess_write", 00433 "adodb_sess_destroy", 00434 "adodb_sess_gc"); 00435 } 00436 00437 /* TEST SCRIPT -- UNCOMMENT */ 00438 00439 if (0) { 00440 00441 session_start(); 00442 session_register('AVAR'); 00443 $_SESSION['AVAR'] += 1; 00444 ADOConnection::outp( " 00445 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false); 00446 } 00447 00448 ?>