<?php /*

 ocPortal
 Copyright (c) ocProducts, 2004-2012

 See text/EN/licence.txt for full licencing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/
/*EXTRA FUNCTIONS: memory_get_usage*/

/**
 * @license		http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright	ocProducts Ltd
 * @package		core
 */

/**
 * Standard code module initialisation function.
 */
function init__site()
{
	if (defined('BREADCRUMB_CROP_LENGTH')) return;
	
	global $HELPER_PANEL_TEXT,$HELPER_PANEL_HTML,$HELPER_PANEL_PIC,$HELPER_PANEL_TUTORIAL;
	$HELPER_PANEL_TEXT='';
	$HELPER_PANEL_HTML='';
	$HELPER_PANEL_PIC='';
	$HELPER_PANEL_TUTORIAL='';

	global $REQUEST_PAGE_NEST_LEVEL;
	$REQUEST_PAGE_NEST_LEVEL=0;

	global $REDIRECT_CACHE;
	$REDIRECT_CACHE=array();

	global $REDIRECTED_TO;
	$REDIRECTED_TO=NULL;

	global $REFRESH_URL,$FORCE_META_REFRESH,$EXTRA_HEAD,$EXTRA_FOOT,$QUICK_REDIRECT;
	$REFRESH_URL[0]='';
	$REFRESH_URL[1]=0;
	$FORCE_META_REFRESH=false;
	if (!isset($EXTRA_HEAD)) $EXTRA_HEAD=new ocp_tempcode();
	if (!isset($EXTRA_FOOT)) $EXTRA_FOOT=new ocp_tempcode();
	$QUICK_REDIRECT=false;

	global $FEED_URL,$FEED_URL_2;
	$FEED_URL=NULL;
	$FEED_URL_2=NULL;

	global $NON_CANONICAL_PARAMS;
	$NON_CANONICAL_PARAMS=array('active_filter','keep_has_js','keep_session','redirected','redirect_url','redirect','redirect_passon','keep_devtest','keep_su','wide_print','keep_cache','keep_markers','keep_print','keep_novalidate','keep_no_query_limit','keep_avoid_memory_limit','keep_no_swfupload','keep_no_xhtml','keep_no_minify','keep_no_frames','keep_su_online','keep_show_parse_errors','keep_firephp_queries','keep_firephp','keep_fatalistic','keep_currency','keep_country','keep_mobile','keep_textonly','keep_noiepng','keep_no_debug_mode','keep_referrer','keep_timezone');

	global $ATTACHED_MESSAGES,$ATTACHED_MESSAGES_RAW,$FAILED_TO_ATTACH_ALL_ERRORS;
	$ATTACHED_MESSAGES=new ocp_tempcode();
	$ATTACHED_MESSAGES_RAW=array();
	$FAILED_TO_ATTACH_ALL_ERRORS=false;

	global $DONE_HEADER;
	$DONE_HEADER=false;

	// We may fill these in from the code, or we may not
	global $SEO_KEYWORDS,$SEO_DESCRIPTION,$SEO_TITLE;
	$SEO_KEYWORDS=NULL;
	$SEO_DESCRIPTION=NULL;
	$SEO_TITLE=NULL;

	global $PAGE_STRING,$LAST_COMCODE_PARSED_TITLE;
	$PAGE_STRING=NULL;
	$LAST_COMCODE_PARSED_TITLE='';

	global $BREADCRUMBS,$BREADCRUMB_SET_PARENTS,$BREADCRUMB_EXTRA_SEGMENTS,$DISPLAYED_TITLE,$BREADCRUMB_SET_SELF;
	$BREADCRUMBS=NULL;
	$BREADCRUMB_SET_PARENTS=array();
	$BREADCRUMB_EXTRA_SEGMENTS=new ocp_tempcode();
	$DISPLAYED_TITLE=NULL;
	$BREADCRUMB_SET_SELF=NULL;
	$bcl=get_value('breadcrumb_crop_length');
	define('BREADCRUMB_CROP_LENGTH',is_null($bcl)?26:intval($bcl));

	global $PT_PAIR_CACHE_CP;
	$PT_PAIR_CACHE_CP=array();
	
	global $ATTACH_MESSAGE_CALLED;
	$ATTACH_MESSAGE_CALLED=0;

	global $ZONE,$RELATIVE_PATH;
	$zone=get_zone_name();
	$real_zone=(($RELATIVE_PATH=='_tests') || ($RELATIVE_PATH=='data') || ($RELATIVE_PATH=='data_custom'))?get_param('zone',''):$zone;
	$ZONE=persistant_cache_get(array('ZONE',$real_zone));

	if ($ZONE===NULL)
	{
		$zones=$GLOBALS['SITE_DB']->query_select('zones',array('*'),array('zone_name'=>$real_zone),'',1);
		if ((!array_key_exists(0,$zones)) && (is_dir(get_file_base().'/'.$real_zone.'/'.'pages')))
		{
			$GLOBALS['SITE_DB']->query_insert('zones',array('zone_name'=>$real_zone,'zone_title'=>insert_lang($real_zone,1),'zone_default_page'=>'start','zone_header_text'=>insert_lang($real_zone,1),'zone_theme'=>'default','zone_wide'=>0,'zone_require_session'=>0,'zone_displayed_in_menu'=>0));
			require_code('menus2');
			add_menu_item_simple('zone_menu',NULL,$real_zone,$real_zone.':',0,1);
			$zones=$GLOBALS['SITE_DB']->query_select('zones z LEFT JOIN '.$GLOBALS['SITE_DB']->get_table_prefix().'translate t ON '.db_string_equal_to('language',user_lang()).' AND z.zone_header_text=t.id',array('z.*','text_original AS zone_header_text_trans'),array('zone_name'=>$real_zone),'',1);
		}
		if (array_key_exists(0,$zones))
		{
			$ZONE=$zones[0];
			$ZONE['zone_header_text_trans']=get_translated_text($ZONE['zone_header_text']);
			persistant_cache_set(array('ZONE',$real_zone),$ZONE);
		}
		if ($ZONE===NULL)
		{
			$zones=$GLOBALS['SITE_DB']->query_select('zones',array('*'),array('zone_name'=>''),'',1);
			$ZONE=$zones[0];
			$ZONE['zone_header_text_trans']=get_translated_text($ZONE['zone_header_text']);
			warn_exit(do_lang_tempcode('BAD_ZONE',escape_html($real_zone)));
		}
		unset($zones);
	}
	if (($ZONE!==NULL) && ($ZONE['zone_wide']===NULL))
	{
		$ZONE['zone_wide']=(get_forum_type()=='ocf')?$GLOBALS['FORUM_DRIVER']->get_member_row_field(get_member(),'m_zone_wide'):1;
	}
	if (($ZONE['zone_name']=='adminzone') || ($ZONE['zone_name']=='cms'))
	{
		require_css('adminzone');
	}

	$_zone=get_zone_name();
	$REDIRECT_CACHE=array($_zone=>array());
	if (addon_installed('redirects_editor'))
	{
		$redirect=persistant_cache_get(array('REDIRECT',$_zone));
		if ($redirect===NULL)
		{
			$redirect=$GLOBALS['SITE_DB']->query_select('redirects',array('*')/*,array('r_from_zone'=>$_zone)*/);
			persistant_cache_set(array('REDIRECT',$_zone),$redirect);
		}
		foreach ($redirect as $r)
		{
			if (($r['r_from_zone']==$r['r_to_zone']) && ($r['r_from_page']==$r['r_to_page'])) continue;

			$REDIRECT_CACHE[$r['r_from_zone']][$r['r_from_page']]=$r;
		}
	}

	// SEO redirection
	require_code('urls');
	if (can_try_mod_rewrite())
	{
		$ruri=ocp_srv('REQUEST_URI');
		
		$old_style=get_option('htm_short_urls')!='1';

		if ((!headers_sent()) && (running_script('index')) && (isset($_SERVER['HTTP_HOST'])) && (count($_POST)==0) && ((strpos($ruri,'/pg/')===false) || (!$old_style)) && ((strpos($ruri,'.htm')===false) || ($old_style)))
		{
			$GLOBALS['HTTP_STATUS_CODE']='301';
			header('HTTP/1.0 301 Moved Permanently');
			header('Location: '.get_self_url(true));
			exit();
		}
	}
	
	// Search engine having session in URL, we don't like this
	if ((get_bot_type()!==NULL) && (isset($_SERVER['HTTP_HOST'])) && (count($_POST)==0) && (get_param_integer('keep_session',NULL)!==NULL))
	{
		$GLOBALS['HTTP_STATUS_CODE']='301';
		header('HTTP/1.0 301 Moved Permanently');
		header('Location: '.get_self_url(true,false,array('keep_session'=>NULL,'keep_print'=>NULL)));
		exit();
	}

	// Detect bad access domain
	global $SITE_INFO;
	$access_host=preg_replace('#:.*#','',ocp_srv('HTTP_HOST'));
	if (($access_host!='') && (isset($_SERVER['HTTP_HOST'])))
	{
		$parsed_base_url=parse_url(get_base_url());
		if ((array_key_exists('host',$parsed_base_url)) && (strtolower($parsed_base_url['host'])!=strtolower($access_host)))
		{
			if (!array_key_exists('ZONE_MAPPING_'.get_zone_name(),$SITE_INFO))
			{
				if ($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member()))
				{
					attach_message(do_lang_tempcode('BAD_ACCESS_DOMAIN',escape_html($parsed_base_url['host']),escape_html($access_host)),'warn');
				}

				header('Location: '.str_replace($access_host,$parsed_base_url['host'],get_self_url_easy()));
				exit();
			}
		}
	}

	// The most important security check
	global $SESSION_CONFIRMED;
	get_member(); // Make sure we've loaded our backdoor if installed
	if (($ZONE['zone_name']!='') && (!is_httpauth_login()) && ((get_session_id()==-1) || (is_guest()) || ($SESSION_CONFIRMED==0)) && (!is_guest()) && ($ZONE['zone_require_session']==1) && (get_page_name()!='login'))
	{
		access_denied((($real_zone=='data') || (has_zone_access(get_member(),$ZONE['zone_name'])))?'ZONE_ACCESS_SESSION':'ZONE_ACCESS',$ZONE['zone_name'],true);
	}
	else
	{
		if (($real_zone=='data') || (has_zone_access(get_member(),$ZONE['zone_name'])))
		{
			global $NON_PAGE_SCRIPT;
			if (($NON_PAGE_SCRIPT==0) && /*((get_page_name()!=$ZONE['zone_default_page']) || ($real_zone!='')) && */(!has_page_access(get_member(),get_page_name(),$ZONE['zone_name'],true)))
			{
				access_denied('PAGE_ACCESS');
			}
		}
		else
		{
	/*		if ($ZONE['zone_name']=='adminzone')	 GoogleAds will pick up on ANY URL any go and CRAWL IT. So don't use with googleads unless you want googlead-triggering-heart-attacks ;)
				log_hack_attack_and_exit('ADMINZONE_ACCESS_DENIED');*/

			if (get_page_name()!='login') access_denied('ZONE_ACCESS',$ZONE['zone_name'],true);
		}
	}
}

