# HG changeset patch # User Dan # Date 1201230369 18000 # Node ID 5bd4294281018774c4972feaefafdbf60dd5aa77 # Parent dc60263769194c594bfc180bf927504e48e2b8d4 A number of scattered changes. Profiler added and only enabled in debug mode (currently on), but awfully useful for fixing performance in the future. Started work on Admin:LangManager diff -r dc6026376919 -r 5bd429428101 includes/clientside/static/misc.js --- a/includes/clientside/static/misc.js Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/clientside/static/misc.js Thu Jan 24 22:06:09 2008 -0500 @@ -325,7 +325,7 @@ case 'invalid_credentials': $errstring = $lang.get('user_err_invalid_credentials'); var subst = { - lockout_fails: $data.lockout_fails, + fails: $data.lockout_fails, lockout_threshold: $data.lockout_threshold, lockout_duration: $data.lockout_duration } diff -r dc6026376919 -r 5bd429428101 includes/common.php --- a/includes/common.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/common.php Thu Jan 24 22:06:09 2008 -0500 @@ -121,6 +121,8 @@ strip_magic_quotes_gpc(); +profiler_log('Files included and magic_quotes_gpc reversed if applicable'); + // Enano has five main components: the database abstraction layer (DBAL), the session manager, // the path/URL manager, the template engine, and the plugin manager. // Each part has its own class and a global object; nearly all Enano functions are handled by one of these five components. @@ -163,6 +165,8 @@ $db = new $dbdriver(); $db->connect(); +profiler_log('Database connected'); + // The URL separator is the character appended to contentPath + url_title type strings. // If the contentPath has a ? in it, this should be an ampersand; else, it should be a // question mark. @@ -203,6 +207,8 @@ $db->free_result(); +profiler_log('Config fetched'); + // Now that we have the config, check the Enano version. if ( enano_version(false, true) != $version && !defined('IN_ENANO_UPGRADE') ) { @@ -240,7 +246,7 @@ } // Is there no default language? -if ( getConfig('lang_default') === false && !defined('IN_ENANO_MIGRATION') ) +if ( getConfig('default_language') === false && !defined('IN_ENANO_MIGRATION') ) { $q = $db->sql_query('SELECT lang_id FROM '.table_prefix.'language LIMIT 1;'); if ( !$q ) @@ -260,6 +266,8 @@ setConfig('default_language', $row['lang_id']); } +profiler_log('Ran checks'); + // Load plugin manager $plugins = new pluginLoader(); @@ -278,12 +286,16 @@ include_once $f; } +profiler_log('Loaded plugins'); + // Three fifths of the Enano API gets the breath of life right here. $session = new sessionManager(); $paths = new pathManager(); $template = new template(); $email = new EmailEncryptor(); +profiler_log('Instanciated important singletons'); + // We've got the five main objects - flick on the switch so if a problem occurs, we can have a "friendly" UI define('ENANO_BASE_CLASSES_INITIALIZED', ''); @@ -301,6 +313,8 @@ eval($cmd); } + profiler_log('Finished base_classes_initted hook'); + // For special and administration pages, sometimes there is a "preloader" function that must be run // before the session manager and/or path manager get the init signal. Call it here. $p = RenderMan::strToPageId($paths->get_pageid_from_url()); @@ -309,6 +323,8 @@ @call_user_func('page_'.$p[1].'_'.$p[0].'_preloader'); } + profiler_log('Checked for preloader'); + // One quick security check... if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) ) { @@ -328,6 +344,8 @@ eval($cmd); } + profiler_log('Ran session_started hook'); + $paths->init(); // We're ready for whatever life throws us now. @@ -369,10 +387,14 @@ eval($cmd); } + profiler_log('Ran disabled-site checks and common_post'); + if ( isset($_GET['noheaders']) ) $template->no_headers = true; } +profiler_log('common finished'); + // That's the end. Enano should be loaded now :-) ?> diff -r dc6026376919 -r 5bd429428101 includes/functions.php --- a/includes/functions.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/functions.php Thu Jan 24 22:06:09 2008 -0500 @@ -1292,7 +1292,8 @@ function enano_debug_print_backtrace($return = false) { ob_start(); - echo '
';
+  if ( !$return )
+    echo '
';
   if ( function_exists('debug_print_backtrace') )
   {
     debug_print_backtrace();
@@ -1301,7 +1302,8 @@
   {
     echo 'Warning: No debug_print_backtrace() support!';
   }
-  echo '
'; + if ( !$return ) + echo '
'; $c = ob_get_contents(); ob_end_clean(); if($return) return $c; @@ -3244,7 +3246,7 @@ VALUES( \'' . $db->escape($lang_code) . '\', \'' . $db->escape($lang_name_neutral) . '\', - \'' . $db->escape($lang_name_native) . '\' + \'' . $db->escape($lang_name_local) . '\' );'); if ( !$q ) $db->_die('functions.php - installing language'); @@ -3280,6 +3282,52 @@ } /** + * Lists available languages. + * @return array Multi-depth. Associative, with children associative containing keys name, name_eng, and dir. + */ + +function list_available_languages() +{ + // Pulled from install/includes/common.php + + // Build a list of available languages + $dir = @opendir( ENANO_ROOT . '/language' ); + if ( !$dir ) + die('CRITICAL: could not open language directory'); + + $languages = array(); + + while ( $dh = @readdir($dir) ) + { + if ( $dh == '.' || $dh == '..' ) + continue; + if ( file_exists( ENANO_ROOT . "/language/$dh/meta.json" ) ) + { + // Found a language directory, determine metadata + $meta = @file_get_contents( ENANO_ROOT . "/language/$dh/meta.json" ); + if ( empty($meta) ) + // Could not read metadata file, continue silently + continue; + + // Do some syntax correction on the metadata + $meta = enano_clean_json($meta); + + $meta = enano_json_decode($meta); + if ( isset($meta['lang_name_english']) && isset($meta['lang_name_native']) && isset($meta['lang_code']) ) + { + $languages[$meta['lang_code']] = array( + 'name' => $meta['lang_name_native'], + 'name_eng' => $meta['lang_name_english'], + 'dir' => $dh + ); + } + } + } + + return $languages; +} + +/** * Scales an image to the specified width and height, and writes the output to the specified * file. Will use ImageMagick if present, but if not will attempt to scale with GD. This will * always scale images proportionally. @@ -3893,6 +3941,140 @@ return Zend_Json::decode($data, Zend_Json::TYPE_ARRAY); } +/** + * Cleans a snippet of JSON for closer standards compliance (shuts up the picky Zend parser) + * @param string Dirty JSON + * @return string Clean JSON + */ + +function enano_clean_json($json) +{ + // eliminate comments + $json = preg_replace(array( + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + ), '', $json); + + $json = preg_replace('/([,\{\[])([\s]*?)([a-z0-9_]+)([\s]*?):/', '\\1\\2"\\3" :', $json); + + return $json; +} + +/** + * Starts the profiler. + */ + +function profiler_start() +{ + global $_profiler; + $_profiler = array(); + + if ( !defined('ENANO_DEBUG') ) + return false; + + $_profiler[] = array( + 'point' => 'Profiling started', + 'time' => microtime_float(), + 'backtrace' => false + ); +} + +/** + * Logs something in the profiler. + * @param string Point name or message + * @param bool Optional. If true (default), a backtrace will be generated and added to the profiler data. False disables this, often for security reasons. + */ + +function profiler_log($point, $allow_backtrace = true) +{ + if ( !defined('ENANO_DEBUG') ) + return false; + + global $_profiler; + $backtrace = false; + if ( $allow_backtrace && function_exists('debug_print_backtrace') ) + { + list(, $backtrace) = explode("\n", enano_debug_print_backtrace(true)); + } + $_profiler[] = array( + 'point' => $point, + 'time' => microtime_float(), + 'backtrace' => $backtrace + ); +} + +/** + * Returns the profiler's data (so far). + * @return array + */ + +function profiler_dump() +{ + return $GLOBALS['_profiler']; +} + +/** + * Generates an HTML version of the performance profile. Not localized because only used as a debugging tool. + * @return string + */ + +function profiler_make_html() +{ + if ( !defined('ENANO_DEBUG') ) + return ''; + + $profile = profiler_dump(); + + $html = '
'; + $html .= ''; + + $time_start = $time_last = $profile[0]['time']; + + foreach ( $profile as $i => $entry ) + { + $html .= ""; + + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + + $time = $entry['time'] - $time_start; + + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + + $time = $entry['time'] - $time_last; + + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + + if ( $entry['backtrace'] ) + { + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + } + + $time_last = $entry['time']; + } + $html .= '
Event $i
Event:' . htmlspecialchars($entry['point']) . '
Time since start:' . $time . 's
Time since last event:' . $time . 's
Called from:' . htmlspecialchars($entry['backtrace']) . '
'; + + return $html; +} + +// Might as well start the profiler, it has no external dependencies except from this file. +profiler_start(); + //die('
Original:  01010101010100101010100101010101011010'."\nProcessed: ".uncompress_bitfield(compress_bitfield('01010101010100101010100101010101011010')).'
'); ?> diff -r dc6026376919 -r 5bd429428101 includes/lang.php --- a/includes/lang.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/lang.php Thu Jan 24 22:06:09 2008 -0500 @@ -89,7 +89,8 @@ } $lang_default = ( $x = getConfig('default_language') ) ? intval($x) : '\'def\''; - $q = $db->sql_query("SELECT lang_id, lang_code, last_changed, ( lang_id = $lang_default ) AS is_default FROM " . table_prefix . "language WHERE $sql_col OR lang_id = $lang_default ORDER BY is_default DESC LIMIT 1;"); + + $q = $db->sql_query("SELECT lang_id, lang_code, last_changed, ( lang_id = $lang_default ) AS is_default FROM " . table_prefix . "language WHERE $sql_col OR lang_id = $lang_default ORDER BY is_default ASC LIMIT 1;"); if ( !$q ) $db->_die('lang.php - main select query'); @@ -320,18 +321,7 @@ $contents = preg_replace('/\}([^}]+)$/', '}', $contents); // Correct syntax to be nice to the json parser - - // eliminate comments - $contents = preg_replace(array( - // eliminate single line comments in '// ...' form - '#^\s*//(.+)$#m', - // eliminate multi-line comments in '/* ... */' form, at start of string - '#^\s*/\*(.+)\*/#Us', - // eliminate multi-line comments in '/* ... */' form, at end of string - '#/\*(.+)\*/\s*$#Us' - ), '', $contents); - - $contents = preg_replace('/([,\{\[])([\s]*?)([a-z0-9_]+)([\s]*?):/', '\\1\\2"\\3" :', $contents); + $contents = enano_clean_json($contents); try { diff -r dc6026376919 -r 5bd429428101 includes/pageprocess.php --- a/includes/pageprocess.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/pageprocess.php Thu Jan 24 22:06:09 2008 -0500 @@ -131,6 +131,8 @@ { global $db, $session, $paths, $template, $plugins; // Common objects + profiler_log("PageProcessor [{$namespace}:{$page_id}]: Started constructor"); + // See if we can get some debug info if ( function_exists('debug_backtrace') && $this->debug['enable'] ) { @@ -148,8 +150,9 @@ if ( !is_int($revision_id) ) $revision_id = 0; + profiler_log("PageProcessor [{$namespace}:{$page_id}]: Ran initial checks"); + $this->_setup( $page_id, $namespace, $revision_id ); - } /** @@ -162,9 +165,12 @@ global $db, $session, $paths, $template, $plugins; // Common objects global $lang; + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Started send process"); + if ( !$this->perms->get_permissions('read') ) { $this->err_access_denied(); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } $pathskey = $paths->nslist[ $this->namespace ] . $this->page_id; @@ -193,6 +199,7 @@ if ( $this->password != $password ) { $this->err_wrong_password(); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } } @@ -211,7 +218,10 @@ $func_name = "page_{$this->namespace}_{$this->page_id}"; if ( function_exists($func_name) ) { - return @call_user_func($func_name); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Calling special/admin page"); + $result = @call_user_func($func_name); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); + return $result; } else { @@ -230,6 +240,7 @@ echo "

$title

$message

"; } + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } } @@ -297,6 +308,7 @@ if ( $text == 'err_no_text_rows' ) { $this->err_no_rows(); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); return false; } else @@ -327,6 +339,7 @@ } } } + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process"); } /** @@ -596,6 +609,7 @@ $this->title = get_page_title_ns($this->page_id, $this->namespace); + profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Ran _setup()"); } /** diff -r dc6026376919 -r 5bd429428101 includes/pageutils.php --- a/includes/pageutils.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/pageutils.php Thu Jan 24 22:06:09 2008 -0500 @@ -21,7 +21,7 @@ * @return string */ - function checkusername($name) + public static function checkusername($name) { global $db, $session, $paths, $template, $plugins; // Common objects $name = str_replace('_', ' ', $name); @@ -47,7 +47,7 @@ * @todo (DONE) Make it require a password (just for security purposes) */ - function getsource($page, $password = false) + public static function getsource($page, $password = false) { global $db, $session, $paths, $template, $plugins; // Common objects if(!isset($paths->pages[$page])) @@ -95,7 +95,7 @@ * @return string */ - function getpage($page, $send_headers = false, $hist_id = false) + public static function getpage($page, $send_headers = false, $hist_id = false) { die('PageUtils->getpage is deprecated.'); global $db, $session, $paths, $template, $plugins; // Common objects @@ -328,7 +328,7 @@ * @return string */ - function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false) + public static function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false) { global $db, $session, $paths, $template, $plugins; // Common objects $uid = sha1(microtime()); @@ -399,7 +399,7 @@ * @return bool true on success, false on failure */ - function createPage($page_id, $namespace, $name = false, $visible = 1) + public static function createPage($page_id, $namespace, $name = false, $visible = 1) { global $db, $session, $paths, $template, $plugins; // Common objects if(in_array($namespace, Array('Special', 'Admin'))) @@ -494,7 +494,7 @@ * @param $reason string why the page is being (un)protected * @return string - "good" on success, in all other cases, an error string (on query failure, calls $db->_die() ) */ - function protect($page_id, $namespace, $level, $reason) + public static function protect($page_id, $namespace, $level, $reason) { global $db, $session, $paths, $template, $plugins; // Common objects @@ -548,7 +548,7 @@ * @return string */ - function histlist($page_id, $namespace) + public static function histlist($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -741,7 +741,7 @@ * @return string */ - function rollback($id) + public static function rollback($id) { global $db, $session, $paths, $template, $plugins; // Common objects if ( !$session->get_permissions('history_rollback') ) @@ -908,7 +908,7 @@ * @return string javascript code */ - function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false) + public static function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false) { global $db, $session, $paths, $template, $plugins; // Common objects $_ob = ''; @@ -943,7 +943,7 @@ * @access private */ - function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '') + public static function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '') { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1202,7 +1202,7 @@ * @return string */ - function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '') + public static function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '') { global $db, $session, $paths, $template, $plugins; // Common objects $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob); @@ -1219,7 +1219,7 @@ * @return string */ - function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '') + public static function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '') { global $db, $session, $paths, $template, $plugins; // Common objects $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob); @@ -1238,7 +1238,7 @@ * @return string */ - function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1) + public static function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1) { global $db, $session, $paths, $template, $plugins; // Common objects if(!$session->get_permissions('edit_comments')) @@ -1289,7 +1289,7 @@ * @return string */ - function savecomment_neater($page_id, $namespace, $subject, $text, $id) + public static function savecomment_neater($page_id, $namespace, $subject, $text, $id) { global $db, $session, $paths, $template, $plugins; // Common objects if(!is_int($id)) die('PageUtils::savecomment: $id is not an integer, aborting for safety'); @@ -1330,7 +1330,7 @@ * @return string */ - function deletecomment($page_id, $namespace, $name, $subj, $text, $id) + public static function deletecomment($page_id, $namespace, $name, $subj, $text, $id) { global $db, $session, $paths, $template, $plugins; // Common objects @@ -1367,7 +1367,7 @@ * @return string */ - function deletecomment_neater($page_id, $namespace, $id) + public static function deletecomment_neater($page_id, $namespace, $id) { global $db, $session, $paths, $template, $plugins; // Common objects @@ -1401,7 +1401,7 @@ * @return string error string or success message */ - function rename($page_id, $namespace, $name) + public static function rename($page_id, $namespace, $name) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1449,7 +1449,7 @@ * @return string error/success string */ - function flushlogs($page_id, $namespace) + public static function flushlogs($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1488,7 +1488,7 @@ * @return string */ - function deletepage($page_id, $namespace, $reason) + public static function deletepage($page_id, $namespace, $reason) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1521,7 +1521,7 @@ * @return string */ - function delvote($page_id, $namespace) + public static function delvote($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1588,7 +1588,7 @@ * @return string */ - function resetdelvotes($page_id, $namespace) + public static function resetdelvotes($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1611,7 +1611,7 @@ * @return string JSON string with an array containing a list of themes */ - function getstyles() + public static function getstyles() { if ( !preg_match('/^([a-z0-9_-]+)$/', $_GET['id']) ) @@ -1648,7 +1648,7 @@ * @return string Javascript code */ - function catedit($page_id, $namespace) + public static function catedit($page_id, $namespace) { $d = PageUtils::catedit_raw($page_id, $namespace); return $d[0] . ' /* BEGIN CONTENT */ document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.rawurlencode($d[1]).'\');'; @@ -1659,7 +1659,7 @@ * @access private */ - function catedit_raw($page_id, $namespace) + public static function catedit_raw($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1742,7 +1742,7 @@ * @return string "GOOD" on success, error string on failure */ - function catsave($page_id, $namespace, $which_cats) + public static function catsave($page_id, $namespace, $which_cats) { global $db, $session, $paths, $template, $plugins; // Common objects if(!$session->get_permissions('edit_cat')) return('Insufficient privileges to change category information'); @@ -1814,7 +1814,7 @@ * @return string "GOOD" on success, error string on failure */ - function setwikimode($page_id, $namespace, $level) + public static function setwikimode($page_id, $namespace, $level) { global $db, $session, $paths, $template, $plugins; // Common objects if(!$session->get_permissions('set_wiki_mode')) return('Insufficient access rights'); @@ -1838,7 +1838,7 @@ * @return string */ - function setpass($page_id, $namespace, $pass) + public static function setpass($page_id, $namespace, $pass) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1880,7 +1880,7 @@ * @return string */ - function genPreview($text) + public static function genPreview($text) { global $lang; $ret = '
' . $lang->get('editor_preview_blurb') . '
'; @@ -1901,7 +1901,7 @@ * @return string */ - function scrollBox($text, $height = 250) + public static function scrollBox($text, $height = 250) { return '
' . $text . '
'; } @@ -1915,7 +1915,7 @@ * @return string XHTML-formatted diff */ - function pagediff($page_id, $namespace, $id1, $id2) + public static function pagediff($page_id, $namespace, $id1, $id2) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -1952,7 +1952,7 @@ * @return array */ - function acl_editor($parms = Array()) + public static function acl_editor($parms = Array()) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -2194,7 +2194,7 @@ * @return string */ - function acl_json($parms = '{ }') + public static function acl_json($parms = '{ }') { global $db, $session, $paths, $template, $plugins; // Common objects $parms = enano_json_decode($parms); @@ -2208,7 +2208,7 @@ * @param array The request data, if any, this should be in the format required by PageUtils::acl_editor() */ - function aclmanager($parms) + public static function aclmanager($parms) { global $db, $session, $paths, $template, $plugins; // Common objects global $lang; @@ -2400,7 +2400,7 @@ * @access private */ - function acl_preprocess($parms) + public static function acl_preprocess($parms) { if ( !isset($parms['mode']) ) // Nothing to do @@ -2445,7 +2445,7 @@ return $parms; } - function acl_postprocess($response) + public static function acl_postprocess($response) { if(!isset($response['mode'])) { diff -r dc6026376919 -r 5bd429428101 includes/paths.php --- a/includes/paths.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/paths.php Thu Jan 24 22:06:09 2008 -0500 @@ -81,6 +81,7 @@ $this->addAdminNode('adm_cat_general', 'adm_page_file_types', 'UploadAllowedMimeTypes'); $this->addAdminNode('adm_cat_general', 'adm_page_plugins', 'PluginManager'); $this->addAdminNode('adm_cat_general', 'adm_page_db_backup', 'DBBackup'); + $this->addAdminNode('adm_cat_general', 'adm_page_lang_manager', 'LangManager'); $this->addAdminNode('adm_cat_content', 'adm_page_manager', 'PageManager'); $this->addAdminNode('adm_cat_content', 'adm_page_editor', 'PageEditor'); $this->addAdminNode('adm_cat_content', 'adm_page_pg_groups', 'PageGroups'); @@ -410,6 +411,7 @@ } $session->init_permissions(); + profiler_log('Paths and CMS core initted'); } function add_page($flags) diff -r dc6026376919 -r 5bd429428101 includes/sessions.php --- a/includes/sessions.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/sessions.php Thu Jan 24 22:06:09 2008 -0500 @@ -560,6 +560,7 @@ $this->style = 'default'; } + profiler_log('Sessions started'); } # Logins @@ -678,7 +679,7 @@ { $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); // increment fail count - $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', UNIX_TIMESTAMP(), \'credential\');'); + $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); $fails++; // ooh boy, somebody's in trouble ;-) return array( @@ -791,7 +792,7 @@ { $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); // increment fail count - $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', UNIX_TIMESTAMP(), \'credential\');'); + $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); $fails++; return array( 'success' => false, @@ -897,7 +898,7 @@ { $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); // increment fail count - $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', UNIX_TIMESTAMP(), \'credential\');'); + $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); $fails++; return array( 'success' => false, @@ -1002,7 +1003,7 @@ { $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); // increment fail count - $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', UNIX_TIMESTAMP(), \'credential\');'); + $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); $fails++; return array( 'success' => false, diff -r dc6026376919 -r 5bd429428101 includes/template.php --- a/includes/template.php Wed Jan 23 12:48:22 2008 -0500 +++ b/includes/template.php Thu Jan 24 22:06:09 2008 -0500 @@ -132,6 +132,8 @@ global $email; global $lang; + profiler_log("template: starting var init"); + if(!$this->theme || !$this->style) { $this->load_theme(); @@ -791,6 +793,8 @@ { eval($cmd); } + + profiler_log("template: finished var init"); } function header($simple = false) @@ -834,10 +838,12 @@
'; } } + function footer($simple = false) { global $db, $session, $paths, $template, $plugins; // Common objects - if(!$this->no_headers) { + if ( !$this->no_headers ) + { if(!defined('ENANO_HEADERS_SENT')) $this->header(); @@ -858,12 +864,20 @@ $t = str_replace('[[Stats]]', $dbg, $t); $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t); $t = str_replace('[[GenTime]]', (string)$f, $t); + + if ( defined('ENANO_DEBUG') ) + $t = str_replace('', '
' . profiler_make_html() . '
', $t); + echo $t; ob_end_flush(); } - else return ''; + else + { + return ''; + } } + function getHeader() { $headers_sent = true; diff -r dc6026376919 -r 5bd429428101 index.php --- a/index.php Wed Jan 23 12:48:22 2008 -0500 +++ b/index.php Thu Jan 24 22:06:09 2008 -0500 @@ -17,6 +17,9 @@ */ define('ENANO_INTERFACE_INDEX', ''); + + // For the mighty and brave. + define('ENANO_DEBUG', ''); // Set up gzip encoding before any output is sent @@ -34,15 +37,6 @@ error_reporting(E_ALL); - // if(!strstr($v, 'CSS') && !strstr($v, 'UploadFile') && !strstr($v, 'DownloadFile')) // These pages are blacklisted because we can't have debugConsole's HTML output disrupting the flow of header() calls and whatnot - // { - // $do_gzip = ( function_exists('gzcompress') && ( isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') ) ) ? true : false; - // // Uncomment the following line to enable debugConsole (requires PHP 5 or later) - // // define('ENANO_DEBUG', ''); - // } - - if(defined('ENANO_DEBUG')) $do_gzip = false; - if($aggressive_optimize_html || $do_gzip) { ob_start(); diff -r dc6026376919 -r 5bd429428101 language/english/admin.json --- a/language/english/admin.json Wed Jan 23 12:48:22 2008 -0500 +++ b/language/english/admin.json Thu Jan 24 22:06:09 2008 -0500 @@ -13,8 +13,8 @@ var enano_lang = { categories: [ 'meta', 'adm', 'acl', 'adminusers', - 'acphome', 'acpgc', 'acpup', 'acpft', 'acppl', 'acppm', 'acped', 'acpdb', 'acppg', 'acpum', 'acpug', 'acpcp', 'acpmm', 'acpsl', 'acpbc', - 'acplo', 'sbedit', + 'acphome', 'acpgc', 'acpup', 'acpft', 'acppl', 'acppm', 'acped', 'acpdb', 'acplm', 'acppg', 'acpum', 'acpug', 'acpcp', 'acpmm', 'acpsl', + 'acpbc', 'acplo', 'sbedit', ], strings: { meta: { @@ -26,6 +26,7 @@ acpft: 'ACP: Allowed file types', acppl: 'ACP: Manage plugins', acpdb: 'ACP: Database backup', + acplm: 'ACP: Language manager', acppm: 'ACP: Manage pages', acped: 'ACP: Edit page content', acppg: 'ACP: Page groups', @@ -51,6 +52,7 @@ page_file_types: 'Allowed file types', page_plugins: 'Manage plugins', page_db_backup: 'Backup database', + page_lang_manager: 'Language manager', page_manager: 'Manage pages', page_editor: 'Edit page content', @@ -440,6 +442,14 @@ lbl_include_data: 'Include table data', btn_create_backup: 'Create backup', }, + acplm: { + heading_install: 'Languages available for installation', + col_lang_code: 'ID', + col_lang_name: 'Language name (native)', + col_lang_name_eng: 'Language name (English)', + btn_install_language: 'Install', + msg_lang_install_success: 'The language pack %lang_name% has been installed.', + }, acppg: { // Main menu heading_main: 'Manage page groups', diff -r dc6026376919 -r 5bd429428101 language/english/user.json --- a/language/english/user.json Wed Jan 23 12:48:22 2008 -0500 +++ b/language/english/user.json Thu Jan 24 22:06:09 2008 -0500 @@ -242,6 +242,8 @@ publicinfo_heading_main: 'Your public profile', publicinfo_note_optional: 'Please note that all of the information you enter here will be publicly viewable. All of the fields on this page are optional and may be left blank if you so desire.', publicinfo_field_realname: 'Real name:', + publicinfo_field_language: 'Preferred language:', + publicinfo_field_language_hint: 'Select the language special pages and page controls should appear in.', publicinfo_field_changetheme_title: 'Change theme:', publicinfo_field_changetheme_hint: 'If you don\'t like the look of the site, need a visual break, or are just curious, we might have some different themes for you to try out!', publicinfo_field_changetheme: 'Change my theme...', diff -r dc6026376919 -r 5bd429428101 plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Wed Jan 23 12:48:22 2008 -0500 +++ b/plugins/SpecialAdmin.php Thu Jan 24 22:06:09 2008 -0500 @@ -46,6 +46,7 @@ require(ENANO_ROOT . '/plugins/admin/GroupManager.php'); require(ENANO_ROOT . '/plugins/admin/SecurityLog.php'); require(ENANO_ROOT . '/plugins/admin/UserManager.php'); +require(ENANO_ROOT . '/plugins/admin/LangManager.php'); // function names are IMPORTANT!!! The name pattern is: page__ diff -r dc6026376919 -r 5bd429428101 plugins/SpecialUpdownload.php --- a/plugins/SpecialUpdownload.php Wed Jan 23 12:48:22 2008 -0500 +++ b/plugins/SpecialUpdownload.php Thu Jan 24 22:06:09 2008 -0500 @@ -70,7 +70,7 @@ } $types = fetch_allowed_extensions(); - $ext = substr($file['name'], strrpos($file['name'], '.')+1, strlen($file['name'])); + $ext = strtolower(substr($file['name'], strrpos($file['name'], '.')+1, strlen($file['name']))); if ( !isset($types[$ext]) || ( isset($types[$ext]) && !$types[$ext] ) ) { die_friendly($lang->get('upload_err_title'), '

