includes/sessions.php
changeset 271 f088805540ae
parent 266 917dcc6c4ceb
parent 270 5bcdee999015
child 304 e2cb5f1432c8
--- 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);