diff --git a/CHANGELOG b/CHANGELOG
index 0e698307324..fc683ef037c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,7 +1,10 @@
CHANGELOG Roundcube Webmail
===========================
+- Add missing sql upgrade file for 'ip' column resize in session table (#5465)
+- Do not show inline images of unsupported mimetype (#5463)
- Password: Added LDAP PPolicy driver (#5364)
+- Password: Added possibility to nicely redirect from other plugins on password expiration (#5468)
- Implement separate action to mark all messages in a folder as \Seen (#5006)
- Implement marking as \Seen in all folders or in a folder and its subfolders (#5076)
- Archive: Don't reload messages list when it's not needed (#5225)
@@ -48,11 +51,16 @@ CHANGELOG Roundcube Webmail
- Managesieve: Unhide advanced rule controls if there are inputs with errors
- Managesieve: Display warning message when filter form contains errors
- Control search engine crawlers via X-Robots-Tag header instead of and robots.txt (#5098)
+- Fix flickering of header topline in min-mode (#5426)
- Fix bug where folders list would scroll to top when clicking on subscription checkbox (#5447)
- Fix decoding of GB2312/GBK text when iconv is not installed (#5448)
- Fix regression where creation of default folders wasn't functioning without prefix (#5460)
- Enigma: Fix bug where last records on keys list were hidden (#5461)
- Enigma: Fix key search with keyword containing non-ascii characters (#5459)
+- Fix bug where deleting folders with subfolders could fail in some cases (#5466)
+- Fix bug where IMAP password could be exposed via error message (#5472)
+- Fix bug where it wasn't possible to store more that 2MB objects in memcache/apc,
+ Added memcache_max_allowed_packet and apc_max_allowed_packet settings (#5452)
RELEASE 1.2.2
-------------
diff --git a/SQL/mssql.initial.sql b/SQL/mssql.initial.sql
index ac9d93f281e..e0f8763487f 100644
--- a/SQL/mssql.initial.sql
+++ b/SQL/mssql.initial.sql
@@ -393,6 +393,6 @@ CREATE TRIGGER [contact_delete_member] ON [dbo].[contacts]
WHERE [contact_id] IN (SELECT [contact_id] FROM deleted)
GO
-INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2016081200')
+INSERT INTO [dbo].[system] ([name], [value]) VALUES ('roundcube-version', '2016100900')
GO
\ No newline at end of file
diff --git a/SQL/mssql/2016100900.sql b/SQL/mssql/2016100900.sql
new file mode 100644
index 00000000000..38b359a4808
--- /dev/null
+++ b/SQL/mssql/2016100900.sql
@@ -0,0 +1,2 @@
+ALTER TABLE [dbo].[session] ALTER COLUMN [ip] [varchar] (40) COLLATE Latin1_General_CI_AI NOT NULL
+GO
diff --git a/SQL/mysql.initial.sql b/SQL/mysql.initial.sql
index 22ffcd0432d..cb2e75f260a 100644
--- a/SQL/mysql.initial.sql
+++ b/SQL/mysql.initial.sql
@@ -210,4 +210,4 @@ CREATE TABLE `system` (
/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2016081200');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2016100900');
diff --git a/SQL/mysql/2016100900.sql b/SQL/mysql/2016100900.sql
new file mode 100644
index 00000000000..ea096e9f90a
--- /dev/null
+++ b/SQL/mysql/2016100900.sql
@@ -0,0 +1 @@
+ALTER TABLE `session` MODIFY `ip` varchar(40) NOT NULL;
diff --git a/SQL/oracle.initial.sql b/SQL/oracle.initial.sql
index fabd2606bb4..668b7133353 100644
--- a/SQL/oracle.initial.sql
+++ b/SQL/oracle.initial.sql
@@ -219,4 +219,4 @@ CREATE TABLE "system" (
"value" long
);
-INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2016081200');
+INSERT INTO "system" ("name", "value") VALUES ('roundcube-version', '2016100900');
diff --git a/SQL/oracle/2016100900.sql b/SQL/oracle/2016100900.sql
new file mode 100644
index 00000000000..e92e7eb91fc
--- /dev/null
+++ b/SQL/oracle/2016100900.sql
@@ -0,0 +1 @@
+ALTER TABLE session MODIFY ip varchar(41) NOT NULL;
diff --git a/SQL/postgres.initial.sql b/SQL/postgres.initial.sql
index 6b2c93902b4..965bc54bd8b 100644
--- a/SQL/postgres.initial.sql
+++ b/SQL/postgres.initial.sql
@@ -291,4 +291,4 @@ CREATE TABLE "system" (
value text
);
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2016081200');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2016100900');
diff --git a/SQL/postgres/2016100900.sql b/SQL/postgres/2016100900.sql
new file mode 100644
index 00000000000..8eb7eedacb3
--- /dev/null
+++ b/SQL/postgres/2016100900.sql
@@ -0,0 +1 @@
+ALTER TABLE session ALTER COLUMN ip TYPE character varying(41);
diff --git a/SQL/sqlite.initial.sql b/SQL/sqlite.initial.sql
index 081fe6ab890..83d6881338f 100644
--- a/SQL/sqlite.initial.sql
+++ b/SQL/sqlite.initial.sql
@@ -202,4 +202,4 @@ CREATE TABLE system (
value text NOT NULL
);
-INSERT INTO system (name, value) VALUES ('roundcube-version', '2016081200');
+INSERT INTO system (name, value) VALUES ('roundcube-version', '2016100900');
diff --git a/SQL/sqlite/2016100900.sql b/SQL/sqlite/2016100900.sql
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/config/config.inc.php.sample b/config/config.inc.php.sample
index 2b72cc6d140..77f367265f9 100644
--- a/config/config.inc.php.sample
+++ b/config/config.inc.php.sample
@@ -41,7 +41,6 @@ $config['default_host'] = 'localhost';
// SMTP server host (for sending mails).
// To use SSL/TLS connection, enter hostname with prefix ssl:// or tls://
-// If left blank, the PHP mail() function is used
// Supported replacement variables:
// %h - user's IMAP hostname
// %n - hostname ($_SERVER['SERVER_NAME'])
@@ -49,7 +48,7 @@ $config['default_host'] = 'localhost';
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
-$config['smtp_server'] = '';
+$config['smtp_server'] = 'localhost';
// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
// deprecated SSL over SMTP (aka SMTPS))
@@ -57,11 +56,11 @@ $config['smtp_port'] = 25;
// SMTP username (if required) if you use %u as the username Roundcube
// will use the current username for login
-$config['smtp_user'] = '';
+$config['smtp_user'] = '%u';
// SMTP password (if required) if you use %p as the password Roundcube
// will use the current user's password for login
-$config['smtp_pass'] = '';
+$config['smtp_pass'] = '%p';
// provide an URL where a user can get support for this Roundcube installation
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
diff --git a/config/defaults.inc.php b/config/defaults.inc.php
index df5340462b7..74cd611e73e 100644
--- a/config/defaults.inc.php
+++ b/config/defaults.inc.php
@@ -308,6 +308,40 @@
$config['ldap_cache_ttl'] = '10m';
+// ----------------------------------
+// CACHE(S)
+// ----------------------------------
+
+// Use these hosts for accessing memcached
+// Define any number of hosts in the form of hostname:port or unix:///path/to/socket.file
+$config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock' );
+
+// Controls the use of a persistent connections to memcache servers
+// See http://php.net/manual/en/memcache.addserver.php
+$config['memcache_pconnect'] = true;
+
+// Value in seconds which will be used for connecting to the daemon
+// See http://php.net/manual/en/memcache.addserver.php
+$config['memcache_timeout'] = 1;
+
+// Controls how often a failed server will be retried (value in seconds).
+// Setting this parameter to -1 disables automatic retry.
+// See http://php.net/manual/en/memcache.addserver.php
+$config['memcache_retry_interval'] = 15;
+
+// use these hosts for accessing Redis.
+// Currently only one host is supported. cluster support may come in a future release.
+// You can pass 4 fields, host, port, database and password.
+// Unset fields will be set to the default values host=127.0.0.1, port=6379, database=0, password= (empty)
+$config['redis_hosts'] = null; // e.g. array( 'localhost:6379' ); array( '192.168.1.1:6379:1:secret' );
+
+// Maximum size of an object in memcache (in bytes). Default: 2MB
+$config['memcache_max_allowed_packet'] = '2M';
+
+// Maximum size of an object in APC cache (in bytes). Default: 2MB
+$config['apc_max_allowed_packet'] = '2M';
+
+
// ----------------------------------
// SYSTEM
// ----------------------------------
@@ -423,30 +457,6 @@
// Setting this value to 'php' will use the default session save handler configured in PHP
$config['session_storage'] = 'db';
-// Use these hosts for accessing memcached
-// Define any number of hosts in the form of hostname:port or unix:///path/to/socket.file
-$config['memcache_hosts'] = null; // e.g. array( 'localhost:11211', '192.168.1.12:11211', 'unix:///var/tmp/memcached.sock' );
-
-// Controls the use of a persistent connections to memcache servers
-// See http://php.net/manual/en/memcache.addserver.php
-$config['memcache_pconnect'] = true;
-
-// Value in seconds which will be used for connecting to the daemon
-// See http://php.net/manual/en/memcache.addserver.php
-$config['memcache_timeout'] = 1;
-
-// Controls how often a failed server will be retried (value in seconds).
-// Setting this parameter to -1 disables automatic retry.
-// See http://php.net/manual/en/memcache.addserver.php
-$config['memcache_retry_interval'] = 15;
-
-// use this for accessing redis
-// currently only one host is supported. cluster support may come in a future release.
-// you can pass 4 fields, host, port, database and password.
-// unset fields will be set to the default values host=127.0.0.1, port=6379, database=0, password= (empty)
-
-$config['redis_hosts'] = null; // e.g. array( 'localhost:6379' ); array( '192.168.1.1:6379:1:secret' );
-
// check client IP in session authorization
$config['ip_check'] = false;
diff --git a/plugins/database_attachments/config.inc.php.dist b/plugins/database_attachments/config.inc.php.dist
index c371cbbb73a..b47615b7908 100644
--- a/plugins/database_attachments/config.inc.php.dist
+++ b/plugins/database_attachments/config.inc.php.dist
@@ -3,6 +3,10 @@
// By default this plugin stores attachments in filesystem
// and copies them into sql database.
// You can change it to use 'memcache' or 'apc'.
+// -----------------------------------------------------------
+// WARNING: Remember to set max_allowed_packet in database or
+// config to match with expected max attachment size.
+// -----------------------------------------------------------
$config['database_attachments_cache'] = 'db';
// Attachment data expires after specied TTL time in seconds (max.2592000).
diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php
index b7fc011611d..7f2bf9b8e65 100644
--- a/plugins/enigma/lib/enigma_ui.php
+++ b/plugins/enigma/lib/enigma_ui.php
@@ -547,7 +547,7 @@ private function key_import()
else if ($err = $_FILES['_file']['error']) {
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
$this->rc->output->show_message('filesizeerror', 'error',
- array('size' => $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize')))));
+ array('size' => $this->rc->show_bytes(rcube_utils::max_upload_size())));
} else {
$this->rc->output->show_message('fileuploaderror', 'error');
}
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
index db50330eb71..0ceb7a72bc6 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
@@ -562,7 +562,7 @@ function save()
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
$msg = $this->rc->gettext(array('name' => 'filesizeerror',
'vars' => array('size' =>
- $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
+ $this->rc->show_bytes(rcube_utils::max_upload_size()))));
}
else {
$this->errors['file'] = $this->plugin->gettext('fileuploaderror');
diff --git a/plugins/password/composer.json b/plugins/password/composer.json
index 8c6848ca7ae..3cc0c397fca 100644
--- a/plugins/password/composer.json
+++ b/plugins/password/composer.json
@@ -3,7 +3,7 @@
"type": "roundcube-plugin",
"description": "Password Change for Roundcube. Plugin adds a possibility to change user password using many methods (drivers) via Settings/Password tab.",
"license": "GPLv3+",
- "version": "4.1",
+ "version": "4.2",
"authors": [
{
"name": "Aleksander Machniak",
diff --git a/plugins/password/localization/en_GB.inc b/plugins/password/localization/en_GB.inc
index 94e7657d3f3..ddd0c52de09 100644
--- a/plugins/password/localization/en_GB.inc
+++ b/plugins/password/localization/en_GB.inc
@@ -31,8 +31,8 @@ $messages['passwordweak'] = 'Password must include at least one number and one s
$messages['passwordforbidden'] = 'Password contains forbidden characters.';
$messages['firstloginchange'] = 'This is your first login. Please change your password.';
$messages['disablednotice'] = 'The system is currently under maintenance and password change is not possible at the moment. Everything should be back to normal soon. We apologise for any inconvenience.';
-$messages['passwdinhistory'] = 'This password has already been used previously';
-$messages['samepasswd'] = 'New password have to be different from the old one';
-$messages['passwdexpirewarning'] = 'Warning! Your password will expire soon, change it before $expirationdatetime';
-$messages['passwdexpired'] = 'Your password has expired, you have to change it now !';
+$messages['passwdinhistory'] = 'This password has already been used previously.';
+$messages['samepasswd'] = 'New password have to be different from the old one.';
+$messages['passwdexpirewarning'] = 'Warning! Your password will expire soon, change it before $expirationdatetime.';
+$messages['passwdexpired'] = 'Your password has expired, you have to change it now!';
diff --git a/plugins/password/localization/en_US.inc b/plugins/password/localization/en_US.inc
index fb9f3912bc4..b25495a33f1 100644
--- a/plugins/password/localization/en_US.inc
+++ b/plugins/password/localization/en_US.inc
@@ -35,8 +35,8 @@ $messages['passwordweak'] = 'Password must include at least one number and one p
$messages['passwordforbidden'] = 'Password contains forbidden characters.';
$messages['firstloginchange'] = 'This is your first login. Please change your password.';
$messages['disablednotice'] = 'The system is currently under maintenance and password change is not possible at the moment. Everything should be back to normal soon. We apologize for any inconvenience.';
-$messages['passwinhistory'] = 'This password has already been used previously';
-$messages['samepasswd'] = 'New password have to be different from the old one';
-$messages['passwdexpirewarning'] = 'Warning! Your password will expire soon, change it before $expirationdatetime';
-$messages['passwdexpired'] = 'Your password has expired, you have to change it now !';
+$messages['passwinhistory'] = 'This password has already been used previously.';
+$messages['samepasswd'] = 'New password have to be different from the old one.';
+$messages['passwdexpirewarning'] = 'Warning! Your password will expire soon, change it before $expirationdatetime.';
+$messages['passwdexpired'] = 'Your password has expired, you have to change it now!';
diff --git a/plugins/password/localization/pl_PL.inc b/plugins/password/localization/pl_PL.inc
index f2b9324c3ae..a12574d7941 100644
--- a/plugins/password/localization/pl_PL.inc
+++ b/plugins/password/localization/pl_PL.inc
@@ -33,5 +33,5 @@ $messages['firstloginchange'] = 'To jest twoje pierwsze logowanie. Proszę zmie
$messages['disablednotice'] = 'System jest w trakcie konserwacji i zmiana hasła w tym momencie nie jest możliwa. Wszystko powinno wrócić do normy w niedługim czasie. Przepraszamy za wszelkie niedogodności';
$messages['passwdinhistory'] = 'To hasło było już użyte poprzednio.';
$messages['samepasswd'] = 'Nowe hasło musi być inne niż obecne.';
-$messages['passwdexpirewarning'] = 'UWAGA! Twoje hasło niebawem wygaśnie, zmień je przed $expirationdatetime';
-$messages['passwdexpired'] = 'Twoje hasło wygasło, musisz je natychmiast zmienić !';
+$messages['passwdexpirewarning'] = 'UWAGA! Twoje hasło niebawem wygaśnie, zmień je przed $expirationdatetime.';
+$messages['passwdexpired'] = 'Twoje hasło wygasło, musisz je natychmiast zmienić!';
diff --git a/plugins/password/password.php b/plugins/password/password.php
index 4666ab3a8c7..2c594df801e 100644
--- a/plugins/password/password.php
+++ b/plugins/password/password.php
@@ -95,17 +95,18 @@ function password_init()
if (rcube_utils::get_input_value('_first', rcube_utils::INPUT_GET)) {
$rcmail->output->command('display_message', $this->gettext('firstloginchange'), 'notice');
}
-
- if (isset ($_SESSION['passwdexpdatetime'])) {
- if ($_SESSION['passwdexpdatetime'] == 1){
+ else if (!empty($_SESSION['password_expires'])) {
+ if ($_SESSION['password_expires'] == 1) {
$rcmail->output->command('display_message', $this->gettext('passwdexpired'), 'error');
}
else {
- $rcmail->output->command('display_message', $this->gettext(
- array('name' => 'passwdexpirewarning', 'vars' => array('expirationdatetime' => $_SESSION['passwdexpdatetime']))), 'warning');
- }
+ $rcmail->output->command('display_message', $this->gettext(array(
+ 'name' => 'passwdexpirewarning',
+ 'vars' => array('expirationdatetime' => $_SESSION['password_expires'])
+ )), 'warning');
+ }
}
-
+
$rcmail->output->send('plugin');
}
@@ -183,8 +184,9 @@ function password_save()
rcube::write_log('password', sprintf('Password changed for user %s (ID: %d) from %s',
$rcmail->get_user_name(), $rcmail->user->ID, rcube_utils::remote_ip()));
}
- // Remove expiration date/time
- $rcmail->session->remove('passwdexpdatetime');
+
+ // Remove expiration date/time
+ $rcmail->session->remove('password_expires');
}
else {
$rcmail->output->command('display_message', $res, 'error');
diff --git a/plugins/redundant_attachments/config.inc.php.dist b/plugins/redundant_attachments/config.inc.php.dist
index 47e84014b6b..9cc1b0034eb 100644
--- a/plugins/redundant_attachments/config.inc.php.dist
+++ b/plugins/redundant_attachments/config.inc.php.dist
@@ -4,6 +4,10 @@
// and copies them into sql database.
// In environments with replicated database it is possible
// to use memcache as a fallback when write-master is unavailable.
+// ------------------------------------------------------------
+// WARNING: Remember to also set memcache_max_allowed_packet in
+// config to match with expected max attachment size.
+// ------------------------------------------------------------
$config['redundant_attachments_memcache'] = false;
// Attachment data expires after specified TTL time in seconds (max.2592000).
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index fc6ea575d30..4402da0f6c2 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -2083,13 +2083,7 @@ public function upload_init($max_size = null)
}
// 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;
- }
-
+ $max_filesize = rcube_utils::max_upload_size();
if ($max_size && $max_size < $max_filesize) {
$max_filesize = $max_size;
}
diff --git a/program/js/editor.js b/program/js/editor.js
index f2fe604cf01..6eb473b6211 100644
--- a/program/js/editor.js
+++ b/program/js/editor.js
@@ -407,27 +407,41 @@ function rcube_text_editor(config, id)
};
// replace selection with text snippet
- this.replace = function(text)
+ // input can be a string or object with 'text' and 'html' properties
+ this.replace = function(input)
{
- var ed = this.editor;
+ var format, ed = this.editor;
// insert into tinymce editor
if (ed) {
ed.getWin().focus(); // correct focus in IE & Chrome
- ed.selection.setContent(rcmail.quote_html(text).replace(/\r?\n/g, '
'), { format:'text' });
+
+ if ($.type(input) == 'object') {
+ input = input.html;
+ format = 'html';
+ }
+ else {
+ input = rcmail.quote_html(input).replace(/\r?\n/g, '
');
+ format = 'text';
+ }
+
+ ed.selection.setContent(input, {format: format});
}
// replace selection in compose textarea
else if (ed = rcube_find_object(this.id)) {
- var selection = $(ed).is(':focus') ? rcmail.get_input_selection(ed) : { start:0, end:0 },
- inp_value = ed.value;
- pre = inp_value.substring(0, selection.start),
- end = inp_value.substring(selection.end, inp_value.length);
+ var selection = $(ed).is(':focus') ? rcmail.get_input_selection(ed) : {start: 0, end: 0},
+ value = ed.value;
+ pre = value.substring(0, selection.start),
+ end = value.substring(selection.end, value.length);
+
+ if ($.type(input) == 'object')
+ input = input.text;
// insert response text
- ed.value = pre + text + end;
+ ed.value = pre + input + end;
// set caret after inserted text
- rcmail.set_caret_pos(ed, selection.start + text.length);
+ rcmail.set_caret_pos(ed, selection.start + input.length);
ed.focus();
}
};
diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php
index 73b9a85d7a5..2cad9df9953 100644
--- a/program/lib/Roundcube/html.php
+++ b/program/lib/Roundcube/html.php
@@ -163,7 +163,7 @@ public static function img($attr = null)
}
return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib,
- array('src','alt','width','height','border','usemap','onclick','onerror')));
+ array('src','alt','width','height','border','usemap','onclick','onerror','onload')));
}
/**
diff --git a/program/lib/Roundcube/rcube_cache.php b/program/lib/Roundcube/rcube_cache.php
index 076a9ab0720..05e858cf0ba 100644
--- a/program/lib/Roundcube/rcube_cache.php
+++ b/program/lib/Roundcube/rcube_cache.php
@@ -645,16 +645,9 @@ private function max_packet_size()
}
$this->max_packet -= 2000;
}
- else if ($this->type == 'memcache') {
- if ($stats = $this->db->getStats()) {
- $remaining = $stats['limit_maxbytes'] - $stats['bytes'];
- $this->max_packet = min($remaining / 5, $this->max_packet);
- }
- }
- else if ($this->type == 'apc' && function_exists('apc_sma_info')) {
- if ($stats = apc_sma_info()) {
- $this->max_packet = min($stats['avail_mem'] / 5, $this->max_packet);
- }
+ else {
+ $max_packet = rcube::get_instance()->config->get($this->type . '_max_allowed_packet');
+ $this->max_packet = parse_bytes($max_packet) ?: $this->max_packet;
}
}
diff --git a/program/lib/Roundcube/rcube_cache_shared.php b/program/lib/Roundcube/rcube_cache_shared.php
index cbf87a4e24b..00d6345b3c7 100644
--- a/program/lib/Roundcube/rcube_cache_shared.php
+++ b/program/lib/Roundcube/rcube_cache_shared.php
@@ -632,16 +632,9 @@ private function max_packet_size()
}
$this->max_packet -= 2000;
}
- else if ($this->type == 'memcache') {
- if ($stats = $this->db->getStats()) {
- $remaining = $stats['limit_maxbytes'] - $stats['bytes'];
- $this->max_packet = min($remaining / 5, $this->max_packet);
- }
- }
- else if ($this->type == 'apc' && function_exists('apc_sma_info')) {
- if ($stats = apc_sma_info()) {
- $this->max_packet = min($stats['avail_mem'] / 5, $this->max_packet);
- }
+ else {
+ $max_packet = rcube::get_instance()->config->get($this->type . '_max_allowed_packet');
+ $this->max_packet = parse_bytes($max_packet) ?: $this->max_packet;
}
}
diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php
index cbc9f3b1c60..2d137e4dade 100644
--- a/program/lib/Roundcube/rcube_imap.php
+++ b/program/lib/Roundcube/rcube_imap.php
@@ -3293,49 +3293,48 @@ public function rename_folder($folder, $new_name)
}
/**
- * Remove folder from server
+ * Remove folder (with subfolders) from the server
*
* @param string $folder Folder name
*
- * @return boolean True on success
+ * @return boolean True on success, False on failure
*/
function delete_folder($folder)
{
- $delm = $this->get_hierarchy_delimiter();
-
if (!$this->check_connection()) {
return false;
}
- // get list of folders
- if ((strpos($folder, '%') === false) && (strpos($folder, '*') === false)) {
- $sub_mboxes = $this->list_folders('', $folder . $delm . '*');
- }
- else {
- $sub_mboxes = $this->list_folders();
- }
-
- // send delete command to server
- $result = $this->conn->deleteFolder($folder);
-
- if ($result) {
- // unsubscribe folder
- $this->conn->unsubscribe($folder);
+ $delm = $this->get_hierarchy_delimiter();
- foreach ($sub_mboxes as $c_mbox) {
- if (strpos($c_mbox, $folder.$delm) === 0) {
- $this->conn->unsubscribe($c_mbox);
- if ($this->conn->deleteFolder($c_mbox)) {
- $this->clear_message_cache($c_mbox);
+ // get list of sub-folders or all folders
+ // if folder name contains special characters
+ $path = strspn($folder, '%*') > 0 ? ($folder . $delm) : '';
+ $sub_mboxes = $this->list_folders('', $path . '*');
+
+ // According to RFC3501 deleting a \Noselect folder
+ // with subfolders may fail. To workaround this we delete
+ // subfolders first (in reverse order) (#5466)
+ if (!empty($sub_mboxes)) {
+ foreach (array_reverse($sub_mboxes) as $mbox) {
+ if (strpos($mbox, $folder . $delm) === 0) {
+ if ($this->conn->deleteFolder($mbox)) {
+ $this->conn->unsubscribe($mbox);
+ $this->clear_message_cache($mbox);
}
}
}
+ }
- // clear folder-related cache
+ // delete the folder
+ if ($result = $this->conn->deleteFolder($folder)) {
+ // and unsubscribe it
+ $this->conn->unsubscribe($folder);
$this->clear_message_cache($folder);
- $this->clear_cache('mailboxes', true);
}
+ $this->clear_cache('mailboxes', true);
+
return $result;
}
diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php
index 98352c27509..4751d15fa8e 100644
--- a/program/lib/Roundcube/rcube_imap_generic.php
+++ b/program/lib/Roundcube/rcube_imap_generic.php
@@ -2028,7 +2028,7 @@ public function fetchHeaderIndex($mailbox, $message_set, $index_field = '', $ski
$request = "$key $cmd $message_set (" . implode(' ', $fields) . ")";
if (!$this->putLine($request)) {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
+ $this->setError(self::ERROR_COMMAND, "Failed to send $cmd command");
return false;
}
@@ -2355,15 +2355,15 @@ public function fetch($mailbox, $message_set, $is_uid = false, $query_items = ar
$result = array();
$key = $this->nextTag();
- $request = $key . ($is_uid ? ' UID' : '') . " FETCH $message_set ";
- $request .= "(" . implode(' ', $query_items) . ")";
+ $cmd = ($is_uid ? 'UID ' : '') . 'FETCH';
+ $request = "$key $cmd $message_set (" . implode(' ', $query_items) . ")";
if ($mod_seq !== null && $this->hasCapability('CONDSTORE')) {
$request .= " (CHANGEDSINCE $mod_seq" . ($vanished ? " VANISHED" : '') .")";
}
if (!$this->putLine($request)) {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
+ $this->setError(self::ERROR_COMMAND, "Failed to send $cmd command");
return false;
}
@@ -2714,7 +2714,7 @@ public function fetchMIMEHeaders($mailbox, $uid, $parts, $mime = true)
// send request
if (!$this->putLine($request)) {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
+ $this->setError(self::ERROR_COMMAND, "Failed to send UID FETCH command");
return false;
}
@@ -2782,14 +2782,15 @@ public function handlePartBody($mailbox, $id, $is_uid=false, $part='', $encoding
// format request
$key = $this->nextTag();
- $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id ($fetch_mode.PEEK[$part]$partial)";
+ $cmd = ($is_uid ? 'UID ' : '') . 'FETCH';
+ $request = "$key $cmd $id ($fetch_mode.PEEK[$part]$partial)";
$result = false;
$found = false;
$initiated = true;
// send request
if (!$this->putLine($request)) {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
+ $this->setError(self::ERROR_COMMAND, "Failed to send $cmd command");
return false;
}
@@ -2990,65 +2991,66 @@ public function append($mailbox, &$message, $flags = array(), $date = null, $bin
$request .= ' ' . ($binary ? '~' : '') . '{' . $len . ($literal_plus ? '+' : '') . '}';
// send APPEND command
- if ($this->putLine($request)) {
- // Do not wait when LITERAL+ is supported
- if (!$literal_plus) {
- $line = $this->readReply();
+ if (!$this->putLine($request)) {
+ $this->setError(self::ERROR_COMMAND, "Failed to send APPEND command");
+ return false;
+ }
- if ($line[0] != '+') {
- $this->parseResult($line, 'APPEND: ');
- return false;
- }
+ // Do not wait when LITERAL+ is supported
+ if (!$literal_plus) {
+ $line = $this->readReply();
+
+ if ($line[0] != '+') {
+ $this->parseResult($line, 'APPEND: ');
+ return false;
}
+ }
- foreach ($msg as $msg_part) {
- // file pointer
- if (is_resource($msg_part)) {
- rewind($msg_part);
- while (!feof($msg_part) && $this->fp) {
- $buffer = fread($msg_part, $chunk_size);
- $this->putLine($buffer, false);
- }
- fclose($msg_part);
+ foreach ($msg as $msg_part) {
+ // file pointer
+ if (is_resource($msg_part)) {
+ rewind($msg_part);
+ while (!feof($msg_part) && $this->fp) {
+ $buffer = fread($msg_part, $chunk_size);
+ $this->putLine($buffer, false);
}
- // string
- else {
- $size = strlen($msg_part);
+ fclose($msg_part);
+ }
+ // string
+ else {
+ $size = strlen($msg_part);
- // Break up the data by sending one chunk (up to 512k) at a time.
- // This approach reduces our peak memory usage
- for ($offset = 0; $offset < $size; $offset += $chunk_size) {
- $chunk = substr($msg_part, $offset, $chunk_size);
- if (!$this->putLine($chunk, false)) {
- return false;
- }
+ // Break up the data by sending one chunk (up to 512k) at a time.
+ // This approach reduces our peak memory usage
+ for ($offset = 0; $offset < $size; $offset += $chunk_size) {
+ $chunk = substr($msg_part, $offset, $chunk_size);
+ if (!$this->putLine($chunk, false)) {
+ return false;
}
}
}
+ }
- if (!$this->putLine('')) { // \r\n
- return false;
- }
+ if (!$this->putLine('')) { // \r\n
+ return false;
+ }
- do {
- $line = $this->readLine();
- } while (!$this->startsWith($line, $key, true, true));
+ do {
+ $line = $this->readLine();
+ } while (!$this->startsWith($line, $key, true, true));
- // Clear internal status cache
- unset($this->data['STATUS:'.$mailbox]);
+ // Clear internal status cache
+ unset($this->data['STATUS:'.$mailbox]);
- if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK)
- return false;
- else if (!empty($this->data['APPENDUID']))
- return $this->data['APPENDUID'];
- else
- return true;
+ if ($this->parseResult($line, 'APPEND: ') != self::ERROR_OK) {
+ return false;
}
- else {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $request");
+
+ if (!empty($this->data['APPENDUID'])) {
+ return $this->data['APPENDUID'];
}
- return false;
+ return true;
}
/**
@@ -3707,7 +3709,10 @@ public function execute($command, $arguments=array(), $options=0)
// Send command
if (!$this->putLineC($query, true, ($options & self::COMMAND_ANONYMIZED))) {
- $this->setError(self::ERROR_COMMAND, "Unable to send command: $query");
+ preg_match('/^[A-Z0-9]+ ((UID )?[A-Z]+)/', $query, $matches);
+ $cmd = $matches[1] ?: 'UNKNOWN';
+ $this->setError(self::ERROR_COMMAND, "Failed to send $cmd command");
+
return $noresp ? self::ERROR_COMMAND : array(self::ERROR_COMMAND, '');
}
diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php
index 30168f884f1..d52c62115d7 100644
--- a/program/lib/Roundcube/rcube_utils.php
+++ b/program/lib/Roundcube/rcube_utils.php
@@ -1274,4 +1274,22 @@ public static function parse_socket_options(&$options, $host = null)
$options = $options[$host];
}
}
+
+ /**
+ * Get maximum upload size
+ *
+ * @return int Maximum size in bytes
+ */
+ public static function max_upload_size()
+ {
+ // 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;
+ }
+
+ return $max_filesize;
+ }
}
diff --git a/program/steps/addressbook/import.inc b/program/steps/addressbook/import.inc
index 4425498712c..2161d9170ac 100644
--- a/program/steps/addressbook/import.inc
+++ b/program/steps/addressbook/import.inc
@@ -77,7 +77,7 @@ if (is_array($_FILES['_file'])) {
// no vcards detected
if (!count($vcards)) {
if ($upload_error == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
- $size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+ $size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
$OUTPUT->show_message('filesizeerror', 'error', array('size' => $size));
}
else if ($upload_error) {
diff --git a/program/steps/addressbook/upload_photo.inc b/program/steps/addressbook/upload_photo.inc
index 4661ed2d2b9..6a5395b91b9 100644
--- a/program/steps/addressbook/upload_photo.inc
+++ b/program/steps/addressbook/upload_photo.inc
@@ -64,7 +64,7 @@ if ($filepath = $_FILES['_photo']['tmp_name']) {
}
else { // upload failed
$err = $_FILES['_photo']['error'];
- $size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+ $size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE)
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc
index 8c1993e670d..b620cd8f72d 100644
--- a/program/steps/mail/attachments.inc
+++ b/program/steps/mail/attachments.inc
@@ -160,7 +160,7 @@ if (is_array($_FILES['_attachments']['tmp_name'])) {
}
else { // upload failed
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
- $size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+ $size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
}
else if ($attachment['error']) {
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index dc6b4d24c99..b3f60c93885 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1322,6 +1322,7 @@ function rcmail_message_body($attrib)
if ($mimetype = rcmail_part_image_type($attach_prop)) {
// display thumbnails
if ($thumbnail_size) {
+ $supported = in_array($mimetype, $client_mimetypes);
$show_link = array(
'href' => $MESSAGE->get_part_url($attach_prop->mime_id, false),
'onclick' => sprintf(
@@ -1329,7 +1330,8 @@ function rcmail_message_body($attrib)
rcmail_output::JS_OBJECT_NAME,
$attach_prop->mime_id)
);
- $out .= html::p('image-attachment',
+
+ $out .= html::p(array('class' => 'image-attachment', 'style' => $supported ? '' : 'display:none'),
html::a($show_link + array('class' => 'image-link', 'style' => sprintf('width:%dpx', $thumbnail_size)),
html::img(array(
'class' => 'image-thumbnail',
@@ -1337,12 +1339,13 @@ function rcmail_message_body($attrib)
'title' => $attach_prop->filename,
'alt' => $attach_prop->filename,
'style' => sprintf('max-width:%dpx; max-height:%dpx', $thumbnail_size, $thumbnail_size),
+ 'onload' => $supported ? '' : '$(this).parents(\'p.image-attachment\').show()',
))
) .
html::span('image-filename', rcube::Q($attach_prop->filename)) .
html::span('image-filesize', rcube::Q($RCMAIL->message_part_size($attach_prop))) .
html::span('attachment-links',
- (in_array($mimetype, $client_mimetypes) ? html::a($show_link, $RCMAIL->gettext('showattachment')) . ' ' : '') .
+ ($supported ? html::a($show_link, $RCMAIL->gettext('showattachment')) . ' ' : '') .
html::a($show_link['href'] . '&_download=1', $RCMAIL->gettext('download'))
) .
html::br(array('style' => 'clear:both'))
diff --git a/program/steps/mail/import.inc b/program/steps/mail/import.inc
index 55941e8a273..9c4eb83a5af 100644
--- a/program/steps/mail/import.inc
+++ b/program/steps/mail/import.inc
@@ -92,7 +92,7 @@ if (is_array($_FILES['_file'])) {
}
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
- $size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+ $size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
$msg = $RCMAIL->gettext(array('name' => 'filesizeerror', 'vars' => array('size' => $size)));
}
else if ($err) {
diff --git a/program/steps/settings/upload.inc b/program/steps/settings/upload.inc
index dc81982a0df..99b398d3c8a 100644
--- a/program/steps/settings/upload.inc
+++ b/program/steps/settings/upload.inc
@@ -47,7 +47,7 @@ $IMAGE_TYPES = explode(',', 'jpeg,jpg,jp2,tiff,tif,bmp,eps,gif,png,png8,png24,pn
$OUTPUT->reset();
$max_size = $RCMAIL->config->get($type . '_image_size', 64) * 1024;
-$post_size = $RCMAIL->show_bytes(parse_bytes(ini_get('upload_max_filesize')));
+$post_size = $RCMAIL->show_bytes(rcube_utils::max_upload_size());
$uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GET);
diff --git a/skins/larry/images/filetypes.png b/skins/larry/images/filetypes.png
index 020c37d97c4..1294718cdf0 100644
Binary files a/skins/larry/images/filetypes.png and b/skins/larry/images/filetypes.png differ
diff --git a/skins/larry/includes/footer.html b/skins/larry/includes/footer.html
index 6cd3e62d133..cade440bd6b 100644
--- a/skins/larry/includes/footer.html
+++ b/skins/larry/includes/footer.html
@@ -1,13 +1,2 @@