' . $lang->get('upload_err_banned_ext', array('ext' => htmlspecialchars($ext))) . '

'); diff -r dc6026376919 -r 5bd429428101 plugins/SpecialUserFuncs.php --- a/plugins/SpecialUserFuncs.php Wed Jan 23 12:48:22 2008 -0500 +++ b/plugins/SpecialUserFuncs.php Thu Jan 24 22:06:09 2008 -0500 @@ -373,14 +373,6 @@ $captcha_code = ( isset($data['captcha_code']) ) ? $data['captcha_code'] : false; $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER; $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $data['crypt_key'], $data['challenge'], $level, $captcha_hash, $captcha_code); - $session->start(); - - // Run the session_started hook to establish special pages - $code = $plugins->setHook('session_started'); - foreach ( $code as $cmd ) - { - eval($cmd); - } if ( $result['success'] ) { @@ -419,18 +411,11 @@ { $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code); } - $session->start(); - - // Run the session_started hook to establish special pages - $code = $plugins->setHook('session_started'); - foreach ( $code as $cmd ) - { - eval($cmd); - } - - $paths->init(); + if($result['success']) { + $session->start(); + $template->load_theme($session->theme, $session->style); if(isset($_POST['return_to'])) { diff -r dc6026376919 -r 5bd429428101 plugins/SpecialUserPrefs.php --- a/plugins/SpecialUserPrefs.php Wed Jan 23 12:48:22 2008 -0500 +++ b/plugins/SpecialUserPrefs.php Thu Jan 24 22:06:09 2008 -0500 @@ -547,8 +547,50 @@ if ( !$q ) $db->_die(); + // verify language id + $lang_id = strval(intval($_POST['lang_id'])); + $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . 'language WHERE lang_id = ' . $lang_id . ';'); + if ( !$q ) + $db->_die(); + + if ( $db->numrows() > 0 ) + { + $db->free_result(); + + // unload / reload $lang, this verifies that the selected language works + unset($GLOBALS['lang']); + unset($lang); + $lang_id = intval($lang_id); + $GLOBALS['lang'] = new Language($lang_id); + global $lang; + + $q = $db->sql_query('UPDATE ' . table_prefix . 'users SET user_lang = ' . $lang_id . " WHERE user_id = {$session->user_id};"); + if ( !$q ) + $db->_die(); + } + else + { + $db->free_result(); + } + echo '
' . $lang->get('usercp_publicinfo_msg_save_success') . '
'; } + + $lang_box = ''; + echo '
'; ?>
@@ -564,6 +606,10 @@ + get('usercp_publicinfo_field_language') . '
' . $lang->get('usercp_publicinfo_field_language_hint') . ''; ?> + + + get('usercp_publicinfo_field_changetheme_title'); ?> get('usercp_publicinfo_field_changetheme_hint'); ?> get('usercp_publicinfo_field_changetheme'); ?> diff -r dc6026376919 -r 5bd429428101 plugins/admin/LangManager.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/admin/LangManager.php Thu Jan 24 22:06:09 2008 -0500 @@ -0,0 +1,131 @@ +auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) + { + $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true); + echo '

