From 677e1f26fe47cc0c3e0819cb99a9024af49a619c Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Tue, 18 May 2010 06:25:29 -0400
Subject: [PATCH] - Some files from /bin + spellchecking actions moved to the new 'utils' task

---
 program/include/rcmail.php |  341 +++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 237 insertions(+), 104 deletions(-)

diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index 3d26065..864ee8d 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -5,7 +5,7 @@
  | program/include/rcmail.php                                            |
  |                                                                       |
  | This file is part of the RoundCube Webmail client                     |
- | Copyright (C) 2008-2009, RoundCube Dev. - Switzerland                 |
+ | Copyright (C) 2008-2010, RoundCube Dev. - Switzerland                 |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -28,24 +28,25 @@
  */
 class rcmail
 {
-  static public $main_tasks = array('mail','settings','addressbook','login','logout','dummy');
-  
+  static public $main_tasks = array('mail','settings','addressbook','login','logout','utils','dummy');
+
   static private $instance;
-  
+
   public $config;
   public $user;
   public $db;
+  public $session;
   public $smtp;
   public $imap;
   public $output;
   public $plugins;
-  public $task = 'mail';
+  public $task;
   public $action = '';
   public $comm_path = './';
-  
+
   private $texts;
-  
-  
+
+
   /**
    * This implements the 'singleton' design pattern
    *
@@ -82,8 +83,6 @@
    */
   private function startup()
   {
-    $config_all = $this->config->all();
-
     // initialize syslog
     if ($this->config->get('log_driver') == 'syslog') {
       $syslog_id = $this->config->get('syslog_id', 'roundcube');
@@ -91,51 +90,41 @@
       openlog($syslog_id, LOG_ODELAY, $syslog_facility);
     }
 
-    // set task and action properties
-    $this->set_task(get_input_value('_task', RCUBE_INPUT_GPC));
-    $this->action = asciiwords(get_input_value('_action', RCUBE_INPUT_GPC));
-
     // connect to database
     $GLOBALS['DB'] = $this->get_dbh();
 
-    // use database for storing session data
-    include_once('include/session.inc');
-
-    // set session domain
-    if (!empty($config_all['session_domain'])) {
-      ini_set('session.cookie_domain', $config_all['session_domain']);
-    }
-    // set session garbage collecting time according to session_lifetime
-    if (!empty($config_all['session_lifetime'])) {
-      ini_set('session.gc_maxlifetime', ($config_all['session_lifetime']) * 120);
-    }
-
-    // start PHP session (if not in CLI mode)
-    if ($_SERVER['REMOTE_ADDR'])
-      session_start();
-
-    // set initial session vars
-    if (!isset($_SESSION['auth_time'])) {
-      $_SESSION['auth_time'] = time();
-      $_SESSION['temp'] = true;
-    }
+    // start session
+    $this->session_init();
 
     // create user object
     $this->set_user(new rcube_user($_SESSION['user_id']));
 
+    // configure session (after user config merge!)
+    $this->session_configure();
+
+    // set task and action properties
+    $this->set_task(get_input_value('_task', RCUBE_INPUT_GPC));
+    $this->action = asciiwords(get_input_value('_action', RCUBE_INPUT_GPC));
+
     // reset some session parameters when changing task
-    if ($_SESSION['task'] != $this->task)
-      rcube_sess_unset('page');
+    if ($this->task != 'utils') {
+      if ($this->session && $_SESSION['task'] != $this->task)
+        $this->session->remove('page');
+      // set current task to session
+      $_SESSION['task'] = $this->task;
+    }
 
-    // set current task to session
-    $_SESSION['task'] = $this->task;
+    // init output class
+    if (!empty($_REQUEST['_remote']))
+      $GLOBALS['OUTPUT'] = $this->json_init();
+    else
+      $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
 
-    // create IMAP object
-    if ($this->task == 'mail')
-      $this->imap_init();
-      
     // create plugin API and load plugins
     $this->plugins = rcube_plugin_api::get_instance();
+
+    // init plugins
+    $this->plugins->init();
   }
   
   
@@ -147,7 +136,13 @@
   public function set_task($task)
   {
     $task = asciiwords($task);
-    $this->task = $task ? $task : 'mail';
+
+    if ($this->user && $this->user->ID)
+      $task = !$task || $task == 'login' ? 'mail' : $task;
+    else
+      $task = 'login';
+
+    $this->task = $task;
     $this->comm_path = $this->url(array('task' => $this->task));
     
     if ($this->output)
@@ -167,7 +162,7 @@
       $GLOBALS['USER'] = $this->user;
       
       // overwrite config with user preferences
-      $this->config->merge((array)$this->user->get_prefs());
+      $this->config->set_user_prefs((array)$this->user->get_prefs());
     }
     
     $_SESSION['language'] = $this->user->language = $this->language_prop($this->config->get('language', $_SESSION['language']));
@@ -250,6 +245,7 @@
   /**
    * Return instance of the internal address book class
    *
+   * @param string  Address book identifier
    * @param boolean True if the address book needs to be writeable
    * @return object rcube_contacts Address book object
    */
@@ -280,11 +276,63 @@
         }
       }
     }
