# HG changeset patch # User Dan # Date 1215041804 14400 # Node ID 27377179fe58a4b32ba7a59ec496041d39520dd0 # Parent 2529833a77314fd907965840df86d4539164b794 Another sweep from the optimization monster. template: rewrote parts of tplWikiFormat to do faster validation and less eval()ing template: sidebar is now cached for anonymous users (thanks to Richard Greene for the suggestion) dbal: rewrote SQL query parser, much cruft taken out template: made tplWikiFormat depend more on RenderMan common: moved some lesser-used includes out of main loading sequence Expect a lot of changes to AES code in the next commit! diff -r 2529833a7731 -r 27377179fe58 ajax.php --- a/ajax.php Mon Jun 30 17:22:29 2008 -0400 +++ b/ajax.php Wed Jul 02 19:36:44 2008 -0400 @@ -14,76 +14,6 @@ define('ENANO_INTERFACE_AJAX', ''); - // fillusername should be done without the help of the rest of Enano - all we need is the DBAL - if ( isset($_GET['_mode']) && $_GET['_mode'] == 'fillusername' ) - { - // setup and load a very basic, specialized instance of the Enano API - function microtime_float() - { - list($usec, $sec) = explode(" ", microtime()); - return ((float)$usec + (float)$sec); - } - // Determine directory (special case for development servers) - if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') ) - { - $filename = str_replace('/repo/', '/', __FILE__); - } - else - { - $filename = __FILE__; - } - define('ENANO_ROOT', dirname($filename)); - require(ENANO_ROOT.'/includes/functions.php'); - require(ENANO_ROOT.'/includes/dbal.php'); - require(ENANO_ROOT.'/includes/json2.php'); - - require(ENANO_ROOT . '/config.php'); - unset($dbuser, $dbpasswd); - if ( !isset($dbdriver) ) - $dbdriver = 'mysql'; - - $db = new $dbdriver(); - - $db->connect(); - - // result is sent using JSON - $return = Array( - 'mode' => 'success', - 'users_real' => Array() - ); - - // should be connected to the DB now - $name = (isset($_GET['name'])) ? $db->escape($_GET['name']) : false; - if ( !$name ) - { - $return = array( - 'mode' => 'error', - 'error' => 'Invalid URI' - ); - die( enano_json_encode($return) ); - } - $allowanon = ( isset($_GET['allowanon']) && $_GET['allowanon'] == '1' ) ? '' : ' AND user_id > 1'; - $q = $db->sql_query('SELECT username FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username) LIKE ' . ENANO_SQLFUNC_LOWERCASE . '(\'%'.$name.'%\')' . $allowanon . ' ORDER BY username ASC;'); - if ( !$q ) - { - $db->die_json(); - } - $i = 0; - while($r = $db->fetchrow()) - { - $return['users_real'][] = $r['username']; - $i++; - } - $db->free_result(); - - // all done! :-) - $db->close(); - - echo enano_json_encode( $return ); - - exit; - } - require('includes/common.php'); global $db, $session, $paths, $template, $plugins; // Common objects @@ -93,6 +23,7 @@ switch($_GET['_mode']) { case "checkusername": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::checkusername($_GET['name']); break; case "getsource": @@ -230,18 +161,7 @@ break; case "savepage": /* **** OBSOLETE **** */ - $summ = ( isset($_POST['summary']) ) ? $_POST['summary'] : ''; - $minor = isset($_POST['minor']); - $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['text'], $summ, $minor); - if ( $e == 'good' ) - { - $page = new PageProcessor($paths->page_id, $paths->namespace); - $page->send(); - } - else - { - echo '
Error saving the page: '.$e.'
'; - } + break; case "savepage_json": header('Content-type: application/json'); @@ -434,6 +354,7 @@ echo enano_json_encode($result); break; case "histlist": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::histlist($paths->page_id, $paths->namespace); break; case "rollback": @@ -445,6 +366,7 @@ echo enano_json_encode($result); break; case "comments": + require_once(ENANO_ROOT.'/includes/comment.php'); $comments = new Comments($paths->page_id, $paths->namespace); if ( isset($_POST['data']) ) { @@ -463,33 +385,42 @@ echo enano_json_encode($result); break; case "flushlogs": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::flushlogs($paths->page_id, $paths->namespace); break; case "deletepage": + require_once(ENANO_ROOT.'/includes/pageutils.php'); $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false; if ( empty($reason) ) die($lang->get('page_err_need_reason')); echo PageUtils::deletepage($paths->page_id, $paths->namespace, $reason); break; case "delvote": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::delvote($paths->page_id, $paths->namespace); break; case "resetdelvotes": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::resetdelvotes($paths->page_id, $paths->namespace); break; case "getstyles": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::getstyles($_GET['id']); break; case "catedit": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::catedit($paths->page_id, $paths->namespace); break; case "catsave": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::catsave($paths->page_id, $paths->namespace, $_POST); break; case "setwikimode": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::setwikimode($paths->page_id, $paths->namespace, (int)$_GET['mode']); break; case "setpass": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::setpass($paths->page_id, $paths->namespace, $_POST['password']); break; case "fillusername": @@ -537,9 +468,11 @@ } break; case "preview": + require_once(ENANO_ROOT.'/includes/pageutils.php'); echo PageUtils::genPreview($_POST['text']); break; case "pagediff": + require_once(ENANO_ROOT.'/includes/pageutils.php'); $id1 = ( isset($_GET['diff1']) ) ? (int)$_GET['diff1'] : false; $id2 = ( isset($_GET['diff2']) ) ? (int)$_GET['diff2'] : false; if(!$id1 || !$id2) { echo 'Invalid request.
'; $template->footer(); break; } @@ -558,6 +491,7 @@ else echo $rdns; break; case 'acljson': + require_once(ENANO_ROOT.'/includes/pageutils.php'); $parms = ( isset($_POST['acl_params']) ) ? rawurldecode($_POST['acl_params']) : false; echo PageUtils::acl_json($parms); break; diff -r 2529833a7731 -r 27377179fe58 includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/clientside/static/ajax.js Wed Jul 02 19:36:44 2008 -0400 @@ -149,7 +149,11 @@ if ( !box ) return false; - var newname = ( obj.getElementsByTagName('input')[0] ).value; + var input = obj.getElementsByTagName('input')[0]; + console.debug(obj, input); + if ( !input ) + return false; + var newname = input.value; newname = trim(newname); if ( newname.length < 1 ) diff -r 2529833a7731 -r 27377179fe58 includes/clientside/static/enano-lib-basic.js --- a/includes/clientside/static/enano-lib-basic.js Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/clientside/static/enano-lib-basic.js Wed Jul 02 19:36:44 2008 -0400 @@ -465,6 +465,7 @@ ajaxEditTheme: 'theme-manager.js', ajaxToggleSystemThemes: 'theme-manager.js', ajaxInstallTheme: 'theme-manager.js', + ajaxInitRankEdit: 'rank-manager.js' }; var placeholder_instances = {}; diff -r 2529833a7731 -r 27377179fe58 includes/clientside/static/functions.js --- a/includes/clientside/static/functions.js Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/clientside/static/functions.js Wed Jul 02 19:36:44 2008 -0400 @@ -558,6 +558,7 @@ return z; } +var shift = false; function isKeyPressed(event) { if (event.shiftKey==1) diff -r 2529833a7731 -r 27377179fe58 includes/common.php --- a/includes/common.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/common.php Wed Jul 02 19:36:44 2008 -0400 @@ -138,20 +138,10 @@ require_once(ENANO_ROOT.'/includes/template.php'); require_once(ENANO_ROOT.'/includes/plugins.php'); require_once(ENANO_ROOT.'/includes/lang.php'); -require_once(ENANO_ROOT.'/includes/comment.php'); -require_once(ENANO_ROOT.'/includes/wikiformat.php'); -require_once(ENANO_ROOT.'/includes/diff.php'); require_once(ENANO_ROOT.'/includes/render.php'); -require_once(ENANO_ROOT.'/includes/stats.php'); -require_once(ENANO_ROOT.'/includes/pageutils.php'); -require_once(ENANO_ROOT.'/includes/js-compressor.php'); require_once(ENANO_ROOT.'/includes/rijndael.php'); require_once(ENANO_ROOT.'/includes/email.php'); -require_once(ENANO_ROOT.'/includes/search.php'); -require_once(ENANO_ROOT.'/includes/json.php'); require_once(ENANO_ROOT.'/includes/json2.php'); -require_once(ENANO_ROOT.'/includes/math.php'); -require_once(ENANO_ROOT.'/includes/wikiengine/Tables.php'); require_once(ENANO_ROOT.'/includes/pageprocess.php'); require_once(ENANO_ROOT.'/includes/tagcloud.php'); @@ -198,6 +188,8 @@ // END BACKGROUND AND ENVIRONMENT CHECKS // +profiler_log('Background/environment checks done'); + // // MAIN API INITIALIZATION // @@ -308,7 +300,6 @@<?php define("ENANO_ALLOW_LOAD_NOLANG", 1); -$_GET["title"] = "langinstall"; require("includes/common.php"); install_language("eng", "English", "English", ENANO_ROOT . "/language/english/enano.json");'); } diff -r 2529833a7731 -r 27377179fe58 includes/constants.php --- a/includes/constants.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/constants.php Wed Jul 02 19:36:44 2008 -0400 @@ -76,6 +76,13 @@ define('IMAGE_TYPE_GIF', 2); define('IMAGE_TYPE_JPG', 3); +// token types +define('TOKEN_VARIABLE', 1); +define('TOKEN_BOOLOP', 2); +define('TOKEN_PARENTHLEFT', 3); +define('TOKEN_PARENTHRIGHT', 4); +define('TOKEN_NOT', 5); + // // User types - don't touch these // diff -r 2529833a7731 -r 27377179fe58 includes/dbal.php --- a/includes/dbal.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/dbal.php Wed Jul 02 19:36:44 2008 -0400 @@ -32,7 +32,10 @@ $debug = $debug[0]['file'] . ', line ' . $debug[0]['line']; echo "$errtype: $errstr
$debug"; } - + +global $db_sql_parse_time; +$db_sql_parse_time = 0; + class mysql { var $num_queries, $query_backtrace, $query_times, $query_sources, $latest_result, $latest_query, $_conn, $sql_stack_fields, $sql_stack_values, $debug; var $row = array(); @@ -309,79 +312,46 @@ } /** - * Checks a SQL query for possible signs of injection attempts + * Performs heuristic analysis on a SQL query to check for known attack patterns. * @param string $q the query to check * @return bool true if query passed check, otherwise false */ function check_query($q, $debug = false) { - if($debug) echo "\$db->check_query(): checking query: ".htmlspecialchars($q).'
' . print_r($match, true) . ''; return false; } + + $ts = microtime_float() - $ts; + $db_sql_parse_time += $ts; return true; } @@ -1066,72 +1036,39 @@ function check_query($q, $debug = false) { - if($debug) echo "\$db->check_query(): checking query: ".htmlspecialchars($q).'
' . print_r($match, true) . ''; return false; } + + $ts = microtime_float() - $ts; + $db_sql_parse_time += $ts; return true; } diff -r 2529833a7731 -r 27377179fe58 includes/functions.php --- a/includes/functions.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/functions.php Wed Jul 02 19:36:44 2008 -0400 @@ -4325,6 +4325,10 @@ foreach ( $profile as $i => $entry ) { + // $time_since_last = $entry['time'] - $time_last; + // if ( $time_since_last < 0.01 ) + // continue; + $html .= "\n
$message
"; } - profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } } @@ -372,13 +366,11 @@ $template->init_vars($this); } - // die($this->page_id); + $text = $this->fetch_text(); - $text = $this->fetch_text(); if ( $text == 'err_no_text_rows' ) { $this->err_no_rows(); - profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } else @@ -409,7 +401,6 @@ } } } - profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); } /** @@ -1029,6 +1020,7 @@ global $lang; $text = $this->fetch_text(); + $text = preg_replace('/([\s]*)__NOBREADCRUMBS__([\s]*)/', '', $text); $text = preg_replace('/([\s]*)__NOTOC__([\s]*)/', '', $text); @@ -1228,7 +1220,6 @@ } else { - $q = $db->sql_query('SELECT t.page_text, t.char_tag, l.time_id FROM '.table_prefix."page_text AS t\n" . " LEFT JOIN " . table_prefix . "logs AS l\n" . " ON ( l.page_id = t.page_id AND l.namespace = t.namespace )\n" diff -r 2529833a7731 -r 27377179fe58 includes/paths.php --- a/includes/paths.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/paths.php Wed Jul 02 19:36:44 2008 -0400 @@ -113,7 +113,7 @@ eval($cmd); } - $this->wiki_mode = (int)getConfig('wiki_mode')=='1'; + $this->wiki_mode = ( getConfig('wiki_mode') == '1' ) ? 1 : 0; $this->template_cache = Array(); } function parse_url($sanitize = true) diff -r 2529833a7731 -r 27377179fe58 includes/render.php --- a/includes/render.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/render.php Wed Jul 02 19:36:44 2008 -0400 @@ -217,6 +217,9 @@ global $db, $session, $paths, $template, $plugins; // Common objects global $lang; + require_once(ENANO_ROOT.'/includes/wikiformat.php'); + require_once(ENANO_ROOT.'/includes/wikiengine/Tables.php'); + profiler_log("RenderMan: starting wikitext render"); $random_id = md5( time() . mt_rand() ); @@ -474,13 +477,19 @@ /** * Parses internal links (wikilinks) in a block of text. * @param string Text to process + * @param string Optional. If included will be used as a template instead of using the default syntax. * @return string */ - public static function parse_internal_links($text) + public static function parse_internal_links($text, $tplcode = false) { global $db, $session, $paths, $template, $plugins; // Common objects + if ( is_string($tplcode) ) + { + $parser = $template->makeParserText($tplcode); + } + // stage 1 - links with alternate text preg_match_all('/\[\[([^\[\]<>\{\}\|]+)\|(.+?)\]\]/', $text, $matches); foreach ( $matches[0] as $i => $match ) @@ -493,7 +502,19 @@ $quot = '"'; $exists = ( isPage($pid_clean) ) ? '' : ' class="wikilink-nonexistent"'; - $link = "{$inner_text}"; + if ( $tplcode ) + { + $parser->assign_vars(array( + 'HREF' => $url, + 'FLAGS' => $exists, + 'TEXT' => $inner_text + )); + $link = $parser->run(); + } + else + { + $link = "{$inner_text}"; + } $text = str_replace($match, $link, $text); } @@ -510,7 +531,19 @@ $quot = '"'; $exists = ( isPage($pid_clean) ) ? '' : ' class="wikilink-nonexistent"'; - $link = "{$inner_text}"; + if ( $tplcode ) + { + $parser->assign_vars(array( + 'HREF' => $url, + 'FLAGS' => $exists, + 'TEXT' => $inner_text + )); + $link = $parser->run(); + } + else + { + $link = "{$inner_text}"; + } $text = str_replace($match, $link, $text); } @@ -845,6 +878,7 @@ public static function diff($str1, $str2) { global $db, $session, $paths, $template, $plugins; // Common objects + require_once(ENANO_ROOT.'/includes/diff.php'); $str1 = explode("\n", $str1); $str2 = explode("\n", $str2); $diff = new Diff($str1, $str2); diff -r 2529833a7731 -r 27377179fe58 includes/sessions.php --- a/includes/sessions.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/sessions.php Wed Jul 02 19:36:44 2008 -0400 @@ -586,8 +586,8 @@ . ' ON g.group_id=m.group_id' . "\n" . ' WHERE ( m.user_id='.$this->user_id.'' . "\n" . ' OR g.group_name=\'Everyone\')' . "\n" - . ' ' . ( enano_version() == '1.0RC1' ? '' : 'AND ( m.pending != 1 OR m.pending IS NULL )' ) . '' . "\n" - . ' ORDER BY group_id ASC;'); // Make sure "Everyone" comes first so the permissions can be overridden + . ' ' . ( /* quick hack for upgrade compatibility reasons */ enano_version() == '1.0RC1' ? '' : 'AND ( m.pending != 1 OR m.pending IS NULL )' ) . '' . "\n" + . ' ORDER BY group_id ASC;'); // The ORDER BY is to make sure "Everyone" comes first so the permissions can be overridden if($row = $db->fetchrow()) { do { @@ -2801,6 +2801,8 @@ $objcache[$namespace][$page_id] = new Session_ACLPageInfo( $page_id, $namespace, $this->acl_types, $this->acl_descs, $this->acl_deps, $this->acl_base_cache ); $object =& $objcache[$namespace][$page_id]; + profiler_log("session: fetched ACLs for page {$namespace}:{$page_id}"); + return $object; } @@ -3020,48 +3022,12 @@ // Cache the sitewide permissions for later use $this->acl_base_cache = $this->perms; - // Eliminate types that don't apply to this namespace - foreach ( $this->perms AS $i => $perm ) - { - if ( !in_array ( $paths->namespace, $this->acl_scope[$i] ) && !in_array('All', $this->acl_scope[$i]) ) - { - unset($this->perms[$i]); - } - } - - // PAGE group info - $pg_list = $paths->get_page_groups($paths->page_id, $paths->namespace); - $pg_info = ''; - foreach ( $pg_list as $g_id ) - { - $pg_info .= ' ( page_id=\'' . $g_id . '\' AND namespace=\'__PageGroup\' ) OR'; - } + profiler_log('session: base ACL set calculated'); - // Build a query to grab ACL info - $bs = 'SELECT rules,target_type,target_id FROM '.table_prefix.'acl WHERE ( '; - $q = Array(); - $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$this->user_id.' )'; - if(count($this->groups) > 0) - { - foreach($this->groups as $g_id => $g_name) - { - $q[] = '( target_type='.ACL_TYPE_GROUP.' AND target_id='.intval($g_id).' )'; - } - } - // The reason we're using an ORDER BY statement here is because ACL_TYPE_GROUP is less than ACL_TYPE_USER, causing the user's individual - // permissions to override group permissions. - $bs .= implode(" OR\n ", $q) . " )\n AND (" . $pg_info . ' ( page_id=\''.$db->escape($paths->page_id).'\' AND namespace=\''.$db->escape($paths->namespace).'\' ) ) - ORDER BY target_type ASC, page_id ASC, namespace ASC;'; - $q = $this->sql($bs); - if ( $row = $db->fetchrow() ) - { - do { - $rules = $this->string_to_perm($row['rules']); - $is_everyone = ( $row['target_type'] == ACL_TYPE_GROUP && $row['target_id'] == 1 ); - $this->acl_merge_with_current($rules, $is_everyone); - } while ( $row = $db->fetchrow() ); - } - + // Load and calculate permissions for the current page + $page_acl = $this->fetch_page_acl($paths->page_id, $paths->namespace); + $this->perms = $page_acl->perms; + $this->acl_defaults_used = $page_acl->acl_defaults_used; } /** @@ -3558,6 +3524,8 @@ global $db, $session, $paths, $template, $plugins; // Common objects // Setup EnanoMath and Diffie-Hellman + require_once(ENANO_ROOT.'/includes/math.php'); + global $dh_supported; $dh_supported = true; try diff -r 2529833a7731 -r 27377179fe58 includes/template.php --- a/includes/template.php Mon Jun 30 17:22:29 2008 -0400 +++ b/includes/template.php Wed Jul 02 19:36:44 2008 -0400 @@ -86,23 +86,9 @@ // List out all CSS files for this theme foreach ( $this->theme_list as $i => &$theme ) { - $theme['css'] = array(); - $dir = ENANO_ROOT . "/themes/{$theme['theme_id']}/css"; - if ( $dh = @opendir($dir) ) - { - while ( ( $file = @readdir($dh) ) !== false ) - { - if ( preg_match('/\.css$/', $file) ) - $theme['css'][] = preg_replace('/\.css$/', '', $file); - } - closedir($dh); - } - // No CSS files? If so, nuke it. - if ( count($theme['css']) < 1 ) - { - unset($this->theme_list[$i]); - } + $theme['css'] = $this->get_theme_css_files($theme['theme_id']); } + unset($theme); $this->theme_list = array_values($this->theme_list); // Create associative array of themes foreach ( $this->theme_list as $i => &$theme ) @@ -116,6 +102,33 @@ } /** + * Gets the list of available CSS files (styles) for the specified theme. + * @param string Theme ID + * @return array + */ + + function get_theme_css_files($theme_id) + { + $css = array(); + $dir = ENANO_ROOT . "/themes/{$theme_id}/css"; + if ( $dh = @opendir($dir) ) + { + while ( ( $file = @readdir($dh) ) !== false ) + { + if ( preg_match('/\.css$/', $file) ) + $css[] = preg_replace('/\.css$/', '', $file); + } + closedir($dh); + } + // No CSS files? If so, nuke it. + if ( count($css) < 1 ) + { + unset($this->theme_list[$theme_id]); + } + return $css; + } + + /** * Failsafe constructor for upgrades. */ @@ -566,8 +579,6 @@ // PAGE TOOLBAR (on-page controls/actions) // - profiler_log('template: var init: finished initial setup, starting toolbar'); - // Initialize the toolbar $tb = ''; @@ -948,8 +959,6 @@ // OTHER SWITCHES // - profiler_log('template: var init: finshed toolbar, starting other switches'); - $is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false; $this->tpl_bool = Array( @@ -1043,8 +1052,6 @@ $admin_link = $parser->run(); - profiler_log('template: var init: finished sidebar/misc processing, starting dynamic vars and finalization'); - $SID = ($session->sid_super) ? $session->sid_super : ''; $urlname_clean = str_replace('\'', '\\\'', str_replace('\\', '\\\\', dirtify_page_id($local_fullpage))); @@ -1111,8 +1118,6 @@ } $js_dynamic .= "\n //]]>\n "; - profiler_log('template: var init: finished JS dynamic vars and assigning final var set'); - $tpl_strings = Array( 'PAGE_NAME'=>htmlspecialchars($local_cdata['name']), 'PAGE_URLNAME'=> $urlname_clean, @@ -1154,14 +1159,14 @@ $this->assign_vars($tpl_strings, true); + profiler_log('template: var init: finished toolbar building and initial assign()'); + // // COMPILE THE SIDEBAR // // This is done after the big assign_vars() so that sidebar code has access to the newly assigned variables - profiler_log('template: var init: finished final var set, executing and applying sidebar templates'); - list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar(); $this->tpl_bool['sidebar_left'] = ( $this->tpl_strings['SIDEBAR_LEFT'] != $min) ? true : false; $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false; @@ -1299,7 +1304,11 @@ $t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t); if ( defined('ENANO_DEBUG') ) + { $t = str_replace('