' . $lang->get('adm_err_not_auth_title') . '

'; + echo '

' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '

'; + return; + } + if ( isset($_POST['action']) ) + { + $action =& $_POST['action']; + if ( strpos($action, ';') ) + { + $parms = substr($action, strpos($action, ';') + 1); + $action = substr($action, 0, strpos($action, ';')); + preg_match_all('/([a-z0-9_]+)=(.+?)(;|$)/', $parms, $matches); + $parms = array(); + foreach ( $matches[0] as $i => $_ ) + { + $parms[$matches[1][$i]] = $matches[2][$i]; + } + } + switch ( $action ) + { + case 'edit_language': + break; + case 'install_language': + $lang_list = list_available_languages(); + // Verify that we have this language's metadata + if ( isset($lang_list[@$parms['iso639']]) ) + { + // From here it's all downhill :-) + $lang_code =& $parms['iso639']; + $lang_data =& $lang_list[$lang_code]; + + $result = install_language($lang_code, $lang_data['name_eng'], $lang_data['name']); + if ( $result ) + { + // Language installed. Import the language files. + $lang_local = new Language($lang_code); + foreach ( array('core', 'admin', 'tools', 'user') as $file ) + { + $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/$file.json"); + } + unset($lang_local); + + echo '
' . $lang->get('acplm_msg_lang_install_success', array('lang_name' => htmlspecialchars($lang_data['name_eng']))) . '
'; + } + } + break; + } + } + + // $lang_list is fetched by the posthandler sometimes + if ( !isset($lang_list) ) + { + // Build a list of languages in the languages/ directory, then + // eliminate the ones that are already installed. + $lang_list = list_available_languages(); + } + + // Select current languages + $q = $db->sql_query('SELECT lang_code FROM ' . table_prefix . "language;"); + if ( !$q ) + $db->_die(); + + while ( $row = $db->fetchrow() ) + { + $lang_code =& $row['lang_code']; + if ( isset($lang_list[$lang_code]) ) + { + unset($lang_list[$lang_code]); + unset($lang_list[$lang_code]); // PHP <5.1.4 Zend bug + } + } + + if ( count($lang_list) > 0 ) + { + echo ''; + echo '

' . $lang->get('acplm_heading_install') . '

'; + echo '
+ + + + + + + '; + + $cls = 'row2'; + foreach ( $lang_list as $lang_code => $lang_data ) + { + $cls = ( $cls == 'row1' ) ? 'row2' : 'row1'; + + echo ''; + + $lang_code = htmlspecialchars($lang_code); + $lang_data['name'] = htmlspecialchars($lang_data['name']); + $lang_data['name_eng'] = htmlspecialchars($lang_data['name_eng']); + + echo ""; + echo ""; + echo ""; + echo ""; + + echo ''; + } + echo ' +
' . $lang->get('acplm_col_lang_code') . '' . $lang->get('acplm_col_lang_name') . '' . $lang->get('acplm_col_lang_name_eng') . '
$lang_code{$lang_data['name']}{$lang_data['name_eng']}
+
'; + echo ''; + } +} +