find_emoticons(); // Sorted in descending length order if ($GLOBALS['XSS_DETECT']) { $orig_escaped = ocp_is_escaped($text); } // Pre-check, optimisation $emoticons = array(); foreach ($_emoticons as $code => $imgcode) { if (is_integer($code)) { $code = strval($code); } if (strpos($text, $code) !== false) { $emoticons[$code] = $imgcode; } } if (count($emoticons) != 0) { $len = strlen($text); for ($i = 0; $i < $len; ++$i) { // Has to go through in byte order so double application cannot happen (i.e. emoticon contains [all or portion of] emoticon code somehow) $char = $text[$i]; if ($char == '"') { // This can cause severe HTML corruption so is a disallowed character $i++; continue; } foreach ($emoticons as $code => $imgcode) { $code_len = strlen($code); if (($char == $code[0]) && (substr($text, $i, $code_len) == $code)) { $eval = do_emoticon($imgcode); $_eval = $eval->evaluate(); if ($GLOBALS['XSS_DETECT']) { ocp_mark_as_escaped($_eval); } $before = substr($text, 0, $i); $after = substr($text, $i + $code_len); if (($before == '') && ($after == '')) { $text = $_eval; } else { $text = $before . $_eval . $after; } $len = strlen($text); $i += strlen($_eval) - 1; break; } } } if (($GLOBALS['XSS_DETECT']) && ($orig_escaped)) { ocp_mark_as_escaped($text); } } return $text; } /** * Turn a triple of emoticon parameters into some actual Tempcode. * * @param array $imgcode Parameter triple(template,src,code) * @return mixed Either a Tempcode result, or a string result, depending on $evaluate */ function do_emoticon($imgcode) { $tpl = do_template($imgcode[0], array('SRC' => $imgcode[1], 'EMOTICON' => $imgcode[2])); return $tpl; } /** * Check the specified URL for potentially malicious JavaScript/etc. If any is found, the hack attack is logged if in an active post request by the submitting member otherwise filtered out. * * @param MEMBER $source_member The member who submitted the URL * @param URLPATH $url The URL to check * @param boolean $as_admin Whether to check as arbitrary admin * @return URLPATH Filtered input URL. */ function check_naughty_javascript_url($source_member, $url, $as_admin) { init_potential_js_naughty_array(); global $POTENTIAL_JS_NAUGHTY_ARRAY; if ((!$as_admin) && (!has_privilege($source_member, 'use_very_dangerous_comcode'))) { $url2 = strtolower($url); $matches = array(); $bad = preg_match_all('#&\#(\d+)#', preg_replace('#\s#', '', $url), $matches) != 0; if ($bad) { for ($i = 0; $i < count($matches[0]); $i++) { $matched_entity = intval($matches[1][$i]); if (($matched_entity < 127) && (array_key_exists(chr($matched_entity), $POTENTIAL_JS_NAUGHTY_ARRAY))) { if ((count($_POST) != 0) && (get_member() == $source_member)) { log_hack_attack_and_exit('ASCII_ENTITY_URL_HACK', $url); } return ''; } } } $bad = preg_match_all('#&\#x([\dA-Za-z][\dA-Za-z]+)#', preg_replace('#\s#', '', $url), $matches) != 0; if ($bad) { for ($i = 0; $i < count($matches[0]); $i++) { $matched_entity = intval(base_convert($matches[1][$i], 16, 10)); if (($matched_entity < 127) && (array_key_exists(chr($matched_entity), $POTENTIAL_JS_NAUGHTY_ARRAY))) { if ((count($_POST) != 0) && (get_member() == $source_member)) { log_hack_attack_and_exit('ASCII_ENTITY_URL_HACK', $url); } return ''; } } } $bad = (strpos($url2, 'script:') !== false) || (strpos($url2, 'data:') !== false); if ($bad) { if ((count($_POST) != 0) && (get_member() == $source_member)) { log_hack_attack_and_exit('SCRIPT_URL_HACK', $url2); } return ''; } } return $url; } /** * Load up Custom Comcode tags so that we may parse them. * * @param object $connection The database connection to use * * @ignore */ function _custom_comcode_import($connection) { init_valid_comcode_tags(); global $IN_MINIKERNEL_VERSION; global $DANGEROUS_TAGS, $VALID_COMCODE_TAGS, $BLOCK_TAGS, $TEXTUAL_TAGS, $IMPORTED_CUSTOM_COMCODE, $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE; if ($IMPORTED_CUSTOM_COMCODE) { return; } if (!$IN_MINIKERNEL_VERSION) { // From forum driver if (method_exists($GLOBALS['FORUM_DRIVER'], 'get_custom_bbcode')) { $custom_bbcode = $GLOBALS['FORUM_DRIVER']->get_custom_bbcode(); foreach ($custom_bbcode as $code) { $code['tag'] = strtolower($code['tag']); $VALID_COMCODE_TAGS[$code['tag']] = true; if ($code['block_tag'] == 1) { $BLOCK_TAGS[$code['tag']] = true; } if ($code['textual_tag'] == 1) { $TEXTUAL_TAGS[$code['tag']] = true; } if ($code['dangerous_tag'] == 1) { $DANGEROUS_TAGS[$code['tag']] = true; } $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE[$code['tag']] = array('replace' => $code['replace'], 'parameters' => $code['parameters']); } } // From Custom Comcode $tags = array(); if (addon_installed('custom_comcode')) { if (is_on_multi_site_network()) { if (is_forum_db($connection)) { $from_db = $GLOBALS['SITE_DB']->query_select('custom_comcode', array('tag_parameters', 'tag_replace', 'tag_tag', 'tag_dangerous_tag', 'tag_block_tag', 'tag_textual_tag'), array('tag_enabled' => 1)); } elseif ((!is_null($GLOBALS['FORUM_DB'])) && (get_forum_type() == 'cns')) { $from_db = $GLOBALS['FORUM_DB']->query_select('custom_comcode', array('tag_parameters', 'tag_replace', 'tag_tag', 'tag_dangerous_tag', 'tag_block_tag', 'tag_textual_tag'), array('tag_enabled' => 1)); } else { $from_db = null; } if (is_array($from_db)) { $tags = array_merge($tags, $from_db); } } $tags = array_merge($tags, $connection->query_select('custom_comcode', array('tag_parameters', 'tag_replace', 'tag_tag', 'tag_dangerous_tag', 'tag_block_tag', 'tag_textual_tag'), array('tag_enabled' => 1))); } foreach ($tags as $tag) { $tag['tag_tag'] = strtolower($tag['tag_tag']); $VALID_COMCODE_TAGS[$tag['tag_tag']] = true; if ($tag['tag_block_tag'] == 1) { $BLOCK_TAGS[$tag['tag_tag']] = true; } if ($tag['tag_textual_tag'] == 1) { $TEXTUAL_TAGS[$tag['tag_tag']] = true; } if ($tag['tag_dangerous_tag'] == 1) { $DANGEROUS_TAGS[$tag['tag_tag']] = true; } $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE[$tag['tag_tag']] = array('replace' => $tag['tag_replace'], 'parameters' => $tag['tag_parameters']); } // From Comcode hooks $hooks = find_all_hooks('systems', 'comcode'); foreach ($hooks as $hook => $hook_dir) { require_code('hooks/systems/comcode/' . filter_naughty_harsh($hook), false, $hook_dir == 'sources_custom'); $object = object_factory('Hook_comcode_' . filter_naughty_harsh($hook), true); $tag = $object->get_tag(); $tag['tag_tag'] = strtolower($tag['tag_tag']); $VALID_COMCODE_TAGS[$tag['tag_tag']] = true; if ($tag['tag_block_tag'] == 1) { $BLOCK_TAGS[$tag['tag_tag']] = true; } if ($tag['tag_textual_tag'] == 1) { $TEXTUAL_TAGS[$tag['tag_tag']] = true; } if ($tag['tag_dangerous_tag'] == 1) { $DANGEROUS_TAGS[$tag['tag_tag']] = true; } $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE[$tag['tag_tag']] = array('replace' => $tag['tag_replace'], 'parameters' => $tag['tag_parameters']); } } $IMPORTED_CUSTOM_COMCODE = true; } /** * Convert the specified Comcode (unknown format) into a Tempcode tree. You shouldn't output the Tempcode tree to the browser, as it looks really horrible. If you are in a rare case where you need to output directly (not through templates), you should call the evaluate method on the Tempcode object, to convert it into a string. * * @param LONG_TEXT $comcode The Comcode to convert * @param ?MEMBER $source_member The member the evaluation is running as. This is a security issue, and you should only run as an administrator if you have considered where the Comcode came from carefully (null: current member) * @param boolean $as_admin Whether to explicitly execute this with admin rights. There are a few rare situations where this should be done, for data you know didn't come from a member, but is being evaluated by one. * @param ?integer $wrap_pos The position to conduct wordwrapping at (null: do not conduct word-wrapping) * @param ?string $pass_id A special identifier that can identify this resource in a sea of our resources of this class; usually this can be ignored, but may be used to provide a binding between JavaScript in evaluated Comcode, and the surrounding environment (null: no explicit binding) * @param ?object $connection The database connection to use (null: standard site connection) * @param boolean $semiparse_mode Whether to parse so as to create something that would fit inside a semihtml tag. It means we generate HTML, with Comcode written into it where the tag could never be reverse-converted (e.g. a block). * @param boolean $preparse_mode Whether this is being pre-parsed, to pick up errors before row insertion. * @param boolean $is_all_semihtml Whether to treat this whole thing as being wrapped in semihtml, but apply normal security otherwise. * @param boolean $structure_sweep Whether we are only doing this parse to find the title structure * @param boolean $check_only Whether to only check the Comcode. It's best to use the check_comcode function which will in turn use this parameter. * @param ?array $highlight_bits A list of words to highlight (null: none) * @param ?MEMBER $on_behalf_of_member The member we are running on behalf of, with respect to how attachments are handled; we may use this members attachments that are already within this post, and our new attachments will be handed to this member (null: member evaluating) * @return Tempcode The Tempcode generated * * @ignore */ function _comcode_to_tempcode($comcode, $source_member = null, $as_admin = false, $wrap_pos = null, $pass_id = null, $connection = null, $semiparse_mode = false, $preparse_mode = false, $is_all_semihtml = false, $structure_sweep = false, $check_only = false, $highlight_bits = null, $on_behalf_of_member = null) { if (has_interesting_post_fields()) { disable_browser_xss_detection(); } if (is_null($connection)) { $connection = $GLOBALS['SITE_DB']; } if (is_null($source_member)) { $source_member = (function_exists('get_member')) ? get_member() : 0; } if (!$structure_sweep) { $comcode = unixify_line_format($comcode); // Done already if this is a structure sweep } // Ensures the 'title' tags are incremental with their anchors global $STRUCTURE_LIST; $old_structure_list = $STRUCTURE_LIST; $STRUCTURE_LIST = array(); $comcode = convert_guids_to_ids($comcode); require_code('comcode_compiler'); $ret = __comcode_to_tempcode($comcode, $source_member, $as_admin, $wrap_pos, $pass_id, $connection, $semiparse_mode, $preparse_mode, $is_all_semihtml, $structure_sweep, $check_only, $highlight_bits, $on_behalf_of_member); $STRUCTURE_LIST = $old_structure_list; // Restore, so that Comcode pages being loaded up in search results don't get skewed TOC's return $ret; } /** * Show a Comcode parser error. * * @param boolean $preparse_mode Whether this is being pre-parsed, to pick up errors before row insertion. * @param array $_message Error message details to pass to do_lang, or if the first in the list is null, use directly * @param integer $pos The position during parsing that the error occurred at * @param LONG_TEXT $comcode The Comcode the parser error occurred in * @param boolean $check_only Whether to only check the Comcode. * @return Tempcode An error message to put in the output stream (shown in certain situations, where in other situations we bomb out). */ function comcode_parse_error($preparse_mode, $_message, $pos, $comcode, $check_only = false) { require_lang('comcode'); if (is_null($_message[0])) { $message = $_message[1]; } else { if (strpos($_message[0], ':') === false) { $_message[0] = 'comcode:' . $_message[0]; } $message = call_user_func_array('do_lang_tempcode', array_map('escape_html', $_message)); } require_code('failure'); if (throwing_errors()) { throw new CMSException($message); } $posted = false; foreach ($_POST + $_GET as $name => $val) { if (is_array($val)) { continue; } if (is_integer($name)) { $name = strval($name); } if ((post_param_string($name, '') == $comcode) || (substr($name, -7) == '_parsed')) { $posted = true; } } if (!$check_only) { if (((get_mass_import_mode()) || (!has_interesting_post_fields()) || (!$posted)) && (!$preparse_mode)) { $line = substr_count(substr($comcode, 0, $pos), "\n") + 1; $out = do_template('COMCODE_CRITICAL_PARSE_ERROR', array('_GUID' => '29da9dc5c6b9a527cb055b7da35bb6b8', 'LINE' => integer_format($line), 'MESSAGE' => $message, 'SOURCE' => $comcode)); // Won't parse, but we can't help it, so we will skip on return $out; } } $len = strlen($comcode); $lines = new Tempcode(); $number = 1; $sofar = ''; $line = null; for ($i = 0; $i < $len; $i++) { $char = $comcode[$i]; if ($i == $pos) { $tmp_tpl = do_template('COMCODE_MISTAKE_ERROR'); $sofar .= $tmp_tpl->evaluate(); $line = $number; } if ($char == "\n") { $lines->attach(do_template('COMCODE_MISTAKE_LINE', array('_GUID' => '2022be3de10590d525f333b6ac0da37b', 'NUMBER' => integer_format($number), 'LINE' => make_string_tempcode($sofar)))); $sofar = ''; $number++; } $sofar .= escape_html($char); } if ($i == $pos) { $tmp_tpl = do_template('COMCODE_MISTAKE_ERROR'); $sofar .= $tmp_tpl->evaluate(); } $lines->attach(do_template('COMCODE_MISTAKE_LINE', array('_GUID' => 'eebfe1342f3129d4e31fc9fc1963af2b', 'NUMBER' => integer_format($number), 'LINE' => make_string_tempcode($sofar)))); if (is_null($line)) { $line = $number; } // Now, using some kind of miracle, we need to find out what parameter name blew-up. Let's look through the parameters and see what // is equal to $comcode. I'd rather not do this in a hackerish way - but the architecture was not designed for this. $name = null; foreach ($_POST as $key => $val) { if (!is_string($val)) { continue; } if (post_param_string($key) == $comcode) { // We have to use post_param_string, because it might be unix-converted / word-filtered $name = $key; break; } } if (is_null($name)) { if ($check_only) { // Maybe it has been appended with something else, so search deeper (we suspect this as we have been explicitly asked to check the Comcode) foreach ($_POST as $key => $val) { if (!is_string($val)) { continue; } $val = post_param_string($key); if ((strlen($val) > 10) && ((strpos($comcode, $val) === 0) || (strpos($comcode, $val) === strlen($comcode) - strlen($val)))) { $name = $key; break; } } } if (is_null($name)) { warn_exit(do_lang_tempcode('COMCODE_ERROR', $message, escape_html(integer_format($line)))); } } if (!running_script('comcode_convert')) { // Don't want it running in background set_http_status_code('400'); } set_helper_panel_text(new Tempcode()); // Output our error / correction form cms_ob_end_clean(); // Emergency output, potentially, so kill off any active buffer $hidden = build_keep_post_fields(array($name)); require_code('form_templates'); $fields = form_input_huge_comcode(do_lang_tempcode('FIXED_COMCODE'), do_lang_tempcode('COMCODE_REPLACEMENT'), $name, $comcode, true, null, 20, null, null, false, true); $post_url = get_self_url(false, false, array('_corrected_comcode' => '1')); $form = do_template('FORM', array('_GUID' => '207bad1252add775029b34ba36e02856', 'URL' => $post_url, 'TEXT' => '', 'HIDDEN' => $hidden, 'FIELDS' => $fields, 'SUBMIT_ICON' => 'buttons__proceed', 'SUBMIT_NAME' => do_lang_tempcode('PROCEED'), 'SKIP_REQUIRED' => true, 'MODSECURITY_WORKAROUND' => true)); $output = do_template('COMCODE_MISTAKE_SCREEN', array('_GUID' => '0010230e6612b0775566d07ddf54305a', 'EDITABLE' => !running_script('preview'), 'FORM' => $form, 'TITLE' => get_screen_title('ERROR_OCCURRED'), 'LINE' => integer_format($line), 'MESSAGE' => $message, 'LINES' => $lines)); $echo = globalise($output, null, '', true); $echo->handle_symbol_preprocessing(); $echo->evaluate_echo(null, true); exit(); } /** * Make a given URL parameter an absolute URL; Fix any errors in it; Test it. * * @param URLPATH $given_url URL to fixup. * @param MEMBER $source_member The member who is responsible for this Comcode * @param boolean $as_admin Whether to check as arbitrary admin * @param ID_TEXT $tag Comcode tag name. * @return URLPATH Fixed URL. */ function absoluteise_and_test_comcode_url($given_url, $source_member, $as_admin, $tag) { $url = $given_url; require_code('urls2'); $url = remove_url_mistakes($url); $url = check_naughty_javascript_url($source_member, $url, $as_admin); if (url_is_local($url)) { if (substr($url, 0, 1) == '/') { $url = substr($url, 1); } if ((file_exists(get_file_base() . '/' . $url)) && (!file_exists(get_custom_file_base() . '/' . $url))) { $url = get_base_url() . '/' . $url; } else { $url = get_custom_base_url() . '/' . $url; } } $temp_tpl = test_url($url, $tag, $given_url, $source_member); return $url; } /** * Test a URL as a broken link. * * @param URLPATH $url_full URL to test. * @param string $tag_type Comcode tag type, to which the URL is associated. * @param string $given_url URL actually provided. * @param MEMBER $source_member The member who is responsible for this Comcode * @return Tempcode Error message, or blank if no error. */ function test_url($url_full, $tag_type, $given_url, $source_member) { if (get_option('check_broken_urls') == '0') { return new Tempcode(); } if (strpos($url_full, '{$') !== false) { return new Tempcode(); } if (substr($url_full, 0, 1) == '#') { return new Tempcode(); } // Exceptions that we don't want to check (typically things we use by default) if (in_array($url_full, array( 'https://search.google.com/search-console/welcome', ))) { return new Tempcode(); } global $COMCODE_PARSE_URLS_CHECKED, $HTTP_MESSAGE, $COMCODE_BROKEN_URLS, $DONT_CARE_MISSING_PAGES; $temp_tpl = new Tempcode(); require_code('global4'); if (!handle_has_checked_recently($url_full)) { $COMCODE_PARSE_URLS_CHECKED++; if ($COMCODE_PARSE_URLS_CHECKED >= MAX_URLS_TO_READ) { $test = ''; } else { $test = http_download_file($url_full, 0, false); if (($test === null) && ($GLOBALS['HTTP_MESSAGE'] == '403')) { $test = http_download_file($url_full, 1, false); // Try without HEAD, sometimes it's not liked } } if ((is_null($test)) && (in_array($HTTP_MESSAGE, array('404')))) { if ($HTTP_MESSAGE != 'could not connect to host'/*don't show for random connectivity issue*/) { $temp_tpl = do_template('WARNING_BOX', array( '_GUID' => '7bcea67226f89840394614d88020e3ac', 'RESTRICT_VISIBILITY' => strval($source_member), //'INLINE' => true, Looks awful 'WARNING' => do_lang_tempcode('MISSING_URL_COMCODE', escape_html($tag_type), escape_html($url_full)), )); } if (isset($COMCODE_BROKEN_URLS)) { $COMCODE_BROKEN_URLS[] = array($url_full, null); } elseif ((!in_array(get_page_name(), $DONT_CARE_MISSING_PAGES)) && (running_script('index'))) { $found_in_post = false; // We don't want to send email if someone's just posting it right now, because they'll see the error on their screen, and we don't want staff spammed by member mistakes foreach ($_POST as $val) { if (is_array($_POST)) { continue; } if (@get_magic_quotes_gpc()) { $val = stripslashes($val); } if ((is_string($val)) && (strpos($val, $given_url) !== false)) { $found_in_post = true; } } if (!$found_in_post) { require_code('failure'); relay_error_notification( do_lang('MISSING_URL_COMCODE', $tag_type, $url_full), false, $GLOBALS['FORUM_DRIVER']->is_staff($source_member) ? 'error_occurred_missing_reference_important' : 'error_occurred_missing_reference' ); } } } } return $temp_tpl; } /** * Get Tempcode for a Comcode tag. This function should always return (errors should be placed in the Comcode output stream), for stability reasons (i.e. if you're submitting something, you can't have the whole submit process die half way through in an unstructured fashion). * * @param string $tag The tag being converted * @param array $attributes A map of the attributes (name=>val) for the tag. Val is usually a string, although in select places, the XML parser may pass Tempcode. * @param mixed $embed Tempcode of the inside of the tag ([between]THIS[/between]); the XML parser may pass in special stuff here, which is interpreted only for select tags * @param boolean $comcode_dangerous Whether we are allowed to proceed even if this tag is marked as 'dangerous' * @param string $pass_id A special identifier to mark where the resultant Tempcode is going to end up (e.g. the ID of a post) * @param integer $marker The position this tag occurred at in the Comcode * @param MEMBER $source_member The member who is responsible for this Comcode * @param boolean $as_admin Whether to check as arbitrary admin * @param object $connection The database connection to use * @param string $comcode The whole chunk of Comcode * @param boolean $structure_sweep Whether this is only a structure sweep * @param boolean $semiparse_mode Whether we are in semi-parse-mode (some tags might convert differently) * @param ?array $highlight_bits A list of words to highlight (null: none) * @param ?MEMBER $on_behalf_of_member The member we are running on behalf of, with respect to how attachments are handled; we may use this members attachments that are already within this post, and our new attachments will be handed to this member (null: member evaluating) * @param boolean $in_semihtml Whether what we have came from inside a semihtml tag * @param boolean $is_all_semihtml Whether what we have came from semihtml mode * @param boolean $html_errors Whether HTML structure errors have been spotted so far (limits how $semiparse_mode rendering works) * @return Tempcode The Tempcode for the Comcode * * @ignore */ function _do_tags_comcode($tag, $attributes, $embed, $comcode_dangerous, $pass_id, $marker, $source_member, $as_admin, $connection, &$comcode, $structure_sweep, $semiparse_mode, $highlight_bits = null, $on_behalf_of_member = null, $in_semihtml = false, $is_all_semihtml = false, $html_errors = false) { if (($structure_sweep) && ($tag != 'title')) { return new Tempcode(); } $param_given = isset($attributes['param']); if ((!isset($attributes['param'])) && ($tag != 'block')) { $attributes['param'] = ''; } // No permission global $DANGEROUS_TAGS, $STRUCTURE_LIST, $COMCODE_PARSE_TITLE; if ((isset($DANGEROUS_TAGS[$tag])) && (!$comcode_dangerous)) { $username = $GLOBALS['FORUM_DRIVER']->get_username($source_member); if (is_null($username)) { $username = do_lang('UNKNOWN'); } if ($semiparse_mode) { // Can't load through error for this, so just show it as a tag return make_string_tempcode(add_wysiwyg_comcode_markup($tag, $attributes, $embed, ($in_semihtml) || ($is_all_semihtml), WYSIWYG_COMCODE__STANDOUT_BLOCK, $html_errors)); } return do_template('WARNING_BOX', array( '_GUID' => 'faea04a9d6f1e409d99b8485d28b2225', 'RESTRICT_VISIBILITY' => strval($source_member), 'WARNING' => do_lang_tempcode('comcode:NO_ACCESS_FOR_TAG', escape_html($tag), escape_html($username)), )); } // These are just for convenience.. we will remap to more formalised Comcode elseif ($tag == 'codebox') { $attributes['scroll'] = '1'; $tag = 'code'; } elseif ($tag == 'left') { $attributes['param'] = 'left'; $tag = 'align'; } elseif ($tag == 'center') { $attributes['param'] = 'center'; $tag = 'align'; } elseif ($tag == 'right') { $attributes['param'] = 'right'; $tag = 'align'; } if ($semiparse_mode) { // We have got to this point because we want to provide a special 'button' editing representation for these tags $eval = $embed->evaluate(); if (strpos($eval, '<') !== false) { $html_errors = false; $xml_tag_stack = array(); $matches = array(); $num_matches = preg_match_all('#<(/)?([^\s<>]*)(\s[^<>]*)?' . '>#', $eval, $matches); for ($i = 0; $i < $num_matches; $i++) { $xml_tag = $matches[2][$i]; if (substr(trim($matches[3][$i]), -1) == '/') { continue; // self-closing } if ($matches[1][$i] == '/') { $expected_xml_tag = array_pop($xml_tag_stack); if ($xml_tag !== $expected_xml_tag) { $html_errors = true; } } else { array_push($xml_tag_stack, $xml_tag); } } if (count($xml_tag_stack) > 0) { $html_errors = true; } } if (wysiwyg_comcode_markup_style($tag, $attributes, $embed, $html_errors) != WYSIWYG_COMCODE__HTML) { $_temp_tpl = add_wysiwyg_comcode_markup($tag, $attributes, $embed, ($in_semihtml) || ($is_all_semihtml), null, $html_errors); if ($_temp_tpl !== null) { $temp_tpl = make_string_tempcode($_temp_tpl); return $temp_tpl; } } } $temp_tpl = new Tempcode(); switch ($tag) { case 'no_parse': $temp_tpl->attach($embed); break; // Undocumented, used to inject dependencies in things like logged e-mail Comcode or notification Comcode, without needing access-restricted Tempcode case 'require_css': $_embed = $embed->evaluate(); if ($_embed != '') { $temp_tpl = new Tempcode(); foreach (explode(',', $_embed) as $css) { if ($css != '') { $temp_tpl->attach(symbol_tempcode('REQUIRE_CSS', array($css))); } } } break; case 'require_javascript': $_embed = $embed->evaluate(); if ($_embed != '') { $temp_tpl = new Tempcode(); foreach (explode(',', $_embed) as $javascript) { if ($javascript != '') { $temp_tpl->attach(symbol_tempcode('REQUIRE_JAVASCRIPT', array($javascript))); } } } break; case 'currency': if (addon_installed('ecommerce')) { $bracket = (array_key_exists('bracket', $attributes) && ($attributes['bracket'] == '1')); if ($attributes['param'] == '') { $attributes['param'] = get_option('currency'); } $temp_tpl = do_template('COMCODE_CURRENCY', array('_GUID' => 'ee1fcdae082af6397ff3bad89006e012', 'AMOUNT' => $embed, 'FROM_CURRENCY' => $attributes['param'], 'BRACKET' => $bracket)); } break; case 'overlay': $x = strval(array_key_exists('x', $attributes) ? intval($attributes['x']) : 100); $y = strval(array_key_exists('y', $attributes) ? intval($attributes['y']) : 100); $width = strval(array_key_exists('width', $attributes) ? intval($attributes['width']) : 300); $height = strval(array_key_exists('height', $attributes) ? intval($attributes['height']) : 300); $timein = strval(array_key_exists('timein', $attributes) ? intval($attributes['timein']) : 0); $timeout = strval(array_key_exists('timeout', $attributes) ? intval($attributes['timeout']) : -1); $temp_tpl = do_template('COMCODE_OVERLAY', array('_GUID' => 'dfd0f7a72cc2bf6b613b28f8165a0034', 'EMBED' => $embed, 'ID' => ($attributes['param'] != '') ? $attributes['param'] : ('rand' . uniqid('', true)), 'X' => $x, 'Y' => $y, 'WIDTH' => $width, 'HEIGHT' => $height, 'TIMEIN' => $timein, 'TIMEOUT' => $timeout)); break; case 'code': list($_embed, $title) = do_code_box($attributes['param'], $embed, (array_key_exists('numbers', $attributes)) && ($attributes['numbers'] == '1'), $in_semihtml, $is_all_semihtml); if (!is_null($_embed)) { $tpl = (array_key_exists('scroll', $attributes) && ($attributes['scroll'] == '1')) ? 'COMCODE_CODE_SCROLL' : 'COMCODE_CODE'; if (($tpl == 'COMCODE_CODE_SCROLL') && (substr_count($_embed, "\n") < 10)) { $style = 'height: auto'; } else { $style = ''; } $temp_tpl = do_template($tpl, array('_GUID' => 'c5d46d0927272fcacbbabcfab0ef6b0c', 'STYLE' => $style, 'TYPE' => $attributes['param'], 'CONTENT' => $_embed, 'TITLE' => $title)); } else { $_embed = ''; } if ($temp_tpl->is_empty()) { $_embed = $embed->evaluate(); if ((!array_key_exists('scroll', $attributes)) && (cms_mb_strlen($_embed) > 1000)) { $attributes['scroll'] = '1'; } $tpl = (array_key_exists('scroll', $attributes) && ($attributes['scroll'] == '1')) ? 'COMCODE_CODE_SCROLL' : 'COMCODE_CODE'; if (($tpl == 'COMCODE_CODE_SCROLL') && (substr_count($_embed, "\n") < 10)) { $style = 'height: auto'; } else { $style = ''; } $temp_tpl = do_template($tpl, array('CONTENT' => $_embed, 'TITLE' => $title, 'STYLE' => $style, 'TYPE' => $attributes['param'])); } break; case 'list': if (is_array($embed)) { $parts = $embed; } else { $_embed = trim($embed->evaluate()); $_embed = str_replace('[/*]', '', $_embed); $parts = explode('[*]', $_embed); } if (isset($temp_tpl->preprocessable_bits)) { $temp_tpl->preprocessable_bits = array_merge($temp_tpl->preprocessable_bits, $embed->preprocessable_bits); } $type = $attributes['param']; if ($type != '') { if ($type == '1') { $type = 'decimal'; } elseif ($type == 'a') { $type = 'lower-alpha'; } elseif ($type == 'i') { $type = 'lower-roman'; } elseif ($type == 'x') { $type = 'none'; } elseif (!in_array($type, array('circle', 'disc', 'square', 'armenian', 'decimal', 'decimal-leading-zero', 'georgian', 'lower-alpha', 'lower-greek', 'lower-latin', 'lower-roman', 'upper-alpha', 'upper-latin', 'upper-roman'))) { $type = 'disc'; } $tag = in_array($type, array('circle', 'disc', 'square')) ? 'ul' : 'ol'; $temp_tpl->attach('<' . $tag . ' style="list-style-type: ' . $type . '">'); foreach ($parts as $i => $part) { if (($i == 0) && (cms_trim($part, true) == '')) { continue; } $temp_tpl->attach('
  • ' . cms_trim($part, true) . '
  • '); } $temp_tpl->attach(''); } else { $temp_tpl->attach(''); } break; case 'snapback': $post_id = intval($embed->evaluate()); $_date = mixed(); if (get_forum_type() == 'cns') { $_date = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_posts', 'p_time', array('id' => $post_id)); } $s_title = mixed(); if ($attributes['param'] == '') { if (get_forum_type() == 'cns') { $_s_title = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_posts', 'p_title', array('id' => $post_id)); if ($_s_title != '') { $forum_id = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_posts', 'p_cache_forum_id', array('id' => $post_id)); if ((!is_null($forum_id)) && (has_category_access($source_member, 'forums', strval($forum_id)))) { $s_title = make_string_tempcode($_s_title); } } } if ($s_title === null) { $s_title = do_lang_tempcode('cns:FORUM_POST_NUMBERED', escape_html(integer_format($post_id))); } } else { $s_title = make_string_tempcode($attributes['param']); } $forum = array_key_exists('forum', $attributes) ? $attributes['forum'] : ''; $temp_tpl = do_template('COMCODE_SNAPBACK', array( '_GUID' => 'af7b6920e58027256d536a8cdb8a164a', 'URL' => $GLOBALS['FORUM_DRIVER']->post_url($post_id, $forum, true), 'TITLE' => $s_title, 'DATE' => is_null($_date) ? null : get_timezoned_date($_date, true, false, false, true), '_DATE' => is_null($_date) ? null : strval($_date), 'POST_ID' => strval($post_id), )); break; case 'post': $post_id = intval($embed->evaluate()); $s_title = ($attributes['param'] == '') ? do_lang_tempcode('cns:FORUM_POST_NUMBERED', escape_html(integer_format($post_id))) : escape_html($attributes['param']); $forum = array_key_exists('forum', $attributes) ? $attributes['forum'] : ''; $temp_tpl->attach(hyperlink($GLOBALS['FORUM_DRIVER']->post_url($post_id, $forum, true), $s_title, false, false)); break; case 'topic': $topic_id = intval($embed->evaluate()); $s_title = ($attributes['param'] == '') ? do_lang_tempcode('cns:FORUM_TOPIC_NUMBERED', escape_html(integer_format($topic_id))) : escape_html($attributes['param']); $forum = array_key_exists('forum', $attributes) ? $attributes['forum'] : ''; $temp_tpl->attach(hyperlink($GLOBALS['FORUM_DRIVER']->topic_url($topic_id, $forum, true), $s_title, false, false)); break; case 'staff_note': $temp_tpl = new Tempcode(); return $temp_tpl; case 'section': $name = (array_key_exists('param', $attributes)) ? $attributes['param'] : ('section' . strval(mt_rand(0, 100))); $default = (array_key_exists('default', $attributes)) ? $attributes['default'] : '0'; $temp_tpl = do_template('COMCODE_SECTION', array('_GUID' => 'a902962ccdc80046c999d6fed907d105', 'PASS_ID' => 'x' . $pass_id, 'DEFAULT' => $default == '1', 'NAME' => $name, 'CONTENT' => $embed)); break; case 'section_controller': $sections = explode(',', $embed->evaluate()); $temp_tpl = do_template('COMCODE_SECTION_CONTROLLER', array('_GUID' => '133bf24892e9e3ec2a01146d6ec418fe', 'SECTIONS' => $sections, 'PASS_ID' => 'x' . $pass_id)); break; case 'big_tab': $name = (array_key_exists('param', $attributes)) ? $attributes['param'] : ('big_tab' . strval(mt_rand(0, 100))); $default = (array_key_exists('default', $attributes)) ? $attributes['default'] : '0'; $temp_tpl = do_template('COMCODE_BIG_TABS_TAB', array('_GUID' => 'f6219b1acd6999acae770da20b95fb99', 'PASS_ID' => 'x' . $pass_id, 'DEFAULT' => $default == '1', 'NAME' => $name, 'CONTENT' => $embed)); break; case 'big_tab_controller': $tabs = explode(',', $embed->evaluate()); if (!array_key_exists('switch_time', $attributes)) { $attributes['switch_time'] = '6000'; } $temp_tpl = do_template('COMCODE_BIG_TABS_CONTROLLER', array('_GUID' => 'b6cc1835b688f086e34837e3c345ba0a', 'SWITCH_TIME' => ($attributes['switch_time'] == '' || intval($attributes['switch_time']) <= 0) ? null : strval(intval($attributes['switch_time'])), 'TABS' => $tabs, 'PASS_ID' => 'x' . $pass_id)); break; case 'tab': $default = (array_key_exists('default', $attributes)) ? $attributes['default'] : '0'; $is_page_link = preg_match('#^\s*[' . URL_CONTENT_REGEXP . ']*(:[^\s\n]+)+\s*$#', $embed->evaluate()) != 0; $temp_tpl = do_template('COMCODE_TAB_BODY', array( '_GUID' => '2d63ed21f8d8b939b8db21b20c147b41', 'DEFAULT' => $default == '1', 'TITLE' => trim($attributes['param']), 'CONTENT' => $is_page_link ? null : $embed, 'PAGE_LINK' => $is_page_link ? $embed : null, )); break; case 'tabs': $heads = new Tempcode(); $tabs = explode(',', $attributes['param']); foreach ($tabs as $i => $tab) { $heads->attach(do_template('COMCODE_TAB_HEAD', array('_GUID' => '735f70b1c8dcc78a0876136cfb4822a0', 'TITLE' => trim($tab), 'FIRST' => $i == 0, 'LAST' => !array_key_exists($i + 1, $tabs)))); } $temp_tpl = do_template('COMCODE_TAB_CONTROLLER', array('_GUID' => '0e56cf180973c57f3633aae54dd9cddc', 'HEADS' => $heads, 'CONTENT' => $embed)); break; case 'carousel': if ($attributes['param'] == '') { $attributes['param'] = '40'; } $temp_tpl = do_template('COMCODE_CAROUSEL', array('_GUID' => '2d0a327a6cb60e3168a5022eb0cfba9a', 'CONTENT' => $embed, 'SCROLL_AMOUNT' => $attributes['param'])); break; case 'menu': $name = (array_key_exists('param', $attributes)) ? $attributes['param'] : ('mnu' . strval(mt_rand(0, 100))); $type = (array_key_exists('type', $attributes)) ? $attributes['type'] : 'tree'; require_code('menus'); require_code('menus_comcode'); $temp_tpl = build_comcode_menu($embed->evaluate(), $name, $source_member, $type); break; case 'if_in_group': $groups = ''; $_groups = explode(',', $attributes['param']); $all_groups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(); foreach ($_groups as $group) { $not = (substr($group, 0, 1) == '!'); if ($not) { $group = substr($group, 1); } $find = array_search($group, $all_groups); if ($find === false) { if ($groups != '') { $groups .= ','; } if ($not) { $groups .= '!'; } $groups .= $group; } else { if ($groups != '') { $groups .= ','; } if ($not) { $groups .= '!'; } $groups .= strval($find); } } $temp_tpl = do_template('COMCODE_IF_IN_GROUP', array('_GUID' => '761a7cc07f7b4b68508d68ce19b87d2c', 'TYPE' => array_key_exists('type', $attributes) ? $attributes['type'] : '', 'CONTENT' => $embed, 'GROUPS' => $groups)); break; case 'acronym': case 'abbr': $temp_tpl = do_template('COMCODE_ABBR', array('_GUID' => 'acbc4f991dsf03f81b61919b74ac24c91', 'CONTENT' => $embed, 'TITLE' => $attributes['param'])); break; case 'address': $temp_tpl = do_template('COMCODE_ADDRESS', array('_GUID' => 'acbcsdf9910703f81b61919b74ac24c91', 'CONTENT' => $embed)); break; case 'dfn': $temp_tpl = do_template('COMCODE_DFN', array('_GUID' => 'acbc4f9910703f81b61sf19b74ac24c91', 'CONTENT' => $embed)); break; case 'pulse': $min_color = array_key_exists('min', $attributes) ? $attributes['min'] : '0000FF'; $max_color = array_key_exists('max', $attributes) ? $attributes['max'] : 'FF0044'; if (substr($min_color, 0, 1) == '#') { $min_color = substr($min_color, 1); } if (substr($max_color, 0, 1) == '#') { $max_color = substr($max_color, 1); } $speed = ($attributes['param'] == '') ? 100 : intval($attributes['param']); $temp_tpl = do_template('COMCODE_PULSE', array('_GUID' => 'adsd4f9910sfd03f81b61919b74ac24c91', 'CONTENT' => $embed, 'MIN_COLOR' => $min_color, 'MAX_COLOR' => $max_color, 'SPEED' => strval($speed))); break; case 'del': $cite = array_key_exists('cite', $attributes) ? $attributes['cite'] : null; if (!is_null($cite)) { $temp_tpl = test_url($cite, 'del', $cite, $source_member); } $datetime = array_key_exists('datetime', $attributes) ? $attributes['datetime'] : null; $temp_tpl->attach(do_template('COMCODE_DEL', array('_GUID' => 'acsd4f9910sfd03f81b61919b74ac24c91', 'CONTENT' => $embed, 'CITE' => $cite, 'DATETIME' => $datetime))); break; case 'ins': $cite = array_key_exists('cite', $attributes) ? $attributes['cite'] : null; if (!is_null($cite)) { $temp_tpl = test_url($cite, 'ins', $cite, $source_member); if (!$temp_tpl->is_empty()) { break; } } $datetime = array_key_exists('datetime', $attributes) ? $attributes['datetime'] : null; $temp_tpl->attach(do_template('COMCODE_INS', array('_GUID' => 'asss4f9910703f81b61919bsfc24c91', 'CONTENT' => $embed, 'CITE' => $cite, 'DATETIME' => $datetime))); break; case 'cite': $temp_tpl = do_template('COMCODE_CITE', array('_GUID' => 'acbcsf910703f81b61919b74ac24c91', 'CONTENT' => $embed)); break; case 'b': if ($semiparse_mode) { $temp_tpl = make_string_tempcode('' . $embed->evaluate() . ''); break; } $temp_tpl = do_template('COMCODE_BOLD', array('_GUID' => 'acbc4fds910703f81b619sf74ac24c91', 'CONTENT' => $embed)); break; case 'align': $align = array_key_exists('param', $attributes) ? $attributes['param'] : 'left'; $temp_tpl = do_template('COMCODE_ALIGN', array('_GUID' => '950b4d9db12cac6bf536860bedd96a36', 'ALIGN' => $align, 'CONTENT' => $embed)); break; case 'indent': $indent = array_key_exists('param', $attributes) ? $attributes['param'] : '10'; if (!is_numeric($indent)) { $indent = '10'; } $temp_tpl = do_template('COMCODE_INDENT', array('_GUID' => 'd8e69fa17eebd5312e3ad5788e3a1343', 'INDENT' => $indent, 'CONTENT' => $embed)); break; case 'surround': if (($semiparse_mode) && ($embed->evaluate() == '')) { // This is probably some signal like a break, so show it in Comcode form $temp_tpl = make_string_tempcode(add_wysiwyg_comcode_markup($tag, $attributes, $embed, ($in_semihtml) || ($is_all_semihtml), WYSIWYG_COMCODE__STANDOUT_BLOCK, $html_errors)); break; } $class = (array_key_exists('param', $attributes) && ($attributes['param'] != '')) ? $attributes['param'] : 'float_surrounder'; $style = array_key_exists('style', $attributes) ? $attributes['style'] : null; if (!$comcode_dangerous) { $style = null; } $temp_tpl = do_template('COMCODE_SURROUND', array('_GUID' => 'e8e69fa17eebd5312e3ad5788e3a1343', 'STYLE' => $style, 'CLASS' => $class, 'CONTENT' => $embed)); break; case 'i': if ($semiparse_mode) { $temp_tpl = make_string_tempcode('' . $embed->evaluate() . ''); break; } $temp_tpl = do_template('COMCODE_ITALICS', array('_GUID' => '4321a1fe3825418e57a29410183c0c60', 'CONTENT' => $embed)); break; case 'u': if ($semiparse_mode) { $temp_tpl = make_string_tempcode('' . $embed->evaluate() . ''); break; } $temp_tpl = do_template('COMCODE_UNDERLINE', array('_GUID' => '69cc8e73b17f9e6a35eb1af2bd1dc6ab', 'CONTENT' => $embed)); break; case 's': if ($semiparse_mode) { $temp_tpl = make_string_tempcode('' . $embed->evaluate() . ''); break; } $temp_tpl = do_template('COMCODE_STRIKE', array('_GUID' => 'ed242591cefd365497cc0c63abbb11a9', 'CONTENT' => $embed)); break; case 'tooltip': $param = comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $temp_tpl = do_template('COMCODE_TOOLTIP', array('_GUID' => 'c9f4793dc0c1a92cd7d08ae1b87c2308', 'URL' => array_key_exists('url', $attributes) ? $attributes['url'] : '', 'TOOLTIP' => $param, 'CONTENT' => $embed)); break; case 'sup': $temp_tpl = do_template('COMCODE_SUP', array('_GUID' => '74d2ecfe193dacb6d922bc288828196a', 'CONTENT' => $embed)); break; case 'sub': $temp_tpl = do_template('COMCODE_SUB', array('_GUID' => '515e310e00a6d7c30f7dca0a5956ebcf', 'CONTENT' => $embed)); break; case 'include': $codename = $embed->evaluate(); $zone = $attributes['param']; if ($zone == '_SEARCH') { $zone = get_comcode_zone($codename); } if ($zone == '_SELF') { $zone = get_zone_name(); } if ($zone == '(template)') { // Special undocumented feature used by tutorial(s) $temp_tpl = comcode_to_tempcode(cms_file_get_contents_safe(get_file_base() . '/data/modules/cms_comcode_pages/' . fallback_lang() . '/' . filter_naughty($codename) . '.txt')); break; } push_output_state(); $temp = request_page($codename, false, $zone, null, true); restore_output_state(); if ($temp->is_empty()) { $temp_tpl = do_template('WARNING_BOX', array( '_GUID' => '1d617fd24b632640dddeeadd8432d7a9', 'WARNING' => do_lang_tempcode('MISSING_RESOURCE_COMCODE', 'include', hyperlink(build_url(array('page' => 'cms_comcode_pages', 'type' => '_edit', 'page_link' => $zone . ':' . $codename), get_module_zone('cms_comcode_pages')), $zone . ':' . $codename, false, true)), )); if ((!in_array(get_page_name(), $GLOBALS['DONT_CARE_MISSING_PAGES'])) && (running_script('index'))) { require_code('failure'); relay_error_notification(do_lang('MISSING_RESOURCE_COMCODE', 'include', $zone . ':' . $codename), false, $GLOBALS['FORUM_DRIVER']->is_staff($source_member) ? 'error_occurred_missing_reference_important' : 'error_occurred_missing_reference'); } } else { $temp_tpl = symbol_tempcode('LOAD_PAGE', array($codename, $zone)); } break; case 'random': unset($attributes['param']); $max = ($embed->evaluate() == '') ? intval($embed->evaluate()) : 0; foreach ($attributes as $num => $val) { $_temp = comcode_to_tempcode($val, $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $attributes[$num] = $_temp->evaluate(); if (intval($num) > $max) { $max = intval($num); } } $_parts = array(); krsort($attributes); foreach ($attributes as $num => $val) { $_parts[] = array('NUM' => strval($num), 'VAL' => $val); } $temp_tpl = do_template('COMCODE_RANDOM', array('_GUID' => '9b77aaf593b12c763fb0c367fab415b6', 'FULL' => $embed, 'MAX' => strval($max), 'PARTS' => $_parts)); break; case 'jumping': unset($attributes['param']); $_parts = array(); foreach ($attributes as $val) { $_temp = comcode_to_tempcode($val, $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $_parts[] = array('PART' => $_temp->evaluate()); } $embed = $embed->evaluate(); $temp_tpl = do_template('COMCODE_JUMPING', array('_GUID' => '85e9f83ed134868436a7db7692f56047', 'FULL' => implode(', ', $attributes), 'TIME' => strval($embed), 'PARTS' => $_parts)); break; case 'shocker': $_parts = array(); foreach ($attributes as $key => $val) { if (substr($key, 0, 5) == 'left_') { $left = $val; $right = array_key_exists('right_' . substr($key, 5), $attributes) ? $attributes['right_' . substr($key, 5)] : ''; $left = comcode_to_tempcode($left, $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $right = comcode_to_tempcode($right, $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $_parts[] = array('LEFT' => $left, 'RIGHT' => $right); } } $min_color = array_key_exists('min', $attributes) ? $attributes['min'] : '0000FF'; $max_color = array_key_exists('max', $attributes) ? $attributes['max'] : 'FF0044'; if (substr($min_color, 0, 1) == '#') { $min_color = substr($min_color, 1); } if (substr($max_color, 0, 1) == '#') { $max_color = substr($max_color, 1); } $embed = $embed->evaluate(); $temp_tpl = do_template('COMCODE_SHOCKER', array('_GUID' => 'd648de0a5e3b5f84d82d781f4964e04a', 'MIN_COLOR' => $min_color, 'MAX_COLOR' => $max_color, 'FULL' => implode(', ', $attributes), 'TIME' => strval(intval($embed)), 'PARTS' => $_parts)); break; case 'ticker': $width = $attributes['param']; if (!is_numeric($width)) { $width = '300'; } $fspeed = array_key_exists('speed', $attributes) ? float_to_raw_string(floatval($attributes['speed'])) : '1'; $temp_tpl = do_template('COMCODE_TICKER', array('_GUID' => 'e48893cda61995261577f0556443c537', 'SPEED' => $fspeed, 'WIDTH' => $width, 'TEXT' => $embed)); break; case 'highlight': $temp_tpl = do_template('COMCODE_HIGHLIGHT', array('_GUID' => '695d041b6605f06ec2aeee1e82f87185', 'CONTENT' => $embed)); break; case 'size': $size = array_key_exists('param', $attributes) ? ($attributes['param']) : '1'; if (is_numeric($size)) { $size = 'font-size: ' . $size . 'em;'; } elseif (substr($size, 0, 1) == '+') { $size = 'font-size: ' . substr($size, 1) . 'em'; } elseif (substr($size, -1) == '%') { $size = 'font-size: ' . float_to_raw_string(floatval(substr($size, 0, strlen($size) - 1)) / 100.0) . 'em'; } elseif (substr($size, -2) == 'of') { $new_size = '1em'; switch ($size) { case '1of': $new_size = '8pt'; break; case '2of': $new_size = '10pt'; break; case '3of': $new_size = '12pt'; break; case '4of': $new_size = '14pt'; break; case '5of': $new_size = '18pt'; break; case '6of': $new_size = '24pt'; break; case '7of': $new_size = '36pt'; break; } $size = 'font-size: ' . $new_size; } else { $size = 'font-size: ' . $size; } $size_len = strlen($size); filter_html($as_admin, $source_member, 0, $size_len, $size, false, false); $temp_tpl = do_template('COMCODE_FONT', array('_GUID' => 'fb23fdcb45aabdfeca9f37ed8098948e', 'CONTENT' => $embed, 'SIZE' => $size, 'COLOR' => '', 'FACE' => '')); break; case 'color': $color = array_key_exists('param', $attributes) ? ('color: ' . $attributes['param'] . ';') : ''; $temp_tpl = do_template('COMCODE_FONT', array('_GUID' => 'bd146414c9239ba2076f4b683df437d7', 'CONTENT' => $embed, 'SIZE' => '', 'COLOR' => $color, 'FACE' => '')); $color_len = strlen($color); filter_html($as_admin, $source_member, 0, $color_len, $color, false, false); break; case 'tt': $temp_tpl = do_template('COMCODE_TELETYPE', array('_GUID' => '422a4785fc9bb0d1a26a09a59184f107', 'CONTENT' => $embed)); break; case 'samp': $temp_tpl = do_template('COMCODE_SAMP', array('_GUID' => '386eddbd74f45a8596f2f21680df99f8', 'CONTENT' => $embed)); break; case 'q': $temp_tpl = do_template('COMCODE_Q', array('_GUID' => 'ab5dc7cddf0ec01be969605cde87356c', 'CONTENT' => $embed)); break; case 'var': $temp_tpl = do_template('COMCODE_VAR', array('_GUID' => '75097f9f0de04bfd92507fdc07547237', 'CONTENT' => $embed)); break; case 'font': $face = $attributes['param']; if (($face == '') && (array_key_exists('face', $attributes))) { $face = $attributes['face']; } $color = array_key_exists('color', $attributes) ? $attributes['color'] : ''; $size = array_key_exists('size', $attributes) ? $attributes['size'] : ''; if ($face == '/') { $face = ''; } if ($color == '/') { $color = ''; } if ($size == '/') { $size = ''; } if ($color != '') { $color = 'color: ' . $color . ';'; } if ($size != '') { if (is_numeric($size)) { $size = 'font-size: ' . $size . 'em;'; } elseif (substr($size, 0, 1) == '+') { $size = 'font-size: ' . substr($size, 1) . 'em'; } elseif (substr($size, -1) == '%') { $size = 'font-size: ' . float_to_raw_string(floatval(substr($size, 0, strlen($size) - 1)) / 100.0) . 'em'; } elseif (substr($size, -2) == 'of') { $new_size = '1em'; switch ($size) { case '1of': $new_size = '8pt'; break; case '2of': $new_size = '10pt'; break; case '3of': $new_size = '12pt'; break; case '4of': $new_size = '14pt'; break; case '5of': $new_size = '18pt'; break; case '6of': $new_size = '24pt'; break; case '7of': $new_size = '36pt'; break; } $size = 'font-size: ' . $new_size; } else { $size = 'font-size: ' . $size; } } if ($face != '') { $face = 'font-family: ' . str_replace('\'', '', $face) . ';'; } $size_len = strlen($size); filter_html($as_admin, $source_member, 0, $size_len, $size, false, false); $color_len = strlen($color); filter_html($as_admin, $source_member, 0, $color_len, $color, false, false); $face_len = strlen($face); filter_html($as_admin, $source_member, 0, $face_len, $face, false, false); $temp_tpl = do_template('COMCODE_FONT', array('_GUID' => 'f5fcafe737b8fdf466a6a51773e09c9b', 'CONTENT' => $embed, 'SIZE' => $size, 'COLOR' => $color, 'FACE' => $face)); break; case 'box': $width = array_key_exists('width', $attributes) ? comcode_to_tempcode($attributes['width'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member) : make_string_tempcode('auto'); $type = array_key_exists('type', $attributes) ? $attributes['type'] : ''; $class = array_key_exists('class', $attributes) ? $attributes['class'] : ''; $options = array_key_exists('options', $attributes) ? $attributes['options'] : ''; $meta = ($comcode_dangerous && isset($attributes['meta'])) ? $attributes['meta'] : ''; // Insecure, unneeded here $links = ($comcode_dangerous && isset($attributes['links'])) ? $attributes['links'] : ''; // Insecure, unneeded here $converted_title = comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $temp_tpl = directive_tempcode('BOX', $embed, array($converted_title, make_string_tempcode($type), $width, make_string_tempcode($options), make_string_tempcode($meta), make_string_tempcode($links), new Tempcode(), make_string_tempcode($class))); if (isset($attributes['float'])) { $temp_tpl = do_template('FLOATER', array('_GUID' => '54e8fc9ec1e16cfc5c8824e22f1e8745', 'FLOAT' => $attributes['float'], 'CONTENT' => $temp_tpl)); } break; case 'concept': if ((!array_key_exists('param', $attributes)) || ($attributes['param'] == '')) { $key = $embed->evaluate(); $temp_tpl = symbol_tempcode('DISPLAY_CONCEPT', array($key)); } else { $temp_tpl = do_template('COMCODE_CONCEPT_INLINE', array('_GUID' => '381a59de4d6f8967446c12bf4641a9ce', 'TEXT' => $embed, 'FULL' => $attributes['param'])); } break; case 'concepts': $title = $embed->evaluate(); $concepts = array(); foreach ($attributes as $_key => $_value) { if (substr($_key, -4) == '_key') { $key = $_value; $cid = substr($_key, 0, strlen($_key) - 4); $to_parse = array_key_exists($cid . '_value', $attributes) ? $attributes[$cid . '_value'] : ''; $value = comcode_to_tempcode($to_parse, $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $concepts[] = array('A' => 'concept__' . preg_replace('#[^\w]#', '_', $key), 'KEY' => $key, 'VALUE' => $value); } } $temp_tpl = do_template('COMCODE_CONCEPTS', array('_GUID' => '4c7a1d70753dc1d209b9951aa10f361a', 'TITLE' => $title, 'CONCEPTS' => $concepts)); break; case 'hide': if (array_key_exists('param', $attributes)) { $text = comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); } else { $text = do_lang_tempcode('EXPAND'); } $temp_tpl = do_template('COMCODE_HIDE', array('_GUID' => 'a591a0d1e6bb3dde0f22cebb9c7ab93e', 'TEXT' => $text, 'CONTENT' => $embed)); break; case 'quote': $cite = array_key_exists('cite', $attributes) ? $attributes['cite'] : null; if (!is_null($cite)) { $temp_tpl = test_url($cite, 'quote', $cite, $source_member); } if (($attributes['param'] == '') && (isset($attributes['author']))) { $attributes['param'] = $attributes['author']; // Compatibility with SMF } if (is_numeric($attributes['param'])) { $attributes['param'] = $GLOBALS['FORUM_DRIVER']->get_username(intval($attributes['param']), true); } if ($attributes['param'] != '') { $attributes['param'] = protect_from_escaping(comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member)); $temp_tpl->attach(do_template('COMCODE_QUOTE_BY', array('_GUID' => '18f55a548892ad08b0b50b3b586b5b95', 'CITE' => $cite, 'CONTENT' => $embed, 'BY' => $attributes['param'], 'SAIDLESS' => array_key_exists('saidless', $attributes) ? $attributes['saidless'] : '0'))); } else { $temp_tpl->attach(do_template('COMCODE_QUOTE', array('_GUID' => 'fa275de59433c17da19b22814c17fdc5', 'CITE' => $cite, 'CONTENT' => $embed))); } break; case 'html': $temp_tpl = $embed; // Plain HTML. But it's been filtered already break; case 'semihtml': $temp_tpl = $embed; // Hybrid HTML. But it's been filtered already break; case 'block': $attributes['block'] = trim($embed->evaluate()); if (preg_match('#^[\w\-]*$#', $attributes['block']) == 0) { $temp_tpl = do_template('WARNING_BOX', array('_GUID' => 'b5638d953c400b7f194b62bc34f89181', 'WARNING' => do_lang_tempcode('MISSING_BLOCK_FILE', escape_html($attributes['block'])))); break; // Avoids a suspected hack attempt by just filtering early } $_attributes = array(); foreach ($attributes as $key => $val) { if (is_integer($key)) { $key = strval($key); } $_attributes[] = $key . '=' . $val; } $temp_tpl = symbol_tempcode('BLOCK', $_attributes); break; case 'title': $level = ($attributes['param'] != '') ? intval($attributes['param']) : 1; if ($level == 0) { $level = 1; // Stop crazy Comcode causing stack errors with the toc } $uniq_id = strval(count($STRUCTURE_LIST)); $STRUCTURE_LIST[] = array($level, $embed, $uniq_id); if ($level == 1) { $template = 'SCREEN_TITLE'; } else { $template = 'COMCODE_SUBTITLE'; } if ($level == 1) { if (is_null($COMCODE_PARSE_TITLE)) { $COMCODE_PARSE_TITLE = $embed->evaluate(); if (is_object($COMCODE_PARSE_TITLE)) { $COMCODE_PARSE_TITLE = $COMCODE_PARSE_TITLE->evaluate(); } } } $base = array_key_exists('base', $attributes) ? intval($attributes['base']) : 1; if ((array_key_exists('number', $attributes)) && ($level >= $base)) { $list_types = ($attributes['number'] == '') ? array() : explode(',', $attributes['number']); $list_types += array('decimal', 'lower-alpha', 'lower-roman', 'upper-alpha', 'upper-roman', 'disc'); $numerals = array('i', 'ii', 'iii', 'iv', 'v', 'vi', 'viii', 'ix', 'x', 'xi', 'xii', 'xiii', 'xiv', 'xv', 'xvi', 'xvii', 'xviii', 'xix', 'xx'); $symbol_lookup = array('decimal' => range(1, 100), 'lower-alpha' => range('a', 'z'), 'lower-roman' => $numerals, 'upper-alpha' => range('A', 'Z'), 'upper-roman' => str_replace('i', 'I', str_replace('v', 'V', str_replace('x', 'X', $numerals)))); $level_text = ''; $list_pos = count($STRUCTURE_LIST) - 2; for ($j = $level; $j >= $base; $j--) { $num_before = 0; for ($i = $list_pos; $i >= 0; $i--) { $list_pos--; if ($STRUCTURE_LIST[$i][0] == $j - 1) { break; } if ($STRUCTURE_LIST[$i][0] == $j) { $num_before++; } } $level_number = @strval($symbol_lookup[$list_types[$j - $base]][$num_before]); $level_text = $level_number . (($level_text != '') ? '.' : '') . $level_text; } $old_embed = $embed; $embed = make_string_tempcode($level_text . ' – '); $embed->attach($old_embed); } if ($semiparse_mode) { $temp_tpl = make_string_tempcode('' . $embed->evaluate() . ''); break; } $tpl_map = array( 'ID' => (substr($pass_id, 0, 5) == 'panel') ? null : $uniq_id, 'TITLE' => $embed, 'HELP_URL' => '', 'HELP_TERM' => '', 'LEVEL' => strval($level), ); if (array_key_exists('sub', $attributes)) { $tpl_map['SUB'] = protect_from_escaping(comcode_to_tempcode($attributes['sub'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member)); } $temp_tpl = do_template($template, $tpl_map); break; case 'contents': // Do structure sweep $urls_for = array(); // Backup then reset so we can track new titles $old_structure_list = $STRUCTURE_LIST; $STRUCTURE_LIST = array(); if ((array_key_exists('files', $attributes)) && ($comcode_dangerous)) { $s_zone = array_key_exists('zone', $attributes) ? $attributes['zone'] : get_zone_name(); $pages = find_all_pages($s_zone, 'comcode_custom/' . get_site_default_lang(), 'txt') + find_all_pages($s_zone, 'comcode/' . get_site_default_lang(), 'txt'); $prefix = $attributes['files']; $_structure_list = array(); foreach ($pages as $pg_name => $pg_type) { if (substr($pg_name, 0, strlen($prefix)) == $prefix) { $c = cms_file_get_contents_safe(zone_black_magic_filterer(get_file_base() . '/' . $s_zone . '/pages/' . $pg_type . '/' . $pg_name . '.txt')); __comcode_to_tempcode($c, $source_member, $as_admin, null, null, $connection, false, false, false, true, false, null, $on_behalf_of_member); $page_url = build_url(array('page' => $pg_name), $s_zone); foreach ($STRUCTURE_LIST as $struct) { $urls_for[] = $page_url; $_structure_list[] = $struct; } $STRUCTURE_LIST = array(); // Reset again, so the title increments for individual pages start from 0 again } } $STRUCTURE_LIST = $_structure_list; $base = array_key_exists('base', $attributes) ? intval($attributes['base']) : 1; } else { require_code('comcode_compiler'); __comcode_to_tempcode($comcode, $source_member, $as_admin, null, null, $connection, false, false, false, true, false, null, $on_behalf_of_member); $base = array_key_exists('base', $attributes) ? intval($attributes['base']) : 1; } $_embed = $embed->evaluate(); if (preg_match('#^test\d+$#', $_embed) != 0) { // Little bit of inbuilt test code, for a particularly dangerously wrong tree if ($_embed == 'test1') { $test_data = array( 2, 3, 2, 3, 4, 4, 4, 2, 3, 2, 1, 1, ); } elseif ($_embed == 'test2') { $test_data = array( 1, 2, 3, 1, 2, 3, ); } elseif ($_embed == 'test3') { $test_data = array( 1, 4, 6, 1, 4, 6, ); } else { $test_data = array( 6, 4, 1, 6, 4, 1, ); } $STRUCTURE_LIST = array(); foreach ($test_data as $t) { $STRUCTURE_LIST[] = array($t, make_string_tempcode(strval($t)), uniqid('', true)); } $list_types = array(); } else { $list_types = ($embed->evaluate() == '') ? array() : explode(',', $_embed); } $list_types = array_merge($list_types, array('decimal', 'lower-alpha', 'lower-roman', 'upper-alpha', 'upper-roman', 'disc')); $levels_allowed = array_key_exists('levels', $attributes) ? intval($attributes['levels']) : null; // Convert the list structure into a tree structure $past_level_stack = array(); $subtree_stack = array(array('', '', '', array())); // Children will be gathered into a 4th entry in the tuple by the end of the stack unravelling process -- our result $actual_past_stack_levels = 0; foreach ($STRUCTURE_LIST as $i => $struct) { // Really complex stack of trees algorithm $level = $struct[0]; $title = $struct[1]; $_title = $title->evaluate(); $uniq_id = $struct[2]; $url = array_key_exists($i, $urls_for) ? $urls_for[$i] : ''; if ((!is_null($levels_allowed)) && ($level > $levels_allowed)) { continue; } // Going back up the tree, destroying levels that must have now closed off while (($actual_past_stack_levels > 0) && ($level <= $past_level_stack[$actual_past_stack_levels - 1])) { array_pop($past_level_stack); // Value useless now, as the $actual_past_stack_levels is the true indicator and the $past_level_stack is just used as a navigation reference point for stack control $subtree = array_pop($subtree_stack); $actual_past_stack_levels--; // Alter the last of the next level on stack so it is actually taking the closed off level as children $subtree_stack[count($subtree_stack) - 1][3][] = $subtree; } // Going down the tree array_push($past_level_stack, $level); array_push($subtree_stack, array($uniq_id, $_title, $url, array())); $actual_past_stack_levels++; } // Close off all levels still open while ($actual_past_stack_levels > 0) { // Pretty much the same as the while loop above array_pop($past_level_stack); // Value useless now, as the $actual_past_stack_levels is the true indicator and the $past_level_stack is just used as a navigation reference point for stack control $subtree = array_pop($subtree_stack); $actual_past_stack_levels--; // Alter the last of the next level on stack so it is actually taking the closed off level as children $subtree_stack[count($subtree_stack) - 1][3][] = $subtree; } // Now we have the structure to display $levels_t = _do_contents_level($subtree_stack[0][3], $list_types, $base); $temp_tpl = do_template('COMCODE_CONTENTS', array('_GUID' => 'ca2f5320fa930e2257a2e74e4f98e5a0', 'LEVELS' => $levels_t)); $STRUCTURE_LIST = $old_structure_list; // Restore, so subsequent 'title' tags have correct numbering break; case 'url': // Make them both HTML strings $url = $embed->evaluate(); $switch_over = ((!looks_like_url($url)) && (looks_like_url($attributes['param'], true))); if ((strpos(preg_replace('#\[\d*\]#', '', $attributes['param']), '[') !== false) || (strpos($attributes['param'], '{') !== false)) { // Extra Comcode parsing wanted? $param_temp = comcode_to_tempcode(escape_html($attributes['param']), $source_member, $as_admin, null, null, $connection, false, false, true, false, false, $highlight_bits, $on_behalf_of_member); global $ADVERTISING_BANNERS_CACHE; $temp_ab = $ADVERTISING_BANNERS_CACHE; $ADVERTISING_BANNERS_CACHE = array(); $caption = $param_temp; $ADVERTISING_BANNERS_CACHE = $temp_ab; } else { $caption = make_string_tempcode(escape_html($attributes['param'])); // Consistency of escaping } // Do we need to switch around? if ($switch_over) { $url = $attributes['param']; if ((strpos(preg_replace('#\[\d*\]#', '', $url), '[') !== false) || (strpos($url, '{') !== false)) { // Extra Comcode parsing wanted? $url = static_evaluate_tempcode(comcode_to_tempcode($url, $source_member, $as_admin, null, null, $connection, false, false, true, false, false, $highlight_bits, $on_behalf_of_member)); } $caption = $embed; } // If we weren't given a caption, use the URL, but crop if necessary if ($caption->evaluate() == '') { $_caption = $url; // Shorten the URL if it is too long $max_link_length = 50; if (strlen($_caption) > $max_link_length) { $_caption = escape_html(substr(@html_entity_decode($_caption, ENT_QUOTES, get_charset()), 0, intval($max_link_length / 2 - 3))) . '…' . escape_html(substr(@html_entity_decode($_caption, ENT_QUOTES, get_charset()), intval(-$max_link_length / 2))); } $caption = make_string_tempcode($_caption); } // Tidy up the URL now $url = @html_entity_decode($url, ENT_QUOTES, get_charset()); $url = fixup_protocolless_urls($url); // Integrity and security $url = check_naughty_javascript_url($source_member, $url, $as_admin); // More URL tidying $local = (url_is_local($url)) || (strpos($url, get_domain()) !== false); $given_url = $url; if (($url != '') && ($url[0] != '#')) { if (substr($url, 0, 1) == '/') { $url = substr($url, 1); } $url_full = url_is_local($url) ? (get_base_url() . '/' . $url) : $url; if ($GLOBALS['XSS_DETECT']) { ocp_mark_as_escaped($url_full); } } else { $url_full = $url; } $striped_base_url = str_replace('www.', '', str_replace('https://', '', str_replace('http://', '', get_base_url()))); if (($striped_base_url != '') && (substr($url, 0, 1) != '%') && (strpos($url_full, $striped_base_url) === false)) { // We don't want to hammer our own server when we have Comcode pages full of links to our own site (much less risk of hammering other people's servers, as we won't tend to have loads of links to them). Would also create bugs in emails sent out - e.g. auto-running approve_ip.php links hence voiding the intent of the feature. $temp_tpl = test_url($url_full, 'url', $given_url, $source_member); } // Render if (empty($attributes['target'])) { $attributes['target'] = $local ? '_top' : '_blank'; } if ($attributes['target'] == 'blank') { $attributes['target'] = '_blank'; // Fix common mistake } if (array_key_exists('rel', $attributes)) { $rel = array_flip(preg_split('#\s+#', trim(strtolower($attributes['rel'])))); } else { $rel = array(); } if ((!$as_admin) && (!has_privilege($source_member, 'search_engine_links'))) { $rel['nofollow'] = true; } if (!$comcode_dangerous) { unset($rel['opener']); $rel['noopener'] = true; } if ($attributes['target'] == '_blank') { $rel['external'] = true; $title = trim(strip_tags(is_object($caption) ? static_evaluate_tempcode($caption) : $caption) . ' ' . do_lang('LINK_NEW_WINDOW')); } else { $title = ''; } $temp_tpl->attach(do_template('COMCODE_URL', array('_GUID' => 'd1657530e6d3d57e6a4791fb3bfa0dd7', 'TITLE' => $title, 'REL' => implode(' ', array_keys($rel)), 'TARGET' => $attributes['target'], 'URL' => $url_full, 'CAPTION' => $caption))); break; case 'email': $_embed = $embed->evaluate(); require_code('type_sanitisation'); require_code('obfuscate'); // If we need to switch if ((!is_email_address($_embed)) && (is_email_address($attributes['param']))) { $temp = $embed; // Is Tempcode $_embed = $attributes['param']; $attributes['param'] = $temp; } else { $attributes['param'] = comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); // Becomes Tempcode } if ($attributes['param']->is_empty()) { $attributes['param'] = obfuscate_email_address($_embed); } $subject = array_key_exists('subject', $attributes) ? $attributes['subject'] : ''; $body = array_key_exists('body', $attributes) ? $attributes['body'] : ''; $title = ''; if (array_key_exists('title', $attributes)) { $title = $attributes['title']; } $temp_tpl = do_template('COMCODE_EMAIL', array('_GUID' => '5f6ade8fe07701b6858575153d78f4e9', 'TITLE' => $title, 'ADDRESS' => obfuscate_email_address($_embed), 'SUBJECT' => $subject, 'BODY' => $body, 'CAPTION' => $attributes['param'])); break; case 'reference': if ((array_key_exists('type', $attributes)) && ($attributes['type'] == 'url')) { $_embed = $embed->evaluate(); $_embed = check_naughty_javascript_url($source_member, $_embed, $as_admin); if (!array_key_exists('title', $attributes)) { $attributes['title'] = $attributes['param']; } if ($attributes['title'] != '') { $_title = comcode_to_tempcode($attributes['title'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); $title = $_title->evaluate(); } else { $title = make_string_tempcode(escape_html($_embed)); } $embed = hyperlink($_embed, $title, true, false); } $temp_tpl = do_template('COMCODE_REFERENCE', array_merge($attributes, array('SOURCE' => $embed))); break; case 'page': $ignore_if_hidden = (array_key_exists('ignore_if_hidden', $attributes)) && ($attributes['ignore_if_hidden'] == '1'); unset($attributes['ignore_if_hidden']); $hash = ''; $caption = $embed; global $OVERRIDE_SELF_ZONE; $page_link = $attributes['param']; list($zone, $_attributes, $hash) = page_link_decode($page_link); if (!array_key_exists('page', $_attributes)) { $_attributes['page'] = ''; } if (($zone == '_SELF') && (!is_null($OVERRIDE_SELF_ZONE))) { $zone = $OVERRIDE_SELF_ZONE; } if ($zone == '_SEARCH') { $zone = get_page_zone($_attributes['page'], false); if (is_null($zone)) { $zone = ''; } } $external = (array_key_exists('external', $attributes) && $attributes['external'] == '1'); $pl_url = build_url($_attributes, $zone, null, false, false, false, $hash); $temp_tpl = hyperlink($pl_url, $caption, $external, true); $page = $_attributes['page']; if ($page != '') { if ($zone == '_SELF') { $zone = get_zone_name(); } if ($zone == '_SEARCH') { $zone = get_page_zone($page, false); if (is_null($zone)) { $zone = ''; // Oh dear, well it will be correctly identified as not found anyway } } $ptest = _request_page($page, $zone); if ($ptest !== false) { if (($page == 'topicview') && (get_forum_type() == 'cns') && (array_key_exists('id', $_attributes))) { if (!is_numeric($_attributes['id'])) { $_attributes['id'] = $GLOBALS['SITE_DB']->query_select_value_if_there('url_id_monikers', 'm_resource_id', array('m_resource_page' => $page, 'm_moniker' => $_attributes['id'])); } if (!is_null($_attributes['id'])) { $test = $GLOBALS['FORUM_DB']->query_select_value_if_there('f_topics', 'id', array('id' => $_attributes['id'])); if (is_null($test)) { $ptest = false; } } else { $ptest = false; } } } if ($ptest === false) { //$temp_tpl->attach(' [' . do_lang('MISSING_RESOURCE') . ']'); // Don't want this as we might be making the page immediately if ((!in_array(get_page_name(), $GLOBALS['DONT_CARE_MISSING_PAGES'])) && (!in_array($page, $GLOBALS['DONT_CARE_MISSING_PAGES'])) && (running_script('index'))) { if ($ignore_if_hidden) { $temp_tpl = do_template('COMCODE_DEL', array('_GUID' => 'df638c61bc17ca975e95cf5f749836f5', 'CONTENT' => $caption)); } else { require_code('failure'); relay_error_notification(do_lang('MISSING_RESOURCE_COMCODE', 'page_link', $page_link), false, $GLOBALS['FORUM_DRIVER']->is_staff($source_member) ? 'error_occurred_missing_reference_important' : 'error_occurred_missing_reference'); } } } } break; case 'thumb': $_embed = $embed->evaluate(); $given_url = $embed->evaluate(); $url_full = absoluteise_and_test_comcode_url($given_url, $source_member, $as_admin, $tag); $align = array_key_exists('align', $attributes) ? $attributes['align'] : 'bottom'; if ((!function_exists('imagetypes')) || ((!has_privilege($source_member, 'draw_to_server')) && (!$as_admin))) { $url_thumb = $url_full; } else { if ($attributes['param'] != '') { $url_thumb = url_is_local($attributes['param']) ? get_custom_base_url() . '/' . $attributes['param'] : $attributes['param']; } if (($attributes['param'] == '') || ((url_is_local($attributes['param'])) && (!file_exists(get_custom_file_base() . '/' . rawurldecode($attributes['param']))))) { $new_name = url_to_filename($url_full); require_code('images'); if (!is_saveable_image($new_name)) { $new_name .= '.png'; } $file_thumb = get_custom_file_base() . '/uploads/auto_thumbs/' . $new_name; if ((!file_exists($file_thumb)) && (strpos($file_thumb, '{$') === false)) { convert_image($url_full, $file_thumb, -1, -1, intval(get_option('thumb_width')), false); } $url_thumb = get_custom_base_url() . '/uploads/auto_thumbs/' . rawurlencode($new_name); } } $caption = array_key_exists('caption', $attributes) ? $attributes['caption'] : ''; $temp_tpl = do_template('COMCODE_THUMB', array('_GUID' => '1b0d25f72ef5f816091269e29c586d60', 'CAPTION' => $caption, 'ALIGN' => $align, 'URL_THUMB' => $url_thumb, 'URL_FULL' => $url_full)); if (array_key_exists('float', $attributes)) { $temp_tpl = do_template('FLOATER', array('_GUID' => 'cbc56770714a44f56676f43da282cc7a', 'FLOAT' => $attributes['float'], 'CONTENT' => $temp_tpl)); } break; case 'img': if (($semiparse_mode) && (array_key_exists('rollover', $attributes))) { $temp_tpl = make_string_tempcode(add_wysiwyg_comcode_markup($tag, $attributes, $embed, ($in_semihtml) || ($is_all_semihtml), WYSIWYG_COMCODE__STANDOUT_BLOCK, $html_errors)); break; } $_embed = $embed->evaluate(); $given_url = $embed->evaluate(); $url_full = absoluteise_and_test_comcode_url($given_url, $source_member, $as_admin, $tag); $align = array_key_exists('align', $attributes) ? $attributes['align'] : ''; $caption = comcode_to_tempcode($attributes['param'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); if (array_key_exists('title', $attributes)) { $tooltip = comcode_to_tempcode($attributes['title'], $source_member, $as_admin, null, null, $connection, false, false, false, false, false, $highlight_bits, $on_behalf_of_member); } else { $tooltip = $caption; } $rollover = array_key_exists('rollover', $attributes) ? $attributes['rollover'] : null; if ((!is_null($rollover)) && (url_is_local($rollover))) { if ((file_exists(get_file_base() . '/' . $rollover)) && (!file_exists(get_custom_file_base() . '/' . $rollover))) { $rollover = get_base_url() . '/' . $rollover; } else { $rollover = get_custom_base_url() . '/' . $rollover; } } $refresh_time = array_key_exists('refresh_time', $attributes) ? strval(intval($attributes['refresh_time'])) : '0'; $temp_tpl->attach(do_template('COMCODE_IMG', array('_GUID' => '70166d8dbb0aff064b99c0dd30ed77a8', 'REFRESH_TIME' => $refresh_time, 'ROLLOVER' => $rollover, 'ALIGN' => $align, 'URL' => $url_full, 'TOOLTIP' => $tooltip, 'CAPTION' => $caption))); if (array_key_exists('float', $attributes)) { $temp_tpl = do_template('FLOATER', array('_GUID' => '918162250c80e10212efd9a051545b9b', 'FLOAT' => $attributes['float'], 'CONTENT' => $temp_tpl)); } break; case 'flash': $given_url = $embed->evaluate(); $url_full = absoluteise_and_test_comcode_url($given_url, $source_member, $as_admin, $tag); if (strpos($attributes['param'], 'x') !== false) { list($width, $height) = explode('x', $attributes['param'], 2); $attributes['width'] = $width; $attributes['height'] = $height; } if (!$as_admin && !has_privilege($source_member, 'comcode_dangerous')) { unset($attributes['mime_type']); } require_code('media_renderer'); $temp_tpl = render_media_url( $url_full, $url_full, $attributes + array('context' => 'comcode_flash'), $as_admin, $source_member, MEDIA_TYPE_OTHER | MEDIA_TYPE_VIDEO | MEDIA_TYPE_AUDIO, (strtolower(substr($given_url, -4)) == '.swf') ? 'flash' : null // LEGACY: Really we should only allow Flash (because we have a 'media' tag), but we always used to support any media via this tag ); break; case 'media_set': $width = array_key_exists('width', $attributes) ? $attributes['width'] : ''; $height = array_key_exists('height', $attributes) ? $attributes['height'] : ''; $temp_tpl = do_template('COMCODE_MEDIA_SET', array( '_GUID' => 'd8f811e2f3d13263edd32a3fe46678aa', 'WIDTH' => $width, 'HEIGHT' => $height, 'MEDIA' => $embed, )); break; case 'media': $url_full = $embed->evaluate(); if (!$as_admin && !has_privilege($source_member, 'comcode_dangerous')) { unset($attributes['mime_type']); } require_code('media_renderer'); $temp_tpl = render_media_url( $url_full, $url_full, $attributes + array('context' => 'comcode_media'), $as_admin, $source_member, MEDIA_TYPE_ALL, ((array_key_exists('type', $attributes)) && ($attributes['type'] != '')) ? $attributes['type'] : null ); break; case 'attachment': case 'attachment_safe': // Work out display type $attributes['type'] = array_key_exists('type', $attributes) ? $attributes['type'] : ''; if ($attributes['type'] == 'extract') { $attributes['type'] = ''; } // LEGACY if ($attributes['type'] == 'inline' || $attributes['type'] == 'left_inline' || $attributes['type'] == 'right_inline') { $attributes['framed'] = '0'; $attributes['type'] = ''; if ($attributes['type'] == 'left_inline') { $attributes['float'] = 'left'; } if ($attributes['type'] == 'right_inline') { $attributes['float'] = 'right'; } } elseif ($attributes['type'] == 'island' || $attributes['type'] == 'lightbox' || $attributes['type'] == 'left_island' || $attributes['type'] == 'right_island') { $attributes['framed'] = '1'; $attributes['type'] = ''; if ($attributes['type'] == 'left_island') { $attributes['float'] = 'left'; } if ($attributes['type'] == 'right_island') { $attributes['float'] = 'right'; } } elseif ($attributes['type'] == 'download') { $attributes['framed'] = '1'; $attributes['type'] = 'hyperlink'; } if (is_null($on_behalf_of_member)) { $on_behalf_of_member = $source_member; } if (!array_key_exists('thumb_url', $attributes)) { $attributes['thumb_url'] = ''; } if (!$as_admin && !has_privilege($source_member, 'comcode_dangerous')) { unset($attributes['mime_type']); } global $COMCODE_ATTACHMENTS; $attachment_row = mixed(); $original_filename = mixed(); $id = $embed->evaluate(); // Check against quota. We work all this out before we do any downloads, to make sure orphaned files aren't dumped on the file system (possible hack method) if ((!is_numeric($id))/*=new upload*/ && (!$as_admin) && (!has_privilege($source_member, 'exceed_filesize_limit'))) { if (get_forum_type() == 'cns') { require_code('cns_groups'); $daily_quota = cns_get_member_best_group_property($source_member, 'max_daily_upload_mb'); } else { $daily_quota = 5; // 5 is a hard coded default for non-Conversr forums } require_code('upload_syndication'); if ((!is_null($daily_quota)) && ((substr($id, 0, 4) != 'new_') || (!upload_will_syndicate('file' . substr($id, 4))))) { $_size_uploaded_today = $connection->query('SELECT SUM(a_file_size) AS the_answer FROM ' . $connection->get_table_prefix() . 'attachments WHERE a_member_id=' . strval($source_member) . ' AND a_add_time>' . strval(time() - 60 * 60 * 24) . ' AND a_add_time<=' . strval(time())); if (is_null($_size_uploaded_today[0]['the_answer'])) { $_size_uploaded_today[0]['the_answer'] = 0; } $size_uploaded_today = ceil(((float)$_size_uploaded_today[0]['the_answer']) / 1024.0 / 1024.0); $attach_size = 0; require_code('uploads'); is_plupload(true); foreach ($_FILES as $_file) { $attach_size += floatval($_file['size']) / 1024.0 / 1024.0; } if (($size_uploaded_today + $attach_size) > floatval($daily_quota)) { $syn_services = array(); $hooks = find_all_hooks('systems', 'upload_syndication'); foreach (array_keys($hooks) as $hook) { require_code('hooks/systems/upload_syndication/' . filter_naughty_harsh($hook)); $ob = object_factory('Hook_upload_syndication_' . filter_naughty_harsh($hook)); if ($ob->is_enabled()) { $syn_services[] = $ob->get_label(); } } require_code('upload_syndication'); list($syndication_json,) = get_upload_syndication_json(CMS_UPLOAD_ANYTHING); if (($daily_quota > 0) || (count($syn_services) == 0)) { $over_quota_str = 'OVER_DAILY_QUOTA'; } else { if (count($syn_services) > 1) { $over_quota_str = '_OVER_DAILY_QUOTA'; } else { $over_quota_str = '__OVER_DAILY_QUOTA'; } } $temp_tpl = do_template('WARNING_BOX', array( '_GUID' => '89b7982164ccf8d98f3d0596ad425f78', 'RESTRICT_VISIBILITY' => strval($source_member), 'WARNING' => do_lang_tempcode($over_quota_str, escape_html(integer_format($daily_quota)), escape_html(float_format($size_uploaded_today)), array( escape_html($GLOBALS['FORUM_DRIVER']->get_username($source_member)), escape_html(get_site_name()), escape_html(isset($syn_services[0]) ? $syn_services[0] : ''), ) ), )); break; } } } // New attachments: embedded attachments (base64) if ((!is_numeric($id)) && (substr($id, 0, 4) != 'new_')) { $file = base64_decode(str_replace("\n", '', $id)); if ($file === false) { $temp_tpl = do_template('WARNING_BOX', array('_GUID' => '422658aee3c0eea77ad85d8621af742b', 'WARNING' => do_lang_tempcode('comcode:CORRUPT_ATTACHMENT'))); break; } $md5 = md5(substr($file, 0, 30)); $original_filename = array_key_exists('filename', $attributes) ? $attributes['filename'] : ($md5 . '.bin'); if (get_file_extension($original_filename) != 'bin') { require_code('files2'); check_extension($original_filename, true); $new_filename = $md5 . '.' . get_file_extension($original_filename) . '.bin'; } else { $new_filename = $md5 . '.' . get_file_extension($original_filename); } require_code('files'); $path = get_custom_file_base() . '/uploads/attachments/' . $new_filename; $success_status = cms_file_put_contents_safe($path, $file, FILE_WRITE_FAILURE_SILENT | FILE_WRITE_FIX_PERMISSIONS | FILE_WRITE_SYNC_FILE); if (!$success_status) { $temp_tpl = do_template('WARNING_BOX', array('_GUID' => '428a36aa6cea693d01429f3d21caac36', 'WARNING' => intelligent_write_error_inline($path))); break; } $_size = strlen($file); $url = 'uploads/attachments/' . $new_filename; if (is_forum_db($connection)) { $url = get_custom_base_url() . '/' . $url; } } // New attachments: uploads elseif (!is_numeric($id)) { if (substr($id, 0, 4) == 'new_') { disable_php_memory_limit(); // In case needs lots of RAM for thumbnail generation // Get/test ID $_id = substr($id, 4); if (!is_numeric($_id)) { $temp_tpl = do_template('WARNING_BOX', array('_GUID' => 'dd7035da4ad83b55fbd185267ab31fe6', 'WARNING' => do_lang_tempcode('comcode:INVALID_ATTACHMENT'))); break; } // Grab actual file require_code('uploads'); require_code('images'); is_plupload(true); $enforce_type = CMS_UPLOAD_ANYTHING; if (((empty($attributes['type'])) || ($attributes['type'] == 'image_websafe')) && (array_key_exists('file' . $_id, $_FILES)) && (is_saveable_image($_FILES['file' . $_id]['name']))) { $enforce_type = CMS_UPLOAD_IMAGE; // Images cleanup pipeline } set_images_cleanup_pipeline_settings(IMG_RECOMPRESS_LOSSLESS, null, null, true); // Code to strip GPS $urls = get_url('', 'file' . $_id, 'uploads/attachments', 2, $enforce_type, ((!array_key_exists('thumb', $attributes)) || ($attributes['thumb'] != '0')) && ($attributes['thumb_url'] == ''), '', '', true, true, true, true, $source_member); reset_images_cleanup_pipeline_settings(); if ($urls[0] == '') { return new Tempcode(); }//warn_exit(do_lang_tempcode('ERROR_UPLOADING')); Can't do this, because this might not be post-calculated if something went wrong once $_size = $_FILES['file' . $_id]['size']; $original_filename = $_FILES['file' . $_id]['name']; if (@get_magic_quotes_gpc()) { $original_filename = stripslashes($original_filename); } require_code('upload_syndication'); $urls[0] = handle_upload_syndication('file' . $_id, '', array_key_exists('description', $attributes) ? $attributes['description'] : '', $urls[0], $original_filename, true); } else { // Should not get here $temp_tpl = do_template('WARNING_BOX', array('_GUID' => 'f7c0ead08bf7e19f3b78a536c755d6a5', 'WARNING' => do_lang_tempcode('comcode:INVALID_ATTACHMENT'))); break; } // If it did not work if ($urls[0] == '') { require_code('images'); require_code('files2'); $temp_tpl = do_template('WARNING_BOX', array('_GUID' => '81dce25ce8c1e0a9a2407315df0cf99c', 'WARNING' => do_lang_tempcode('ATTACHMENT_WOULD_NOT_UPLOAD', escape_html(float_format(get_max_file_size() / 1024 / 1024)), escape_html(float_format(get_max_image_size() / 1024 / 1024))))); break; } $url = $urls[0]; if ($attributes['thumb_url'] == '') { $attributes['thumb_url'] = array_key_exists(1, $urls) ? $urls[1] : ''; } } else { // Existing attachments $__id = intval($id); // Load attachment $attachment_rows = $connection->query_select('attachments', array('*'), array('id' => $__id), '', 1); if (!array_key_exists(0, $attachment_rows)) { // Missing attachment! $temp_tpl = do_template('WARNING_BOX', array('_GUID' => 'be1c9c26a8802a00955fbd7a55b08bd3', 'WARNING' => do_lang_tempcode('MISSING_RESOURCE_COMCODE', 'attachment', escape_html(strval($__id))))); if ((!in_array(get_page_name(), $GLOBALS['DONT_CARE_MISSING_PAGES'])) && (running_script('index'))) { require_code('failure'); relay_error_notification(do_lang('MISSING_RESOURCE_COMCODE', 'attachment', strval($__id)), false, $GLOBALS['FORUM_DRIVER']->is_staff($source_member) ? 'error_occurred_missing_reference_important' : 'error_occurred_missing_reference'); } break; } $attachment_row = $attachment_rows[0]; // Check permission require_code('attachments'); $already_referenced = array_key_exists($__id, $GLOBALS['ATTACHMENTS_ALREADY_REFERENCED']); if (($already_referenced) || ($as_admin) || (/*(!is_guest($source_member)) && */($source_member === $attachment_row['a_member_id'])) || ((has_privilege($source_member, 'reuse_others_attachments')) && (has_attachment_access($source_member, $__id))) ) { if (!array_key_exists('type', $attributes)) { $attributes['type'] = 'auto'; } $COMCODE_ATTACHMENTS[$pass_id][] = array('tag_type' => $tag, 'time' => $attachment_row['a_add_time'], 'type' => 'existing', 'initial_id' => $id, 'id' => $__id, 'attachmenttype' => $attributes['type'], 'comcode' => $comcode); } else { // No permission require_lang('permissions'); $username = $GLOBALS['FORUM_DRIVER']->get_username($source_member); if (is_null($username)) { $username = do_lang('DELETED'); } $temp_tpl = do_template('WARNING_BOX', array( '_GUID' => 'af61f96b5cc6819979ce681d6f49b384', 'RESTRICT_VISIBILITY' => strval($source_member), 'WARNING' => do_lang_tempcode('permissions:ACCESS_DENIED__REUSE_ATTACHMENT', $username), )); break; } } // New attachments need inserting if (is_null($attachment_row)) { require_code('images'); // Thumbnail generation if ($attributes['thumb_url'] == '') { if (is_saveable_image($original_filename)) { if (function_exists('imagetypes')) { require_code('images'); if (!is_saveable_image($url)) { $ext = '.png'; } else { $ext = '.' . get_file_extension($original_filename); } $md5 = md5(substr($original_filename, 0, 30)); $attributes['thumb_url'] = 'uploads/attachments_thumbs/' . $md5 . $ext; convert_image(get_custom_base_url() . '/' . $url, get_custom_file_base() . '/' . $attributes['thumb_url'], -1, -1, intval(get_option('thumb_width')), true, null, false, true); if (is_forum_db($connection)) { $attributes['thumb_url'] = get_custom_base_url() . '/' . $attributes['thumb_url']; } } else { $attributes['thumb_url'] = $url; } } elseif ((addon_installed('galleries')) && (is_video($original_filename, $as_admin)) && (url_is_local($url))) { require_code('galleries2'); $attributes['thumb_url'] = create_video_thumb(url_is_local($url) ? (get_custom_base_url() . '/' . $url) : $url); } } // Width/height auto-detection if ((addon_installed('galleries')) && (is_video($original_filename, $as_admin)) && (url_is_local($url))) { require_code('galleries2'); $vid_details = url_is_local($url) ? get_video_details(get_custom_file_base() . '/' . rawurldecode($url), $original_filename, true) : false; if ($vid_details !== false) { list($_width, $_height,) = $vid_details; if ((!array_key_exists('width', $attributes)) || ($attributes['width'] == '')) { $attachment_row['width'] = strval($_width); } if ((!array_key_exists('height', $attributes)) || ($attributes['height'] == '')) { $attachment_row['height'] = strval($_height); } } } // Set URL correctly, if on an M.S.N. if (is_forum_db($connection)) { if (url_is_local($url)) { $url = get_custom_base_url() . '/' . $url; } if (url_is_local($attributes['thumb_url'])) { $attributes['thumb_url'] = get_custom_base_url() . '/' . $attributes['thumb_url']; } } // Insert attachment $attachment_row = array( 'a_member_id' => $on_behalf_of_member, 'a_file_size' => $_size, 'a_url' => $url, 'a_thumb_url' => preg_replace('#^' . preg_quote(get_custom_base_url() . '/') . '#', '', $attributes['thumb_url']), 'a_original_filename' => $original_filename, 'a_num_downloads' => 0, 'a_last_downloaded_time' => null, 'a_add_time' => time(), 'a_description' => array_key_exists('description', $attributes) ? $attributes['description'] : '', ); $attachment_row['id'] = $connection->query_insert('attachments', $attachment_row, true); // Transcode if (addon_installed('galleries')) { require_code('images'); if ((is_video($url, $as_admin)) && ($connection->connection_read == $GLOBALS['SITE_DB']->connection_read)) { require_code('transcoding'); transcode_video($url, 'attachments', $attachment_row['id'], 'id', 'a_url', 'a_original_filename', null, null); } } // Create and document attachment $COMCODE_ATTACHMENTS[$pass_id][] = array('type' => 'new', 'initial_id' => $id, 'id' => $attachment_row['id']); // Marker will allow us to search back and replace this with the added ID } // Lock it if we are doing a 'safe' attachment if ($tag == 'attachment_safe') { $connection->query_delete('attachment_refs', array('r_referer_type' => 'null', 'r_referer_id' => '', 'a_id' => $attachment_row['id']), '', 1); $connection->query_insert('attachment_refs', array('r_referer_type' => 'null', 'r_referer_id' => '', 'a_id' => $attachment_row['id'])); } // Now, render it // ============== require_code('attachments'); $temp_tpl = render_attachment($tag, $attributes, $attachment_row, $pass_id, $source_member, $as_admin, $connection, $highlight_bits, $on_behalf_of_member, $semiparse_mode); break; } if (is_null($temp_tpl)) { $temp_tpl = new Tempcode(); } // Last ditch effort: custom tags if ($temp_tpl->is_empty_shell()) { global $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE; if (array_key_exists($tag, $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE)) { $replace = $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE[$tag]['replace']; $parameters = explode(',', $CUSTOM_COMCODE_REPLACE_TARGETS_CACHE[$tag]['parameters']); $binding = array('CONTENT' => $embed); foreach ($parameters as $parameter) { $parameter = trim($parameter); $parts = explode('=', $parameter); if (count($parts) == 1) { $parts[] = ''; } if (count($parts) != 2) { continue; } list($parameter, $default) = $parts; if ((!array_key_exists($parameter, $attributes)) || ($attributes[$parameter] == '')) { $attributes[$parameter] = $default; } $binding[strtoupper($parameter)] = $attributes[$parameter]; if (is_string($replace)) { $replace = str_replace('{' . $parameter . '}', '{' . strtoupper($parameter) . '*}', $replace); } } if (is_string($replace)) { $replace = str_replace('{content}', array_key_exists($tag, $GLOBALS['TEXTUAL_TAGS']) ? '{CONTENT}' : '{CONTENT*}', $replace); require_code('tempcode_compiler'); $temp_tpl = template_to_tempcode($replace); $temp_tpl = $temp_tpl->bind($binding, '(custom comcode: ' . $tag . ')'); } else { $temp_tpl = call_user_func($replace, $embed, $attributes); } } } return $temp_tpl; } /** * Render a code box. * * @param string $type The data type (e.g. file extension) we are rendering. * @param Tempcode $embed Contents (code) to render. * @param boolean $numbers Whether to show line numbers. * @param boolean $in_semihtml Whether what we have came from inside a semihtml tag * @param boolean $is_all_semihtml Whether what we have came from semihtml mode * @return array A pair: The Tempcode for the code box, and the title of the box */ function do_code_box($type, $embed, $numbers = true, $in_semihtml = false, $is_all_semihtml = false) { $_embed = mixed(); $title = do_lang_tempcode('CODE'); if ((file_exists(get_file_base() . '/sources_custom/geshi/' . filter_naughty(($type == 'HTML') ? 'html5' : strtolower($type)) . '.php')) && (!in_safe_mode())) { $evaluated = $embed->evaluate(); if (($in_semihtml) || ($is_all_semihtml)) { require_code('comcode_from_html'); $evaluated = semihtml_to_comcode($evaluated, true); $evaluated = preg_replace('#^\[(semi)?html\]#', '', $evaluated); $evaluated = preg_replace('#\[/(semi)?html\]$#', '', $evaluated); } require_code('geshi'); if (class_exists('GeSHi')) { require_code('developer_tools'); destrictify(false); $geshi = new GeSHi($evaluated, ($type == 'HTML') ? 'html5' : strtolower($type)); $geshi->set_header_type(GESHI_HEADER_DIV); if ($numbers) { $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); } $title = do_lang_tempcode('comcode:CODE_IN_LANGUAGE', escape_html($type)); require_code('xhtml'); $_embed = xhtmlise_html($geshi->parse_code()); restrictify(); } } else { switch (strtolower($type)) { case 'php': if (php_function_allowed('highlight_string')) { $evaluated = $embed->evaluate(); if (($in_semihtml) || ($is_all_semihtml)) { require_code('comcode_from_html'); $evaluated = semihtml_to_comcode($evaluated, true); $evaluated = preg_replace('#^\[(semi)?html\]#', '', $evaluated); $evaluated = preg_replace('#\[/(semi)?html\]$#', '', $evaluated); } if (strpos($evaluated, '<' . '?php') === false) { $strip = true; $evaluated = "<" . "?php\n" . $evaluated . "\n?" . ">"; } else { $strip = false; } require_code('xhtml'); ob_start(); highlight_string($evaluated); $h_result = ob_get_clean(); $_embed = xhtmlise_html($h_result); if ($strip) { $_embed = str_replace('<?php
    ', '', $_embed); $_embed = str_replace('?>', '', $_embed); } $title = do_lang_tempcode('comcode:PHP_CODE'); } break; } } return array($_embed, $title); } /** * Recursive algorithm to make table of contents. * * @param array $tree_structure The TOC (sub)tree * @param array $list_types The list types to use for each level * @param integer $base The level to start from * @param integer $the_level The level we are at in the recursion * @return Tempcode The TOC node. * * @ignore */ function _do_contents_level($tree_structure, $list_types, $base, $the_level = 0) { $lines = array(); foreach ($tree_structure as $level) { if (array_key_exists(3, $level)) { $under = _do_contents_level($level[3], $list_types, $base, $the_level + 1); if ($the_level < $base - 1) { return $under; // Top level not assembled because it has top level title, above contents } } else { $under = new Tempcode(); } $lines[] = array('ID' => $level[0], 'LINE' => $level[1], 'URL' => $level[2], 'UNDER' => $under); } if ($lines === array()) { return new Tempcode(); } return do_template('COMCODE_CONTENTS_LEVEL', array('_GUID' => 'cd2811bf69387ca05bf9612319db956b', 'TYPE' => $list_types[max($the_level - $base + 1/*because $base counts from 1 not 0*/, 0)], 'LINES' => $lines)); } /** * Find a specified tutorial link identifier. * * @param ID_TEXT $name The name of the value * @return ?SHORT_TEXT The value (null: value not found) */ function get_tutorial_link($name) { static $cache = array(); if (isset($cache[$name])) { $ret = $cache[$name]; } else { $ret = $GLOBALS['SITE_DB']->query_select_value_if_there('tutorial_links', 'the_value', array('the_name' => cms_mb_strtolower($name))); $cache[$name] = $ret; } return $ret; } /** * Set the specified value to the specified tutorial link identifier. * * @param ID_TEXT $name The name of the value * @param SHORT_TEXT $value The value */ function set_tutorial_link($name, $value) { if (strpos($value, ':search:') !== false) { return; // Do not want tutorial links to search results page } if (get_tutorial_link($name) !== $value) { $GLOBALS['SITE_DB']->query_delete('tutorial_links', array('the_name' => cms_mb_strtolower($name)), '', 1); $GLOBALS['SITE_DB']->query_insert('tutorial_links', array('the_value' => $value, 'the_name' => cms_mb_strtolower($name)), false, true); // Allow failure, if there is a race condition } }