/**
 * Attach a message to the page output.
 *
 * @param  mixed			The type of special message
 * @param  ID_TEXT		The template to use
 * @set    inform warn
 * @return string			Blank string so it can be chained in the Tempcode compiler. You will rarely want to use this return value. It's kind of a failsafe.
 */
function attach_message($message,$type='inform')
{
	if ((error_reporting()==0) && ($type=='warn')) return ''; // Supressing errors

	global $DONE_HEADER,$ATTACH_MESSAGE_CALLED,$ATTACHED_MESSAGES,$ATTACHED_MESSAGES_RAW;

	foreach ($ATTACHED_MESSAGES_RAW as $last)
	{
		if (array(is_object($last[0])?$last[0]->evaluate():$last[0],$last[1])==array(is_object($message)?$message->evaluate():$message,$type)) return ''; // Already shown
	}

	$ATTACH_MESSAGE_CALLED++;
	if ($ATTACH_MESSAGE_CALLED>5)
	{
		critical_error('EMERGENCY',is_object($message)?$message->evaluate():$message);
	}
	
	if ($DONE_HEADER)
	{
		// Drastic measures
		global $FAILED_TO_ATTACH_ALL_ERRORS;
		if (!$FAILED_TO_ATTACH_ALL_ERRORS)
		{
			// Okay, start recording what will be shown on the bottom from this point
			$ATTACHED_MESSAGES=new ocp_tempcode();
			$ATTACHED_MESSAGES_RAW=array();
			$FAILED_TO_ATTACH_ALL_ERRORS=true;
		}
	}

	if (($type=='warn') && (strlen(is_object($message)?$message->evaluate():$message)<130))
	{
		require_code('failure');

		$webservice_result=get_webservice_result($message);
		if ($webservice_result!==NULL)
		{
			if ((is_object($message)) && ($message->pure_lang)) $message=$message->evaluate();
			elseif (is_object($message)) $message=escape_html($message->evaluate());
			else $message=escape_html($message);
			$message=do_template('CROP_TEXT_MOUSE_OVER',array(
				'TEXT_LARGE'=>$webservice_result,
				'TEXT_SMALL'=>protect_from_escaping($message),
			));
			$message=protect_from_escaping($message);
		}
	}
	
	if ((get_param_integer('keep_fatalistic',0)==1) && ($type=='warn')) fatal_exit($message);

	$ATTACHED_MESSAGES_RAW[]=array($message,$type);
	$message=do_template('ADDITIONAL',array('_GUID'=>'ec843c8619d21fbeeb512686ea300a17','TYPE'=>$type,'MESSAGE'=>is_string($message)?escape_html($message):$message));
	$ATTACHED_MESSAGES->attach($message);

	$ATTACH_MESSAGE_CALLED--;

	return '';
}

/**
 * Get the relative URL to the logo for the current zone.
 *
 * @param  ?ID_TEXT		The zone being operated within (NULL: auto-detect)
 * @return URLPATH		The relative URL to the logo for the current zone
 */
function get_logo_url($zone_name=NULL)
{
	if (!addon_installed('zone_logos'))
		return find_theme_image('logo/-logo');

	global $ZONE;
	if ($zone_name===NULL) $zone_name=$ZONE['zone_name'];

	$image=find_theme_image('logo/'.$zone_name.'-logo',true);
	if ($image=='') // Fallback to welcome zone logo
		$image=find_theme_image('logo/-logo');

	return $image;
}

/**
 * Get the tempcode for the breadcrumbs.
 *
 * @return tempcode		The breadcrumbs
 */
function breadcrumbs()
{
	global $BREADCRUMB_SET_PARENTS,$BREADCRUMBS,$BREADCRUMB_EXTRA_SEGMENTS;

	$show_top=((get_param_integer('wide_high',get_param_integer('keep_wide_high',0))!=1));
	if (!$show_top) return new ocp_tempcode();

	if ($BREADCRUMBS===NULL)
	{
		$BREADCRUMBS=breadcrumbs_get_default_stub($BREADCRUMB_EXTRA_SEGMENTS->is_empty());
	}
	$out=new ocp_tempcode();
	$out->attach($BREADCRUMBS);
	if (!$BREADCRUMB_EXTRA_SEGMENTS->is_empty())
	{
		if (!$out->is_empty()) $out->attach(do_template('BREADCRUMB_ESCAPED'));
		$out->attach($BREADCRUMB_EXTRA_SEGMENTS);
	}

	// Substitutions (deprecated hardcoding example)
	$segment_substitutions=array();
	$root=get_param('keep_catalogue_root_page',NULL);
	if ($root!==NULL)
	{
		$page_name=get_param('keep_catalogue_root_page_name');
		$target_url=build_url(array('page'=>$root),'_SEARCH');
		$breadcrumb_tpl=do_template('BREADCRUMB_ESCAPED');
		$from='\<a title="[^"]*" href="[^"]*/site/index.php\?page=catalogues&amp;type=misc[^"]*"\>Catalogues\</a\>'.$breadcrumb_tpl->evaluate();
		$to='<a title="'.do_lang('GO_BACKWARDS_TO',escape_html(strip_tags($page_name))).'" href="'.escape_html($target_url->evaluate()).'">'.escape_html($page_name).'</a>'.$breadcrumb_tpl->evaluate();
		$segment_substitutions[$from]=$to;
	}
	// Substitutions (XML)
	if ((addon_installed('breadcrumbs')) && (function_exists('xml_parser_create')))
	{
		$data=@file_get_contents(get_custom_file_base().'/data_custom/breadcrumbs.xml',FILE_TEXT);
		if (($data===false) && (get_custom_file_base()!=get_file_base()))
			$data=@file_get_contents(get_file_base().'/data_custom/breadcrumbs.xml',FILE_TEXT);
		if (trim($data)!='')
		{
			require_code('breadcrumbs');
			$segment_substitutions=array_merge($segment_substitutions,load_breadcrumb_substitutions($out->evaluate(),$data));
		}
	}

	if (count($segment_substitutions)!=0)
	{
		$_out=$out->evaluate();
		foreach ($segment_substitutions as $from=>$to)
		{
			$_out=preg_replace('~'.str_replace('~','\~',$from).'~Us',$to,$_out,1);
		}
		return make_string_tempcode($_out);
	}

	return $out;
}

/**
 * Get the tempcode for the default breadcrumbs stub. This isn't entirely a default, because it does work with breadcrumb_set_parents. We refer to it as a default as it is possible to override the whole breadcrumbs environment via the special BREADCRUMBS global variable.
 *
 * @param  boolean		Whether we'll be providing a link to where we are currently at
 * @return tempcode		The default breadcrumb stub
 */
function breadcrumbs_get_default_stub($link_to_self_entrypoint=true)
{
	global $BREADCRUMB_SET_PARENTS,$DISPLAYED_TITLE,$BREADCRUMB_SET_SELF;
	$stub=new ocp_tempcode();

	// Special hard-coded link to menu structure for Admin and CMS zones
	$zone=get_zone_name();
	if ((($zone=='adminzone') || ($zone=='cms')) && (get_option('deeper_admin_breadcrumbs')=='1'))
	{
		require_code('site_adminzone');
		adminzone_extend_breadcrumbs($stub);
	}

	// Specified parents
	foreach ($BREADCRUMB_SET_PARENTS as $bit)
	{
		list($entrypoint,$title)=$bit;
		$title=symbol_truncator(array(is_object($title)?$title:escape_html($title),BREADCRUMB_CROP_LENGTH,'1','1'),'spread');

		if (!$stub->is_empty()) $stub->attach(do_template('BREADCRUMB_ESCAPED'));
		if ($entrypoint==='')
		{
			$stub->attach($title);
		} else
		{
			if (is_object($entrypoint))
			{
				$url=$entrypoint;
			} else
			{
				list($zone,$attributes,)=page_link_decode($entrypoint);
				$url=build_url($attributes,$zone);
			}
			$stub->attach(hyperlink($url,$title,false,false,do_lang_tempcode('GO_BACKWARDS_TO',@html_entity_decode(strip_tags(is_object($title)?$title->evaluate():$title),ENT_QUOTES,get_charset()))));
		}
	}
	
	// Self-link
	if ($link_to_self_entrypoint)
	{
		if (!$stub->is_empty()) $stub->attach(do_template('BREADCRUMB_ESCAPED'));
		$title=($BREADCRUMB_SET_SELF===NULL)?$DISPLAYED_TITLE:$BREADCRUMB_SET_SELF;
		if ($title!==NULL)
		{
			$title=symbol_truncator(array(is_object($title)?$title:escape_html($title),(strlen(strip_tags($stub->evaluate()))<BREADCRUMB_CROP_LENGTH)?(BREADCRUMB_CROP_LENGTH*2):BREADCRUMB_CROP_LENGTH,'1','1'),'spread');
			if (((is_object($title)) && (!$title->is_empty())) || ((is_string($title)) && ($title!='')))
			{
				$stub->attach('<span>');
				$stub->attach($title);
				$stub->attach('</span>');
			}
		}
	}

	return $stub;
}

/**
 * Add a segment to the breadcrumbs (if this isn't used, a default will be used for the stub).
 *
 * @param  tempcode		The segment
 * @param  ?mixed			The title of the follower of the segment OR an array as for breadcrumb_set_parents (NULL: implicit in $segment)
 */
