0); if ($handle) fclose($handle); if ($tries == 0) { // failed to start session. if (FS_SESSION_DEBUG) echo "Failed to start session in $dir
"; return "Failed to start session in $dir
"; } $session = array(); $session['sid'] = $sid; $session['accessed'] = time(); global $FS_CONTEXT; $session['context'] = $FS_CONTEXT; $GLOBALS['FS_SESSION'] = $session; // store the session now, // to make sure its already available to sub-scripts that attempt to // access the session information before this script has terminated. return fs_store_session(); } else // need to load existing session. { // garbage collect first. $gc = fs_session_gc(); if (is_string($gc)) return $gc; $file = "$dir/session_$sid"; if (file_exists($file)) { $handle = @fopen($file,"r"); if ($handle != false) { $fresh = false; $str = @fgets($handle); fclose($handle); if ($str != false) { $session = unserialize($str); $accessed = isset($session['accessed'])? (int)$session['accessed'] : 0; $fresh = time() - $accessed < SESSION_TIMEOUT; if ($fresh) { $GLOBALS['FS_SESSION'] = $session; } } return $fresh; } else { if (FS_SESSION_DEBUG) echo "Error opening session file $file
"; return "Error opening session file $file"; } } else { if (FS_SESSION_DEBUG) echo "Session file not found : $file
"; return false; } } } /** * Stores a session object, called automatically when the script processing is complete. */ function fs_store_session() { if (isset($GLOBALS['FS_SESSION'])) { $session_initialized = fs_initialize_session_dir(true); if ($session_initialized !== true) return $session_initialized; global $FS_CONTEXT; $session = $GLOBALS['FS_SESSION']; $session['context'] = $FS_CONTEXT; $session['accessed'] = time(); $sid = $session['sid']; $dir = $GLOBALS['FS_TEMP_DIR']; $handle = @fopen("$dir/session_$sid","w+"); fputs($handle,serialize($session)); fclose($handle); } return true; } /** * Garbage collect stale session. * this is called automatically and perform its operation at most every GC_INTERVAL_SECONDS. */ function fs_session_gc() { $session_initialized = fs_initialize_session_dir(true); if ($session_initialized !== true) return $session_initialized; $last_gc = 0; $dir = $GLOBALS['FS_TEMP_DIR']; $fname = "$dir/last_gc"; if (file_exists($fname)) { $f = file($fname); if (isset($f[0]) && is_numeric($f[0])) $last_gc = (int)$f[0]; } if (time() - $last_gc > GC_INTERVAL_SECONDS) { //echo "running gc
"; $dh = opendir($dir); while (false !== ($filename = readdir($dh))) { if ($filename != 'last_gc' && $filename != '.' && $filename != '..') { $fn = "$dir/$filename"; if (strstr($filename,'session_') != $filename || @is_dir($fn)) { continue; } $rotten = false; $fd = @fopen($fn, "r"); if ($fd == false) { if (FS_SESSION_DEBUG) echo "Error opening $fn
"; // error opening the file, assume invalid and (try to) gc it. $rotten = true; } else { $str = fgets($fd); fclose($fd); if ($str == false) { // error reading the file, assume invalid and gc it. $rotten = true; } else { $session = @unserialize($str); if ($session != false) { $accessed = (int)$session['accessed']; //echo "elapsed " . (time() - $accessed) . "
"; $rotten = time() - $accessed >= SESSION_TIMEOUT; } else { if (FS_SESSION_DEBUG) echo "Error unserialzing $fn
"; // bad file. $rotten = true; } } } if ($rotten) { if (FS_SESSION_DEBUG) echo "Session GC: unlinking $filename
"; if(!@unlink($fn)) { if (FS_SESSION_DEBUG) echo "Error unlinking $fn
"; } } } } if (fs_is_writable_and_readable($fname)) { $fd = fopen($fname,"w+"); fputs($fd,time()); fclose($fd); } else { return "$fname is not writeable by PHP user"; } } } /** * WARNING: This is one tricky function from hell. * DO NOT TOUCH if you are not 100% sure you know what you are doing, many people have died to get this function to where it is today. */ function fs_initialize_session_dir($silent_test = false) { // only detect the temp dir once. if (isset($GLOBALS['FS_TEMP_DIR'])) return true; $help_url = "http://firestats.cc/wiki/ErrorInitializingSessionsDir"; $text = sprintf("

Error initializing sessions directory, read this for help


%%s"); // user may override the detection of temp dir with FS_TEMP_DIR if (defined("FS_TEMP_DIR")) { $temp_dir = FS_TEMP_DIR; } else { $temp_dir = sys_get_temp_dir(); } $home_temp_dir = dirname(dirname(__FILE__)); $home_temp_dir .= "/".SESSIONS_DIR; // if FS_TEMP_DIR is NOT defined // AND one the following coditions is true, then try to use sessions directory under firestats directory: // 1. home_temp exists // 2. can't detect temp directory // 3. php is running in safe mode // 4. temp is not writable. if(!defined("FS_TEMP_DIR") && (@is_dir($home_temp_dir) || ini_get('safe_mode') == 1 || $temp_dir === false || !fs_is_dir_writable_and_readable($temp_dir))) { // sessions dir not found? // we require that the user create the directory because // if we create it the user will not be able to delete it. if (!@is_dir($home_temp_dir)) { return fs_session_die($silent_test, sprintf($text,"Directory ,'$home_temp_dir' does not exist, please create it")); } $temp_dir = $home_temp_dir; } else // temp directory exists, normal flow. { // make sure the dir ends with / fs_fix_dir1($temp_dir); // if FS_TEMP_DIR is not defined, append fs_sessions to the temp dir. if (!defined("FS_TEMP_DIR")) { $temp_dir .= SESSIONS_DIR; if (!is_dir($temp_dir)) // sessions dir not found inside temp dir, attempt to create it. { if (!mkdir($temp_dir, 0700)) { return fs_session_die($silent_test, sprintf($text,"Failed to create '$temp_dir'")); } } } else { // just make sure the directory the user defined exists. if (!is_dir($temp_dir)) { return fs_session_die($silent_test, sprintf($text,"Directory ,'$temp_dir' does not exist")); } } } // make sure the dir ends with / fs_fix_dir1($temp_dir); if (!fs_is_dir_writable_and_readable($temp_dir)) { return fs_session_die($silent_test, sprintf($text,"Directory ,'$temp_dir' is not writable or readable by the PHP user")); } // unfortunatelly, not all systems has posix_getuid, also - this cause problems when safe_mode is turned on. // if we run on a system that does not have it, and also happens to // have multiple (system) users accessing firestats, we are screwed. if (CREATE_USER_DIR == true && function_exists("posix_getuid") && ini_get('safe_mode') != 1) { $temp_dir .= posix_getuid(); // make sure the dir ends with / fs_fix_dir1($temp_dir); } if (!@file_exists($temp_dir) && !mkdir($temp_dir, 0700)) { return fs_session_die($silent_test, sprintf($text,"Failed to create '$temp_dir'")); } $GLOBALS['FS_TEMP_DIR'] = $temp_dir; // create an index.html inside the sessions dir to prevent directory listing // if this failes it's not important because it means session files creation will also fail, so there is nothing to hide. if (!@file_exists($temp_dir."index.html")) { $handle = @fopen($temp_dir."index.html","w+"); if ($handle !== false) { @fputs($handle,"Move along, nothing to see here."); @fclose($handle); } } return true; } function fs_ensure_sys_get_temp_dir_available() { if ( !function_exists('sys_get_temp_dir') ) { // Based on http://www.phpit.net/ // article/creating-zip-tar-archives-dynamically-php/2/ function sys_get_temp_dir() { // Try to get from environment variable if ( !empty($_ENV['TMP']) ) { return realpath( $_ENV['TMP'] ); } else if ( !empty($_ENV['TMPDIR']) ) { return realpath( $_ENV['TMPDIR'] ); } else if ( !empty($_ENV['TEMP']) ) { return realpath( $_ENV['TEMP'] ); } // Detect by creating a temporary file else { // Try to use system's temporary directory // as random name shouldn't exist $temp_file = @tempnam( md5(uniqid(rand(), TRUE)), '' ); if ( $temp_file ) { $temp_dir = realpath( dirname($temp_file) ); if (!@unlink( $temp_file )) return FALSE; return $temp_dir; } else { return FALSE; } } } } } function fs_is_dir_writable_and_readable($dir) { fs_fix_dir1($dir); return fs_is_writable_and_readable($dir); } function fs_is_writable_and_readable($path) { //will work in despite of Windows ACLs bug //NOTE: use a trailing slash for folders!!! //see http://bugs.php.net/bug.php?id=27609 //see http://bugs.php.net/bug.php?id=30931 if ($path{strlen($path)-1}=='/') // recursively return a temporary file path return fs_is_writable_and_readable($path.uniqid(mt_rand()).'.tmp'); else if (@is_dir($path)) return fs_is_writable_and_readable($path.'/'.uniqid(mt_rand()).'.tmp'); // check tmp file for read/write capabilities $f = @fopen($path, 'w+'); if ($f === false) return false; $res = fputs($f,'test'); if ($res === false) { fclose($f); return false; } $data = file_get_contents($path); if ($data === false) { fclose($f); return false; } if ('test' !== $data) { fclose($f); return false; } fclose($f); @unlink($path); return true; } function fs_resume_existing_session() { $sid = null; if (isset($_REQUEST['sid']) && !empty($_REQUEST['sid'])) { $sid = $_REQUEST['sid']; } else if (isset($_POST['sid']) && !empty($_POST['sid'])) { $sid = $_POST['sid']; } else if (isset($_COOKIE['FS_SESSION_ID'])) { $sid = $_COOKIE['FS_SESSION_ID']; } else return "sid not specified"; $res = fs_session_start($sid); global $FS_SESSION; if (is_bool($res) && $res) { global $FS_CONTEXT; $FS_CONTEXT = $FS_SESSION['context']; return true; } else { if (is_string($res)) { return $res; } else { return "Session expired"; } } } function fs_session_die($silent_test, $msg) { if ($silent_test) return $msg; else die($msg); } function fs_fix_dir1(&$dir) { // make sure the dir ends with / $last = substr($dir, strlen($dir) - 1 ); if ($last != "/" && $last != '\\') $dir .= "/"; return $dir; } ?>