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
--- 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
}
--- 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 :-)
?>
--- 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 '<pre>';
+ if ( !$return )
+ echo '<pre>';
if ( function_exists('debug_print_backtrace') )
{
debug_print_backtrace();
@@ -1301,7 +1302,8 @@
{
echo '<b>Warning:</b> No debug_print_backtrace() support!';
}
- echo '</pre>';
+ if ( !$return )
+ echo '</pre>';
$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 = '<div class="tblholder">';
+ $html .= '<table border="0" cellspacing="1" cellpadding="4">';
+
+ $time_start = $time_last = $profile[0]['time'];
+
+ foreach ( $profile as $i => $entry )
+ {
+ $html .= "<tr><th colspan=\"2\">Event $i</th></tr>";
+
+ $html .= '<tr>';
+ $html .= '<td class="row2">Event:</td>';
+ $html .= '<td class="row1">' . htmlspecialchars($entry['point']) . '</td>';
+ $html .= '</tr>';
+
+ $time = $entry['time'] - $time_start;
+
+ $html .= '<tr>';
+ $html .= '<td class="row2">Time since start:</td>';
+ $html .= '<td class="row1">' . $time . 's</td>';
+ $html .= '</tr>';
+
+ $time = $entry['time'] - $time_last;
+
+ $html .= '<tr>';
+ $html .= '<td class="row2">Time since last event:</td>';
+ $html .= '<td class="row1">' . $time . 's</td>';
+ $html .= '</tr>';
+
+ if ( $entry['backtrace'] )
+ {
+ $html .= '<tr>';
+ $html .= '<td class="row2">Called from:</td>';
+ $html .= '<td class="row1">' . htmlspecialchars($entry['backtrace']) . '</td>';
+ $html .= '</tr>';
+ }
+
+ $time_last = $entry['time'];
+ }
+ $html .= '</table></div>';
+
+ return $html;
+}
+
+// Might as well start the profiler, it has no external dependencies except from this file.
+profiler_start();
+
//die('<pre>Original: 01010101010100101010100101010101011010'."\nProcessed: ".uncompress_bitfield(compress_bitfield('01010101010100101010100101010101011010')).'</pre>');
?>
--- 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
{
--- 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 "<h2>$title</h2>
<p>$message</p>";
}
+ 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()");
}
/**
--- 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 = '<div class="info-box">' . $lang->get('editor_preview_blurb') . '</div><div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: 250px; overflow: auto; margin: 10px 0;">';
@@ -1901,7 +1901,7 @@
* @return string
*/
- function scrollBox($text, $height = 250)
+ public static function scrollBox($text, $height = 250)
{
return '<div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: '.(string)intval($height).'px; overflow: auto; margin: 1em 0 1em 1em;">' . $text . '</div>';
}
@@ -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']))
{
--- 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)
--- 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,
--- 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 @@
</div>';
}
}
+
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('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
+
echo $t;
ob_end_flush();
}
- else return '';
+ else
+ {
+ return '';
+ }
}
+
function getHeader()
{
$headers_sent = true;
--- 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();
--- 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',
--- 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 <b>publicly viewable.</b> 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...',
--- 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_<namespace ID>_<page URLname, without namespace>
--- 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'), '<p>' . $lang->get('upload_err_banned_ext', array('ext' => htmlspecialchars($ext))) . '</p>');
--- 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']))
{
--- 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 '<div class="info-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_publicinfo_msg_save_success') . '</div>';
}
+
+ $lang_box = '<select name="lang_id">';
+ $q = $db->sql_query('SELECT lang_id, lang_name_native FROM ' . table_prefix . "language;");
+ if ( !$q )
+ $db->_die();
+
+ while ( $row = $db->fetchrow_num() )
+ {
+ list($lang_id, $lang_name) = $row;
+ $lang_name = htmlspecialchars($lang_name);
+ $selected = ( $lang->lang_id == $lang_id ) ? ' selected="selected"' : '';
+ $lang_box .= "<option value=\"$lang_id\"$selected>$lang_name</option>";
+ }
+
+ $lang_box .= '</select>';
+
echo '<form action="'.makeUrl($paths->fullpage).'" method="post">';
?>
<div class="tblholder">
@@ -564,6 +606,10 @@
<td class="row1" style="width: 50%;"><input type="text" name="real_name" value="<?php echo $session->real_name; ?>" size="30" /></td>
</tr>
<tr>
+ <td class="row2"><?php echo $lang->get('usercp_publicinfo_field_language') . '<br /><small>' . $lang->get('usercp_publicinfo_field_language_hint') . '</small>'; ?></td>
+ <td class="row1"><?php echo $lang_box; ?></td>
+ </tr>
+ <tr>
<td class="row2"><?php echo $lang->get('usercp_publicinfo_field_changetheme_title'); ?></td>
<td class="row1"><?php echo $lang->get('usercp_publicinfo_field_changetheme_hint'); ?> <a href="<?php echo makeUrlNS('Special', 'ChangeStyle/' . $paths->page); ?>" onclick="ajaxChangeStyle(); return false;"><?php echo $lang->get('usercp_publicinfo_field_changetheme'); ?></a></td>
</tr>
--- /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 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.0.3 (Dyrad)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ */
+
+function page_Admin_LangManager()
+{
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ global $lang;
+ if ( $session->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 '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+ echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+ 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 '<div class="info-box">' . $lang->get('acplm_msg_lang_install_success', array('lang_name' => htmlspecialchars($lang_data['name_eng']))) . '</div>';
+ }
+ }
+ 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 '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
+ echo '<h3>' . $lang->get('acplm_heading_install') . '</h3>';
+ echo '<div class="tblholder">
+ <table border="0" cellspacing="1" cellpadding="4">
+ <tr>
+ <th>' . $lang->get('acplm_col_lang_code') . '</th>
+ <th>' . $lang->get('acplm_col_lang_name') . '</th>
+ <th>' . $lang->get('acplm_col_lang_name_eng') . '</th>
+ <th></th>
+ </tr>';
+
+ $cls = 'row2';
+ foreach ( $lang_list as $lang_code => $lang_data )
+ {
+ $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+
+ echo '<tr>';
+
+ $lang_code = htmlspecialchars($lang_code);
+ $lang_data['name'] = htmlspecialchars($lang_data['name']);
+ $lang_data['name_eng'] = htmlspecialchars($lang_data['name_eng']);
+
+ echo "<td class=\"$cls\" style=\"text-align: center;\">$lang_code</td>";
+ echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name']}</td>";
+ echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name_eng']}</td>";
+ echo "<td class=\"$cls\" style=\"text-align: center;\"><button name=\"action\" value=\"install_language;iso639=$lang_code\">" . $lang->get('acplm_btn_install_language') . "</button></td>";
+
+ echo '</tr>';
+ }
+ echo ' </tr>
+ </table>
+ </div>';
+ echo '</form>';
+ }
+}
+