function breadcrumb_add_segment($segment,$final_title=NULL)
{
	global $BREADCRUMB_EXTRA_SEGMENTS;

	$BREADCRUMB_EXTRA_SEGMENTS->attach($segment);
	if ($final_title!==NULL)
	{
		if (is_array($final_title))
		{
			foreach ($final_title as $bit)
			{
				list($entrypoint,$title)=$bit;
				$title=symbol_truncator(array(is_object($title)?$title:escape_html($title),BREADCRUMB_CROP_LENGTH,'1','1'),'spread');

				$BREADCRUMB_EXTRA_SEGMENTS->attach(do_template('BREADCRUMB_ESCAPED'));

				if ($entrypoint==='')
				{
					$BREADCRUMB_EXTRA_SEGMENTS->attach($title);
				} else
				{
					if (is_object($entrypoint))
					{
						$url=$entrypoint;
					} else
					{
						list($zone,$attributes,)=page_link_decode($entrypoint);
						$url=build_url($attributes,$zone);
					}
					$BREADCRUMB_EXTRA_SEGMENTS->attach(hyperlink($url,$title,false,false,do_lang_tempcode('GO_BACKWARDS_TO',@html_entity_decode(strip_tags(is_object($title)?$title->evaluate():$title),ENT_QUOTES,get_charset()))));
				}
			}
		} else
		{
			$title=$final_title;
			$BREADCRUMB_EXTRA_SEGMENTS->attach(do_template('BREADCRUMB_ESCAPED'));
			$title=symbol_truncator(array(is_object($title)?$title:escape_html($title),BREADCRUMB_CROP_LENGTH,'1','1'),'spread');
			$BREADCRUMB_EXTRA_SEGMENTS->attach($title);
		}
	}
}

/**
 * Put a list of parents in for the breadcrumbs.
 *
 * @param  array			The list of parent entry points (pairs: entry point, title)
 */
function breadcrumb_set_parents($parents)
{
	global $BREADCRUMB_SET_PARENTS;
	$BREADCRUMB_SET_PARENTS=$parents;
}

/**
 * Set the current title.
 *
 * @param  tempcode		The title
 */
function breadcrumb_set_self($title)
{
	global $BREADCRUMB_SET_SELF;
	$BREADCRUMB_SET_SELF=$title;
}

/**
 * Get the tempcode for the header. You will not normally need to use this function, as this is called as part of the website engine.
 *
 * @param  boolean		Whether to skip showing the top (logo/zone-navigation/banner)
 * @return tempcode		The site header
 */
function do_header($skip_top=false)
{
	$version_number=ocp_version_full();
	global $ZONE,$DONE_HEADER;
	global $SEO_KEYWORDS,$SEO_DESCRIPTION,$SEO_TITLE,$DISPLAYED_TITLE;
	if ($ZONE===NULL)
	{
		warn_exit(do_lang_tempcode('ZONE_NOT_INSTALLED'));
	}

	$DONE_HEADER=true;

	$GLOBALS['META_DATA']+=array(
		'site_newestmember'=>get_value('ocf_newest_member_username'),
		'site_nummembers'=>strval($GLOBALS['FORUM_DRIVER']->get_members()),
		'site_bestmember'=>get_value('site_bestmember'),
		'forum_numtopics'=>strval($GLOBALS['FORUM_DRIVER']->get_topics()),
		'forum_numposts'=>strval($GLOBALS['FORUM_DRIVER']->get_num_forum_posts()),
	);

	// Lots of work to get the perfect header text
	if (($SEO_TITLE===NULL) || ($SEO_TITLE=='')) // Take from either zone header or page title
	{
		if (($DISPLAYED_TITLE!==NULL) && (strip_tags($DISPLAYED_TITLE->evaluate())!=''))
		{
			$header_text=protect_from_escaping(strip_tags($DISPLAYED_TITLE->evaluate()));
		} else
		{
			$header_text=make_string_tempcode($ZONE['zone_header_text_trans']);
		}
	} else // Take from SEO title
	{
		$comcodeless=strip_comcode($SEO_TITLE); // This is not HTML
		
		// Strip 'Welcome to' off if it's there
		/*$comcodeless=str_replace('&hellip;','...',$comcodeless);
		$comcodeless=str_replace('&middot;','-',$comcodeless);
		$comcodeless=str_replace('&ndash;','-',$comcodeless);
		$comcodeless=str_replace('&mdash;','-',$comcodeless);*/
		$_header_text=preg_replace('#'.str_replace('#','\#',preg_quote(do_lang('WELCOME_TO_STRIPPABLE').' '.get_site_name())).'([^-]+\s*-\s*)?#','',$comcodeless);
		// Strip site name off it it's there (it'll be put on in the templates, so we don't want it twice)
		$stub=get_site_name().' - ';
		if (substr($_header_text,strlen($stub))==$stub) $_header_text=substr($_header_text,strlen($stub));
		if ($_header_text==get_site_name()) $_header_text='';

		$header_text=make_string_tempcode($_header_text);
	}

	// Some meta details
	if (($SEO_DESCRIPTION===NULL) || ($SEO_DESCRIPTION==''))
	{
		if ((isset($GLOBALS['META_DATA']['description'])) && ($GLOBALS['META_DATA']['description']!=''))
		{
			$description=$GLOBALS['META_DATA']['description'];
		} else
		{
			$description=get_option('description');
		}
	} else
	{
		$description=$SEO_DESCRIPTION;
	}
	if ($description===NULL) $description=''; // Shouldn't happen
	$keywords=get_option('keywords');
	if ($SEO_KEYWORDS===NULL) $SEO_KEYWORDS=array();
	$keywords_array=array_merge($SEO_KEYWORDS,explode(',',$keywords));
	$keywords=implode(',',array_unique($keywords_array));

	// The logo area
	$logourl=get_logo_url();
	//$logomap=get_option('logo_map');
	//$logomap=preg_replace('#href="(.)"#e','\'href="\'.easy_build_url(\'\\1\').\'"\'',$logomap);
	$show_top=((get_param_integer('wide_high',get_param_integer('keep_wide_high',0))!=1) && (!$skip_top) && (!running_script('preview')) && (!running_script('iframe'))/* && (is_null(get_param('zone',NULL)))*/);

	// Is this refreshing?
	global $REFRESH_URL,$FORCE_META_REFRESH;
	if ((!running_script('upgrader')) && (get_option('force_meta_refresh')=='1')) $FORCE_META_REFRESH=true;
	if ((array_key_exists(0,$REFRESH_URL)) && ($REFRESH_URL[0]!='') && ($FORCE_META_REFRESH)) // The page itself has actually told it to refresh itself DISABLED FOR ACCESSIBILITY REASONS: Now headers do refreshing when it's crucial
	{
		if (!array_key_exists(1,$REFRESH_URL)) $REFRESH_URL[1]=1;
		$refresh=do_template('META_REFRESH_LINE',array('_GUID'=>'6ee20694dfa474f160481a3ab5331d87','URL'=>$REFRESH_URL[0],'TIME'=>integer_format($REFRESH_URL[1])));
	} else $refresh=new ocp_tempcode();

	// RSS
	if (addon_installed('syndication'))
	{
		if (get_option('is_on_rss',true)==='1')
		{
			if ($GLOBALS['FEED_URL']!==NULL)
				$refresh->attach(do_template('RSS_HEADER',array('FEED_URL'=>$GLOBALS['FEED_URL'])));
			if ($GLOBALS['FEED_URL_2']!==NULL)
				$refresh->attach(do_template('RSS_HEADER',array('FEED_URL'=>$GLOBALS['FEED_URL_2'],'TITLE'=>do_lang('COMMENTS'))));
			if (addon_installed('news'))
				$refresh->attach(do_template('RSS_HEADER',array('FEED_URL'=>find_script('backend').'?mode=news','TITLE'=>do_lang('NEWS'))));
		}
	}

	// Put it all together
	global $NON_CANONICAL_PARAMS;
	$non_canonical=array();
	foreach ($NON_CANONICAL_PARAMS as $n) $non_canonical[$n]=NULL;
	$map=array('_GUID'=>'c2625aa7d8f0d5347552f6099a302930','SHOW_TOP'=>$show_top,'LOGOURL'=>$logourl,/*'LOGOMAP'=>$logomap,*/'SELF_URL'=>get_self_url(false,false,$non_canonical),'HEADER_TEXT'=>$header_text,'CHARSET'=>get_charset(),'REGISTERED_OR_NOT'=>$version_number/*legacy*/,'VERSION_NUMBER'=>$version_number,'REFRESH'=>$refresh,'header_text'=>$header_text,'DESCRIPTION'=>$description,'KEYWORDS'=>$keywords);
	$map['EXTRA_HEAD']=$GLOBALS['EXTRA_HEAD'];

	$map['ZONE_HEADER_TEXT']=$ZONE['zone_header_text_trans'];

	return do_template('HEADER',$map);
}

/**
 * Get the tempcode for the footer. You will not normally need to use this function, as this is called as part of the website engine.
 *
 * @param  boolean		Whether we are forcibly handling a bail-out (an error occurred during output and our XHTML is likely corrupted)
 * @return tempcode		The site footer
 */
function do_footer($bail_out=false)
{
	$show_bottom=((get_param_integer('wide_high',get_param_integer('keep_wide_high',0))!=1) && (!running_script('preview')));

	$has_su=false;
	$staff_actions='';
	if (!is_guest())
	{
		// Admins can jump user
		$has_su=(get_option('ocp_show_su',true)=='1') && (has_specific_permission(get_member(),'assume_any_member'));

		// Different types of page type for staff (debug view, etc)
		if ((get_option('ocp_show_staff_page_actions',true)=='1') && (has_specific_permission(get_member(),'view_profiling_modes')) && (count($_POST)==0)) // We count POST because we don't want to allow double submits
		{
			require_code('site2');
			$staff_actions=get_staff_actions_list();
		}
	}

	$messages=new ocp_tempcode();
	global $FAILED_TO_ATTACH_ALL_ERRORS;
	if ($FAILED_TO_ATTACH_ALL_ERRORS)
	{
		global $ATTACHED_MESSAGES;
		$messages=$ATTACHED_MESSAGES;
	}

	return do_template('FOOTER',array('_GUID'=>'0b7aa662fed823988c9267677cd0b471','EXTRA_FOOT'=>$GLOBALS['EXTRA_FOOT'],'BAIL_OUT'=>$bail_out,'ERROR_MESSAGES_DURING_OUTPUT'=>$messages,'SHOW_BOTTOM'=>$show_bottom,'HAS_SU'=>$has_su,'STAFF_ACTIONS'=>$staff_actions));
}

/**
 * This is it - the start of rendering of a website page.
 * Take in all inputs, sends them to the correct functions to process, gathers up all the outputs, sticks them together and echoes them.
 */
