Aleksander Machniak
2013-10-17 197203727417a03d87053a47e5aa5175a76e3e0b
program/include/rcmail.php
@@ -337,20 +337,41 @@
      }
      $this->memcache = new Memcache;
      $mc_available = 0;
      $this->mc_available = 0;
      // add alll 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;
        // add server and attempt to connect if not already done yet
        if ($this->memcache->addServer($host, $port) && !$mc_available)
          $mc_available += intval($this->memcache->connect($host, $port));
        $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
      if (!$mc_available)
      if (!$this->mc_available)
        $this->memcache = false;
    }
    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--;
      raise_error(array('code' => 604, 'type' => 'db',
        'line' => __LINE__, 'file' => __FILE__,
        'message' => "Memcache failure on host $host:$port"),
        true, false);
    }
  }
@@ -431,9 +452,12 @@
        true, true);
    }
    // set configured sort order
    if ($sort_col = $this->config->get('addressbook_sort_col'))
        $contacts->set_sort_order($sort_col);
    // add to the 'books' array for shutdown function
    if (!isset($this->address_books[$id]))
      $this->address_books[$id] = $contacts;
    $this->address_books[$id] = $contacts;
    return $contacts;
  }
@@ -462,7 +486,8 @@
        'name'     => rcube_label('personaladrbook'),
        'groups'   => $this->address_books['0']->groups,
        'readonly' => $this->address_books['0']->readonly,
        'autocomplete' => in_array('sql', $autocomplete)
        'autocomplete' => in_array('sql', $autocomplete),
        'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
      );
    }
@@ -572,7 +597,6 @@
      return;
    $this->imap = new rcube_imap();
    $this->imap->debug_level = $this->config->get('debug_level');
    $this->imap->skip_deleted = $this->config->get('skip_deleted');
    // enable caching of imap data
@@ -594,7 +618,7 @@
    // Setting root and delimiter before establishing the connection
    // can save time detecting them using NAMESPACE and LIST
    $options = array(
      'auth_method' => $this->config->get('imap_auth_type', 'check'),
      'auth_type'   => $this->config->get('imap_auth_type', 'check'),
      'auth_cid'    => $this->config->get('imap_auth_cid'),
      'auth_pw'     => $this->config->get('imap_auth_pw'),
      'debug'       => (bool) $this->config->get('imap_debug', 0),
@@ -657,18 +681,21 @@
    if (session_id())
      return;
    $sess_name   = $this->config->get('session_name');
    $sess_domain = $this->config->get('session_domain');
    $lifetime    = $this->config->get('session_lifetime', 0) * 60;
    // set session domain
    if ($domain = $this->config->get('session_domain')) {
      ini_set('session.cookie_domain', $domain);
    if ($sess_domain) {
      ini_set('session.cookie_domain', $sess_domain);
    }
    // set session garbage collecting time according to session_lifetime
    $lifetime = $this->config->get('session_lifetime', 0) * 60;
    if ($lifetime) {
      ini_set('session.gc_maxlifetime', $lifetime * 2);
    }
    ini_set('session.cookie_secure', rcube_https_check());
    ini_set('session.name', 'roundcube_sessid');
    ini_set('session.name', $sess_name ? $sess_name : 'roundcube_sessid');
    ini_set('session.use_cookies', 1);
    ini_set('session.use_only_cookies', 1);
    ini_set('session.serialize_handler', 'php');
@@ -677,8 +704,7 @@
    $this->session = new rcube_session($this->get_dbh(), $this->config);
    $this->session->register_gc_handler('rcmail_temp_gc');
    if ($this->config->get('enable_caching'))
      $this->session->register_gc_handler('rcmail_cache_gc');
    $this->session->register_gc_handler('rcmail_cache_gc');
    // start PHP session (if not in CLI mode)
    if ($_SERVER['REMOTE_ADDR'])
@@ -708,7 +734,7 @@
      $keep_alive = max(60, $keep_alive);
      $this->session->set_keep_alive($keep_alive);
    }
    $this->session->set_secret($this->config->get('des_key') . $_SERVER['HTTP_USER_AGENT']);
    $this->session->set_ip_check($this->config->get('ip_check'));
  }
@@ -818,16 +844,8 @@
    if (!$imap_login)
      return false;
    $this->set_imap_prop();
    // user already registered -> update user's record
    if (is_object($user)) {
      // fix some old settings according to namespace prefix
      $this->fix_namespace_settings($user);
      // create default folders on first login
      if (!$user->data['last_login'] && $config['create_default_folders'])
        $this->imap->create_default_folders();
      // update last login timestamp
      $user->touch();
    }
