Location: PHPKode > projects > WikyBlog > include/tool/session.php
<?php
//$langA variable is not available for the majority of this file


defined('WikyBlog') or die("Not an entry point...");



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//			NEW
//
/*			Not using PHP's SESSION functions

			Benefits:
				-	Other users will be able to change a users SESSION information: keywords/tags for example

			Issues:
				-	register_shutdown_function() 
				
					it's called as part of the request allowing output to be sent to the 
					browser... problem being that the browser waits for the end of the response making it look like
					there's more information to come even if there isn't!
						Order of calling
						1)	SESSION	_OPEN
						2)			_READ
						3)			_WRITE
						4)			_CLOSE
						5)	register_shutdown_function 
						
						... so using register_shutdown_function() for session info wouldn't actually slow the response down!
					
					it's also called after user aborts and script timeouts! 
					Both cases in which the script was never given a chance to finish!
					
				-	$_SESSION works even without session_start()

			Normal Sessions
				- 	would be easier by changing ini setting "session.serialize_handler"
				
			
			//SESSION USERLEVELS
				5:	Site Admin... 		can only be set by the $GLOBALS['wbAdminUser'] account
				4:  Owner (strict)
				3:	Full privileges... 	can be given to any user for any account
				2:	Workgroup...		for even IP addresses, gives users the ability to edit pages that are flagged "restricted"
				1:	logged-in			
				0:	not-logged-in
				-1: Banned User...		Cannot make edits
				
				... see hasPrivilege()
				
*/



//do this here for install
global $wbCookieDomain;
wbSession::cookieDomain(); //init $wbCookieDomain
wbSession::siteCookie('g', '://'.$wbCookieDomain);


// //erase a few cookies just in case
// global $wbDirPrefix;
// $tempDomain = wbSession::generateDomain();
// $reset = array('remember'=>true,'wbsid2'=>true);
// foreach($_COOKIE as $name => $value){
// 	setcookie($name, $value, time()-2592000, $wbDirPrefix.'/', $tempDomain);
// }

//	For debugging the cookie/session issue
//	somehow, a cookie['g'] = true is still showing up?
//
// if( $_SERVER['REMOTE_ADDR'] == '97.119.198.50' ){
// 	message(showArray($_COOKIE));
// 	$headers = getallheaders();
// 	message(showArray($headers['Cookie']));
// }


class wbSession{
	