function do_site()
{
	// More SEO redirection (monikers)
	// Does this URL arrangement support monikers?
	$url_id=get_param('id',NULL,true);
	if (($url_id!==NULL) && ((url_monikers_enabled())/* && (!is_numeric(str_replace(',','',$url_id)))*/))
	{
		$type=get_param('type','misc');
		$looking_for='_SEARCH:'.get_page_name().':'.$type.':_WILD';
		$hooks=find_all_hooks('systems','content_meta_aware');
		$ob_info=NULL;
		foreach (array_keys($hooks) as $hook)
		{
			require_code('hooks/systems/content_meta_aware/'.filter_naughty($hook));
			$ob=object_factory('Hook_content_meta_aware_'.$hook,true);
			if ($ob===NULL) continue;
			$ob_info=$ob->info();
			$ob_info['view_pagelink_pattern']=preg_replace('#:[^:]*$#',':_WILD',$ob_info['view_pagelink_pattern']);

			if (($ob_info['view_pagelink_pattern']==$looking_for) && ($ob_info['support_url_monikers']))
			{
				if (is_numeric($url_id)) // Lookup and redirect to moniker
				{
					$correct_moniker=find_id_moniker(array('page'=>get_page_name(),'type'=>get_param('type','misc'),'id'=>$url_id));
					if (($correct_moniker!==NULL) && ($correct_moniker!=$url_id) && (count($_POST)==0)) // test is very unlikely to fail. Will only fail if the title of the resource was numeric - in which case the moniker was chosen to be the ID (NOT the number in the title, as that would have created ambiguity).
					{
						header('HTTP/1.0 301 Moved Permanently');
						$_new_url=build_url(array('page'=>'_SELF','id'=>$correct_moniker),'_SELF',NULL,true);
						$new_url=$_new_url->evaluate();
						header('Location: '.$new_url);
						exit();
					}
				} else
				{
					// See if it is deprecated
					if (strpos(get_db_type(),'mysql')!==false)
					{
						$monikers=$GLOBALS['SITE_DB']->query_select('url_id_monikers USE INDEX (uim_moniker)',array('m_resource_id','m_deprecated'),array('m_resource_page'=>get_page_name(),'m_resource_type'=>get_param('type','misc'),'m_moniker'=>$url_id));
					} else
					{
						$monikers=$GLOBALS['SITE_DB']->query_select('url_id_monikers',array('m_resource_id','m_deprecated'),array('m_resource_page'=>get_page_name(),'m_resource_type'=>get_param('type','misc'),'m_moniker'=>$url_id));
					}
					if (!array_key_exists(0,$monikers)) // hmm, deleted?
					{
						warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
					}
					$deprecated=$monikers[0]['m_deprecated']==1;
					if (($deprecated) && (count($_POST)==0))
					{
						$correct_moniker=find_id_moniker(array('page'=>get_page_name(),'type'=>get_param('type','misc'),'id'=>$monikers[0]['m_resource_id']));
						header('HTTP/1.0 301 Moved Permanently');
						$_new_url=build_url(array('page'=>'_SELF','id'=>$correct_moniker),'_SELF',NULL,true);
						$new_url=$_new_url->evaluate();
						header('Location: '.$new_url);
						exit();
					} else // Map back 'id'
					{
						$_GET['id']=$monikers[0]['m_resource_id']; // We need to know the ID number rather than the moniker
					}
				}
				break;
			}
		}
	}

	// Any messages to output?
	if (get_param_integer('redirected',0)==1)
	{
		$messages=$GLOBALS['SITE_DB']->query_select('messages_to_render',array('r_message','r_type'),array('r_session_id'=>get_session_id(),),'ORDER BY r_time DESC');
		foreach ($messages as $message)
		{
			if ($GLOBALS['XSS_DETECT']) ocp_mark_as_escaped($message['r_message']);
			attach_message(protect_from_escaping($message['r_message']),$message['r_type']);
		}
		if (count($messages)!=0)
		{
			$GLOBALS['SITE_DB']->query('DELETE FROM '.$GLOBALS['SITE_DB']->get_table_prefix().'messages_to_render WHERE r_session_id='.strval((integer)get_session_id()).' OR r_time<'.strval(time()-60*60));
		}
	}

	$special_page_type=get_param('special_page_type','view');

	global $ZONE;
	$keep_markers=get_param_integer('keep_markers',0);
	$show_edit_links=get_param_integer('show_edit_links',0);
	global $KEEP_MARKERS,$SHOW_EDIT_LINKS;
	$KEEP_MARKERS=($keep_markers==1) || ($special_page_type=='show_markers');
	if (($KEEP_MARKERS) && (!headers_sent())) header('Content-type: text/html; charset='.get_charset());
	$SHOW_EDIT_LINKS=($show_edit_links==1) || ($special_page_type=='show_edit_links');
	$out_evaluated=NULL;

	if (($special_page_type!='view') && ($special_page_type!='show_markers'))
	{
		require_code('view_modes');
		initialise_special_page_types($special_page_type);
	}

	// Set up Xdebug profiling
	if ($special_page_type=='profile')
	{
		if (function_exists('xdebug_start_profiling')) xdebug_start_profiling(); // xdebug 1 style
		if (ini_get('xdebug.profiler_enable')!='1') attach_message(escape_html('Profiling must be enabled in php.ini'),'warn'); // xdebug 2 style

		if (!is_writable_wrap(ini_get('xdebug.profiler_output_dir')))
		{
			attach_message(escape_html('xdebug.profiler_output_dir needs setting to a writable directory'),'warn');
		}
	}

	// Allow the site to be closed
	$site_closed=get_option('site_closed');
	if (($site_closed=='1') && (!has_specific_permission(get_member(),'access_closed_site')) && (!$GLOBALS['IS_ACTUALLY_ADMIN']))
	{
		require_code('site2');
		closed_site();
	}
	
	// Work out which page we're viewing
	global $PAGE;
	$PAGE=get_page_name();

	$doing_special_page_type=($special_page_type!='view') && ($special_page_type!='show_markers') && ($special_page_type!='show_edit_links') && ($special_page_type!='memory') && ((has_specific_permission(get_member(),'view_profiling_modes')) || ($GLOBALS['IS_ACTUALLY_ADMIN']));

	// Load up our frames into strings. Note that the header and the footer are fixed already.
	$middle=request_page($PAGE,true);
	global $CYCLES; $CYCLES=array(); // Here we reset some Tempcode environmental stuff, because template compilation or preprocessing may have dirtied things
	if (($middle===NULL) || ($middle->is_definitely_empty()))
	{
		$GLOBALS['HTTP_STATUS_CODE']='404';
		if ((!browser_matches('ie')) && (strpos(ocp_srv('SERVER_SOFTWARE'),'IIS')===false)) header('HTTP/1.0 404 Not Found');

		$title=get_page_title('ERROR_OCCURRED');
		$text=do_lang_tempcode('NO_PAGE_OUTPUT');
		$middle=warn_screen($title,$text,false);
	}

	// Extra stuff we can tag on (like messages)
	$additional=new ocp_tempcode();
	$site_closed=get_option('site_closed'); // May have been JUST changed in page load - think Setup Wizard
	if (($site_closed=='1') && ($PAGE!='login') && ($PAGE!='join') && (get_param_integer('wide_high',0)==0))
	{
		$additional->attach(do_template('ADDITIONAL',array('_GUID'=>'03a41a91606b3ad05330e7d6f3e741c1','TYPE'=>'notice','MESSAGE'=>do_lang_tempcode(has_specific_permission(get_member(),'access_closed_site')?'SITE_SPECIAL_ACCESS':'SITE_SPECIAL_ACCESS_SU'))));
	}
	if ($GLOBALS['IS_ACTUALLY_ADMIN'])
	{
		$unsu_link=get_self_url(true,true,array('keep_su'=>NULL));
		$su_username=$GLOBALS['FORUM_DRIVER']->get_username(get_member());
		$additional->attach(do_template('ADDITIONAL',array('_GUID'=>'13a41a91606b3ad05330e7d6f3e741c1','TYPE'=>'notice','MESSAGE'=>do_lang_tempcode('USING_SU',escape_html($unsu_link),escape_html($su_username)))));
	}

	$out=new ocp_tempcode(); // This is important - it makes sure the tempcode tree appears nicely

	$middle->handle_symbol_preprocessing(); // Due to the '->evaluate()' below, plus so that some symbol preprocessing can be passed into header

	$out->attach(do_header());
	if ((function_exists('memory_get_usage')) && (get_param('special_page_type','')=='memory'))
	{
		$additional->attach(do_template('ADDITIONAL',array('_GUID'=>'d605c0d111742a8cd2d4ef270a1e5fe1','TYPE'=>'inform','MESSAGE'=>do_lang_tempcode('MEMORY_USAGE',float_format(round(floatval(memory_get_usage())/1024.0/1024.0,2))))));
	}

	// Whack it into our global template
	global $ATTACHED_MESSAGES;
	$global_template='GLOBAL';
	if (get_option('show_docs')=='0') $GLOBALS['HELPER_PANEL_TUTORIAL']='';
	$helper_panel_pic=$GLOBALS['HELPER_PANEL_PIC'];
	if ($helper_panel_pic!='')
		if (find_theme_image($helper_panel_pic,true)=='') $helper_panel_pic='';
	$global=do_template($global_template,array('HELPER_PANEL_TUTORIAL'=>$GLOBALS['HELPER_PANEL_TUTORIAL'],'HELPER_PANEL_HTML'=>$GLOBALS['HELPER_PANEL_HTML'],'HELPER_PANEL_TEXT'=>$GLOBALS['HELPER_PANEL_TEXT'],'HELPER_PANEL_PIC'=>$helper_panel_pic,'MIDDLE'=>$doing_special_page_type?$middle:$middle->evaluate()/*FUDGEFUDGE*/,'MESSAGE_TOP'=>$ATTACHED_MESSAGES,'MESSAGE'=>$additional,'BREADCRUMBS'=>breadcrumbs()));
	unset($middle);
	$out->attach($global);
	$out->attach(do_footer());
	$out->handle_symbol_preprocessing();
	if (get_value('xhtml_strict')==='1')
	{
		$out=make_xhtml_strict($out);
	}

	// Validation
	$novalidate=get_param_integer('keep_novalidate',get_param_integer('novalidate',0));
	$show_edit_links=get_param_integer('show_edit_links',0);
	if (((in_array(ocp_srv('HTTP_HOST'),array('localhost','test.ocportal.com'))) || ($GLOBALS['FORUM_DRIVER']->is_staff(get_member()))) && (($special_page_type=='code') || (($novalidate==0) && (get_option('validation')=='1'))) && ($GLOBALS['REFRESH_URL'][0]=='') && ($show_edit_links==0)) // Not a permission - a matter of performance
	{
		require_code('view_modes');
		$out_evaluated=$out->evaluate(NULL,false);
		do_xhtml_validation($out_evaluated,($special_page_type=='code' && (get_param_integer('preview_mode',NULL)===NULL)),get_param_integer('preview_mode',0));
	}

	// Cacheing for spiders
	if ((running_script('index')) && (count($_POST)==0) && (isset($GLOBALS['SITE_INFO']['fast_spider_cache'])) && ($GLOBALS['SITE_INFO']['fast_spider_cache']=='1') && (is_guest()))
	{
		$bot_type=get_bot_type();
		if ((($bot_type!==NULL) || ((isset($GLOBALS['SITE_INFO']['any_guest_cached_too'])) && ($GLOBALS['SITE_INFO']['any_guest_cached_too']=='1'))) && (can_fast_spider_cache()))
		{
			$fast_cache_path=get_custom_file_base().'/persistant_cache/'.md5(serialize(get_self_url_easy()));
			if ($bot_type===NULL) $fast_cache_path.='__non-bot';
			if (!array_key_exists('js_on',$_COOKIE)) $fast_cache_path.='__no-js';
			$fast_cache_path.='.gcd';

			if (!is_dir(get_custom_file_base().'/persistant_cache/'))
			{
				if (@mkdir(get_custom_file_base().'/persistant_cache/',0777))
				{
					fix_permissions(get_custom_file_base().'/persistant_cache/',0777);
					sync_file(get_custom_file_base().'/persistant_cache/');
				} else
				{
					intelligent_write_error($fast_cache_path);
				}
			}

			$out_evaluated=$out->evaluate(NULL,false);

			$myfile=@fopen($fast_cache_path,'wb') OR intelligent_write_error($fast_cache_path);
			if (function_exists('gzencode'))
			{
				fwrite($myfile,gzencode($out_evaluated,9));
			} else
			{
				fwrite($myfile,$out_evaluated);
			}
			fclose($myfile);
			fix_permissions($fast_cache_path);
			sync_file($fast_cache_path);
		}
	}

	if ($doing_special_page_type)
	{
		special_page_types($special_page_type,$out,$out_evaluated);
	}

	// We calculated the time before outputting so that latency and bandwidth do not adversely affect the result
	global $PAGE_START_TIME,$PAGE_STRING;
	$page_generation_time=microtime_diff($PAGE_START_TIME,microtime(false));

	if (!$GLOBALS['QUICK_REDIRECT'])
	{
		if ($out_evaluated!==NULL)
		{
			echo $out_evaluated;
		} else
		{
			$GLOBALS['FINISHING_OUTPUT']=true;
			$out->evaluate_echo();
		}
	}

	// Finally, stats
	if ($PAGE_STRING!==NULL) log_stats($PAGE_STRING,intval($page_generation_time));

	// When someone hits the Admin Zone front page.
	if (($ZONE['zone_name']=='adminzone') && (get_page_name()=='start'))
	{
		// Security feature admins can turn on
		require_code('notifications');
		$current_username=$GLOBALS['FORUM_DRIVER']->get_username(get_member());
		$subject=do_lang('AFA_NOTIFICATION_MAIL_SUBJECT',get_site_name(),$current_username);
		$mail=do_lang('AFA_NOTIFICATION_MAIL',comcode_escape(get_site_name()),comcode_escape($current_username));
		dispatch_notification('adminzone_frontpage_accessed',NULL,$subject,$mail);

		// Track very basic details of what sites use ocPortal. You can remove if you like.
		if (preg_match('#^localhost[\.\:$]?#',ocp_srv('HTTP_HOST'))==0)
		{
			global $EXPIRE,$KEY;
			$timeout_before=@ini_get('default_socket_timeout');
			@ini_set('default_socket_timeout','3');
			http_download_file('http://ocportal.com/user.php?url='.urlencode(get_base_url()).'&name='.urlencode(get_site_name()).'&registered=2&key='.(($KEY===NULL)?'':strval($KEY)).'&expire='.(($EXPIRE===NULL)?'':strval($EXPIRE)).'&version='.urlencode(ocp_version_full()),NULL,false);
			@ini_set('default_socket_timeout',$timeout_before);
		}
	}

	// Little disk space check
	$last_space_check=get_value('last_space_check');
	if (($last_space_check===NULL) || (intval($last_space_check)<time()-60*60*3))
	{
		set_value('last_space_check',strval(time()));

		$low_space_check=intval(get_option('low_space_check'))*1024*1024;
		$disk_space=@disk_free_space(get_file_base());
		if ((is_integer($disk_space)) && ($disk_space<$low_space_check))
		{
			require_code('notifications');
			$subject=do_lang('LOW_DISK_SPACE_SUBJECT',NULL,NULL,NULL,get_site_default_lang());
			$message=do_lang('LOW_DISK_SPACE_MAIL',strval(intval(round($disk_space/1024/1024))),NULL,get_site_default_lang());
			dispatch_notification('low_disk_space',NULL,$subject,$message,NULL,A_FROM_SYSTEM_PRIVILEGED);
		}
	}

	//exit();
}