@@ -835,9 +853,6 @@
    else if ($config['auto_create_user']) {
      if ($created = rcube_user::create($username, $host)) {
        $user = $created;
        // create default folders on first login
        if ($config['create_default_folders'])
          $this->imap->create_default_folders();
      }
      else {
        raise_error(array(
@@ -857,8 +872,18 @@
    // login succeeded
    if (is_object($user) && $user->ID) {
      // Configure environment
      $this->set_user($user);
      $this->set_imap_prop();
      $this->session_configure();
      // fix some old settings according to namespace prefix
      $this->fix_namespace_settings($user);
      // create default folders on first login
      if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) {
        $this->imap->create_default_folders();
      }
      // set session vars
      $_SESSION['user_id']   = $user->ID;
@@ -868,9 +893,11 @@
      $_SESSION['imap_ssl']  = $imap_ssl;
      $_SESSION['password']  = $this->encrypt($pass);
      $_SESSION['login_time'] = mktime();
      if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_')
        $_SESSION['timezone'] = floatval($_REQUEST['_timezone']);
      if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_')
        $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']);
      // force reloading complete list of subscribed mailboxes
      $this->imap->clear_cache('mailboxes', true);
@@ -949,7 +976,9 @@
  /**
   * Get localized text in the desired language
   *
   * @param mixed Named parameters array or label name
   * @param mixed   $attrib  Named parameters array or label name
   * @param string  $domain  Label domain (plugin) name
   *
   * @return string Localized text
   */
  public function gettext($attrib, $domain=null)
@@ -964,7 +993,7 @@
    $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
    $name = $attrib['name'] ? $attrib['name'] : '';
    // attrib contain text values: use them from now
    if (($setval = $attrib[strtolower($_SESSION['language'])]) || ($setval = $attrib['en_us']))
        $this->texts[$name] = $setval;
@@ -1020,19 +1049,40 @@
  /**
   * Check if the given text lable exists
   * Check if the given text label exists
   *
   * @param string Label name
   * @param string  $name       Label name
   * @param string  $domain     Label domain (plugin) name or '*' for all domains
   * @param string  $ref_domain Sets domain name if label is found
   *
   * @return boolean True if text exists (either in the current language or in en_US)
   */
  public function text_exists($name, $domain=null)
  public function text_exists($name, $domain = null, &$ref_domain = null)
  {
    // load localization files if not done yet
    if (empty($this->texts))
      $this->load_language();
    // check for text with domain first
    return ($domain && isset($this->texts[$domain.'.'.$name])) || isset($this->texts[$name]);
    if (isset($this->texts[$name])) {
        $ref_domain = '';
        return true;
    }
    // any of loaded domains (plugins)
    if ($domain == '*') {
      foreach ($this->plugins->loaded_plugins() as $domain)
        if (isset($this->texts[$domain.'.'.$name])) {
          $ref_domain = $domain;
          return true;
        }
    }
    // specified domain
    else if ($domain) {
      $ref_domain = $domain;
      return isset($this->texts[$domain.'.'.$name]);
    }
    return false;
  }
  /**
@@ -1180,7 +1230,6 @@
    // before closing the database connection, write session data
    if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
      $this->session->cleanup();
      session_write_close();
    }
@@ -1222,7 +1271,7 @@
  {
    $sess_id = $_COOKIE[ini_get('session.name')];
    if (!$sess_id) $sess_id = session_id();
    $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->task . $this->config->get('des_key') . $sess_id)));
    $plugin = $this->plugins->exec_hook('request_token', array('value' => md5('RT' . $this->user->ID . $this->config->get('des_key') . $sess_id)));
    return $plugin['value'];
  }
@@ -1516,7 +1565,7 @@
    // use strtr behaviour of going through source string once
    $cmd = strtr($cmd, $replacements);
    return (string)shell_exec($cmd);
  }
@@ -1552,7 +1601,7 @@
      }
    }
  }
  /**
   * Returns current action filename
   *
@@ -1582,8 +1631,8 @@
    if (!$prefix_len)
      return;
    $prefs = $user->get_prefs();
    if (empty($prefs) || $prefs['namespace_fixed'])
    $prefs = $this->config->all();
    if (!empty($prefs['namespace_fixed']))
      return;
    // Build namespace prefix regexp