David Carter
2013-08-30 de8687f9f11d49d36b322af72f644f7c5a232b9f
program/lib/Roundcube/rcube.php
@@ -99,20 +99,20 @@
    protected $texts;
    protected $caches = array();
    protected $shutdown_functions = array();
    protected $expunge_cache = false;
    /**
     * This implements the 'singleton' design pattern
     *
     * @param integer Options to initialize with this instance. See rcube::INIT_WITH_* constants
     * @param string Environment name to run (e.g. live, dev, test)
     *
     * @return rcube The one and only instance
     */
    static function get_instance($mode = 0)
    static function get_instance($mode = 0, $env = '')
    {
        if (!self::$instance) {
            self::$instance = new rcube();
            self::$instance = new rcube($env);
            self::$instance->init($mode);
        }
@@ -123,10 +123,10 @@
    /**
     * Private constructor
     */
    protected function __construct()
    protected function __construct($env = '')
    {
        // load configuration
        $this->config  = new rcube_config;
        $this->config  = new rcube_config($env);
        $this->plugins = new rcube_dummy_plugin_api;
        register_shutdown_function(array($this, 'shutdown'));
@@ -269,16 +269,18 @@
    {
        $shared_name = "shared_$name";
        if (!isset($this->caches[$shared_name])) {
        if (!array_key_exists($shared_name, $this->caches)) {
            $opt  = strtolower($name) . '_cache';
            $type = $this->config->get($opt);
            $ttl  = $this->config->get($opt . '_ttl');
            if (!$type) {
                $type = $this->config->get('shared_cache');
                // cache is disabled
                return $this->caches[$shared_name] = null;
            }
            if ($ttl === null) {
                $ttl = $this->config->get('shared_cache_ttl');
                $ttl = $this->config->get('shared_cache_ttl', '10d');
            }
            $this->caches[$shared_name] = new rcube_cache_shared($type, $name, $ttl, $packed);
@@ -376,6 +378,7 @@
            'auth_pw'     => $this->config->get("{$driver}_auth_pw"),
            'debug'       => (bool) $this->config->get("{$driver}_debug"),
            'force_caps'  => (bool) $this->config->get("{$driver}_force_caps"),
            'disabled_caps' => $this->config->get("{$driver}_disabled_caps"),
            'timeout'     => (int) $this->config->get("{$driver}_timeout"),
            'skip_deleted' => (bool) $this->config->get('skip_deleted'),
            'driver'      => $driver,
@@ -455,22 +458,36 @@
        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');
        ini_set('session.cookie_httponly', 1);
        // use database for storing session data
        $this->session = new rcube_session($this->get_dbh(), $this->config);
        $this->session->register_gc_handler(array($this, 'temp_gc'));
        $this->session->register_gc_handler(array($this, 'cache_gc'));
        $this->session->register_gc_handler(array($this, 'gc'));
        $this->session->set_secret($this->config->get('des_key') . dirname($_SERVER['SCRIPT_NAME']));
        $this->session->set_ip_check($this->config->get('ip_check'));
        if ($this->config->get('session_auth_name')) {
            $this->session->set_cookiename($this->config->get('session_auth_name'));
        }
        // start PHP session (if not in CLI mode)
        if ($_SERVER['REMOTE_ADDR']) {
            session_start();
            $this->session->start();
        }
    }
    /**
     * Garbage collector - cache/temp cleaner
     */
    public function gc()
    {
        rcube_cache::gc();
        rcube_cache_shared::gc();
        $this->get_storage()->cache_gc();
        $this->gc_temp();
    }
@@ -478,18 +495,25 @@
     * Garbage collector function for temp files.
     * Remove temp files older than two days
     */
    public function temp_gc()
    public function gc_temp()
    {
        $tmp = unslashify($this->config->get('temp_dir'));
        $expire = time() - 172800;  // expire in 48 hours
        // expire in 48 hours by default
        $temp_dir_ttl = $this->config->get('temp_dir_ttl', '48h');
        $temp_dir_ttl = get_offset_sec($temp_dir_ttl);
        if ($temp_dir_ttl < 6*3600)
            $temp_dir_ttl = 6*3600;   // 6 hours sensible lower bound.
        $expire = time() - $temp_dir_ttl;
        if ($tmp && ($dir = opendir($tmp))) {
            while (($fname = readdir($dir)) !== false) {
                if ($fname{0} == '.') {
                if ($fname[0] == '.') {
                    continue;
                }
                if (filemtime($tmp.'/'.$fname) < $expire) {
                if (@filemtime($tmp.'/'.$fname) < $expire) {
                    @unlink($tmp.'/'.$fname);
                }
            }
@@ -500,14 +524,21 @@
    /**
     * Garbage collector for cache entries.
     * Set flag to expunge caches on shutdown
     * Runs garbage collector with probability based on
     * session settings. This is intended for environments
     * without a session.
     */
    public function cache_gc()
    public function gc_run()
    {
        // because this gc function is called before storage is initialized,
        // we just set a flag to expunge storage cache on shutdown.
        $this->expunge_cache = true;
        $probability = (int) ini_get('session.gc_probability');
        $divisor     = (int) ini_get('session.gc_divisor');
        if ($divisor > 0 && $probability > 0) {
            $random = mt_rand(1, $divisor);
            if ($random <= $probability) {
                $this->gc();
            }
        }
    }
@@ -891,6 +922,14 @@
            call_user_func($function);
        }
        // write session data as soon as possible and before
        // closing database connection, don't do this before
        // registered shutdown functions, they may need the session
        // Note: this will run registered gc handlers (ie. cache gc)
        if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
            $this->session->write_close();
        }
        if (is_object($this->smtp)) {
            $this->smtp->disconnect();
        }
@@ -902,9 +941,6 @@
        }
        if (is_object($this->storage)) {
            if ($this->expunge_cache) {
                $this->storage->expunge_cache();
            }
            $this->storage->close();
        }
    }
@@ -1368,6 +1404,10 @@
            'options' => $options,
        ));
        if ($plugin['abort']) {
            return isset($plugin['result']) ? $plugin['result'] : false;
        }
        $from    = $plugin['from'];
        $mailto  = $plugin['mailto'];
        $options = $plugin['options'];
@@ -1464,7 +1504,7 @@
                    $subject    = str_replace("\r\n", $delim, $subject);
                }
                if (ini_get('safe_mode'))
                if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN))
                    $sent = mail($to, $subject, $msg_body, $header_str);
                else
                    $sent = mail($to, $subject, $msg_body, $header_str, "-f$from");