示例#1
0
/**
 * Compile a template into a list of appendable outputs, for the closure-style Tempcode implementation.
 *
 * @param  string			The template file contents
 * @param  ID_TEXT		The name of the template
 * @param  ID_TEXT		The name of the theme
 * @param  ID_TEXT		The language it is for
 * @param  boolean		Whether to tolerate errors
 * @return array			A pair: array Compiled result structure, array preprocessable bits (special stuff needing attention that is referenced within the template)
 */
function compile_template($data, $template_name, $theme, $lang, $tolerate_errors = false)
{
    if (strpos($data, '{$,Parser hint: pure}') !== false) {
        return array(array('"' . php_addslashes(preg_replace('#\\{\\$,.*\\}#U', '/*no minify*/', $data)) . '"'), array());
    }
    $data = preg_replace('#<\\?php(.*)\\?' . '>#sU', '{+START,PHP}${1}{+END}', $data);
    $compilable_symbols = array('"ADDON_INSTALLED"', '"COPYRIGHT"', '"SITE_NAME"', '"BRAND_BASE_URL"', '"BRAND_NAME"', '"IMG_WIDTH"', '"IMG_HEIGHT"', '"LANG"', '"THEME"', '"VALUE_OPTION"', '"CONFIG_OPTION"');
    if (function_exists('get_option') && get_option('enable_https', true) != '1') {
        $compilable_symbols[] = '"BASE_URL"';
    }
    global $SITE_INFO;
    if (isset($SITE_INFO['no_keep_params']) && $SITE_INFO['no_keep_params'] == '1') {
        $compilable_symbols[] = '"PAGE_LINK"';
        $compilable_symbols[] = '"FIND_SCRIPT"';
    }
    require_code('lang');
    require_code('urls');
    $cl = fallback_lang();
    $bits = array_values(preg_split('#(?<!\\\\)(\\{(?=[\\dA-Z\\$\\+\\!\\_]+[\\.`%\\*=\\;\\#\\-~\\^\\|\'&/@]*))|((?<!\\\\)\\,)|((?<!\\\\)\\})#', $data, -1, PREG_SPLIT_DELIM_CAPTURE));
    // One error mail showed on a server it had weird indexes, somehow. Hence the array_values call to reindex it
    $count = count($bits);
    $stack = array();
    $current_level_mode = PARSE_NO_MANS_LAND;
    $current_level_data = array();
    $current_level_params = array();
    $preprocessable_bits = array();
    for ($i = 0; $i < $count; $i++) {
        $next_token = $bits[$i];
        if ($next_token == '') {
            continue;
        }
        if ($i != $count - 1 && $next_token == '{' && preg_match('#^[\\dA-Z\\$\\+\\!\\_]#', $bits[$i + 1]) == 0) {
            $current_level_data[] = '"{}"';
            continue;
        }
        switch ($next_token) {
            case '{':
                // Open a new level
                $stack[] = array($current_level_mode, $current_level_data, $current_level_params, NULL, NULL, NULL);
                ++$i;
                $next_token = isset($bits[$i]) ? $bits[$i] : NULL;
                if (is_null($next_token)) {
                    if ($tolerate_errors) {
                        continue;
                    }
                    warn_exit(do_lang_tempcode('ABRUPTED_DIRECTIVE_OR_BRACE', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
                }
                $current_level_data = array();
                switch (substr($next_token, 0, 1)) {
                    case '$':
                        $current_level_mode = PARSE_SYMBOL;
                        $current_level_data[] = '"' . php_addslashes(substr($next_token, 1)) . '"';
                        break;
                    case '+':
                        $current_level_mode = PARSE_DIRECTIVE;
                        $current_level_data[] = '"' . php_addslashes(substr($next_token, 1)) . '"';
                        break;
                    case '!':
                        $current_level_mode = PARSE_LANGUAGE_REFERENCE;
                        $current_level_data[] = '"' . php_addslashes(substr($next_token, 1)) . '"';
                        break;
                    default:
                        $current_level_mode = PARSE_PARAMETER;
                        $current_level_data[] = '"' . php_addslashes($next_token) . '"';
                        break;
                }
                $current_level_params = array();
                break;
            case '}':
                if (count($stack) == 0 || $current_level_mode == PARSE_DIRECTIVE_INNER) {
                    $literal = php_addslashes($next_token);
                    if ($GLOBALS['XSS_DETECT']) {
                        ocp_mark_as_escaped($literal);
                    }
                    $current_level_data[] = '"' . $literal . '"';
                    break;
                }
                $opener_params = array_merge($current_level_params, array($current_level_data));
                $__first_param = array_shift($opener_params);
                $_first_param = implode('.', $__first_param);
                if ($bits[$i - 1] == '') {
                    $current_level_data[] = '""';
                }
                // Return to the previous level
                $past_level_data = $current_level_data;
                $past_level_params = $current_level_params;
                $past_level_mode = $current_level_mode;
                if (count($stack) == 0) {
                    if (!$tolerate_errors) {
                        warn_exit(do_lang_tempcode('TEMPCODE_TOO_MANY_CLOSES', escape_html($template_name), integer_format(1 + _length_so_far($bits, $i))));
                    }
                } else {
                    list($current_level_mode, $current_level_data, $current_level_params, , , ) = array_pop($stack);
                }
                // Handle the level we just closed
                if (function_exists('str_split')) {
                    $_escaped = str_split(preg_replace('#[^:\\.`%\\*=\\;\\#\\-~\\^\\|\'&/@]:?#', '', $_first_param));
                    // :? is so that the ":" in lang strings does not get considered an escape
                } else {
                    $temp = preg_replace('#[^:\\.`%\\*=\\;\\#\\-~\\^\\|\'&/@]:?#', '', $_first_param);
                    $_escaped = array();
                    for ($j = 0; $j < strlen($temp); $j++) {
                        $_escaped[] = $temp[$j];
                    }
                }
                $escaped = array();
                foreach ($_escaped as $e) {
                    switch ($e) {
                        case '`':
                            $escaped[] = NULL_ESCAPED;
                            break;
                        case '%':
                            $escaped[] = NAUGHTY_ESCAPED;
                            break;
                        case '*':
                            $escaped[] = ENTITY_ESCAPED;
                            break;
                        case '=':
                            $escaped[] = FORCIBLY_ENTITY_ESCAPED;
                            break;
                        case ';':
                            $escaped[] = SQ_ESCAPED;
                            break;
                        case '#':
                            $escaped[] = DQ_ESCAPED;
                            break;
                        case '~':
                            $escaped[] = NL_ESCAPED;
                            break;
                        case '^':
                            $escaped[] = NL2_ESCAPED;
                            break;
                        case '|':
                            $escaped[] = ID_ESCAPED;
                            break;
                        case '\'':
                            $escaped[] = CSS_ESCAPED;
                            break;
                        case '&':
                            $escaped[] = UL_ESCAPED;
                            break;
                        case '.':
                            $escaped[] = UL2_ESCAPED;
                            break;
                        case '/':
                            $escaped[] = JSHTML_ESCAPED;
                            break;
                        case '@':
                            $escaped[] = CC_ESCAPED;
                            break;
                            // This is used as a hint to not preprocess
                        // This is used as a hint to not preprocess
                        case '-':
                    }
                }
                $_opener_params = '';
                foreach ($opener_params as $param) {
                    if ($param == array()) {
                        $param = array('""');
                    }
                    if ($_opener_params != '') {
                        $_opener_params .= ',';
                    }
                    $_opener_params .= implode('.', $param);
                }
                $first_param = str_replace(array('`', '%', '*', '=', ';', '#', '-', '~', '^', '|', '\'', '&', '.', '/', '@'), array('', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), $_first_param);
                switch ($past_level_mode) {
                    case PARSE_SYMBOL:
                        $no_preprocess = in_array('-', $_escaped);
                        if (!$no_preprocess) {
                            switch ($first_param) {
                                case '"CSS_INCLUDE"':
                                case '"JAVASCRIPT_INCLUDE"':
                                case '"JS_TEMPCODE"':
                                case '"CSS_TEMPCODE"':
                                case '"SET"':
                                case '"BLOCK"':
                                case '"LOAD_PAGE"':
                                case '"LOAD_PANEL"':
                                    foreach ($stack as $level_test) {
                                        if ($level_test[3] == PARSE_DIRECTIVE && isset($level_test[5][1]) && isset($level_test[5][1][0]) && $level_test[5][1][0] == '"LOOP"') {
                                            $eval = @eval('return array(' . $_opener_params . ');');
                                            if (is_array($eval)) {
                                                $pp_bit = array(array(), TC_SYMBOL, str_replace('"', '', $first_param), $eval);
                                                $preprocessable_bits[] = $pp_bit;
                                            }
                                            break 2;
                                        }
                                    }
                                    $symbol_params = array();
                                    foreach ($opener_params as $param) {
                                        if ($param == array()) {
                                            $param = array('""');
                                        }
                                        $myfunc = 'tcpfunc_' . fast_uniqid();
                                        $funcdef = build_closure_function($myfunc, $param);
                                        $symbol_params[] = new ocp_tempcode(array($funcdef, array(array($myfunc, array(), TC_KNOWN, '', ''))));
                                        // Parameters will be bound in later.
                                    }
                                    $pp_bit = array(array(), TC_SYMBOL, str_replace('"', '', $first_param), $symbol_params);
                                    $preprocessable_bits[] = $pp_bit;
                                    break;
                            }
                        }
                        if ($first_param == '"IMG"' && strpos($_opener_params, ',') === false) {
                            $_opener_params .= ',"0","' . php_addslashes($theme) . '"';
                        }
                        if ($first_param == '"?"') {
                            if (implode('.', $opener_params[0]) == '"1".""') {
                                if (isset($opener_params[1])) {
                                    $current_level_data[] = implode('.', $opener_params[1]);
                                }
                                break;
                            }
                            if (implode('.', $opener_params[0]) == '"0".""' || implode('.', $opener_params[0]) == '""') {
                                if (isset($opener_params[2])) {
                                    $current_level_data[] = implode('.', $opener_params[2]);
                                }
                                break;
                            }
                        }
                        if ($first_param != '""') {
                            $new_line = 'ecv($cl,array(' . implode(',', $escaped) . '),' . strval(TC_SYMBOL) . ',' . $first_param . ',array(' . $_opener_params . '))';
                            if (in_array($first_param, $compilable_symbols) && preg_match('#^[^\\(\\)]*$#', $_opener_params) != 0) {
                                $new_line = '"' . php_addslashes(eval('return ' . $new_line . ';')) . '"';
                            }
                            $current_level_data[] = $new_line;
                        }
                        break;
                    case PARSE_LANGUAGE_REFERENCE:
                        $new_line = 'ecv($cl,array(' . implode(',', $escaped) . '),' . strval(TC_LANGUAGE_REFERENCE) . ',' . $first_param . ',array(' . $_opener_params . '))';
                        if ($_opener_params == '' && count($escaped) == 0) {
                            $looked_up = do_lang(eval('return ' . $first_param . ';'), NULL, NULL, NULL, $lang, false);
                            if (!is_null($looked_up)) {
                                if (apply_tempcode_escaping($escaped, $looked_up) == $looked_up) {
                                    $new_line = '"' . php_addslashes($looked_up) . '"';
                                }
                            }
                        }
                        $current_level_data[] = $new_line;
                        break;
                    case PARSE_PARAMETER:
                        $parameter = str_replace('"', '', str_replace("'", '', $first_param));
                        $parameter = preg_replace('#[^\\w\\_\\d]#', '', $parameter);
                        // security to stop PHP injection
                        $temp = 'output_tempcode_parameter( isset ($bound_' . php_addslashes($parameter) . ')?$bound_' . php_addslashes($parameter) . ':NULL,"' . php_addslashes($parameter) . '","' . php_addslashes($template_name) . '")';
                        if (count($escaped) == 0) {
                            $current_level_data[] = $temp;
                        } else {
                            $s_escaped = '';
                            foreach ($escaped as $esc) {
                                if ($s_escaped != '') {
                                    $s_escaped .= ',';
                                }
                                $s_escaped .= strval($esc);
                            }
                            if ($s_escaped == strval(ENTITY_ESCAPED) && !$GLOBALS['XSS_DETECT']) {
                                $current_level_data[] = '( isset ($bound_' . $parameter . ')?(((isset($bound_' . $parameter . '->preprocessable_bits)) && ($bound_' . $parameter . '->pure_lang))?' . $temp . ':str_replace($GLOBALS[\'HTML_ESCAPE_1_STRREP\'],$GLOBALS[\'HTML_ESCAPE_2\'],' . $temp . ')):attach_message(do_lang_tempcode(\'MISSING_TEMPLATE_PARAMETER\',"' . php_addslashes($parameter) . '","' . php_addslashes($template_name) . '"),"warn"))';
                            } else {
                                if ($s_escaped == strval(ENTITY_ESCAPED)) {
                                    $current_level_data[] = '( isset ($bound_' . $parameter . ')?(((isset($bound_' . $parameter . '->preprocessable_bits)) && ($bound_' . $parameter . '->pure_lang))?' . $temp . ':apply_tempcode_escaping_inline(array(' . $s_escaped . '),' . $temp . ')):attach_message(do_lang_tempcode(\'MISSING_TEMPLATE_PARAMETER\',"' . php_addslashes($parameter) . '","' . php_addslashes($template_name) . '"),"warn"))';
                                } else {
                                    $current_level_data[] = '( isset ($bound_' . $parameter . ')?apply_tempcode_escaping_inline(array(' . $s_escaped . '),' . $temp . '):attach_message(do_lang_tempcode(\'MISSING_TEMPLATE_PARAMETER\',"' . php_addslashes($parameter) . '","' . php_addslashes($template_name) . '"),"warn"))';
                                }
                            }
                        }
                        break;
                }
                // Handle directive nesting
                if ($past_level_mode == PARSE_DIRECTIVE) {
                    $eval = @eval('return ' . $first_param . ';');
                    if (!is_string($eval)) {
                        $eval = '';
                    }
                    if ($eval == 'START') {
                        // Open a new directive level
                        $stack[] = array($current_level_mode, $current_level_data, $current_level_params, $past_level_mode, $past_level_data, $past_level_params);
                        $current_level_data = array();
                        $current_level_params = array();
                        $current_level_mode = PARSE_DIRECTIVE_INNER;
                    } elseif ($eval == 'END') {
                        // Test that the top stack does represent a started directive, and close directive level
                        $past_level_data = $current_level_data;
                        if ($past_level_data == array()) {
                            $past_level_data = array('""');
                        }
                        $past_level_params = $current_level_params;
                        $past_level_mode = $current_level_mode;
                        if (count($stack) == 0) {
                            if ($tolerate_errors) {
                                continue;
                            }
                            warn_exit(do_lang_tempcode('TEMPCODE_TOO_MANY_CLOSES', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
                        }
                        list($current_level_mode, $current_level_data, $current_level_params, $directive_level_mode, $directive_level_data, $directive_level_params) = array_pop($stack);
                        if (!is_array($directive_level_params)) {
                            if ($tolerate_errors) {
                                continue;
                            }
                            warn_exit(do_lang_tempcode('UNCLOSED_DIRECTIVE_OR_BRACE', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
                        }
                        $directive_opener_params = array_merge($directive_level_params, array($directive_level_data));
                        if ($directive_level_mode != PARSE_DIRECTIVE || $directive_opener_params[0][0] != '"START"') {
                            if ($tolerate_errors) {
                                continue;
                            }
                            warn_exit(do_lang_tempcode('TEMPCODE_TOO_MANY_CLOSES', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
                        }
                        // Handle directive
                        if (count($directive_opener_params) == 1) {
                            if ($tolerate_errors) {
                                continue;
                            }
                            warn_exit(do_lang_tempcode('NO_DIRECTIVE_TYPE', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
                        }
                        $directive_params = '';
                        $first_directive_param = '""';
                        if ($directive_opener_params[1] == array()) {
                            $directive_opener_params[1] = array('""');
                        }
                        for ($j = 2; $j < count($directive_opener_params); $j++) {
                            if ($directive_opener_params[$j] == array()) {
                                $directive_opener_params[$j] = array('""');
                            }
                            if ($directive_params != '') {
                                $directive_params .= ',';
                            }
                            $directive_params .= implode('.', $directive_opener_params[$j]);
                            if ($j == 2) {
                                $first_directive_param = implode('.', $directive_opener_params[$j]);
                            }
                        }
                        $eval = @eval('return ' . implode('.', $directive_opener_params[1]) . ';');
                        if (!is_string($eval)) {
                            $eval = '';
                        }
                        $directive_name = $eval;
                        switch ($directive_name) {
                            case 'FRACTIONAL_EDITABLE':
                                $pp_bit = array(array(), TC_DIRECTIVE, str_replace('"', '', $directive_name), array());
                                $preprocessable_bits[] = $pp_bit;
                                break;
                        }
                        switch ($directive_name) {
                            case 'IF':
                                if (preg_match('#^ecv\\(\\$cl,array\\(\\),0,"NOT",array\\("1"\\)\\).""$#', $first_directive_param) != 0) {
                                    $first_directive_param = '"0".""';
                                }
                                if (preg_match('#^ecv\\(\\$cl,array\\(\\),0,"NOT",array\\("0"\\)\\).""$#', $first_directive_param) != 0) {
                                    $first_directive_param = '"1".""';
                                }
                                if ($first_directive_param == '"1".""') {
                                    $current_level_data[] = '(' . implode('.', $past_level_data) . ')';
                                } elseif ($first_directive_param != '"0".""') {
                                    $current_level_data[] = '((' . $first_directive_param . '=="1")?(' . implode('.', $past_level_data) . '):\'\')';
                                }
                                break;
                            case 'IF_EMPTY':
                                $current_level_data[] = '((' . $first_directive_param . '==\'\')?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'WHILE':
                                $current_level_data[] = 'closure_while_loop(array($parameters,$cl,$last_attach),' . chr(10) . 'create_function(\'$parameters,$cl,$last_attach\',"extract(\\$parameters,EXTR_PREFIX_ALL,\'bound\'); return (' . php_addslashes($first_directive_param) . ')==\\"1\\";"),' . chr(10) . 'create_function(\'$parameters,$cl,$last_attach\',"extract(\\$parameters,EXTR_PREFIX_ALL,\'bound\'); return ' . php_addslashes(implode('.', $past_level_data)) . ';"))';
                                break;
                            case 'PHP':
                                $current_level_data[] = 'closure_eval(' . implode('.', $past_level_data) . ',$parameters)';
                                break;
                            case 'LOOP':
                                $current_level_data[] = 'closure_loop(array(' . $directive_params . ',\'vars\'=>$parameters),array($parameters,$cl,$last_attach),' . chr(10) . 'create_function(\'$parameters,$cl,$last_attach\',"extract(\\$parameters,EXTR_PREFIX_ALL,\'bound\'); return ' . php_addslashes(implode('.', $past_level_data)) . ';"))';
                                break;
                            case 'IF_NON_EMPTY':
                                $current_level_data[] = '((' . $first_directive_param . '!=\'\')?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'IF_PASSED':
                                $eval = @eval('return ' . $first_directive_param . ';');
                                if (!is_string($eval)) {
                                    $eval = '';
                                }
                                $current_level_data[] = '(isset($bound_' . preg_replace('#[^\\w\\d\\_]#', '', $eval) . ')?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'IF_NON_PASSED':
                                $eval = @eval('return ' . $first_directive_param . ';');
                                if (!is_string($eval)) {
                                    $eval = '';
                                }
                                $current_level_data[] = '(!isset($bound_' . preg_replace('#[^\\w\\d\\_]#', '', $eval) . ')?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'IF_ADJACENT':
                                $current_level_data[] = '(($last_attach=="' . php_addslashes($template_name) . '")?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'IF_NON_ADJACENT':
                                $current_level_data[] = '(($last_attach!="' . php_addslashes($template_name) . '")?(' . implode('.', $past_level_data) . '):\'\')';
                                break;
                            case 'SHIFT_ENCODE':
                                $eval = @eval('return ' . implode('.', $directive_opener_params[2]) . ';');
                                if (!is_string($eval)) {
                                    $eval = '';
                                }
                                $key = $eval;
                                $set_op = '$GLOBALS[\'SHIFT_VARIABLES\']["' . php_addslashes($key) . '"]=make_string_tempcode(' . implode('.', $past_level_data) . ')';
                                if (array_key_exists(3, $directive_opener_params)) {
                                    $attach_op = '$GLOBALS[\'SHIFT_VARIABLES\']["' . php_addslashes($key) . '"]->attach(' . implode('.', $past_level_data) . ')';
                                    $is_set_check = 'array_key_exists("' . php_addslashes($key) . '",$GLOBALS[\'SHIFT_VARIABLES\'])';
                                    // NB: The "/*SHIFT_ENCODE*/" bit is critical, it's used as a marker for identifying the need for preexecution
                                    $current_level_data[] = '/*SHIFT_ENCODE*/(is_null(((!' . $is_set_check . ') || (' . implode('.', $directive_opener_params[3]) . '==\'0\'))' . '?' . $set_op . ':' . $attach_op . ')?\'\':\'\')';
                                } else {
                                    $current_level_data[] = '/*SHIFT_ENCODE*/(is_null(' . $set_op . ')?\'\':\'\')';
                                }
                                break;
                            case 'INCLUDE':
                                global $FILE_ARRAY;
                                if (count($directive_opener_params) == 3 && $past_level_data == array('""') && !isset($FILE_ARRAY)) {
                                    $eval = @eval('return ' . $first_directive_param . ';');
                                    if (!is_string($eval)) {
                                        $eval = '';
                                    }
                                    $found = find_template_place($eval, '', $theme, '.tpl', 'templates');
                                    $_theme = $found[0];
                                    $fullpath = get_custom_file_base() . '/themes/' . $_theme . $found[1] . $eval . '.tpl';
                                    if (!is_file($fullpath)) {
                                        $fullpath = get_file_base() . '/themes/' . $_theme . $found[1] . $eval . '.tpl';
                                    }
                                    $filecontents = @file_get_contents($fullpath, FILE_TEXT);
                                    if ($filecontents === false) {
                                        $filecontents = '';
                                    }
                                    list($_current_level_data, $_preprocessable_bits) = compile_template($filecontents, $eval, $theme, $lang);
                                    $current_level_data = array_merge($current_level_data, $_current_level_data);
                                    $preprocessable_bits = array_merge($preprocessable_bits, $_preprocessable_bits);
                                    break;
                                }
                            default:
                                if ($directive_params != '') {
                                    $directive_params .= ',';
                                }
                                $directive_params .= implode('.', $past_level_data);
                                if (isset($GLOBALS['DIRECTIVES_NEEDING_VARS'][$directive_name])) {
                                    $current_level_data[] = 'ecv($cl,array(),' . strval(TC_DIRECTIVE) . ',' . implode('.', $directive_opener_params[1]) . ',array(' . $directive_params . ',\'vars\'=>$parameters))';
                                } else {
                                    $current_level_data[] = 'ecv($cl,array(),' . strval(TC_DIRECTIVE) . ',' . implode('.', $directive_opener_params[1]) . ',array(' . $directive_params . '))';
                                }
                                break;
                        }
                    } else {
                        $eval = @eval('return ' . $first_param . ';');
                        if (!is_string($eval)) {
                            $eval = '';
                        }
                        $directive_name = $eval;
                        if (isset($GLOBALS['DIRECTIVES_NEEDING_VARS'][$directive_name])) {
                            $current_level_data[] = 'ecv($cl,array(' . implode(',', $escaped) . '),' . strval(TC_DIRECTIVE) . ',' . $first_param . ',array(' . $_opener_params . ',\'vars\'=>$parameters))';
                        } else {
                            $current_level_data[] = 'ecv($cl,array(' . implode(',', $escaped) . '),' . strval(TC_DIRECTIVE) . ',' . $first_param . ',array(' . $_opener_params . '))';
                        }
                    }
                }
                break;
            case ',':
                switch ($current_level_mode) {
                    case PARSE_NO_MANS_LAND:
                    case PARSE_DIRECTIVE_INNER:
                        $current_level_data[] = '\',\'';
                        break;
                    default:
                        $current_level_params[] = $current_level_data;
                        $current_level_data = array();
                        break;
                }
                break;
            default:
                $literal = php_addslashes(str_replace('\\,', ',', str_replace('\\}', '}', str_replace('\\{', '{', $next_token))));
                if ($GLOBALS['XSS_DETECT']) {
                    ocp_mark_as_escaped($literal);
                }
                $current_level_data[] = '"' . $literal . '"';
                break;
        }
    }
    if (!array_key_exists('LAX_COMCODE', $GLOBALS) || !$GLOBALS['LAX_COMCODE']) {
        if (count($stack) != 0) {
            if (!$tolerate_errors) {
                warn_exit(do_lang_tempcode('UNCLOSED_DIRECTIVE_OR_BRACE', escape_html($template_name), integer_format(1 + substr_count(substr($data, 0, _length_so_far($bits, $i)), chr(10)))));
            }
        }
    }
    return array($current_level_data, $preprocessable_bits);
}
示例#2
0
/**
 * Get a tempcoded version of a normal XHTML template. It is perhaps the most common ocPortal function to load up templates using do_template, and then attach them together either as parameters to each other, or via the tempcode attach method.
 *
 * @param  ID_TEXT			The codename of the template being loaded
 * @param  ?array				A map of parameters for the template (key to value) (NULL: no parameters)
 * @param  ?LANGUAGE_NAME 	The language to load the template in (templates can embed language references) (NULL: users own language)
 * @param  boolean			Whether to not produce a stack dump if the template is missing
 * @param  ?ID_TEXT			Alternate template to use if the primary one does not exist (NULL: none)
 * @param  string				File type suffix of template file (e.g. .tpl)
 * @param  string				Subdirectory type to look in
 * @set    templates css
 * @param  ?ID_TEXT			Theme to use (NULL: current theme)
 * @return tempcode			The tempcode for this template
 */
function do_template($codename, $parameters = NULL, $lang = NULL, $light_error = false, $fallback = NULL, $suffix = '.tpl', $type = 'templates', $theme = NULL)
{
    if (!isset($lang) || $lang == '') {
        global $USER_LANG_CACHED;
        $lang = isset($USER_LANG_CACHED) ? $USER_LANG_CACHED : (function_exists('user_lang') ? user_lang() : 'EN');
    }
    if ($GLOBALS['SEMI_DEBUG_MODE']) {
        if ($codename == strtolower($codename) && $type != 'css' && $codename != 'tempcode_test' && $codename != 'handle_conflict_resolution') {
            fatal_exit('Template names should be in upper case, and the files should be stored in upper case.');
        }
        if (substr($codename, -7) == '_SCREEN' || substr($codename, -8) == '_OVERLAY' || $codename == 'POOR_XHTML_WRAPPER' || $codename == 'OCF_WRAPPER') {
            $GLOBALS['SCREEN_TEMPLATE_CALLED'] = $codename;
        }
    }
    global $TEMPLATE_PREVIEW_OP, $RECORD_TEMPLATES_USED, $RECORDED_TEMPLATES_USED, $FILE_ARRAY, $MEM_CACHE, $KEEP_MARKERS, $SHOW_EDIT_LINKS, $XHTML_SPIT_OUT, $CACHE_TEMPLATES, $FORUM_DRIVER, $POSSIBLY_IN_SAFE_MODE, $CACHED_THEME, $CACHED_FOUND, $LOADED_TPL_CACHE;
    $special_treatment = ($KEEP_MARKERS || $SHOW_EDIT_LINKS) && is_null($XHTML_SPIT_OUT);
    if ($RECORD_TEMPLATES_USED) {
        $RECORDED_TEMPLATES_USED[] = $codename;
    }
    // Variables we'll need
    if (!isset($theme)) {
        $theme = isset($CACHED_THEME) ? $CACHED_THEME : (isset($FORUM_DRIVER) && is_object($FORUM_DRIVER) && method_exists($FORUM_DRIVER, 'get_theme') ? filter_naughty($FORUM_DRIVER->get_theme()) : 'default');
    }
    $prefix_default = get_file_base() . '/themes/';
    $prefix = $theme == 'default' ? $prefix_default : get_custom_file_base() . '/themes/';
    // Is it structurally cached on disk yet?
    if (!isset($CACHED_FOUND[$codename][$lang][$theme][$suffix][$type])) {
        $loaded_this_once = false;
    } else {
        $loaded_this_once = true;
    }
    $_data = false;
    if ($CACHE_TEMPLATES && !$TEMPLATE_PREVIEW_OP && (!$POSSIBLY_IN_SAFE_MODE || !in_safe_mode())) {
        $tcp_path = $prefix . $theme . '/templates_cached/' . $lang . '/' . $codename . $suffix . '.tcp';
        if ($loaded_this_once) {
            if (isset($LOADED_TPL_CACHE[$codename][$theme])) {
                $_data = $LOADED_TPL_CACHE[$codename][$theme];
            } else {
                $_data = new ocp_tempcode();
                $test = $_data->from_assembly_executed($tcp_path, array($codename, $codename, $lang, $theme, $suffix, $type, $fallback));
                if (!$test) {
                    $_data = false;
                }
                // failed
            }
        } else {
            global $SITE_INFO;
            $support_smart_decaching = !isset($SITE_INFO['disable_smart_decaching']) || $SITE_INFO['disable_smart_decaching'] == '0';
            if ($support_smart_decaching) {
                if (!isset($CACHED_FOUND[$codename][$lang][$theme][$suffix][$type])) {
                    $found = find_template_place($codename, $lang, $theme, $suffix, $type);
                    $CACHED_FOUND[$codename][$lang][$theme][$suffix][$type] = $found;
                } else {
                    $found = $CACHED_FOUND[$codename][$lang][$theme][$suffix][$type];
                }
                if (!is_null($found)) {
                    if (isset($GLOBALS['CURRENT_SHARE_USER'])) {
                        $file_path = get_custom_file_base() . '/themes/' . $found[0] . $found[1] . $codename . $suffix;
                        if (!is_file($file_path)) {
                            $file_path = get_file_base() . '/themes/' . $found[0] . $found[1] . $codename . $suffix;
                        }
                    } else {
                        $file_path = ($theme == 'default' && $suffix != '.css' ? get_file_base() : get_custom_file_base()) . '/themes/' . $found[0] . $found[1] . $codename . $suffix;
                    }
                    $tcp_time = @filemtime($tcp_path);
                } else {
                    $tcp_time = false;
                }
            }
            if (!$support_smart_decaching || $tcp_time !== false && is_file($file_path) && $found !== NULL) {
                if (!$support_smart_decaching || filemtime($file_path) < $tcp_time) {
                    $_data = new ocp_tempcode();
                    $test = $_data->from_assembly_executed($tcp_path, array($codename, $codename, $lang, $theme, $suffix, $type, $fallback));
                    if (!$test) {
                        $_data = false;
                    }
                    // failed
                }
            }
        }
    }
    if ($_data === false) {
        if (!isset($CACHED_FOUND[$codename][$lang][$theme][$suffix][$type])) {
            $found = find_template_place($codename, $lang, $theme, $suffix, $type);
            $CACHED_FOUND[$codename][$lang][$theme][$suffix][$type] = $found;
        } else {
            $found = $CACHED_FOUND[$codename][$lang][$theme][$suffix][$type];
        }
        unset($CACHED_FOUND[$codename][$lang][$theme][$suffix][$type]);
        if (is_null($found)) {
            if (is_null($fallback)) {
                if ($light_error) {
                    return paragraph(do_lang_tempcode('MISSING_TEMPLATE_FILE', escape_html($codename)), '34rwefwfdee');
                }
                fatal_exit(do_lang_tempcode('MISSING_TEMPLATE_FILE', escape_html($codename)));
            } else {
                $result = do_template($fallback, $parameters, $lang);
                return $result;
            }
        } else {
            require_code('tempcode_compiler');
            $_data = _do_template($found[0], $found[1], $codename, $codename, $lang, $suffix, $theme);
        }
    }
    if ($loaded_this_once) {
        // On 3rd load (and onwards) it will be fully cached
        $LOADED_TPL_CACHE[$codename][$theme] = $_data;
    }
    if (!isset($parameters)) {
        $out = new ocp_tempcode();
        $out->codename = $codename;
        $out->code_to_preexecute = $_data->code_to_preexecute;
        $out->preprocessable_bits = $_data->preprocessable_bits;
        $out->seq_parts = $_data->seq_parts;
        foreach ($out->seq_parts as $i => $bit) {
            if ($bit[1] != array()) {
                $out->seq_parts[$i][1] = array();
            }
        }
        return $out;
    }
    $ret = $_data->bind($parameters, $codename);
    if ($special_treatment) {
        $ret->codename = '(mixed)';
        // Stop optimisation that assumes the codename represents the sole content of it
    }
    if ($special_treatment) {
        if ($KEEP_MARKERS) {
            $__data = new ocp_tempcode();
            $__data->attach('<!-- START-TEMPLATE=' . escape_html($codename) . ' -->');
            $__data->attach($ret);
            $__data->attach('<!-- END-TEMPLATE=' . escape_html($codename) . ' -->');
            $ret = $__data;
        }
        if ($SHOW_EDIT_LINKS && $codename != 'PARAM_INFO') {
            $edit_url = build_url(array('page' => 'admin_themes', 'type' => '_edit_templates', 'theme' => $theme, 'f0file' => $codename), 'adminzone');
            $parameters2 = array();
            foreach ($parameters as $k => $v) {
                if (is_array($v)) {
                    $parameters2[$k] = '(array)';
                } elseif (!is_object($v)) {
                    $parameters2[$k] = $v;
                } else {
                    $parameters2[$k] = $v->evaluate();
                    if (strlen($parameters2[$k]) > 100) {
                        $parameters2[$k] = substr($parameters2[$k], 0, 100) . '...';
                    }
                }
            }
            $param_info = do_template('PARAM_INFO', array('MAP' => $parameters2));
            $SHOW_EDIT_LINKS = false;
            $ret = do_template('TEMPLATE_EDIT_LINK', array('_GUID' => '511ae911d31a5b237a4371ff22fc78fd', 'PARAM_INFO' => $param_info, 'CONTENTS' => $ret, 'CODENAME' => $codename, 'EDIT_URL' => $edit_url));
            $SHOW_EDIT_LINKS = true;
        }
    }
    return $ret;
}
示例#3
0
/**
 * Force a CSS file to be cached.
 *
 * @param  string			The CSS file required
 * @param  ?ID_TEXT		The name of the theme (NULL: current theme)
 * @param  ?boolean		Whether to minify (NULL: read from environment)
 * @return string			The path to the CSS file in the cache (blank: no file)
 */
function css_enforce($c, $theme = NULL, $minify = NULL)
{
    $text_only = get_param_integer('keep_textonly', 0) == 1;
    if ($text_only) {
        $c .= '_textonly';
    }
    if ($minify === NULL) {
        $minify = get_param_integer('keep_no_minify', 0) == 0;
    }
    global $SITE_INFO;
    // Make sure the CSS file exists
    if ($theme === NULL) {
        $theme = @method_exists($GLOBALS['FORUM_DRIVER'], 'get_theme') ? $GLOBALS['FORUM_DRIVER']->get_theme() : 'default';
    }
    $active_theme = $theme;
    $dir = get_custom_file_base() . '/themes/' . $theme . '/templates_cached/' . filter_naughty(user_lang());
    if (!isset($SITE_INFO['no_disk_sanity_checks']) || $SITE_INFO['no_disk_sanity_checks'] == '0') {
        if (!is_dir($dir)) {
            if (@mkdir($dir, 0777) === false) {
                warn_exit(do_lang_tempcode('WRITE_ERROR_DIRECTORY_REPAIR', escape_html($dir)));
            }
            fix_permissions($dir, 0777);
            sync_file($dir);
        }
    }
    $css_cache_path = $dir . '/' . filter_naughty_harsh($c);
    if (!$minify) {
        $css_cache_path .= '_non_minified';
    }
    if (get_option('enable_https', true) == '1' && function_exists('is_page_https') && function_exists('get_zone_name') && (tacit_https() || is_page_https(get_zone_name(), get_page_name()))) {
        $css_cache_path .= '_ssl';
    }
    if (is_mobile()) {
        $css_cache_path .= '_mobile';
    }
    $css_cache_path .= '.css';
    global $CACHE_TEMPLATES;
    $support_smart_decaching = !isset($SITE_INFO['disable_smart_decaching']) || $SITE_INFO['disable_smart_decaching'] == '0';
    $is_cached = ($CACHE_TEMPLATES || !running_script('index')) && @(filesize($css_cache_path) != 0) && !is_browser_decacheing() && !in_safe_mode();
    if ($support_smart_decaching || !$is_cached || $text_only) {
        $found = find_template_place($c, '', $theme, '.css', 'css');
        if ($found === NULL) {
            return '';
        }
        $theme = $found[0];
        $fullpath = get_custom_file_base() . '/themes/' . $theme . $found[1] . $c . '.css';
        if (!is_file($fullpath)) {
            $fullpath = get_file_base() . '/themes/' . $theme . $found[1] . $c . '.css';
        }
        if ($text_only && !is_file($fullpath)) {
            return '';
        }
    }
    if (!$is_cached || $support_smart_decaching && (@(filemtime($css_cache_path) < filemtime($fullpath)) && @filemtime($fullpath) < time())) {
        require_code('css_and_js');
        css_compile($active_theme, $theme, $c, $fullpath, $css_cache_path, $minify);
    }
    if (@filesize($css_cache_path) == 0) {
        return '';
    }
    return $css_cache_path;
}
示例#4
0
/**
 * Handle special page type output.
 *
 * @param  ID_TEXT		The special page type.
 * @set    query templates tree lang
 * @param  tempcode		The normal script tempcode output
 * @param  string			The normal script evaluated output
 */
function special_page_types($special_page_type, &$out, $out_evaluated)
{
    global $RECORDED_TEMPLATES_USED;
    if (function_exists('set_time_limit')) {
        @set_time_limit(280);
    }
    $echo = do_header();
    //$echo->evaluate_echo();
    $echo2 = new ocp_tempcode();
    if (is_null($out_evaluated)) {
        ob_start();
        $out->evaluate_echo();
        // False evaluation
        ob_end_clean();
    }
    // HACKHACK: Yuck. we have to after-the-fact make it wide, and empty lots of internal caching to reset the state.
    $_GET['wide_high'] = '1';
    $_GET['wide'] = '1';
    $GLOBALS['LOADED_PANELS'] = array();
    $GLOBALS['IS_WIDE_HIGH'] = 1;
    $GLOBALS['IS_WIDE'] = 1;
    $GLOBALS['TEMPCODE_SETGET'] = array();
    $GLOBALS['LOADED_TPL_CACHE'] = array();
    $GLOBALS['HELPER_PANEL_PIC'] = NULL;
    $GLOBALS['HELPER_PANEL_TEXT'] = NULL;
    $GLOBALS['HELPER_PANEL_TUTORIAL'] = NULL;
    $GLOBALS['HELPER_PANEL_HTML'] = NULL;
    // CSS
    if (substr($special_page_type, -4) == '.css') {
        $url = build_url(array('page' => 'admin_themes', 'type' => 'edit_css', 'theme' => $GLOBALS['FORUM_DRIVER']->get_theme(), 'file' => $special_page_type, 'keep_wide_high' => 1), get_module_zone('admin_themes'));
        header('Location: ' . $url->evaluate());
        exit;
    }
    // Site Tree Editor
    if ($special_page_type == 'site_tree') {
        $url = build_url(array('page' => 'admin_sitetree', 'type' => 'site_tree', 'id' => get_zone_name() . ':' . get_page_name()), get_module_zone('admin_sitetree'));
        header('Location: ' . $url->evaluate());
        exit;
    }
    // IDE linkage
    if ($special_page_type == 'ide_linkage') {
        $title = get_page_title('IDE_LINKAGE');
        $file_links = new ocp_tempcode();
        global $JAVASCRIPTS, $CSSS, $_REQUIRED_CODE, $LANGS_REQUESTED;
        /*foreach (array_keys($JAVASCRIPTS) as $name)	Already in list of templates
        		{
        			$txtmte_url='txmt://open?url=file://'.$name;
        			$file_links->attach(do_template('INDEX_SCREEN_ENTRY',array('URL'=>$txtmte_url,'NAME'=>$name)));
        		}*/
        foreach (array_keys($CSSS) as $name) {
            $search = find_template_place($name, get_site_default_lang(), $GLOBALS['FORUM_DRIVER']->get_theme(), '.css', 'css');
            if (!is_null($search)) {
                list($theme, $type) = $search;
                $txtmte_url = 'txmt://open?url=file://' . get_file_base() . '/themes/' . $theme . '/' . $type . '/' . $name . '.css';
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(CSS)', 'URL' => $txtmte_url, 'NAME' => $name . '.css')));
            }
        }
        foreach (array_keys($_REQUIRED_CODE) as $name) {
            $path_a = get_file_base() . '/' . (strpos($name, '.php') === false ? '/sources_custom/' . $name . '.php' : $name);
            $path_b = get_file_base() . '/' . (strpos($name, '.php') === false ? '/sources/' . $name . '.php' : str_replace('_custom', '', $name));
            if (file_exists($path_a)) {
                $txtmte_url = 'txmt://open?url=file://' . $path_a;
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(PHP)', 'URL' => $txtmte_url, 'NAME' => $name . (strpos($name, '.php') === false ? '.php' : ''))));
            }
            if (file_exists($path_b)) {
                $txtmte_url = 'txmt://open?url=file://' . $path_b;
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(PHP)', 'URL' => $txtmte_url, 'NAME' => $name . (strpos($name, '.php') === false ? '.php' : ''))));
            }
        }
        foreach (array_keys($LANGS_REQUESTED) as $name) {
            if (file_exists(get_file_base() . '/lang_custom/' . fallback_lang() . '/' . $name . '.ini')) {
                $txtmte_url = 'txmt://open?url=file://' . get_file_base() . '/lang_custom/' . fallback_lang() . '/' . $name . '.ini';
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(Language)', 'URL' => $txtmte_url, 'NAME' => $name . '.ini')));
            }
            if (file_exists(get_file_base() . '/lang/' . fallback_lang() . '/' . $name . '.ini')) {
                $txtmte_url = 'txmt://open?url=file://' . get_file_base() . '/lang/' . fallback_lang() . '/' . $name . '.ini';
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(Language)', 'URL' => $txtmte_url, 'NAME' => $name . '.ini')));
            }
        }
        foreach (array_unique($RECORDED_TEMPLATES_USED) as $name) {
            $search = find_template_place($name, get_site_default_lang(), $GLOBALS['FORUM_DRIVER']->get_theme(), '.tpl', 'templates');
            if (!is_null($search)) {
                list($theme, $type) = $search;
                $txtmte_url = 'txmt://open?url=file://' . get_file_base() . '/themes/' . $theme . '/' . $type . '/' . $name . '.tpl';
                $file_links->attach(do_template('INDEX_SCREEN_ENTRY', array('DISPLAY_STRING' => '(Templates)', 'URL' => $txtmte_url, 'NAME' => $name . '.tpl')));
            }
        }
        $echo2 = do_template('INDEX_SCREEN', array('TITLE' => $title, 'CONTENT' => $file_links, 'PRE' => do_lang_tempcode('TXMT_PROTOCOL_EXPLAIN'), 'POST' => ''));
    }
    // Theme images mode
    if ($special_page_type == 'theme_images') {
        $title = get_page_title('THEME_IMAGE_EDITING');
        $theme_images = new ocp_tempcode();
        global $RECORDED_IMG_CODES;
        foreach (array_keys($RECORDED_IMG_CODES) as $theme_image_details) {
            list($id, $theme, $lang) = unserialize($theme_image_details);
            $url = build_url(array('page' => 'admin_themes', 'type' => 'edit_image', 'theme' => is_null($theme) ? $GLOBALS['FORUM_DRIVER']->get_theme() : $theme, 'lang' => $lang, 'id' => $id), 'adminzone');
            $image = find_theme_image($id, false, false, $theme, $lang);
            if ($image == '') {
                continue;
            }
            $theme_images->attach(do_template('INDEX_SCREEN_FANCIER_ENTRY', array('IMG' => $image, 'DESCRIPTION' => '', 'URL' => $url, 'NAME' => $id)));
        }
        $echo2 = do_template('INDEX_SCREEN_FANCIER_SCREEN', array('TITLE' => $title, 'CONTENT' => $theme_images, 'PRE' => do_lang_tempcode('CONTEXTUAL_EDITING_SCREEN'), 'POST' => ''));
    }
    // Profile mode?
    if ($special_page_type == 'profile') {
        if (function_exists('xdebug_dump_function_profile')) {
            $type = XDEBUG_PROFILER_FS_SUM;
            xdebug_dump_function_profile($type);
        } else {
            $echo2 = make_string_tempcode('Check out the dump using KCacheGrind.');
        }
    } elseif (substr($special_page_type, 0, 12) == 'lang_content') {
        $map_a = get_file_base() . '/lang/langs.ini';
        $map_b = get_custom_file_base() . '/lang_custom/langs.ini';
        if (!file_exists($map_b)) {
            $map_b = $map_a;
        }
        $map = better_parse_ini_file($map_b);
        $lang_name = user_lang();
        if (array_key_exists($lang_name, $map)) {
            $lang_name = $map[$lang_name];
        }
        global $RECORDED_LANG_STRINGS_CONTENT;
        require_lang('lang');
        require_code('form_templates');
        $fields = new ocp_tempcode();
        require_code('lang2');
        $names = find_lang_content_names(array_keys($RECORDED_LANG_STRINGS_CONTENT));
        foreach ($RECORDED_LANG_STRINGS_CONTENT as $key => $forum_db) {
            $value_found = get_translated_text($key, $forum_db ? $GLOBALS['FORUM_DB'] : $GLOBALS['SITE_DB']);
            if ($value_found != '') {
                $description = make_string_tempcode(escape_html($value_found));
                if (get_value('google_translate_api_key') === NULL || user_lang() == get_site_default_lang()) {
                    $actions = new ocp_tempcode();
                } else {
                    require_javascript('javascript_translate');
                    $actions = do_template('TRANSLATE_ACTION', array('LANG_FROM' => get_site_default_lang(), 'LANG_TO' => user_lang(), 'NAME' => 'trans_' . strval($key), 'OLD' => $value_found));
                }
                $description->attach($actions);
                $fields->attach(form_input_text(is_null($names[$key]) ? '#' . strval($key) : $names[$key], $description, 'trans_' . strval($key), $value_found, false));
            }
        }
        if ($fields->is_empty()) {
            inform_exit(do_lang_tempcode('NOTHING_TO_TRANSLATE'));
        }
        $title = get_page_title('__TRANSLATE_CONTENT', true, array($lang_name));
        $post_url = build_url(array('page' => 'admin_lang', 'type' => '_content', 'contextual' => 1), 'adminzone');
        $hidden = form_input_hidden('redirect', get_self_url(true, true));
        $hidden = form_input_hidden('lang', user_lang());
        $echo2 = do_template('FORM_SCREEN', array('_GUID' => '0d4dd16b023d0a7960f3eac85f54ddc4', 'SKIP_VALIDATION' => true, 'TITLE' => $title, 'HIDDEN' => $hidden, 'FIELDS' => $fields, 'URL' => $post_url, 'TEXT' => do_lang_tempcode('CONTEXTUAL_EDITING_SCREEN'), 'SUBMIT_NAME' => do_lang_tempcode('SAVE')));
    } elseif (substr($special_page_type, 0, 4) == 'lang') {
        $map_a = get_file_base() . '/lang/langs.ini';
        $map_b = get_custom_file_base() . '/lang_custom/langs.ini';
        if (!file_exists($map_b)) {
            $map_b = $map_a;
        }
        $map = better_parse_ini_file($map_b);
        $lang_name = user_lang();
        if (array_key_exists($lang_name, $map)) {
            $lang_name = $map[$lang_name];
        }
        global $RECORDED_LANG_STRINGS;
        require_lang('lang');
        require_code('form_templates');
        require_code('lang2');
        $fields = new ocp_tempcode();
        $descriptions = get_lang_file_descriptions(fallback_lang());
        foreach (array_keys($RECORDED_LANG_STRINGS) as $key) {
            $value_found = do_lang($key, NULL, NULL, NULL, NULL, false);
            $description = array_key_exists($key, $descriptions) ? make_string_tempcode($descriptions[$key]) : new ocp_tempcode();
            if (!is_null($value_found)) {
                if (get_value('google_translate_api_key') === NULL || user_lang() == get_site_default_lang()) {
                    $actions = new ocp_tempcode();
                } else {
                    require_javascript('javascript_translate');
                    $actions = do_template('TRANSLATE_ACTION', array('LANG_FROM' => get_site_default_lang(), 'LANG_TO' => user_lang(), 'NAME' => 'l_' . $key, 'OLD' => str_replace('\\n', chr(10), $value_found)));
                }
                $description->attach($actions);
                $fields->attach(form_input_text($key, $description, 'l_' . $key, str_replace('\\n', chr(10), $value_found), false));
            }
        }
        $title = get_page_title('__TRANSLATE_CODE', true, array($lang_name));
        $post_url = build_url(array('page' => 'admin_lang', 'type' => '_code2'), 'adminzone');
        $hidden = form_input_hidden('redirect', get_self_url(true, true));
        $hidden = form_input_hidden('lang', user_lang());
        $echo2 = do_template('FORM_SCREEN', array('_GUID' => '0d4dd16b023d0a7960f3eac85f54ddc4', 'SKIP_VALIDATION' => true, 'TITLE' => $title, 'HIDDEN' => $hidden, 'FIELDS' => $fields, 'URL' => $post_url, 'TEXT' => do_lang_tempcode('CONTEXTUAL_EDITING_SCREEN'), 'SUBMIT_NAME' => do_lang_tempcode('SAVE')));
    }
    // Template mode?
    if ($special_page_type == 'templates' || $special_page_type == 'tree') {
        require_lang('themes');
        global $RECORD_TEMPLATES_USED;
        $RECORD_TEMPLATES_USED = false;
        $templates = new ocp_tempcode();
        if ($special_page_type == 'templates') {
            $title = get_page_title('TEMPLATES');
            $_RECORDED_TEMPLATES_USED = array_count_values($RECORDED_TEMPLATES_USED);
            ksort($_RECORDED_TEMPLATES_USED);
            foreach ($_RECORDED_TEMPLATES_USED as $name => $count) {
                //$restore_from=find_template_path($name);
                $file = $name . '.tpl';
                $edit_url = build_url(array('page' => 'admin_themes', 'type' => '_edit_templates', 'theme' => $GLOBALS['FORUM_DRIVER']->get_theme(), 'f0file' => $file), 'adminzone', NULL, false, true);
                $templates->attach(do_template('TEMPLATE_LIST_ENTRY', array('COUNT' => integer_format($count), 'NAME' => $name, 'EDIT_URL' => $edit_url)));
            }
        } else {
            $title = get_page_title('TEMPLATE_TREE');
            $hidden = new ocp_tempcode();
            global $CSSS, $JAVASCRIPTS;
            foreach (array_keys($CSSS) as $c) {
                $hidden->attach(form_input_hidden('f' . strval(mt_rand(0, 100000)) . 'file', $c . '.css'));
            }
            foreach (array_keys($JAVASCRIPTS) as $c) {
                $hidden->attach(form_input_hidden('f' . strval(mt_rand(0, 100000)) . 'file', strtoupper($c) . '.tpl'));
            }
            $edit_url = build_url(array('page' => 'admin_themes', 'type' => '_edit_templates', 'preview_url' => get_self_url(true, false, array('special_page_type' => NULL)), 'theme' => $GLOBALS['FORUM_DRIVER']->get_theme()), 'adminzone', NULL, false, true);
            $tree = find_template_tree_nice($out->codename, $out->children, $out->fresh);
            $templates = do_template('TEMPLATE_TREE', array('_GUID' => 'ff2a2233b8b4045ba4d8777595ef64c7', 'HIDDEN' => $hidden, 'EDIT_URL' => $edit_url, 'TREE' => $tree));
        }
        $echo2 = do_template('TEMPLATE_LIST_SCREEN', array('_GUID' => 'ab859f67dcb635fcb4d1747d3c6a2c17', 'TITLE' => $title, 'TEMPLATES' => $templates));
    }
    // Query mode?
    if ($special_page_type == 'query') {
        require_lang("profiling");
        global $QUERY_LIST;
        $queries = new ocp_tempcode();
        $total_time = 0.0;
        global $M_SORT_KEY;
        $M_SORT_KEY = 'time';
        usort($QUERY_LIST, 'multi_sort');
        $QUERY_LIST = array_reverse($QUERY_LIST);
        foreach ($QUERY_LIST as $query) {
            $queries->attach(do_template('QUERY_LOG', array('_GUID' => 'ab88e1e92609136229ad920c30647647', 'TIME' => float_format($query['time'], 3), 'TEXT' => $query['text'])));
            $total_time += $query['time'];
        }
        $title = get_page_title("VIEW_PAGE_QUERIES");
        $total = count($QUERY_LIST);
        $echo2 = do_template('QUERY_SCREEN', array('_GUID' => '5f679c8f657b4e4ae94ae2d0ed4843fa', 'TITLE' => $title, 'TOTAL' => integer_format($total), 'TOTAL_TIME' => float_format($total_time, 3), 'QUERIES' => $queries));
    }
    $echo->attach(globalise($echo2));
    $echo->attach(do_footer());
    $echo->handle_symbol_preprocessing();
    $echo->evaluate_echo();
    exit;
}