Example #1
0
/**
 * Get the text with all the smilie codes replaced with the correct XHTML. Smiles are determined by your forum system.
 * This is not used in the normal comcode chain - it's for non-comcode things that require smilies (actually in reality it is used in the Comcode chain if the optimiser sees that a full parse is not needed)
 *
 * @param  string			The text to add smilies to (assumption: that this is XHTML)
 * @return string			The XHTML with the image-substitution of smilies
 */
function apply_emoticons($text)
{
    $_smilies = $GLOBALS['FORUM_DRIVER']->find_emoticons();
    // Sorted in descending length order
    if ($GLOBALS['XSS_DETECT']) {
        $orig_escaped = ocp_is_escaped($text);
    }
    // Pre-check, optimisation
    $smilies = array();
    foreach ($_smilies as $code => $imgcode) {
        if (strpos($text, $code) !== false) {
            $smilies[$code] = $imgcode;
        }
    }
    if (count($smilies) != 0) {
        $len = strlen($text);
        for ($i = 0; $i < $len; ++$i) {
            $char = $text[$i];
            if ($char == '"') {
                $i++;
                continue;
            }
            foreach ($smilies 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;
}
Example #2
0
/**
 * Convert a language string into another language string.
 *
 * @param  mixed			The string to convert
 * @param  LONG_TEXT		The language to convert to
 * @return LONG_TEXT		The converted string
 */
function google_translate($str_in, $lang)
{
    $tempcode = is_object($str_in);
    $GLOBALS['NO_QUERY_LIMIT'] = true;
    if (get_option('enable_google_translate', true) !== '1') {
        return $str_in;
    }
    if ($tempcode) {
        $str_in = $str_in->evaluate();
    }
    global $DOING_TRANSLATE;
    if (!isset($DOING_TRANSLATE)) {
        $DOING_TRANSLATE = false;
    }
    if ($DOING_TRANSLATE) {
        return $tempcode ? protect_from_escaping($str_in) : $str_in;
    }
    // Don't want loops
    if ($str_in == '') {
        return $tempcode ? protect_from_escaping(escape_html('')) : escape_html('');
    }
    if (strpos($str_in, 'gtranslate_cache') !== false) {
        return $tempcode ? protect_from_escaping($str_in) : $str_in;
    }
    // Stop loops about corrupt/missing database tables
    $language_list = array('ar' => 'Arabic', 'bg' => 'Bulgarian', 'zh-cn' => 'Simplified Chinese', 'zh-tw' => 'Traditional Chinese', 'hr' => 'Croatian', 'cs' => 'Czech', 'da' => 'Danish', 'nl' => 'Dutch', 'en' => 'English', 'fi' => 'Finnish', 'fr' => 'French', 'de' => 'German', 'el' => 'Greek', 'hi' => 'Hindi', 'it' => 'Italian', 'ja' => 'Japanese', 'ko' => 'Korean', 'pl' => 'Polish', 'pt' => 'Portuguese', 'ro' => 'Romanian', 'ru' => 'Russian', 'es' => 'Spanish', 'sv' => 'Swedish');
    $lang = strtolower($lang);
    if (!array_key_exists($lang, $language_list)) {
        return $tempcode ? protect_from_escaping($str_in) : $str_in;
    }
    $DOING_TRANSLATE = true;
    require_lang('lang');
    $chache = check_google_cache($str_in, $lang);
    if (count($chache) == 0) {
        require_code('GTranslate');
        $translate = new GTranslate();
        $num_matches = array();
        $matches = array();
        $rep = array();
        $prepped = $str_in;
        $j = 0;
        foreach (array(array('[', ']'), array('{', '}')) as $symbol) {
            $_matches = array();
            $_num_matches = preg_match_all('#[' . preg_quote($symbol[0]) . '][^' . preg_quote($symbol[0]) . preg_quote($symbol[1]) . ']*[' . preg_quote($symbol[1]) . ']#', $str_in, $_matches);
            $matches[$symbol[0]] = $_matches;
            $num_matches[$symbol[0]] = $_num_matches;
            for ($i = 0; $i < $_num_matches; $i++) {
                $from = $_matches[0][$i];
                $to = '<span class="notranslate">' . strval($j) . '</span>';
                $rep['!' . strval($j)] = $from;
                // The '!' bit is because we can't trust indexing in PHP arrays if it is numeric
                $pos = 0;
                do {
                    $pos = strpos($prepped, $from, $pos);
                    if ($pos !== false) {
                        $pos_open = strrpos(substr($prepped, 0, $pos), '<');
                        $pos_close = strrpos(substr($prepped, 0, $pos), '>');
                        if ($pos_open === false || $pos_close !== false && $pos_close > $pos_open) {
                            $prepped = substr($prepped, 0, $pos) . $to . substr($prepped, $pos + strlen($from));
                            $pos += strlen($to);
                        } else {
                            $pos_title = strrpos(substr($prepped, 0, $pos), 'title="');
                            $pos_alt = strrpos(substr($prepped, 0, $pos), 'alt="');
                            $pos_quote = strrpos(substr($prepped, 0, $pos), '"');
                            if ($pos_alt !== false && $pos_alt > $pos_open && $pos_quote == $pos_alt + 4 || $pos_title !== false && $pos_title > $pos_open && $pos_quote == $pos_title + 6) {
                                $to2 = ' conv' . strval($j) . ' ';
                                $prepped = substr($prepped, 0, $pos) . $to2 . substr($prepped, $pos + strlen($from));
                                $pos += strlen($to2);
                            } else {
                                $pos += strlen($from);
                            }
                        }
                    }
                } while ($pos !== false);
                $j++;
            }
        }
        if (strpos(preg_replace('#<[^>]*>#', '', $prepped), '{') !== false) {
            $DOING_TRANSLATE = false;
            return $tempcode ? protect_from_escaping($str_in) : $str_in;
            // Cannot translate as it has very complex Tempcode in it
        }
        $to = $language_list[$lang];
        $from_lang = strtolower(get_site_default_lang());
        try {
            $convertedstring = $translate->Text($prepped)->From(array_key_exists($from_lang, $language_list) ? $language_list[$from_lang] : 'English')->To($to);
        } catch (Exception $e) {
        }
        if ($convertedstring === NULL) {
            $convertedstring = $str_in;
        }
        do {
            $before = $convertedstring;
            $convertedstring = preg_replace('#(<span class="notranslate">\\d+) (.*</span>)#', '${1}</span> <span class="notranslate">${2}', $convertedstring);
        } while ($before != $convertedstring);
        foreach (array_reverse($rep) as $_j => $from) {
            $j = intval(substr($_j, 1));
            $convertedstring = preg_replace('#\\s*<span class="notranslate">\\s*' . preg_quote(strval($j)) . '\\s*</span>\\s*#', $from, $convertedstring);
            $convertedstring = preg_replace('# conv' . preg_quote(strval($j)) . '\\s*#', $from, $convertedstring);
        }
        $convertedstring = str_replace('<html> ', '', $convertedstring);
        $convertedstring = str_replace('&#39;', '', $convertedstring);
        save_google_cache($str_in, $lang, $convertedstring);
        $str = $convertedstring;
    } else {
        $str = $chache['t_result'];
    }
    $DOING_TRANSLATE = false;
    if (function_exists('ocp_mark_as_escaped') && ocp_is_escaped($str_in)) {
        ocp_mark_as_escaped($str);
    }
    return $tempcode ? protect_from_escaping($str) : $str;
}
Example #3
0
/**
 * Function that 'fixes' HTML (or bad XHTML) enough for it to pass most basic structural validation.
 *
 * @param  string			The XHTML string to convert to XHTML
 * @param  boolean		Whether to force a repair even if we aren't in XHTML mode
 * @return string			The converted string
 */
function xhtmlise_html($html, $definitely_want = false)
{
    // Tests...
    // echo xhtmlise_html('test<a></a><br /><po></p><p></po>'); // expect: test<a></a><br /><po><p></p></po>
    if (!$definitely_want) {
        if (!($GLOBALS['SEMI_DEBUG_MODE'] && browser_matches('true_xhtml'))) {
            return $html;
        }
        // One day, this will get removed and we'll ensure all our output is always XHTML. But so far there's no point as IE doesn't support true XHTML
    }
    $is_escaped = $GLOBALS['XSS_DETECT'] && ocp_is_escaped($html);
    $html = preg_replace('#<\\!--.*($|-->)#Us', '', $html);
    // Strip comments
    require_code('obfuscate');
    require_code('validation');
    global $XML_CONSTRAIN, $LAST_TAG_ATTRIBUTES, $POS, $OUT, $TAG_STACK, $INBETWEEN_TEXT, $LEN, $WELL_FORMED_ONLY, $MUST_SELFCLOSE_TAGS, $LINENO, $LINESTART;
    $POS = 0;
    $OUT = $html;
    $LEN = strlen($html);
    $TAG_STACK = array();
    $WELL_FORMED_ONLY = true;
    $LINENO = 0;
    $LINESTART = 0;
    $XML_CONSTRAIN = true;
    $new = '';
    $token = _get_next_tag();
    // If we actually have a partial tag right at the start (ie. we're breaking into some HTML at a bad point)
    $ang_pos = strpos($INBETWEEN_TEXT, '>');
    if ($ang_pos !== false) {
        $INBETWEEN_TEXT = substr($INBETWEEN_TEXT, $ang_pos + 1);
    }
    $new .= fix_entities($INBETWEEN_TEXT);
    while (!is_null($token)) {
        while (is_array($token)) {
            if ($token[0] !== NULL) {
                $token = $token[0];
                // We can at least discern something
            } else {
                $token = _get_next_tag();
                // No, we need to just move on
            }
        }
        $basis_token = _get_tag_basis($token);
        if ($basis_token != '') {
            // Open, close, or monitonic?
            $term = strpos($token, '/');
            if ($term !== 1) {
                if ($term === false && !isset($MUST_SELFCLOSE_TAGS[$basis_token])) {
                    // Fix nesting
                    if ($basis_token == 'li' && !in_array('ul', $TAG_STACK) && !in_array('ol', $TAG_STACK) && !in_array('dl', $TAG_STACK) && !in_array('dd', $TAG_STACK) && !in_array('dt', $TAG_STACK) && !in_array('dir', $TAG_STACK) && !in_array('menu', $TAG_STACK)) {
                        array_push($TAG_STACK, 'ul');
                        $new .= '<ul>';
                    }
                    if (($basis_token == 'tr' || $basis_token == 'colgroup' || $basis_token == 'col' || $basis_token == 'tbody' || $basis_token == 'tfoot' || $basis_token == 'thead' || $basis_token == 'caption') && !in_array('table', $TAG_STACK)) {
                        array_push($TAG_STACK, 'table');
                        $new .= '<table>';
                    }
                    if (($basis_token == 'td' || $basis_token == 'th') && !in_array('table', $TAG_STACK)) {
                        array_push($TAG_STACK, 'table');
                        $new .= '<table>';
                        array_push($TAG_STACK, 'tr');
                        $new .= '<tr>';
                    }
                    if ($basis_token == 'param' && !in_array('object', $TAG_STACK)) {
                        array_push($TAG_STACK, 'object');
                        $new .= '<object>';
                    }
                    if ($basis_token == 'option' && !in_array('select', $TAG_STACK)) {
                        array_push($TAG_STACK, 'select');
                        $new .= '<select>';
                    }
                    if ($basis_token == 'noembed' && !in_array('map', $TAG_STACK)) {
                        array_push($TAG_STACK, 'map');
                        $new .= '<map>';
                    }
                    array_push($TAG_STACK, $basis_token);
                    $new .= '<' . $basis_token;
                    foreach ($LAST_TAG_ATTRIBUTES as $key => $val) {
                        $new .= ' ' . $key . '="' . fix_entities($val) . '"';
                    }
                    $new .= '>';
                } else {
                    $new .= '<' . $basis_token;
                    foreach ($LAST_TAG_ATTRIBUTES as $key => $val) {
                        $new .= ' ' . $key . '="' . fix_entities($val) . '"';
                    }
                    $new .= ' />';
                }
            } else {
                // For case 3
                if (!in_array($basis_token, $TAG_STACK)) {
                    // Do nothing, we can't handle it because we're closing something that was never opened
                } else {
                    $previous = '';
                    do {
                        $previous = array_pop($TAG_STACK);
                        if ($basis_token != $previous) {
                            $new .= '</' . $previous . '>';
                        }
                        // We'll have to assume it should be implicitly closed
                    } while ($basis_token != $previous);
                    $new .= '</' . $basis_token . '>';
                    // Ok so we finally got an opener match and managed to put out our closer
                }
            }
        }
        $token = _get_next_tag();
        if (is_null($token)) {
            // If we actually have a partial tag right at the end (ie. we're breaking out of some HTML at a bad point)
            $ang_pos = strpos($INBETWEEN_TEXT, '<');
            if ($ang_pos !== false) {
                $INBETWEEN_TEXT = substr($INBETWEEN_TEXT, 0, $ang_pos);
            }
        }
        $new .= fix_entities($INBETWEEN_TEXT);
    }
    // Check we have everything closed
    while (count($TAG_STACK) != 0) {
        $previous = array_pop($TAG_STACK);
        $new .= '</' . $previous . '>';
    }
    // Remove some empty tags that shouldn't be empty (e.g. table)
    $may_not_be_empty = array('br', 'hr', 'table', 'tbody', 'tfoot', 'thead', 'tr', 'dd', 'dt', 'dl', 'li', 'ol', 'ul', 'rbc', 'rtc', 'rb', 'rt', 'rp', 'abbr', 'acronym', 'cite', 'dfn', 'ruby', 'bdo', 'img', 'param', 'input', 'select', 'object', 'caption', 'label', 'base', 'body', 'col', 'colgroup', 'map', 'optgroup', 'option', 'legend', 'area', 'form');
    foreach ($may_not_be_empty as $t) {
        $new = preg_replace('#<' . $t . '(\\s[^>]*)?' . '>\\s*</' . $t . '>#', '', $new);
    }
    unset($OUT);
    unset($TAG_STACK);
    if ($is_escaped) {
        ocp_mark_as_escaped($new);
    }
    return $new;
}
Example #4
0
    /**
     * Output an XML-RPC packet (hopefully) to the AJAX in the frontend.
     *
     * @return boolean			Success?
     */
    function output_xml()
    {
        if (count($this->parsed_input) < 1) {
            return false;
        }
        header('Content-Type: text/xml');
        header('HTTP/1.0 200 Ok');
        if (is_object($this->output[STREAM_STDCOMMAND])) {
            $this->output[STREAM_STDCOMMAND] = $this->output[STREAM_STDCOMMAND]->evaluate();
        }
        if (is_object($this->output[STREAM_STDHTML])) {
            $this->output[STREAM_STDHTML] = $this->output[STREAM_STDHTML]->evaluate();
        }
        if (is_object($this->output[STREAM_STDOUT])) {
            $this->output[STREAM_STDOUT] = $this->output[STREAM_STDOUT]->evaluate();
        }
        if (is_object($this->output[STREAM_STDERR])) {
            $this->output[STREAM_STDERR] = $this->output[STREAM_STDERR]->evaluate();
        }
        $output = '<' . '?xml version="1.0" encoding="utf-8" ?' . '>
<response>
	<result>
		<command>' . xmlentities($this->current_input) . '</command>
		<stdcommand>' . $this->output[STREAM_STDCOMMAND] . '</stdcommand>
		<stdhtml><div xmlns="http://www.w3.org/1999/xhtml">' . $this->output[STREAM_STDHTML] . '</div></stdhtml>
		<stdout>' . xmlentities($this->output[STREAM_STDOUT]) . '</stdout>
		<stderr>' . xmlentities($this->output[STREAM_STDERR]) . '</stderr>
		<stdnotifications>' . get_queued_messages() . '</stdnotifications>
	</result>
</response>';
        if ($GLOBALS['XSS_DETECT']) {
            if (ocp_is_escaped($this->output[STREAM_STDHTML])) {
                ocp_mark_as_escaped($output);
            }
        }
        echo $output;
        set_value('last_occle_command', strval(time()));
        return true;
    }
Example #5
0
/**
 * Get the human-readable form of a language id, or a language entry from a language INI file.
 *
 * @param  ID_TEXT		The language id
 * @param  ?mixed			The first token [string or tempcode] (replaces {1}) (NULL: none)
 * @param  ?mixed			The second token [string or tempcode] (replaces {2}) (NULL: none)
 * @param  ?mixed			The third token (replaces {3}). May be an array of [of string], to allow any number of additional args (NULL: none)
 * @param  ?LANGUAGE_NAME The language to use (NULL: users language)
 * @param  boolean		Whether to cause ocPortal to exit if the lookup does not succeed
 * @return ?mixed			The human-readable content (NULL: not found). String normally. Tempcode if tempcode parameters.
 */
function _do_lang($codename, $token1 = NULL, $token2 = NULL, $token3 = NULL, $lang = NULL, $require_result = true)
{
    global $LANGUAGE, $USER_LANG_CACHED, $RECORD_LANG_STRINGS, $XSS_DETECT, $PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED;
    if ($lang === NULL) {
        $lang = $USER_LANG_CACHED === NULL ? user_lang() : $USER_LANG_CACHED;
    }
    if ($GLOBALS['SEMI_DEBUG_MODE']) {
        $pos = strpos($codename, '=');
        if ($pos !== false) {
            // Find loaded file with smallest levenstein distance to current page
            $best = mixed();
            $best_for = NULL;
            global $LANGS_REQUESTED;
            foreach (array_keys($LANGS_REQUESTED) as $possible) {
                $dist = levenshtein(get_page_name(), $possible);
                if (is_null($best) || $best > $dist) {
                    $best = $dist;
                    $best_for = $possible;
                }
            }
            $save_path = get_file_base() . '/lang/' . fallback_lang() . '/' . $best_for . '.ini';
            if (!is_file($save_path)) {
                $save_path = get_file_base() . '/lang_custom/' . fallback_lang() . '/' . $best_for . '.ini';
            }
            // Tack language strings onto this file
            list($codename, $value) = explode('=', $codename, 2);
            $myfile = fopen($save_path, 'at');
            fwrite($myfile, "\n" . $codename . '=' . $value);
            fclose($myfile);
            // Fake-load the string
            $LANGUAGE[$lang][$codename] = $value;
            // Go through all required files, doing a string replace if needed
            $included_files = get_included_files();
            foreach ($included_files as $inc) {
                $orig_contents = file_get_contents($inc);
                $contents = str_replace("'" . $codename . '=' . $value . "'", "'" . $codename . "'", $orig_contents);
                if ($orig_contents != $contents) {
                    $myfile = fopen($inc, 'wt');
                    fwrite($myfile, $contents);
                    fclose($myfile);
                }
            }
        }
    }
    $there = isset($LANGUAGE[$lang][$codename]);
    if (!$there) {
        $pos = strpos($codename, ':');
        if ($pos !== false) {
            require_lang(substr($codename, 0, $pos), NULL, NULL, !$require_result);
            $codename = substr($codename, $pos + 1);
        }
        $there = isset($LANGUAGE[$lang][$codename]);
    }
    if ($RECORD_LANG_STRINGS) {
        global $RECORDED_LANG_STRINGS;
        $RECORDED_LANG_STRINGS[$codename] = 1;
    }
    if (!$there && (!isset($LANGUAGE[$lang]) || !array_key_exists($codename, $LANGUAGE[$lang]))) {
        global $PAGE_CACHE_LAZY_LOAD, $PAGE_CACHE_LANGS_REQUESTED, $LANG_REQUESTED_LANG;
        if ($PAGE_CACHE_LAZY_LOAD) {
            $PAGE_CACHE_LAZY_LOAD = false;
            // We can't be lazy any more, but we will keep growing our pool so hopefully CAN be lazy the next time
            foreach ($PAGE_CACHE_LANGS_REQUESTED as $request) {
                list($that_codename, $that_lang) = $request;
                unset($LANG_REQUESTED_LANG[$that_lang][$that_codename]);
                require_lang($that_codename, $that_lang, NULL, true);
            }
            $ret = _do_lang($codename, $token1, $token2, $token3, $lang, $require_result);
            if ($ret === NULL) {
                $PAGE_CACHE_LANG_LOADED[$lang][$codename] = NULL;
                if ($GLOBALS['MEM_CACHE'] !== NULL) {
                    persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED);
                } else {
                    open_page_cache_file();
                    @rewind($PAGE_CACHE_FILE);
                    @flock($PAGE_CACHE_FILE, LOCK_EX);
                    @ftruncate($PAGE_CACHE_FILE, 0);
                    @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
                    @flock($PAGE_CACHE_FILE, LOCK_UN);
                }
            }
            return $ret;
        }
        require_all_open_lang_files($lang);
    }
    if ($lang == 'xxx') {
        return 'xxx';
    }
    // Helpful for testing language compliancy. We don't expect to see non x's if we're running this language
    if (!isset($LANGUAGE[$lang][$codename]) && ($require_result || !isset($LANGUAGE[$lang]) || !array_key_exists($codename, $LANGUAGE[$lang]))) {
        if ($lang != fallback_lang()) {
            $ret = do_lang($codename, $token1, $token2, $token3, fallback_lang(), $require_result);
            if ($PAGE_CACHE_FILE !== NULL) {
                if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename]) && isset($PAGE_CACHE_LANG_LOADED[fallback_lang()][$codename])) {
                    $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $PAGE_CACHE_LANG_LOADED[fallback_lang()][$codename];
                    // Will have been cached into fallback_lang() from the nested do_lang call, we need to copy it into our cache bucket for this language
                    if ($GLOBALS['MEM_CACHE'] !== NULL) {
                        persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED);
                    } else {
                        open_page_cache_file();
                        @rewind($PAGE_CACHE_FILE);
                        @flock($PAGE_CACHE_FILE, LOCK_EX);
                        @ftruncate($PAGE_CACHE_FILE, 0);
                        @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
                        @flock($PAGE_CACHE_FILE, LOCK_UN);
                    }
                }
            }
            return $ret;
        } else {
            if ($require_result) {
                global $USER_LANG_LOOP, $REQUIRE_LANG_LOOP;
                //print_r(debug_backtrace());
                if ($USER_LANG_LOOP == 1) {
                    critical_error('RELAY', 'Missing language code: ' . escape_html($codename) . '. This language code is required to produce error messages, and thus a critical error was prompted by the non-ability to show less-critical error messages. It is likely the source language files (lang/' . fallback_lang() . '/*.ini) for ocPortal on this website have been corrupted.');
                }
                if ($REQUIRE_LANG_LOOP >= 2) {
                    return '';
                }
                // Probably failing to load global.ini, so just output with some text missing
                require_code('view_modes');
                erase_cached_language();
                require_code('site');
                attach_message(do_lang_tempcode('MISSING_LANG_ENTRY', escape_html($codename)), 'warn');
                return '';
            } else {
                return NULL;
            }
        }
    }
    if ($PAGE_CACHE_FILE !== NULL) {
        if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename]) && (!isset($PAGE_CACHE_LANG_LOADED[$lang]) || !array_key_exists($codename, $PAGE_CACHE_LANG_LOADED[$lang]))) {
            $PAGE_CACHE_LANG_LOADED[$lang][$codename] = $LANGUAGE[$lang][$codename];
            if ($GLOBALS['MEM_CACHE'] !== NULL) {
                persistant_cache_set($PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED);
            } else {
                open_page_cache_file();
                @rewind($PAGE_CACHE_FILE);
                @flock($PAGE_CACHE_FILE, LOCK_EX);
                @ftruncate($PAGE_CACHE_FILE, 0);
                @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
                @flock($PAGE_CACHE_FILE, LOCK_UN);
            }
        }
    }
    // Put in parameters
    static $non_plural_non_vowel = array('1', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', '{');
    $looked_up = $LANGUAGE[$lang][$codename];
    if ($looked_up === NULL) {
        return NULL;
        // Learning cache pool has told us this string definitely does not exist
    }
    $out = str_replace('\\n', "\n", $looked_up);
    $plural_or_vowel_check = strpos($out, '|') !== false;
    if ($XSS_DETECT) {
        ocp_mark_as_escaped($out);
    }
    if ($token1 !== NULL) {
        if (is_object($token1) && $token2 === NULL || $token2 !== NULL && is_object($token2)) {
            $bits = preg_split('#\\{\\d[^\\}]*\\}#', $out, 2, PREG_SPLIT_OFFSET_CAPTURE);
            $ret = new ocp_tempcode();
            foreach ($bits as $bit) {
                if ($XSS_DETECT) {
                    ocp_mark_as_escaped($bit[0]);
                }
                $at = $bit[1];
                if ($at != 0) {
                    if ($out[$at - 2] == '1') {
                        $ret->attach($token1);
                    } elseif ($out[$at - 2] == '2') {
                        $ret->attach($token2);
                    } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '1|') {
                        $exploded = explode('|', $out[$at - 2]);
                        $_token = $token1->evaluate();
                        $_token_denum = str_replace(',', '', $_token);
                        $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]);
                    } elseif ($plural_or_vowel_check && substr($out[$at - 2], 0, 2) == '2|') {
                        $exploded = explode('|', $out[$at - 2]);
                        $_token = $token2->evaluate();
                        $_token_denum = str_replace(',', '', $_token);
                        $ret->attach(in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($_token, 0, 1)), $non_plural_non_vowel) ? $exploded[1] : $exploded[2]);
                    }
                }
                $ret->attach($bit[0]);
            }
            return $ret;
        } elseif ($token1 !== NULL) {
            $out = str_replace('{1}', $token1, $out);
            if ($plural_or_vowel_check) {
                $_token_denum = str_replace(',', '', $token1);
                $out = preg_replace('#\\{1\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token1, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out);
            }
            if ($XSS_DETECT && ocp_is_escaped($token1)) {
                ocp_mark_as_escaped($out);
            }
        }
        if ($token2 !== NULL) {
            if ($XSS_DETECT) {
                $escaped = ocp_is_escaped($out);
            }
            $out = str_replace('{2}', $token2, $out);
            if ($plural_or_vowel_check) {
                $_token_denum = str_replace(',', '', $token1);
                $out = preg_replace('#\\{2\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token2, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out);
            }
            if ($XSS_DETECT && ocp_is_escaped($token2) && $escaped) {
                ocp_mark_as_escaped($out);
            }
            if ($token3 !== NULL) {
                $i = 3;
                if (!is_array($token3)) {
                    $token3 = array($token3);
                }
                foreach ($token3 as $token) {
                    if ($XSS_DETECT) {
                        $escaped = ocp_is_escaped($out);
                    }
                    $out = str_replace('{' . strval($i) . '}', $token, $out);
                    if ($plural_or_vowel_check) {
                        $_token_denum = str_replace(',', '', $token);
                        $out = preg_replace('#\\{' . strval($i) . '\\|(.*)\\|(.*)\\}#U', in_array(is_numeric($_token_denum) ? $_token_denum : ocp_mb_strtolower(ocp_mb_substr($token, 0, 1)), $non_plural_non_vowel) ? '\\1' : '\\2', $out);
                    }
                    if ($XSS_DETECT && ocp_is_escaped($token) && $escaped) {
                        ocp_mark_as_escaped($out);
                    }
                    $i++;
                }
            }
        }
    }
    return $out;
}
Example #6
0
/**
 * Handle truncation symbols in all their complexity
 *
 * @param  array			Parameters passed to the symbol (0=text, 1=amount, 2=tooltip?, 3=is_html?, 4=use as grammatical length rather than HTML byte length, 5=fractional-deviation-tolerance for grammar-preservation)
 * @param  string			The type of truncation to do
 * @set    left right spread
 * @param  ?mixed			Tooltip to add on, but only if we end up creating our own tooltip (NULL: none)
 * @return string			The result.
 */
