false, 'wide' => false, 'wide_print' => false, 'filtered' => false, 'utheme' => false, 'active_filter' => true, 'redirected' => true, 'redirect_url' => true, 'redirect' => true, 'redirect_passon' => true); inform_non_canonical_parameter('#^(.*_)?(max|start|sort)$#'); if (function_exists('get_value')) { $is_non_canonical = false; $canonical_keep_params = explode(',', is_null(get_value('canonical_keep_params')) ? 'keep_devtest' : get_value('canonical_keep_params')); foreach (array_merge(array_keys($_GET), array('keep_session'/*may be inserted later*/)) as $key) { if ((is_string($key)) && (substr($key, 0, 5) == 'keep_') && (!@in_array($key, $canonical_keep_params))) { $NON_CANONICAL_PARAMS[$key] = true; $is_non_canonical = true; } } /* Doing this redirect is too risky. Some code (including user code) may redirect back to inject missing parameters. if (($is_non_canonical) && (get_bot_type() !== null)) { // Force bots onto the canonical URL if there were non-standard keep parameters, as they may ignore even the canonical meta tag. $non_canonical = array(); if (is_array($NON_CANONICAL_PARAMS)) { foreach (array_keys($NON_CANONICAL_PARAMS) as $n) { $non_canonical[$n] = null; } } set_http_status_code('301'); require_code('urls'); header('Location: ' . escape_header(get_self_url(true, false, $non_canonical))); exit(); } */ } global $PAGE_STRING, $LAST_COMCODE_PARSED_TITLE; $PAGE_STRING = null; $LAST_COMCODE_PARSED_TITLE = ''; global $PT_PAIR_CACHE_CP; $PT_PAIR_CACHE_CP = array(); global $ATTACH_MESSAGE_CALLED; $ATTACH_MESSAGE_CALLED = 0; load_zone_data(); // SEO redirection require_code('urls'); if (can_try_url_schemes()) { $ruri = cms_srv('REQUEST_URI'); $url_scheme = get_option('url_scheme'); if (($url_scheme == 'PG') || ($url_scheme == 'HTM')) { if ( (!headers_sent()) && (running_script('index')) && ($GLOBALS['RELATIVE_PATH'] == get_zone_name()/*i.e. a proper zone*/) && (cms_srv('REQUEST_METHOD') != 'POST') && (get_param_integer('keep_failover', null) !== 0) && ((strpos($ruri, '/pg/') === false) || ($url_scheme != 'PG')) && ((strpos($ruri, '.htm') === false) || ($url_scheme != 'HTM')) && ($ruri != '/') ) { require_code('permissions'); set_http_status_code('301'); header('Location: ' . escape_header(get_self_url(true))); exit(); } } } // Search engine having session in URL, we don't like this if ((get_bot_type() !== null) && (cms_srv('REQUEST_METHOD') != 'POST') && (get_param_string('keep_session', null) !== null)) { //Too risky, what if something sets it at run-time. Relying on canonical URL is better. //set_http_status_code('301'); //header('Location: ' . escape_header(get_self_url(true, false, array('keep_session' => null, 'keep_print' => null)))); //exit(); } $cli = ((php_function_allowed('php_sapi_name')) && (php_sapi_name() == 'cli') && (cms_srv('REMOTE_ADDR') == '')); if ((running_script('index')) && (!$cli)) { $access_host = preg_replace('#:.*#', '', cms_srv('HTTP_HOST')); // Detect bad access domain global $SITE_INFO; if (($access_host != '') && ((isset($_SERVER['HTTP_HOST'])) || (isset($_ENV['HTTP_HOST']))) && (empty($GLOBALS['EXTERNAL_CALL']))) { $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 (empty($SITE_INFO['ZONE_MAPPING_' . get_zone_name()])) { if ((!is_null($GLOBALS['FORUM_DRIVER'])) && ($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'); } set_http_status_code('301'); header('Location: ' . escape_header(get_self_url(true, false))); exit(); } } } // Detect bad access protocol if ((get_value('access_protocol_redirect') === '1') && ((substr(get_base_url(), 0, 8) == 'https://') && (!tacit_https()) || (substr(get_base_url(), 0, 7) == 'http://') && (tacit_https()))) { set_http_status_code('301'); header('Location: ' . escape_header(get_self_url(true, false))); exit(); } if (get_value('disable_cookie_checks') !== '1') { // Detect bad cookie domain (reasonable approximation) $cookie_domain = @ltrim(get_cookie_domain(), '.'); if (!empty($cookie_domain) && !empty($access_host)) { if (substr($access_host, -strlen($cookie_domain)) != $cookie_domain) { attach_message(do_lang_tempcode('INCORRECT_COOKIE_DOMAIN', escape_html($cookie_domain), escape_html($access_host)), 'warn'); } } // Detect bad cookie path $cookie_path = get_cookie_path(); $access_path = cms_srv('SCRIPT_NAME'); if (!empty($cookie_path) && !empty($access_path)) { if (substr($access_path, 0, strlen($cookie_path)) != $cookie_path) { attach_message(do_lang_tempcode('INCORRECT_COOKIE_PATH', escape_html($cookie_path), escape_html($access_path)), 'warn'); } } } } if (running_script('index')) { process_url_monikers(get_page_name()); } // Bulk advance loading global $SMART_CACHE; if (isset($SMART_CACHE)) { $_comcode_pages_needed = $SMART_CACHE->get('comcode_pages_needed'); if ($_comcode_pages_needed !== null) { $comcode_pages_needed = array(); foreach ($_comcode_pages_needed as $_comcode_page_needed => $_) { $__comcode_page_needed = @unserialize($_comcode_page_needed); if ($__comcode_page_needed !== false) { $comcode_pages_needed[] = $__comcode_page_needed; } } if (count($comcode_pages_needed) < 20) { _load_comcodes_page_from_cache($comcode_pages_needed); } } } global $COMCODE_PAGE_RUNTIME_CACHE; $COMCODE_PAGE_RUNTIME_CACHE = array(); } /** * Load up details for the current zone. */ function check_has_page_access() { $real_zone = load_zone_data(); // The most important security check global $SESSION_CONFIRMED_CACHE; get_member(); // Make sure we've loaded our backdoor if installed require_code('permissions'); global $ZONE; if ($ZONE['zone_require_session'] == 1) { set_no_clickjacking_csp(); } if (($ZONE['zone_name'] != '') && (!is_httpauth_login()) && ((get_session_id() == '') || (!$SESSION_CONFIRMED_CACHE)) && ($ZONE['zone_require_session'] == 1) && (get_page_name() != 'login') && (!is_guest())) { 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']))) { if ((running_script('index')) && /*Actually we will allow Guest denying to the front page even though that is a bit weird ((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 (get_page_name() != 'login') { access_denied('ZONE_ACCESS', $ZONE['zone_name'], true); } } } } /** * Load up details for the current zone. * * @return ID_TEXT The "real" zone name (not actually the zone name, but the zone name wants details to load for). */ function load_zone_data() { global $ZONE, $RELATIVE_PATH; $zone_name = get_zone_name(); $real_zone = (($RELATIVE_PATH == '_tests') || ($RELATIVE_PATH == 'data') || ($RELATIVE_PATH == 'data_custom')) ? get_param_string('zone', '') : $zone_name; /** A map of the current zone that is running. * * @global array $ZONE */ if ($ZONE === null) { $ZONE = persistent_cache_get(array('ZONE', $real_zone)); if ($ZONE === null) { find_all_zones(); // Optimisation, this will load up our zone list which *usually* includes caching of current zone, as this likely is needed somewhere anyway global $ALL_ZONES_TITLED_CACHE; if (isset($ALL_ZONES_TITLED_CACHE[$real_zone][3])) { $ZONE = $ALL_ZONES_TITLED_CACHE[$real_zone][3]; } } if ($ZONE === null) { $zones = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => $real_zone), '', 1); // Auto-create zone if ((!array_key_exists(0, $zones)) && (is_dir(get_file_base() . '/' . $real_zone . '/' . 'pages'))) { $zones = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => preg_replace('#\d#', '', $real_zone)), '', 1); if (array_key_exists(0, $zones)) { // Ah, we have a zone with the same name, except the numbers stripped -- this can be a template $map = $zones[0]; $map['zone_name'] = $real_zone; $map = insert_lang('zone_title', get_translated_text($zones[0]['zone_title']), 1) + $map; $map = insert_lang('zone_header_text', get_translated_text($zones[0]['zone_header_text']), 1) + $map; $access = $GLOBALS['SITE_DB']->query_select('group_zone_access', array('group_id'), array('zone_name' => $zones[0]['zone_name'])); foreach ($access as $a) { $GLOBALS['SITE_DB']->query_insert('group_zone_access', array('group_id' => $a['group_id'], 'zone_name' => $real_zone)); } } else { $zone_default_page = 'start'; if ($real_zone == 'forum') { // A bit of an architectural fudge, but people get confused why it doesn't come back the same $zone_default_page = 'forumview'; } if ($real_zone == 'docs') { $zone_default_page = 'tutorials'; } $map = array( 'zone_name' => $real_zone, 'zone_default_page' => $zone_default_page, 'zone_theme' => 'default', 'zone_require_session' => 0, ); $map += insert_lang('zone_title', $real_zone, 1); $map += insert_lang('zone_header_text', $real_zone, 1); } $GLOBALS['SITE_DB']->query_insert('zones', $map); $zones = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => $real_zone), '', 1); } if (array_key_exists(0, $zones)) { $ZONE = $zones[0]; persistent_cache_set(array('ZONE', $real_zone), $ZONE); } // Missing zone if ($ZONE === null) { $zones = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => ''), '', 1); $ZONE = $zones[0]; warn_exit(do_lang_tempcode('BAD_ZONE', escape_html($real_zone))); } unset($zones); } } return $real_zone; } /** * Attach some extra JavaScript to . Don't use this too commonly, it's not a 'tidy' way of doing things. * * @sets_output_state * * @param mixed $data JavaScript to attach (Tempcode or string) */ function attach_to_javascript($data) { global $JAVASCRIPT; if ($JAVASCRIPT === null) { $JAVASCRIPT = new Tempcode(); } $JAVASCRIPT->attach($data); } /** * Attach some XHTML to the screen header. * * @sets_output_state * * @param mixed $data XHTML to attach (Tempcode or string) */ function attach_to_screen_header($data) { global $EXTRA_HEAD; if ($EXTRA_HEAD === null) { $EXTRA_HEAD = new Tempcode(); } $EXTRA_HEAD->attach($data); } /** * Mark another parameter non-canonical, so that Google won't consider it when indexing URLs. * * @sets_output_state * * @param ID_TEXT $param Parameter name * @param boolean $block_page_from_static_cache_if_present If set to true and if this parameter is present in the URL then no static cache save will happen */ function inform_non_canonical_parameter($param, $block_page_from_static_cache_if_present = true) { global $NON_CANONICAL_PARAMS; if ($param[0] == '#') { // A regexp foreach (array_keys($_GET) as $key) { if (is_numeric($key)) { $key = strval($key); } if (preg_match($param, $key) != 0) { inform_non_canonical_parameter($key); } } } else { $NON_CANONICAL_PARAMS[$param] = $block_page_from_static_cache_if_present; } } /** * Attach a message to the page output. * * @sets_output_state * * @param mixed $message The type of special message * @param ID_TEXT $type The template to use * @set inform notice warn * @param boolean $put_in_helper_panel Whether to put into the helper panel instead of the normal header area * @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', $put_in_helper_panel = false) { if ((error_reporting() == 0) && ($type == 'warn')) { return ''; // Suppressing errors } static $am_looping = false; if ($am_looping) { return ''; // Was a lang lookup error and got in an infinite loop of attaching errors about missing lang errors (because each iteration causes a reevaluation of past messages) } $am_looping = true; global $ATTACH_MESSAGE_CALLED, $ATTACHED_MESSAGES, $ATTACHED_MESSAGES_RAW, $LATE_ATTACHED_MESSAGES; if (!isset($ATTACH_MESSAGE_CALLED)) { return ''; // Still starting up } foreach ($ATTACHED_MESSAGES_RAW as $last) { if (array(strip_tags(is_object($last[0]) ? $last[0]->evaluate() : $last[0]), $last[1]) == array(strip_tags(is_object($message) ? $message->evaluate() : $message), $type)) { $am_looping = false; return ''; // Already shown } } $ATTACH_MESSAGE_CALLED++; if ($ATTACH_MESSAGE_CALLED > 5) { critical_error('EMERGENCY', is_object($message) ? $message->evaluate() : escape_html($message)); } 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( '_GUID' => '36ccd2ff13867ed000a46f15df0a4a22', '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); } $message_tpl = do_template('MESSAGE', array( '_GUID' => 'ec843c8619d21fbeeb512686ea300a17', 'TYPE' => $type, 'MESSAGE' => is_string($message) ? escape_html($message) : $message )); if ($put_in_helper_panel) { set_helper_panel_text($message_tpl, true, false); } else { $ATTACHED_MESSAGES_RAW[] = array($message, $type); if ($GLOBALS['TEMPCODE_OUTPUT_STARTED']) { if ($LATE_ATTACHED_MESSAGES === null) { $LATE_ATTACHED_MESSAGES = new Tempcode(); } $LATE_ATTACHED_MESSAGES->attach($message_tpl); } else { if ($ATTACHED_MESSAGES === null) { $ATTACHED_MESSAGES = new Tempcode(); } $ATTACHED_MESSAGES->attach($message_tpl); } } $ATTACH_MESSAGE_CALLED--; if ($GLOBALS['REFRESH_URL'][0] != '') { $GLOBALS['SITE_DB']->query_insert('messages_to_render', array( 'r_session_id' => get_session_id(), 'r_message' => is_object($message) ? $message->evaluate() : escape_html($message), 'r_type' => $type, 'r_time' => time(), )); } $am_looping = false; return ''; } /** * Get the relative URL to the logo for the current zone. * * @param ?ID_TEXT $zone_name 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. * * @param boolean $show_self Whether to show a self segment * @return Tempcode The breadcrumbs */ function breadcrumbs($show_self = true) { static $out = null; if ($out !== null) { return $out; } global $BREADCRUMB_SET_PARENTS, $BREADCRUMBS; // Special hard-coded link to sitemap structure for Admin and CMS zones $zone = get_zone_name(); if ((($zone == 'adminzone') || ($zone == 'cms')) && (get_option('deeper_admin_breadcrumbs') == '1') && (get_page_name() != 'login')) { require_code('site_adminzone'); $BREADCRUMB_SET_PARENTS = array_merge(adminzone_extended_breadcrumbs(), $BREADCRUMB_SET_PARENTS); } // Substitutions if ((addon_installed('breadcrumbs')) && (function_exists('xml_parser_create'))) { // We may need to add in the final label so load_breadcrumb_substitutions can see and match on it; we will then pop that final label knowing that load_breadcrumb_substitutions altered the BREADCRUMB_SET_SELF global if it needed to require_code('breadcrumbs'); $needs_pop = false; if (($GLOBALS['BREADCRUMB_SET_SELF'] !== null) || ($GLOBALS['DISPLAYED_TITLE'] !== null)) { $last_segment_label = isset($BREADCRUMB_SET_PARENTS[count($BREADCRUMB_SET_PARENTS) - 1]) ? $BREADCRUMB_SET_PARENTS[count($BREADCRUMB_SET_PARENTS) - 1][1] : null; $new_last_segment_label = ($GLOBALS['BREADCRUMB_SET_SELF'] !== null) ? $GLOBALS['BREADCRUMB_SET_SELF'] : $GLOBALS['DISPLAYED_TITLE']; if (($last_segment_label === null) || ((is_object($new_last_segment_label) ? $new_last_segment_label->evaluate() : $new_last_segment_label) != (is_object($last_segment_label) ? $last_segment_label->evaluate() : $last_segment_label))) { $BREADCRUMB_SET_PARENTS[] = array(null, $last_segment_label); $needs_pop = true; } } $BREADCRUMB_SET_PARENTS = load_breadcrumb_substitutions($BREADCRUMB_SET_PARENTS); if ($needs_pop) { array_pop($BREADCRUMB_SET_PARENTS); } } // Render if ($BREADCRUMBS === null) { $BREADCRUMBS = breadcrumbs_get_default_stub($show_self); } $out = new Tempcode(); $out->attach($BREADCRUMBS); 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 $link_to_self_entrypoint 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 Tempcode(); // Specified parents $stub->attach(breadcrumb_segments_to_tempcode($BREADCRUMB_SET_PARENTS, $link_to_self_entrypoint)); // Self-link if ($link_to_self_entrypoint) { $label = (($BREADCRUMB_SET_SELF === null) && ($DISPLAYED_TITLE !== null)) ? protect_from_escaping($DISPLAYED_TITLE) : $BREADCRUMB_SET_SELF; if ($label !== null) { $label_eval = is_object($label) ? $label->evaluate() : $label; $last_breadcrumb_label_eval = mixed(); $last_breadcrumb_label_eval = (count($BREADCRUMB_SET_PARENTS) == 0) ? '' : $BREADCRUMB_SET_PARENTS[count($BREADCRUMB_SET_PARENTS) - 1][1]; if (is_object($last_breadcrumb_label_eval)) { $last_breadcrumb_label_eval = $last_breadcrumb_label_eval->evaluate(); } if ($label_eval != $last_breadcrumb_label_eval) { if (count($BREADCRUMB_SET_PARENTS) != 0) { $stub->attach(do_template('BREADCRUMB_SEPARATOR')); } $stub->attach(do_template('BREADCRUMB_LONE_WRAP', array('_GUID' => '769236ef4f20a0a05cee6d7a335eaf9f', 'LABEL' => $label))); } } } return $stub; } /** * Convert breadcrumb segments to Tempcode breadcrumbs. * * @param array $segments The segments in array format * @param ?mixed $link_to_self_entrypoint Whether we'll be providing a link to where we are currently at (by reference, gets set to false in some circumstances) (null: don't save by reference) * @return Tempcode The segments in Tempcode0 */ function breadcrumb_segments_to_tempcode($segments, &$link_to_self_entrypoint = null) { $out = new Tempcode(); foreach ($segments as $i => $bit) { list($entry_point, $label) = $bit; $tooltip = isset($bit[2]) ? $bit[2] : ''; if (!(((is_string($tooltip)) && ($tooltip == '')) || ((is_object($tooltip)) && ($tooltip->is_empty())))) { $link_to_self_entrypoint = false; // Tooltip implies that we are defining end-point ourselves } if ($i != 0) { $out->attach(do_template('BREADCRUMB_SEPARATOR')); } if ($entry_point == '') { $out->attach(do_template('BREADCRUMB_LONE_WRAP', array('_GUID' => 'fcf371ee4a071ebdd170dc16a55f36dd', 'LABEL' => $label))); $link_to_self_entrypoint = false; // Empty part implies that we are defining end-point ourselves } else { $url = page_link_to_tempcode_url($entry_point); $out->attach(do_template('BREADCRUMB_LINK_WRAP', array('_GUID' => 'f7e8a83d61bde871ab182dec7da84ccc', 'LABEL' => $label, 'URL' => $url, 'TOOLTIP' => $tooltip))); } } return $out; } /** * Put a list of parents in for the breadcrumbs. * * @sets_output_state * * @param array $parents 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. * * @sets_output_state * * @param mixed $title The title (Tempcode or string) */ function breadcrumb_set_self($title) { global $BREADCRUMB_SET_SELF; $BREADCRUMB_SET_SELF = $title; } /** * Set the feed (RSS/Atom) URL. * * @sets_output_state * * @param URLPATH $url The URL */ function set_feed_url($url) { global $FEED_URL; $FEED_URL = $url; } /** * Set the helper panel text. * * @sets_output_state * * @param Tempcode $text The text * @param boolean $append Whether to append * @param boolean $put_in_box Whether to add a box around the parameter */ function set_helper_panel_text($text, $append = true, $put_in_box = true) { if ($put_in_box) { $text = put_in_standard_box($text); } global $HELPER_PANEL_TEXT; if ($append) { if (is_string($HELPER_PANEL_TEXT)) { $HELPER_PANEL_TEXT = make_string_tempcode($HELPER_PANEL_TEXT); } $HELPER_PANEL_TEXT->attach($text); } else { $HELPER_PANEL_TEXT = $text; } } /** * Set the helper panel tutorial. * * @sets_output_state * * @param ID_TEXT $tutorial The page name of the tutorial (must be an existing one on the brand site, i.e. compo.sr) */ function set_helper_panel_tutorial($tutorial) { global $HELPER_PANEL_TUTORIAL; $HELPER_PANEL_TUTORIAL = $tutorial; } /** * Sets the short title, used for screen header text if set. * Does not do anything if output streaming is on and already started. * * @sets_output_state * * @param string $title The short title */ function set_short_title($title) { global $SHORT_TITLE, $FORCE_SET_TITLE; if (!$FORCE_SET_TITLE) { $SHORT_TITLE = ($title == '') ? null : $title; } } /** * Process URL monikers, changing 'id' GET param to be correct. * * @param ID_TEXT $page The page name to do it for * @param boolean $redirect_if_non_canonical Do a redirect if we're not on the canonical URL */ function process_url_monikers($page, $redirect_if_non_canonical = true) { static $run_once = false; if ($run_once) { return; } $run_once = true; $zone = get_zone_name(); $type = get_param_string('type', null, true); $url_id = get_param_string('id', null, true); if (url_monikers_enabled()) { // Monikers relative to the zone $page_place = _request_page($page, $zone); if (($page_place !== false) && ($page_place[0] == 'REDIRECT')) { $page_place_r = $page_place; $page_place = _request_page($page_place[1]['r_to_page'], $page_place[1]['r_to_zone']); if (($page_place !== false) && (substr($page_place[0], 0, 7) != 'COMCODE') || ($type === null)) { // We're viewing the Comcode page behind this redirect, or it's not a Comcode page so nothing is underneath it $page = $page_place_r[1]['r_to_page']; $zone = $page_place_r[1]['r_to_zone']; } } if (($page_place === false) || ((substr($page_place[0], 0, 7) == 'COMCODE') && ($type !== null/*looking deeper than a normal Comcode page*/))) { // This code branch is finding absolute monikers (easy case), or monikers pointing to a Comcode page (special case)... // Reassemble source URL moniker from incorrectly-derived URL components $url_moniker = ''; $url_moniker .= get_param_string('page', '', true); /* Has to be unadulterated, $page has /s/-/_ */ if ($type !== null) { $url_moniker .= '/' . $type; } if ($url_id !== null) { $url_moniker .= '/' . $url_id; } // ... and query it $sql = 'SELECT * FROM ' . get_table_prefix() . 'url_id_monikers WHERE '; $sql .= db_string_equal_to('m_moniker', '/' . $url_moniker) . ' OR '; // Absolute $sql .= db_string_equal_to('m_moniker', $url_moniker) . ' AND ' . db_string_equal_to('m_resource_type', '') . ' AND ' . db_string_equal_to('m_resource_id', $zone) . ' OR '; // Comcode page // (dash replacement...) $sql .= db_string_equal_to('m_moniker', '/' . str_replace('-', '_', $url_moniker)) . ' OR '; // Absolute $sql .= db_string_equal_to('m_moniker', str_replace('-', '_', $url_moniker)) . ' AND ' . db_string_equal_to('m_resource_type', '') . ' AND ' . db_string_equal_to('m_resource_id', $zone); // Comcode page $monikers = $GLOBALS['SITE_DB']->query($sql, 1); if (array_key_exists(0, $monikers)) { if (_request_page($monikers[0]['m_resource_page'], $zone) !== false) { // ... if operable within the zone we're in // Bind to correct new values global $PAGE_NAME_CACHE, $GETTING_PAGE_NAME; $PAGE_NAME_CACHE = $monikers[0]['m_resource_page']; $GETTING_PAGE_NAME = false; if ($monikers[0]['m_resource_type'] == '') { $_GET['page'] = $monikers[0]['m_resource_page']; unset($_GET['type']); unset($_GET['id']); } else { $_GET['page'] = $monikers[0]['m_resource_page']; $_GET['type'] = $monikers[0]['m_resource_type']; $_GET['id'] = $monikers[0]['m_resource_id']; } // Check for (and handle) deprecation handle_moniker_deprecation_redirect($zone, $monikers[0], $redirect_if_non_canonical, true); return; } } } // Does this URL arrangement support monikers? We find out by interrogating hooks to see if the moniker can sit under the module's zone+page+type stub. if ($url_id !== null) { // NB: Comcode page monikers would have been handled in the code above $type = get_param_string('type', 'browse'); $looking_for = '_SEARCH:' . $page . ':' . $type . ':_WILD'; $hooks = find_all_hooks('systems', 'content_meta_aware'); $ob_info = null; foreach (array_keys($hooks) as $hook) { require_code('content'); $ob = get_content_object($hook); if ($ob === null) { continue; } $ob_info = $ob->info(); if ($ob_info === null) { continue; } if ($ob_info['view_page_link_pattern'] !== null) { $ob_info['view_page_link_pattern'] = preg_replace('#:[^:]*$#', ':_WILD', $ob_info['view_page_link_pattern']); } if (($ob_info['view_page_link_pattern'] == $looking_for) && ($ob_info['support_url_monikers'])) { if (is_numeric($url_id)) { // We definitely did not go to a moniker URL (as the URL ID was numeric). Lookup and redirect to the true moniker URL. $correct_moniker = find_id_moniker(array('page' => $page, 'type' => get_param_string('type', 'browse'), 'id' => $url_id), $zone); if (($correct_moniker !== null) && ($correct_moniker != $url_id) && (get_param_integer('keep_failover', null) !== 0) && (cms_srv('REQUEST_METHOD') != 'POST')) { // 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). set_http_status_code('301'); $_new_url = build_url(array('page' => '_SELF', 'id' => $correct_moniker), '_SELF', null, true); $new_url = $_new_url->evaluate(); header('Location: ' . escape_header($new_url)); exit(); } } else { // Look up the moniker row $table = 'url_id_monikers'; if (strpos(get_db_type(), 'mysql') !== false) { $table .= ' FORCE INDEX (uim_moniker)'; } $monikers = $GLOBALS['SITE_DB']->query_select($table, array('*'), array('m_resource_page' => $page, 'm_resource_type' => get_param_string('type', 'browse'), 'm_moniker' => $url_id)); if (!array_key_exists(0, $monikers)) { // Uh oh // Assume that it wasn't a moniker after all if (!$ob_info['id_field_numeric']) { return; } // Okay it was deleted or never existed then?! Just set to -1 as nothing will have that ID, and we'll get an error from the module when bootstrapping is fully finished $_GET['id'] = '-1'; return; } // Map back 'id' $_GET['id'] = $monikers[0]['m_resource_id']; // We need to know the ID number rather than the moniker // Check for (and handle) deprecation handle_moniker_deprecation_redirect($zone, $monikers[0], $redirect_if_non_canonical); } return; } } } } } /** * Redirect to the latest moniker, if appropriate. * * @param ID_TEXT $zone The zone * @param array $moniker_row The current moniker row * @param boolean $redirect_if_non_canonical Do a redirect if we're not on the canonical URL * @param boolean $is_complete_url_under_zone Is the moniker representing the full URL (as opposed to being underneath a module)? */ function handle_moniker_deprecation_redirect($zone, $moniker_row, $redirect_if_non_canonical, $is_complete_url_under_zone = false) { $deprecated = $moniker_row['m_deprecated'] == 1; if (($redirect_if_non_canonical) && ($deprecated) && (cms_srv('REQUEST_METHOD') != 'POST') && (get_param_integer('keep_failover', null) !== 0)) { $_moniker_row = $moniker_row; unset($_moniker_row['id']); unset($_moniker_row['m_moniker']); unset($_moniker_row['m_moniker_reversed']); unset($_moniker_row['m_manually_chosen']); $_moniker_row['m_deprecated'] = 0; $correct_moniker_rows = $GLOBALS['SITE_DB']->query_select('url_id_monikers', array('m_moniker'), $_moniker_row, '', 1); $correct_moniker = array_key_exists(0, $correct_moniker_rows) ? $correct_moniker_rows[0]['m_moniker'] : null; if (($correct_moniker !== null) && ($correct_moniker != $moniker_row['m_moniker'])) { // Just in case database corruption means ALL are deprecated set_http_status_code('301'); if ($is_complete_url_under_zone) { $_new_url = build_url(array('page' => $correct_moniker), '_SELF', null, true); } else { $_new_url = build_url(array('page' => '_SELF', 'id' => $correct_moniker), '_SELF', null, true); } $new_url = $_new_url->evaluate(); header('Location: ' . escape_header($new_url)); exit(); } } } /** * 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() { // 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 ' . db_string_equal_to('r_session_id', get_session_id()) . ' OR r_time<' . strval(time() - 60 * 60)); } } $out_evaluated = null; global $ZONE; // Note any special handling needed $special_page_type = get_param_string('special_page_type', 'view'); $keep_markers = get_param_integer('keep_markers', 0); $show_edit_links = get_param_integer('show_edit_links', 0); global $KEEP_MARKERS, $SHOW_EDIT_LINKS; /** Whether we will be embedding template markers in the output. * * @sets_output_state * * @global ?array $KEEP_MARKERS */ $KEEP_MARKERS = ($keep_markers == 1) || ($special_page_type == 'show_markers'); if (($KEEP_MARKERS) && (!headers_sent())) { header('Content-type: text/html; charset=' . get_charset()); } /** Whether we will be embedding edit links in the output. * * @sets_output_state * * @global ?array $SHOW_EDIT_LINKS */ $SHOW_EDIT_LINKS = ($show_edit_links == 1) || ($special_page_type == 'show_edit_links'); if ($SHOW_EDIT_LINKS) { require_css('themes_editor'); } if (($special_page_type != 'view') && ($special_page_type != 'show_markers')) { require_code('view_modes'); initialise_special_page_types($special_page_type); } $doing_special_page_type = ($special_page_type != 'view') && ($special_page_type != 'show_markers') && ($special_page_type != 'show_edit_links') && ($special_page_type != 'memory') && ((has_privilege(get_member(), 'view_profiling_modes')) || ($GLOBALS['IS_ACTUALLY_ADMIN'])); // Allow the site to be closed $site_closed = get_option('site_closed'); if (($site_closed == '1') && (!has_privilege(get_member(), 'access_closed_site')) && (!$GLOBALS['IS_ACTUALLY_ADMIN'])) { require_code('site2'); closed_site(); } // Warning about whether the Setup Wizard still needs running $zone = get_zone_name(); if ((($zone == 'adminzone') || ($zone == 'cms')) && (get_param_integer('wide_high', 0) == 0)) { if ((get_param_integer('cancel_sw_warn', 0) == 1) || (!addon_installed('setupwizard'))) { set_value('setupwizard_completed', '1'); } else { $_done_sw_once = get_value('setupwizard_completed'); $done_sw_once = !is_null($_done_sw_once); if ((!$done_sw_once) && (get_page_name() != 'admin_setupwizard') && (has_actual_page_access(get_member(), 'admin_setupwizard'))) { require_lang('config'); $setupwizard_url = build_url(array('page' => 'admin_setupwizard'), get_module_zone('admin_setupwizard')); $cancel_sw_url = get_self_url(false, true, array('cancel_sw_warn' => 1)); attach_message(do_lang_tempcode('SETUPWIZARD_NOT_RUN', escape_html($setupwizard_url->evaluate()), escape_html($cancel_sw_url->evaluate())), 'notice'); } } } // Warning if dev-mode is on if (($GLOBALS['DEV_MODE']) && (get_param_integer('wide_high', 0) == 0) && (get_param_integer('keep_hide_dev_mode_message', 0) == 0)) { static $done_message = false; if (!$done_message) { attach_message(do_lang_tempcode('DEV_MODE_ON'), 'notice'); $done_message = true; } } // Web Standards mode? $webstandards_check = get_param_integer('keep_webstandards_check', get_param_integer('webstandards_check', 0)); $show_edit_links = get_param_integer('show_edit_links', 0); $webstandards_mode = ( (($GLOBALS['IS_ACTUALLY_ADMIN']) || ($GLOBALS['FORUM_DRIVER']->is_staff(get_member()))) && (($special_page_type == 'code') || (($webstandards_check == 1) && ($GLOBALS['REFRESH_URL'][0] == '') && ($show_edit_links == 0)))); // Not a permission - a matter of performance if ($webstandards_mode) { $GLOBALS['OUTPUT_STREAMING'] = false; } // Output streaming? $out = globalise(null, null, '', true); // Load up our frames into strings. Note that the header and the footer are fixed already. $middle = request_page(get_page_name(), true, null, null, false, false, $out); if ($middle->is_empty_shell()) { set_http_status_code('404'); $title = get_screen_title('ERROR_OCCURRED'); $text = do_lang_tempcode('NO_PAGE_OUTPUT'); $middle = warn_screen($title, $text, false); } $out->singular_bind('MIDDLE', $middle); if (!$GLOBALS['OUTPUT_STREAMING']) { $out->handle_symbol_preprocessing(); } // Web Standards mode if ($webstandards_mode) { require_code('view_modes'); $out_evaluated = $out->evaluate(null); check_xhtml_webstandards($out_evaluated, ($special_page_type == 'code' && (get_param_integer('preview_mode', null) === null)), get_param_integer('preview_mode', 0)); } // Caching for spiders if ($GLOBALS['STATIC_CACHE_ENABLED']) { $out2 = clone $out; // This is needed to stop things messing up during output streaming save_static_caching($out2); } // Something to do now rather than output normal screen? if ($doing_special_page_type) { special_page_types($special_page_type, $out, $out_evaluated); } if ((in_safe_mode()) && (!isset($GLOBALS['SITE_INFO']['safe_mode']))) { global $SITE_INFO; $safe_mode_via_config = (isset($SITE_INFO['safe_mode'])) && ($SITE_INFO['safe_mode'] == '1'); $disable_safe_mode_url = get_self_url(true, true, array('keep_safe_mode' => $safe_mode_via_config ? 0 : null)); attach_message(do_lang_tempcode('CURRENTLY_HAS_KEEP_SAFE_MODE', escape_html($disable_safe_mode_url)), 'notice'); } if (get_param_integer('keep_fatalistic', 0) == 1) { $disable_fatalistic_url = get_self_url(true, true, array('keep_fatalistic' => null)); attach_message(do_lang_tempcode('CURRENTLY_HAS_KEEP_FATALISTIC', escape_html($disable_fatalistic_url)), 'notice'); } // 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(true) - $PAGE_START_TIME) * 1000.0; // Output if (!$GLOBALS['QUICK_REDIRECT']) { if ($out_evaluated !== null) { echo $out_evaluated; } else { if ($GLOBALS['OUTPUT_STREAMING']) { $middle->handle_symbol_preprocessing(); } $GLOBALS['FINISHING_OUTPUT'] = true; /*if (get_option('gzip_output')=='1') Does not work well ob_start('_compress_html_output');*/ $out->evaluate_echo(null); } } // Finally, stats if ($PAGE_STRING !== null) { log_stats($PAGE_STRING, intval($page_generation_time)); } // When someone hits the Admin Zone if (($ZONE !== null) && ($ZONE['zone_name'] == 'adminzone')) { // Security feature admins can turn on if (get_page_name() == 'start') { require_code('notifications'); $current_username = $GLOBALS['FORUM_DRIVER']->get_username(get_member()); $subject = do_lang('AFA_NOTIFICATION_MAIL_SUBJECT', $current_username, get_site_name(), get_ip_address()); $mail = do_notification_lang('AFA_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($current_username), comcode_escape(get_ip_address())); dispatch_notification('adminzone_dashboard_accessed', null, $subject, $mail); } // Track very basic details of what sites use Composr if ((!running_locally()) && (get_option('call_home') == '1')) { $timeout_before = @ini_get('default_socket_timeout'); safe_ini_set('default_socket_timeout', '3'); require_code('version2'); require_code('files2'); cache_and_carry('http_download_file', array('http://compo.sr/uploads/website_specific/compo.sr/scripts/user.php?url=' . urlencode(get_base_url()) . '&name=' . urlencode(get_site_name()) . '&version=' . urlencode(get_version_dotted()), null, false), 60 * 24/*once a day*/); safe_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)) { if (!$GLOBALS['SITE_DB']->table_is_locked('values')) { set_value('last_space_check', strval(time())); } if (php_function_allowed('disk_free_space')) { $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_notification_lang('LOW_DISK_SPACE_MAIL', strval(intval(round($disk_space / 1024 / 1024))), null, null, get_site_default_lang()); dispatch_notification('low_disk_space', null, $subject, $message, null, A_FROM_SYSTEM_PRIVILEGED); } } } } /** * Do any static cache saving that we want to do. * * @param mixed $out Output to cache (Tempcode or string) * @param string $mime_type Mime type to use */ function save_static_caching($out, $mime_type = 'text/html') { // We cannot cache if there's a redirect $headers_sent = headers_list(); foreach ($headers_sent as $header) { if (preg_match('#^Location:#i', $header) != 0) { return; } } global $SITE_INFO; if ((cms_srv('REQUEST_METHOD') != 'POST') && (isset($SITE_INFO['fast_spider_cache'])) && ($SITE_INFO['fast_spider_cache'] != '0') && (is_guest()) && (!$GLOBALS['IS_ACTUALLY_ADMIN'])) { if ((get_zone_name() == '') && (get_zone_default_page('') == get_page_name()) && (count(array_diff(array_keys($_GET), array('page', 'keep_session', 'keep_devtest', 'keep_failover'))) > 0)) { /*TODO: Reenable in v11 if ($debugging) { if (php_function_allowed('error_log')) { @error_log('SC save: No, home page has spurious parameters, likely a bot probing'); } }*/ return; } $bot_type = get_bot_type(); $supports_failover_mode = (isset($SITE_INFO['failover_mode'])) && ($SITE_INFO['failover_mode'] != 'off'); $supports_guest_caching = (isset($SITE_INFO['any_guest_cached_too'])) && ($SITE_INFO['any_guest_cached_too'] == '1'); require_code('static_cache'); if ((($bot_type !== null) || ($supports_failover_mode) || ($supports_guest_caching)) && (can_static_cache())) { $url = static_cache_current_url(); $fast_cache_path = get_custom_file_base() . '/caches/guest_pages/' . md5($url); $fast_cache_path_failover_mode = $fast_cache_path; if ($bot_type === null) { $fast_cache_path .= '__non-bot'; } if (!array_key_exists('js_on', $_COOKIE)) { $fast_cache_path .= '__no-js'; } if (is_mobile()) { $fast_cache_path .= '__mobile'; $fast_cache_path_failover_mode .= '__mobile'; } $fast_cache_path_failover_mode .= '__failover_mode'; if (is_object($out)) { $out_evaluated = $out->evaluate(null); $static_cache = $out_evaluated; } else { $static_cache = $out; } if (!$GLOBALS['STATIC_CACHE_ENABLED']) { return; // Something in the output tree decided this was not cacheable } // Remove any sessions etc $static_cache = preg_replace('#(&|&|&amp;|%3Aamp%3A|\?)?(keep_session|keep_devtest|keep_failover)(=|%3D)\w+#', '', $static_cache); // Add URL identifier $static_cache .= "\n\n" . ''; // Add mime type $static_cache .= "\n\n" . ''; $file_extension = ($mime_type == 'text/xml') ? '.xml' : '.htm'; // Cache, but only if we want to // If it's a noindex page we don't (to limit cache size). That is a deep page a bot took a look at, and we even told the bot it was not important. if (strpos($static_cache, ' 20) { $REQUEST_PAGE_NEST_LEVEL = 0; attach_message(do_lang_tempcode('STOPPED_RECURSIVE_RESOURCE_INCLUDE', escape_html($codename), escape_html(do_lang('PAGE'))), 'warn'); return new Tempcode(); } // Run hooks, if any exist $hooks = find_all_hooks('systems', 'upon_page_load'); foreach ($hooks as $hook => $hook_dir) { require_code('hooks/systems/upon_page_load/' . filter_naughty_harsh($hook), false, $hook_dir == 'sources_custom'); $ob = object_factory('Hook_upon_page_load_' . filter_naughty_harsh($hook), true); if ($ob === null) { continue; } $ob->run($codename, $required, $zone, $page_type, $being_included, $details); } if ($details === false) { if ($required) { if (get_option('url_scheme') == 'SIMPLE') { $details = _request_page('404', '', null, null, false); } } 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 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], $out); $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], $out); $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, $out); $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, $out); $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, $out); $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, null, $out)); $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, null, $out)); $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, $out); $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, $out); $REQUEST_PAGE_NEST_LEVEL--; return $ret; case 'REDIRECT': $redirect = $details[1]; if ($required) { global $REDIRECTED_TO_CACHE; $REDIRECTED_TO_CACHE = $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) || ($being_included)) { if (($being_included) && (!has_page_access(get_member(), $redirect['r_to_page'], $redirect['r_to_zone'], true))) { if ($being_included) { return new Tempcode(); } 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, true/*Don't want redirect loops*/, $out); $REQUEST_PAGE_NEST_LEVEL--; return $ret; } } else { $title = get_screen_title('REDIRECTING'); $url = build_url($bits[1], $redirect['r_to_zone'], null, true); set_http_status_code('301'); $ret = redirect_screen($title, $url, do_lang_tempcode('REDIRECTED_LINK'), true); $REQUEST_PAGE_NEST_LEVEL--; return $ret; } } $REQUEST_PAGE_NEST_LEVEL--; return new Tempcode(); // should never get here } /** * Take the specified parameters, and try to find the corresponding page (caching front end). * * @param ID_TEXT $codename The codename of the page to load * @param ID_TEXT $zone The zone the page is being loaded in * @param ?ID_TEXT $page_type The type of page - for if you know it (null: don't know it) * @param ?LANGUAGE_NAME $lang Language name (null: user's language) * @param boolean $no_redirect_check 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) { $details = persistent_cache_get(array('PAGE_INFO', $codename, $zone, $page_type, $lang, $no_redirect_check)); if ($details === null || $details === false/*caching negativity breaks things if the page subsequently appears - even adding a page does a pre-check so would net a cached false*/) { $details = __request_page($codename, $zone, $page_type, $lang, $no_redirect_check); persistent_cache_set(array('PAGE_INFO', $codename, $zone, $page_type, $lang, $no_redirect_check), $details); } return $details; } /** * Take the specified parameters, and try to find the corresponding page. * * @param ID_TEXT $codename The codename of the page to load * @param ID_TEXT $zone The zone the page is being loaded in * @param ?ID_TEXT $page_type The type of page - for if you know it (null: don't know it) * @param ?LANGUAGE_NAME $lang Language name (null: user's language) * @param boolean $no_redirect_check Whether to not check for redirects (normally you would) * @return ~array A list of details (false: page not found) * @ignore */ 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) && (get_value('no_priority_redirects') !== '1') && (addon_installed('redirects_editor'))) { $test = _request_page__redirects($codename, $zone); if ($test !== false) { return $test; } } // 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 (get_custom_file_base() != get_file_base()) { // For multisite installs 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/minimodules_custom/' . $codename . '.php', true); if (@is_file(get_file_base() . '/' . $path)) { return array('MINIMODULES_CUSTOM', $zone, $codename, $path); } } 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 (get_custom_file_base() != get_file_base()) { // For multisite installs 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); } } } 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/minimodules/' . $codename . '.php', true); if (@is_file(get_file_base() . '/' . $path)) { return array('MINIMODULES', $zone, $codename, $path); } // As a fallback 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 (get_custom_file_base() != get_file_base()) { // For multisite installs 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/html_custom/' . $fallback_lang . '/' . $codename . '.htm', true); if (@is_file(get_custom_file_base() . '/' . $path)) { return array('HTML_CUSTOM', $zone, $codename, $fallback_lang, $path); } } } // Or check for default pages $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); } $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); } foreach ($langs_to_try as $fallback_lang) { $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); } $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); } } // Redirect if ((!$no_redirect_check) && (addon_installed('redirects_editor'))) { $test = _request_page__redirects($codename, $zone, true/*include wildcards as this is lowest priority*/); if ($test !== false) { return $test; } } return false; } /** * Take the specified parameters, and try to find a redirect for the corresponding page. * * @param ID_TEXT $codename The codename of the page to load * @param ID_TEXT $zone The zone the page is being loaded in * @param boolean $wildcard_mode Whether to also search in wildcard mode * @return ~array A list of details (false: page not found) * @ignore */ function _request_page__redirects($codename, $zone, $wildcard_mode = false) { $codename = strtolower($codename); static $internal_cache = array(); if (isset($internal_cache[$codename][$zone][$wildcard_mode])) { return $internal_cache[$codename][$zone][$wildcard_mode]; } global $REDIRECT_CACHE; if ($REDIRECT_CACHE === null) { load_redirect_cache(); } if (isset($REDIRECT_CACHE)) { if (isset($REDIRECT_CACHE[$zone][$codename])) { $redirect = array($REDIRECT_CACHE[$zone][$codename]); } elseif (($wildcard_mode) && (isset($REDIRECT_CACHE['*'][$codename]))) { $redirect = array($REDIRECT_CACHE['*'][$codename]); } else { $redirect = array(); } } else { $query = 'SELECT * FROM ' . get_table_prefix() . 'redirects WHERE (' . db_string_equal_to('r_from_zone', $zone); if ($wildcard_mode) { $query .= ' OR ' . db_string_equal_to('r_from_zone', '*'); } $query .= ') AND ' . db_string_equal_to('r_from_page', $codename); $query .= ' ORDER BY r_from_zone DESC'; // The ordering ensures '*' comes last, as we want to deprioritise this $redirect = $GLOBALS['SITE_DB']->query($query, 1, null, false, true); } if (isset($redirect[0])) { $ret = array('REDIRECT', $redirect[0]); $internal_cache[$codename][$zone][$wildcard_mode] = $ret; return $ret; } $internal_cache[$codename][$zone][$wildcard_mode] = false; return false; } /** * Get a Comcode page from the cache. * * @param ID_TEXT $codename The codename of the page * @param ID_TEXT $zone The zone the page is being loaded from * @param ID_TEXT $theme The theme * @return array The page row */ function load_comcode_page_from_cache($codename, $zone, $theme) { $tuple = array($codename, $zone, $theme); global $SMART_CACHE; if ($SMART_CACHE !== null) { $SMART_CACHE->append('comcode_pages_needed', serialize($tuple)); } $ret = _load_comcodes_page_from_cache(array($tuple)); return isset($ret[0]) ? $ret[0] : null; } /** * Wraps load_comcode_page_from_cache for bulk loading. * * @param array $pages Details of pages to load * @return array Database rows * * @ignore */ function _load_comcodes_page_from_cache($pages) { global $COMCODE_PAGE_RUNTIME_CACHE; $ret = array(); $needs_query = false; $sql = 'SELECT * FROM ' . get_table_prefix() . 'cached_comcode_pages a JOIN ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'comcode_pages b ON a.the_page=b.the_page AND a.the_zone=b.the_zone'; $sql .= ' WHERE 1=0'; foreach ($pages as $page) { $sz = serialize($page); if (isset($COMCODE_PAGE_RUNTIME_CACHE[$sz])) { $ret[] = $COMCODE_PAGE_RUNTIME_CACHE[$sz]; } else { list($codename, $zone, $theme) = $page; $sql .= ' OR '; $sql .= db_string_equal_to('a.the_page', $codename) . ' AND ' . db_string_equal_to('a.the_zone', $zone) . ' AND ' . db_string_equal_to('the_theme', $theme); $needs_query = true; } } if ($needs_query) { $_ret = $GLOBALS['SITE_DB']->query($sql, null, null, false, false, array('string_index' => 'LONG_TRANS__COMCODE', 'cc_page_title' => '?SHORT_TRANS')); foreach ($_ret as $_page) { $sz = serialize(array($_page['the_page'], $_page['the_zone'], $_page['the_theme'])); $COMCODE_PAGE_RUNTIME_CACHE[$sz] = $_page; $ret[] = $_page; } } return $ret; } /** * Get the parsed contents of a Comcode page. * * @param PATH $string The relative (to Composr's base directory) path to the page (e.g. pages/comcode/EN/start.txt) * @param ID_TEXT $zone The zone the page is being loaded from * @param ID_TEXT $codename The codename of the page * @param ?PATH $file_base The file base to load from (null: standard) * @param boolean $being_included Whether the page is being included from another * @param ?object $out Semi-filled output template (null: definitely not doing output streaming) * @return Tempcode The page */ function load_comcode_page($string, $zone, $codename, $file_base = null, $being_included = false, &$out = null) { 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') { set_http_status_code('404'); } if ( ( ($is_panel) || ($codename[0] == '_') || ($zone . ':' . $codename == ':404') || // FUDGE. Sculpt what comes up in Google a bit. We don't want really meta contextual help muddying search results ($codename == 'rules') || ($zone . ':' . $codename == ':recommend_help') || ($zone . ':' . $codename == ':popup_blockers') || ($zone . ':' . $codename == ':help') || ($zone . ':' . $codename == ':userguide_chatcode') || ($zone . ':' . $codename == ':userguide_comcode') || ($zone . ':' . $codename == 'site:popup_blockers') || ($zone . ':' . $codename == 'site:help') || ($zone . ':' . $codename == 'site:userguide_chatcode') || ($zone . ':' . $codename == 'site:userguide_comcode') ) && (get_page_name() == $codename/*Top-level*/) ) { attach_to_screen_header(''); // XHTMLXHTML } if ($zone == 'adminzone') { require_code('site_adminzone'); adminzone_special_cases($codename); } if ($codename == 'sitemap') { set_feed_url('?mode=comcode_pages&select=' . urlencode($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, 'p_order' => 0, ); if ((has_caching_for('comcode_page')) && (get_param_integer('keep_print', 0) == 0)) { $support_smart_decaching = support_smart_decaching(); if (is_browser_decaching()) { $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 (isset($comcode_page[0])) { 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)); $GLOBALS['COMCODE_PAGE_RUNTIME_CACHE'] = array(); } } $theme = $GLOBALS['FORUM_DRIVER']->get_theme(); if ($GLOBALS['PERSISTENT_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 decaching the file. It'll get fixed automatically in a few hours when the hours of the timezone difference passes. } $pcache = persistent_cache_get(array('COMCODE_PAGE', $codename, $zone, $theme, user_lang()), $mtime); } else { $pcache = persistent_cache_get(array('COMCODE_PAGE', $codename, $zone, $theme, user_lang())); } } else { $pcache = null; } if ($pcache === null) { $comcode_page_row = load_comcode_page_from_cache($codename, $zone, $theme); if ($comcode_page_row !== 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 decaching 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_row['p_edit_date'] !== null) && ($comcode_page_row['p_edit_date'] >= $mtime)) || (($comcode_page_row['p_edit_date'] === null) && ($comcode_page_row['p_add_date'] !== null) && ($comcode_page_row['p_add_date'] >= $mtime)))) { // Make sure it has not been edited since last edited or created // Optimised path for empty panels when no super-fast persistent cache if ($support_smart_decaching/*only should do an fstat if this is enabled*/ && ($being_included || $is_panel) && $GLOBALS['PERSISTENT_CACHE'] === null && filesize($file_base . '/' . $string) == 0) { return new Tempcode(); } $just_comcode_page_row = db_map_restrict($comcode_page_row, array('the_page', 'the_zone', 'the_theme', 'string_index')); $db_set = get_translated_tempcode('cached_comcode_pages', $just_comcode_page_row, 'string_index', null, user_lang(), true, true/*,true*/); } 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 decaching 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_row['string_index']); $GLOBALS['COMCODE_PAGE_RUNTIME_CACHE'] = array(); $db_set = null; $comcode_page_row = null; } } else { $db_set = null; $comcode_page_row = null; } if ($db_set !== null) { $index = $comcode_page_row['string_index']; $title_to_use = $comcode_page_row['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; $raw_comcode = get_translated_text($comcode_page_row['string_index']); } else { $comcode_page = $GLOBALS['SITE_DB']->query_select('comcode_pages', array('*'), array('the_page' => $codename, 'the_zone' => $zone), '', 1); if (isset($comcode_page[0])) { $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, $raw_comcode) = _load_comcode_page_not_cached($string, $zone, $codename, $file_base, $comcode_page_row, $new_comcode_page_row, $being_included); } persistent_cache_set(array('COMCODE_PAGE', $codename, $zone, $theme, user_lang()), array($html, $title_to_use, $comcode_page_row, $raw_comcode)); } else { list($html, $title_to_use, $comcode_page_row, $raw_comcode) = $pcache; } } else { require_code('site2'); $new_comcode_page_row['p_add_date'] = filectime($file_base . '/' . $string); list($html, $comcode_page_row, $title_to_use, $raw_comcode) = _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_screen_title($title_to_use, false); // Little hack - this will force DISPLAYED_TITLE to get set. $filtered_title_to_use = strip_html($title_to_use); } seo_meta_load_for('comcode_page', $zone . ':' . $codename, $filtered_title_to_use); } $LAST_COMCODE_PARSED_TITLE = $title_to_use; if (($html->is_empty_shell()) && ($being_included || $is_panel)) { return $html; } if ((function_exists('has_edit_comcode_page_permission')) && (has_edit_comcode_page_permission($zone, $codename, $comcode_page_row['p_submitter']))) { $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), get_module_zone('admin_zones')); } else { $edit_url = build_url(array('page' => 'cms_comcode_pages', 'type' => '_edit', 'page_link' => $zone . ':' . $codename, /*'lang' => user_lang(), */'redirect' => $redirect), get_module_zone('cms_comcode_pages')); } } else { $edit_url = new Tempcode(); } $add_child_url = new Tempcode(); if (has_add_comcode_page_permission($zone)) { if (strpos($raw_comcode, 'main_comcode_page_children') !== false) { $add_child_url = (get_option('is_on_comcode_page_children') == '1') ? build_url(array('page' => 'cms_comcode_pages', 'type' => '_edit', 'parent_page' => $codename, 'page_link' => $zone . ':'/*Don't make too many assumptions about user flow , 'lang' => user_lang()*//*, 'redirect' => $redirect*/), get_module_zone('cms_comcode_pages')) : new Tempcode(); } } $warning_details = new Tempcode(); if (($comcode_page_row['p_validated'] !== null) && ($comcode_page_row['p_validated'] == 0) && (!$being_included)) { 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') : protect_from_escaping(escape_html($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_string('keep_page_root', ''), ($comcode_page_row['p_parent_page'] == '') || !has_privilege(get_member(), 'open_virtual_roots')); breadcrumb_set_parents($comcode_breadcrumbs); set_extra_request_metadata(array( 'title' => ($title_to_use == '') ? null : ('[semihtml]' . $title_to_use . '[/semihtml]'), 'identifier' => $zone . ':' . $codename, ), $comcode_page_row, 'comcode_page', $zone . ':' . $codename); } if (($GLOBALS['OUTPUT_STREAMING']) && ($out !== null)) { $GLOBALS['TEMPCODE_CURRENT_PAGE_OUTPUTTING'] = $out; $out->evaluate_echo(null, true); } 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_option('show_content_tagging') == '0') ? /*optimisation, can be intensive with many page includes*/ new Tempcode() : 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, 'NATIVE_ZONE' => $zone, )); if (($is_panel) || ($being_included)) { $SCREEN_TEMPLATE_CALLED = $st; } return $ret; } /** * Get a route from a known Comcode page back to the declared root of the tree. * * @param ID_TEXT $the_page The Comcode page name * @param ID_TEXT $the_zone The Comcode page zone * @param ID_TEXT $root The virtual root * @param boolean $no_link_for_me_sir Whether not to put a link at this point in the navigation tree (usually, because the viewer is already at it) * @param integer $jumps The number of jumps we have gone through so far (cuts out after 10 as a failsafe) * @return array The breadcrumbs */ function comcode_breadcrumbs($the_page, $the_zone, $root = '', $no_link_for_me_sir = true, $jumps = 0) { // Cut off broken recursion if ($jumps == 10) { return array(); // Probably a loop } if ($the_page == '') { return array(); } // Find link $map = array('page' => $the_page); if ($jumps == 0) { $map['keep_page_root'] = $the_page; } elseif ($root != '') { $map['keep_page_root'] = $root; } $page_link = build_page_link($map, $the_zone); // Find title global $PT_PAIR_CACHE_CP; if (!array_key_exists($the_page, $PT_PAIR_CACHE_CP)) { $test = _request_page__redirects($the_page, $the_zone); if ($test !== false) { $_the_page = $test[1]['r_to_page']; $_the_zone = $test[1]['r_to_zone']; } else { $_the_page = $the_page; $_the_zone = $the_zone; } $page_rows = $GLOBALS['SITE_DB']->query_select('cached_comcode_pages a 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'), array('a.the_page' => $_the_page, 'a.the_zone' => $_the_zone), '', 1, null, false, array('cc_page_title' => '?SHORT_TRANS')); if (!array_key_exists(0, $page_rows)) { global $DISPLAYED_TITLE; push_output_state(); $DISPLAYED_TITLE = new Tempcode(); request_page($the_page, false, $the_zone, null, true); // It's not cached, force the issue and then try again... $temp_title = $DISPLAYED_TITLE; restore_output_state(); $page_rows = $GLOBALS['SITE_DB']->query_select('cached_comcode_pages a 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'), array('a.the_page' => $_the_page, 'a.the_zone' => $_the_zone), '', 1, null, false, array('cc_page_title' => '?SHORT_TRANS')); if (!array_key_exists(0, $page_rows)) { // Oh well, fallback (maybe page doesn't exist yet, ?)... $PT_PAIR_CACHE_CP[$the_page] = array(); $PT_PAIR_CACHE_CP[$the_page]['cc_page_title'] = $temp_title->evaluate(); if ($PT_PAIR_CACHE_CP[$the_page]['cc_page_title'] == '') { $PT_PAIR_CACHE_CP[$the_page]['cc_page_title'] = $the_page; } $PT_PAIR_CACHE_CP[$the_page]['p_parent_page'] = ''; } } 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; } // End of recursion if ($the_page == $root) { if ($no_link_for_me_sir) { return array(); } return array(array($page_link, is_object($title) ? $title : protect_from_escaping(escape_html($title)))); } // Cut off broken recursion if ($PT_PAIR_CACHE_CP[$the_page]['p_parent_page'] == $the_page) { fatal_exit(do_lang_tempcode('RECURSIVE_TREE_CHAIN', escape_html($the_page), 'comcode_page')); } // Our point in the chain $segments = array(); if (!$no_link_for_me_sir) { $segments[] = array($page_link, is_object($title) ? $title : protect_from_escaping(escape_html($title)), ($jumps == 0) ? do_lang('VIRTUAL_ROOT') : ''); } else { if (!(((is_string($title)) && ($title == '')) || ((is_object($title)) && ($title->is_empty())))) { $segments[] = array('', is_object($title) ? $title : protect_from_escaping(escape_html($title))); } } // Further recursion $below = comcode_breadcrumbs($PT_PAIR_CACHE_CP[$the_page]['p_parent_page'], $the_zone, $root, false, $jumps + 1); return array_merge($below, $segments); } /** * Log statistics for the page view. * * @param string $string The string to the page file * @param integer $pg_time 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('stats_when_closed') == '0')) { return; } if ((get_option('super_logging') == '1') || (get_param_string('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(); $session_id = get_session_id(); global $IS_ACTUALLY; $member = ($IS_ACTUALLY === null) ? get_member() : $IS_ACTUALLY; $time = time(); $referer = cms_mb_substr(cms_srv('HTTP_REFERER'), 0, 255); $browser = cms_mb_substr(get_browser_string(), 0, 255); $os = cms_mb_substr(get_os_string(), 0, 255); if ($os === null) { $os = ''; } if ((get_option('bot_stats') == '1') && ((stripos($browser, 'http:') !== false) || (stripos($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, 'session_id' => $session_id, 'member_id' => $member, 'date_and_time' => $time, 'referer' => $referer, 's_get' => $get, 'post' => $post, 'milliseconds' => intval($pg_time), ), false, true); if (mt_rand(0, 100) == 1) { if (!$GLOBALS['SITE_DB']->table_is_locked('stats')) { $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'))), 500/*to reduce lock times*/); } } global $SITE_INFO; if (isset($SITE_INFO['throttle_bandwidth_views_per_meg'])) { if (!$GLOBALS['SITE_DB']->table_is_locked('values')) { set_value('page_views', strval(intval(get_value('page_views')) + 1)); } } } /* * * Output filter to compress HTML. * * @param string $data The HTML to filter * @return string Compressed HTML */ /*f unction _compress_html_output($data) { return preg_replace(array('#>[ \t]+#', '#[ \t]+<#', '#\n[ \t]+\r?\n#', '#\n+#'), array('> ', ' <', "\n", "\n"), $data); }*/