	function control(&$ownerName){
		global $sessionCheckSum, $pageOwnerCheckSum, $sessRemember, $page, $sessValues;
	
		$updateJS = false;
		
		/////	Important SESSION variables
			session_cache_limiter( 'private, must-revalidate' );
			$sessRemember = false;
			
		
		/////	control the flow of logging in and out
		
			$sessionAction = null;
			if( !empty( $_POST['session']) ){
				$sessionAction = $_POST['session'];
				
			}elseif( !empty($_GET['session'])){
				$sessionAction = $_GET['session'];
			}
		
			if( !empty($sessionAction) ){
				includeFile('tool/sessionActions.php');
				

				switch( wbStrtolower($sessionAction) ){
					
					case 'log out':
					case 'logout':
						sessLog::out();
					break;
					
					case 'register':
						includeFile('tool/sessionRegister.php');
						$regObject = new registerUser();
						$regObject->attempt();
					break;
					
					case 'confirm':
						includeFile('tool/sessionConfirm.php');
					break;
					
					
					case 'log in':
						unset($_GET['session']);
						sessLog::in(false);
						$updateJS = true;
					break;
			
				}
			}
		
			wbSession::start($ownerName);
			
		///		actions to do after $_SESSION && $pageOwner are set
			if( !empty( $sessionAction) ){
				switch( $sessionAction ){
					case 'register':
					case 'log in':
						sessLog::afterIn();
					break;
				}
			}
			
						
		////	flags
			if( empty($GLOBALS['pageOwner']) ){
				global $unknownName;
				$unknownName = $ownerName;
				$page->status = 'lost_page';
			}
			
		////	Salt Last Modified
			if( isset($_SESSION['modified']) ){
				$page->saltMod($_SESSION['modified']);
			}
			
			
		////	PageOwner Stuff
			if( !empty($GLOBALS['pageOwner']) ){
				$page->saltMod($GLOBALS['pageOwner']['modified']);
				
				//blogT	version 1.4.2
				//nBlog	version 1.6b1
				//$GLOBALS['pageOwner'] += array('blogT' => 'page', 'nBlog'=>'5', 'ihelp'=>'On');
				$GLOBALS['pageOwner'] += array('nBlog'=>'5', 'ihelp'=>'On'); //blogT removed for 1.7.1
				
				//1.6.1
				unset($GLOBALS['pageOwner']['fileUsage']);
				unset($GLOBALS['pageOwner']['disk_usage']);
			}
			
			
			
		////	Set UserPreferences
			if( isset($_GET['cmd']) && $_GET['cmd'] == 'setlang' ){
				if( !cookies() ){
					message('COOKIES_REQUIRED');
				}else{
					$_SERVER['HTTP_ACCEPT_LANGUAGE'] = $_GET['language'].';'.$_SERVER['HTTP_ACCEPT_LANGUAGE'];
					unset($_SESSION['lang']);
				}
			}

			if( !empty($_SESSION['lang']) && is_string($_SESSION['lang']) && strlen($_SESSION['lang']) == 2 ){
				$GLOBALS['userLanguage'] = $_SESSION['lang'];
				
			}else{
				$GLOBALS['userLanguage'] = wbData::detectLang(); //detect the users HTTP_ACCEPT_LANGUAGE
				$_SESSION['lang'] = $GLOBALS['userLanguage'];
			}
			
		////	Update Values
			if( function_exists('updateSessValues') ){
				updateSessValues();
			}
			
		////	Update Javascript .. this happens when a user logs in
			if( $updateJS && $page->ajaxRequest ){
				$addContent = new content();
				$addContent->aa = 'eval';
				$addContent->bb = '';
				if( isset($_SESSION['ajax']) ){
					$addContent->bb .= 'WB.ajax="'.$_SESSION['ajax'].'";';
				}
				if( isset($_SESSION['nTabs']) ){
					$addContent->bb .= 'WB.tabs='.$_SESSION['nTabs'].';';
				}
				if( isset($_SESSION['nWin']) ){
					$addContent->bb .= 'WB.win="'.$_SESSION['nWin'].'";';
				}
				if( isset($_SESSION['scrl']) ){
					if( $_SESSION['scrl'] == 'Off' ){
						$addContent->bb .= 'WBx.uDS();';
					}else{
						$addContent->bb .= 'WBx.iDS();';
					}
				}
				
				
				if( !empty($addContent->bb) ){
					$page->contentClasses[] = $addContent;
				}
			}

		
		//these session values need to be set for everyone
		//	ihelp	version 1.6
		$_SESSION += array('ihelp'=>'Off','nWin'=>'Off');
	}
	
	
	///////////////////////////////////////////////////////////////////////////////////
	//
	//			Session Starting
	//
	function start(&$ownerName){
		global $page ,$serverName2;
		
		////////	Set Vars
			if( !empty($_COOKIE['wbsid2']) ){
				$sid = wbDB::escape($_COOKIE['wbsid2']);
			}else{
				$sid = false;
			}
	
			$i = 0;
			$keywords = '';
			
			$ownerName = wbDB::escape(toStorage($ownerName));
			$result = wbSession::query($ownerName,$sid);
			$num = mysql_num_rows($result);
			
			while( $row = mysql_fetch_assoc($result) ){
				$i++;
				
				//owner is always done first IF IT WAS FOUND
				if( wbStrcasecmp($ownerName,$row['username']) ){
					$isOwnerRow = true;
					$keywords = $row['keyword_count'];
					wbSession::setPageOptions($row);
				}else{
					$isOwnerRow = false;
					
					////	USERLEVEL for Anonymous Users
					if( empty($row['username']) ){
						$remoteLevel = $row['userlevel'];
					}
				}
				
				////	$_SESSION
				if( !empty($sid) 
					&& ($row['sid'] === $sid) 
					&& wbSession::setSession($row,$isOwnerRow)
					){
						continue;	//if the session started, we don't need to check the other options
				}
				
				////	setPageOwner
				if( $isOwnerRow ){
					wbSession::setPageOwner($row);
				}
				
				
				// Searching for $sid didn't work, so get rid of $sid and start session for anonymous user
				// also if wbSession::set() didn't set $_SESSION
				if( ($i === $num) && empty($_SESSION) && !empty($sid) ){
					// just get rid of $_COOKIE['wbsid2'], since the sid was not found in the database
					// ownerArray should already be set
					wbSession::autoLogout();
					$sid = '';
					$result = wbSession::query($ownerName,$sid,false);
				}
			}
			
			
		////////	Reset keywords
		//		keywords need to be reset when a plugin has been removed that allows keywords. See PluginAdd.php
			if( $keywords == 'reset'){
				includeFile('maintenance/tags1.php');
				fixTags();
			}			
			
			
		////////	Normal Sessions	:: not logged in
			if( empty($_SESSION) ){
				wbSession::anonSession($remoteLevel);
			}
	}