/**
 * Take the specified parameters, and try to find the corresponding page, then execute a function to load the page (load_html_page/load_comcode_page).
 *
 * @param  ID_TEXT		The codename of the page to load
 * @param  boolean		Whether it is required for this page to exist (shows an error if it doesn't) -- otherwise, it will just return NULL
 * @param  ?ID_TEXT		The zone the page is being loaded in (NULL: as shown by access URL)
 * @param  ?ID_TEXT		The type of page - for if you know it (NULL: don't know it)
 * @param  boolean		Whether the page is being included from another
 * @param  boolean		Whether to not check for redirects (normally you would)
 * @return ?tempcode		The page (NULL: no page)
 */
function request_page($codename,$required,$zone=NULL,$page_type=NULL,$being_included=false,$no_redirect_check=false)
{
	global $SITE_INFO;

	if ($zone===NULL) $zone=get_zone_name();

	$details=persistant_cache_get(array('PAGE_INFO',$codename,$required,$zone));
	if (($details===NULL) || ($details===false))
	{
		$details=_request_page($codename,$zone,$page_type,NULL,$no_redirect_check);
		persistant_cache_set(array('PAGE_INFO',$codename,$required,$zone),$details);
	}

	global $REQUEST_PAGE_NEST_LEVEL;
	$REQUEST_PAGE_NEST_LEVEL++;
	if ($REQUEST_PAGE_NEST_LEVEL>50)
	{
		$REQUEST_PAGE_NEST_LEVEL=0;
		warn_exit(do_lang_tempcode('STOPPED_RECURSIVE_RESOURCE_INCLUDE'));
	}
//if (rand(0,10)==1) @exit('!'.$zone.':'.$codename.'!'.$REQUEST_PAGE_NEST_LEVEL.chr(10));
	// Run hooks, if any exist
	$hooks=find_all_hooks('systems','upon_page_load');
	foreach (array_keys($hooks) as $hook)
	{
		require_code('hooks/systems/upon_page_load/'.filter_naughty($hook));
		$ob=object_factory('upon_page_load'.filter_naughty($hook),true);
		if ($ob===NULL) continue;
		$ob->run($codename,$required,$zone,$page_type,$being_included,$details);
	}

	if ($details===false)
	{
		if ($required)
		{
			require_code('site2');
			$ret=page_not_found($codename,$zone);
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		}
		$REQUEST_PAGE_NEST_LEVEL--;
		return new ocp_tempcode();
	}

	switch ($details[0])
	{
		case 'MODULES_CUSTOM':
			$path=isset($details[3])?$details[3]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/modules_custom/'.$details[2].'.php',true);
			$ret=load_module_page($path,$details[2]);
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'MODULES':
			$path=isset($details[3])?$details[3]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/modules/'.$details[2].'.php',true);
			$ret=load_module_page($path,$details[2]);
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'COMCODE_CUSTOM':
			$path=isset($details[4])?$details[4]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/comcode_custom/'.$details[3].'/'.$details[2].'.txt',true);
			if (((isset($SITE_INFO['no_disk_sanity_checks'])) && ($SITE_INFO['no_disk_sanity_checks']=='1') && (get_custom_file_base()==get_file_base())) || (is_file(get_custom_file_base().'/'.$path)))
			{
				$ret=load_comcode_page($path,$details[1],$details[2],get_custom_file_base(),$being_included);
				$REQUEST_PAGE_NEST_LEVEL--;
				return $ret;
			}
			// else roll on, as probably been deleted since persistent cache was filled
		case 'COMCODE_CUSTOM_PURE':
			$path=isset($details[4])?$details[4]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/comcode_custom/'.$details[3].'/'.$details[2].'.txt',true);
			if (((isset($SITE_INFO['no_disk_sanity_checks'])) && ($SITE_INFO['no_disk_sanity_checks']=='1')) || (is_file(get_file_base().'/'.$path)))
			{
				$ret=load_comcode_page($path,$details[1],$details[2],get_file_base(),$being_included);
				$REQUEST_PAGE_NEST_LEVEL--;
				return $ret;
			}
			// else roll on, as probably been deleted since persistent cache was filled
		case 'COMCODE':
			$path=isset($details[4])?$details[4]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/comcode/'.$details[3].'/'.$details[2].'.txt',true);
			if (((isset($SITE_INFO['no_disk_sanity_checks'])) && ($SITE_INFO['no_disk_sanity_checks']=='1')) || (is_file(get_file_base().'/'.$path)))
			{
				$ret=load_comcode_page($path,$details[1],$details[2],NULL,$being_included);
				$REQUEST_PAGE_NEST_LEVEL--;
				return $ret;
			}
			// else roll on, as probably been deleted since persistent cache was filled
		case 'HTML_CUSTOM':
			require_code('site_html_pages');
			$path=isset($details[4])?$details[4]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/html_custom/'.$details[3].'/'.$details[2].'.htm',true);
			$ret=make_string_tempcode(load_html_page($path));
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'HTML':
			require_code('site_html_pages');
			$path=isset($details[4])?$details[4]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/html/'.$details[3].'/'.$details[2].'.htm',true);
			$ret=make_string_tempcode(load_html_page($path));
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'MINIMODULES_CUSTOM':
			$path=isset($details[3])?$details[3]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/minimodules_custom/'.$codename.'.php',true);
			$ret=load_minimodule_page($path);
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'MINIMODULES':
			$path=isset($details[3])?$details[3]:zone_black_magic_filterer($details[1].(($details[1]=='')?'':'/').'pages/minimodules/'.$codename.'.php',true);
			$ret=load_minimodule_page($path);
			$REQUEST_PAGE_NEST_LEVEL--;
			return $ret;
		case 'REDIRECT':
			$redirect=$details[1];
			if ($required)
			{
				global $REDIRECTED_TO;
				$REDIRECTED_TO=$redirect;
			}
			if (strpos($redirect['r_to_page'],':')!==false)
			{
				$bits=page_link_decode($redirect['r_to_zone'].':'.$redirect['r_to_page']);
			} else $bits=array($redirect['r_to_zone'],array('page'=>$redirect['r_to_page']));
			// Transparent redirection?
			if ($redirect['r_is_transparent']==1)
			{
				if (($being_included) && (!has_page_access(get_member(),$redirect['r_to_page'],$redirect['r_to_zone'],true)))
				{
					access_denied('PAGE_ACCESS');
				}

				foreach ($bits[1] as $key=>$val)
					if ($key!='page') $_GET[$key]=get_magic_quotes_gpc()?addslashes($val):$val;
				if (($redirect['r_to_page']!=$codename) || ($redirect['r_to_zone']!=$zone))
				{
					$ret=request_page($redirect['r_to_page'],$required,$redirect['r_to_zone'],NULL,$being_included,$redirect['r_is_transparent']==1);
					$REQUEST_PAGE_NEST_LEVEL--;
					return $ret;
				}
			} else
			{
				$title=get_page_title('REDIRECTING');
				$url=build_url($bits[1],$redirect['r_to_zone'],NULL,true);
				header('HTTP/1.1 301 Moved Permanently');
				$ret=redirect_screen($title,$url,do_lang_tempcode('REDIRECTED_LINK'),true);
				$REQUEST_PAGE_NEST_LEVEL--;
				return $ret;
			}
	}

	$REQUEST_PAGE_NEST_LEVEL--;
	return new ocp_tempcode(); // should never get here
}

