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. 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_sess_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 text not null, 00047 primary key (sesskey) 00048 ); 00049 00050 For oracle: 00051 create table sessions ( 00052 SESSKEY char(32) not null, 00053 EXPIRY DECIMAL(16) not null, 00054 EXPIREREF varchar(64), 00055 DATA varchar(4000) not null, 00056 primary key (sesskey) 00057 ); 00058 00059 00060 2. Then define the following parameters. You can either modify 00061 this file, or define them before this file is included: 00062 00063 $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; 00064 $ADODB_SESSION_CONNECT='server to connect to'; 00065 $ADODB_SESSION_USER ='user'; 00066 $ADODB_SESSION_PWD ='password'; 00067 $ADODB_SESSION_DB ='database'; 00068 $ADODB_SESSION_TBL = 'sessions' 00069 00070 3. Recommended is PHP 4.1.0 or later. There are documented 00071 session bugs in earlier versions of PHP. 00072 00073 4. If you want to receive notifications when a session expires, then 00074 you can tag a session with an EXPIREREF, and before the session 00075 record is deleted, we can call a function that will pass the EXPIREREF 00076 as the first parameter, and the session key as the second parameter. 00077 00078 To do this, define a notification function, say NotifyFn: 00079 00080 function NotifyFn($expireref, $sesskey) 00081 { 00082 } 00083 00084 Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY. 00085 This is an array with 2 elements, the first being the name of the variable 00086 you would like to store in the EXPIREREF field, and the 2nd is the 00087 notification function's name. 00088 00089 In this example, we want to be notified when a user's session 00090 has expired, so we store the user id in the global variable $USERID, 00091 store this value in the EXPIREREF field: 00092 00093 $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn'); 00094 00095 Then when the NotifyFn is called, we are passed the $USERID as the first 00096 parameter, eg. NotifyFn($userid, $sesskey). 00097 */ 00098 00099 if (!defined('_ADODB_LAYER')) { 00100 include (dirname(__FILE__).'/adodb.inc.php'); 00101 } 00102 00103 if (!defined('ADODB_SESSION')) { 00104 00105 define('ADODB_SESSION',1); 00106 00107 /* if database time and system time is difference is greater than this, then give warning */ 00108 define('ADODB_SESSION_SYNCH_SECS',60); 00109 00110 /* 00111 Thanks Joe Li. See http://phplens.com/lens/lensforum/msgs.php?id=11487&x=1 00112 */ 00113 function adodb_session_regenerate_id() 00114 { 00115 $conn =& ADODB_Session::_conn(); 00116 if (!$conn) return false; 00117 00118 $old_id = session_id(); 00119 if (function_exists('session_regenerate_id')) { 00120 session_regenerate_id(); 00121 } else { 00122 session_id(md5(uniqid(rand(), true))); 00123 $ck = session_get_cookie_params(); 00124 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']); 00125 //@session_start(); 00126 } 00127 $new_id = session_id(); 00128 $ok =& $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id)); 00129 00130 /* it is possible that the update statement fails due to a collision */ 00131 if (!$ok) { 00132 session_id($old_id); 00133 if (empty($ck)) $ck = session_get_cookie_params(); 00134 setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']); 00135 return false; 00136 } 00137 00138 return true; 00139 } 00140 00141 /****************************************************************************************\ 00142 Global definitions 00143 \****************************************************************************************/ 00144 GLOBAL $ADODB_SESSION_CONNECT, 00145 $ADODB_SESSION_DRIVER, 00146 $ADODB_SESSION_USER, 00147 $ADODB_SESSION_PWD, 00148 $ADODB_SESSION_DB, 00149 $ADODB_SESS_CONN, 00150 $ADODB_SESS_LIFE, 00151 $ADODB_SESS_DEBUG, 00152 $ADODB_SESSION_EXPIRE_NOTIFY, 00153 $ADODB_SESSION_CRC, 00154 $ADODB_SESSION_TBL; 00155 00156 00157 $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime'); 00158 if ($ADODB_SESS_LIFE <= 1) { 00159 // bug in PHP 4.0.3 pl 1 -- how about other versions? 00160 //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>"; 00161 $ADODB_SESS_LIFE=1440; 00162 } 00163 $ADODB_SESSION_CRC = false; 00164 //$ADODB_SESS_DEBUG = true; 00165 00167 /* SET THE FOLLOWING PARAMETERS */ 00169 00170 if (empty($ADODB_SESSION_DRIVER)) { 00171 $ADODB_SESSION_DRIVER='mysql'; 00172 $ADODB_SESSION_CONNECT='localhost'; 00173 $ADODB_SESSION_USER ='root'; 00174 $ADODB_SESSION_PWD =''; 00175 $ADODB_SESSION_DB ='xphplens_2'; 00176 } 00177 00178 if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) { 00179 $ADODB_SESSION_EXPIRE_NOTIFY = false; 00180 } 00181 // Made table name configurable - by David Johnson djohnson@inpro.net 00182 if (empty($ADODB_SESSION_TBL)){ 00183 $ADODB_SESSION_TBL = 'sessions'; 00184 } 00185 00186 /* 00187 $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER; 00188 $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT; 00189 $ADODB_SESS['user'] = $ADODB_SESSION_USER; 00190 $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD; 00191 $ADODB_SESS['db'] = $ADODB_SESSION_DB; 00192 $ADODB_SESS['life'] = $ADODB_SESS_LIFE; 00193 $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; 00194 00195 $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; 00196 $ADODB_SESS['table'] = $ADODB_SESS_TBL; 00197 */ 00198 00199 /****************************************************************************************\ 00200 Create the connection to the database. 00201 00202 If $ADODB_SESS_CONN already exists, reuse that connection 00203 \****************************************************************************************/ 00204 function adodb_sess_open($save_path, $session_name,$persist=true) 00205 { 00206 GLOBAL $ADODB_SESS_CONN; 00207 if (isset($ADODB_SESS_CONN)) return true; 00208 00209 GLOBAL $ADODB_SESSION_CONNECT, 00210 $ADODB_SESSION_DRIVER, 00211 $ADODB_SESSION_USER, 00212 $ADODB_SESSION_PWD, 00213 $ADODB_SESSION_DB, 00214 $ADODB_SESS_DEBUG; 00215 00216 // cannot use & below - do not know why... 00217 $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER); 00218 if (!empty($ADODB_SESS_DEBUG)) { 00219 $ADODB_SESS_CONN->debug = true; 00220 ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB "); 00221 } 00222 if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT, 00223 $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); 00224 else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT, 00225 $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); 00226 00227 if (!$ok) ADOConnection::outp( " 00228 -- Session: connection failed</p>",false); 00229 } 00230 00231 /****************************************************************************************\ 00232 Close the connection 00233 \****************************************************************************************/ 00234 function adodb_sess_close() 00235 { 00236 global $ADODB_SESS_CONN; 00237 00238 if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close(); 00239 return true; 00240 } 00241 00242 /****************************************************************************************\ 00243 Slurp in the session variables and return the serialized string 00244 \****************************************************************************************/ 00245 function adodb_sess_read($key) 00246 { 00247 global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC; 00248 00249 $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time()); 00250 if ($rs) { 00251 if ($rs->EOF) { 00252 $v = ''; 00253 } else 00254 $v = rawurldecode(reset($rs->fields)); 00255 00256 $rs->Close(); 00257 00258 // new optimization adodb 2.1 00259 $ADODB_SESSION_CRC = strlen($v).crc32($v); 00260 00261 return $v; 00262 } 00263 00264 return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com 00265 } 00266 00267 /****************************************************************************************\ 00268 Write the serialized data to a database. 00269 00270 If the data has not been modified since adodb_sess_read(), we do not write. 00271 \****************************************************************************************/ 00272 function adodb_sess_write($key, $val) 00273 { 00274 global 00275 $ADODB_SESS_CONN, 00276 $ADODB_SESS_LIFE, 00277 $ADODB_SESSION_TBL, 00278 $ADODB_SESS_DEBUG, 00279 $ADODB_SESSION_CRC, 00280 $ADODB_SESSION_EXPIRE_NOTIFY; 00281 00282 $expiry = time() + $ADODB_SESS_LIFE; 00283 00284 // crc32 optimization since adodb 2.1 00285 // now we only update expiry date, thx to sebastian thom in adodb 2.32 00286 if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) { 00287 if ($ADODB_SESS_DEBUG) echo " 00288 -- Session: Only updating date - crc32 not changed</p>"; 00289 $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time(); 00290 $rs = $ADODB_SESS_CONN->Execute($qry); 00291 return true; 00292 } 00293 $val = rawurlencode($val); 00294 00295 $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val); 00296 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00297 $var = reset($ADODB_SESSION_EXPIRE_NOTIFY); 00298 global $$var; 00299 $arr['expireref'] = $$var; 00300 } 00301 $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 00302 'sesskey',$autoQuote = true); 00303 00304 if (!$rs) { 00305 ADOConnection::outp( ' 00306 -- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false); 00307 } else { 00308 // bug in access driver (could be odbc?) means that info is not commited 00309 // properly unless select statement executed in Win2000 00310 if ($ADODB_SESS_CONN->databaseType == 'access') 00311 $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00312 } 00313 return !empty($rs); 00314 } 00315 00316 function adodb_sess_destroy($key) 00317 { 00318 global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; 00319 00320 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00321 reset($ADODB_SESSION_EXPIRE_NOTIFY); 00322 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); 00323 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); 00324 $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00325 $ADODB_SESS_CONN->SetFetchMode($savem); 00326 if ($rs) { 00327 $ADODB_SESS_CONN->BeginTrans(); 00328 while (!$rs->EOF) { 00329 $ref = $rs->fields[0]; 00330 $key = $rs->fields[1]; 00331 $fn($ref,$key); 00332 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00333 $rs->MoveNext(); 00334 } 00335 $ADODB_SESS_CONN->CommitTrans(); 00336 } 00337 } else { 00338 $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; 00339 $rs = $ADODB_SESS_CONN->Execute($qry); 00340 } 00341 return $rs ? true : false; 00342 } 00343 00344 function adodb_sess_gc($maxlifetime) 00345 { 00346 global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; 00347 00348 if ($ADODB_SESSION_EXPIRE_NOTIFY) { 00349 reset($ADODB_SESSION_EXPIRE_NOTIFY); 00350 $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); 00351 $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); 00352 $t = time(); 00353 $rs =& $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t"); 00354 $ADODB_SESS_CONN->SetFetchMode($savem); 00355 if ($rs) { 00356 $ADODB_SESS_CONN->BeginTrans(); 00357 while (!$rs->EOF) { 00358 $ref = $rs->fields[0]; 00359 $key = $rs->fields[1]; 00360 $fn($ref,$key); 00361 $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); 00362 $rs->MoveNext(); 00363 } 00364 $rs->Close(); 00365 00366 $ADODB_SESS_CONN->CommitTrans(); 00367 00368 } 00369 } else { 00370 $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time(); 00371 $ADODB_SESS_CONN->Execute($qry); 00372 00373 if ($ADODB_SESS_DEBUG) ADOConnection::outp(" 00374 -- <b>Garbage Collection</b>: $qry</p>"); 00375 } 00376 // suggested by Cameron, "GaM3R" <gamr@outworld.cx> 00377 if (defined('ADODB_SESSION_OPTIMIZE')) { 00378 global $ADODB_SESSION_DRIVER; 00379 00380 switch( $ADODB_SESSION_DRIVER ) { 00381 case 'mysql': 00382 case 'mysqlt': 00383 $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL; 00384 break; 00385 case 'postgresql': 00386 case 'postgresql7': 00387 $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL; 00388 break; 00389 } 00390 if (!empty($opt_qry)) { 00391 $ADODB_SESS_CONN->Execute($opt_qry); 00392 } 00393 } 00394 if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL; 00395 else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL; 00396 00397 $rs =& $ADODB_SESS_CONN->SelectLimit($sql,1); 00398 if ($rs && !$rs->EOF) { 00399 00400 $dbts = reset($rs->fields); 00401 $rs->Close(); 00402 $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts); 00403 $t = time(); 00404 00405 if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) { 00406 00407 $msg = 00408 __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)"; 00409 error_log($msg); 00410 if ($ADODB_SESS_DEBUG) ADOConnection::outp(" 00411 -- $msg</p>"); 00412 } 00413 } 00414 00415 return true; 00416 } 00417 00418 session_module_name('user'); 00419 session_set_save_handler( 00420 "adodb_sess_open", 00421 "adodb_sess_close", 00422 "adodb_sess_read", 00423 "adodb_sess_write", 00424 "adodb_sess_destroy", 00425 "adodb_sess_gc"); 00426 } 00427 00428 /* TEST SCRIPT -- UNCOMMENT */ 00429 00430 if (0) { 00431 00432 session_start(); 00433 session_register('AVAR'); 00434 $_SESSION['AVAR'] += 1; 00435 ADOConnection::outp( " 00436 -- \$_SESSION['AVAR']={$_SESSION['AVAR']}</p>",false); 00437 } 00438 00439 ?>