-    else {
+    else { // $id == 'sql'
       $contacts = new rcube_contacts($this->db, $this->user->ID);
     }
     
     return $contacts;
+  }
+
+
+  /**
+   * Return address books list
+   *
+   * @param boolean True if the address book needs to be writeable
+   * @return array  Address books array
+   */
+  public function get_address_sources($writeable = false)
+  {
+    $abook_type = strtolower($this->config->get('address_book_type'));
+    $ldap_config = $this->config->get('ldap_public');
+    $autocomplete = (array) $this->config->get('autocomplete_addressbooks');
+    $list = array();
+
+    // We are using the DB address book
+    if ($abook_type != 'ldap') {
+      $contacts = new rcube_contacts($this->db, null);
+      $list['0'] = array(
+        'id' => 0,
+        'name' => rcube_label('personaladrbook'),
+        'groups' => $contacts->groups,
+        'readonly' => false,
+        'autocomplete' => in_array('sql', $autocomplete)
+      );
+    }
+
+    if ($ldap_config) {
+      $ldap_config = (array) $ldap_config;
+      foreach ($ldap_config as $id => $prop)
+        $list[$id] = array(
+          'id' => $id,
+          'name' => $prop['name'],
+          'groups' => false,
+          'readonly' => !$prop['writable'],
+          'autocomplete' => in_array('sql', $autocomplete)
+        );
+    }
+
+    $plugin = $this->plugins->exec_hook('address_sources', array('sources' => $list));
+    $list = $plugin['sources'];
+
+    if ($writeable && !empty($list)) {
+      foreach ($list as $idx => $item) {
+        if ($item['readonly']) {
+          unset($list[$idx]);
+        }
+      }
+    }
+
+    return $list;
   }
   
   
@@ -303,11 +351,8 @@
       $this->output = new rcube_template($this->task, $framed);
 
     // set keep-alive/check-recent interval