/**
 * Take the specified parameters, and try to find the corresponding page
 *
 * @param  ID_TEXT			The codename of the page to load
 * @param  ID_TEXT			The zone the page is being loaded in
 * @param  ?ID_TEXT			The type of page - for if you know it (NULL: don't know it)
 * @param  ?LANGUAGE_NAME	Language name (NULL: users language)
 * @param  boolean			Whether to not check for redirects (normally you would)
 * @return ~array				A list of details (false: page not found)
 */
function _request_page($codename,$zone,$page_type=NULL,$lang=NULL,$no_redirect_check=false)
{
	if ($lang===NULL) $lang=user_lang();

	if ($codename=='login') // Special case
	{
		$login_zone=get_module_zone('login');
		$path=zone_black_magic_filterer($login_zone.(($login_zone=='')?'':'/').'pages/modules_custom/'.$codename.'.php',true);
		if (is_file(get_file_base().'/'.$path))
			return array('MODULES_CUSTOM',$login_zone,$codename,$path);
		$path=zone_black_magic_filterer($login_zone.(($login_zone=='')?'':'/').'pages/modules/'.$codename.'.php',true);
		if (is_file(get_file_base().'/'.$path))
			return array('MODULES',$login_zone,$codename,$path);
	}

	// Redirect
	if ((!$no_redirect_check) && (addon_installed('redirects_editor')))
	{
		global $REDIRECT_CACHE;
		if (array_key_exists($zone,$REDIRECT_CACHE))
		{
			$redirect=array_key_exists($codename,$REDIRECT_CACHE[$zone])?array($REDIRECT_CACHE[$zone][$codename]):array();
		} else
		{
			$redirect=$GLOBALS['SITE_DB']->query_select('redirects',array('*'),array('r_from_zone'=>$zone,'r_from_page'=>$codename),'',1);
		}
		if (array_key_exists(0,$redirect))
		{
			return array('REDIRECT',$redirect[0]);
		}
	}

	//If we know the page type
	if ($page_type!==NULL)
	{
		switch ($page_type)
		{
			case 'modules_custom':
				if (!in_safe_mode())
				{
					$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/modules_custom/'.$codename.'.php',true);
					if (is_file(get_file_base().'/'.$path))
						return array('MODULES_CUSTOM',$zone,$codename,$path);
				}
				break;
			case 'modules':
				$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/modules/'.$codename.'.php',true);
				if (is_file(get_file_base().'/'.$path))
					return array('MODULES',$zone,$codename,$path);
				break;
			case 'comcode_custom':
				if (!in_safe_mode())
				{
					if (get_param_integer('keep_theme_test',0)==1)
					{
						$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$GLOBALS['FORUM_DRIVER']->get_theme().'__'.$codename.'.txt',true);
						if (is_file(get_custom_file_base().'/'.$path))
						{
							return array('COMCODE_CUSTOM',$zone,$GLOBALS['FORUM_DRIVER']->get_theme().'__'.$codename,$lang,$path);
						}
					}

					$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$codename.'.txt',true);
					if (is_file(get_custom_file_base().'/'.$path))
						return array('COMCODE_CUSTOM',$zone,$codename,$lang,$path);
					if ($GLOBALS['CURRENT_SHARE_USER']!==NULL) // For multisite instals we also will search the root site's custom Comcode pages
					{
						$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$codename.'.txt',true);
						if (is_file(get_file_base().'/'.$path))
							return array('COMCODE_CUSTOM_PURE',$zone,$codename,$lang,$path);
					}
				}
				//break;
			case 'comcode':
				$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode/'.$lang.'/'.$codename.'.txt',true);
				if (is_file(get_file_base().'/'.$path))
					return array('COMCODE',$zone,$codename,$lang,$path);
				break;
			case 'html_custom':
				if (!in_safe_mode())
				{
					$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html_custom/'.$lang.'/'.$codename.'.htm',true);
					if (is_file(get_custom_file_base().'/'.$path))
						return array('HTML_CUSTOM',$zone,$codename,$lang,$path);
				}
				break;
			case 'html':
				$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html/'.$lang.'/'.$codename.'.htm',true);
				if (is_file(get_file_base().'/'.$path))
					return array('HTML',$zone,$codename,$lang,$path);
				break;
			case 'minimodules_custom':
				if (!in_safe_mode())
				{
					$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/minimodules_custom/'.$lang.'/'.$codename.'.php',true);
					if (is_file(get_file_base().'/'.$path))
						return array('MINIMODULES_CUSTOM',$zone,$codename,$path);
				}
				break;
			case 'minimodules':
				$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/minimodules/'.$lang.'/'.$codename.'.php',true);
				if (is_file(get_file_base().'/'.$path))
					return array('MINIMODULES',$zone,$codename,$path);
				break;
		}
		
		return false;
	}

	// We have a priority list to find our page
	if (!in_safe_mode())
	{
		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/modules_custom/'.$codename.'.php',true);
		if (is_file(get_file_base().'/'.$path))
			return array('MODULES_CUSTOM',$zone,$codename,$path);
	}
	$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/modules/'.$codename.'.php',true);
	if (is_file(get_file_base().'/'.$path))
		return array('MODULES',$zone,$codename,$path);
	if (!in_safe_mode())
	{
		if (get_param_integer('keep_theme_test',0)==1)
		{
			$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$GLOBALS['FORUM_DRIVER']->get_theme().'__'.$codename.'.txt',true);
			if (is_file(get_custom_file_base().'/'.$path))
			{
				return array('COMCODE_CUSTOM',$zone,$GLOBALS['FORUM_DRIVER']->get_theme().'__'.$codename,$lang,$path);
			}
		}

		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$codename.'.txt',true);
		if (is_file(get_custom_file_base().'/'.$path))
			return array('COMCODE_CUSTOM',$zone,$codename,$lang,$path);
		if ($GLOBALS['CURRENT_SHARE_USER']!==NULL) // For multisite instals we also will search the root site's custom Comcode pages
		{
			$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$lang.'/'.$codename.'.txt',true);
			if (is_file(get_file_base().'/'.$path))
				return array('COMCODE_CUSTOM_PURE',$zone,$codename,$lang,$path);
		}
	}
	$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode/'.$lang.'/'.$codename.'.txt',true);
	if (is_file(get_file_base().'/'.$path))
		return array('COMCODE',$zone,$codename,$lang,$path);
	if (!in_safe_mode())
	{
		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html_custom/'.$lang.'/'.$codename.'.htm',true);
		if (is_file(get_custom_file_base().'/'.$path))
			return array('HTML_CUSTOM',$zone,$codename,$lang,$path);
	}
	$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html/'.$lang.'/'.$codename.'.htm',true);
	if (is_file(get_file_base().'/'.$path))
		return array('HTML',$zone,$codename,$lang,$path);
	if (!in_safe_mode())
	{
		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/minimodules_custom/'.$codename.'.php',true);
		if (is_file(get_file_base().'/'.$path))
			return array('MINIMODULES_CUSTOM',$zone,$codename,$path);
	}
	$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/minimodules/'.$codename.'.php',true);
	if (is_file(get_file_base().'/'.$path))
		return array('MINIMODULES',$zone,$codename,$path);

	// As a last resort, consider it might not yet have been translated
	$fallback_lang=fallback_lang();
	$site_lang=get_site_default_lang();
	$langs_to_try=array();
	if ($lang!=$site_lang) $langs_to_try[]=$site_lang;
	if ($lang!=$fallback_lang) $langs_to_try[]=$fallback_lang;
	foreach ($langs_to_try as $fallback_lang)
	{
		if (!in_safe_mode())
		{
			$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$fallback_lang.'/'.$codename.'.txt',true);
			if (is_file(get_custom_file_base().'/'.$path))
				return array('COMCODE_CUSTOM',$zone,$codename,$fallback_lang,$path);
			if ($GLOBALS['CURRENT_SHARE_USER']!==NULL) // For multisite instals we also will search the root site's custom Comcode pages
			{
				$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode_custom/'.$fallback_lang.'/'.$codename.'.txt',true);
				if (is_file(get_file_base().'/'.$path))
					return array('COMCODE_CUSTOM_PURE',$zone,$codename,$fallback_lang,$path);
			}
		}
		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/comcode/'.$fallback_lang.'/'.$codename.'.txt',true);
		if (is_file(get_file_base().'/'.$path))
			return array('COMCODE',$zone,$codename,$fallback_lang,$path);
		if (!in_safe_mode())
		{
			$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html_custom/'.$fallback_lang.'/'.$codename.'.htm',true);
			if (is_file(get_custom_file_base().'/'.$path))
				return array('HTML_CUSTOM',$zone,$codename,$fallback_lang,$path);
		}
		$path=zone_black_magic_filterer($zone.(($zone=='')?'':'/').'pages/html/'.$fallback_lang.'/'.$codename.'.htm',true);
		if (is_file(get_file_base().'/'.$path))
			return array('HTML',$zone,$codename,$fallback_lang,$path);
	}

	return false;
}

