Example #1
0
/**
 * Convert a string to an array, with utf-8 awareness where possible/required.
 *
 * @param  string			Input
 * @param  boolean		Whether to force unicode as on.
 * @return array			Output
 */
function ocp_mb_str_split($str, $force = false)
{
    $len = ocp_mb_strlen($str, $force);
    $array = array();
    for ($i = 0; $i < $len; $i++) {
        $array[] = ocp_mb_substr($str, $i, 1, $force);
    }
    return $array;
}
Example #2
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)
 {
     $pos = strpos($codename, ':');
     if ($pos !== false) {
         require_lang(substr($codename, 0, $pos));
         $codename = substr($codename, $pos + 1);
     }
     global $LANGUAGE, $USER_LANG_CACHED, $RECORD_LANG_STRINGS, $XSS_DETECT, $PAGE_CACHE_FILE, $PAGE_CACHE_LANG_LOADED;
     if ($RECORD_LANG_STRINGS) {
         global $RECORDED_LANG_STRINGS;
         $RECORDED_LANG_STRINGS[$codename] = 1;
     }
     if ($lang === NULL) {
         $lang = $USER_LANG_CACHED === NULL ? user_lang() : $USER_LANG_CACHED;
     }
     if (!isset($LANGUAGE[$lang][$codename]) && (!array_key_exists($lang, $LANGUAGE) || !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 {
                     @rewind($PAGE_CACHE_FILE);
                     @ftruncate($PAGE_CACHE_FILE, 0);
                     @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
                 }
             }
             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]) && (!array_key_exists($lang, $LANGUAGE) || !array_key_exists($codename, $LANGUAGE[$lang]))) {
         if ($lang != fallback_lang()) {
             $ret = do_lang($codename, $token1, $token2, $token3, fallback_lang(), $require_result);
             if ($codename == 'charset') {
                 switch (strtolower($lang)) {
                     case 'ar':
                     case 'bg':
                     case 'zh-CN':
                     case 'zh-TW':
                     case 'hr':
                     case 'cs':
                     case 'da':
                     case 'nl':
                     case 'fi':
                     case 'fr':
                     case 'de':
                     case 'el':
                     case 'hi':
                     case 'it':
                     case 'ja':
                     case 'ko':
                     case 'pl':
                     case 'pt':
                     case 'ro':
                     case 'ru':
                     case 'es':
                     case 'sv':
                         $ret = 'utf-8';
                         break;
                 }
             } elseif (substr($codename, 0, 3) == 'FC_') {
                 $ret = ocp_mb_substr(trim(do_lang(substr($codename, 3), $token1, $token2, $token3, $lang)), 0, 1);
             } elseif ($codename == 'locale') {
                 $ret = strtolower($lang) . '_' . strtoupper($lang);
             } else {
                 $ret2 = strtolower($codename) != $codename ? google_translate($ret, $lang) : $ret;
                 if ($ret2 != $ret) {
                     $ret = $ret2;
                 }
             }
             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] = $ret;
                     // 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 {
                         @rewind($PAGE_CACHE_FILE);
                         @ftruncate($PAGE_CACHE_FILE, 0);
                         @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
                     }
                 }
             }
             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();
                 fatal_exit(do_lang_tempcode('MISSING_LANG_ENTRY', escape_html($codename)));
             } else {
                 return NULL;
             }
         }
     }
     if ($PAGE_CACHE_FILE !== NULL) {
         if (!isset($PAGE_CACHE_LANG_LOADED[$lang][$codename])) {
             $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 {
                 @rewind($PAGE_CACHE_FILE);
                 @ftruncate($PAGE_CACHE_FILE, 0);
                 @fwrite($PAGE_CACHE_FILE, serialize($PAGE_CACHE_LANG_LOADED));
             }
         }
     }
     // 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 : strtolower(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 : strtolower(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 : strtolower(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 : strtolower(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 : strtolower(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 #3
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;
}
Example #4
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 #5
0
 /**
  * Load up a language file, compiling it (it's not cached yet).
  *
  * @param  ID_TEXT			The language file name
  * @param  ?LANGUAGE_NAME	The language (NULL: uses the current language)
  * @param  ?string			The language type (lang_custom, or custom) (NULL: normal priorities are used)
  * @set    lang_custom custom
  * @param  PATH				Where we are cacheing too
  * @param  boolean			Whether to just return if there was a loading error
  * @return boolean			Whether we FAILED to load
  */
 function require_lang_compile($codename, $lang, $type, $cache_path, $ignore_errors = false)
 {
     global $LANGUAGE, $REQUIRE_LANG_LOOP, $LANG_LOADED_LANG;
     $desire_cache = function_exists('get_option') && (get_option('is_on_lang_cache', true) == '1' || get_param_integer('keep_cache', 0) == 1 || get_param_integer('cache', 0) == 1) && get_param_integer('keep_cache', NULL) !== 0 && get_param_integer('cache', NULL) !== 0;
     if ($desire_cache) {
         if ($GLOBALS['IN_MINIKERNEL_VERSION'] == 0) {
             global $DECACHED_COMCODE_LANG_STRINGS;
             // Cleanup language strings
             if (!$DECACHED_COMCODE_LANG_STRINGS) {
                 $DECACHED_COMCODE_LANG_STRINGS = true;
                 $comcode_lang_strings = $GLOBALS['SITE_DB']->query_select('cached_comcode_pages', array('string_index'), array('the_zone' => '!'), '', NULL, NULL, true);
                 if (!is_null($comcode_lang_strings)) {
                     $GLOBALS['SITE_DB']->query_delete('cached_comcode_pages', array('the_zone' => '!'));
                     foreach ($comcode_lang_strings as $comcode_lang_string) {
                         delete_lang($comcode_lang_string['string_index']);
                     }
                 }
             }
         }
         $load_target = array();
     } else {
         $load_target =& $LANGUAGE[$lang];
     }
     global $FILE_ARRAY;
     if (@is_array($FILE_ARRAY) && file_array_exists('lang/' . $lang . '/' . $codename . '.ini')) {
         $lang_file = 'lang/' . $lang . '/' . $codename . '.ini';
         $file = file_array_get($lang_file);
         _get_lang_file_map($file, $load_target, NULL, true);
         $bad = true;
     } else {
         $bad = true;
         $dirty = false;
         // Load originals
         $lang_file = get_file_base() . '/lang/' . $lang . '/' . filter_naughty($codename) . '.ini';
         if (file_exists($lang_file)) {
             _get_lang_file_map($lang_file, $load_target, NULL, false);
             $bad = false;
         }
         // Load overrides now if they are there
         if ($type != 'lang') {
             $lang_file = get_custom_file_base() . '/lang_custom/' . $lang . '/' . $codename . '.ini';
             if (!file_exists($lang_file) && get_file_base() != get_custom_file_base()) {
                 $lang_file = get_file_base() . '/lang_custom/' . $lang . '/' . $codename . '.ini';
             }
             if (!file_exists($lang_file)) {
                 $lang_file = get_custom_file_base() . '/lang_custom/' . $lang . '/' . $codename . '.po';
                 if (!file_exists($lang_file)) {
                     $lang_file = get_file_base() . '/lang_custom/' . $lang . '/' . $codename . '-' . strtolower($lang) . '.po';
                 }
             }
         }
         if ($type != 'lang' && file_exists($lang_file)) {
             _get_lang_file_map($lang_file, $load_target, NULL, false);
             $bad = false;
             $dirty = true;
             // Tainted from the official pack, so can't store server wide
         }
         // NB: Merge op doesn't happen in require_lang. It happens when do_lang fails and then decides it has to force a recursion to do_lang(xx,fallback_lang()) which triggers require_lang(xx,fallback_lang()) when it sees it's not loaded
         if ($bad && $lang != fallback_lang()) {
             require_lang($codename, fallback_lang(), $type, $ignore_errors);
             $REQUIRE_LANG_LOOP--;
             $fallback_cache_path = get_custom_file_base() . '/lang_cached/' . fallback_lang() . '/' . $codename . '.lcd';
             if (file_exists($fallback_cache_path)) {
                 require_code('files');
                 $fallback_map = unserialize(file_get_contents($fallback_cache_path));
                 $sep = '<span class="notranslate">----</span>';
                 $to_translate = '';
                 $i = 0;
                 $from = 0;
                 $lang_codes = array_keys($fallback_map);
                 foreach ($fallback_map as $value) {
                     if (strlen($to_translate . $sep . $to_translate) >= 3000) {
                         $translated = preg_split('#<span class="notranslate">[^<>]*----[^<>]*</span>#', google_translate($to_translate, $lang));
                         foreach ($translated as $j => $t_value) {
                             if (strtolower($lang_codes[$from + $j]) == $lang_codes[$from + $j]) {
                                 $t_value = $fallback_map[$lang_codes[$from + $j]];
                             }
                             if ($lang_codes[$from + $j] == 'locale') {
                                 $t_value = strtolower($lang) . '_' . strtoupper($lang);
                             }
                             $fallback_map[$lang_codes[$from + $j]] = $t_value;
                             $load_target[$lang_codes[$from + $j]] = $t_value;
                         }
                         $from = $i;
                         $to_translate = '';
                     }
                     if ($to_translate != '') {
                         $to_translate .= $sep;
                     }
                     $to_translate .= $value;
                     $i++;
                 }
                 $translated = preg_split('#<span class="notranslate">[^<>]*----[^<>]*</span>#', google_translate($to_translate, $lang));
                 foreach ($translated as $j => $t_value) {
                     if (strtolower($lang_codes[$from + $j]) == $lang_codes[$from + $j]) {
                         $t_value = $fallback_map[$lang_codes[$from + $j]];
                     }
                     if ($lang_codes[$from + $j] == 'locale') {
                         $t_value = strtolower($lang) . '_' . strtoupper($lang);
                     }
                     $fallback_map[$lang_codes[$from + $j]] = $t_value;
                     $load_target[$lang_codes[$from + $j]] = $t_value;
                 }
                 if (function_exists('ocp_mb_substr') && $codename == 'dates') {
                     foreach (array_keys($fallback_map) as $key) {
                         if (substr($key, 0, 3) == 'FC_') {
                             $test = ocp_mb_substr(trim($fallback_map[substr($key, 3)]), 0, 1, true);
                             if ($test !== false) {
                                 $fallback_map[$key] = $test;
                             }
                         }
                     }
                 }
                 $myfile = fopen($cache_path, 'wb');
                 fwrite($myfile, serialize($fallback_map));
                 fclose($myfile);
                 fix_permissions($cache_path);
             }
             if (!array_key_exists($lang, $LANG_LOADED_LANG)) {
                 $LANG_LOADED_LANG[$lang] = array();
             }
             $LANG_LOADED_LANG[$lang][$codename] = 1;
             if (!$bad) {
                 $LANGUAGE[$lang] += $fallback_map;
             }
             return $bad;
         }
         if ($bad) {
             if ($ignore_errors) {
                 return true;
             }
             if ($codename != 'critical_error' || $lang != get_site_default_lang()) {
                 fatal_exit(do_lang_tempcode('MISSING_LANG_FILE', escape_html($codename), escape_html($lang)));
             } else {
                 critical_error('CRIT_LANG');
             }
         }
     }
     if (is_null($GLOBALS['MEM_CACHE'])) {
         // Cache
         if ($desire_cache) {
             $file = @fopen($cache_path, 'wt');
             // Will fail if cache dir missing .. e.g. in quick installer
             if ($file) {
                 if (fwrite($file, serialize($load_target)) > 0) {
                     // Success
                     fclose($file);
                     require_code('files');
                     fix_permissions($cache_path);
                 } else {
                     // Failure
                     fclose($file);
                     @unlink($cache_path);
                 }
             }
         }
     } else {
         persistant_cache_set(array('LANG', $lang, $codename), $load_target, !$dirty);
     }
     if ($desire_cache) {
         $LANGUAGE[$lang] += $load_target;
     }
     return $bad;
 }