	function anonSession($remoteLevel){
		session_start();
					
		//use the configuration setting if not already set
		if( !empty($GLOBALS['wbConfig']['ajax']) && empty($_SESSION['ajax']) ){
			$_SESSION['ajax'] = $GLOBALS['wbConfig']['ajax'];
		}
		
		$_SESSION['user_id'] = -1;
		if( empty($remoteLevel) ){
			$_SESSION['userlevel'] = 0;
		}else{
			$_SESSION['userlevel'] = (int)$remoteLevel;
		}		
	}
	
	// Set the $pageOwner global variable	
	function setPageOwner(&$ownerRow){
		global $pageOwnerCheckSum,$page;
		wbSession::regShutdown();
		
		$GLOBALS['pageOwner'] = unserialize($ownerRow['data']);
		$GLOBALS['pageOwner']['username'] = $ownerRow['username'];
		$GLOBALS['pageOwner']['user_id'] = $ownerRow['user_id'];
		$GLOBALS['pageOwner']['modified'] = $ownerRow['modified'];
		if( !empty($ownerRow['data2']) ){
			$GLOBALS['pageOwner']['data2'] = unserialize($ownerRow['data2']);
		}
			
		$pageOwnerCheckSum = wbSession::checkSum($GLOBALS['pageOwner']);
		
		//Any Changes to $pageOwner from here on out will be saved!
	}
	
	
	//
	//set page options based on the $pageOwner settings
	//
	function setPageOptions(&$ownerRow){
		global $page, $dbObject;
		
		//Limits .. these might need to be $page->max.. instead of $GLOBALS
		$GLOBALS['maxUserDiskUsage'] = $ownerRow['max_usage'];
		$GLOBALS['maxHistory'] = $ownerRow['max_history'];
		
		
		//$pageOwner flags
		$ownerFlags = $ownerRow['flags'];
		if( strpos($ownerFlags,'disabled') !== false ){
			includeFile('tool/SpecialContent.php');
			specialContent::message('disabled');
			$page->disabled = true;
		}
		if( strpos($ownerFlags,'nofollow') !== false ){
			$page->nofollow = true;
		}
		if( strpos($ownerFlags,'suspended') !== false){
			unset($GLOBALS['pageOwner']);
			$page->status = 'Suspended'; //results in special content "template:suspended"
		}
		if( strpos($ownerFlags,'pending') !== false ){
			$page->status = 'Pending';
		}
		
		//
		//Prevent usage of the restricted areas 
		//
		if( !empty($ownerRow['restricted']) ){
			$restricted = explode(',',$ownerRow['restricted']);
			if( in_array($page->effectiveSpace,$restricted) ){
				$page->status = 'restricted';
			}
		}

	}
	