function symbol_truncator($param, $type, $tooltip_if_truncated = NULL)
{
    $value = '';
    if (is_object($param[0])) {
        $param[0] = $param[0]->evaluate();
        if (!isset($param[2])) {
            $param[2] = '0';
        }
        $param[3] = '1';
    }
    if ($GLOBALS['XSS_DETECT']) {
        $is_escaped = ocp_is_escaped($param[0]);
    }
    $amount = intval(isset($param[1]) ? $param[1] : '60');
    $is_html = isset($param[3]) && $param[3] == '1';
    if ($is_html) {
        $not_html = @html_entity_decode(strip_tags($param[0]), ENT_QUOTES, get_charset());
        // In case it contains HTML. This is imperfect, but having to cut something up is imperfect from the offset.
        $html = $param[0];
        if ($GLOBALS['XSS_DETECT']) {
            ocp_mark_as_escaped($html);
        }
        if ($html == $not_html && strpos($html, '&') === false && strpos($html, '<') === false) {
            $is_html = false;
        }
        // Conserve memory
    } else {
        $not_html = $param[0];
        $html = escape_html($param[0]);
    }
    if (ocp_mb_strlen($not_html) > $amount) {
        $tooltip = isset($param[2]) && $param[2] == '1';
        $literal_pos = isset($param[4]) ? $param[4] == '1' : false;
        $grammar_completeness_tolerance = isset($param[5]) ? floatval($param[5]) : 0.0;
        if ($is_html || $grammar_completeness_tolerance != 0.0) {
            require_code('xhtml');
        }
        $truncated = $not_html;
        switch ($type) {
            case 'left':
                $temp = $is_html || $grammar_completeness_tolerance != 0.0 ? xhtml_substr($html, 0, $amount - 3, $literal_pos, false, $grammar_completeness_tolerance) : escape_html(ocp_mb_substr($not_html, 0, $amount - 3));
                if ($temp != $html && in_array(substr($temp, -1), array('.', '?', '!'))) {
                    $temp .= '<br />';
                }
                // so the "..." does not go right after the sentence terminator
                $truncated = $temp == $html ? $temp : str_replace(array('</p>&hellip;', '</div>&hellip;'), array('&hellip;</p>', '&hellip;</div>'), rtrim($temp) . '&hellip;');
                break;
            case 'expand':
                $temp = $is_html || $grammar_completeness_tolerance != 0.0 ? xhtml_substr($html, 0, $amount - 3, $literal_pos, false, $grammar_completeness_tolerance) : escape_html(ocp_mb_substr($not_html, 0, $amount - 3));
                if ($temp != $html && in_array(substr($temp, -1), array('.', '?', '!'))) {
                    $temp .= '<br />';
                }
                // so the "..." does not go right after the sentence terminator
                $_truncated = do_template('COMCODE_HIDE', array('TEXT' => protect_from_escaping($temp), 'CONTENT' => protect_from_escaping($html)));
                $truncated = $_truncated->evaluate();
                break;
            case 'right':
                $truncated = str_replace(array('</p>&hellip;', '</div>&hellip;'), array('&hellip;</p>', '&hellip;</div>'), '&hellip;' . ltrim($is_html || $grammar_completeness_tolerance != 0.0 ? xhtml_substr($html, -$amount - 3, NULL, $literal_pos, false, $grammar_completeness_tolerance) : escape_html(ocp_mb_substr($not_html, -$amount - 3))));
                break;
            case 'spread':
                $pos = intval(floor(floatval($amount) / 2.0)) - 1;
                $truncated = str_replace(array('</p>&hellip;', '</div>&hellip;'), array('&hellip;</p>', '&hellip;</div>'), rtrim(($is_html || $grammar_completeness_tolerance != 0.0 ? xhtml_substr($html, 0, $pos, $literal_pos, false, $grammar_completeness_tolerance) : escape_html(ocp_mb_substr($not_html, 0, $pos))) . '&hellip;' . ltrim($is_html || $grammar_completeness_tolerance != 0.0 ? xhtml_substr($html, -$pos - 1) : escape_html(ocp_mb_substr($not_html, -$pos - 1)))));
                break;
        }
        if ($tooltip) {
            if (!is_null($tooltip_if_truncated)) {
                $tif = is_object($tooltip_if_truncated) ? $tooltip_if_truncated->evaluate() : $tooltip_if_truncated;
                if (strpos($tif, $html) !== false) {
                    $html = $tif;
                } else {
                    $html .= ' &ndash; ' . $tif;
                }
            }
            $tpl = strpos($truncated, '<div') !== false || strpos($truncated, '<p') !== false || strpos($truncated, '<table') !== false ? 'CROP_TEXT_MOUSE_OVER' : 'CROP_TEXT_MOUSE_OVER_INLINE';
            $value_tempcode = do_template($tpl, array('_GUID' => '36ae945ed864633cfa0d67e5c3f2d1c8', 'TEXT_SMALL' => $truncated, 'TEXT_LARGE' => $html));
            $value = $value_tempcode->evaluate();
            if ($GLOBALS['XSS_DETECT']) {
                ocp_mark_as_escaped($value);
            }
        } else {
            $value = $truncated;
        }
    } else {
        $value = $html;
    }
    if ($GLOBALS['XSS_DETECT']) {
        if ($is_escaped || !$is_html) {
            ocp_mark_as_escaped($value);
        }
    }
    return $value;
}