/**
 * Get the parsed contents of a comcode page.
 *
 * @param  PATH			The relative (to ocPortal's base directory) path to the page (e.g. pages/comcode/EN/start.txt)
 * @param  ID_TEXT		The zone the page is being loaded from
 * @param  ID_TEXT		The codename of the page
 * @param  ?PATH			The file base to load from (NULL: standard)
 * @param  boolean		Whether the page is being included from another
 * @return tempcode		The page
 */
function load_comcode_page($string,$zone,$codename,$file_base=NULL,$being_included=false)
{
	if ($file_base===NULL) $file_base=get_file_base();

	if (!$being_included) $GLOBALS['TITLE_CALLED']=true;
	
	$is_panel=(substr($codename,0,6)=='panel_') || ((strpos($codename,'panel_')!==false) && (get_param_integer('keep_theme_test',0)==1));

	if ($zone=='' && $codename=='404')
	{
		global $EXTRA_HEAD;
		$EXTRA_HEAD->attach('<meta name="robots" content="noindex" />'); // XHTMLXHTML

		$GLOBALS['HTTP_STATUS_CODE']='404';
		if ((!browser_matches('ie')) && (strpos(ocp_srv('SERVER_SOFTWARE'),'IIS')===false)) header('HTTP/1.0 404 Not Found');
	}
	
	if ((($is_panel) || ($codename[0]=='_')) && (get_page_name()==$codename))
	{
		global $EXTRA_HEAD;
		$EXTRA_HEAD->attach('<meta name="robots" content="noindex" />'); // XHTMLXHTML
	}

	if ($zone=='adminzone')
	{
		require_code('site_adminzone');
		adminzone_special_cases($codename);
	}

	if ($codename=='sitemap')
	{
		$GLOBALS['FEED_URL']=find_script('backend').'?mode=comcode_pages&filter='.$zone;
	}

	global $PAGE_STRING,$COMCODE_PARSE_TITLE,$LAST_COMCODE_PARSED_TITLE;
	$COMCODE_PARSE_TITLE=NULL;
	if ($PAGE_STRING===NULL && !$being_included && !$is_panel) $PAGE_STRING=$string;

	$new_comcode_page_row=array(
		'the_zone'=>$zone,
		'the_page'=>$codename,
		'p_parent_page'=>'',
		'p_validated'=>1,
		'p_edit_date'=>NULL,
		'p_add_date'=>NULL,
		'p_submitter'=>NULL,
		'p_show_as_edit'=>0
	);

	if (((get_option('is_on_comcode_page_cache')=='1') || (get_param_integer('keep_cache',0)==1) || (get_param_integer('cache',0)==1)) && (get_param_integer('keep_cache',NULL)!==0) && (get_param_integer('cache',NULL)!==0) && (get_param_integer('keep_print',0)==0))
	{
		global $SITE_INFO;
		$support_smart_decaching=(!isset($SITE_INFO['disable_smart_decaching'])) || ($SITE_INFO['disable_smart_decaching']=='0');

		if (is_browser_decacheing())
		{
			$comcode_page=$GLOBALS['SITE_DB']->query_select('cached_comcode_pages',array('string_index','cc_page_title'),array('the_page'=>$codename,'the_zone'=>$zone,'the_theme'=>$GLOBALS['FORUM_DRIVER']->get_theme()),'',1,0,false,array());
			if (array_key_exists(0,$comcode_page))
			{
				if ($comcode_page[0]['string_index']!==NULL) delete_lang($comcode_page[0]['string_index']);
				$GLOBALS['SITE_DB']->query_delete('cached_comcode_pages',array('the_page'=>$codename,'the_zone'=>$zone));
			}
		}
		$theme=$GLOBALS['FORUM_DRIVER']->get_theme();
		if ($GLOBALS['MEM_CACHE']!==NULL)
		{
			if ($support_smart_decaching)
			{
				$mtime=filemtime($file_base.'/'.$string);
				if ($mtime>time()) $mtime=time(); // Timezone error, we have to assume that cache is ok rather than letting us get in a loop decacheing the file. It'll get fixed automatically in a few hours when the hours of the timezone difference passes.
				$pcache=persistant_cache_get(array('COMCODE_PAGE',$codename,$zone,$theme,user_lang()),$mtime);
			} else
			{
				$pcache=persistant_cache_get(array('COMCODE_PAGE',$codename,$zone,$theme,user_lang()));
			}
		} else $pcache=NULL;
		if ($pcache===NULL)
		{
			$comcode_page=$GLOBALS['SITE_DB']->query_select('cached_comcode_pages a LEFT JOIN '.$GLOBALS['SITE_DB']->get_table_prefix().'comcode_pages b ON (a.the_page=b.the_page AND a.the_zone=b.the_zone)',array('*'),array('a.the_page'=>$codename,'a.the_zone'=>$zone,'the_theme'=>$theme),'',1,NULL,false,array('string_index','cc_page_title'));
			if (array_key_exists(0,$comcode_page))
			{
				if ($support_smart_decaching)
				{
					$mtime=filemtime($file_base.'/'.$string);
					if ($mtime>time()) $mtime=time(); // Timezone error, we have to assume that cache is ok rather than letting us get in a loop decacheing the file. It'll get fixed automatically in a few hours when the hours of the timezone difference passes.
				}
				if ((!$support_smart_decaching) || ((($comcode_page[0]['p_edit_date']!==NULL) && ($comcode_page[0]['p_edit_date']>=$mtime)) || (($comcode_page[0]['p_edit_date']===NULL) && ($comcode_page[0]['p_add_date']!==NULL) && ($comcode_page[0]['p_add_date']>=$mtime)))) // Make sure it has not been edited since last edited or created
				{
					$comcode_page_row=$comcode_page[0];
					$db_set=get_translated_tempcode($comcode_page[0]['string_index'],NULL,user_lang(),true,true,true);
					unset($GLOBALS['RECORDED_LANG_STRINGS_CONTENT'][$comcode_page[0]['string_index']]);
				} else
				{
					$mtime=filemtime($file_base.'/'.$string);
					if ($mtime>time()) $mtime=time(); // Timezone error, we have to assume that cache is ok rather than letting us get in a loop decacheing the file. It'll get fixed automatically in a few hours when the hours of the timezone difference passes.
					$GLOBALS['SITE_DB']->query_update('comcode_pages',array('p_edit_date'=>$mtime),array('the_page'=>$codename,'the_zone'=>$zone),'',1);
					$GLOBALS['SITE_DB']->query_delete('cached_comcode_pages',array('the_zone'=>$zone,'the_page'=>$codename));
					delete_lang($comcode_page[0]['string_index']);

					$db_set=NULL;
					$comcode_page_row=NULL;
				}
			} else
			{
				$db_set=NULL;
				$comcode_page_row=NULL;
			}
			if ($db_set!==NULL)
			{
				$index=$comcode_page[0]['string_index'];
				$title_to_use=$comcode_page[0]['cc_page_title'];
				if ($title_to_use!==NULL)
				{
					$title_to_use=get_translated_text($title_to_use,NULL,NULL,true);
					if ($title_to_use===NULL) $title_to_use=$codename;
				}
				$html=$db_set;
			} else
			{
				$comcode_page=$GLOBALS['SITE_DB']->query_select('comcode_pages',array('*'),array('the_page'=>$codename,'the_zone'=>$zone),'',1);
				if (array_key_exists(0,$comcode_page)) $comcode_page_row=$comcode_page[0];

				require_code('site2');
				$new_comcode_page_row['p_add_date']=filectime($file_base.'/'.$string);
				list($html,$title_to_use,$comcode_page_row)=_load_comcode_page_not_cached($string,$zone,$codename,$file_base,$comcode_page_row,$new_comcode_page_row,$being_included);
			}

			persistant_cache_set(array('COMCODE_PAGE',$codename,$zone,$theme,user_lang()),array($html,$title_to_use,$comcode_page_row));
		} else
		{
			list($html,$title_to_use,$comcode_page_row)=$pcache;
		}
	} else
	{
		require_code('site2');
		$new_comcode_page_row['p_add_date']=filectime($file_base.'/'.$string);
		list($html,$comcode_page_row,$title_to_use)=_load_comcode_page_cache_off($string,$zone,$codename,$file_base,$new_comcode_page_row,$being_included);
	}
	$filtered_title_to_use=mixed();
	if ((!$is_panel) && (!$being_included))
	{
		if (($title_to_use!==NULL) && ($title_to_use!=''))
		{
			get_page_title($title_to_use,false); // Little hack - this gets shift encoded, but shift encoding can't survive a tempcode cache. This will force it to reshift. It'll also make sure DISPLAYED_TITLE gets set.
			$filtered_title_to_use=@html_entity_decode(strip_tags($title_to_use),ENT_QUOTES,get_charset());
		}
		seo_meta_load_for('comcode_page',$zone.':'.$codename,$filtered_title_to_use);
	}
	$LAST_COMCODE_PARSED_TITLE=$title_to_use;

	if (($html->is_definitely_empty()) && ($being_included)) return $html;

	if ((has_actual_page_access(get_member(),'cms_comcode_pages',NULL,NULL,(($comcode_page_row['p_submitter']==get_member()) && (!is_guest()))?'edit_own_highrange_content':'edit_highrange_content')))
	{
		$redirect=get_self_url(true,false,array('redirect'=>NULL,'redirected'=>NULL));
		if ((($codename=='panel_left') || ($codename=='panel_right')) && (has_js()) && (has_actual_page_access(get_member(),'admin_zones')))
		{
			$edit_url=build_url(array('page'=>'admin_zones','type'=>'_editor','id'=>get_zone_name(),'redirect'=>$redirect,'wide'=>1),get_module_zone('admin_zones'));
		} else
		{
			$edit_url=build_url(array('page'=>'cms_comcode_pages','type'=>'_ed','page_link'=>$zone.':'.$codename,/*'lang'=>user_lang(),*/'redirect'=>$redirect),get_module_zone('cms_comcode_pages'));
		}
		$add_child_url=(get_option('is_on_comcode_page_children')=='1')?build_url(array('page'=>'cms_comcode_pages','type'=>'_ed','parent_page'=>$codename,'page_link'=>$zone.':'/*,'lang'=>user_lang()*//*,'redirect'=>$redirect*/),get_module_zone('cms_comcode_pages')):new ocp_tempcode();
	} else
	{
		$edit_url=new ocp_tempcode();
		$add_child_url=new ocp_tempcode();
	}

	$warning_details=new ocp_tempcode();
	if (($comcode_page_row['p_validated']!==NULL) && ($comcode_page_row['p_validated']==0))
	{
		require_code('site2');
		$warning_details=get_page_warning_details($zone,$codename,$edit_url);
	}

	if ((!$is_panel) && ($title_to_use!==NULL) && (!$being_included))
	{
		global $PT_PAIR_CACHE_CP;
		$PT_PAIR_CACHE_CP[$codename]['cc_page_title']=($title_to_use===NULL)?do_lang_tempcode('NA_EM'):make_string_tempcode($title_to_use);
		$PT_PAIR_CACHE_CP[$codename]['p_parent_page']=$comcode_page_row['p_parent_page'];
		$comcode_breadcrumbs=comcode_breadcrumbs($codename,$zone,get_param('root',''),($comcode_page_row['p_parent_page']=='') || !has_specific_permission(get_member(),'open_virtual_roots'));
		breadcrumb_add_segment($comcode_breadcrumbs);

		$GLOBALS['META_DATA']+=array(
			'created'=>date('Y-m-d',$comcode_page_row['p_add_date']),
			'creator'=>(is_guest($comcode_page_row['p_submitter']))?'':$GLOBALS['FORUM_DRIVER']->get_username($comcode_page_row['p_submitter']),
			'publisher'=>'', // blank means same as creator
			'modified'=>($comcode_page_row['p_edit_date']===NULL)?'':date('Y-m-d',$comcode_page_row['p_edit_date']),
			'type'=>'Comcode page',
			'title'=>$title_to_use,
			'identifier'=>$zone.':'.$codename,
			'description'=>'',
		);
	}

	if (($html->is_definitely_empty()) && ($is_panel)) return $html;

	global $SCREEN_TEMPLATE_CALLED;
	$st=$SCREEN_TEMPLATE_CALLED;
	$ret=do_template('COMCODE_PAGE_SCREEN',array('_GUID'=>'0fc4fe4f27e54aaaa2b7e4848c02bacb','IS_PANEL'=>$is_panel,'BEING_INCLUDED'=>$being_included,'SUBMITTER'=>strval($comcode_page_row['p_submitter']),'TAGS'=>get_loaded_tags('comcode_pages'),'WARNING_DETAILS'=>$warning_details,'EDIT_DATE_RAW'=>($comcode_page_row['p_edit_date']===NULL)?'':strval($comcode_page_row['p_edit_date']),'SHOW_AS_EDIT'=>$comcode_page_row['p_show_as_edit']==1,'CONTENT'=>$html,'EDIT_URL'=>$edit_url,'ADD_CHILD_URL'=>$add_child_url,'NAME'=>$codename));
	if (($is_panel) || ($being_included))
	{
		$SCREEN_TEMPLATE_CALLED=$st;
	}
	return $ret;
}