	function autoLogout(){
		global $page;
		message('AUTO_LOGOUT');
		wbSession::siteCookie('wbsid2','',time()-2592000);
		$page->session = true; //send a new userMenu
	}
	
	
	// 	- will get one or two rows: one for pageOwner and one for user
	// 	- if it's the user, it tries to get the userlevel from workgroup
	//	- checks for admin userlevel in the "{$GLOBALS['wbAdminUser']}" workgroup for user
	function query(&$ownerName,&$sid,$getOwner=true){
		global $wbTables,$page;
		
		$remoteAddr = wbDB::escape($_SERVER["REMOTE_ADDR"]);
		
		
		//Query Variables
		$userJoin = "{$wbTables['users']} LEFT JOIN {$wbTables['workgroup']} on ( {$wbTables['users']}.username = {$wbTables['workgroup']}.`guest` )";
		$selectFromUsers = " {$wbTables['users']}.`username`, {$wbTables['users']}.`flags`,  {$wbTables['users']}.`user_id`, {$wbTables['users']}.`ip`, {$wbTables['users']}.`data`, {$wbTables['users']}.`sid`, `modified` , {$wbTables['users']}.`visited` as `visited`, `max_usage`, `max_history`  ";
		
		if( $page->sessionData2 ){
			$selectFromUsers .= ", {$wbTables['users']}.`data2` as `data2` ";
		}
		
		
		//pageOwner Query
		if( $getOwner ){
			//$row['userlevel'] will always be 4 for the $pageOwner['username'] unless it's admin (5)
			$queryA[0] = ' SELECT /* Session:PageOwner */ '.$selectFromUsers;
			$queryA[0] .= ', 4 as `userlevel` ';
			$queryA[0] .= ', '.$wbTables['users'].'.`keyword_count` ';
			$queryA[0] .= ', '.$wbTables['users'].'.`restricted` ';
			$queryA[0] .= ' FROM '.$wbTables['users'];
			$queryA[0] .= ' WHERE `username` = "'.$ownerName.'" LIMIT 1';
		}
		
		$selectFromUsers .= ', '.$wbTables['workgroup'].'.`userlevel` as `userlevel`, "" as `keyword_count`, "" as `restricted` ';
		
		//Logged in User
		if( !empty($sid) ){
			
			// .. other users
			$queryA[1] = 'SELECT /* Session:User1b */ '.$selectFromUsers;
			$queryA[1] .= ' FROM '.$userJoin.' AND '.$wbTables['workgroup'].'.`owner` = "'.$ownerName.'" AND '.$wbTables['workgroup'].'.`type` = "username" ';
			$queryA[1] .= ' WHERE `sid` = "'.$sid.'" AND `username` != "'.$ownerName.'" ';
			$queryA[1] .= ' LIMIT 1 OFFSET 0';
			
		//Non-Logged in User
		//	get the minimum user level specified for this IP
		//	treat `guest` as expression in SQL LIKE
		}else{
			
			$queryA[2] = 'SELECT /* Session:User2 */ null as `username`, null as `flags`, -1 as `user_id`, -1 as `ip`, null as `data`, null as `sid`, 0 as `modified`, 0 as `visited`, 0 as `max_usage`, 0 as `max_history` ';
			if( $page->sessionData2 ){
				$queryA[2] .= ', null as `data2` ';
			}
			$queryA[2] .= ',  MIN(`userlevel`) as `userlevel`, "" as `keyword_count`, "" as `restricted`  ';
			
			$queryA[2] .= ' FROM '.$wbTables['workgroup'];
			$queryA[2] .= ' WHERE ('.$wbTables['workgroup'].'.`owner` = "'.$ownerName.'") ';
			//$queryA[2] .= ' AND ('.$wbTables['workgroup'].'.`guest` = "'.$remoteAddr.'") ';
			$queryA[2] .= ' AND ("'.$remoteAddr.'" LIKE '.$wbTables['workgroup'].'.`guest`) ';
			$queryA[2] .= ' AND '.$wbTables['workgroup'].'.`type` = "ip" ';
			$queryA[2] .= ' LIMIT 1 OFFSET 0';
		}
	
		if( count($queryA) === 1){
			$query = current($queryA);
		}else{
			$query = '( '.implode(' ) UNION ( ',$queryA).' ) LIMIT 2';
		}
		
		return wbDB::runQuery($query);
	}
	
	
	
