[Svn] r3296 - in trunk/roundcubemail: . plugins/managesieve plugins/new_user_dialog program/include program/steps/mail

trac at roundcube.net trac at roundcube.net
Mon Mar 1 20:04:34 CET 2010


Author: alec
Date: 2010-03-01 13:04:34 -0600 (Mon, 01 Mar 2010)
New Revision: 3296

Added:
   trunk/roundcubemail/program/include/rcube_session.php
Modified:
   trunk/roundcubemail/CHANGELOG
   trunk/roundcubemail/index.php
   trunk/roundcubemail/plugins/managesieve/managesieve.php
   trunk/roundcubemail/plugins/new_user_dialog/new_user_dialog.php
   trunk/roundcubemail/program/include/iniset.php
   trunk/roundcubemail/program/include/main.inc
   trunk/roundcubemail/program/include/rcmail.php
   trunk/roundcubemail/program/include/rcube_plugin_api.php
   trunk/roundcubemail/program/include/rcube_template.php
   trunk/roundcubemail/program/include/rcube_user.php
   trunk/roundcubemail/program/steps/mail/func.inc
Log:
- Improve performance by avoiding unnecessary updates to the session table (#1486325)


Modified: trunk/roundcubemail/CHANGELOG
===================================================================
--- trunk/roundcubemail/CHANGELOG	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/CHANGELOG	2010-03-01 19:04:34 UTC (rev 3296)
@@ -1,6 +1,7 @@
 CHANGELOG RoundCube Webmail
 ===========================
 
+- Improve performance by avoiding unnecessary updates to the session table (#1486325)
 - Fix invalid font tags which cause HTML message rendering problems (#1486521)
 - Fix CVE-2010-0464: Disable DNS prefetching (#1486449)
 - Fix Received headers to behave better with SpamAssassin (#1486513)

Modified: trunk/roundcubemail/index.php
===================================================================
--- trunk/roundcubemail/index.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/index.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -96,8 +96,8 @@
         !empty($auth['host']) && !empty($auth['user']) &&
         $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'])) {
     // create new session ID
-    rcube_sess_unset('temp');
-    rcube_sess_regenerate_id();
+    $RCMAIL->session->remove('temp');
+    $RCMAIL->session->regenerate_id();
 
     // send auth cookie if necessary
     $RCMAIL->authenticate_session();

Modified: trunk/roundcubemail/plugins/managesieve/managesieve.php
===================================================================
--- trunk/roundcubemail/plugins/managesieve/managesieve.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/plugins/managesieve/managesieve.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -221,7 +221,7 @@
 	if ($result === true) {
 	  $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
 	  $this->rc->output->command('managesieve_reload');
-	  rcube_sess_unset('managesieve_current');
+	  $this->rc->session->remove('managesieve_current');
 	} else {
           $this->rc->output->show_message('managesieve.setdeleteerror', 'error');
 	}
@@ -270,7 +270,7 @@
       if (!$error) {
 	$this->rc->output->show_message('managesieve.setcreated', 'confirmation');
 	$this->rc->output->command('parent.managesieve_reload', $name);
-//	rcube_sess_unset('managesieve_current');
+//	$this->rc->session->remove('managesieve_current');
       } else {
         $this->rc->output->show_message($error, 'error');
       }

Modified: trunk/roundcubemail/plugins/new_user_dialog/new_user_dialog.php
===================================================================
--- trunk/roundcubemail/plugins/new_user_dialog/new_user_dialog.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/plugins/new_user_dialog/new_user_dialog.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -98,7 +98,7 @@
     // save data if not empty
     if (!empty($save_data['name']) && !empty($save_data['email'])) {
       $rcmail->user->update_identity($identity['identity_id'], $save_data);
-      rcube_sess_unset('plugin.newuserdialog');
+      $rcmail->session->remove('plugin.newuserdialog');
     }
     
     $rcmail->output->redirect('');

Modified: trunk/roundcubemail/program/include/iniset.php
===================================================================
--- trunk/roundcubemail/program/include/iniset.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/program/include/iniset.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -52,15 +52,6 @@
 }
 
 ini_set('error_reporting', E_ALL&~E_NOTICE);
-if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') {
-   ini_set('session.cookie_secure', 1);
-} else {
-   ini_set('session.cookie_secure', 0);
-}
-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');
 
 // increase maximum execution time for php scripts
 // (does not work in safe mode)

Modified: trunk/roundcubemail/program/include/main.inc
===================================================================
--- trunk/roundcubemail/program/include/main.inc	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/program/include/main.inc	2010-03-01 19:04:34 UTC (rev 3296)
@@ -1487,13 +1487,21 @@
     return true;
   if ($port && $_SERVER['SERVER_PORT'] == $port)
     return true;
-  if ($use_https && $RCMAIL->config->get('use_https'))
+  if ($use_https && isset($RCMAIL) && $RCMAIL->config->get('use_https'))
     return true;
 
   return false;
 }
 
+// for backward compatibility
+function rcube_sess_unset($var_name=null)
+{
+  global $RCMAIL;
 
+  $RCMAIL->session->remove($var_name);
+}
+
+
 /**
  * E-mail address validation
  */

Modified: trunk/roundcubemail/program/include/rcmail.php
===================================================================
--- trunk/roundcubemail/program/include/rcmail.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/program/include/rcmail.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -35,6 +35,7 @@
   public $config;
   public $user;
   public $db;
+  public $session;
   public $smtp;
   public $imap;
   public $output;
@@ -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');
@@ -94,45 +93,29 @@
     // connect to database
     $GLOBALS['DB'] = $this->get_dbh();
 
-    // use database for storing session data
-    include_once('include/session.inc');
+    // start session
+    $this->session_init();
 
-    // 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;
-    }
-
     // 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');
+      $this->session->remove('page');
 
     // set current task to session
     $_SESSION['task'] = $this->task;
 
     // init output class
     if (!empty($_REQUEST['_remote']))
-      $GLOBALS['OUTPUT'] = $this->init_json();
+      $GLOBALS['OUTPUT'] = $this->json_init();
     else
       $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
 
@@ -314,11 +297,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 ($keep_alive = $this->session->get_keep_alive()) {
+      $this->output->set_env('keep_alive', $keep_alive);
     }
 
     if ($framed) {
@@ -343,7 +323,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);
@@ -444,6 +424,65 @@
 
 
   /**
+   * Create session object and start the session.
+   */
+  public function session_init()
+  {
+    $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()
+  {
+    $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);
+    }
+  }
+
+
+  /**
    * Perfom login to the IMAP server and to the webmail service.
    * This will also create a new user entry if auto_create_user is configured.
    *
@@ -794,8 +833,6 @@
    */
   function authenticate_session()
   {
-    global $SESS_CLIENT_IP, $SESS_CHANGED;
-
     // advanced session authentication
     if ($this->config->get('double_auth')) {
       $now = time();
@@ -810,12 +847,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;
     }
 
@@ -830,7 +868,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();

Modified: trunk/roundcubemail/program/include/rcube_plugin_api.php
===================================================================
--- trunk/roundcubemail/program/include/rcube_plugin_api.php	2010-02-28 08:07:45 UTC (rev 3295)
+++ trunk/roundcubemail/program/include/rcube_plugin_api.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -69,7 +69,7 @@
   /**
    * Load and init all enabled plugins
    *
-   * This has to be done after rcmail::load_gui() or rcmail::init_json()
+   * This has to be done after rcmail::load_gui() or rcmail::json_init()
    * was called because plugins need to have access to rcmail->output
    */
   public function init()

Added: trunk/roundcubemail/program/include/rcube_session.php
===================================================================
--- trunk/roundcubemail/program/include/rcube_session.php	                        (rev 0)
+++ trunk/roundcubemail/program/include/rcube_session.php	2010-03-01 19:04:34 UTC (rev 3296)
@@ -0,0 +1,330 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_session.php                                     |
+ |                                                                       |
+ | This file is part of the RoundCube Webmail client                     |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland                 |
+ | Licensed under the GNU GPL                                            |
+ |                                                                       |
+ | PURPOSE:                                                              |
+ |   Provide database supported session management                       |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube at gmail.com>                        |
+ | Author: Aleksander Machniak <alec at alec.pl>                            |
+ +-----------------------------------------------------------------------+
+
+ $Id: session.inc 2932 2009-09-07 12:51:21Z alec $
+
+*/
+
+class rcube_session
+{
+  private $db;
+  private $ip;
+  private $changed;
+  private $unsets = array();
+  private $gc_handlers = array();
+  private $start;
+  private $vars = false;
+  private $key;
+  private $keep_alive = 0;
+
+  /**
+   * Default constructor
+   */
+  public function __construct($db, $lifetime=60)
+  {
+    $this->db = $db;
+    $this->lifetime = $lifetime;
+    $this->start = microtime(true);
+
+    // set custom functions for PHP s