/**
 * Get a UI element of a route from a known Comcode page back to the declared root of the tree.
 *
 * @param  ID_TEXT		The Comcode page name
 * @param  ID_TEXT		The Comcode page zone
 * @param  ID_TEXT		The virtual root
 * @param  boolean		Whether not to put a link at this point in the navigation tree (usually, because the viewer is already at it)
 * @param  integer		The number of jumps we have gone through so far (cuts out after 10 as a failsafe)
 * @return tempcode		The navigation element
 */
function comcode_breadcrumbs($the_page,$the_zone,$root='',$no_link_for_me_sir=true,$jumps=0)
{
	if ($jumps==10) return new ocp_tempcode();

	$map=array('page'=>$the_page);
	if ($jumps==0) $map['root']=$the_page;
	elseif ($root!='') $map['root']=$root;
	$url=build_url($map,$the_zone);

	if ($the_page=='') return new ocp_tempcode();
	if ($the_page==$root)
	{
		if ($no_link_for_me_sir) return new ocp_tempcode();
		$_title=$GLOBALS['SITE_DB']->query_value_null_ok('cached_comcode_pages','cc_page_title',array('the_page'=>$the_page,'the_zone'=>$the_zone));
		$title=NULL;
		if ($_title!==NULL) $title=get_translated_text($_title,NULL,NULL,true);
		if ($_title===NULL) $title=escape_html($the_page);
		return hyperlink($url,$title,false,false,do_lang_tempcode('GO_BACKWARDS_TO',@html_entity_decode(strip_tags($title),ENT_QUOTES,get_charset())),NULL,NULL,'up');
	}

	global $PT_PAIR_CACHE_CP;
	if (!array_key_exists($the_page,$PT_PAIR_CACHE_CP))
	{
		$page_rows=$GLOBALS['SITE_DB']->query_select('cached_comcode_pages a LEFT JOIN '.$GLOBALS['SITE_DB']->get_table_prefix().'comcode_pages b ON (a.the_page=b.the_page AND a.the_zone=b.the_zone)',array('cc_page_title','p_parent_page','string_index'),array('a.the_page'=>$the_page,'a.the_zone'=>$the_zone),'',1,NULL,false,array('string_index','cc_page_title'));
		if (!array_key_exists(0,$page_rows))
		{
			request_page($the_page,false,$the_zone,NULL,true); // It's not cached, force the issue and then try again...
			$page_rows=$GLOBALS['SITE_DB']->query_select('cached_comcode_pages a LEFT JOIN '.$GLOBALS['SITE_DB']->get_table_prefix().'comcode_pages b ON (a.the_page=b.the_page AND a.the_zone=b.the_zone)',array('cc_page_title','p_parent_page','string_index'),array('a.the_page'=>$the_page,'a.the_zone'=>$the_zone),'',1,NULL,false,array('string_index','cc_page_title'));
			if (!array_key_exists(0,$page_rows)) // Oh well, fallback (maybe page doesn't exist yet, ?)...
			{
				$_title=$the_page;
				$PT_PAIR_CACHE_CP[$the_page]=array();
				$PT_PAIR_CACHE_CP[$the_page]['cc_page_title']=escape_html($_title);
				$PT_PAIR_CACHE_CP[$the_page]['p_parent_page']=NULL;
			}
		}
		if (array_key_exists(0,$page_rows))
		{
			$PT_PAIR_CACHE_CP[$the_page]=$page_rows[0];
			$_title=get_translated_text($PT_PAIR_CACHE_CP[$the_page]['cc_page_title'],NULL,NULL,true);
			if ($_title===NULL) $_title=$the_page;
			$PT_PAIR_CACHE_CP[$the_page]['cc_page_title']=$_title;
		}
	}

	$title=$PT_PAIR_CACHE_CP[$the_page]['cc_page_title'];
	if ($title===NULL) $title=$the_page;
	if (!$no_link_for_me_sir)
	{
		$tpl_url=($PT_PAIR_CACHE_CP[$the_page]['p_parent_page']=='')?new ocp_tempcode():do_template('BREADCRUMB_ESCAPED');
		$_title=is_object($title)?$title->evaluate():$title;
		$tooltip=($jumps==0)?do_lang_tempcode('VIRTUAL_ROOT'):do_lang_tempcode('GO_BACKWARDS_TO',@html_entity_decode(strip_tags($_title),ENT_QUOTES,get_charset()));

		$title=symbol_truncator(array($_title,BREADCRUMB_CROP_LENGTH,'1','1'),'spread',$tooltip);
		$tpl_url->attach(hyperlink($url,$title,false,false,(strlen($_title)>BREADCRUMB_CROP_LENGTH)?new ocp_tempcode():$tooltip,NULL,NULL,'up'));
	} else
	{
		$tpl_url=new ocp_tempcode();
		if ($jumps==0)
		{
			$tpl_url=($PT_PAIR_CACHE_CP[$the_page]['p_parent_page']=='')?new ocp_tempcode():do_template('BREADCRUMB_ESCAPED');
			$_title=is_object($title)?$title->evaluate():$title;
			if ($_title!='')
				$tpl_url->attach('<span>'.$_title.'</span>');
		}
	}

	if ($PT_PAIR_CACHE_CP[$the_page]['p_parent_page']==$the_page) fatal_exit(do_lang_tempcode('RECURSIVE_TREE_CHAIN',escape_html($the_page)));
	$below=comcode_breadcrumbs($PT_PAIR_CACHE_CP[$the_page]['p_parent_page'],$the_zone,$root,false,$jumps+1);
	$below->attach($tpl_url);

	return $below;
}

/**
 * Log statistics for the page view.
 *
 * @param  string			The string to the page file
 * @param  integer		The time taken for page loading in milliseconds
 */
function log_stats($string,$pg_time)
{
	if (!addon_installed('stats')) return;

	if ((get_option('site_closed')=='1') && (get_option('no_stats_when_closed',true)==='1')) return;

	if ((get_option('super_logging')=='1') || (get_param('track',NULL)!==NULL))
	{
		$get=substr(flatten_slashed_array($_GET),0,255);
		$post2=$_POST;
		unset($post2['password']);
		unset($post2['password_confirm']);
		unset($post2['decrypt']);
		$post=flatten_slashed_array($post2);
	} else
	{
		$get='';
		$post='';
	}
	$page=$string;
	$ip=get_ip_address();
	$member=get_member();
	if (is_guest($member)) $member=-get_session_id();
	$time=time();
	$referer=substr(ocp_srv('HTTP_REFERER'),0,255);
	$browser=substr(get_browser_string(),0,255);
	$os=substr(get_os_string(),0,255);
	if ($os===NULL) $os='';

	if ((get_option('no_bot_stats',true)==='1') && ((strpos(strtolower($browser),'http:')!==false) || (strpos(strtolower($browser),'bot')!==false) || (get_bot_type()!==NULL))) return;

	$GLOBALS['SITE_DB']->query_insert('stats',array('access_denied_counter'=>0,'browser'=>$browser,'operating_system'=>$os,'the_page'=>$page,'ip'=>$ip,'the_user'=>$member,'date_and_time'=>$time,'referer'=>$referer,'get'=>$get,'post'=>$post,'milliseconds'=>intval($pg_time*1000)),false,true);
	if (mt_rand(0,1000)==1) $GLOBALS['SITE_DB']->query('DELETE FROM '.get_table_prefix().'stats WHERE date_and_time<'.strval(time()-60*60*24*intval(get_option('stats_store_time'))));

	global $SITE_INFO;
	if (isset($SITE_INFO['throttle_bandwidth_views_per_meg'])) set_value('page_views',strval(intval(get_value('page_views'))+1));
}