	function setSession(&$row,&$isPageOwner){
		global $sessionCheckSum, $sessRemember,$page,$packageVersion,$building;
		
		//check IP
		$checkIP = wbSession::IP($_SERVER['REMOTE_ADDR']);
		$ipLen = strlen($checkIP);
		if( $checkIP !== substr($row['ip'],0,$ipLen) ){
			return false;
		}
		
		//get data ready
		$visited = dbFromDate($row['visited'],'unix');
		$elapsedTime = time() - $visited;
		$elapsedTime = $elapsedTime/60; //minutes
		$sessionData = unserialize($row['data']);
		
		
		/// after 120 minutes: Logout if $_SESSION['remember'] doesn't match $_COOKIE['remember']
			if( $elapsedTime > 120 ){
				
				//don't start this session
				if( empty($sessionData['remember']) || empty($_COOKIE['remember']) || ($_COOKIE['remember'] !== $sessionData['remember']) ){
					$_POST['username'] = $sessionData['username']; //for the login form
					//includeFile('tool/sessionActions.php');
					//sessLog::out(false);
					// AUTO LOGOUT
					return false;
				}
				
				//reset cookie for good measure
				wbSession::cookie();
			}
			
		
			wbSession::regShutdown();
			
		/// Session Values and checksum
			$_SESSION = $sessionData;
			$_SESSION['username'] = $row['username'];
			$_SESSION['user_id'] = $row['user_id'];
			$_SESSION['modified'] = $row['modified'];
			if( !empty($row['data2']) ){
				$_SESSION['data2'] = unserialize($row['data2']);
			}
			$sessionCheckSum = wbSession::checkSum($_SESSION);
			
			
			//unset adminConfirmed
			if( isset($_SESSION['adminConfirmed']) ){
				$diff = mktime() - $_SESSION['adminConfirmed'];
				if( $diff > 3600 ){//one hour
					unset($_SESSION['adminConfirmed']);
					$_SESSION['updateNow'] = true;
				}
			}
			
			
		/// after 60 minutes w/out a change, update the database so the user isn't logged out
			if($elapsedTime>60 ){
				$_SESSION['updateNow'] = true; //this will just force the checksum to be different
			}
						
		///	Userlevel
			if( is_numeric($row['userlevel']) ){
				$_SESSION['userlevel'] = (int)$row['userlevel'];
				
			}else{
				$_SESSION['userlevel'] = 1;
			}
			
		///	Admin
			if( strpos(','.$row['flags'].',',',admin,') !== false){
				$_SESSION['admin'] = true;
				
			//}elseif( strcasecmp($_SESSION['username'],$GLOBALS['wbAdminUser']) === 0 ){ //should be able to get rid of this test after 1.7.1
			//	$_SESSION['admin'] = true;
				
			}else{
				unset($_SESSION['admin']);
			}

			$page->lastModSalts[] = 883638010;
			
		//If User is  the pageOwner
			if( $isPageOwner ){
				$GLOBALS['pageOwner'] =& $GLOBALS['_SESSION'];
				if( ($_SESSION['userlevel'] === 1) && ($_SESSION['userlevel'] !== 5) ){
					$_SESSION['userlevel'] = 4; //this is the ownerStrict value
				}
			}
			
		return true;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	//			
	//			save $_SESSION and $pageOwner values only when there have been changes
	//			They are done seperately because it is unlikely that both would change with the same request
	//				-	when keywords are changed, it's inevitable that the $pageOwner will change
	//
	
	function save(){
		global $pageOwner;
		global $sessionCheckSum,$pageOwnerCheckSum;
		
		/// flush output to user first...
		///		- xmlHTTP won't get the 200 response untill everything has been sent..
		/// flush() has no effect on the buffering scheme of your webserver or the browser on the client side. 
		/// Thus you need to call both ob_flush() and flush() to flush the output buffers. --http://dev/manuals/Php/function.flush.html
		//
		if( function_exists('ob_get_level') ){
			while( ob_get_level() > 0){
				ob_end_flush();
			}
			flush();
		}
		
		/// aborted or timed-out
			if(  connection_status() !== 0 ){
				return;
			}
		
		/// Session... only my SESSIONS!
			if( isset($_SESSION['username']) ){
				unset($_SESSION['userlevel']);
				if( $sessionCheckSum !== wbSession::checkSum($_SESSION) ){
					wbSession::save2($_SESSION,true);
				}
			}
		
		/// PageOwner
			//don't save twice
			if( isset($_SESSION['username']) && ($_SESSION['username'] == $pageOwner['username']) ){
				return;
			}
			//don't save for the error page
			if( empty($pageOwner['username']) || count($pageOwner) < 2 ){
				return;
			}
			
			if( !empty($pageOwnerCheckSum) ){
				if( $pageOwnerCheckSum !== wbSession::checkSum($pageOwner) ){
					wbSession::save2($pageOwner,false);
				}
			}
	}
	
	function save2(&$array,$session){
		global $wbTables,$wbNow;
		
		
		/// Update Modified/Visited?
			if( $session ){
				$update['modified'] = $wbNow;
				$update['visited'] = $wbNow;
				
			}else{
				//don't want to change the visited when it's $pageOwner
				$update['modified'] = $wbNow;
			}
		
		///	Clean-Up Session data not used anymore
			unset($array['revision']);
			unset($array['xmlSave']);
			
		/// Clean-Up data that doesn't need to be saved
			unset($array['sid']);
			unset($array['wbsid']);
			unset($array['wbsid2']);
			unset($array['updateNow']);
			unset($array['user_id']);
			unset($array['modified']);
	
			
		/// Orgnize Images
			if( isset($array['imgs']) && is_array($array['imgs']) ){
				ksort($array['imgs']);
			}
			
		///	Run Query
			if( isset($array['data2']) && !empty($array['data2']) ){
				$update['data2'] = serialize($array['data2']);
				unset($array['data2']);
			}
			
			if( empty($array['totalUsage']) ) {
				$array['totalUsage'] = 0;
			}
			$update['total_usage'] = $array['totalUsage']; //version 1.6.1
			$update['data'] = serialize($array);
			$where['username'] = $array['username'];
			$num = wbDB::dbUpdate2($wbTables['users'],$update,$where);
			
		if($num > 1){
			trigger_error('<b>Error:</b> Multiple accounts may have been affected: ');
			return false;
		}
	}	
	
	
	
	/////////////////////////////////////////////////////////////////////////////////////
	//
	// 			tools
	//
	function cookie(){
		global $sessRemember;
		
		//2592000 = 30 days
		//86400 = one day
		//3600 = one hour	
		//$exp = time()+2592000;
		
		
		wbSession::siteCookie('wbsid2',$_COOKIE['wbsid2']);
		if( $sessRemember ){
			wbSession::siteCookie('remember',$sessRemember);
		}
	}
	
	function siteCookie($name,$value, $expire = false){
		global $wbDirPrefix, $wbCookieDomain, $wbCookieDir;
		if( $expire === false ){
			$expire = time()+2592000;
		}
		
		setcookie($name,$value,$expire, $wbCookieDir.'/', $wbCookieDomain );
		
		//custom version
		// 
		// header('Set-Cookie: '.rawurlencode($name).'='.rawurlencode($value)
		// 		.'; Domain='.wbSession::cookieDomain()
		// 		.( $path ? '' : '; Path='.$path)
		// 		.'; expires='.$expire
		// 		//.(empty($maxage) ? '' : '; Max-Age='.$maxage) //maxage is not supported by enough browsers
		// 		.'; HttpOnly'
		// 		, false); 
		
	}
	
	function cookieDomain(){
		global $wbCookieDomain, $wbDirPrefix;
		
		//set cookieDomain
		if( !isset($wbCookieDomain) ){
			$wbCookieDomain = wbSession::generateDomain();
		}
		
		//check against $_COOKIE['g']
		if( !isset($_COOKIE['g']) ){
			return;
		}
		
		//version <1.7 $_COOKIE['g'] is not set with the $wbCookieDomain value
		if( ($_COOKIE['g'] == 'true') || ($_COOKIE['g'] == true) ){
			$prevDomain = wbSession::generateDomain(); //could have been the empty string?
		}else{
			$prevDomain = substr($_COOKIE['g'],3);
		}
		
		if( $prevDomain === $wbCookieDomain ){
			return;
		}
		
		//only reset these cookies
		$reset = array('remember'=>true,'wbsid2'=>true);
		
		//$wbCookieDomain has changed!
		foreach($_COOKIE as $name => $value){
			
			//expire for the old cookieDomain
			setcookie($name, $value, time()-2592000, $wbDirPrefix.'/', $prevDomain );
			
			//reset for new cookieDomain
			if( isset($reset[$name]) ){
				wbSession::siteCookie($name, $value);
			}
		}
	}
	
	
	function generateDomain(){
		$dom = $_SERVER['HTTP_HOST'];
		$pos = strpos($dom,':');
		if( $pos !== false){
			$dom = substr($dom,0,$pos);
		}
		
		$test = str_replace('.','',$dom);
		if( is_numeric($test) ){
			return '';
			//return $dom;
		}
		
		$parts = explode('.',$dom);
		if( count($parts) > 2 ){
			array_shift($parts); //just take off the first one
			
		}elseif( count($parts) < 2){ //not enough parts, just use defaults
			return '';
		}
		return  '.'.implode('.',$parts);
	}
	
	
	function IP($ip){
		global $wbConfig;
		if( isset($wbConfig['sesslevel']) && is_numeric($wbConfig['sesslevel']) ){
			$level =& $wbConfig['sesslevel'];
		}else{
			$level = 2;
		}
		$temp = explode('.',$ip);
		
		$i = 0;
		while( $level > $i){
			array_pop($temp);
			$i++;
		}
		
		$checkIP = array_shift($temp); //don't pad with zero's for first part
		foreach($temp as $num){
			$checkIP .= str_pad($num,3,'0',STR_PAD_LEFT); 
		}
		return $checkIP;
	}	
	
	function regShutdown(){
		static $done = false;
		if( $done ){
			return;
		}
		register_shutdown_function(array('wbSession','save'));
		$done = true;
	}
	
	//	Used to get an integer value from SESSION array
	//	to see if the SESSION array has changed
	function checkSum($array){
		
		return crc32(serialize($array) );
		
		// foreach($array as $key => $val){
		// 	if(is_array($val)){
		// 		$array[$key] = wbSession::checkSum($val);
		// 	}
		// }
		// return crc32(implode('.',$array));
	}	
}

//
//
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 			DisplayFunctions
//
//	

function getUserMenu($return = false,$watchWarn=false){ 
	global $langA, $wbConfig, $dbInfo, $pageOwner, $wbAdminUser;
	
	if( $return ){
		ob_start();
	}
		
	
	echo '<ul onmouseover="WB.CT(ckt);" onmouseout="if(WB.si)WB.HI(WB.si);">';
	if( isset( $_SESSION['username'] ) ){
		$root = '/'.$_SESSION['username'].'/';
		
		echo '<li>';
		echo wbLinks::user($_SESSION['username']);
		echo '</li>';
		
		$createNew = true;
		if( isset($wbConfig['allUsers']) && $wbConfig['allUsers'] == 'Off'){
			if( toStorage($GLOBALS['wbAdminUser'],true) !== toStorage($_SESSION['username'],true) ){
				if( toStorage($GLOBALS['wbConfig']['pUser'],true) !== toStorage($_SESSION['username'],true) ){
					$createNew = false;
				}				
			}
		}
		if( $createNew ){
			$temp = createNew();
			if( $temp ){
				echo '<li>';
				echo $temp;
				echo '</li>';
			}
		}
		
		echo '<li>';
		$label = $langA['watchlist'].' ';
		// if( $watchWarn ){
		// 	$label .= '<img src="'.wbLinks::getDir('/imgs/icons/bullet_error.gif').'"';
		// }else{
		// 	$label .= '<img src="'.wbLinks::getDir('/imgs/blank.gif').'"';
		// }
		// $label .= ' style="vertical-align:middle" alt="" height="16" width="16" />';
		
		echo wbLinks::special('WatchList',$label,'',$_SESSION['username']);
		echo '</li>';
		
		//echo '<li onmouseover="WB.SI(this)" onmouseout="WB.HI(this)">';
		echo '<li onmouseover="WB.SI(this)">';
		echo wbLinks::special('ControlPanel',$langA['control_panel'].' ...','',$_SESSION['username']);
			echo '<ul style="display:none">';
				getUserMenuPrefs();
				echo '<li>';
				echo '<img alt="" height="16" width="16" src="'.wbLinks::getDir('/imgs/blank.gif').'" style="vertical-align:middle" />&nbsp; ';
				//echo ' (' . wbLinks::special('JSPrefs','preferences',' rel="nofollow"') . ')';
				echo ' (' . wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs','preferences',' rel="nofollow"') . ')';
				echo '</li>';
			echo '</ul>';
		echo '</li>';
		
		if( isAdmin(false) ){
			echo '<li>';
			echo wbLinks::special('ControlPanel?a','administration','',$wbAdminUser);
			//echo wbLinks::admin('ControlPanel','administration','',$wbAdminUser);
			echo '</li>';
		}

		echo '<li>';
		//echo wbLinks::special('ControlPanel?session=logout','log_out','',$_SESSION['username']);
		echo wbLinks::special('ControlPanel?session=logout','log_out');
		echo '</li>';

	}else{
		if(empty($_POST['username']) ){
			$_POST['username'] = $langA['username'];
		}
		
		echo '<li>';
		echo wbLinks::special('ControlPanel','log_in');
		echo '</li>';
		echo '<li>';
		echo wbLinks::special('Register','register');
		echo '</li>';
		
		$langs = wbData::detectLang(false);
		foreach($langs as $language){
			if( $language == $_SESSION['lang']){
				continue;
			}
			$link = '?cmd=setlang&amp;language='.$language;
			echo '<li><a href="'.$link.'" >'.$langA['lang'][$language].'</a></li>';
		}
		//echo '<li onmouseover="WB.SI(this)" onmouseout="WB.HI(this)" class="scriptOnly">';
		echo '<li onmouseover="WB.SI(this)" class="scriptOnly">';
		//echo wbLinks::special('JSPrefs',$langA['preferences'].' ...',' rel="nofollow"');
		echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs',$langA['preferences'].' ...',' rel="nofollow"');
			echo '<ul style="display:none">';
			getUserMenuPrefs();
			echo '</ul>';
		echo '</li>';
	}
	
