--- a/includes/common.php Sat Nov 17 22:25:37 2007 -0500
+++ b/includes/common.php Sun Nov 18 20:37:08 2007 -0500
@@ -273,6 +273,12 @@
@call_user_func('page_'.$p[1].'_'.$p[0].'_preloader');
}
+ // One quick security check...
+ if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) )
+ {
+ die('SECURITY: spoofed IP address');
+ }
+
$session->start();
$paths->init();
--- a/includes/dbal.php Sat Nov 17 22:25:37 2007 -0500
+++ b/includes/dbal.php Sun Nov 18 20:37:08 2007 -0500
@@ -121,13 +121,25 @@
return $internal_text;
}
- function connect() {
+ function connect()
+ {
$this->enable_errorhandler();
+
dc_here('dbal: trying to connect....');
- @include(ENANO_ROOT.'/config.php');
- if(isset($crypto_key))
+
+ if ( defined('IN_ENANO_INSTALL') )
+ {
+ @include(ENANO_ROOT.'/config.new.php');
+ }
+ else
+ {
+ @include(ENANO_ROOT.'/config.php');
+ }
+
+ if ( isset($crypto_key) )
unset($crypto_key); // Get this sucker out of memory fast
- if(!defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') )
+
+ if ( !defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') )
{
dc_here('dbal: oops, looks like Enano isn\'t set up. Constants ENANO_INSTALLED, MIDGET_INSTALLED, and IN_ENANO_INSTALL are all undefined.');
header('Location: install.php');
@@ -136,46 +148,74 @@
$this->_conn = @mysql_connect($dbhost, $dbuser, $dbpasswd);
unset($dbuser);
unset($dbpasswd); // Security
- if(!$this->_conn) { dc_here('dbal: uhoh!<br />'.mysql_error()); grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to MySQL.<br />'.mysql_error().'</p>'); }
+
+ if ( !$this->_conn )
+ {
+ dc_here('dbal: uhoh!<br />'.mysql_error());
+ grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to MySQL.<br />'.mysql_error().'</p>');
+ }
+
+ // Reset some variables
$this->query_backtrace = '';
$this->num_queries = 0;
+
dc_here('dbal: we\'re in, selecting database...');
$q = $this->sql_query('USE `'.$dbname.'`;');
- if(!$q) $this->_die('The database could not be selected.');
+
+ if ( !$q )
+ $this->_die('The database could not be selected.');
+
+ // We're in!
dc_here('dbal: connected to MySQL');
+
$this->disable_errorhandler();
+ return true;
}
- function sql_query($q) {
+ function sql_query($q)
+ {
$this->enable_errorhandler();
$this->num_queries++;
- $this->query_backtrace .= $q."\n";
+ $this->query_backtrace .= $q . "\n";
$this->latest_query = $q;
dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>');
- if(!$this->_conn) $this->_die('A database connection has not yet been established.');
- if(!$this->check_query($q))
+ // First make sure we have a connection
+ if ( !$this->_conn )
+ {
+ $this->_die('A database connection has not yet been established.');
+ }
+ // Does this query look malicious?
+ if ( !$this->check_query($q) )
{
$this->report_query($q);
grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>');
}
+
$r = mysql_query($q, $this->_conn);
$this->latest_result = $r;
$this->disable_errorhandler();
return $r;
}
- function sql_unbuffered_query($q) {
+ function sql_unbuffered_query($q)
+ {
$this->enable_errorhandler();
$this->num_queries++;
$this->query_backtrace .= '(UNBUFFERED) ' . $q."\n";
$this->latest_query = $q;
dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>');
- if(!$this->_conn) $this->_die('A database connection has not yet been established.');
- if(!$this->check_query($q))
+ // First make sure we have a connection
+ if ( !$this->_conn )
+ {
+ $this->_die('A database connection has not yet been established.');
+ }
+ // Does this query look malicious?
+ if ( !$this->check_query($q) )
{
$this->report_query($q);
grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>');
}
+
$r = mysql_unbuffered_query($q, $this->_conn);
$this->latest_result = $r;
$this->disable_errorhandler();
--- a/includes/functions.php Sat Nov 17 22:25:37 2007 -0500
+++ b/includes/functions.php Sun Nov 18 20:37:08 2007 -0500
@@ -2735,7 +2735,7 @@
{
$array[$i] = decode_unicode_url($val);
}
- else
+ else if ( is_array($val) )
{
$array[$i] = decode_unicode_array($val);
}
@@ -2999,6 +2999,72 @@
return $ips;
}
+/**
+ * Parses a valid IP address range into a regular expression.
+ * @param string IP range string
+ * @return string
+ */
+
+function parse_ip_range_regex($range)
+{
+ // Regular expression to test the range string for validity
+ $regex = '/^(([0-9]+(-[0-9]+)?)(\|([0-9]+(-[0-9]+)?))*)\.'
+ . '(([0-9]+(-[0-9]+)?)(\|([0-9]+(-[0-9]+)?))*)\.'
+ . '(([0-9]+(-[0-9]+)?)(\|([0-9]+(-[0-9]+)?))*)\.'
+ . '(([0-9]+(-[0-9]+)?)(\|([0-9]+(-[0-9]+)?))*)$/';
+ if ( !preg_match($regex, $range) )
+ {
+ return false;
+ }
+ $octets = array(0 => array(), 1 => array(), 2 => array(), 3 => array());
+ list($octets[0], $octets[1], $octets[2], $octets[3]) = explode('.', $range);
+ $return = '^';
+ foreach ( $octets as $octet )
+ {
+ // alternatives array
+ $alts = array();
+ if ( strpos($octet, '|') )
+ {
+ $particles = explode('|', $octet);
+ }
+ else
+ {
+ $particles = array($octet);
+ }
+ foreach ( $particles as $atom )
+ {
+ // each $atom will be either
+ if ( strval(intval($atom)) == $atom )
+ {
+ $alts[] = $atom;
+ continue;
+ }
+ else
+ {
+ // it's a range - parse it out
+ $alt2 = int_range($atom);
+ if ( !$alt2 )
+ return false;
+ foreach ( $alt2 as $neutrino )
+ $alts[] = $neutrino;
+ }
+ }
+ $alts = array_unique($alts);
+ $alts = '|' . implode('|', $alts) . '|';
+ // we can further optimize/compress this by weaseling our way into using some character ranges
+ for ( $i = 1; $i <= 25; $i++ )
+ {
+ $alts = str_replace("|{$i}0|{$i}1|{$i}2|{$i}3|{$i}4|{$i}5|{$i}6|{$i}7|{$i}8|{$i}9|", "|{$i}[0-9]|", $alts);
+ }
+ $alts = str_replace("|1|2|3|4|5|6|7|8|9|", "|[1-9]|", $alts);
+ $alts = '(' . substr($alts, 1, -1) . ')';
+ $return .= $alts . '\.';
+ }
+ $return = substr($return, 0, -2);
+ $return .= '$';
+ return $return;
+}
+
function password_score_len($password)
{
if ( !is_string($password) )
--- a/includes/pageutils.php Sat Nov 17 22:25:37 2007 -0500
+++ b/includes/pageutils.php Sun Nov 18 20:37:08 2007 -0500
@@ -24,6 +24,7 @@
function checkusername($name)
{
global $db, $session, $paths, $template, $plugins; // Common objects
+ $name = str_replace('_', ' ', $name);
$q = $db->sql_query('SELECT username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape(rawurldecode($name)) . '\'');
if ( !$q )
{
--- a/includes/sessions.php Sat Nov 17 22:25:37 2007 -0500
+++ b/includes/sessions.php Sun Nov 18 20:37:08 2007 -0500
@@ -151,7 +151,7 @@
*/
//var $valid_username = '([A-Za-z0-9 \!\@\(\)-]+)';
- var $valid_username = '([^<>_&\?\'"%\n\r\t\a\/]+)';
+ var $valid_username = '([^<>&\?\'"%\n\r\t\a\/]+)';
/**
* What we're allowed to do as far as permissions go. This changes based on the value of the "auth" URI param.
@@ -260,7 +260,16 @@
function __construct()
{
global $db, $session, $paths, $template, $plugins; // Common objects
- include(ENANO_ROOT.'/config.php');
+
+ if ( defined('IN_ENANO_INSTALL') )
+ {
+ @include(ENANO_ROOT.'/config.new.php');
+ }
+ else
+ {
+ @include(ENANO_ROOT.'/config.php');
+ }
+
unset($dbhost, $dbname, $dbuser, $dbpasswd);
if(isset($crypto_key))
{
@@ -563,7 +572,7 @@
* @return string 'success' on success, or error string on failure
*/
- function login_with_crypto($username, $aes_data, $aes_key, $challenge, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false)
+ function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false)
{
global $db, $session, $paths, $template, $plugins; // Common objects
@@ -613,7 +622,7 @@
// Fetch our decryption key
- $aes_key = $this->fetch_public_key($aes_key);
+ $aes_key = $this->fetch_public_key($aes_key_id);
if(!$aes_key)
return array(
'success' => false,
@@ -636,6 +645,7 @@
$success = false;
// Escaped username
+ $username = str_replace('_', ' ', $username);
$db_username_lower = $this->prepare_text(strtolower($username));
$db_username = $this->prepare_text($username);
@@ -802,6 +812,10 @@
$pass_hashed = ( $already_md5ed ) ? $password : md5($password);
+ // Replace underscores with spaces in username
+ // (Added in 1.0.2)
+ $username = str_replace('_', ' ', $username);
+
// Perhaps we're upgrading Enano?
if($this->compat)
{
@@ -1025,7 +1039,7 @@
/**
* Registers a session key in the database. This function *ASSUMES* that the username and password have already been validated!
- * Basically the session key is a base64-encoded cookie (encrypted with the site's private key) that says "u=[username];p=[sha1 of password]"
+ * Basically the session key is a hex-encoded cookie (encrypted with the site's private key) that says "u=[username];p=[sha1 of password];s=[unique key id]"
* @param int $user_id
* @param string $username
* @param string $password
@@ -1084,7 +1098,7 @@
}
/**
- * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this.
+ * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this except in the upgrade script under very controlled circumstances.
* @see sessionManager::register_session()
* @access private
*/
@@ -1536,59 +1550,79 @@
function check_banlist()
{
global $db, $session, $paths, $template, $plugins; // Common objects
- if($this->compat)
- $q = $this->sql('SELECT ban_id,ban_type,ban_value,is_regex FROM '.table_prefix.'banlist ORDER BY ban_type;');
- else
- $q = $this->sql('SELECT ban_id,ban_type,ban_value,is_regex,reason FROM '.table_prefix.'banlist ORDER BY ban_type;');
- if(!$q) $db->_die('The banlist data could not be selected.');
- $banned = false;
- while($row = $db->fetchrow())
+ $col_reason = ( $this->compat ) ? '"No reason entered (session manager is in compatibility mode)" AS reason' : 'reason';
+ $is_banned = false;
+ if ( $this->user_logged_in )
{
- if($this->compat)
- $row['reason'] = 'None available - session manager is in compatibility mode';
- switch($row['ban_type'])
+ // check by IP, email, and username
+ $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n"
+ . " ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR \n"
+ . " ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n"
+ . " ( ban_type = " . BAN_USER . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n"
+ . " ( ban_type = " . BAN_USER . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n"
+ . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n"
+ . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n"
+ . " ORDER BY ban_type ASC;";
+ $q = $this->sql($sql);
+ if ( $db->numrows() > 0 )
{
- case BAN_IP:
- if(intval($row['is_regex'])==1) {
- if(preg_match('#'.$row['ban_value'].'#i', $_SERVER['REMOTE_ADDR']))
+ while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
+ {
+ if ( $ban_type == BAN_IP && $row['is_regex'] != 1 )
{
+ // check range
+ $regexp = parse_ip_range_regex($ban_value);
+ if ( !$regexp )
+ {
+ continue;
+ }
+ if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) )
+ {
+ $banned = true;
+ }
+ }
+ else
+ {
+ // User is banned
$banned = true;
- $reason = $row['reason'];
}
}
- else {
- if($row['ban_value']==$_SERVER['REMOTE_ADDR']) { $banned = true; $reason = $row['reason']; }
- }
- break;
- case BAN_USER:
- if(intval($row['is_regex'])==1) {
- if(preg_match('#'.$row['ban_value'].'#i', $this->username))
+ }
+ $db->free_result();
+ }
+ else
+ {
+ // check by IP only
+ $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE
+ ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR
+ ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value )
+ ORDER BY ban_type ASC;";
+ $q = $this->sql($sql);
+ if ( $db->numrows() > 0 )
+ {
+ while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
+ {
+ if ( $ban_type == BAN_IP && $row['is_regex'] != 1 )
{
+ // check range
+ $regexp = parse_ip_range_regex($ban_value);
+ if ( !$regexp )
+ continue;
+ if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) )
+ {
+ $banned = true;
+ }
+ }
+ else
+ {
+ // User is banned
$banned = true;
- $reason = $row['reason'];
}
}
- else {
- if($row['ban_value']==$this->username) { $banned = true; $reason = $row['reason']; }
- }
- break;
- case BAN_EMAIL:
- if(intval($row['is_regex'])==1) {
- if(preg_match('#'.$row['ban_value'].'#i', $this->email))
- {
- $banned = true;
- $reason = $row['reason'];
- }
- }
- else {
- if($row['ban_value']==$this->email) { $banned = true; $reason = $row['reason']; }
- }
- break;
- default:
- die('Ban error: rule "'.$row['ban_value'].'" has an invalid type ('.$row['ban_type'].')');
}
+ $db->free_result();
}
- if($banned && $paths->get_pageid_from_url() != $paths->nslist['Special'].'CSS')
+ if ( $banned && $paths->get_pageid_from_url() != $paths->nslist['Special'].'CSS' )
{
// This guy is banned - kill the session, kill the database connection, bail out, and be pretty about it
die_semicritical('Ban notice', '<div class="error-box">You have been banned from this website. Please contact the site administrator for more information.<br /><br />Reason:<br />'.$reason.'</div>');
@@ -1600,11 +1634,11 @@
/**
* Registers a user. This does not perform any type of login.
- * @param string $username
- * @param string $password This should be unencrypted.
- * @param string $email
- * @param string $real_name Optional, defaults to ''.
- * @param bool $coppa Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice.
+ * @param string New user's username
+ * @param string This should be unencrypted.
+ * @param string E-mail address.
+ * @param string Optional, defaults to ''.
+ * @param bool Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice.
*/
function create_user($username, $password, $email, $real_name = '', $coppa = false)
@@ -1615,6 +1649,7 @@
$aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
if(!preg_match('#^'.$this->valid_username.'$#', $username)) return 'The username you chose contains invalid characters.';
+ $username = str_replace('_', ' ', $username);
$user_orig = $username;
$username = $this->prepare_text($username);
$email = $this->prepare_text($email);
--- a/install.php Sat Nov 17 22:25:37 2007 -0500
+++ b/install.php Sun Nov 18 20:37:08 2007 -0500
@@ -105,7 +105,7 @@
}
if ( !$resumed && $allow_skip )
{
- echo_stage_success($stage_id, "[dbg: skipped] $stage_name");
+ echo_stage_success($stage_id, $stage_name);
return false;
}
if ( !function_exists($function) )
@@ -142,7 +142,6 @@
$neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
echo '<tr><td style="width: 500px; background-color: #' . "{$neutral_color}{$neutral_color}FF{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Done" src="images/good.gif" /></td></tr>' . "\n";
ob_flush();
- flush();
}
function echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack)
@@ -153,12 +152,12 @@
$neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
echo '<tr><td style="width: 500px; background-color: #' . "FF{$neutral_color}{$neutral_color}{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Failed" src="images/bad.gif" /></td></tr>' . "\n";
ob_flush();
- flush();
close_install_table();
$post_data = '';
$mysql_error = mysql_error();
foreach ( $_POST as $key => $value )
{
+ // FIXME: These should really also be sanitized for double quotes
$value = htmlspecialchars($value);
$key = htmlspecialchars($key);
$post_data .= " <input type=\"hidden\" name=\"$key\" value=\"$value\" />\n";
@@ -388,11 +387,15 @@
$cacheonoff = is_writable(ENANO_ROOT.'/cache/') ? '1' : '0';
+ $admin_user = $_POST['admin_user'];
+ $admin_user = str_replace('_', ' ', $admin_user);
+ $admin_user = mysql_real_escape_string($admin_user);
+
$schema = file_get_contents('schema.sql');
$schema = str_replace('{{SITE_NAME}}', mysql_real_escape_string($_POST['sitename'] ), $schema);
$schema = str_replace('{{SITE_DESC}}', mysql_real_escape_string($_POST['sitedesc'] ), $schema);
$schema = str_replace('{{COPYRIGHT}}', mysql_real_escape_string($_POST['copyright'] ), $schema);
- $schema = str_replace('{{ADMIN_USER}}', mysql_real_escape_string($_POST['admin_user'] ), $schema);
+ $schema = str_replace('{{ADMIN_USER}}', $admin_user , $schema);
$schema = str_replace('{{ADMIN_PASS}}', mysql_real_escape_string($admin_pass ), $schema);
$schema = str_replace('{{ADMIN_EMAIL}}', mysql_real_escape_string($_POST['admin_email']), $schema);
$schema = str_replace('{{ENABLE_CACHE}}', mysql_real_escape_string($cacheonoff ), $schema);
@@ -462,6 +465,7 @@
$key = $aes->hextostring($key);
$admin_pass = $aes->encrypt($admin_pass, $key, ENC_HEX);
$admin_user = mysql_real_escape_string($_POST['admin_user']);
+ $admin_user = str_replace('_', ' ', $admin_user);
$q = @mysql_query("UPDATE {$_POST['table_prefix']}users SET password='$admin_pass' WHERE username='$admin_user';");
if ( !$q )
@@ -1826,52 +1830,77 @@
err('Hacking attempt was detected in table_prefix.');
start_install_table();
- // The stages connect, decrypt, genkey, and parse are preprocessing and don't do any actual data modification.
- // Thus, they need to be run on each retry, e.g. never skipped.
- run_installer_stage('connect', $lang->get('install_stg_connect_title'), 'stg_mysql_connect', $lang->get('install_stg_connect_body'), false);
- if ( isset($_POST['drop_tables']) )
+
+ // Are we just trying to auto-rename the config files? If so, skip everything else
+ if ( !isset($_GET['stage']) || ( isset($_GET['stage']) && $_GET['stage'] != 'renameconfig' ) )
{
- // Are we supposed to drop any existing tables? If so, do it now
- run_installer_stage('drop', $lang->get('install_stg_drop_title'), 'stg_drop_tables', 'This step never returns failure');
+
+ // The stages connect, decrypt, genkey, and parse are preprocessing and don't do any actual data modification.
+ // Thus, they need to be run on each retry, e.g. never skipped.
+ run_installer_stage('connect', $lang->get('install_stg_connect_title'), 'stg_mysql_connect', $lang->get('install_stg_connect_body'), false);
+ if ( isset($_POST['drop_tables']) )
+ {
+ // Are we supposed to drop any existing tables? If so, do it now
+ run_installer_stage('drop', $lang->get('install_stg_drop_title'), 'stg_drop_tables', 'This step never returns failure');
+ }
+ run_installer_stage('decrypt', $lang->get('install_stg_decrypt_title'), 'stg_decrypt_admin_pass', $lang->get('install_stg_decrypt_body'), false);
+ run_installer_stage('genkey', $lang->get('install_stg_genkey_title', array( 'aes_bits' => AES_BITS )), 'stg_generate_aes_key', $lang->get('install_stg_genkey_body'), false);
+ run_installer_stage('parse', $lang->get('install_stg_parse_title'), 'stg_parse_schema', $lang->get('install_stg_parse_body'), false);
+ run_installer_stage('sql', $lang->get('install_stg_sql_title'), 'stg_install', $lang->get('install_stg_sql_body'), false);
+ run_installer_stage('writeconfig', $lang->get('install_stg_writeconfig_title'), 'stg_write_config', $lang->get('install_stg_writeconfig_body'));
+
+ // Mainstream installation complete - Enano should be usable now
+ // The stage of starting the API is special because it has to be called out of function context.
+ // To alleviate this, we have two functions, one that returns success and one that returns failure
+ // If the Enano API load is successful, the success function is called to report the action to the user
+ // If unsuccessful, the failure report is sent
+
+ $template_bak = $template;
+
+ $_GET['title'] = 'Main_Page';
+ require('includes/common.php');
+
+ if ( is_object($db) && is_object($session) )
+ {
+ run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_start_api_success', '...', false);
+ }
+ else
+ {
+ run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_start_api_failure', $lang->get('install_stg_startapi_body'), false);
+ }
+
+ // We need to be logged in (with admin rights) before logs can be flushed
+ $admin_password = stg_decrypt_admin_pass(true);
+ $session->login_without_crypto($_POST['admin_user'], $admin_password, false);
+
+ // Now that login cookies are set, initialize the session manager and ACLs
+ $session->start();
+ $paths->init();
+
+ run_installer_stage('importlang', $lang->get('install_stg_importlang_title'), 'stg_import_language', $lang->get('install_stg_importlang_body'));
+ run_installer_stage('initlogs', $lang->get('install_stg_initlogs_title'), 'stg_init_logs', $lang->get('install_stg_initlogs_body'));
+
+ /*
+ * HACKERS:
+ * If you're making a custom distribution of Enano, put all your custom plugin-related code here.
+ * You have access to the full Enano API as well as being logged in with complete admin rights.
+ * Don't do anything horrendously fancy here, unless you add a new stage (or more than one) and
+ * have the progress printed out properly.
+ */
+
+ } // check for stage == renameconfig
+ else
+ {
+ // If we did skip the main installer routine, set $template_bak to make the reversal later work properly
+ $template_bak = $template;
}
- run_installer_stage('decrypt', $lang->get('install_stg_decrypt_title'), 'stg_decrypt_admin_pass', $lang->get('install_stg_decrypt_body'), false);
- run_installer_stage('genkey', $lang->get('install_stg_genkey_title', array( 'aes_bits' => AES_BITS )), 'stg_generate_aes_key', $lang->get('install_stg_genkey_body'), false);
- run_installer_stage('parse', $lang->get('install_stg_parse_title'), 'stg_parse_schema', $lang->get('install_stg_parse_body'), false);
- run_installer_stage('sql', $lang->get('install_stg_sql_title'), 'stg_install', $lang->get('install_stg_sql_body'), false);
- run_installer_stage('writeconfig', $lang->get('install_stg_writeconfig_title'), 'stg_write_config', $lang->get('install_stg_writeconfig_body'));
+
+ // Final step is to rename the config file
+ // In early revisions of 1.0.2, this step was performed prior to the initialization of the Enano API. It was decided to move
+ // this stage to the end because it will fail more often than any other stage, thus making alternate routes imperative. If this
+ // stage fails, then no big deal, we'll just have the user rename the files manually and then let them see the pretty success message.
run_installer_stage('renameconfig', $lang->get('install_stg_rename_title'), 'stg_rename_config', $lang->get('install_stg_rename_body'));
- // Mainstream installation complete - Enano should be usable now
- // The stage of starting the API is special because it has to be called out of function context.
- // To alleviate this, we have two functions, one that returns success and one that returns failure
- // If the Enano API init is successful, the success function is called to report the action to the user
- // If unsuccessful, the failure report is sent
-
- $template_bak = $template;
-
- $_GET['title'] = 'Main_Page';
- require('includes/common.php');
-
- if ( is_object($db) && is_object($session) )
- {
- run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_start_api_success', '...', false);
- }
- else
- {
- run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_start_api_failure', $lang->get('install_stg_startapi_body'), false);
- }
-
- // We need to be logged in (with admin rights) before logs can be flushed
- $admin_password = stg_decrypt_admin_pass(true);
- $session->login_without_crypto($_POST['admin_user'], $admin_password, false);
-
- // Now that login cookies are set, initialize the session manager and ACLs
- $session->start();
- $paths->init();
-
- run_installer_stage('importlang', $lang->get('install_stg_importlang_title'), 'stg_import_language', $lang->get('install_stg_importlang_body'));
-
- run_installer_stage('initlogs', $lang->get('install_stg_initlogs_title'), 'stg_init_logs', $lang->get('install_stg_initlogs_body'));
close_install_table();
unset($template);
--- a/plugins/SpecialAdmin.php Sat Nov 17 22:25:37 2007 -0500
+++ b/plugins/SpecialAdmin.php Sun Nov 18 20:37:08 2007 -0500
@@ -2228,17 +2228,14 @@
}
if ( $type == BAN_IP )
{
- // parse a range of addresses
- $range = parse_ip_range($entry);
- if ( !$range )
+ if ( !isset($_POST['regex']) )
{
- $error = true;
- echo '<div class="error-box">Malformed IP address expression.</div>';
- break;
+ // as of 1.0.2 parsing is done at runtime
+ $entries[] = $entry;
}
- foreach ($range as $ip)
+ else
{
- $entries[] = $ip;
+ $entries[] = $entry;
}
}
else
@@ -2290,7 +2287,7 @@
?>
Type: <select name="type"><option value="<?php echo BAN_IP; ?>">IP address</option><option value="<?php echo BAN_USER; ?>">Username</option><option value="<?php echo BAN_EMAIL; ?>">E-mail address</option></select><br />
Rule: <input type="text" name="value" size="30" /><br />
- <small>You can ban multiple IP addresses, users, or e-mail addresses by separating entries with a single comma (User1,User2). Do not put a space after the comma. For IP addresses, you may specify ranges like 172|192.168.4-30|90-167.1-90, which will turn into 172 and 192 . 168 . 4-30 and 90-167 . 1 - 90, which matches 18,899 IP addresses. Don't specify large ranges (like the example one here) at once or you risk temporarily (~60sec) overloading the server.</small><br />
+ <small>You can ban multiple IP addresses, users, or e-mail addresses by separating entries with a single comma (User1,User2). Do not put a space after the comma. For IP addresses, you may specify ranges like 172|192.168.4-30|90-167.1-90, which will turn into 172 and 192 . 168 . 4-30 and 90-167 . 1 - 90, which matches 18,899 IP addresses.</small><br />
Reason to show to the banned user: <textarea name="reason" rows="7" cols="40"></textarea><br />
<input type="checkbox" name="regex" id="regex" /> <label for="regex">This rule is a regular expression</label> (advanced users only)<br />
<input type="submit" style="font-weight: bold;" name="create" value="Create new ban rule" />
--- a/plugins/SpecialUserFuncs.php Sat Nov 17 22:25:37 2007 -0500
+++ b/plugins/SpecialUserFuncs.php Sun Nov 18 20:37:08 2007 -0500
@@ -820,7 +820,7 @@
if(!namegood && ( field.name == 'username' || field.name == '_nil' ) )
{
//if(frm.username.value.match(/^([A-z0-9 \!@\-\(\)]+){2,}$/ig))
- var regex = new RegExp('^([^<>_&\?]+){2,}$', 'ig');
+ var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig');
if ( frm.username.value.match(regex) )
{
document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
@@ -885,10 +885,8 @@
if(!namegood)
{
- <?php
- // sorry for this ugly hack but jedit gets f***ed otherwise
- echo 'if(frm.username.value.match(/^([A-z0-9 \.:\!@\#\*]+){2,}$/ig))';
- ?>
+ var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig');
+ if ( frm.username.value.match(regex) )
{
document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
document.getElementById('e_username').innerHTML = ' ';