-    if ($keep_alive = $this->config->get('keep_alive')) {
-      // be sure that it's less than session lifetime
-      if ($session_lifetime = $this->config->get('session_lifetime'))
-        $keep_alive = min($keep_alive, $session_lifetime * 60 - 30);
-      $this->output->set_env('keep_alive', max(60, $keep_alive));
+    if ($this->session && ($keep_alive = $this->session->get_keep_alive())) {
+      $this->output->set_env('keep_alive', $keep_alive);
     }
 
     if ($framed) {
@@ -332,7 +377,7 @@
    *
    * @return object rcube_json_output Reference to JSON output object
    */
-  public function init_json()
+  public function json_init()
   {
     if (!($this->output instanceof rcube_json_output))
       $this->output = new rcube_json_output($this->task);
@@ -363,10 +408,13 @@
    */
   public function imap_init($connect = false)
   {
+    // already initialized
+    if (is_object($this->imap))
+      return;
+      
     $this->imap = new rcube_imap($this->db);
     $this->imap->debug_level = $this->config->get('debug_level');
     $this->imap->skip_deleted = $this->config->get('skip_deleted');
-    $this->imap->index_sort = $this->config->get('index_sort', true);
 
     // enable caching of imap data
     if ($this->config->get('enable_caching')) {
@@ -376,22 +424,31 @@
     // set pagesize from config
     $this->imap->set_pagesize($this->config->get('pagesize', 50));
     
-    // Setting root and delimiter before iil_Connect can save time detecting them
-    // using NAMESPACE and LIST 
+    // 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'),
       'delimiter' => isset($_SESSION['imap_delimiter']) ? $_SESSION['imap_delimiter'] : $this->config->get('imap_delimiter'),
       'rootdir' => isset($_SESSION['imap_root']) ? $_SESSION['imap_root'] : $this->config->get('imap_root'),
       'debug_mode' => (bool) $this->config->get('imap_debug', 0),
+      'force_caps' => (bool) $this->config->get('imap_force_caps'),
     );
 
     $this->imap->set_options($options);
   
     // set global object for backward compatibility
     $GLOBALS['IMAP'] = $this->imap;
+
+    $hook = $this->plugins->exec_hook('imap_init', array('fetch_headers' => $this->imap->fetch_add_headers));
+    if ($hook['fetch_headers'])
+      $this->imap->fetch_add_headers = $hook['fetch_headers'];
     
-    if ($connect)
+    // support this parameter for backward compatibility but log warning
+    if ($connect) {
       $this->imap_connect();
+      raise_error(array('code' => 800, 'type' => 'imap', 'file' => __FILE__,
+        'message' => "rcube::imap_init(true) is deprecated, use rcube::imap_connect() instead"), true, false);
+    }
   }
 
 
@@ -402,18 +459,87 @@
    */
   public function imap_connect()
   {
-    $conn = false;
+    if (!$this->imap)
+      $this->imap_init();
     
-    if ($_SESSION['imap_host'] && !$this->imap->conn) {
-      if (!($conn = $this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']))) {
+    if ($_SESSION['imap_host'] && !$this->imap->conn->connected()) {
+      if (!$this->imap->connect($_SESSION['imap_host'], $_SESSION['username'], $this->decrypt($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])) {
         if ($this->output)
           $this->output->show_message($this->imap->error_code == -1 ? 'imaperror' : 'sessionerror', 'error');
       }
-
-      $this->set_imap_prop();
+      else {
+        $this->set_imap_prop();
+        return $this->imap->conn;
+      }
     }
 
-    return $conn;
+    return false;
+  }
+
+
+  /**
+   * Create session object and start the session.
+   */
+  public function session_init()
+  {
+    // session started (Installer?)
+    if (session_id())
+      return;
+
+    $lifetime = $this->config->get('session_lifetime', 0) * 60;
+
+    // set session domain
+    if ($domain = $this->config->get('session_domain')) {
+      ini_set('session.cookie_domain', $domain);
+    }
+    // set session garbage collecting time according to session_lifetime
+    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.use_cookies', 1);
+    ini_set('session.use_only_cookies', 1);  
+    ini_set('session.serialize_handler', 'php');
+
+    // use database for storing session data
+    $this->session = new rcube_session($this->get_dbh(), $lifetime);
+
+    $this->session->register_gc_handler('rcmail_temp_gc');
+    if ($this->config->get('enable_caching'))
+      $this->session->register_gc_handler('rcmail_cache_gc');
+
+    // start PHP session (if not in CLI mode)
+    if ($_SERVER['REMOTE_ADDR'])
+      session_start();
+
+    // set initial session vars
+    if (!isset($_SESSION['auth_time'])) {
+      $_SESSION['auth_time'] = time();
+      $_SESSION['temp'] = true;
+    }
+  }
+
+
+  /**
+   * Configure session object internals
+   */
+  public function session_configure()
+  {
+    if (!$this->session)
+      return;
+
+    $lifetime = $this->config->get('session_lifetime', 0) * 60;
+
+    // set keep-alive/check-recent interval
+    if ($keep_alive = $this->config->get('keep_alive')) {
+      // be sure that it's less than session lifetime
+      if ($lifetime)
+        $keep_alive = min($keep_alive, $lifetime - 30);
+      $keep_alive = max(60, $keep_alive);
+      $this->session->set_keep_alive($keep_alive);
+    }
   }
 
 
@@ -488,6 +614,9 @@
     if ($user = rcube_user::query($username, $host))
       $username = $user->data['username'];
 
+    if (!$this->imap)
+      $this->imap_init();
+
     // exit if IMAP login failed
     if (!($imap_login  = $this->imap->connect($host, $username, $pass, $imap_port, $imap_ssl)))
       return false;
@@ -512,7 +641,7 @@
       else {
         raise_error(array(
           'code' => 600, 'type' => 'php',
-	  'file' => __FILE__, 'line' => __LINE__,
+	      'file' => __FILE__, 'line' => __LINE__,
           'message' => "Failed to create a user record. Maybe aborted by a plugin?"
           ), true, false);
       }
@@ -765,8 +894,6 @@
    */
   function authenticate_session()
   {
-    global $SESS_CLIENT_IP, $SESS_CHANGED;
-
     // advanced session authentication
     if ($this->config->get('double_auth')) {
       $now = time();
@@ -781,12 +908,13 @@
       }
     }
     else {
-      $valid = $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] == $SESS_CLIENT_IP : true;
+      $valid = $this->config->get('ip_check') ? $_SERVER['REMOTE_ADDR'] == $this->session->get_ip() : true;
     }
 
     // check session filetime
     $lifetime = $this->config->get('session_lifetime');
-    if (!empty($lifetime) && isset($SESS_CHANGED) && $SESS_CHANGED + $lifetime*60 < time()) {
+    $sess_ts = $this->session->get_ts();
+    if (!empty($lifetime) && !empty($sess_ts) && $sess_ts + $lifetime*60 < time()) {
       $valid = false;
     }
 
@@ -801,7 +929,7 @@
   {
     $this->plugins->exec_hook('kill_session');
     
-    rcube_sess_unset();
+    $this->session->remove();
     $_SESSION = array('language' => $this->user->language, 'auth_time' => time(), 'temp' => true);
     rcmail::setcookie('sessauth', '-del-', time() - 60);
     $this->user->reset();
@@ -820,7 +948,7 @@
       if (!$this->authenticate_session())
         return;
 
-      $this->imap_init(true);
+      $this->imap_connect();
     }
 
     if ($config['logout_purge'] && !empty($config['trash_mbox'])) {
@@ -839,10 +967,8 @@
    */
   public function shutdown()
   {
-    if (is_object($this->imap)) {
+    if (is_object($this->imap))
       $this->imap->close();
-      $this->imap->write_cache();
-    }
 
     if (is_object($this->smtp))
       $this->smtp->disconnect();
@@ -862,7 +988,10 @@
         $mem .= '/'.show_bytes(memory_get_peak_usage());
 
       $log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : '');
-      rcube_print_time(RCMAIL_START, $log);
+      if (defined('RCMAIL_START'))
+        rcube_print_time(RCMAIL_START, $log);
+      else
+        console($log);
     }
   }
   
@@ -947,23 +1076,25 @@
       mcrypt_generic_deinit($td);
       mcrypt_module_close($td);
     }
-    else if (function_exists('des'))
-    {
-      define('DES_IV_SIZE', 8);
-      $iv = '';
-      for ($i = 0; $i < constant('DES_IV_SIZE'); $i++)
-        $iv .= sprintf("%c", mt_rand(0, 255));
-      $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv);
+    else {
+      @include_once('lib/des.inc');
+
+      if (function_exists('des')) {
+        $des_iv_size = 8;
+        $iv = '';
+        for ($i = 0; $i < $des_iv_size; $i++)
+          $iv .= sprintf("%c", mt_rand(0, 255));
+        $cipher = $iv . des($this->config->get_crypto_key($key), $clear, 1, 1, $iv);
+      }
+      else {
+        raise_error(array(
+          'code' => 500, 'type' => 'php',
+          'file' => __FILE__, 'line' => __LINE__,
+          'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available"
+        ), true, true);
+      }
     }
-    else
-    {
-      raise_error(array(
-        'code' => 500, 'type' => 'php',
-        'file' => __FILE__, 'line' => __LINE__,
-        'message' => "Could not perform encryption; make sure Mcrypt is installed or lib/des.inc is available"
-      ), true, true);
-    }
-  
+
     return $base64 ? base64_encode($cipher) : $cipher;
   }
 
@@ -993,22 +1124,24 @@
       mcrypt_generic_deinit($td);
       mcrypt_module_close($td);
     }
-    else if (function_exists('des'))
-    {
-      define('DES_IV_SIZE', 8);
-      $iv = substr($cipher, 0, constant('DES_IV_SIZE'));
-      $cipher = substr($cipher, constant('DES_IV_SIZE'));
-      $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv);
+    else {
+      @include_once('lib/des.inc');
+    
+      if (function_exists('des')) {
+        $des_iv_size = 8;
+        $iv = substr($cipher, 0, $des_iv_size);
+        $cipher = substr($cipher, $des_iv_size);
+        $clear = des($this->config->get_crypto_key($key), $cipher, 0, 1, $iv);
+      }
+      else {
+        raise_error(array(
+          'code' => 500, 'type' => 'php',
+          'file' => __FILE__, 'line' => __LINE__,
+          'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available"
+        ), true, true);
+      }
     }
-    else
-    {
-      raise_error(array(
-        'code' => 500, 'type' => 'php',
-        'file' => __FILE__, 'line' => __LINE__,
-        'message' => "Could not perform decryption; make sure Mcrypt is installed or lib/des.inc is available"
-      ), true, true);
-    }
-  
+
     /*-
      * Trim PHP's padding and the canary byte; see note in
      * rcmail::encrypt() and http://php.net/mcrypt_generic#68082

--
Gitblit v1.9.1