	echo '</ul>';
		
	if( $return ){
		return wb::get_clean();
	}
}
function getUserMenuPrefs(){
	global $langA, $pageOwner;
	
	
	//enhanced tabbed browsing
		echo '<li>';
		if( $_SESSION['ajax'] == 'Off' ){
			$label = '<img alt="'.$langA['off'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/delete.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['enhanced_tabs'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=ajax&v=On',$label,' rel="nofollow"');
		}else{
			$label = '<img alt="'.$langA['on'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/tick.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['enhanced_tabs'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=ajax&v=Off',$label,' rel="nofollow"');
		}
		echo '</li>';
	
	
	
	//enhanced scrolling
		echo '<li>';
		if( $_SESSION['scrl'] == 'Off' ){
			$label = '<img alt="'.$langA['off'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/delete.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['scrl'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=scrl&v=On',$label,' rel="nofollow"');
			
		}else{
			$label = '<img alt="'.$langA['on'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/tick.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['scrl'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=scrl&v=Off',$label,' rel="nofollow"');
		}
		echo '</li>';
	
	//external links in new window
		echo '<li>';
		if( $_SESSION['nWin'] == 'Off' ){
			$label = '<img alt="'.$langA['off'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/delete.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['nWin'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=nWin&v=On',$label,' rel="nofollow"');
			
		}else{
			$label = '<img alt="'.$langA['on'].'" height="16" width="16" src="'.wbLinks::getDir('/imgs/icons/tick.gif').'" style="vertical-align:middle" />&nbsp; '.$langA['nWin'];
			echo wbLinks::js('/Special/'.$pageOwner['username'].'/JSPrefs?cmd=js&k=nWin&v=Off',$label,' rel="nofollow"');
		}
		echo '</li>';	
}

function createNew($name='',$inputStyle=''){
	global $langA, $wbConfig, $dbInfo, $wbNow;
	
	$spaces = array();
	if( !isset($wbConfig['createNew']) ){
		return false;
	}
	foreach($wbConfig['createNew'] as $space => $value){
		if( !isset($dbInfo[$space]) ){
			continue; //for maps
		}
		if( ($value === 2) && !isAdmin(false) ){
			continue;
		}
		$spaces[] = $space;
	}
	if( count($spaces) < 1){
		return false;
	}
	
	if( empty($name) ){
		$name =& $_SESSION['username'];
	}
	
	//new
	$temp = toDisplay(dbFromDate($wbNow,$langA['NEW_PAGE_FORMAT']));
		
	$action = wbLinks::getUrl('/redir');
	$text = '<form onsubmit="return WB.RS(event)" action="'.$action.'" method="post" style="margin:0;padding:0;display:inline;" enctype="application/x-www-form-urlencoded">';
		$text .= '<input name="wbRedir" value="wbRedir" type="hidden" /> ';
		$text .= '<input type="text" name="x_" value="" size="5"  style="display:none" />';
		$text .= '<span>';
			$text .= '<a href="javascript:void(0)" onclick="WB.SI(this.parentNode);return false;" >'.$langA['create_new'].'</a>';
			$text .= '<br/>';
			$text .= '<input type="text" name="title" size="25" value="'.$temp.'" '.$inputStyle.' onclick="WB.SI(this.parentNode)" onfocus="WB.SI(this.parentNode)" onblur="WB.HI(this.parentNode)" />';
			$text .= '<br/>';
			$text .= '<span class="loadHide">';
				$text .= '<select name="root" '.$inputStyle.' size="'.count($spaces).'" onfocus="WB.SI(this.parentNode.parentNode)" onblur="WB.HI(this.parentNode.parentNode)">';
				$i = 0;
				foreach($spaces as $space ){
					$root = '/'.$space.'/'.$name.'/';
					if( $i === 0){
						$text .= '<option value="'.wbHtmlspecialchars($root).'" selected="selected">'.$langA[$space].'</option>';
					}else{
						$text .= '<option value="'.wbHtmlspecialchars($root).'">'.$langA[$space].'</option>';
					}
					$i++;
				}
				$text .= '</select>';
				$text .= '<br/>';
				$text .= '<input type="submit" name="null" value="'.$langA['go'].'" onfocus="WB.SI(this.parentNode.parentNode)" onblur="WB.HI(this.parentNode.parentNode)" /> ';
			$text .= '</span>';
		$text .= '</span>';
	$text .= '</form>';
	
	return $text;
}

Return current item: WikyBlog