summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--index.php379
-rw-r--r--program/include/clisetup.php2
-rw-r--r--program/include/iniset.php1
-rw-r--r--program/include/rcmail.php1689
-rw-r--r--program/include/rcmail_html_page.php5
-rw-r--r--program/include/rcmail_output_html.php7
-rw-r--r--program/include/rcmail_string_replacer.php21
-rw-r--r--program/lib/Roundcube/rcube.php7
8 files changed, 1064 insertions, 1047 deletions
diff --git a/index.php b/index.php
index 03c3f4322..7adb0beb0 100644
--- a/index.php
+++ b/index.php
@@ -32,6 +32,7 @@
| |
+-------------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+ | Author: Aleksander Machniak <alec@alec.pl> |
+-------------------------------------------------------------------------+
*/
@@ -49,34 +50,36 @@ ob_start();
// check if config files had errors
if ($err_str = $RCMAIL->config->get_error()) {
- rcmail::raise_error(array(
- 'code' => 601,
- 'type' => 'php',
- 'message' => $err_str), false, true);
+ rcmail::raise_error(array(
+ 'code' => 601,
+ 'type' => 'php',
+ 'message' => $err_str), false, true);
}
// check DB connections and exit on failure
if ($err_str = $RCMAIL->db->is_error()) {
- rcmail::raise_error(array(
- 'code' => 603,
- 'type' => 'db',
- 'message' => $err_str), FALSE, TRUE);
+ rcmail::raise_error(array(
+ 'code' => 603,
+ 'type' => 'db',
+ 'message' => $err_str), FALSE, TRUE);
}
// error steps
if ($RCMAIL->action == 'error' && !empty($_GET['_code'])) {
- rcmail::raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE);
+ rcmail::raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE);
}
// check if https is required (for login) and redirect if necessary
if (empty($_SESSION['user_id']) && ($force_https = $RCMAIL->config->get('force_https', false))) {
- $https_port = is_bool($force_https) ? 443 : $force_https;
- if (!rcube_utils::https_check($https_port)) {
- $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
- $host .= ($https_port != 443 ? ':' . $https_port : '');
- header('Location: https://' . $host . $_SERVER['REQUEST_URI']);
- exit;
- }
+ $https_port = is_bool($force_https) ? 443 : $force_https;
+
+ if (!rcube_utils::https_check($https_port)) {
+ $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
+ $host .= ($https_port != 443 ? ':' . $https_port : '');
+
+ header('Location: https://' . $host . $_SERVER['REQUEST_URI']);
+ exit;
+ }
}
// trigger startup plugin hook
@@ -86,165 +89,176 @@ $RCMAIL->action = $startup['action'];
// try to log in
if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') {
- $request_valid = $_SESSION['temp'] && $RCMAIL->check_request(rcube_utils::INPUT_POST, 'login');
-
- // purge the session in case of new login when a session already exists
- $RCMAIL->kill_session();
-
- $auth = $RCMAIL->plugins->exec_hook('authenticate', array(
- 'host' => $RCMAIL->autoselect_host(),
- 'user' => trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)),
- 'pass' => rcube_utils::get_input_value('_pass', rcube_utils::INPUT_POST, true,
- $RCMAIL->config->get('password_charset', 'ISO-8859-1')),
- 'cookiecheck' => true,
- 'valid' => $request_valid,
- ));
-
- // Login
- if ($auth['valid'] && !$auth['abort'] &&
- $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'], $auth['cookiecheck'])
- ) {
- // create new session ID, don't destroy the current session
- // it was destroyed already by $RCMAIL->kill_session() above
- $RCMAIL->session->remove('temp');
- $RCMAIL->session->regenerate_id(false);
-
- // send auth cookie if necessary
- $RCMAIL->session->set_auth_cookie();
-
- // log successful login
- $RCMAIL->log_login();
-
- // restore original request parameters
- $query = array();
- if ($url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST)) {
- parse_str($url, $query);
-
- // prevent endless looping on login page
- if ($query['_task'] == 'login')
- unset($query['_task']);
-
- // prevent redirect to compose with specified ID (#1488226)
- if ($query['_action'] == 'compose' && !empty($query['_id']))
- $query = array();
- }
+ $request_valid = $_SESSION['temp'] && $RCMAIL->check_request(rcube_utils::INPUT_POST, 'login');
- // allow plugins to control the redirect url after login success
- $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail'));
- unset($redir['abort'], $redir['_err']);
+ // purge the session in case of new login when a session already exists
+ $RCMAIL->kill_session();
- // send redirect
- $OUTPUT->redirect($redir);
- }
- else {
- if (!$auth['valid']) {
- $error_code = RCMAIL::ERROR_INVALID_REQUEST;
+ $auth = $RCMAIL->plugins->exec_hook('authenticate', array(
+ 'host' => $RCMAIL->autoselect_host(),
+ 'user' => trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)),
+ 'pass' => rcube_utils::get_input_value('_pass', rcube_utils::INPUT_POST, true,
+ $RCMAIL->config->get('password_charset', 'ISO-8859-1')),
+ 'cookiecheck' => true,
+ 'valid' => $request_valid,
+ ));
+
+ // Login
+ if ($auth['valid'] && !$auth['abort']
+ && $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'], $auth['cookiecheck'])
+ ) {
+ // create new session ID, don't destroy the current session
+ // it was destroyed already by $RCMAIL->kill_session() above
+ $RCMAIL->session->remove('temp');
+ $RCMAIL->session->regenerate_id(false);
+
+ // send auth cookie if necessary
+ $RCMAIL->session->set_auth_cookie();
+
+ // log successful login
+ $RCMAIL->log_login();
+
+ // restore original request parameters
+ $query = array();
+ if ($url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST)) {
+ parse_str($url, $query);
+
+ // prevent endless looping on login page
+ if ($query['_task'] == 'login') {
+ unset($query['_task']);
+ }
+
+ // prevent redirect to compose with specified ID (#1488226)
+ if ($query['_action'] == 'compose' && !empty($query['_id'])) {
+ $query = array();
+ }
+ }
+
+ // allow plugins to control the redirect url after login success
+ $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail'));
+ unset($redir['abort'], $redir['_err']);
+
+ // send redirect
+ $OUTPUT->redirect($redir);
}
else {
- $error_code = $auth['error'] ? $auth['error'] : $RCMAIL->login_error();
- }
+ if (!$auth['valid']) {
+ $error_code = RCMAIL::ERROR_INVALID_REQUEST;
+ }
+ else {
+ $error_code = $auth['error'] ? $auth['error'] : $RCMAIL->login_error();
+ }
- $error_labels = array(
- RCMAIL::ERROR_STORAGE => 'storageerror',
- RCMAIL::ERROR_COOKIES_DISABLED => 'cookiesdisabled',
- RCMAIL::ERROR_INVALID_REQUEST => 'invalidrequest',
- RCMAIL::ERROR_INVALID_HOST => 'invalidhost',
- );
+ $error_labels = array(
+ RCMAIL::ERROR_STORAGE => 'storageerror',
+ RCMAIL::ERROR_COOKIES_DISABLED => 'cookiesdisabled',
+ RCMAIL::ERROR_INVALID_REQUEST => 'invalidrequest',
+ RCMAIL::ERROR_INVALID_HOST => 'invalidhost',
+ );
- $error_message = $error_labels[$error_code] ? $error_labels[$error_code] : 'loginfailed';
+ $error_message = $error_labels[$error_code] ? $error_labels[$error_code] : 'loginfailed';
- // log failed login
- $RCMAIL->log_login($auth['user'], true, $error_code);
+ $OUTPUT->show_message($error_message, 'warning');
- $OUTPUT->show_message($error_message, 'warning');
- $RCMAIL->plugins->exec_hook('login_failed', array(
- 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user']));
- $RCMAIL->kill_session();
- }
+ // log failed login
+ $RCMAIL->log_login($auth['user'], true, $error_code);
+
+ $RCMAIL->plugins->exec_hook('login_failed', array(
+ 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user']));
+
+ $RCMAIL->kill_session();
+ }
}
// end session (after optional referer check)
-else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL->config->get('referer_check') || rcube_utils::check_referer())) {
- $userdata = array(
- 'user' => $_SESSION['username'],
- 'host' => $_SESSION['storage_host'],
- 'lang' => $RCMAIL->user->language,
- );
- $OUTPUT->show_message('loggedout');
- $RCMAIL->logout_actions();
- $RCMAIL->kill_session();
- $RCMAIL->plugins->exec_hook('logout_after', $userdata);
+else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])
+ && (!$RCMAIL->config->get('referer_check') || rcube_utils::check_referer())
+) {
+ $userdata = array(
+ 'user' => $_SESSION['username'],
+ 'host' => $_SESSION['storage_host'],
+ 'lang' => $RCMAIL->user->language,
+ );
+
+ $OUTPUT->show_message('loggedout');
+
+ $RCMAIL->logout_actions();
+ $RCMAIL->kill_session();
+ $RCMAIL->plugins->exec_hook('logout_after', $userdata);
}
// check session and auth cookie
else if ($RCMAIL->task != 'login' && $_SESSION['user_id'] && $RCMAIL->action != 'send') {
- if (!$RCMAIL->session->check_auth()) {
- $RCMAIL->kill_session();
- $session_error = true;
- }
+ if (!$RCMAIL->session->check_auth()) {
+ $RCMAIL->kill_session();
+ $session_error = true;
+ }
}
// not logged in -> show login page
if (empty($RCMAIL->user->ID)) {
- // log session failures
- $task = rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC);
- if ($task && !in_array($task, array('login','logout')) && !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])) {
- $RCMAIL->session->log("Aborted session " . $sess_id . "; no valid session data found");
- $session_error = true;
- }
-
- // check if installer is still active
- if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) {
- $OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"),
- html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") .
- html::p(null, "The install script of your Roundcube installation is still stored in its default location!") .
- html::p(null, "Please <b>remove</b> the whole <tt>installer</tt> folder from the Roundcube directory because .
- these files may expose sensitive configuration data like server passwords and encryption keys
- to the public. Make sure you cannot access the <a href=\"./installer/\">installer script</a> from your browser.")
- )
- );
- }
+ // log session failures
+ $task = rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC);
+
+ if ($task && !in_array($task, array('login','logout'))
+ && !$session_error && ($sess_id = $_COOKIE[ini_get('session.name')])
+ ) {
+ $RCMAIL->session->log("Aborted session $sess_id; no valid session data found");
+ $session_error = true;
+ }
+
+ // check if installer is still active
+ if ($RCMAIL->config->get('enable_installer') && is_readable('./installer/index.php')) {
+ $OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"),
+ html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") .
+ html::p(null, "The install script of your Roundcube installation is still stored in its default location!") .
+ html::p(null, "Please <b>remove</b> the whole <tt>installer</tt> folder from the Roundcube directory because .
+ these files may expose sensitive configuration data like server passwords and encryption keys
+ to the public. Make sure you cannot access the <a href=\"./installer/\">installer script</a> from your browser.")
+ ));
+ }
+
+ if ($session_error || $_REQUEST['_err'] == 'session') {
+ $OUTPUT->show_message('sessionerror', 'error', null, true, -1);
+ }
- if ($session_error || $_REQUEST['_err'] == 'session') {
- $OUTPUT->show_message('sessionerror', 'error', null, true, -1);
- }
+ if ($OUTPUT->ajax_call || !empty($_REQUEST['_framed'])) {
+ $OUTPUT->command('session_error', $RCMAIL->url(array('_err' => 'session')));
+ $OUTPUT->send('iframe');
+ }
- if ($OUTPUT->ajax_call || !empty($_REQUEST['_framed'])) {
- $OUTPUT->command('session_error', $RCMAIL->url(array('_err' => 'session')));
- $OUTPUT->send('iframe');
- }
+ $plugin = $RCMAIL->plugins->exec_hook('unauthenticated', array('task' => 'login', 'error' => $session_error));
- $plugin = $RCMAIL->plugins->exec_hook('unauthenticated', array('task' => 'login', 'error' => $session_error));
+ $RCMAIL->set_task($plugin['task']);
- $RCMAIL->set_task($plugin['task']);
- $OUTPUT->send($plugin['task']);
+ $OUTPUT->send($plugin['task']);
}
// CSRF prevention
else {
- // don't check for valid request tokens in these actions
- $request_check_whitelist = array('login'=>1, 'spell'=>1, 'spell_html'=>1);
-
- if (!$request_check_whitelist[$RCMAIL->action]) {
- // check client X-header to verify request origin
- if ($OUTPUT->ajax_call) {
- if (rcube_utils::request_header('X-Roundcube-Request') != $RCMAIL->get_request_token()) {
- header('HTTP/1.1 403 Forbidden');
- die("Invalid Request");
- }
- }
- // check request token in POST form submissions
- else if (!empty($_POST) && !$RCMAIL->check_request()) {
- $OUTPUT->show_message('invalidrequest', 'error');
- $OUTPUT->send($RCMAIL->task);
+ // don't check for valid request tokens in these actions
+ $request_check_whitelist = array('login'=>1, 'spell'=>1, 'spell_html'=>1);
+
+ if (!$request_check_whitelist[$RCMAIL->action]) {
+ // check client X-header to verify request origin
+ if ($OUTPUT->ajax_call) {
+ if (rcube_utils::request_header('X-Roundcube-Request') != $RCMAIL->get_request_token()) {
+ header('HTTP/1.1 403 Forbidden');
+ die("Invalid Request");
+ }
+ }
+ // check request token in POST form submissions
+ else if (!empty($_POST) && !$RCMAIL->check_request()) {
+ $OUTPUT->show_message('invalidrequest', 'error');
+ $OUTPUT->send($RCMAIL->task);
+ }
+
+ // check referer if configured
+ if ($RCMAIL->config->get('referer_check') && !rcube_utils::check_referer()) {
+ raise_error(array(
+ 'code' => 403, 'type' => 'php',
+ 'message' => "Referer check failed"), true, true);
+ }
}
-
- // check referer if configured
- if ($RCMAIL->config->get('referer_check') && !rcube_utils::check_referer()) {
- raise_error(array(
- 'code' => 403, 'type' => 'php',
- 'message' => "Referer check failed"), true, true);
- }
- }
}
// we're ready, user is authenticated and the request is safe
@@ -254,58 +268,57 @@ $RCMAIL->action = $plugin['action'];
// handle special actions
if ($RCMAIL->action == 'keep-alive') {
- $OUTPUT->reset();
- $RCMAIL->plugins->exec_hook('keep_alive', array());
- $OUTPUT->send();
+ $OUTPUT->reset();
+ $RCMAIL->plugins->exec_hook('keep_alive', array());
+ $OUTPUT->send();
}
else if ($RCMAIL->action == 'save-pref') {
- include INSTALL_PATH . 'program/steps/utils/save_pref.inc';
+ include INSTALL_PATH . 'program/steps/utils/save_pref.inc';
}
// include task specific functions
-if (is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/func.inc'))
- include_once $incfile;
+if (is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/func.inc')) {
+ include_once $incfile;
+}
// allow 5 "redirects" to another action
$redirects = 0; $incstep = null;
while ($redirects < 5) {
- // execute a plugin action
- if ($RCMAIL->plugins->is_plugin_task($RCMAIL->task)) {
- if (!$RCMAIL->action) $RCMAIL->action = 'index';
- $RCMAIL->plugins->exec_action($RCMAIL->task.'.'.$RCMAIL->action);
- break;
- }
- else if (preg_match('/^plugin\./', $RCMAIL->action)) {
- $RCMAIL->plugins->exec_action($RCMAIL->action);
- break;
- }
- // try to include the step file
- else if (($stepfile = $RCMAIL->get_action_file())
- && is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/'.$stepfile)
- ) {
- // include action file only once (in case it don't exit)
- include_once $incfile;
- $redirects++;
- }
- else {
- break;
- }
+ // execute a plugin action
+ if ($RCMAIL->plugins->is_plugin_task($RCMAIL->task)) {
+ if (!$RCMAIL->action) $RCMAIL->action = 'index';
+ $RCMAIL->plugins->exec_action($RCMAIL->task.'.'.$RCMAIL->action);
+ break;
+ }
+ else if (preg_match('/^plugin\./', $RCMAIL->action)) {
+ $RCMAIL->plugins->exec_action($RCMAIL->action);
+ break;
+ }
+ // try to include the step file
+ else if (($stepfile = $RCMAIL->get_action_file())
+ && is_file($incfile = INSTALL_PATH . 'program/steps/'.$RCMAIL->task.'/'.$stepfile)
+ ) {
+ // include action file only once (in case it don't exit)
+ include_once $incfile;
+ $redirects++;
+ }
+ else {
+ break;
+ }
}
if ($RCMAIL->action == 'refresh') {
- $RCMAIL->plugins->exec_hook('refresh', array('last' => intval(rcube_utils::get_input_value('_last', rcube_utils::INPUT_GPC))));
+ $RCMAIL->plugins->exec_hook('refresh', array('last' => intval(rcube_utils::get_input_value('_last', rcube_utils::INPUT_GPC))));
}
// parse main template (default)
$OUTPUT->send($RCMAIL->task);
-
// if we arrive here, something went wrong
rcmail::raise_error(array(
- 'code' => 404,
- 'type' => 'php',
- 'line' => __LINE__,
- 'file' => __FILE__,
- 'message' => "Invalid request"), true, true);
-
+ 'code' => 404,
+ 'type' => 'php',
+ 'line' => __LINE__,
+ 'file' => __FILE__,
+ 'message' => "Invalid request"), true, true);
diff --git a/program/include/clisetup.php b/program/include/clisetup.php
index 07e318521..47a40719a 100644
--- a/program/include/clisetup.php
+++ b/program/include/clisetup.php
@@ -20,7 +20,7 @@
*/
if (php_sapi_name() != 'cli') {
- die('Not on the "shell" (php-cli).');
+ die('Not on the "shell" (php-cli).');
}
require_once INSTALL_PATH . 'program/include/iniset.php';
diff --git a/program/include/iniset.php b/program/include/iniset.php
index 919cc7682..f6ad466da 100644
--- a/program/include/iniset.php
+++ b/program/include/iniset.php
@@ -84,4 +84,3 @@ function rcmail_autoload($classname)
return false;
}
-
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index e85d82cde..a927b7946 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -5,8 +5,8 @@
| program/include/rcmail.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2008-2012, The Roundcube Dev Team |
- | Copyright (C) 2011-2012, Kolab Systems AG |
+ | Copyright (C) 2008-2013, The Roundcube Dev Team |
+ | Copyright (C) 2011-2013, Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -21,7 +21,6 @@
+-----------------------------------------------------------------------+
*/
-
/**
* Application class of Roundcube Webmail
* implemented as singleton
@@ -30,616 +29,640 @@
*/
class rcmail extends rcube
{
- /**
- * Main tasks.
- *
- * @var array
- */
- static public $main_tasks = array('mail','settings','addressbook','login','logout','utils','dummy');
-
- /**
- * Current task.
- *
- * @var string
- */
- public $task;
-
- /**
- * Current action.
- *
- * @var string
- */
- public $action = '';
- public $comm_path = './';
- public $filename = '';
-
- private $address_books = array();
- private $action_map = array();
-
-
- 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
- *
- * @param string Environment name to run (e.g. live, dev, test)
- * @return rcmail The one and only instance
- */
- static function get_instance($env = '')
- {
- if (!self::$instance || !is_a(self::$instance, 'rcmail')) {
- self::$instance = new rcmail($env);
- self::$instance->startup(); // init AFTER object was linked with self::$instance
- }
+ /**
+ * Main tasks.
+ *
+ * @var array
+ */
+ static public $main_tasks = array('mail','settings','addressbook','login','logout','utils','dummy');
- return self::$instance;
- }
-
-
- /**
- * Initial startup function
- * to register session, create database and imap connections
- */
- protected function startup()
- {
- $this->init(self::INIT_WITH_DB | self::INIT_WITH_PLUGINS);
-
- // set filename if not index.php
- if (($basename = basename($_SERVER['SCRIPT_FILENAME'])) && $basename != 'index.php')
- $this->filename = $basename;
-
- // start session
- $this->session_init();
-
- // create user object
- $this->set_user(new rcube_user($_SESSION['user_id']));
-
- // set task and action properties
- $this->set_task(rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC));
- $this->action = asciiwords(rcube_utils::get_input_value('_action', rcube_utils::INPUT_GPC));
-
- // reset some session parameters when changing task
- if ($this->task != 'utils') {
- // we reset list page when switching to another task
- // but only to the main task interface - empty action (#1489076)
- // this will prevent from unintentional page reset on cross-task requests
- if ($this->session && $_SESSION['task'] != $this->task && empty($this->action))
- $this->session->remove('page');
- // set current task to session
- $_SESSION['task'] = $this->task;
- }
+ /**
+ * Current task.
+ *
+ * @var string
+ */
+ public $task;
- // init output class
- if (!empty($_REQUEST['_remote']))
- $GLOBALS['OUTPUT'] = $this->json_init();
- else
- $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
-
- // load plugins
- $this->plugins->init($this, $this->task);
- $this->plugins->load_plugins((array)$this->config->get('plugins', array()), array('filesystem_attachments', 'jqueryui'));
- }
-
-
- /**
- * Setter for application task
- *
- * @param string Task to set
- */
- public function set_task($task)
- {
- $task = asciiwords($task, true);
-
- if ($this->user && $this->user->ID)
- $task = !$task ? 'mail' : $task;
- else
- $task = 'login';
-
- $this->task = $task;
- $this->comm_path = $this->url(array('task' => $this->task));
-
- if ($this->output)
- $this->output->set_env('task', $this->task);
- }
-
-
- /**
- * Setter for system user object
- *
- * @param rcube_user Current user instance
- */
- public function set_user($user)
- {
- if (is_object($user)) {
- $this->user = $user;
-
- // overwrite config with user preferences
- $this->config->set_user_prefs((array)$this->user->get_prefs());
- }
+ /**
+ * Current action.
+ *
+ * @var string
+ */
+ public $action = '';
+ public $comm_path = './';
+ public $filename = '';
- $lang = $this->language_prop($this->config->get('language', $_SESSION['language']));
- $_SESSION['language'] = $this->user->language = $lang;
+ private $address_books = array();
+ private $action_map = array();
- // set localization
- setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8');
- // workaround for http://bugs.php.net/bug.php?id=18556
- if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
- setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8');
- }
- }
-
-
- /**
- * Return instance of the internal address book class
- *
- * @param string Address book identifier (-1 for default addressbook)
- * @param boolean True if the address book needs to be writeable
- *
- * @return rcube_contacts Address book object
- */
- public function get_address_book($id, $writeable = false)
- {
- $contacts = null;
- $ldap_config = (array)$this->config->get('ldap_public');
-
- // 'sql' is the alias for '0' used by autocomplete
- if ($id == 'sql')
- $id = '0';
- else if ($id == -1) {
- $id = $this->config->get('default_addressbook');
- $default = true;
- }
+ const ERROR_STORAGE = -2;
+ const ERROR_INVALID_REQUEST = 1;
+ const ERROR_INVALID_HOST = 2;
+ const ERROR_COOKIES_DISABLED = 3;
- // use existing instance
- if (isset($this->address_books[$id]) && ($this->address_books[$id] instanceof rcube_addressbook)) {
- $contacts = $this->address_books[$id];
- }
- else if ($id && $ldap_config[$id]) {
- $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $this->config->mail_domain($_SESSION['storage_host']));
- }
- else if ($id === '0') {
- $contacts = new rcube_contacts($this->db, $this->get_user_id());
- }
- else {
- $plugin = $this->plugins->exec_hook('addressbook_get', array('id' => $id, 'writeable' => $writeable));
- // plugin returned instance of a rcube_addressbook
- if ($plugin['instance'] instanceof rcube_addressbook) {
- $contacts = $plugin['instance'];
- }
- }
+ /**
+ * This implements the 'singleton' design pattern
+ *
+ * @param string Environment name to run (e.g. live, dev, test)
+ *
+ * @return rcmail The one and only instance
+ */
+ static function get_instance($env = '')
+ {
+ if (!self::$instance || !is_a(self::$instance, 'rcmail')) {
+ self::$instance = new rcmail($env);
+ // init AFTER object was linked with self::$instance
+ self::$instance->startup();
+ }
- // when user requested default writeable addressbook
- // we need to check if default is writeable, if not we
- // will return first writeable book (if any exist)
- if ($contacts && $default && $contacts->readonly && $writeable) {
- $contacts = null;
+ return self::$instance;
}
- // Get first addressbook from the list if configured default doesn't exist
- // This can happen when user deleted the addressbook (e.g. Kolab folder)
- if (!$contacts && (!$id || $default)) {
- $source = reset($this->get_address_sources($writeable, !$default));
- if (!empty($source)) {
- $contacts = $this->get_address_book($source['id']);
- if ($contacts) {
- $id = $source['id'];
+ /**
+ * Initial startup function
+ * to register session, create database and imap connections
+ */
+ protected function startup()
+ {
+ $this->init(self::INIT_WITH_DB | self::INIT_WITH_PLUGINS);
+
+ // set filename if not index.php
+ if (($basename = basename($_SERVER['SCRIPT_FILENAME'])) && $basename != 'index.php') {
+ $this->filename = $basename;
}
- }
- }
- if (!$contacts) {
- // there's no default, just return
- if ($default) {
- return null;
- }
-
- self::raise_error(array(
- 'code' => 700, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Addressbook source ($id) not found!"),
- true, true);
- }
+ // start session
+ $this->session_init();
- // add to the 'books' array for shutdown function
- $this->address_books[$id] = $contacts;
+ // create user object
+ $this->set_user(new rcube_user($_SESSION['user_id']));
- if ($writeable && $contacts->readonly) {
- return null;
- }
+ // set task and action properties
+ $this->set_task(rcube_utils::get_input_value('_task', rcube_utils::INPUT_GPC));
+ $this->action = asciiwords(rcube_utils::get_input_value('_action', rcube_utils::INPUT_GPC));
- // set configured sort order
- if ($sort_col = $this->config->get('addressbook_sort_col')) {
- $contacts->set_sort_order($sort_col);
- }
+ // reset some session parameters when changing task
+ if ($this->task != 'utils') {
+ // we reset list page when switching to another task
+ // but only to the main task interface - empty action (#1489076)
+ // this will prevent from unintentional page reset on cross-task requests
+ if ($this->session && $_SESSION['task'] != $this->task && empty($this->action)) {
+ $this->session->remove('page');
+ }
- return $contacts;
- }
-
-
- /**
- * Return identifier of the address book object
- *
- * @param rcube_addressbook Addressbook source object
- *
- * @return string Source identifier
- */
- public function get_address_book_id($object)
- {
- foreach ($this->address_books as $index => $book) {
- if ($book === $object) {
- return $index;
- }
- }
- }
-
-
- /**
- * Return address books list
- *
- * @param boolean True if the address book needs to be writeable
- * @param boolean True if the address book needs to be not hidden
- *
- * @return array Address books array
- */
- public function get_address_sources($writeable = false, $skip_hidden = false)
- {
- $abook_type = (string) $this->config->get('address_book_type');
- $ldap_config = (array) $this->config->get('ldap_public');
- $autocomplete = (array) $this->config->get('autocomplete_addressbooks');
- $list = array();
-
- // We are using the DB address book or a plugin address book
- if (!empty($abook_type) && strtolower($abook_type) != 'ldap') {
- if (!isset($this->address_books['0']))
- $this->address_books['0'] = new rcube_contacts($this->db, $this->get_user_id());
- $list['0'] = array(
- 'id' => '0',
- 'name' => $this->gettext('personaladrbook'),
- 'groups' => $this->address_books['0']->groups,
- 'readonly' => $this->address_books['0']->readonly,
- 'autocomplete' => in_array('sql', $autocomplete),
- 'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
- );
- }
+ // set current task to session
+ $_SESSION['task'] = $this->task;
+ }
- if (!empty($ldap_config)) {
- foreach ($ldap_config as $id => $prop) {
- // handle misconfiguration
- if (empty($prop) || !is_array($prop)) {
- continue;
- }
- $list[$id] = array(
- 'id' => $id,
- 'name' => html::quote($prop['name']),
- 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']),
- 'readonly' => !$prop['writable'],
- 'hidden' => $prop['hidden'],
- 'autocomplete' => in_array($id, $autocomplete)
- );
- }
- }
+ // init output class
+ if (!empty($_REQUEST['_remote']))
+ $GLOBALS['OUTPUT'] = $this->json_init();
+ else
+ $GLOBALS['OUTPUT'] = $this->load_gui(!empty($_REQUEST['_framed']));
- $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list));
- $list = $plugin['sources'];
-
- foreach ($list as $idx => $item) {
- // register source for shutdown function
- if (!is_object($this->address_books[$item['id']])) {
- $this->address_books[$item['id']] = $item;
- }
- // remove from list if not writeable as requested
- if ($writeable && $item['readonly']) {
- unset($list[$idx]);
- }
- // remove from list if hidden as requested
- else if ($skip_hidden && $item['hidden']) {
- unset($list[$idx]);
- }
+ // load plugins
+ $this->plugins->init($this, $this->task);
+ $this->plugins->load_plugins((array)$this->config->get('plugins', array()),
+ array('filesystem_attachments', 'jqueryui'));
}
- return $list;
- }
-
- /**
- * Getter for compose responses.
- * These are stored in local config and user preferences.
- *
- * @param boolean True to sort the list alphabetically
- * @param boolean True if only this user's responses shall be listed
- * @return array List of the current user's stored responses
- */
- public function get_compose_responses($sorted = false, $user_only = false)
- {
- $responses = array();
-
- if (!$user_only) {
- foreach ($this->config->get('compose_responses_static', array()) as $response) {
- if (empty($response['key']))
- $response['key'] = substr(md5($response['name']), 0, 16);
- $response['static'] = true;
- $response['class'] = 'readonly';
- $k = $sorted ? '0000-' . strtolower($response['name']) : $response['key'];
- $responses[$k] = $response;
- }
- }
+ /**
+ * Setter for application task
+ *
+ * @param string Task to set
+ */
+ public function set_task($task)
+ {
+ $task = asciiwords($task, true);
- foreach ($this->config->get('compose_responses', array()) as $response) {
- if (empty($response['key']))
- $response['key'] = substr(md5($response['name']), 0, 16);
- $k = $sorted ? strtolower($response['name']) : $response['key'];
- $responses[$k] = $response;
- }
+ if ($this->user && $this->user->ID)
+ $task = !$task ? 'mail' : $task;
+ else
+ $task = 'login';
- // sort list by name
- if ($sorted) {
- ksort($responses, SORT_LOCALE_STRING);
- }
+ $this->task = $task;
+ $this->comm_path = $this->url(array('task' => $this->task));
- return array_values($responses);
- }
-
-
- /**
- * Init output object for GUI and add common scripts.
- * This will instantiate a rcmail_output_html object and set
- * environment vars according to the current session and configuration
- *
- * @param boolean True if this request is loaded in a (i)frame
- * @return rcube_output Reference to HTML output object
- */
- public function load_gui($framed = false)
- {
- // init output page
- if (!($this->output instanceof rcmail_output_html))
- $this->output = new rcmail_output_html($this->task, $framed);
-
- // set refresh interval
- $this->output->set_env('refresh_interval', $this->config->get('refresh_interval', 0));
- $this->output->set_env('session_lifetime', $this->config->get('session_lifetime', 0) * 60);
-
- if ($framed) {
- $this->comm_path .= '&_framed=1';
- $this->output->set_env('framed', true);
+ if ($this->output) {
+ $this->output->set_env('task', $this->task);
+ }
}
- $this->output->set_env('task', $this->task);
- $this->output->set_env('action', $this->action);
- $this->output->set_env('comm_path', $this->comm_path);
- $this->output->set_charset(RCUBE_CHARSET);
-
- if ($this->user && $this->user->ID)
- $this->output->set_env('user_id', $this->user->get_hash());
-
- // add some basic labels to client
- $this->output->add_label('loading', 'servererror', 'requesttimedout', 'refreshing');
-
- return $this->output;
- }
-
-
- /**
- * Create an output object for JSON responses
- *
- * @return rcube_output Reference to JSON output object
- */
- public function json_init()
- {
- if (!($this->output instanceof rcmail_output_json))
- $this->output = new rcmail_output_json($this->task);
-
- return $this->output;
- }
-
-
- /**
- * Create session object and start the session.
- */
- public function session_init()
- {
- parent::session_init();
-
- // set initial session vars
- if (!$_SESSION['user_id'])
- $_SESSION['temp'] = true;
-
- // restore skin selection after logout
- if ($_SESSION['temp'] && !empty($_SESSION['skin']))
- $this->config->set('skin', $_SESSION['skin']);
- }
-
-
- /**
- * Perfom login to the mail server and to the webmail service.
- * This will also create a new user entry if auto_create_user is configured.
- *
- * @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, $cookiecheck = false)
- {
- $this->login_error = null;
-
- if (empty($username)) {
- return false;
- }
+ /**
+ * Setter for system user object
+ *
+ * @param rcube_user Current user instance
+ */
+ public function set_user($user)
+ {
+ if (is_object($user)) {
+ $this->user = $user;
- if ($cookiecheck && empty($_COOKIE)) {
- $this->login_error = self::ERROR_COOKIES_DISABLED;
- return false;
- }
+ // overwrite config with user preferences
+ $this->config->set_user_prefs((array)$this->user->get_prefs());
+ }
- $config = $this->config->all();
-
- if (!$host)
- $host = $config['default_host'];
-
- // Validate that selected host is in the list of configured hosts
- if (is_array($config['default_host'])) {
- $allowed = false;
- foreach ($config['default_host'] as $key => $host_allowed) {
- if (!is_numeric($key))
- $host_allowed = $key;
- if ($host == $host_allowed) {
- $allowed = true;
- break;
- }
- }
- if (!$allowed) {
- $host = null;
- }
- }
- else if (!empty($config['default_host']) && $host != rcube_utils::parse_host($config['default_host'])) {
- $host = null;
- }
+ $lang = $this->language_prop($this->config->get('language', $_SESSION['language']));
+ $_SESSION['language'] = $this->user->language = $lang;
- if (!$host) {
- $this->login_error = self::ERROR_INVALID_HOST;
- return false;
- }
+ // set localization
+ setlocale(LC_ALL, $lang . '.utf8', $lang . '.UTF-8', 'en_US.utf8', 'en_US.UTF-8');
- // parse $host URL
- $a_host = parse_url($host);
- if ($a_host['host']) {
- $host = $a_host['host'];
- $ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
- if (!empty($a_host['port']))
- $port = $a_host['port'];
- else if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143))
- $port = 993;
+ // workaround for http://bugs.php.net/bug.php?id=18556
+ if (version_compare(PHP_VERSION, '5.5.0', '<') && in_array($lang, array('tr_TR', 'ku', 'az_AZ'))) {
+ setlocale(LC_CTYPE, 'en_US.utf8', 'en_US.UTF-8');
+ }
}
- if (!$port) {
- $port = $config['default_port'];
- }
+ /**
+ * Return instance of the internal address book class
+ *
+ * @param string Address book identifier (-1 for default addressbook)
+ * @param boolean True if the address book needs to be writeable
+ *
+ * @return rcube_contacts Address book object
+ */
+ public function get_address_book($id, $writeable = false)
+ {
+ $contacts = null;
+ $ldap_config = (array)$this->config->get('ldap_public');
+
+ // 'sql' is the alias for '0' used by autocomplete
+ if ($id == 'sql')
+ $id = '0';
+ else if ($id == -1) {
+ $id = $this->config->get('default_addressbook');
+ $default = true;
+ }
- // Check if we need to add/force domain to username
- if (!empty($config['username_domain'])) {
- $domain = is_array($config['username_domain']) ? $config['username_domain'][$host] : $config['username_domain'];
+ // use existing instance
+ if (isset($this->address_books[$id]) && ($this->address_books[$id] instanceof rcube_addressbook)) {
+ $contacts = $this->address_books[$id];
+ }
+ else if ($id && $ldap_config[$id]) {
+ $domain = $this->config->mail_domain($_SESSION['storage_host']);
+ $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $domain);
+ }
+ else if ($id === '0') {
+ $contacts = new rcube_contacts($this->db, $this->get_user_id());
+ }
+ else {
+ $plugin = $this->plugins->exec_hook('addressbook_get', array('id' => $id, 'writeable' => $writeable));
- if ($domain = rcube_utils::parse_host((string)$domain, $host)) {
- $pos = strpos($username, '@');
+ // plugin returned instance of a rcube_addressbook
+ if ($plugin['instance'] instanceof rcube_addressbook) {
+ $contacts = $plugin['instance'];
+ }
+ }
- // force configured domains
- if (!empty($config['username_domain_forced']) && $pos !== false) {
- $username = substr($username, 0, $pos) . '@' . $domain;
+ // when user requested default writeable addressbook
+ // we need to check if default is writeable, if not we
+ // will return first writeable book (if any exist)
+ if ($contacts && $default && $contacts->readonly && $writeable) {
+ $contacts = null;
}
- // just add domain if not specified
- else if ($pos === false) {
- $username .= '@' . $domain;
+
+ // Get first addressbook from the list if configured default doesn't exist
+ // This can happen when user deleted the addressbook (e.g. Kolab folder)
+ if (!$contacts && (!$id || $default)) {
+ $source = reset($this->get_address_sources($writeable, !$default));
+ if (!empty($source)) {
+ $contacts = $this->get_address_book($source['id']);
+ if ($contacts) {
+ $id = $source['id'];
+ }
+ }
}
- }
- }
- if (!isset($config['login_lc'])) {
- $config['login_lc'] = 2; // default
- }
+ if (!$contacts) {
+ // there's no default, just return
+ if ($default) {
+ return null;
+ }
+
+ self::raise_error(array(
+ 'code' => 700,
+ 'file' => __FILE__,
+ 'line' => __LINE__,
+ 'message' => "Addressbook source ($id) not found!"
+ ),
+ true, true);
+ }
+
+ // add to the 'books' array for shutdown function
+ $this->address_books[$id] = $contacts;
+
+ if ($writeable && $contacts->readonly) {
+ return null;
+ }
- // Convert username to lowercase. If storage backend
- // is case-insensitive we need to store always the same username (#1487113)
- if ($config['login_lc']) {
- 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);
- }
+ // set configured sort order
+ if ($sort_col = $this->config->get('addressbook_sort_col')) {
+ $contacts->set_sort_order($sort_col);
+ }
+
+ return $contacts;
}
- // try to resolve email address from virtuser table
- if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) {
- $username = $virtuser;
+ /**
+ * Return identifier of the address book object
+ *
+ * @param rcube_addressbook Addressbook source object
+ *
+ * @return string Source identifier
+ */
+ public function get_address_book_id($object)
+ {
+ foreach ($this->address_books as $index => $book) {
+ if ($book === $object) {
+ return $index;
+ }
+ }
}
- // Here we need IDNA ASCII
- // Only rcube_contacts class is using domain names in Unicode
- $host = rcube_utils::idn_to_ascii($host);
- $username = rcube_utils::idn_to_ascii($username);
+ /**
+ * Return address books list
+ *
+ * @param boolean True if the address book needs to be writeable
+ * @param boolean True if the address book needs to be not hidden
+ *
+ * @return array Address books array
+ */
+ public function get_address_sources($writeable = false, $skip_hidden = false)
+ {
+ $abook_type = (string) $this->config->get('address_book_type');
+ $ldap_config = (array) $this->config->get('ldap_public');
+ $autocomplete = (array) $this->config->get('autocomplete_addressbooks');
+ $list = array();
+
+ // We are using the DB address book or a plugin address book
+ if (!empty($abook_type) && strtolower($abook_type) != 'ldap') {
+ if (!isset($this->address_books['0'])) {
+ $this->address_books['0'] = new rcube_contacts($this->db, $this->get_user_id());
+ }
+
+ $list['0'] = array(
+ 'id' => '0',
+ 'name' => $this->gettext('personaladrbook'),
+ 'groups' => $this->address_books['0']->groups,
+ 'readonly' => $this->address_books['0']->readonly,
+ 'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'),
+ 'autocomplete' => in_array('sql', $autocomplete),
+ );
+ }
+
+ if (!empty($ldap_config)) {
+ foreach ($ldap_config as $id => $prop) {
+ // handle misconfiguration
+ if (empty($prop) || !is_array($prop)) {
+ continue;
+ }
+
+ $list[$id] = array(
+ 'id' => $id,
+ 'name' => html::quote($prop['name']),
+ 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']),
+ 'readonly' => !$prop['writable'],
+ 'hidden' => $prop['hidden'],
+ 'autocomplete' => in_array($id, $autocomplete)
+ );
+ }
+ }
+
+ $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list));
+ $list = $plugin['sources'];
+
+ foreach ($list as $idx => $item) {
+ // register source for shutdown function
+ if (!is_object($this->address_books[$item['id']])) {
+ $this->address_books[$item['id']] = $item;
+ }
+ // remove from list if not writeable as requested
+ if ($writeable && $item['readonly']) {
+ unset($list[$idx]);
+ }
+ // remove from list if hidden as requested
+ else if ($skip_hidden && $item['hidden']) {
+ unset($list[$idx]);
+ }
+ }
- // user already registered -> overwrite username
- if ($user = rcube_user::query($username, $host)) {
- $username = $user->data['username'];
+ return $list;
}
- $storage = $this->get_storage();
+ /**
+ * Getter for compose responses.
+ * These are stored in local config and user preferences.
+ *
+ * @param boolean True to sort the list alphabetically
+ * @param boolean True if only this user's responses shall be listed
+ *
+ * @return array List of the current user's stored responses
+ */
+ public function get_compose_responses($sorted = false, $user_only = false)
+ {
+ $responses = array();
+
+ if (!$user_only) {
+ foreach ($this->config->get('compose_responses_static', array()) as $response) {
+ if (empty($response['key'])) {
+ $response['key'] = substr(md5($response['name']), 0, 16);
+ }
+
+ $response['static'] = true;
+ $response['class'] = 'readonly';
- // try to log in
- if (!$storage->connect($host, $username, $pass, $port, $ssl)) {
- return false;
+ $k = $sorted ? '0000-' . strtolower($response['name']) : $response['key'];
+ $responses[$k] = $response;
+ }
+ }
+
+ foreach ($this->config->get('compose_responses', array()) as $response) {
+ if (empty($response['key'])) {
+ $response['key'] = substr(md5($response['name']), 0, 16);
+ }
+
+ $k = $sorted ? strtolower($response['name']) : $response['key'];
+ $responses[$k] = $response;
+ }
+
+ // sort list by name
+ if ($sorted) {
+ ksort($responses, SORT_LOCALE_STRING);
+ }
+
+ return array_values($responses);
}
- // user already registered -> update user's record
- if (is_object($user)) {
- // update last login timestamp
- $user->touch();
+ /**
+ * Init output object for GUI and add common scripts.
+ * This will instantiate a rcmail_output_html object and set
+ * environment vars according to the current session and configuration
+ *
+ * @param boolean True if this request is loaded in a (i)frame
+ *
+ * @return rcube_output Reference to HTML output object
+ */
+ public function load_gui($framed = false)
+ {
+ // init output page
+ if (!($this->output instanceof rcmail_output_html)) {
+ $this->output = new rcmail_output_html($this->task, $framed);
+ }
+
+ // set refresh interval
+ $this->output->set_env('refresh_interval', $this->config->get('refresh_interval', 0));
+ $this->output->set_env('session_lifetime', $this->config->get('session_lifetime', 0) * 60);
+
+ if ($framed) {
+ $this->comm_path .= '&_framed=1';
+ $this->output->set_env('framed', true);
+ }
+
+ $this->output->set_env('task', $this->task);
+ $this->output->set_env('action', $this->action);
+ $this->output->set_env('comm_path', $this->comm_path);
+ $this->output->set_charset(RCUBE_CHARSET);
+
+ if ($this->user && $this->user->ID) {
+ $this->output->set_env('user_id', $this->user->get_hash());
+ }
+
+ // add some basic labels to client
+ $this->output->add_label('loading', 'servererror', 'requesttimedout', 'refreshing');
+
+ return $this->output;
}
- // create new system user
- else if ($config['auto_create_user']) {
- if ($created = rcube_user::create($username, $host)) {
- $user = $created;
- }
- else {
- self::raise_error(array(
- 'code' => 620, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Failed to create a user record. Maybe aborted by a plugin?"
- ), true, false);
- }
+
+ /**
+ * Create an output object for JSON responses
+ *
+ * @return rcube_output Reference to JSON output object
+ */
+ public function json_init()
+ {
+ if (!($this->output instanceof rcmail_output_json)) {
+ $this->output = new rcmail_output_json($this->task);
+ }
+
+ return $this->output;
}
- else {
- self::raise_error(array(
- 'code' => 621, 'type' => 'php',
- 'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Access denied for new user $username. 'auto_create_user' is disabled"
- ), true, false);
+
+ /**
+ * Create session object and start the session.
+ */
+ public function session_init()
+ {
+ parent::session_init();
+
+ // set initial session vars
+ if (!$_SESSION['user_id']) {
+ $_SESSION['temp'] = true;
+ }
+
+ // restore skin selection after logout
+ if ($_SESSION['temp'] && !empty($_SESSION['skin'])) {
+ $this->config->set('skin', $_SESSION['skin']);
+ }
}
- // login succeeded
- if (is_object($user) && $user->ID) {
- // Configure environment
- $this->set_user($user);
- $this->set_storage_prop();
+ /**
+ * Perfom login to the mail server and to the webmail service.
+ * This will also create a new user entry if auto_create_user is configured.
+ *
+ * @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, $cookiecheck = false)
+ {
+ $this->login_error = null;
+
+ if (empty($username)) {
+ return false;
+ }
- // fix some old settings according to namespace prefix
- $this->fix_namespace_settings($user);
+ if ($cookiecheck && empty($_COOKIE)) {
+ $this->login_error = self::ERROR_COOKIES_DISABLED;
+ return false;
+ }
- // create default folders on first login
- if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) {
- $storage->create_default_folders();
- }
+ $config = $this->config->all();
- // set session vars
- $_SESSION['user_id'] = $user->ID;
- $_SESSION['username'] = $user->data['username'];
- $_SESSION['storage_host'] = $host;
- $_SESSION['storage_port'] = $port;
- $_SESSION['storage_ssl'] = $ssl;
- $_SESSION['password'] = $this->encrypt($pass);
- $_SESSION['login_time'] = time();
+ if (!$host) {
+ $host = $config['default_host'];
+ }
- if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_')
- $_SESSION['timezone'] = rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_GPC);
+ // Validate that selected host is in the list of configured hosts
+ if (is_array($config['default_host'])) {
+ $allowed = false;
- // force reloading complete list of subscribed mailboxes
- $storage->clear_cache('mailboxes', true);
+ foreach ($config['default_host'] as $key => $host_allowed) {
+ if (!is_numeric($key)) {
+ $host_allowed = $key;
+ }
+ if ($host == $host_allowed) {
+ $allowed = true;
+ break;
+ }
+ }
- return true;
- }
+ if (!$allowed) {
+ $host = null;
+ }
+ }
+ else if (!empty($config['default_host']) && $host != rcube_utils::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);
+ if ($a_host['host']) {
+ $host = $a_host['host'];
+ $ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? $a_host['scheme'] : null;
+
+ if (!empty($a_host['port']))
+ $port = $a_host['port'];
+ else if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143))
+ $port = 993;
+ }
+
+ if (!$port) {
+ $port = $config['default_port'];
+ }
+
+ // Check if we need to add/force domain to username
+ if (!empty($config['username_domain'])) {
+ $domain = is_array($config['username_domain']) ? $config['username_domain'][$host] : $config['username_domain'];
+
+ if ($domain = rcube_utils::parse_host((string)$domain, $host)) {
+ $pos = strpos($username, '@');
+
+ // force configured domains
+ if (!empty($config['username_domain_forced']) && $pos !== false) {
+ $username = substr($username, 0, $pos) . '@' . $domain;
+ }
+ // just add domain if not specified
+ else if ($pos === false) {
+ $username .= '@' . $domain;
+ }
+ }
+ }
+
+ if (!isset($config['login_lc'])) {
+ $config['login_lc'] = 2; // default
+ }
+
+ // Convert username to lowercase. If storage backend
+ // is case-insensitive we need to store always the same username (#1487113)
+ if ($config['login_lc']) {
+ 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
+ if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) {
+ $username = $virtuser;
+ }
+
+ // Here we need IDNA ASCII
+ // Only rcube_contacts class is using domain names in Unicode
+ $host = rcube_utils::idn_to_ascii($host);
+ $username = rcube_utils::idn_to_ascii($username);
- return false;
- }
+ // user already registered -> overwrite username
+ if ($user = rcube_user::query($username, $host)) {
+ $username = $user->data['username'];
+ }
+
+ $storage = $this->get_storage();
+
+ // try to log in
+ if (!$storage->connect($host, $username, $pass, $port, $ssl)) {
+ return false;
+ }
+
+ // user already registered -> update user's record
+ if (is_object($user)) {
+ // update last login timestamp
+ $user->touch();
+ }
+ // create new system user
+ else if ($config['auto_create_user']) {
+ if ($created = rcube_user::create($username, $host)) {
+ $user = $created;
+ }
+ else {
+ self::raise_error(array(
+ 'code' => 620,
+ 'file' => __FILE__,
+ 'line' => __LINE__,
+ 'message' => "Failed to create a user record. Maybe aborted by a plugin?"
+ ),
+ true, false);
+ }
+ }
+ else {
+ self::raise_error(array(
+ 'code' => 621,
+ 'file' => __FILE__,
+ 'line' => __LINE__,
+ 'message' => "Access denied for new user $username. 'auto_create_user' is disabled"
+ ),
+ true, false);
+ }
+
+ // login succeeded
+ if (is_object($user) && $user->ID) {
+ // Configure environment
+ $this->set_user($user);
+ $this->set_storage_prop();
+
+ // 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']))) {
+ $storage->create_default_folders();
+ }
+
+ // set session vars
+ $_SESSION['user_id'] = $user->ID;
+ $_SESSION['username'] = $user->data['username'];
+ $_SESSION['storage_host'] = $host;
+ $_SESSION['storage_port'] = $port;
+ $_SESSION['storage_ssl'] = $ssl;
+ $_SESSION['password'] = $this->encrypt($pass);
+ $_SESSION['login_time'] = time();
+
+ if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') {
+ $_SESSION['timezone'] = rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_GPC);
+ }
+
+ // force reloading complete list of subscribed mailboxes
+ $storage->clear_cache('mailboxes', true);
+ return true;
+ }
+
+ return false;
+ }
/**
* Returns error code of last login operation
@@ -657,315 +680,317 @@ class rcmail extends rcube
}
}
+ /**
+ * Auto-select IMAP host based on the posted login information
+ *
+ * @return string Selected IMAP host
+ */
+ public function autoselect_host()
+ {
+ $default_host = $this->config->get('default_host');
+ $host = null;
+
+ if (is_array($default_host)) {
+ $post_host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST);
+ $post_user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST);
- /**
- * Auto-select IMAP host based on the posted login information
- *
- * @return string Selected IMAP host
- */
- public function autoselect_host()
- {
- $default_host = $this->config->get('default_host');
- $host = null;
-
- if (is_array($default_host)) {
- $post_host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST);
- $post_user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST);
-
- list(, $domain) = explode('@', $post_user);
-
- // direct match in default_host array
- if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) {
- $host = $post_host;
- }
- // try to select host by mail 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;
- break;
- }
- else if (stripos($storage_host, $domain) !== false || stripos(strval($mail_domains), $domain) !== false) {
- $host = is_numeric($storage_host) ? $mail_domains : $storage_host;
- break;
- }
+ list(, $domain) = explode('@', $post_user);
+
+ // direct match in default_host array
+ if ($default_host[$post_host] || in_array($post_host, array_values($default_host))) {
+ $host = $post_host;
+ }
+ // try to select host by mail 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;
+ break;
+ }
+ else if (stripos($storage_host, $domain) !== false || stripos(strval($mail_domains), $domain) !== false) {
+ $host = is_numeric($storage_host) ? $mail_domains : $storage_host;
+ break;
+ }
+ }
+ }
+
+ // take the first entry if $host is still not set
+ if (empty($host)) {
+ list($key, $val) = each($default_host);
+ $host = is_numeric($key) ? $val : $key;
+ }
+ }
+ else if (empty($default_host)) {
+ $host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST);
+ }
+ else {
+ $host = rcube_utils::parse_host($default_host);
}
- }
- // take the first entry if $host is still not set
- if (empty($host)) {
- list($key, $val) = each($default_host);
- $host = is_numeric($key) ? $val : $key;
- }
+ return $host;
}
- else if (empty($default_host)) {
- $host = rcube_utils::get_input_value('_host', rcube_utils::INPUT_POST);
+
+ /**
+ * Destroy session data and remove cookie
+ */
+ public function kill_session()
+ {
+ $this->plugins->exec_hook('session_destroy');
+
+ $this->session->kill();
+ $_SESSION = array('language' => $this->user->language, 'temp' => true, 'skin' => $this->config->get('skin'));
+ $this->user->reset();
}
- else
- $host = rcube_utils::parse_host($default_host);
- return $host;
- }
+ /**
+ * Do server side actions on logout
+ */
+ public function logout_actions()
+ {
+ $config = $this->config->all();
+ $storage = $this->get_storage();
+
+ if ($config['logout_purge'] && !empty($config['trash_mbox'])) {
+ $storage->clear_folder($config['trash_mbox']);
+ }
+ if ($config['logout_expunge']) {
+ $storage->expunge_folder('INBOX');
+ }
- /**
- * Destroy session data and remove cookie
- */
- public function kill_session()
- {
- $this->plugins->exec_hook('session_destroy');
+ // Try to save unsaved user preferences
+ if (!empty($_SESSION['preferences'])) {
+ $this->user->save_prefs(unserialize($_SESSION['preferences']));
+ }
+ }
- $this->session->kill();
- $_SESSION = array('language' => $this->user->language, 'temp' => true, 'skin' => $this->config->get('skin'));
- $this->user->reset();
- }
+ /**
+ * Generate a unique token to be used in a form request
+ *
+ * @return string The request token
+ */
+ public function get_request_token()
+ {
+ $sess_id = $_COOKIE[ini_get('session.name')];
+ if (!$sess_id) {
+ $sess_id = session_id();
+ }
- /**
- * Do server side actions on logout
- */
- public function logout_actions()
- {
- $config = $this->config->all();
- $storage = $this->get_storage();
+ $plugin = $this->plugins->exec_hook('request_token', array(
+ 'value' => md5('RT' . $this->get_user_id() . $this->config->get('des_key') . $sess_id)));
- if ($config['logout_purge'] && !empty($config['trash_mbox'])) {
- $storage->clear_folder($config['trash_mbox']);
+ return $plugin['value'];
}
- if ($config['logout_expunge']) {
- $storage->expunge_folder('INBOX');
- }
+ /**
+ * Check if the current request contains a valid token
+ *
+ * @param int Request method
+ *
+ * @return boolean True if request token is valid false if not
+ */
+ public function check_request($mode = rcube_utils::INPUT_POST)
+ {
+ $token = rcube_utils::get_input_value('_token', $mode);
+ $sess_id = $_COOKIE[ini_get('session.name')];
- // Try to save unsaved user preferences
- if (!empty($_SESSION['preferences'])) {
- $this->user->save_prefs(unserialize($_SESSION['preferences']));
- }
- }
-
-
- /**
- * Generate a unique token to be used in a form request
- *
- * @return string The request token
- */
- public function get_request_token()
- {
- $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->get_user_id() . $this->config->get('des_key') . $sess_id)));
-
- return $plugin['value'];
- }
-
-
- /**
- * Check if the current request contains a valid token
- *
- * @param int Request method
- * @return boolean True if request token is valid false if not
- */
- public function check_request($mode = rcube_utils::INPUT_POST)
- {
- $token = rcube_utils::get_input_value('_token', $mode);
- $sess_id = $_COOKIE[ini_get('session.name')];
- return !empty($sess_id) && $token == $this->get_request_token();
- }
-
-
- /**
- * Build a valid URL to this instance of Roundcube
- *
- * @param mixed Either a string with the action or url parameters as key-value pairs
- *
- * @return string Valid application URL
- */
- public function url($p)
- {
- if (!is_array($p)) {
- if (strpos($p, 'http') === 0)
- return $p;
-
- $p = array('_action' => @func_get_arg(0));
+ return !empty($sess_id) && $token == $this->get_request_token();
}
- $task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task);
- $p['_task'] = $task;
- unset($p['task']);
-
- $url = './' . $this->filename;
- $delm = '?';
- foreach (array_reverse($p) as $key => $val) {
- if ($val !== '' && $val !== null) {
- $par = $key[0] == '_' ? $key : '_'.$key;
- $url .= $delm.urlencode($par).'='.urlencode($val);
- $delm = '&';
- }
- }
- return $url;
- }
+ /**
+ * Build a valid URL to this instance of Roundcube
+ *
+ * @param mixed Either a string with the action or url parameters as key-value pairs
+ *
+ * @return string Valid application URL
+ */
+ public function url($p)
+ {
+ if (!is_array($p)) {
+ if (strpos($p, 'http') === 0) {
+ return $p;
+ }
+ $p = array('_action' => @func_get_arg(0));
+ }
- /**
- * Function to be executed in script shutdown
- */
- public function shutdown()
- {
- parent::shutdown();
+ $task = $p['_task'] ? $p['_task'] : ($p['task'] ? $p['task'] : $this->task);
+ $p['_task'] = $task;
+ unset($p['task']);
- foreach ($this->address_books as $book) {
- if (is_object($book) && is_a($book, 'rcube_addressbook'))
- $book->close();
- }
+ $url = './' . $this->filename;
+ $delm = '?';
- // write performance stats to logs/console
- if ($this->config->get('devel_mode')) {
- if (function_exists('memory_get_usage'))
- $mem = $this->show_bytes(memory_get_usage());
- if (function_exists('memory_get_peak_usage'))
- $mem .= '/'.$this->show_bytes(memory_get_peak_usage());
-
- $log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : '');
- if (defined('RCMAIL_START'))
- self::print_timer(RCMAIL_START, $log);
- else
- self::console($log);
- }
- }
-
-
- /**
- * Registers action aliases for current task
- *
- * @param array $map Alias-to-filename hash array
- */
- public function register_action_map($map)
- {
- if (is_array($map)) {
- foreach ($map as $idx => $val) {
- $this->action_map[$idx] = $val;
- }
- }
- }
-
-
- /**
- * Returns current action filename
- *
- * @param array $map Alias-to-filename hash array
- */
- public function get_action_file()
- {
- if (!empty($this->action_map[$this->action])) {
- return $this->action_map[$this->action];
+ foreach (array_reverse($p) as $key => $val) {
+ if ($val !== '' && $val !== null) {
+ $par = $key[0] == '_' ? $key : '_'.$key;
+ $url .= $delm.urlencode($par).'='.urlencode($val);
+ $delm = '&';
+ }
+ }
+
+ return $url;
}
- return strtr($this->action, '-', '_') . '.inc';
- }
-
-
- /**
- * Fixes some user preferences according to namespace handling change.
- * Old Roundcube versions were using folder names with removed namespace prefix.
- * Now we need to add the prefix on servers where personal namespace has prefix.
- *
- * @param rcube_user $user User object
- */
- private function fix_namespace_settings($user)
- {
- $prefix = $this->storage->get_namespace('prefix');
- $prefix_len = strlen($prefix);
-
- if (!$prefix_len)
- return;
-
- $prefs = $this->config->all();
- if (!empty($prefs['namespace_fixed']))
- return;
-
- // Build namespace prefix regexp
- $ns = $this->storage->get_namespace();
- $regexp = array();
-
- foreach ($ns as $entry) {
- if (!empty($entry)) {
- foreach ($entry as $item) {
- if (strlen($item[0])) {
- $regexp[] = preg_quote($item[0], '/');
- }
+ /**
+ * Function to be executed in script shutdown
+ */
+ public function shutdown()
+ {
+ parent::shutdown();
+
+ foreach ($this->address_books as $book) {
+ if (is_object($book) && is_a($book, 'rcube_addressbook'))
+ $book->close();
}
- }
- }
- $regexp = '/^('. implode('|', $regexp).')/';
- // Fix preferences
- $opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
- foreach ($opts as $opt) {
- if ($value = $prefs[$opt]) {
- if ($value != 'INBOX' && !preg_match($regexp, $value)) {
- $prefs[$opt] = $prefix.$value;
+ // write performance stats to logs/console
+ if ($this->config->get('devel_mode')) {
+ if (function_exists('memory_get_usage'))
+ $mem = $this->show_bytes(memory_get_usage());
+ if (function_exists('memory_get_peak_usage'))
+ $mem .= '/'.$this->show_bytes(memory_get_peak_usage());
+
+ $log = $this->task . ($this->action ? '/'.$this->action : '') . ($mem ? " [$mem]" : '');
+
+ if (defined('RCMAIL_START'))
+ self::print_timer(RCMAIL_START, $log);
+ else
+ self::console($log);
}
- }
}
- if (!empty($prefs['default_folders'])) {
- foreach ($prefs['default_folders'] as $idx => $name) {
- if ($name != 'INBOX' && !preg_match($regexp, $name)) {
- $prefs['default_folders'][$idx] = $prefix.$name;
+ /**
+ * Registers action aliases for current task
+ *
+ * @param array $map Alias-to-filename hash array
+ */
+ public function register_action_map($map)
+ {
+ if (is_array($map)) {
+ foreach ($map as $idx => $val) {
+ $this->action_map[$idx] = $val;
+ }
}
- }
}
- if (!empty($prefs['search_mods'])) {
- $folders = array();
- foreach ($prefs['search_mods'] as $idx => $value) {
- if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
- $idx = $prefix.$idx;
+ /**
+ * Returns current action filename
+ *
+ * @param array $map Alias-to-filename hash array
+ */
+ public function get_action_file()
+ {
+ if (!empty($this->action_map[$this->action])) {
+ return $this->action_map[$this->action];
}
- $folders[$idx] = $value;
- }
- $prefs['search_mods'] = $folders;
+
+ return strtr($this->action, '-', '_') . '.inc';
}
- if (!empty($prefs['message_threading'])) {
- $folders = array();
- foreach ($prefs['message_threading'] as $idx => $value) {
- if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
- $idx = $prefix.$idx;
+ /**
+ * Fixes some user preferences according to namespace handling change.
+ * Old Roundcube versions were using folder names with removed namespace prefix.
+ * Now we need to add the prefix on servers where personal namespace has prefix.
+ *
+ * @param rcube_user $user User object
+ */
+ private function fix_namespace_settings($user)
+ {
+ $prefix = $this->storage->get_namespace('prefix');
+ $prefix_len = strlen($prefix);
+
+ if (!$prefix_len)
+ return;
+
+ $prefs = $this->config->all();
+ if (!empty($prefs['namespace_fixed']))
+ return;
+
+ // Build namespace prefix regexp
+ $ns = $this->storage->get_namespace();
+ $regexp = array();
+
+ foreach ($ns as $entry) {
+ if (!empty($entry)) {
+ foreach ($entry as $item) {
+ if (strlen($item[0])) {
+ $regexp[] = preg_quote($item[0], '/');
+ }
+ }
+ }
+ }
+ $regexp = '/^('. implode('|', $regexp).')/';
+
+ // Fix preferences
+ $opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
+ foreach ($opts as $opt) {
+ if ($value = $prefs[$opt]) {
+ if ($value != 'INBOX' && !preg_match($regexp, $value)) {
+ $prefs[$opt] = $prefix.$value;
+ }
+ }
}
- $folders[$prefix.$idx] = $value;
- }
- $prefs['message_threading'] = $folders;
- }
- if (!empty($prefs['collapsed_folders'])) {
- $folders = explode('&&', $prefs['collapsed_folders']);
- $count = count($folders);
- $folders_str = '';
+ if (!empty($prefs['default_folders'])) {
+ foreach ($prefs['default_folders'] as $idx => $name) {
+ if ($name != 'INBOX' && !preg_match($regexp, $name)) {
+ $prefs['default_folders'][$idx] = $prefix.$name;
+ }
+ }
+ }
- if ($count) {
- $folders[0] = substr($folders[0], 1);
- $folders[$count-1] = substr($folders[$count-1], 0, -1);
- }
+ if (!empty($prefs['search_mods'])) {
+ $folders = array();
+ foreach ($prefs['search_mods'] as $idx => $value) {
+ if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
+ $idx = $prefix.$idx;
+ }
+ $folders[$idx] = $value;
+ }
- foreach ($folders as $value) {
- if ($value != 'INBOX' && !preg_match($regexp, $value)) {
- $value = $prefix.$value;
+ $prefs['search_mods'] = $folders;
+ }
+
+ if (!empty($prefs['message_threading'])) {
+ $folders = array();
+ foreach ($prefs['message_threading'] as $idx => $value) {
+ if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
+ $idx = $prefix.$idx;
+ }
+ $folders[$prefix.$idx] = $value;
+ }
+
+ $prefs['message_threading'] = $folders;
}
- $folders_str .= '&'.$value.'&';
- }
- $prefs['collapsed_folders'] = $folders_str;
- }
- $prefs['namespace_fixed'] = true;
+ if (!empty($prefs['collapsed_folders'])) {
+ $folders = explode('&&', $prefs['collapsed_folders']);
+ $count = count($folders);
+ $folders_str = '';
- // save updated preferences and reset imap settings (default folders)
- $user->save_prefs($prefs);
- $this->set_storage_prop();
- }
+ if ($count) {
+ $folders[0] = substr($folders[0], 1);
+ $folders[$count-1] = substr($folders[$count-1], 0, -1);
+ }
+ foreach ($folders as $value) {
+ if ($value != 'INBOX' && !preg_match($regexp, $value)) {
+ $value = $prefix.$value;
+ }
+ $folders_str .= '&'.$value.'&';
+ }
+
+ $prefs['collapsed_folders'] = $folders_str;
+ }
+
+ $prefs['namespace_fixed'] = true;
+
+ // save updated preferences and reset imap settings (default folders)
+ $user->save_prefs($prefs);
+ $this->set_storage_prop();
+ }
/**
* Overwrite action variable
@@ -978,7 +1003,6 @@ class rcmail extends rcube
$this->output->set_env('action', $action);
}
-
/**
* Set environment variables for specified config options
*/
@@ -991,7 +1015,6 @@ class rcmail extends rcube
}
}
-
/**
* Returns RFC2822 formatted current date in user's timezone
*
@@ -1011,7 +1034,6 @@ class rcmail extends rcube
return $date->format('r');
}
-
/**
* Write login data (name, ID, IP address) to the 'userlogins' log file.
*/
@@ -1036,14 +1058,13 @@ class rcmail extends rcube
}
$message = sprintf('Successful login for %s (ID: %d) from %s in session %s',
- $user_name, $user_id, rcube_utils::remote_ip(), session_id());
+ $user_name, $user_id, rcube_utils::remote_ip(), session_id());
}
// log login
self::write_log('userlogins', $message);
}
-
/**
* Create a HTML table based on the given data
*
@@ -1093,7 +1114,6 @@ class rcmail extends rcube
return $table->show($attrib);
}
-
/**
* Convert the given date to a human readable form
* This uses the date formatting properties from config
@@ -1223,7 +1243,6 @@ class rcmail extends rcube
return $out;
}
-
/**
* Return folders list in HTML
*
@@ -1316,7 +1335,6 @@ class rcmail extends rcube
return $out;
}
-
/**
* Return folders list as html_select object
*
@@ -1360,7 +1378,6 @@ class rcmail extends rcube
return $select;
}
-
/**
* Create a hierarchical array of the mailbox list
*/
@@ -1418,7 +1435,6 @@ class rcmail extends rcube
}
}
-
/**
* Return html for a structured list &lt;ul&gt; for the mailbox tree
*/
@@ -1513,7 +1529,6 @@ class rcmail extends rcube
return $out;
}
-
/**
* Return html for a flat list <select> for the mailbox tree
*/
@@ -1558,7 +1573,6 @@ class rcmail extends rcube
return $out;
}
-
/**
* Return internal name for the given folder if it matches the configured special folders
*/
@@ -1577,7 +1591,6 @@ class rcmail extends rcube
}
}
-
/**
* Try to localize the given IMAP folder name.
* UTF-7 decode it in case no localized text was found
@@ -1695,7 +1708,6 @@ class rcmail extends rcube
return $quota_result;
}
-
/**
* Outputs error message according to server error/response codes
*
@@ -1749,7 +1761,6 @@ class rcmail extends rcube
}
}
-
/**
* Output HTML editor scripts
*
@@ -1790,7 +1801,6 @@ class rcmail extends rcube
$this->output->add_script("rcmail_editor_init($script)", 'docready');
}
-
/**
* Replaces TinyMCE's emoticon images with plain-text representation
*
@@ -1828,7 +1838,6 @@ class rcmail extends rcube
return preg_replace($search, $replace, $html);
}
-
/**
* File upload progress handler.
*/
@@ -1860,7 +1869,6 @@ class rcmail extends rcube
$this->output->send();
}
-
/**
* Initializes file uploading interface.
*/
@@ -1878,6 +1886,7 @@ class rcmail extends rcube
// find max filesize value
$max_filesize = parse_bytes(ini_get('upload_max_filesize'));
$max_postsize = parse_bytes(ini_get('post_max_size'));
+
if ($max_postsize && $max_postsize < $max_filesize) {
$max_filesize = $max_postsize;
}
@@ -1890,7 +1899,6 @@ class rcmail extends rcube
return $max_filesize;
}
-
/**
* Initializes client-side autocompletion.
*/
@@ -1917,7 +1925,6 @@ class rcmail extends rcube
$this->output->add_label('autocompletechars', 'autocompletemore');
}
-
/**
* Returns supported font-family specifications
*
@@ -1950,7 +1957,6 @@ class rcmail extends rcube
return $fonts;
}
-
/**
* Create a human readable string for a number of bytes
*
@@ -1978,7 +1984,6 @@ class rcmail extends rcube
return $str;
}
-
/**
* Returns real size (calculated) of the message part
*
diff --git a/program/include/rcmail_html_page.php b/program/include/rcmail_html_page.php
index 5d07b8d04..d5610ab47 100644
--- a/program/include/rcmail_html_page.php
+++ b/program/include/rcmail_html_page.php
@@ -38,11 +38,12 @@ class rcmail_html_page extends rcmail_output_html
}
else { // set default styles for warning blocks inside the attachment part frame
$this->add_header(html::tag('style', array('type' => 'text/css'),
- ".rcmail-inline-message { font-family: sans-serif; border:2px solid #ffdf0e; background:#fef893; padding:0.6em 1em; margin-bottom:0.6em }\n" .
+ ".rcmail-inline-message { font-family: sans-serif; border:2px solid #ffdf0e;"
+ . "background:#fef893; padding:0.6em 1em; margin-bottom:0.6em }\n" .
".rcmail-inline-buttons { margin-bottom:0 }"
));
}
parent::write($contents);
}
-} \ No newline at end of file
+}
diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php
index e4059b73d..4df755985 100644
--- a/program/include/rcmail_output_html.php
+++ b/program/include/rcmail_output_html.php
@@ -5,7 +5,7 @@
| program/include/rcmail_output_html.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2006-2012, The Roundcube Dev Team |
+ | Copyright (C) 2006-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -83,9 +83,9 @@ class rcmail_output_html extends rcmail_output
$this->set_env('skin', $skin);
if (!empty($_REQUEST['_extwin']))
- $this->set_env('extwin', 1);
+ $this->set_env('extwin', 1);
if ($this->framed || !empty($_REQUEST['_framed']))
- $this->set_env('framed', 1);
+ $this->set_env('framed', 1);
// add common javascripts
$this->add_script('var '.self::JS_OBJECT_NAME.' = new rcube_webmail();', 'head_top');
@@ -119,6 +119,7 @@ class rcmail_output_html extends rcmail_output
public function set_env($name, $value, $addtojs = true)
{
$this->env[$name] = $value;
+
if ($addtojs || isset($this->js_env[$name])) {
$this->js_env[$name] = $value;
}
diff --git a/program/include/rcmail_string_replacer.php b/program/include/rcmail_string_replacer.php
index 4fbc611c9..6771375e1 100644
--- a/program/include/rcmail_string_replacer.php
+++ b/program/include/rcmail_string_replacer.php
@@ -5,7 +5,7 @@
| program/include/rcmail_string_replacer.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2012, The Roundcube Dev Team |
+ | Copyright (C) 2012-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -19,7 +19,6 @@
+-----------------------------------------------------------------------+
*/
-
/**
* Helper class for turning URLs and email addresses in plaintext content
* into clickable links.
@@ -40,15 +39,15 @@ class rcmail_string_replacer extends rcube_string_replacer
*/
public function mailto_callback($matches)
{
- $href = $matches[1];
- $suffix = $this->parse_url_brackets($href);
+ $href = $matches[1];
+ $suffix = $this->parse_url_brackets($href);
- $i = $this->add(html::a(array(
- 'href' => 'mailto:' . $href,
- 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('compose','".rcube::JQ($href)."',this)",
- ), rcube::Q($href)) . $suffix);
+ $i = $this->add(html::a(array(
+ 'href' => 'mailto:' . $href,
+ 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".command('compose','".rcube::JQ($href)."',this)",
+ ),
+ rcube::Q($href)) . $suffix);
- return $i >= 0 ? $this->get_replacement($i) : '';
+ return $i >= 0 ? $this->get_replacement($i) : '';
}
-
-} \ No newline at end of file
+}
diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php
index 331b57e96..503e29d6f 100644
--- a/program/lib/Roundcube/rcube.php
+++ b/program/lib/Roundcube/rcube.php
@@ -1152,7 +1152,6 @@ class rcube
// handle PHP exceptions
if (is_object($arg) && is_a($arg, 'Exception')) {
$arg = array(
- 'type' => 'php',
'code' => $arg->getCode(),
'line' => $arg->getLine(),
'file' => $arg->getFile(),
@@ -1160,7 +1159,7 @@ class rcube
);
}
else if (is_string($arg)) {
- $arg = array('message' => $arg, 'type' => 'php');
+ $arg = array('message' => $arg);
}
if (empty($arg['code'])) {
@@ -1176,7 +1175,7 @@ class rcube
$cli = php_sapi_name() == 'cli';
- if (($log || $terminate) && !$cli && $arg['type'] && $arg['message']) {
+ if (($log || $terminate) && !$cli && $arg['message']) {
$arg['fatal'] = $terminate;
self::log_bug($arg);
}
@@ -1204,7 +1203,7 @@ class rcube
*/
public static function log_bug($arg_arr)
{
- $program = strtoupper($arg_arr['type']);
+ $program = strtoupper(!empty($arg_arr['type']) ? $arg_arr['type'] : 'php');
$level = self::get_instance()->config->get('debug_level');
// disable errors for ajax requests, write to log instead (#1487831)