From 48a04205c8513fdc4f923fef556e3db8cc17d9f9 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Fri, 17 Aug 2012 09:02:18 -0400
Subject: [PATCH] Fix bug where domain name was converted to lower-case even with login_lc=false (#1488593)

---
 program/include/rcmail.php |   96 +++++++++++++++++++++++++++++++++++------------
 1 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 65c48fa..44a6016 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -131,6 +131,11 @@
   private $shutdown_functions = array();
   private $expunge_cache = false;
 
+  const ERROR_STORAGE          = -2;
+  const ERROR_INVALID_REQUEST  = 1;
+  const ERROR_INVALID_HOST     = 2;
+  const ERROR_COOKIES_DISABLED = 3;
+
 
   /**
    * This implements the 'singleton' design pattern
@@ -339,15 +344,20 @@
 
       $this->memcache = new Memcache;
       $this->mc_available = 0;
-      
-      // add alll configured hosts to pool
+
+      // add all configured hosts to pool
       $pconnect = $this->config->get('memcache_pconnect', true);
       foreach ($this->config->get('memcache_hosts', array()) as $host) {
-        list($host, $port) = explode(':', $host);
-        if (!$port) $port = 11211;
+        if (substr($host, 0, 7) != 'unix://') {
+          list($host, $port) = explode(':', $host);
+          if (!$port) $port = 11211;
+        }
+        else {
+          $port = 0;
+        }
         $this->mc_available += intval($this->memcache->addServer($host, $port, $pconnect, 1, 1, 15, false, array($this, 'memcache_failure')));
       }
-      
+
       // test connection and failover (will result in $this->mc_available == 0 on complete failure)
       $this->memcache->increment('__CONNECTIONTEST__', 1);  // NOP if key doesn't exist
 
@@ -357,14 +367,14 @@
 
     return $this->memcache;
   }
-  
+
   /**
    * Callback for memcache failure
    */
   public function memcache_failure($host, $port)
   {
     static $seen = array();
-    
+
     // only report once
     if (!$seen["$host:$port"]++) {
       $this->mc_available--;
@@ -814,12 +824,20 @@
    * @param string Mail storage (IMAP) user name
    * @param string Mail storage (IMAP) password
    * @param string Mail storage (IMAP) host
+   * @param bool   Enables cookie check
    *
    * @return boolean True on success, False on failure
    */
-  function login($username, $pass, $host=NULL)
+  function login($username, $pass, $host = null, $cookiecheck = false)
   {
+    $this->login_error = null;
+
     if (empty($username)) {
+      return false;
+    }
+
+    if ($cookiecheck && empty($_COOKIE)) {
+      $this->login_error = self::ERROR_COOKIES_DISABLED;
       return false;
     }
 
@@ -839,11 +857,18 @@
           break;
         }
       }
-      if (!$allowed)
-        return false;
+      if (!$allowed) {
+        $host = null;
       }
-    else if (!empty($config['default_host']) && $host != rcube_parse_host($config['default_host']))
+    }
+    else if (!empty($config['default_host']) && $host != rcube_parse_host($config['default_host'])) {
+      $host = null;
+    }
+
+    if (!$host) {
+      $this->login_error = self::ERROR_INVALID_HOST;
       return false;
+    }
 
     // parse $host URL
     $a_host = parse_url($host);
@@ -874,7 +899,14 @@
     // Convert username to lowercase. If storage backend
     // is case-insensitive we need to store always the same username (#1487113)
     if ($config['login_lc']) {
-      $username = mb_strtolower($username);
+      if ($config['login_lc'] == 2 || $config['login_lc'] === true) {
+        $username = mb_strtolower($username);
+      }
+      else if (strpos($username, '@')) {
+        // lowercase domain name
+        list($local, $domain) = explode('@', $username);
+        $username = $local . '@' . mb_strtolower($domain);
+      }
     }
 
     // try to resolve email address from virtuser table
@@ -884,17 +916,13 @@
 
     // Here we need IDNA ASCII
     // Only rcube_contacts class is using domain names in Unicode
-    $host = rcube_idn_to_ascii($host);
-    if (strpos($username, '@')) {
-      // lowercase domain name
-      list($local, $domain) = explode('@', $username);
-      $username = $local . '@' . mb_strtolower($domain);
-      $username = rcube_idn_to_ascii($username);
-    }
+    $host     = rcube_idn_to_ascii($host);
+    $username = rcube_idn_to_ascii($username);
 
     // user already registered -> overwrite username
-    if ($user = rcube_user::query($username, $host))
+    if ($user = rcube_user::query($username, $host)) {
       $username = $user->data['username'];
+    }
 
     if (!$this->storage)
       $this->storage_init();
@@ -983,6 +1011,23 @@
   }
 
 
+    /**
+     * Returns error code of last login operation
+     *
+     * @return int Error code
+     */
+    public function login_error()
+    {
+        if ($this->login_error) {
+            return $this->login_error;
+        }
+
+        if ($this->storage && $this->storage->get_error_code() < -1) {
+            return self::ERROR_STORAGE;
+        }
+    }
+
+
   /**
    * Set storage parameters.
    * This must be done AFTER connecting to the server!
@@ -1017,15 +1062,16 @@
 
     if (is_array($default_host)) {
       $post_host = get_input_value('_host', RCUBE_INPUT_POST);
+      $post_user = get_input_value('_user', RCUBE_INPUT_POST);
+
+      list($user, $domain) = explode('@', $post_user);
 
       // direct match in default_host array
-      if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) {
+      if ($default_host[$post_host] || in_array($post_host, $default_host)) {
         $host = $post_host;
       }
-
       // try to select host by mail domain
-      list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST));
-      if (!empty($domain)) {
+      else if (!empty($domain)) {
         foreach ($default_host as $storage_host => $mail_domains) {
           if (is_array($mail_domains) && in_array_nocase($domain, $mail_domains)) {
             $host = $storage_host;
@@ -1167,7 +1213,7 @@
         $this->texts = array_merge($this->texts, $messages);
 
       // include user language files
-      if ($lang != 'en' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
+      if ($lang != 'en' && $lang != 'en_US' && is_dir(INSTALL_PATH . 'program/localization/' . $lang)) {
         include_once(INSTALL_PATH . 'program/localization/' . $lang . '/labels.inc');
         include_once(INSTALL_PATH . 'program/localization/' . $lang . '/messages.inc');
 

--
Gitblit v1.9.1