summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--CHANGELOG2
-rw-r--r--composer.json-dist33
-rw-r--r--config/main.inc.php.dist10
-rw-r--r--program/include/rcube_imap.php5
-rw-r--r--program/include/rcube_output_html.php183
-rw-r--r--program/js/app.js19
-rw-r--r--program/steps/mail/compose.inc5
-rw-r--r--program/steps/mail/func.inc16
-rw-r--r--program/steps/mail/list.inc36
-rw-r--r--program/steps/mail/sendmail.inc11
-rw-r--r--program/steps/settings/func.inc3
-rw-r--r--skins/classic/templates/compose.html4
-rw-r--r--skins/larry/mail.css5
-rw-r--r--skins/larry/templates/compose.html2
15 files changed, 235 insertions, 106 deletions
diff --git a/.gitignore b/.gitignore
index f55131f8c..c410c9b8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,9 @@
logs/*
temp/*
config/*
-plugins/*/config.inc.php \ No newline at end of file
+plugins/*/config.inc.php
+
+# composer-related
+composer.phar
+composer.lock
+vendor
diff --git a/CHANGELOG b/CHANGELOG
index 6705a92ea..ff33fd99f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail
===========================
+- Add option to disable saving sent mail in Sent folder - no_save_sent_messages (#1488686)
+- Fix handling dont_override with message_sort_col and message_sort_order settings (#1488760)
- Fix HTML part detection in messages with attachments (#1488769)
- Fix bug where wrong words were highlighted on spell-before-send check
- Fix handling of URLs with asterisk characters (#1488759)
diff --git a/composer.json-dist b/composer.json-dist
new file mode 100644
index 000000000..104b572c4
--- /dev/null
+++ b/composer.json-dist
@@ -0,0 +1,33 @@
+{
+ "name": "roundcube/roundcubemail",
+ "description": "The Roundcube Webmail suite",
+ "license": "GPL-3.0",
+ "repositories": [
+ {
+ "packagist": false
+ },
+ {
+ "type": "pear",
+ "url": "http://pear.php.net/"
+ },
+ {
+ "type": "package",
+ "package": {
+ "name": "Net_SMTP",
+ "version": "dev-master",
+ "source": {
+ "url": "http://github.com/pear/Net_SMTP",
+ "type": "git",
+ "reference": "master"
+ }
+ }
+ }
+ ],
+ "require" : {
+ "pear-pear/Mail_Mime": ">=1.8.1",
+ "pear-pear/Mail_mimeDecode": ">=1.5.5",
+ "Net_SMTP": "dev-master",
+ "pear-pear/Net_IDNA2": ">=0.1.1",
+ "pear-pear/Auth_SASL": ">=1.0.6"
+ }
+}
diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist
index 770d9f4d8..2ee4ccd27 100644
--- a/config/main.inc.php.dist
+++ b/config/main.inc.php.dist
@@ -182,6 +182,9 @@ $rcmail_config['smtp_timeout'] = 0;
// ONLY ENABLE IT IF YOU'RE REALLY SURE WHAT YOU'RE DOING!
$rcmail_config['enable_installer'] = false;
+// don't allow these settings to be overriden by the user
+$rcmail_config['dont_override'] = array();
+
// provide an URL where a user can get support for this Roundcube installation
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
$rcmail_config['support_url'] = '';
@@ -349,9 +352,6 @@ $rcmail_config['line_length'] = 72;
// send plaintext messages as format=flowed
$rcmail_config['send_format_flowed'] = true;
-// don't allow these settings to be overriden by the user
-$rcmail_config['dont_override'] = array();
-
// Set identities access level:
// 0 - many identities with possibility to edit all params
// 1 - many identities with possibility to edit all params but not email address
@@ -379,6 +379,10 @@ $rcmail_config['contact_photo_size'] = 160;
// Enable DNS checking for e-mail address validation
$rcmail_config['email_dns_check'] = false;
+// Disables saving sent messages in Sent folder (like gmail) (Default: false)
+// Note: useful when SMTP server stores sent mail in user mailbox
+$rcmail_config['no_save_sent_messages'] = false;
+
// ----------------------------------
// PLUGINS
// ----------------------------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 1e6cf360b..a89fd164d 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -4119,6 +4119,11 @@ class rcube_imap extends rcube_storage
return $this->delete_folder($folder);
}
+ function clear_mailbox($folder = null)
+ {
+ return $this->clear_folder($folder);
+ }
+
public function mailbox_exists($folder, $subscription=false)
{
return $this->folder_exists($folder, $subscription);
diff --git a/program/include/rcube_output_html.php b/program/include/rcube_output_html.php
index 6138e2a30..2e3cd506d 100644
--- a/program/include/rcube_output_html.php
+++ b/program/include/rcube_output_html.php
@@ -33,7 +33,7 @@ class rcube_output_html extends rcube_output
protected $js_env = array();
protected $js_labels = array();
protected $js_commands = array();
- protected $plugin_skin_path;
+ protected $skin_paths = array();
protected $template_name;
protected $scripts_path = '';
protected $script_files = array();
@@ -161,9 +161,27 @@ class rcube_output_html extends rcube_output
$this->config->set('skin_path', $skin_path);
+ // register skin path(s)
+ $this->skin_paths = array();
+ $this->load_skin($skin_path);
+
return $valid;
}
+ /**
+ * Helper method to recursively read skin meta files and register search paths
+ */
+ private function load_skin($skin_path)
+ {
+ $this->skin_paths[] = $skin_path;
+
+ // read meta file and check for dependecies
+ $meta = @json_decode(@file_get_contents($skin_path.'/meta.json'), true);
+ if ($meta['extends'] && is_dir('skins/' . $meta['extends'])) {
+ $this->load_skin('skins/' . $meta['extends']);
+ }
+ }
+
/**
* Check if a specific template exists
@@ -173,8 +191,14 @@ class rcube_output_html extends rcube_output
*/
public function template_exists($name)
{
- $filename = $this->config->get('skin_path') . '/templates/' . $name . '.html';
- return (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]));
+ $found = false;
+ foreach ($this->skin_paths as $skin_path) {
+ $filename = $skin_path . '/templates/' . $name . '.html';
+ $found = (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]));
+ if ($found)
+ break;
+ }
+ return $found;
}
@@ -359,41 +383,60 @@ class rcube_output_html extends rcube_output
*/
function parse($name = 'main', $exit = true, $write = true)
{
- $skin_path = $this->config->get('skin_path');
$plugin = false;
$realname = $name;
- $temp = explode('.', $name, 2);
-
- $this->plugin_skin_path = null;
- $this->template_name = $realname;
+ $this->template_name = $realname;
+ $temp = explode('.', $name, 2);
if (count($temp) > 1) {
$plugin = $temp[0];
$name = $temp[1];
$skin_dir = $plugin . '/skins/' . $this->config->get('skin');
- $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
- // fallback to default skin
- if (!is_dir($skin_path)) {
+ // apply skin search escalation list to plugin directory
+ $plugin_skin_paths = array();
+ foreach ($this->skin_paths as $skin_path) {
+ $plugin_skin_paths[] = $this->app->plugins->dir . $plugin . '/' . $skin_path;
+ }
+
+ // add fallback to default skin
+ if (is_dir($this->app->plugins->dir . $plugin . '/skins/default')) {
$skin_dir = $plugin . '/skins/default';
- $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
+ $plugin_skin_paths[] = $this->app->plugins->dir . $skin_dir;
}
+
+ // add plugin skin paths to search list
+ $this->skin_paths = array_merge($plugin_skin_paths, $this->skin_paths);
}
- $path = "$skin_path/templates/$name.html";
+ // find skin template
+ $path = false;
+ foreach ($this->skin_paths as $skin_path) {
+ $path = "$skin_path/templates/$name.html";
- if (!is_readable($path) && $this->deprecated_templates[$realname]) {
- $path = "$skin_path/templates/".$this->deprecated_templates[$realname].".html";
- if (is_readable($path))
- rcube::raise_error(array('code' => 502, 'type' => 'php',
+ // fallback to deprecated template names
+ if (!is_readable($path) && $this->deprecated_templates[$realname]) {
+ $path = "$skin_path/templates/" . $this->deprecated_templates[$realname] . ".html";
+ rcube::raise_error(array(
+ 'code' => 502, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Using deprecated template '".$this->deprecated_templates[$realname]
- ."' in $skin_path/templates. Please rename to '".$realname."'"),
- true, false);
+ 'message' => "Using deprecated template '" . $this->deprecated_templates[$realname]
+ . "' in $skin_path/templates. Please rename to '$realname'"),
+ true, false);
+ }
+
+ if (is_readable($path)) {
+ $this->config->set('skin_path', $skin_path);
+ $this->base_path = $skin_path;
+ break;
+ }
+ else {
+ $path = false;
+ }
}
// read template file
- if (($templ = @file_get_contents($path)) === false) {
+ if (!$path || ($templ = @file_get_contents($path)) === false) {
rcube::raise_error(array(
'code' => 501,
'type' => 'php',
@@ -421,7 +464,7 @@ class rcube_output_html extends rcube_output
$output = $hook['content'];
unset($hook['content']);
- $output = $this->parse_with_globals($output);
+ $output = $this->parse_with_globals($this->fix_paths($output));
// make sure all <form> tags have a valid request token
$output = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $output);
@@ -493,7 +536,7 @@ class rcube_output_html extends rcube_output
public function abs_url($str)
{
if ($str[0] == '/')
- return $this->config->get('skin_path') . $str;
+ return $this->base_path . $str;
else
return $str;
}
@@ -527,7 +570,7 @@ class rcube_output_html extends rcube_output
{
$GLOBALS['__version'] = html::quote(RCMAIL_VERSION);
$GLOBALS['__comm_path'] = html::quote($this->app->comm_path);
- $GLOBALS['__skin_path'] = html::quote($this->config->get('skin_path'));
+ $GLOBALS['__skin_path'] = html::quote($this->base_path);
return preg_replace_callback('/\$(__[a-z0-9_\-]+)/',
array($this, 'globals_callback'), $input);
@@ -544,6 +587,43 @@ class rcube_output_html extends rcube_output
/**
+ * Correct absolute paths in images and other tags
+ * add timestamp to .js and .css filename
+ */
+ protected function fix_paths($output)
+ {
+ return preg_replace_callback(
+ '!(src|href|background)=(["\']?)([a-z0-9/_.-]+)(["\'\s>])!i',
+ array($this, 'file_callback'), $output);
+ }
+
+
+ /**
+ * Callback function for preg_replace_callback in write()
+ *
+ * @return string Parsed string
+ */
+ protected function file_callback($matches)
+ {
+ $file = $matches[3];
+
+ // correct absolute paths
+ if ($file[0] == '/') {
+ $file = $this->base_path . $file;
+ }
+
+ // add file modification timestamp
+ if (preg_match('/\.(js|css)$/', $file)) {
+ if ($fs = @filemtime($file)) {
+ $file .= '?s=' . $fs;
+ }
+ }
+
+ return $matches[1] . '=' . $matches[2] . $file . $matches[4];
+ }
+
+
+ /**
* Public wrapper to dipp into template parsing.
*
* @param string $input
@@ -705,6 +785,9 @@ class rcube_output_html extends rcube_output
// show a label
case 'label':
+ if ($attrib['expression'])
+ $attrib['name'] = eval("return " . $this->parse_expression($attrib['expression']) .";");
+
if ($attrib['name'] || $attrib['command']) {
// @FIXME: 'noshow' is useless, remove?
if ($attrib['noshow']) {
@@ -736,8 +819,17 @@ class rcube_output_html extends rcube_output
// include a file
case 'include':
- if (!$this->plugin_skin_path || !is_file($path = realpath($this->plugin_skin_path . $attrib['file'])))
- $path = realpath(($attrib['skin_path'] ? $attrib['skin_path'] : $this->config->get('skin_path')).$attrib['file']);
+ $old_base_path = $this->base_path;
+ $skin_paths = $this->skin_paths;
+ if ($attrib['skin_path'])
+ array_unshift($skin_paths, $attrib['skin_path']);
+ foreach ($skin_paths as $skin_path) {
+ $path = realpath($skin_path . $attrib['file']);
+ if (is_file($path)) {
+ $this->base_path = $skin_path;
+ break;
+ }
+ }
if (is_readable($path)) {
if ($this->config->get('skin_include_php')) {
@@ -747,14 +839,16 @@ class rcube_output_html extends rcube_output
$incl = file_get_contents($path);
}
$incl = $this->parse_conditions($incl);
- return $this->parse_xml($incl);
+ $incl = $this->parse_xml($incl);
+ $incl = $this->fix_paths($incl);
+ $this->base_path = $old_base_path;
+ return $incl;
}
break;
case 'plugin.include':
$hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib);
return $hook['content'];
- break;
// define a container block
case 'container':
@@ -1234,14 +1328,6 @@ class rcube_output_html extends rcube_output
$output = substr_replace($output, $css, $pos, 0);
}
- $this->base_path = $base_path;
-
- // correct absolute paths in images and other tags
- // add timestamp to .js and .css filename
- $output = preg_replace_callback(
- '!(src|href|background)=(["\']?)([a-z0-9/_.-]+)(["\'\s>])!i',
- array($this, 'file_callback'), $output);
-
// trigger hook with final HTML content to be sent
$hook = $this->app->plugins->exec_hook("send_page", array('content' => $output));
if (!$hook['abort']) {
@@ -1256,31 +1342,6 @@ class rcube_output_html extends rcube_output
/**
- * Callback function for preg_replace_callback in write()
- *
- * @return string Parsed string
- */
- protected function file_callback($matches)
- {
- $file = $matches[3];
-
- // correct absolute paths
- if ($file[0] == '/') {
- $file = $this->base_path . $file;
- }
-
- // add file modification timestamp
- if (preg_match('/\.(js|css)$/', $file)) {
- if ($fs = @filemtime($file)) {
- $file .= '?s=' . $fs;
- }
- }
-
- return $matches[1] . '=' . $matches[2] . $file . $matches[4];
- }
-
-
- /**
* Returns iframe object, registers some related env variables
*
* @param array $attrib HTML attributes
diff --git a/program/js/app.js b/program/js/app.js
index 06eb9295c..8296400ba 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -594,12 +594,11 @@ function rcube_webmail()
break;
case 'sort':
- var sort_order, sort_col = props;
+ var sort_order = this.env.sort_order,
+ sort_col = !this.env.disabled_sort_col ? props : this.env.sort_col;
- if (this.env.sort_col==sort_col)
- sort_order = this.env.sort_order=='ASC' ? 'DESC' : 'ASC';
- else
- sort_order = 'ASC';
+ if (!this.env.disabled_sort_order)
+ sort_order = this.env.sort_col == sort_col && sort_order == 'ASC' ? 'DESC' : 'ASC';
// set table header and update env
this.set_list_sorting(sort_col, sort_order);
@@ -5733,13 +5732,11 @@ function rcube_webmail()
col = this.env.coltypes[n];
if ((cell = thead.rows[0].cells[n]) && (col == 'from' || col == 'to' || col == 'fromto')) {
cell.id = 'rcm'+col;
+ $('span,a', cell).text(this.get_label(col == 'fromto' ? smart_col : col));
// if we have links for sorting, it's a bit more complicated...
- if (cell.firstChild && cell.firstChild.tagName.toLowerCase()=='a') {
- cell = cell.firstChild;
- cell.onclick = function(){ return rcmail.command('sort', this.__col, this); };
- cell.__col = col;
- }
- cell.innerHTML = this.get_label(col == 'fromto' ? smart_col : col);
+ $('a', cell).click(function(){
+ return rcmail.command('sort', this.id.replace(/^rcm/, ''), this);
+ });
}
}
}
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 691eca2db..7ac9a8d39 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -1528,6 +1528,11 @@ function rcmail_check_sent_folder($folder, $create=false)
{
global $RCMAIL;
+ // we'll not save the message, so it doesn't matter
+ if ($RCMAIL->config->get('no_save_sent_messages')) {
+ return true;
+ }
+
if ($RCMAIL->storage->folder_exists($folder, true)) {
return true;
}
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 39bccac16..4302bf9af 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -381,6 +381,8 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
*/
function rcmail_message_list_head($attrib, $a_show_cols)
{
+ global $RCMAIL;
+
$skin_path = $_SESSION['skin_path'];
$image_tag = html::img(array('src' => "%s%s", 'alt' => "%s"));
@@ -388,8 +390,18 @@ function rcmail_message_list_head($attrib, $a_show_cols)
$sort_col = $_SESSION['sort_col'];
$sort_order = $_SESSION['sort_order'];
+ $dont_override = (array)$RCMAIL->config->get('dont_override');
+ $disabled_sort = in_array('message_sort_col', $dont_override);
+ $disabled_order = in_array('message_sort_order', $dont_override);
+
+ $RCMAIL->output->set_env('disabled_sort_col', $disabled_sort);
+ $RCMAIL->output->set_env('disabled_sort_order', $disabled_order);
+
// define sortable columns
- $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc');
+ if ($disabled_sort)
+ $a_sort_cols = $sort_col && !$disabled_order ? array($sort_col) : array();
+ else
+ $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc');
if (!empty($attrib['optionsmenuicon'])) {
$onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')";
@@ -439,7 +451,7 @@ function rcmail_message_list_head($attrib, $a_show_cols)
else if ($col_name[0] != '<')
$col_name = '<span class="' . $col .'">' . $col_name . '</span>';
- $sort_class = $col == $sort_col ? " sorted$sort_order" : '';
+ $sort_class = $col == $sort_col && !$disabled_order ? " sorted$sort_order" : '';
$class_name = $col.$sort_class;
// put it all together
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index b5d579d7d..b433f81fc 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -23,27 +23,33 @@ if (!$OUTPUT->ajax_call) {
return;
}
+$save_arr = array();
+$dont_override = (array) $RCMAIL->config->get('dont_override');
+
// is there a sort type for this request?
-if ($sort = get_input_value('_sort', RCUBE_INPUT_GET))
-{
+if ($sort = get_input_value('_sort', RCUBE_INPUT_GET)) {
// yes, so set the sort vars
list($sort_col, $sort_order) = explode('_', $sort);
// set session vars for sort (so next page and task switch know how to sort)
- $save_arr = array();
- $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
- $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
+ if (!in_array('message_sort_col', $dont_override)) {
+ $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
+ }
+ if (!in_array('message_sort_order', $dont_override)) {
+ $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
+ }
}
// is there a set of columns for this request?
-if ($cols = get_input_value('_cols', RCUBE_INPUT_GET))
-{
- $save_arr = array();
- $save_arr['list_cols'] = explode(',', $cols);
+if ($cols = get_input_value('_cols', RCUBE_INPUT_GET)) {
+ if (!in_array('list_cols', $dont_override)) {
+ $save_arr['list_cols'] = explode(',', $cols);
+ }
}
-if ($save_arr)
+if (!empty($save_arr)) {
$RCMAIL->user->save_prefs($save_arr);
+}
$mbox_name = $RCMAIL->storage->get_folder();
$threading = (bool) $RCMAIL->storage->get_threading();
@@ -52,8 +58,7 @@ $threading = (bool) $RCMAIL->storage->get_threading();
$RCMAIL->storage->folder_sync($mbox_name);
// initialize searching result if search_filter is used
-if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL')
-{
+if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
$search_request = md5($mbox_name.$_SESSION['search_filter']);
$RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCMAIL_CHARSET, rcmail_sort_column());
$_SESSION['search'] = $RCMAIL->storage->get_search_set();
@@ -76,7 +81,6 @@ else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) {
$RCMAIL->session->remove('search');
}
-
// empty result? we'll skip UNSEEN counting in rcmail_send_unread_count()
if (empty($search_request) && empty($a_headers)) {
$unseen = 0;
@@ -96,10 +100,10 @@ $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text());
// add message rows
rcmail_js_message_list($a_headers, FALSE, $cols);
-if (isset($a_headers) && count($a_headers))
-{
- if ($search_request)
+if (isset($a_headers) && count($a_headers)) {
+ if ($search_request) {
$OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+ }
}
else {
// handle IMAP errors (e.g. #1486905)
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 9fe510794..4fac872d1 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -49,7 +49,7 @@ if (!$savedraft) {
if(!empty($CONFIG['sendmail_delay'])) {
$wait_sec = time() - intval($CONFIG['sendmail_delay']) - intval($CONFIG['last_message_time']);
- if($wait_sec < 0) {
+ if ($wait_sec < 0) {
$OUTPUT->show_message('senttooquickly', 'error', array('sec' => $wait_sec * -1));
$OUTPUT->send('iframe');
}
@@ -676,19 +676,18 @@ if (!$savedraft)
$smtp_error, $mailbody_file, $smtp_opts);
// return to compose page if sending failed
- if (!$sent)
- {
+ if (!$sent) {
// remove temp file
if ($mailbody_file) {
unlink($mailbody_file);
- }
+ }
if ($smtp_error)
$OUTPUT->show_message($smtp_error['label'], 'error', $smtp_error['vars']);
else
$OUTPUT->show_message('sendingfailed', 'error');
$OUTPUT->send('iframe');
- }
+ }
// save message sent time
if (!empty($CONFIG['sendmail_delay']))
@@ -706,7 +705,7 @@ if (!$savedraft)
// Determine which folder to save message
if ($savedraft)
$store_target = $CONFIG['drafts_mbox'];
-else
+else if (!$RCMAIL->config->get('no_save_sent_messages'))
$store_target = isset($_POST['_store_target']) ? get_input_value('_store_target', RCUBE_INPUT_POST) : $CONFIG['sent_mbox'];
if ($store_target) {
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index c60d17f30..ba42e81f7 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -198,9 +198,6 @@ function rcmail_user_prefs($current=null)
$select_timezone->add('(GMT ' . $offset . ') ' . strtr($tzs, '_', ' '), $tzs);
}
- if (is_numeric($config['timezone']))
- timezone_name_from_abbr("", $config['timezone'] * 3600, 0);
-
$blocks['main']['options']['timezone'] = array(
'title' => html::label($field_id, Q(rcube_label('timezone'))),
'content' => $select_timezone->show((string)$config['timezone']),
diff --git a/skins/classic/templates/compose.html b/skins/classic/templates/compose.html
index 1e1403e18..23998ee0f 100644
--- a/skins/classic/templates/compose.html
+++ b/skins/classic/templates/compose.html
@@ -143,10 +143,10 @@
</tr><tr>
<td><label for="rcmcomposepriority"><roundcube:label name="priority" />:</label></td>
<td><roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" /></td>
- </tr><tr>
+ </tr><roundcube:if condition="!config:no_save_sent_messages" /><tr>
<td><label><roundcube:label name="savesentmessagein" />:</label></td>
<td><roundcube:object name="storetarget" maxlength="30" /></td>
- </tr>
+ </tr><roundcube:endif />
</table>
</div>
diff --git a/skins/larry/mail.css b/skins/larry/mail.css
index 95d76c596..76ca4edfa 100644
--- a/skins/larry/mail.css
+++ b/skins/larry/mail.css
@@ -415,12 +415,15 @@ a.iconbutton.threadmode.selected {
border-left: 0;
}
-
#messagelist tr td.size {
width: 60px;
text-align: right;
}
+#messagelist thead tr td.size {
+ text-align: left;
+}
+
#messagelist tr td.fromto,
#messagelist tr td.from,
#messagelist tr td.to,
diff --git a/skins/larry/templates/compose.html b/skins/larry/templates/compose.html
index d29c1bd2a..ef49ece90 100644
--- a/skins/larry/templates/compose.html
+++ b/skins/larry/templates/compose.html
@@ -140,9 +140,11 @@
<span class="composeoption">
<label><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" /> <roundcube:label name="dsn" /></label>
</span>
+ <roundcube:if condition="!config:no_save_sent_messages" />
<span class="composeoption">
<label><roundcube:label name="savesentmessagein" /> <roundcube:object name="storetarget" maxlength="30" style="max-width:12em" /></label>
</span>
+ <roundcube:endif />
<roundcube:container name="composeoptions" id="composeoptions" />
</div>
</div>