From d5190084980835d68847a9b9c18f68c00b4cd37a Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 12 May 2014 12:13:24 +0200 Subject: Add configurable LDAP_OPT_DEREF option (#1489864) - patch from Stuart C. Naifeh --- config/defaults.inc.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'config/defaults.inc.php') diff --git a/config/defaults.inc.php b/config/defaults.inc.php index a76eec6dc..85190eb0a 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -784,6 +784,8 @@ $config['ldap_public']['Verisign'] = array( 'sizelimit' => '0', // Enables you to limit the count of entries fetched. Setting this to 0 means no limit. 'timelimit' => '0', // Sets the number of seconds how long is spend on the search. Setting this to 0 means no limit. 'referrals' => false, // Sets the LDAP_OPT_REFERRALS option. Mostly used in multi-domain Active Directory setups + 'dereference' => 0, // Sets the LDAP_OPT_DEREF option. One of: LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING, LDAP_DEREF_FINDING, LDAP_DEREF_ALWAYS + // Used where addressbook contains aliases to objects elsewhere in the LDAP tree. // definition for contact groups (uncomment if no groups are supported) // for the groups base_dn, the user replacements %fu, %u, $d and %dc work as for base_dn (see above) -- cgit v1.2.3 From 769829a0cec6198fedf8dd937b123377cb45510d Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 16 Jun 2014 12:40:27 +0200 Subject: Add notes about messages_cache setting requirements (#1489946) --- config/defaults.inc.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'config/defaults.inc.php') diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 85190eb0a..859378624 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -173,6 +173,9 @@ $config['imap_auth_pw'] = null; $config['imap_cache'] = null; // Enables messages cache. Only 'db' cache is supported. +// This requires an IMAP server that supports QRESYNC and CONDSTORE +// extensions (RFC7162). See synchronize() in program/lib/Roundcube/rcube_imap_cache.php +// for further info, or if you experience syncing problems. $config['messages_cache'] = false; // Lifetime of IMAP indexes cache. Possible units: s, m, h, d, w -- cgit v1.2.3 From 109bcce470b789dac498d0fba8fb9673b988f867 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 16 Jun 2014 14:13:58 +0200 Subject: Add config option to specify IMAP connection socket parameters - imap_conn_options (#1489948) --- CHANGELOG | 1 + config/defaults.inc.php | 37 ++++-- program/lib/Roundcube/rcube.php | 19 +-- program/lib/Roundcube/rcube_imap.php | 12 +- program/lib/Roundcube/rcube_imap_generic.php | 181 +++++++++++++++------------ 5 files changed, 145 insertions(+), 105 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/CHANGELOG b/CHANGELOG index 9e26b9501..d2fc4faaf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Add config option to specify IMAP connection socket parameters - imap_conn_options (#1489948) - Password: Add option to force new users to change their password (#1486884) - Improve support for screen readers and assistive technology using WCAG 2.0 and WAI ARIA standards - Enable basic keyboard navigation throughout the UI (#1487845) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 859378624..c20a06bf7 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -123,6 +123,27 @@ $config['default_port'] = 143; // best server supported one) $config['imap_auth_type'] = null; +// IMAP socket context options +// See http://php.net/manual/en/context.ssl.php +// The example below enables server certificate validation +//$config['imap_conn_options'] = array( +// 'ssl' => array( +// 'verify_peer' => true, +// 'verify_depth' => 3, +// 'cafile' => '/etc/openssl/certs/ca.crt', +// ), +// ); +$config['imap_conn_options'] = null; + +// IMAP connection timeout, in seconds. Default: 0 (use default_socket_timeout) +$config['imap_timeout'] = 0; + +// Optional IMAP authentication identifier to be used as authorization proxy +$config['imap_auth_cid'] = null; + +// Optional IMAP authentication password to be used for imap_auth_cid +$config['imap_auth_pw'] = null; + // If you know your imap's folder delimiter, you can specify it here. // Otherwise it will be determined automatically $config['imap_delimiter'] = null; @@ -160,15 +181,6 @@ $config['imap_force_ns'] = false; // Note: Because the list is cached, re-login is required after change. $config['imap_disabled_caps'] = array(); -// IMAP connection timeout, in seconds. Default: 0 (use default_socket_timeout) -$config['imap_timeout'] = 0; - -// Optional IMAP authentication identifier to be used as authorization proxy -$config['imap_auth_cid'] = null; - -// Optional IMAP authentication password to be used for imap_auth_cid -$config['imap_auth_pw'] = null; - // Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache'. $config['imap_cache'] = null; @@ -244,13 +256,14 @@ $config['smtp_timeout'] = 0; // requires 'smtp_timeout' to be non zero. // $config['smtp_conn_options'] = array( // 'ssl' => array( -// 'verify_peer' => true, -// 'verify_depth => 3, -// 'cafile' => '/etc/openssl/certs/ca.crt', +// 'verify_peer' => true, +// 'verify_depth' => 3, +// 'cafile' => '/etc/openssl/certs/ca.crt', // ), // ); $config['smtp_conn_options'] = null; + // ---------------------------------- // LDAP // ---------------------------------- diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index d618fb64d..cf54c3c12 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -357,15 +357,16 @@ class rcube // set class options $options = array( - 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), - 'auth_cid' => $this->config->get("{$driver}_auth_cid"), - '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, + 'auth_type' => $this->config->get("{$driver}_auth_type", 'check'), + 'auth_cid' => $this->config->get("{$driver}_auth_cid"), + '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"), + 'socket_options' => $this->config->get("{$driver}_conn_options"), + 'timeout' => (int) $this->config->get("{$driver}_timeout"), + 'skip_deleted' => (bool) $this->config->get('skip_deleted'), + 'driver' => $driver, ); if (!empty($_SESSION['storage_host'])) { diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index e29bfc46b..109886f8d 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -110,13 +110,13 @@ class rcube_imap extends rcube_storage /** * Connect to an IMAP server * - * @param string $host Host to connect - * @param string $user Username for IMAP account - * @param string $pass Password for IMAP account - * @param integer $port Port to connect to - * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection + * @param string $host Host to connect + * @param string $user Username for IMAP account + * @param string $pass Password for IMAP account + * @param integer $port Port to connect to + * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection * - * @return boolean TRUE on success, FALSE on failure + * @return boolean True on success, False on failure */ public function connect($host, $user, $pass, $port=143, $use_ssl=null) { diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php index e4c9b7eb8..5aaad0a00 100644 --- a/program/lib/Roundcube/rcube_imap_generic.php +++ b/program/lib/Roundcube/rcube_imap_generic.php @@ -723,110 +723,38 @@ class rcube_imap_generic // configure $this->set_prefs($options); - $auth_method = $this->prefs['auth_type']; - $result = false; - - // initialize connection - $this->error = ''; - $this->errornum = self::ERROR_OK; - $this->selected = null; - $this->user = $user; $this->host = $host; + $this->user = $user; $this->logged = false; + $this->selected = null; // check input if (empty($host)) { $this->setError(self::ERROR_BAD, "Empty host"); return false; } + if (empty($user)) { $this->setError(self::ERROR_NO, "Empty user"); return false; } + if (empty($password)) { $this->setError(self::ERROR_NO, "Empty password"); return false; } - if (!$this->prefs['port']) { - $this->prefs['port'] = 143; - } - // check for SSL - if ($this->prefs['ssl_mode'] && $this->prefs['ssl_mode'] != 'tls') { - $host = $this->prefs['ssl_mode'] . '://' . $host; - } - - if ($this->prefs['timeout'] <= 0) { - $this->prefs['timeout'] = max(0, intval(ini_get('default_socket_timeout'))); - } - // Connect - $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); - - if (!$this->fp) { - if (!$errstr) { - $errstr = "Unknown reason (fsockopen() function disabled?)"; - } - $this->setError(self::ERROR_BAD, sprintf("Could not connect to %s:%d: %s", $host, $this->prefs['port'], $errstr)); - return false; - } - - if ($this->prefs['timeout'] > 0) { - stream_set_timeout($this->fp, $this->prefs['timeout']); - } - - $line = trim(fgets($this->fp, 8192)); - - if ($this->_debug) { - // set connection identifier for debug output - preg_match('/#([0-9]+)/', (string)$this->fp, $m); - $this->resourceid = strtoupper(substr(md5($m[1].$this->user.microtime()), 0, 4)); - - if ($line) - $this->debug('S: '. $line); - } - - // Connected to wrong port or connection error? - if (!preg_match('/^\* (OK|PREAUTH)/i', $line)) { - if ($line) - $error = sprintf("Wrong startup greeting (%s:%d): %s", $host, $this->prefs['port'], $line); - else - $error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']); - - $this->setError(self::ERROR_BAD, $error); - $this->closeConnection(); + if (!$this->_connect($host)) { return false; } - // RFC3501 [7.1] optional CAPABILITY response - if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) { - $this->parseCapability($matches[1], true); - } - - // TLS connection - if ($this->prefs['ssl_mode'] == 'tls' && $this->getCapability('STARTTLS')) { - $res = $this->execute('STARTTLS'); - - if ($res[0] != self::ERROR_OK) { - $this->closeConnection(); - return false; - } - - if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - $this->setError(self::ERROR_BAD, "Unable to negotiate TLS"); - $this->closeConnection(); - return false; - } - - // Now we're secure, capabilities need to be reread - $this->clearCapability(); - } - // Send ID info if (!empty($this->prefs['ident']) && $this->getCapability('ID')) { $this->id($this->prefs['ident']); } + $auth_method = $this->prefs['auth_type']; $auth_methods = array(); $result = null; @@ -900,6 +828,103 @@ class rcube_imap_generic return false; } + /** + * Connects to IMAP server. + * + * @param string $host Server hostname or IP + * + * @return bool True on success, False on failure + */ + protected function _connect($host) + { + // initialize connection + $this->error = ''; + $this->errornum = self::ERROR_OK; + + if (!$this->prefs['port']) { + $this->prefs['port'] = 143; + } + + // check for SSL + if ($this->prefs['ssl_mode'] && $this->prefs['ssl_mode'] != 'tls') { + $host = $this->prefs['ssl_mode'] . '://' . $host; + } + + if ($this->prefs['timeout'] <= 0) { + $this->prefs['timeout'] = max(0, intval(ini_get('default_socket_timeout'))); + } + + if (!empty($this->prefs['socket_options'])) { + $context = stream_context_create($this->prefs['socket_options']); + $this->fp = stream_socket_client($host . ':' . $this->prefs['port'], $errno, $errstr, + $this->prefs['timeout'], STREAM_CLIENT_CONNECT, $context); + } + else { + $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); + } + + if (!$this->fp) { + $this->setError(self::ERROR_BAD, sprintf("Could not connect to %s:%d: %s", + $host, $this->prefs['port'], $errstr ?: "Unknown reason")); + + return false; + } + + if ($this->prefs['timeout'] > 0) { + stream_set_timeout($this->fp, $this->prefs['timeout']); + } + + $line = trim(fgets($this->fp, 8192)); + + if ($this->_debug) { + // set connection identifier for debug output + preg_match('/#([0-9]+)/', (string) $this->fp, $m); + $this->resourceid = strtoupper(substr(md5($m[1].$this->user.microtime()), 0, 4)); + + if ($line) { + $this->debug('S: '. $line); + } + } + + // Connected to wrong port or connection error? + if (!preg_match('/^\* (OK|PREAUTH)/i', $line)) { + if ($line) + $error = sprintf("Wrong startup greeting (%s:%d): %s", $host, $this->prefs['port'], $line); + else + $error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']); + + $this->setError(self::ERROR_BAD, $error); + $this->closeConnection(); + return false; + } + + // RFC3501 [7.1] optional CAPABILITY response + if (preg_match('/\[CAPABILITY ([^]]+)\]/i', $line, $matches)) { + $this->parseCapability($matches[1], true); + } + + // TLS connection + if ($this->prefs['ssl_mode'] == 'tls' && $this->getCapability('STARTTLS')) { + $res = $this->execute('STARTTLS'); + + if ($res[0] != self::ERROR_OK) { + $this->closeConnection(); + return false; + } + + if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { + $this->setError(self::ERROR_BAD, "Unable to negotiate TLS"); + $this->closeConnection(); + return false; + } + + // Now we're secure, capabilities need to be reread + $this->clearCapability(); + } + + return true; + } + /** * Initializes environment */ -- cgit v1.2.3 From cd01dc027b8fb9cc4ce7237fbb8e7359c4a5d47e Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sat, 21 Jun 2014 15:41:40 +0200 Subject: Add option to set default message list mode - default_list_mode (#1487312) --- CHANGELOG | 1 + config/defaults.inc.php | 9 ++++++--- program/steps/mail/func.inc | 7 +++++-- program/steps/settings/edit_folder.inc | 6 ++++-- program/steps/settings/folders.inc | 7 ++++--- program/steps/settings/save_folder.inc | 14 +++++--------- 6 files changed, 25 insertions(+), 19 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/CHANGELOG b/CHANGELOG index 0b15aaf47..43c2504bb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Add option to set default message list mode - default_list_mode (#1487312) - Close "no subject" prompt with Enter key (#1489580) - Add config option to specify IMAP connection socket parameters - imap_conn_options (#1489948) - Password: Add option to force new users to change their password (#1486884) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index c20a06bf7..71a2e4277 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -978,9 +978,12 @@ $config['check_all_folders'] = false; // If true, after message delete/move, the next message will be displayed $config['display_next'] = true; -// 0 - Do not expand threads -// 1 - Expand all threads automatically -// 2 - Expand only threads with unread messages +// Default messages listing mode. One of 'threads' or 'list'. +$config['default_list_mode'] = 'list'; + +// 0 - Do not expand threads +// 1 - Expand all threads automatically +// 2 - Expand only threads with unread messages $config['autoexpand_threads'] = 0; // When replying: diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index ac343ad5a..e8bf5e1fd 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -166,6 +166,7 @@ function rcmail_init_env() { global $RCMAIL; + $default_threading = $RCMAIL->config->get('default_list_mode', 'list') == 'threads'; $a_threading = $RCMAIL->config->get('message_threading', array()); $message_sort_col = $RCMAIL->config->get('message_sort_col'); $message_sort_order = $RCMAIL->config->get('message_sort_order'); @@ -205,13 +206,15 @@ function rcmail_init_env() $RCMAIL->storage->set_page($_SESSION['page'] = 1); } - unset($a_threading[$_SESSION['mbox']]); + $a_threading[$_SESSION['mbox']] = false; } $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); } - $RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]); + $threading = isset($a_threading[$_SESSION['mbox']]) ? $a_threading[$_SESSION['mbox']] : $default_threading; + + $RCMAIL->storage->set_threading($threading); } /** diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc index 30a187fc4..87a45fa8d 100644 --- a/program/steps/settings/edit_folder.inc +++ b/program/steps/settings/edit_folder.inc @@ -163,8 +163,10 @@ function rcmail_folder_form($attrib) $value = (int) $_POST['_viewmode']; } else if (strlen($mbox_imap)) { - $a_threaded = $RCMAIL->config->get('message_threading', array()); - $value = (int) isset($a_threaded[$mbox_imap]); + $a_threaded = $RCMAIL->config->get('message_threading', array()); + $default_mode = $RCMAIL->config->get('default_list_mode', 'list'); + + $value = (int) (isset($a_threaded[$mbox_imap]) ? $a_threaded[$mbox_imap] : $default_mode == 'threads'); } $form['props']['fieldsets']['settings']['content']['viewmode'] = array( diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index 1bcfb4cfc..8b74a59e1 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -406,16 +406,17 @@ function rcmail_rename_folder($oldname, $newname) $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; - foreach (array_keys($a_threaded) as $key) { + foreach ($a_threaded as $key => $val) { if ($key == $oldname) { unset($a_threaded[$key]); - $a_threaded[$newname] = true; + $a_threaded[$newname] = $val; } else if (preg_match($oldprefix, $key)) { unset($a_threaded[$key]); - $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = true; + $a_threaded[preg_replace($oldprefix, $newname.$delimiter, $key)] = $val; } } + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); // #1488692: update session diff --git a/program/steps/settings/save_folder.inc b/program/steps/settings/save_folder.inc index d1449bb38..a054224f1 100644 --- a/program/steps/settings/save_folder.inc +++ b/program/steps/settings/save_folder.inc @@ -115,15 +115,13 @@ if (!$error && !strlen($old)) { if (isset($_POST['_viewmode'])) { $a_threaded = (array) $RCMAIL->config->get('message_threading', array()); - if ($_POST['_viewmode']) - $a_threaded[$folder['name']] = true; - else - unset($a_threaded[$folder['name']]); + $a_threaded[$folder['name']] = (bool) $_POST['_viewmode']; $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); } rcmail_update_folder_row($folder['name'], null, $folder['subscribe'], $folder['class']); + $OUTPUT->show_message('foldercreated', 'confirmation'); // reset folder preview frame $OUTPUT->command('subscription_select'); @@ -167,14 +165,12 @@ else if (!$error) { } else if (preg_match($oldprefix, $key)) { unset($a_threaded[$key]); - $a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = true; + $a_threaded[preg_replace($oldprefix, $folder['name'].$delimiter, $key)] = $val; } } } - if ($_POST['_viewmode']) - $a_threaded[$folder['name']] = true; - else - unset($a_threaded[$folder['name']]); + + $a_threaded[$folder['name']] = (bool) $_POST['_viewmode']; $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); } -- cgit v1.2.3 From 3cc1afa1c2f30bfebb30146795e50172947b4b5f Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 29 Jun 2014 16:35:18 +0200 Subject: Support images in HTML signatures (#1488676) This enables image button and file browser in html editor for signatures --- CHANGELOG | 1 + config/defaults.inc.php | 4 ++ program/include/rcmail.php | 79 +++++++++++++++++++++++++++++++- program/js/app.js | 15 +++--- program/js/editor.js | 16 +++++-- program/steps/mail/attachments.inc | 63 +------------------------ program/steps/settings/edit_identity.inc | 10 ++++ program/steps/settings/func.inc | 1 + program/steps/settings/save_identity.inc | 34 +++++++++++++- 9 files changed, 149 insertions(+), 74 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/CHANGELOG b/CHANGELOG index e4a02ad4f..b73ee3f19 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Support images in HTML signatures (#1488676) - Display full quota information in popup (#1485769, #1486604) - Mail compose: Selecting contact inserts recipient to previously focused input - to/cc/bcc accordingly (#1489684) - Add option to set default message list mode - default_list_mode (#1487312) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 71a2e4277..e7cb1e3aa 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -481,6 +481,10 @@ $config['mdn_use_from'] = false; // 4 - one identity with possibility to edit only signature $config['identities_level'] = 0; +// Maximum size of uploaded image in kilobytes +// Images (in html signatures) are stored in database as data URIs +$config['identity_image_size'] = 64; + // Mimetypes supported by the browser. // attachments of these types will open in a preview window // either a comma-separated list or an array: 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,application/pdf' diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 0151020c7..54d0d88e6 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -1944,8 +1944,10 @@ class rcmail extends rcube /** * Initializes file uploading interface. + * + * @param $int Optional maximum file size in bytes */ - public function upload_init() + public function upload_init($max_size = null) { // Enable upload progress bar if ($seconds = $this->config->get('upload_progress')) { @@ -1973,6 +1975,10 @@ class rcmail extends rcube $max_filesize = $max_postsize; } + if ($max_size && $max_size < $max_filesize) { + $max_filesize = $max_size; + } + $this->output->set_env('max_filesize', $max_filesize); $max_filesize = $this->show_bytes($max_filesize); $this->output->set_env('filesizeerror', $this->gettext(array( @@ -1981,6 +1987,77 @@ class rcmail extends rcube return $max_filesize; } + /** + * Outputs uploaded file content (with image thumbnails support + * + * @param array $file Upload file data + */ + public function display_uploaded_file($file) + { + if (empty($file)) { + return; + } + + $file = $this->plugins->exec_hook('attachment_display', $file); + + if ($file['status']) { + if (empty($file['size'])) { + $file['size'] = $file['data'] ? strlen($file['data']) : @filesize($file['path']); + } + + // generate image thumbnail for file browser in HTML editor + if (!empty($_GET['_thumbnail'])) { + $temp_dir = $this->config->get('temp_dir'); + $thumbnail_size = 80; + list(,$ext) = explode('/', $file['mimetype']); + $mimetype = $file['mimetype']; + $file_ident = $file['id'] . ':' . $file['mimetype'] . ':' . $file['size']; + $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $this->user->ID . ':' . $thumbnail_size); + $cache_file = $cache_basename . '.' . $ext; + + // render thumbnail image if not done yet + if (!is_file($cache_file)) { + if (!$file['path']) { + $orig_name = $filename = $cache_basename . '.orig.' . $ext; + file_put_contents($orig_name, $file['data']); + } + else { + $filename = $file['path']; + } + + $image = new rcube_image($filename); + if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { + $mimetype = 'image/' . $imgtype; + + if ($orig_name) { + unlink($orig_name); + } + } + } + + if (is_file($cache_file)) { + // cache for 1h + $this->output->future_expire_header(3600); + header('Content-Type: ' . $mimetype); + header('Content-Length: ' . filesize($cache_file)); + + readfile($cache_file); + exit; + } + } + + header('Content-Type: ' . $file['mimetype']); + header('Content-Length: ' . $file['size']); + + if ($file['data']) { + echo $file['data']; + } + else if ($file['path']) { + readfile($file['path']); + } + } + } + /** * Initializes client-side autocompletion. */ diff --git a/program/js/app.js b/program/js/app.js index 8f2065635..3b5ff0422 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -4083,6 +4083,14 @@ function rcube_webmail() if (upload_id) this.triggerEvent('fileuploaded', {name: name, attachment: att, id: upload_id}); + if (!this.env.attachments) + this.env.attachments = {}; + + if (upload_id && this.env.attachments[upload_id]) + delete this.env.attachments[upload_id]; + + this.env.attachments[name] = att; + if (!this.gui_objects.attachmentlist) return false; @@ -4112,11 +4120,6 @@ function rcube_webmail() var tabindex = $(this.gui_objects.attachmentlist).attr('data-tabindex') || '0'; li.find('a').attr('tabindex', tabindex); - if (upload_id && this.env.attachments[upload_id]) - delete this.env.attachments[upload_id]; - - this.env.attachments[name] = att; - return true; }; @@ -7563,7 +7566,7 @@ function rcube_webmail() $(form).attr({ target: frame_name, - action: this.url(action, { _id:this.env.compose_id||'', _uploadid:ts }), + action: this.url(action, {_id: this.env.compose_id || '', _uploadid: ts, _from: this.env.action}), method: 'POST'}) .attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data') .submit(); diff --git a/program/js/editor.js b/program/js/editor.js index dfd3e27ea..0dd8fef9a 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -65,10 +65,12 @@ function rcube_text_editor(config, id) // minimal editor if (config.mode == 'identity') { $.extend(conf, { - plugins: 'autolink charmap code colorpicker hr link paste tabfocus textcolor', + plugins: 'autolink charmap code colorpicker hr image link paste tabfocus textcolor', toolbar: 'bold italic underline alignleft aligncenter alignright alignjustify' - + ' | outdent indent charmap hr link unlink code forecolor' - + ' | fontselect fontsizeselect' + + ' | outdent indent charmap hr link unlink image code forecolor' + + ' | fontselect fontsizeselect', + file_browser_callback: function(name, url, type, win) { ref.file_browser_callback(name, url, type); }, + file_browser_callback_types: 'image' }); } // full-featured editor @@ -610,6 +612,8 @@ function rcube_text_editor(config, id) } }); } + + // @todo: upload progress indicator }; // close file browser window @@ -652,7 +656,9 @@ function rcube_text_editor(config, id) } if (rx.test(file.mimetype)) { - var href = rcmail.env.comm_path+'&_id='+rcmail.env.compose_id+'&_action=display-attachment&_file='+file_id, + var path = rcmail.env.comm_path + '&_from=' + rcmail.env.action, + action = rcmail.env.compose_id ? '&_id=' + rcmail.env.compose_id + '&_action=display-attachment' : '&_action=upload-display', + href = path + action + '&_file=' + file_id, img = $('').attr({title: file.name, src: img_src ? img_src : href + '&_thumbnail=1'}); return $('
  • ').attr({tabindex: 0}) @@ -686,7 +692,7 @@ function rcube_text_editor(config, id) this.hack_file_input = function(elem, clone_form) { var link = $(elem), - file = $(''), + file = $('').attr('name', '_files[]'), form = $('
    ').attr({method: 'post', enctype: 'multipart/form-data'}), offset = link.offset(); diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc index fd122c5c1..5eaa655e3 100644 --- a/program/steps/mail/attachments.inc +++ b/program/steps/mail/attachments.inc @@ -38,7 +38,7 @@ if (!$COMPOSE) { // remove an attachment -if ($RCMAIL->action=='remove-attachment') { +if ($RCMAIL->action == 'remove-attachment') { $id = 'undefined'; if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) { @@ -67,66 +67,7 @@ if ($RCMAIL->action == 'display-attachment') { $id = $regs[1]; } - if ($attachment = $COMPOSE['attachments'][$id]) { - $attachment = $RCMAIL->plugins->exec_hook('attachment_display', $attachment); - } - - if ($attachment['status']) { - if (empty($attachment['size'])) { - $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']); - } - - // generate image thumbnail for file browser in HTML editor - if (!empty($_GET['_thumbnail'])) { - $temp_dir = $RCMAIL->config->get('temp_dir'); - $thumbnail_size = 80; - list(,$ext) = explode('/', $attachment['mimetype']); - $mimetype = $attachment['mimetype']; - $file_ident = $attachment['id'] . ':' . $attachment['mimetype'] . ':' . $attachment['size']; - $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size); - $cache_file = $cache_basename . '.' . $ext; - - // render thumbnail image if not done yet - if (!is_file($cache_file)) { - if (!$attachment['path']) { - $orig_name = $filename = $cache_basename . '.orig.' . $ext; - file_put_contents($orig_name, $attachment['data']); - } - else { - $filename = $attachment['path']; - } - - $image = new rcube_image($filename); - if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { - $mimetype = 'image/' . $imgtype; - - if ($orig_name) { - unlink($orig_name); - } - } - } - - if (is_file($cache_file)) { - // cache for 1h - $RCMAIL->output->future_expire_header(3600); - header('Content-Type: ' . $mimetype); - header('Content-Length: ' . filesize($cache_file)); - - readfile($cache_file); - exit; - } - } - - header('Content-Type: ' . $attachment['mimetype']); - header('Content-Length: ' . $attachment['size']); - - if ($attachment['data']) { - echo $attachment['data']; - } - else if ($attachment['path']) { - readfile($attachment['path']); - } - } + $RCMAIL->display_uploaded_file($COMPOSE['attachments'][$id]); exit; } diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc index 20f822027..34fe9798f 100644 --- a/program/steps/settings/edit_identity.inc +++ b/program/steps/settings/edit_identity.inc @@ -176,5 +176,15 @@ function rcube_identity_form($attrib) $out .= $form_end; + // add image upload form + $max_filesize = $RCMAIL->upload_init($RCMAIL->config->get('identity_image_size', 64) * 1024); + $upload_form_id = 'identityImageUpload'; + + $out .= '' + . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) + . '
    '; + + $RCMAIL->output->add_gui_object('uploadform', $upload_form_id); + return $out; } diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 89103ee44..7ccbfa4a5 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -44,6 +44,7 @@ $RCMAIL->register_action_map(array( 'add-response' => 'edit_response.inc', 'save-response' => 'edit_response.inc', 'delete-response' => 'responses.inc', + 'upload-display' => 'upload.inc', )); diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc index 77245b988..de0c84c91 100644 --- a/program/steps/settings/save_identity.inc +++ b/program/steps/settings/save_identity.inc @@ -79,8 +79,11 @@ foreach ($email_checks as $email) { } } -// XSS protection in HTML signature (#1489251) if (!empty($save_data['signature']) && !empty($save_data['html_signature'])) { + // replace uploaded images with data URIs + $save_data['signature'] = rcmail_attach_images($save_data['signature']); + + // XSS protection in HTML signature (#1489251) $save_data['signature'] = rcmail_wash_html($save_data['signature']); // clear POST data of signature, we want to use safe content @@ -190,6 +193,35 @@ else { } +/** + * Attach uploaded images into signature as data URIs + */ +function rcmail_attach_images($html) +{ + global $RCMAIL; + + $offset = 0; + $regexp = '/\s(poster|src)\s*=\s*[\'"]*\S+upload-display\S+file=rcmfile([0-9]+)[\s\'"]*/'; + + while (preg_match($regexp, $html, $matches, 0, $offset)) { + $file_id = $matches[2]; + $data_uri = ' '; + + if ($file_id && ($file = $_SESSION['identity']['files'][$file_id])) { + $file = $RCMAIL->plugins->exec_hook('attachment_get', $file); + + $data_uri .= 'src="data:' . $file['mimetype'] . ';base64,'; + $data_uri .= base64_encode($file['data'] ? $file['data'] : file_get_contents($file['path'])); + $data_uri .= '" '; + } + + $html = str_replace($matches[0], $data_uri, $html); + $offset += strlen($data_uri) - strlen($matches[0]) + 1; + } + + return $html; +} + /** * Sanity checks/cleanups on HTML body of signature */ -- cgit v1.2.3 From 36d004e3d0ad9ff97b66b2e505f6b17fd6d23102 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Thu, 3 Jul 2014 14:25:19 +0200 Subject: Added 'contact_search_name' option to define autocompletion entry format --- CHANGELOG | 1 + config/defaults.inc.php | 5 +++ program/js/app.js | 2 +- program/lib/Roundcube/rcube_addressbook.php | 53 +++++++++++++++++++++++++++++ program/steps/mail/autocomplete.inc | 10 ++++-- 5 files changed, 68 insertions(+), 3 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/CHANGELOG b/CHANGELOG index 4730642ef..6b3927a08 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Added 'contact_search_name' option to define autocompletion entry format - Display quota information for current folder not INBOX only (#1487993) - Support images in HTML signatures (#1488676) - Display full quota information in popup (#1485769, #1486604) diff --git a/config/defaults.inc.php b/config/defaults.inc.php index e7cb1e3aa..18171b75f 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -877,6 +877,11 @@ $config['address_template'] = '{street}
    {locality} {zipcode}
    {country} { // Note: For LDAP sources fuzzy_search must be enabled to use 'partial' or 'prefix' mode $config['addressbook_search_mode'] = 0; +// Template of contact entry on the autocompletion list. +// You can use contact fields as: name, email, organization, department, etc. +// See program/steps/addressbook/func.inc for a list +$config['contact_search_name'] = '{name} <{email}>'; + // ---------------------------------- // USER PREFERENCES // ---------------------------------- diff --git a/program/js/app.js b/program/js/app.js index a3060a8c3..34871f798 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -4568,7 +4568,7 @@ function rcube_webmail() // add each result line to list if (results && (len = results.length)) { for (i=0; i < len && maxlen > 0; i++) { - text = typeof results[i] === 'object' ? results[i].name : results[i]; + text = typeof results[i] === 'object' ? (results[i].display || results[i].name) : results[i]; type = typeof results[i] === 'object' ? results[i].type : ''; id = i + this.env.contacts.length; $('
  • ').attr('id', 'rcmkSearchItem' + id) diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index 4d9fa3db1..7566d6546 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -556,6 +556,59 @@ abstract class rcube_addressbook return $fn; } + /** + * Build contact display name for autocomplete listing + * + * @param array Hash array with contact data as key-value pairs + * @param string Optional email address + * @param string Optional name (self::compose_list_name() result) + * + * @return string Display name + */ + public static function compose_search_name($contact, $email = null, $name = null) + { + static $template; + + if (!isset($template)) { // cache this + $template = rcube::get_instance()->config->get('contact_search_name'); + if (empty($template)) { + $template = '{name} <{email}>'; + } + } + + $result = $template; + + if (preg_match_all('/\{[a-z]+\}/', $result, $matches)) { + foreach ($matches[0] as $key) { + $key = trim($key, '{}'); + + switch ($key) { + case 'name': + $value = $name ?: self::compose_list_name($contact); + break; + + case 'email': + $value = $email; + break; + } + + if (empty($value)) { + $value = strpos($key, ':') ? $contact[$key] : self::get_col_values($key, $contact, true); + if (is_array($value)) { + $value = $value[0]; + } + } + + $result = str_replace('{' . $key . '}', $value, $result); + } + } + + $result = preg_replace('/\s+/', ' ', $result); + $result = trim($result); + + return $result; + } + /** * Create a unique key for sorting contacts */ diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc index 71b337a53..c805cd009 100644 --- a/program/steps/mail/autocomplete.inc +++ b/program/steps/mail/autocomplete.inc @@ -90,8 +90,14 @@ if (!empty($book_types) && strlen($search)) { // skip duplicates if (!in_array($contact, $contacts)) { - $contacts[] = array('name' => $contact, 'type' => $sql_arr['_type']); - $sort_keys[] = sprintf('%s %03d', $sql_arr['name'] , $idx++); + $contact = array('name' => $contact, 'type' => $sql_arr['_type']); + + if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) { + $contact['display'] = $display; + } + + $contacts[] = $contact; + $sort_keys[] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++); if (count($contacts) >= $MAXNUM) { break 2; -- cgit v1.2.3 From d01f9fc7f5a369284fbfd92c6e804d84147e42a1 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 4 Aug 2014 19:03:27 +0200 Subject: Add option (disabled_actions) to disable UI elements/actions (#1489638) --- CHANGELOG | 1 + config/defaults.inc.php | 3 +++ index.php | 8 ++++++++ program/include/rcmail_output_html.php | 30 ++++++++++++++++++++++++++--- program/steps/mail/func.inc | 1 + skins/classic/includes/messagetoolbar.html | 30 ++++++++++++++--------------- skins/classic/templates/compose.html | 4 ++-- skins/classic/templates/messagepreview.html | 4 ++-- skins/larry/includes/mailtoolbar.html | 30 ++++++++++++++--------------- skins/larry/templates/addressbook.html | 16 +++++++-------- skins/larry/templates/compose.html | 4 ++-- skins/larry/templates/folders.html | 4 ++-- skins/larry/templates/mail.html | 30 ++++++++++++++--------------- skins/larry/templates/message.html | 4 ++-- skins/larry/templates/messagepreview.html | 4 ++-- 15 files changed, 105 insertions(+), 68 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/CHANGELOG b/CHANGELOG index f2bbe353d..4b799ca62 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Add option (disabled_actions) to disable UI elements/actions (#1489638) - Support password encryption using openssl extension (#1489989) - Create/rename groups in UI dialogs (#1489951) - Added 'contact_search_name' option to define autocompletion entry format diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 18171b75f..625d4ea80 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -285,6 +285,9 @@ $config['enable_installer'] = false; // don't allow these settings to be overriden by the user $config['dont_override'] = array(); +// List of disabled UI elements/actions +$config['disabled_actions'] = array(); + // define which settings should be listed under the 'advanced' block // which is hidden by default $config['advanced_prefs'] = array(); diff --git a/index.php b/index.php index e0aaf77f8..3154daf68 100644 --- a/index.php +++ b/index.php @@ -260,6 +260,14 @@ else { 'message' => "Referer check failed"), true, true); } } + + // check access to disabled actions + $disabled_actions = (array) $RCMAIL->config->get('disabled_actions'); + if (in_array($RCMAIL->task . '.' . ($RCMAIL->action ?: 'index'), $disabled_actions)) { + rcube::raise_error(array( + 'code' => 403, 'type' => 'php', + 'message' => "Action disabled"), true, true); + } } // we're ready, user is authenticated and the request is safe diff --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 705a72ece..a84824648 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -1139,7 +1139,8 @@ EOF; */ public function button($attrib) { - static $s_button_count = 100; + static $s_button_count = 100; + static $disabled_actions = null; // these commands can be called directly via url $a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities'); @@ -1148,9 +1149,14 @@ EOF; return ''; } + // try to find out the button type if ($attrib['type']) { $attrib['type'] = strtolower($attrib['type']); + if ($pos = strpos($attrib['type'], '-menuitem')) { + $attrib['type'] = substr($attrib['type'], 0, -9); + $menuitem = true; + } } else { $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; @@ -1158,8 +1164,21 @@ EOF; $command = $attrib['command']; - if ($attrib['task']) - $command = $attrib['task'] . '.' . $command; + if ($attrib['task']) { + $element = $command = $attrib['task'] . '.' . $command; + } + else { + $element = ($this->env['task'] ? $this->env['task'] . '.' : '') . $command; + } + + if ($disabled_actions === null) { + $disabled_actions = (array) $this->config->get('disabled_actions'); + } + + // remove buttons for disabled actions + if (in_array($element, $disabled_actions)) { + return ''; + } if (!$attrib['image']) { $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; @@ -1292,6 +1311,11 @@ EOF; $out = html::tag($attrib['wrapper'], null, $out); } + if ($menuitem) { + $class = $attrib['menuitem-class'] ? ' class="' . $attrib['menuitem-class'] . '"' : ''; + $out = '
  • ' . $out . '
  • '; + } + return $out; } diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 103d79d73..c6c0b95e6 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -2075,6 +2075,7 @@ function rcmail_message_import_form($attrib = array()) )); $content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) + . html::tag('input', array('type' => 'hidden', 'name' => '_framed', 'value' => '1')) . html::div(null, $fileinput->show()) . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))); diff --git a/skins/classic/includes/messagetoolbar.html b/skins/classic/includes/messagetoolbar.html index 9d067fb8d..7cf7d477c 100644 --- a/skins/classic/includes/messagetoolbar.html +++ b/skins/classic/includes/messagetoolbar.html @@ -28,39 +28,39 @@
      -
    • -
    • + +
      -
    • -
    • + +
      -
    • -
    • -
    • -
    • -
    • - -
    • + + + + + + +
      -
    • -
    • -
    • -
    • + + + +
    diff --git a/skins/classic/templates/compose.html b/skins/classic/templates/compose.html index 19b22bc69..1515eeb06 100644 --- a/skins/classic/templates/compose.html +++ b/skins/classic/templates/compose.html @@ -202,8 +202,8 @@
  • -
  • -
  • + + diff --git a/skins/classic/templates/messagepreview.html b/skins/classic/templates/messagepreview.html index 82414c420..869f03f65 100644 --- a/skins/classic/templates/messagepreview.html +++ b/skins/classic/templates/messagepreview.html @@ -28,8 +28,8 @@
      -
    • -
    • + +
    diff --git a/skins/larry/includes/mailtoolbar.html b/skins/larry/includes/mailtoolbar.html index 7485a93bd..9d66763cd 100644 --- a/skins/larry/includes/mailtoolbar.html +++ b/skins/larry/includes/mailtoolbar.html @@ -21,8 +21,8 @@ @@ -30,8 +30,8 @@ @@ -39,13 +39,13 @@ @@ -53,10 +53,10 @@ diff --git a/skins/larry/templates/addressbook.html b/skins/larry/templates/addressbook.html index 424e96597..62bca3c84 100644 --- a/skins/larry/templates/addressbook.html +++ b/skins/larry/templates/addressbook.html @@ -29,8 +29,8 @@ @@ -76,10 +76,10 @@ @@ -132,8 +132,8 @@ diff --git a/skins/larry/templates/compose.html b/skins/larry/templates/compose.html index 7fa21650e..04a987f89 100644 --- a/skins/larry/templates/compose.html +++ b/skins/larry/templates/compose.html @@ -212,8 +212,8 @@ -
  • -
  • + + diff --git a/skins/larry/templates/folders.html b/skins/larry/templates/folders.html index 034f35ab3..f48169cd4 100644 --- a/skins/larry/templates/folders.html +++ b/skins/larry/templates/folders.html @@ -32,8 +32,8 @@ diff --git a/skins/larry/templates/mail.html b/skins/larry/templates/mail.html index 6da2cf6f6..2c4e0f2c5 100644 --- a/skins/larry/templates/mail.html +++ b/skins/larry/templates/mail.html @@ -157,18 +157,18 @@ @@ -176,21 +176,21 @@ diff --git a/skins/larry/templates/message.html b/skins/larry/templates/message.html index a6b4cf5d8..dde15acfb 100644 --- a/skins/larry/templates/message.html +++ b/skins/larry/templates/message.html @@ -100,8 +100,8 @@ diff --git a/skins/larry/templates/messagepreview.html b/skins/larry/templates/messagepreview.html index 03fc91505..2e3b5efd1 100644 --- a/skins/larry/templates/messagepreview.html +++ b/skins/larry/templates/messagepreview.html @@ -68,8 +68,8 @@ -- cgit v1.2.3 From 561f5e0a22a16ab39d9bc8b9e4e2cdbd6abaa954 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Thu, 7 Aug 2014 17:06:16 +0200 Subject: Describe new config options --- config/defaults.inc.php | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'config/defaults.inc.php') diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 625d4ea80..b5a6d422a 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -66,6 +66,10 @@ $config['log_driver'] = 'file'; // (read http://php.net/manual/en/function.date.php for all format characters) $config['log_date_format'] = 'd-M-Y H:i:s O'; +// length of the session ID to prepend each log line with +// set to 0 to avoid session IDs being logged. +$config['log_session_id'] = 8; + // Syslog ident string to use, if using the 'syslog' log driver. $config['syslog_id'] = 'roundcube'; @@ -181,6 +185,10 @@ $config['imap_force_ns'] = false; // Note: Because the list is cached, re-login is required after change. $config['imap_disabled_caps'] = array(); +// Log IMAP session identifers after each IMAP login. +// This is used to relate IMAP session with Roundcube user sessions +$config['imap_log_session'] = false; + // Type of IMAP indexes cache. Supported values: 'db', 'apc' and 'memcache'. $config['imap_cache'] = null; -- cgit v1.2.3 From aecdf0644d836660fc06eac91b5528e50f00efa8 Mon Sep 17 00:00:00 2001 From: Victor Benincasa Date: Tue, 12 Aug 2014 01:13:03 -0300 Subject: Remove $config['default_folders'] from config tips Remove $config['default_folders'] from config tips as this option was removed on commit dc0b500. Related ticket: http://trac.roundcube.net/ticket/1489737 --- config/defaults.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config/defaults.inc.php') diff --git a/config/defaults.inc.php b/config/defaults.inc.php index b5a6d422a..56791fb99 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -1028,7 +1028,7 @@ $config['force_7bit'] = false; // Defaults of the search field configuration. // The array can contain a per-folder list of header fields which should be considered when searching // The entry with key '*' stands for all folders which do not have a specific list set. -// Please note that folder names should to be in sync with $config['default_folders'] +// Please note that folder names should to be in sync with $config['*_mbox'] options $config['search_mods'] = null; // Example: array('*' => array('subject'=>1, 'from'=>1), 'Sent' => array('subject'=>1, 'to'=>1)); // Defaults of the addressbook search field configuration. -- cgit v1.2.3 From 44b47dfb359f8a7412208079202fca0adf741540 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Wed, 20 Aug 2014 08:30:24 +0200 Subject: Add config/preference option to disable saving messages in localStorage (#1489979) --- config/defaults.inc.php | 4 ++++ program/js/app.js | 9 +++++++-- program/localization/en_US/labels.inc | 1 + program/steps/mail/compose.inc | 1 + program/steps/settings/func.inc | 14 ++++++++++++++ program/steps/settings/save_prefs.inc | 1 + 6 files changed, 28 insertions(+), 2 deletions(-) (limited to 'config/defaults.inc.php') diff --git a/config/defaults.inc.php b/config/defaults.inc.php index 56791fb99..5e9a2bbdd 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -947,6 +947,10 @@ $config['compose_extwin'] = false; // 0 - never, 1 - always, 2 - on reply to HTML message, 3 - on forward or reply to HTML message $config['htmleditor'] = 0; +// save copies of compose messages in the browser's local storage +// for recovery in case of browser crashes and session timeout. +$config['compose_save_localstorage'] = true; + // show pretty dates as standard $config['prettydate'] = true; diff --git a/program/js/app.js b/program/js/app.js index 20ad93a1a..0fca47191 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -3361,7 +3361,8 @@ function rcube_webmail() } // check for locally stored compose data - this.compose_restore_dialog(0, html_mode) + if (this.env.save_localstorage) + this.compose_restore_dialog(0, html_mode) if (input_to.val() == '') input_to.focus(); @@ -3793,7 +3794,7 @@ function rcube_webmail() } // save compose form content to local storage every 5 seconds - if (!this.local_save_timer && window.localStorage) { + if (!this.local_save_timer && window.localStorage && this.env.save_localstorage) { // track typing activity and only save on changes this.compose_type_activity = this.compose_type_activity_last = 0; $(document).bind('keypress', function(e){ ref.compose_type_activity++; }); @@ -3849,6 +3850,10 @@ function rcube_webmail() // store the contents of the compose form to localstorage this.save_compose_form_local = function() { + // feature is disabled + if (!this.env.save_localstorage) + return; + var formdata = { session:this.env.session_id, changed:new Date().getTime() }, ed, empty = true; diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index 449b278f8..a8d9abc13 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -484,6 +484,7 @@ $labels['2231folding'] = 'Full RFC 2231 (Thunderbird)'; $labels['miscfolding'] = 'RFC 2047/2231 (MS Outlook)'; $labels['2047folding'] = 'Full RFC 2047 (other)'; $labels['force7bit'] = 'Use MIME encoding for 8-bit characters'; +$labels['savelocalstorage'] = "Save in the browser's local storage (temporarily)"; $labels['advancedoptions'] = 'Advanced options'; $labels['toggleadvancedoptions'] = 'Toggle advanced options'; $labels['focusonnewmessage'] = 'Focus browser window on new message'; diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index a3c8a8a64..1770a1bcb 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -91,6 +91,7 @@ $OUTPUT->set_env('session_id', session_id()); $OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); $OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); $OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); +$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage')); $drafts_mbox = $RCMAIL->config->get('drafts_mbox'); $config_show_sig = $RCMAIL->config->get('show_sig', 1); diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 619710f32..0b2039a78 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -918,6 +918,20 @@ function rcmail_user_prefs($current = null) ); } + if (!isset($no_override['compose_save_localstorage'])) { + if (!$current) { + continue 2; + } + + $field_id = 'rcmfd_compose_save_localstorage'; + $input = new html_checkbox(array('name' => '_compose_save_localstorage', 'id' => $field_id, 'value' => 1)); + + $blocks['advanced']['options']['compose_save_localstorage'] = array( + 'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('savelocalstorage'))), + 'content' => $input->show($config['compose_save_localstorage']?1:0), + ); + } + break; // Addressbook config diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index 7a17f21f4..f0ce9c9a3 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -90,6 +90,7 @@ case 'compose': 'default_font_size' => rcube_utils::get_input_value('_default_font_size', rcube_utils::INPUT_POST), 'reply_all_mode' => intval($_POST['_reply_all_mode']), 'forward_attachment' => !empty($_POST['_forward_attachment']), + 'compose_save_localstorage' => intval($_POST['_compose_save_localstorage']), ); break; -- cgit v1.2.3