[Pkg-roundcube-maintainers] Bug#887507: stretch-pu: package roundcube/1.2.3+dfsg.1-4+deb9u1

Sandro Knauß hefee at debian.org
Wed Jan 17 16:04:15 UTC 2018


Package: release.debian.org
Severity: normal
Tags: stretch
User: release.debian.org at packages.debian.org
Usertags: pu

Hey,

upstream releases only bugfix releases for the 1.2 branch. As they,
do not add any new feature IMO it would makes sense to ship the newest
1.2.7 for Debian Stretch users. This is a prepackage request, I havn't
packaged 1.2.7 for Debian yet, as I would only put effort into it, if it
can enter stretch in principal. What I can present at the current state
is a diff of the upstream tarballs (excluded the minified files, cause
we create those in the packageing process itself). I don't expect any
changes in the debian folder itself, but I would present a complete
debdiff, if you approved the general idea of shipping 1.2.7 via pu.


Regards,

sandro


-- System Information:
Debian Release: buster/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'stable-updates'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.14.0-3-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8), LANGUAGE=en_US (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
-------------- next part --------------
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/bin/installto.sh roundcubemail-1.2.7/bin/installto.sh
--- roundcubemail-1.2.3/bin/installto.sh	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/bin/installto.sh	2017-11-08 19:52:27.000000000 +0100
@@ -42,7 +42,6 @@
 $input = trim(fgets(STDIN));
 
 if (strtolower($input) == 'y') {
-  $err = false;
   echo "Copying files to target location...";
 
   // Save a copy of original .htaccess file (#1490623)
@@ -56,16 +55,16 @@
   }
   foreach ($dirs as $dir) {
     // @FIXME: should we use --delete for all directories?
-    $delete = in_array($dir, array('program', 'installer')) ? '--delete ' : '';
-    if (!system("rsync -avC " . $delete . INSTALL_PATH . "$dir/* $target_dir/$dir/")) {
-      $err = true;
-      break;
+    $delete  = in_array($dir, array('program', 'installer')) ? '--delete ' : '';
+    $command = "rsync -aC --out-format \"%n\" " . $delete . INSTALL_PATH . "$dir/* $target_dir/$dir/";
+    if (!system($command, $ret) || $ret > 0) {
+      rcube::raise_error("Failed to execute command: $command", false, true);
     }
   }
   foreach (array('index.php','.htaccess','config/defaults.inc.php','composer.json-dist','CHANGELOG','README.md','UPGRADING','LICENSE','INSTALL') as $file) {
-    if (!system("rsync -av " . INSTALL_PATH . "$file $target_dir/$file")) {
-      $err = true;
-      break;
+    $command = "rsync -a --out-format \"%n\" " . INSTALL_PATH . "$file $target_dir/$file";
+    if (file_exists(INSTALL_PATH . $file) && (!system($command, $ret) || $ret > 0)) {
+      rcube::raise_error("Failed to execute command: $command", false, true);
     }
   }
 
@@ -96,13 +95,12 @@
       echo "done.\n\n";
   }
 
-  if (!$err) {
-    echo "Running update script at target...\n";
-    system("cd $target_dir && php bin/update.sh --version=$oldversion");
-    echo "All done.\n";
-  }
+  echo "Running update script at target...\n";
+  system("cd $target_dir && php bin/update.sh --version=$oldversion");
+  echo "All done.\n";
 }
-else
+else {
   echo "Update cancelled. See ya!\n";
+}
 
 ?>
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/CHANGELOG roundcubemail-1.2.7/CHANGELOG
--- roundcubemail-1.2.3/CHANGELOG	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/CHANGELOG	2017-11-08 19:52:27.000000000 +0100
@@ -1,6 +1,61 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+RELEASE 1.2.7
+-------------
+- Fix rewind(): stream does not support seeking (#5950)
+- Fix bug where HTML messages could have been rendered empty on some systems (#5957)
+- Fix (again) bug where image data URIs in css style were treated as evil/remote in mail preview (#5580)
+- Managesieve: Fix parsing dot-staffed lines in multiline text (#5838, #5959)
+- Fix file disclosure vulnerability caused by insufficient input validation [CVE-2017-16651] (#6026)
+
+RELEASE 1.2.6
+-------------
+- Don't ignore (global) userlogins/sendmail logging in per_user_logging mode
+- Enigma: Fix compatibility with assets_dir
+- Managesieve: Fix AM/PM suffix in vacation time selectors
+- Fix bug where comment notation within style tag would cause the whole style to be ignored (#5747)
+- Fix bug where it wasn't possible to scroll folders list in Edge (#5750)
+- Fix addressbook searching by gender (#5757)
+- Fix SQL syntax error on MariaDB 10.2 (#5774)
+- Fix bug where it wasn't possible to set timezone to auto-detected value (#5782)
+- Fix uninitialized string offset in rcube_utils::bin2ascii() and make sure rcube_utils::random_bytes() result has always requested length (#5788)
+- Fix potential XSS vulnerability with malformed HTML message markup
+
+RELEASE 1.2.5
+-------------
+- Fix re-positioning of the fixed header of messages list in Chrome when using minimal mode toggle and About dialog (#5711)
+- Fix so settings/upload.inc could not be used by plugins (#5694)
+- Fix regression in LDAP fuzzy search where it always used prefix search instead (#5713)
+- Fix bug where namespace prefix could not be truncated on folders list if show_real_foldernames=true (#5695)
+- Fix bug where base_dn setting was ignored inside group_filters (#5720)
+- Password: Fix security issue in virtualmin and sasl drivers [CVE-2017-8114]
+
+RELEASE 1.2.4
+-------------
+- Managesieve: Fix handling of scripts with nested rules (#5540)
+- Managesieve: Fix parser issue with empty lines between comments (#5657)
+- Managesieve: Fix possible defect in handling \r\n in scripts (#5685)
+- Enigma: Fix handling of messages with nested PGP encrypted parts (#5634)
+- Enigma: Fix PHP fatal error when decrypting a message with invalid signature (#5555)
+- Enigma: Fix missing require statement for Crypt_GPG_KeyGenerator (#5641)
+- Fix variable substitution in ldap host for some use-cases, e.g. new_user_identity (#5544)
+- Fix adding images to new identity signatures
+- Fix rsync error handling in installto.sh script (#5562)
+- Fix some advanced search issues with multiple addressbooks (#5572)
+- Fix so group/addressbook selection is retained on page refresh
+- Fix bug where image data URIs in css style were treated as evil/remote in mail preview (#5580)
+- Fix bug where external content in src attribute of input/video tags was not secured (#5583)
+- Fix PHP error on update of a contact with multiple email addresses when using PHP 7.1 (#5587)
+- Fix bug where mail content frame couldn't be reset in some corner cases (#5608)
+- Fix bug where some classic skin images were not displayed in IE/Edge (#5614)
+- Fix bug where signature couldn't be added above the quote in Firefox 51 (#5628)
+- Fix regression where groups with email address were resolved to its members' addresses
+- Fix update of group name in the contacts list header on group rename (#5648)
+- Add rewrite rule to disable access to /vendor/bin folder in .htaccess (#5630)
+- Fix bug where it was too easy accidentally move a folder when using the subscription checkbox (#5655)
+- Fix XSS issue in handling of a style tag inside of an svg element (CVE-2017-6820)
+
 RELEASE 1.2.3
 -------------
 - Searching in both contacts and groups when LDAP addressbook with group_filters option is used
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/config/defaults.inc.php roundcubemail-1.2.7/config/defaults.inc.php
--- roundcubemail-1.2.3/config/defaults.inc.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/config/defaults.inc.php	2017-11-08 19:52:27.000000000 +0100
@@ -1032,11 +1032,11 @@
 // sort contacts by this col (preferably either one of name, firstname, surname)
 $config['addressbook_sort_col'] = 'surname';
 
-// the way how contact names are displayed in the list
-// 0: display name
-// 1: (prefix) firstname middlename surname (suffix)
-// 2: (prefix) surname firstname middlename (suffix)
-// 3: (prefix) surname, firstname middlename (suffix)
+// The way how contact names are displayed in the list.
+// 0: prefix firstname middlename surname suffix (only if display name is not set)
+// 1: firstname middlename surname
+// 2: surname firstname middlename
+// 3: surname, firstname middlename
 $config['addressbook_name_listing'] = 0;
 
 // use this timezone to display date/time
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/.htaccess roundcubemail-1.2.7/.htaccess
--- roundcubemail-1.2.3/.htaccess	2016-11-27 17:08:56.000000000 +0100
+++ roundcubemail-1.2.7/.htaccess	2017-11-08 19:52:27.000000000 +0100
@@ -33,6 +33,8 @@
 RewriteRule ^(?!installer|\.well-known\/|[a-zA-Z0-9]{16})(\.?[^\.]+)$ - [F]
 # - deny access to some locations
 RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|program\/(include|lib|localization|steps)) - [F]
+# - deny access to composer binaries
+RewriteRule ^/vendor\/bin\/.* - [F]
 # - deny access to some documentation files
 RewriteRule /?(README\.md|composer\.json-dist|composer\.json|package\.xml|Dockerfile)$ - [F]
 </IfModule>
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/index.php roundcubemail-1.2.7/index.php
--- roundcubemail-1.2.3/index.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/index.php	2017-11-08 19:52:27.000000000 +0100
@@ -2,9 +2,9 @@
 /**
  +-------------------------------------------------------------------------+
  | Roundcube Webmail IMAP Client                                           |
- | Version 1.2.3                                                           |
+ | Version 1.2.7                                                           |
  |                                                                         |
- | Copyright (C) 2005-2016, The Roundcube Dev Team                         |
+ | Copyright (C) 2005-2017, The Roundcube Dev Team                         |
  |                                                                         |
  | This program is free software: you can redistribute it and/or modify    |
  | it under the terms of the GNU General Public License (with exceptions   |
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/installer/index.php roundcubemail-1.2.7/installer/index.php
--- roundcubemail-1.2.3/installer/index.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/installer/index.php	2017-11-08 19:52:27.000000000 +0100
@@ -3,9 +3,9 @@
 /**
  +-------------------------------------------------------------------------+
  | Roundcube Webmail setup tool                                            |
- | Version 1.2.3                                                           |
+ | Version 1.2.7                                                           |
  |                                                                         |
- | Copyright (C) 2009-2016, The Roundcube Dev Team                         |
+ | Copyright (C) 2009-2017, The Roundcube Dev Team                         |
  |                                                                         |
  | This program is free software: you can redistribute it and/or modify    |
  | it under the terms of the GNU General Public License (with exceptions   |
Only in roundcubemail-1.2.3/plugins/acl: tests
Only in roundcubemail-1.2.3/plugins/additional_message_headers: tests
Only in roundcubemail-1.2.3/plugins/archive: tests
Only in roundcubemail-1.2.3/plugins/autologon: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/database_attachments/database_attachments.php roundcubemail-1.2.7/plugins/database_attachments/database_attachments.php
--- roundcubemail-1.2.3/plugins/database_attachments/database_attachments.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/database_attachments/database_attachments.php	2017-11-08 19:52:27.000000000 +0100
@@ -85,6 +85,8 @@
             if ($args['data'] === false) {
                 return $args;
             }
+
+            $args['path'] = null;
         }
 
         $data   = base64_encode($args['data']);
@@ -131,10 +133,13 @@
         $cache = $this->get_cache();
         $data  = $cache->read($args['id']);
 
-        if ($data) {
+        if ($data !== null && $data !== false) {
             $args['data'] = base64_decode($data);
             $args['status'] = true;
         }
+        else {
+            $args['status'] = false;
+        }
 
         return $args;
     }
Only in roundcubemail-1.2.3/plugins/database_attachments: tests
Only in roundcubemail-1.2.3/plugins/debug_logger: tests
Only in roundcubemail-1.2.3/plugins/emoticons: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/enigma/lib/enigma_driver_gnupg.php roundcubemail-1.2.7/plugins/enigma/lib/enigma_driver_gnupg.php
--- roundcubemail-1.2.3/plugins/enigma/lib/enigma_driver_gnupg.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/enigma/lib/enigma_driver_gnupg.php	2017-11-08 19:52:27.000000000 +0100
@@ -281,6 +281,8 @@
      */
     public function gen_key($data)
     {
+        require_once 'Crypt/GPG/KeyGenerator.php';
+
         try {
             $debug  = $this->rc->config->get('enigma_debug');
             $keygen = new Crypt_GPG_KeyGenerator(array(
@@ -409,17 +411,20 @@
      */
     protected function parse_signature($sig)
     {
-        $user = $sig->getUserId();
-
         $data = new enigma_signature();
+
         $data->id          = $sig->getId();
         $data->valid       = $sig->isValid();
         $data->fingerprint = $sig->getKeyFingerprint();
         $data->created     = $sig->getCreationDate();
         $data->expires     = $sig->getExpirationDate();
-        $data->name        = $user->getName();
-        $data->comment     = $user->getComment();
-        $data->email       = $user->getEmail();
+
+        // In case of ERRSIG user may not be set
+        if ($user = $sig->getUserId()) {
+            $data->name    = $user->getName();
+            $data->comment = $user->getComment();
+            $data->email   = $user->getEmail();
+        }
 
         return $data;
     }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/enigma/lib/enigma_engine.php roundcubemail-1.2.7/plugins/enigma/lib/enigma_engine.php
--- roundcubemail-1.2.3/plugins/enigma/lib/enigma_engine.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/enigma/lib/enigma_engine.php	2017-11-08 19:52:27.000000000 +0100
@@ -404,11 +404,6 @@
     {
         $part = $p['structure'];
 
-        // exit, if we're already inside a decrypted message
-        if (in_array($part->mime_id, $this->encrypted_parts)) {
-            return;
-        }
-
         // Get message body from IMAP server
         if ($body === null) {
             $body = $this->get_part_body($p['object'], $part);
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/enigma/lib/enigma_ui.php roundcubemail-1.2.7/plugins/enigma/lib/enigma_ui.php
--- roundcubemail-1.2.3/plugins/enigma/lib/enigma_ui.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/enigma/lib/enigma_ui.php	2017-11-08 19:52:27.000000000 +0100
@@ -116,14 +116,12 @@
      */
     function add_css()
     {
-        if ($this->css_loaded)
+        if ($this->css_loaded) {
             return;
-
-        $skin_path = $this->enigma->local_skin_path();
-        if (is_file($this->home . "/$skin_path/enigma.css")) {
-            $this->enigma->include_stylesheet("$skin_path/enigma.css");
         }
 
+        $skin_path = $this->enigma->local_skin_path();
+        $this->enigma->include_stylesheet("$skin_path/enigma.css");
         $this->css_loaded = true;
     }
 
@@ -185,17 +183,7 @@
      */
     function tpl_key_frame($attrib)
     {
-        if (!$attrib['id']) {
-            $attrib['id'] = 'rcmkeysframe';
-        }
-
-        $attrib['name'] = $attrib['id'];
-
-        $this->rc->output->set_env('contentframe', $attrib['name']);
-        $this->rc->output->set_env('blankpage', $attrib['src'] ?
-            $this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
-        return $this->rc->output->frame($attrib);
+        return $this->rc->output->frame($attrib, true);
     }
 
     /**
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/enigma/README roundcubemail-1.2.7/plugins/enigma/README
--- roundcubemail-1.2.3/plugins/enigma/README	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/enigma/README	2017-11-08 19:52:27.000000000 +0100
@@ -55,6 +55,12 @@
 There are some know issues with accepting key passphrases on various
 system configurations. This is caused by issues in PinEntry handling.
 Make sure that vendor/bin/crypt-gpg-pinentry works from command line.
+
 Possible reasons:
 - non-supported GnuPG version, i.e. >= 2.1
 - non-working loader in shebang (#! /usr/bin/env php)
+  Make sure it works for the user the php scripts are executed upon
+  (i.e. apache, www-date, etc.)
+- SELinux setting, try command: setsebool -P httpd_unified 0
+
+Note: for server use GnuPG developers still recommend version 1.4.
Only in roundcubemail-1.2.3/plugins/enigma: tests
Only in roundcubemail-1.2.3/plugins/example_addressbook: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/filesystem_attachments/filesystem_attachments.php roundcubemail-1.2.7/plugins/filesystem_attachments/filesystem_attachments.php
--- roundcubemail-1.2.3/plugins/filesystem_attachments/filesystem_attachments.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/filesystem_attachments/filesystem_attachments.php	2017-11-08 19:52:27.000000000 +0100
@@ -7,12 +7,19 @@
  * attachments of messages currently being composed, writing attachments
  * to disk when drafts with attachments are re-opened and writing
  * attachments to disk for inline display in current html compositions.
+ * It also handles uploaded files for other uses, so not only attachments.
  *
  * Developers may wish to extend this class when creating attachment
  * handler plugins:
  *   require_once('plugins/filesystem_attachments/filesystem_attachments.php');
  *   class myCustom_attachments extends filesystem_attachments
  *
+ * Note for developers: It is plugin's responsibility to care about security.
+ * So, e.g. if the plugin is asked about some file path it should check
+ * if it's really the storage path of the plugin and not e.g. /etc/passwd.
+ * It is done by setting 'status' flag on every plugin hook it uses.
+ * Roundcube core will trust the returned path if status=true.
+ *
  * @license GNU GPLv3+
  * @author Ziba Scott <ziba at umich.edu>
  * @author Thomas Bruederli <roundcube at gmail.com>
@@ -107,7 +114,7 @@
      */
     function remove($args)
     {
-        $args['status'] = @unlink($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && @unlink($args['path']);
         return $args;
     }
 
@@ -118,7 +125,7 @@
      */
     function display($args)
     {
-        $args['status'] = file_exists($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && file_exists($args['path']);
         return $args;
     }
 
@@ -129,6 +136,10 @@
      */
     function get($args)
     {
+        if (!$this->verify_path($args['path'])) {
+            $args['path'] = null;
+        }
+
         return $args;
     }
 
@@ -147,7 +158,7 @@
                 }
 
                 foreach ((array)$files as $filename) {
-                    if(file_exists($filename)) {
+                    if (file_exists($filename)) {
                         unlink($filename);
                     }
                 }
@@ -182,4 +193,34 @@
             }
         }
     }
+
+    /**
+     * For security we'll always verify the file path stored in session,
+     * as session entries can be faked in various ways e.g. #6026.
+     * We allow only files in Roundcube temp dir
+     */
+    protected function verify_path($path)
+    {
+        if (empty($path)) {
+            return false;
+        }
+
+        $rcmail    = rcube::get_instance();
+        $temp_dir  = $rcmail->config->get('temp_dir');
+        $file_path = pathinfo($path, PATHINFO_DIRNAME);
+
+        if ($temp_dir !== $file_path) {
+            rcube::raise_error(array(
+                    'code'    => 403,
+                    'file'    => __FILE__,
+                    'line'    => __LINE__,
+                    'message' => sprintf("%s can't read %s (not in temp_dir)",
+                        $rcmail->get_user_name(), substr($path, 0, 512))
+                ), true, false);
+
+            return false;
+        }
+
+        return true;
+    }
 }
Only in roundcubemail-1.2.3/plugins/filesystem_attachments: tests
Only in roundcubemail-1.2.3/plugins/help: tests
Only in roundcubemail-1.2.3/plugins/hide_blockquote: tests
Only in roundcubemail-1.2.3/plugins/http_authentication: tests
Only in roundcubemail-1.2.3/plugins/identity_select: tests
Only in roundcubemail-1.2.3/plugins/jqueryui: tests
Only in roundcubemail-1.2.3/plugins/krb_authentication: tests
Only in roundcubemail-1.2.3/plugins/legacy_browser: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/managesieve/Changelog roundcubemail-1.2.7/plugins/managesieve/Changelog
--- roundcubemail-1.2.3/plugins/managesieve/Changelog	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/managesieve/Changelog	2017-11-08 19:52:27.000000000 +0100
@@ -1,3 +1,7 @@
+- Fix parsing dot-staffed lines in multiline text (#5838)
+- Fix handling of scripts with nested rules (#5540)
+- Fix possible defect in handling \r\n in scripts (#5685)
+
 * version 8.6 [2016-04-06]
 -----------------------------------------------------------
 - Refactored script parser to be 100x faster
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php roundcubemail-1.2.7/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
--- roundcubemail-1.2.3/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php	2017-11-08 19:52:27.000000000 +0100
@@ -562,7 +562,8 @@
                     $prefix .= $line . "\n";
                 }
 
-                $position = $endl + 1;
+                // skip empty lines after the comment (#5657)
+                $position = self::ltrim_position($script, $endl + 1);
             }
 
             // handle script header
@@ -805,6 +806,11 @@
             $token     = !empty($tokens) ? array_shift($tokens) : $separator;
 
             switch ($token) {
+            case 'if':
+                // nested 'if' conditions, ignore the whole rule (#5540)
+                $this->_parse_actions($content, $position);
+                continue 2;
+
             case 'discard':
             case 'keep':
             case 'stop':
@@ -890,8 +896,9 @@
                 break;
             }
 
-            if ($separator == $end)
+            if ($separator == $end) {
                 break;
+            }
         }
 
         return $result;
@@ -1208,7 +1215,7 @@
                         if ($str[$position] == "\n") {
                             $position++;
                         }
-                        else if ($str[$position] == "\r" && $str[$position] == "\n") {
+                        else if ($str[$position] == "\r" && $str[$position + 1] == "\n") {
                             $position += 2;
                         }
 
@@ -1224,11 +1231,16 @@
                             $text    .= substr($str, $position, $pos - $position);
                             $position = $pos + 2;
 
-                            if ($str[$pos] == "\n"
-                                || ($str[$pos] == "\r" && $str[$pos + 1] == "\n")
-                            ) {
+                            if ($str[$position] == "\n") {
+                                break;
+                            }
+
+                            if ($str[$position] == "\r" && $str[$position + 1] == "\n") {
+                                $position++;
                                 break;
                             }
+
+                            $text .= "\n.";
                         }
 
                         // remove dot-stuffing
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php roundcubemail-1.2.7/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
--- roundcubemail-1.2.3/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php	2017-11-08 19:52:27.000000000 +0100
@@ -395,8 +395,8 @@
         }
 
         if ($date_extension) {
-            $time_from   = new html_inputfield(array('name' => 'vacation_timefrom', 'id' => 'vacation_timefrom', 'size' => 6));
-            $time_to     = new html_inputfield(array('name' => 'vacation_timeto', 'id' => 'vacation_timeto', 'size' => 6));
+            $time_from   = new html_inputfield(array('name' => 'vacation_timefrom', 'id' => 'vacation_timefrom', 'size' => 7));
+            $time_to     = new html_inputfield(array('name' => 'vacation_timeto', 'id' => 'vacation_timeto', 'size' => 7));
             $time_format = $this->rc->config->get('time_format', 'H:i');
             $date_value  = array();
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/managesieve/managesieve.js roundcubemail-1.2.7/plugins/managesieve/managesieve.js
--- roundcubemail-1.2.3/plugins/managesieve/managesieve.js	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/managesieve/managesieve.js	2017-11-08 19:52:27.000000000 +0100
@@ -870,8 +870,8 @@
   for (i=0; i<format.length; i++) {
     c = format.charAt(i);
     switch (c) {
-      case 'a': time += hour > 12 ? 'am' : 'pm'; break;
-      case 'A': time += hour > 12 ? 'AM' : 'PM'; break;
+      case 'a': time += hour >= 12 ? 'pm' : 'am'; break;
+      case 'A': time += hour >= 12 ? 'PM' : 'AM'; break;
       case 'g':
       case 'h':
         h = hour == 0 ? 12 : hour > 12 ? hour - 12 : hour;
Only in roundcubemail-1.2.3/plugins/managesieve: tests
Only in roundcubemail-1.2.3/plugins/markasjunk: tests
Only in roundcubemail-1.2.3/plugins/newmail_notifier: tests
Only in roundcubemail-1.2.3/plugins/new_user_dialog: tests
Only in roundcubemail-1.2.3/plugins/new_user_identity: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/password/drivers/sasl.php roundcubemail-1.2.7/plugins/password/drivers/sasl.php
--- roundcubemail-1.2.3/plugins/password/drivers/sasl.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/password/drivers/sasl.php	2017-11-08 19:52:27.000000000 +0100
@@ -36,7 +36,7 @@
     function save($currpass, $newpass)
     {
         $curdir   = RCUBE_PLUGINS_DIR . 'password/helpers';
-        $username = escapeshellcmd($_SESSION['username']);
+        $username = escapeshellarg($_SESSION['username']);
         $args     = rcmail::get_instance()->config->get('password_saslpasswd_args', '');
 
         if ($fh = popen("$curdir/chgsaslpasswd -p $args $username", 'w')) {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/plugins/password/drivers/virtualmin.php roundcubemail-1.2.7/plugins/password/drivers/virtualmin.php
--- roundcubemail-1.2.3/plugins/password/drivers/virtualmin.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/plugins/password/drivers/virtualmin.php	2017-11-08 19:52:27.000000000 +0100
@@ -70,9 +70,9 @@
             $domain = $rcmail->user->get_username('domain');
         }
 
-        $username = escapeshellcmd($username);
-        $domain   = escapeshellcmd($domain);
-        $newpass  = escapeshellcmd($newpass);
+        $username = escapeshellarg($username);
+        $domain   = escapeshellarg($domain);
+        $newpass  = escapeshellarg($newpass);
         $curdir   = RCUBE_PLUGINS_DIR . 'password/helpers';
 
         exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue);
Only in roundcubemail-1.2.3/plugins/password: tests
Only in roundcubemail-1.2.3/plugins/redundant_attachments: tests
Only in roundcubemail-1.2.3/plugins/show_additional_headers: tests
Only in roundcubemail-1.2.3/plugins/squirrelmail_usercopy: tests
Only in roundcubemail-1.2.3/plugins/subscriptions_option: tests
Only in roundcubemail-1.2.3/plugins/userinfo: tests
Only in roundcubemail-1.2.3/plugins/vcard_attachments: tests
Only in roundcubemail-1.2.3/plugins/virtuser_file: tests
Only in roundcubemail-1.2.3/plugins/virtuser_query: tests
Only in roundcubemail-1.2.3/plugins/zipdownload: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/include/iniset.php roundcubemail-1.2.7/program/include/iniset.php
--- roundcubemail-1.2.3/program/include/iniset.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/include/iniset.php	2017-11-08 19:52:27.000000000 +0100
@@ -5,7 +5,7 @@
  | program/include/iniset.php                                            |
  |                                                                       |
  | This file is part of the Roundcube Webmail client                     |
- | Copyright (C) 2008-2016, The Roundcube Dev Team                       |
+ | Copyright (C) 2008-2017, The Roundcube Dev Team                       |
  |                                                                       |
  | Licensed under the GNU General Public License version 3 or            |
  | any later version with exceptions for skins & plugins.                |
@@ -21,7 +21,7 @@
 */
 
 // application constants
-define('RCMAIL_VERSION', '1.2.3');
+define('RCMAIL_VERSION', '1.2.7');
 define('RCMAIL_START', microtime(true));
 
 if (!defined('INSTALL_PATH')) {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/include/rcmail.php roundcubemail-1.2.7/program/include/rcmail.php
--- roundcubemail-1.2.3/program/include/rcmail.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/include/rcmail.php	2017-11-08 19:52:27.000000000 +0100
@@ -669,8 +669,9 @@
             $_SESSION['password']     = $this->encrypt($password);
             $_SESSION['login_time']   = time();
 
-            if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') {
-                $_SESSION['timezone'] = rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_GPC);
+            $timezone = rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_GPC);
+            if ($timezone && is_string($timezone) && $timezone != '_default_') {
+                $_SESSION['timezone'] = $timezone;
             }
 
             // fix some old settings according to namespace prefix
@@ -1674,12 +1675,13 @@
      * Try to localize the given IMAP folder name.
      * UTF-7 decode it in case no localized text was found
      *
-     * @param string $name      Folder name
-     * @param bool   $with_path Enable path localization
+     * @param string $name        Folder name
+     * @param bool   $with_path   Enable path localization
+     * @param bool   $path_remove Remove the path
      *
      * @return string Localized folder name in UTF-8 encoding
      */
-    public function localize_foldername($name, $with_path = false)
+    public function localize_foldername($name, $with_path = false, $path_remove = false)
     {
         $realnames = $this->config->get('show_real_foldernames');
 
@@ -1687,12 +1689,20 @@
             return $this->gettext($folder_class);
         }
 
+        $storage   = $this->get_storage();
+        $delimiter = $storage->get_hierarchy_delimiter();
+
+        // Remove the path
+        if ($path_remove) {
+            if (strpos($name, $delimiter)) {
+                $path = explode($delimiter, $name);
+                $name = array_pop($path);
+            }
+        }
         // try to localize path of the folder
-        if ($with_path && !$realnames) {
-            $storage   = $this->get_storage();
-            $delimiter = $storage->get_hierarchy_delimiter();
-            $path      = explode($delimiter, $name);
-            $count     = count($path);
+        else if ($with_path && !$realnames) {
+            $path  = explode($delimiter, $name);
+            $count = count($path);
 
             if ($count > 1) {
                 for ($i = 1; $i < $count; $i++) {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/js/app.js roundcubemail-1.2.7/program/js/app.js
--- roundcubemail-1.2.3/program/js/app.js	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/js/app.js	2017-11-08 19:52:27.000000000 +0100
@@ -339,8 +339,21 @@
           // init message compose form
           this.init_messageform();
         }
-        else if (this.env.action == 'get')
-          this.enable_command('download', 'print', true);
+        else if (this.env.action == 'get') {
+          this.enable_command('download', true);
+
+          // Mozilla's PDF.js viewer does not allow printing from host page (#5125)
+          // to minimize user confusion we disable the Print button
+          if (bw.mz && this.env.mimetype == 'application/pdf') {
+            n = 0; // there will be two onload events, first for the preload page
+            $(this.gui_objects.messagepartframe).on('load', function() {
+              if (n++) try { this.contentWindow.document; ref.enable_command('print', true); }
+                catch (e) {/* ignore */}
+            });
+          }
+          else
+            this.enable_command('print', true);
+        }
         // show printing dialog
         else if (this.env.action == 'print' && this.env.uid
           && !this.env.is_pgp_content && !this.env.pgp_mime_part
@@ -3228,7 +3241,8 @@
     var r_uids = [],
       post_data = this.selection_post_data({_uid: this.uids_to_list(a_uids), _flag: 'delete'}),
       lock = this.display_message(this.get_label('markingmessage'), 'loading'),
-      rows = this.message_list ? this.message_list.rows : {},
+      list = this.message_list,
+      rows = list ? list.rows : {},
       count = 0;
 
     for (var i=0, len=a_uids.length; i<len; i++) {
@@ -3239,7 +3253,7 @@
 
         if (this.env.skip_deleted) {
           count += this.update_thread(uid);
-          this.message_list.remove_row(uid, (this.env.display_next && i == this.message_list.selection.length-1));
+          list.remove_row(uid, (this.env.display_next && i == list.selection.length-1));
         }
         else
           this.set_message(uid, 'deleted', true);
@@ -3247,9 +3261,9 @@
     }
 
     // make sure there are no selected rows
-    if (this.env.skip_deleted && this.message_list) {
-      if (!this.env.display_next)
-        this.message_list.clear_selection();
+    if (this.env.skip_deleted && list) {
+      if (!this.env.display_next || !list.rowcount)
+        list.clear_selection();
       if (count < 0)
         post_data._count = (count*-1);
       else if (count > 0)
@@ -3987,6 +4001,8 @@
       // add signature according to selected identity
       // if we have HTML editor, signature is added in a callback
       if (input_from.prop('type') == 'select-one') {
+        // for some reason the caret initially is not at pos=0 in Firefox 51 (#5628)
+        this.set_caret_pos(input_message, 0);
         this.change_identity(input_from[0]);
       }
 
@@ -5572,6 +5588,9 @@
       url._search = this.env.search_request;
 
     this.http_request(this.env.task == 'mail' ? 'list-contacts' : 'list', url, lock);
+
+    if (this.env.task != 'mail')
+      this.update_state({_source: src, _page: page && page > 1 ? page : null, _gid: group});
   };
 
   this.list_contacts_clear = function()
@@ -5602,9 +5621,6 @@
 
       boxtitle.append($('<span>').text(prop ? prop.name : this.get_label('contacts')));
     }
-
-    if (prop)
-      this.triggerEvent('groupupdate', prop);
   };
 
   // load contact record
@@ -6030,6 +6046,7 @@
     else {
       $(this.treelist.get_item(key)).children().first().html(prop.name);
       this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name;
+      this.set_group_prop(prop);
     }
 
     // update list node and re-sort it
@@ -6502,7 +6519,7 @@
       .addEventListener('collapse', function(node) { ref.folder_collapsed(node) })
       .addEventListener('expand', function(node) { ref.folder_collapsed(node) })
       .addEventListener('search', function(p) { if (p.query) ref.subscription_select(); })
-      .draggable({cancel: 'li.mailbox.root'})
+      .draggable({cancel: 'li.mailbox.root,input,div.treetoggle'})
       .droppable({
         // @todo: find better way, accept callback is executed for every folder
         // on the list when dragging starts (and stops), this is slow, but
Only in roundcubemail-1.2.7/program/js/tinymce/plugins/media: moxieplayer.swf
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/bootstrap.php roundcubemail-1.2.7/program/lib/Roundcube/bootstrap.php
--- roundcubemail-1.2.3/program/lib/Roundcube/bootstrap.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/bootstrap.php	2017-11-08 19:52:28.000000000 +0100
@@ -3,7 +3,7 @@
 /**
  +-----------------------------------------------------------------------+
  | This file is part of the Roundcube PHP suite                          |
- | Copyright (C) 2005-2015, The Roundcube Dev Team                       |
+ | Copyright (C) 2005-2017, The Roundcube Dev Team                       |
  |                                                                       |
  | Licensed under the GNU General Public License version 3 or            |
  | any later version with exceptions for skins & plugins.                |
@@ -55,7 +55,7 @@
 }
 
 // framework constants
-define('RCUBE_VERSION', '1.2.3');
+define('RCUBE_VERSION', '1.2.7');
 define('RCUBE_CHARSET', 'UTF-8');
 
 if (!defined('RCUBE_LIB_DIR')) {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_addressbook.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_addressbook.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_addressbook.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_addressbook.php	2017-11-08 19:52:28.000000000 +0100
@@ -497,8 +497,11 @@
         $contact = rcube::get_instance()->plugins->exec_hook('contact_displayname', $contact);
         $fn = $contact['name'];
 
-        if (!$fn)  // default display name composition according to vcard standard
-            $fn = trim(join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix']))));
+        // default display name composition according to vcard standard
+        if (!$fn) {
+            $fn = join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])));
+            $fn = trim(preg_replace('/\s+/', ' ', $fn));
+        }
 
         // use email address part for name
         $email = self::get_col_values('email', $contact, true);
@@ -547,6 +550,7 @@
         }
 
         $fn = trim($fn, ', ');
+        $fn = preg_replace('/\s+/', ' ', $fn);
 
         // fallbacks...
         if ($fn === '') {
@@ -666,6 +670,11 @@
                 && $value->format('Ymd') == $search->format('Ymd'));
         }
 
+        // Gender is a special value, must use strict comparison (#5757)
+        if ($colname == 'gender') {
+            $mode = self::SEARCH_STRICT;
+        }
+
         // composite field, e.g. address
         foreach ((array)$value as $val) {
             $val = mb_strtolower($val);
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_contacts.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_contacts.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_contacts.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_contacts.php	2017-11-08 19:52:28.000000000 +0100
@@ -502,7 +502,7 @@
 
         // count contacts for this user
         $sql_result = $this->db->query(
-            "SELECT COUNT(c.`contact_id`) AS rows".
+            "SELECT COUNT(c.`contact_id`) AS cnt".
             " FROM " . $this->db->table_name($this->db_name, true) . " AS c".
                 $join.
             " WHERE c.`del` <> 1".
@@ -515,7 +515,7 @@
 
         $sql_arr = $this->db->fetch_assoc($sql_result);
 
-        $this->cache['count'] = (int) $sql_arr['rows'];
+        $this->cache['count'] = (int) $sql_arr['cnt'];
 
         return $this->cache['count'];
     }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_ldap_generic.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_ldap_generic.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_ldap_generic.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_ldap_generic.php	2017-11-08 19:52:28.000000000 +0100
@@ -48,7 +48,8 @@
     {
         // Net_LDAP3 does not support IDNA yet
         // also parse_host() here is very Roundcube specific
-        $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host));
+        $host = rcube_utils::parse_host($host, $this->config['mail_domain']);
+        $host = rcube_utils::idn_to_ascii($host);
 
         return parent::connect($host);
     }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_ldap.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_ldap.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_ldap.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_ldap.php	2017-11-08 19:52:28.000000000 +0100
@@ -228,7 +228,7 @@
 
         $this->sort_col    = is_array($p['sort']) ? $p['sort'][0] : $p['sort'];
         $this->debug       = $debug;
-        $this->mail_domain = $mail_domain;
+        $this->mail_domain = $this->prop['mail_domain'] = $mail_domain;
 
         // initialize cache
         $rcube = rcube::get_instance();
@@ -260,11 +260,13 @@
     {
         $rcube = rcube::get_instance();
 
-        if ($this->ready)
+        if ($this->ready) {
             return true;
+        }
 
-        if (!is_array($this->prop['hosts']))
+        if (!is_array($this->prop['hosts'])) {
             $this->prop['hosts'] = array($this->prop['hosts']);
+        }
 
         // try to connect + bind for every host configured
         // with OpenLDAP 2.x ldap_connect() always succeeds but ldap_bind will fail if host isn't reachable
@@ -838,7 +840,7 @@
             }
 
             // compose a full-text-like search filter
-            $filter = rcube_ldap_generic::fulltext_search_filter($value, $attributes, $mode);
+            $filter = rcube_ldap_generic::fulltext_search_filter($value, $attributes, $mode & ~rcube_addressbook::SEARCH_GROUPS);
         }
 
         // add required (non empty) fields filter
@@ -909,7 +911,7 @@
     protected function extended_search($count = false)
     {
         $prop    = $this->group_id ? $this->group_data : $this->prop;
-        $base_dn = $this->group_id ? $this->groups_base_dn : $this->base_dn;
+        $base_dn = $this->group_id ? $prop['base_dn'] : $this->base_dn;
         $attrs   = $count ? array('dn') : $this->prop['attributes'];
         $entries = array();
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_message.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_message.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_message.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_message.php	2017-11-08 19:52:28.000000000 +0100
@@ -243,7 +243,7 @@
             if (is_resource($mode)) {
                 if ($body !== false) {
                     fwrite($mode, $body);
-                    rewind($mode);
+                    @rewind($mode);
                 }
 
                 return $body !== false;
@@ -268,7 +268,7 @@
             !($mode && $formatted), $max_bytes, $mode && $formatted);
 
         if (is_resource($mode)) {
-            rewind($mode);
+            @rewind($mode);
             return $body !== false;
         }
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube.php roundcubemail-1.2.7/program/lib/Roundcube/rcube.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube.php	2017-11-08 19:52:28.000000000 +0100
@@ -1219,9 +1219,9 @@
         $log_dir = null;
 
         // per-user logging is activated
-        if (self::$instance && self::$instance->config->get('per_user_logging', false) && self::$instance->get_user_id()) {
+        if (self::$instance && self::$instance->config->get('per_user_logging') && self::$instance->get_user_id()) {
             $log_dir = self::$instance->get_user_log_dir();
-            if (empty($log_dir) && $name != 'errors') {
+            if (empty($log_dir) && !in_array($name, array('errors', 'userlogins', 'sendmail'))) {
                 return false;
             }
         }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_user.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_user.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_user.php	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_user.php	2017-11-08 19:52:28.000000000 +0100
@@ -188,14 +188,16 @@
         $a_user_prefs = $plugin['prefs'];
         $old_prefs    = $plugin['old'];
         $config       = $this->rc->config;
+        $defaults     = $config->all();
 
         // merge (partial) prefs array with existing settings
         $this->prefs = $save_prefs = $a_user_prefs + $old_prefs;
         unset($save_prefs['language']);
 
         // don't save prefs with default values if they haven't been changed yet
+        // Warning: we use result of rcube_config::all() here instead of just get() (#5782)
         foreach ($a_user_prefs as $key => $value) {
-            if ($value === null || (!isset($old_prefs[$key]) && ($value == $config->get($key)))) {
+            if ($value === null || (!isset($old_prefs[$key]) && $value === $defaults[$key])) {
                 unset($save_prefs[$key]);
             }
         }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_utils.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_utils.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_utils.php	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_utils.php	2017-11-08 19:52:28.000000000 +0100
@@ -396,7 +396,7 @@
         // ignore the whole block if evil styles are detected
         $source   = self::xss_entity_decode($source);
         $stripped = preg_replace('/[^a-z\(:;]/i', '', $source);
-        $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\(' : '');
+        $evilexpr = 'expression|behavior|javascript:|import[^a]' . (!$allow_remote ? '|url\((?!data:image)' : '');
 
         if (preg_match("/$evilexpr/i", $stripped)) {
             return '/* evil! */';
@@ -419,10 +419,17 @@
             if ($allow_remote) {
                 $a_styles = preg_split('/;[\r\n]*/', $styles, -1, PREG_SPLIT_NO_EMPTY);
 
-                foreach ($a_styles as $line) {
+                for ($i=0, $len=count($a_styles); $i < $len; $i++) {
+                    $line     = $a_styles[$i];
                     $stripped = preg_replace('/[^a-z\(:;]/i', '', $line);
-                    // ... and only allow strict url() values
-                    if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
+
+                    // allow data:image uri, join with continuation
+                    if (stripos($stripped, 'url(data:image')) {
+                        $a_styles[$i] .= ';' . $a_styles[$i+1];
+                        unset($a_styles[$i+1]);
+                    }
+                    // allow strict url() values only
+                    else if (stripos($stripped, 'url(') && !preg_match($strict_url_regexp, $line)) {
                         $a_styles = array('/* evil! */');
                         break;
                     }
@@ -499,9 +506,11 @@
     public static function xss_entity_decode($content)
     {
         $out = html_entity_decode(html_entity_decode($content));
+        $out = trim(preg_replace('/(^<!--|-->$)/', '', trim($out)));
         $out = preg_replace_callback('/\\\([0-9a-f]{4})/i',
             array(self, 'xss_entity_decode_callback'), $out);
         $out = preg_replace('#/\*.*\*/#Ums', '', $out);
+        $out = strip_tags($out);
 
         return $out;
     }
@@ -1159,28 +1168,33 @@
      */
     public static function random_bytes($length, $raw = false)
     {
+        $hextab  = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+        $tabsize = strlen($hextab);
+
         // Use PHP7 true random generator
-        if (function_exists('random_bytes')) {
-            // random_bytes() can throw an Error/TypeError/Exception in some cases
-            try {
-                $random = random_bytes($length);
-            }
-            catch (Throwable $e) {}
+        if ($raw && function_exists('random_bytes')) {
+            return random_bytes($length);
         }
 
-        if (!$random) {
-            $random = openssl_random_pseudo_bytes($length);
-        }
+        if (!$raw && function_exists('random_int')) {
+            $result = '';
+            while ($length-- > 0) {
+                $result .= $hextab[random_int(0, $tabsize - 1)];
+            }
 
-        if ($raw) {
-            return $random;
+            return $result;
         }
 
-        $random = self::bin2ascii($random);
+        $random = openssl_random_pseudo_bytes($length);
 
-        // truncate to the specified size...
-        if ($length < strlen($random)) {
-            $random = substr($random, 0, $length);
+        if ($random === false) {
+            throw new Exception("Failed to get random bytes");
+        }
+
+        if (!$raw) {
+            for ($x = 0; $x < $length; $x++) {
+                $random[$x] = $hextab[ord($random[$x]) % $tabsize];
+            }
         }
 
         return $random;
@@ -1191,40 +1205,16 @@
      *
      * @param string $input Binary input
      *
-     * @return string Readable output
+     * @return string Readable output (Base62)
+     * @deprecated since 1.3.1
      */
     public static function bin2ascii($input)
     {
-        // Above method returns "hexits".
-        // Based on bin_to_readable() function in ext/session/session.c.
-        // Note: removed ",-" characters from hextab
         $hextab = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-        $nbits  = 6; // can be 4, 5 or 6
-        $length = strlen($input);
         $result = '';
-        $char   = 0;
-        $i      = 0;
-        $have   = 0;
-        $mask   = (1 << $nbits) - 1;
-
-        while (true) {
-            if ($have < $nbits) {
-                if ($i < $length) {
-                    $char |= ord($input[$i++]) << $have;
-                    $have += 8;
-                }
-                else if (!$have) {
-                    break;
-                }
-                else {
-                    $have = $nbits;
-                }
-            }
 
-            // consume nbits
-            $result .= $hextab[$char & $mask];
-            $char  >>= $nbits;
-            $have   -= $nbits;
+        for ($x = 0; $x < strlen($input); $x++) {
+            $result .= $hextab[ord($input[$x]) % 62];
         }
 
         return $result;
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/lib/Roundcube/rcube_washtml.php roundcubemail-1.2.7/program/lib/Roundcube/rcube_washtml.php
--- roundcubemail-1.2.3/program/lib/Roundcube/rcube_washtml.php	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/lib/Roundcube/rcube_washtml.php	2017-11-08 19:52:28.000000000 +0100
@@ -289,17 +289,17 @@
                     }
                 }
 
-                if ($this->is_image_attribute($node->tagName, $key)) {
+                if ($this->is_image_attribute($node->nodeName, $key)) {
                     $out = $this->wash_uri($value, true);
                 }
-                else if ($this->is_link_attribute($node->tagName, $key)) {
+                else if ($this->is_link_attribute($node->nodeName, $key)) {
                     if (!preg_match('!^(javascript|vbscript|data:text)!i', $value)
                         && preg_match('!^([a-z][a-z0-9.+-]+:|//|#).+!i', $value)
                     ) {
                         $out = $value;
                     }
                 }
-                else if ($this->is_funciri_attribute($node->tagName, $key)) {
+                else if ($this->is_funciri_attribute($node->nodeName, $key)) {
                     if (preg_match('/^[a-z:]*url\(/i', $val)) {
                         if (preg_match('/^([a-z:]*url)\(\s*[\'"]?([^\'"\)]*)[\'"]?\s*\)/iu', $value, $match)) {
                             if ($url = $this->wash_uri($match[2])) {
@@ -386,7 +386,7 @@
         return $attr == 'background'
             || $attr == 'color-profile' // SVG
             || ($attr == 'poster' && $tag == 'video')
-            || ($attr == 'src' && preg_match('/^(img|source)$/i', $tag))
+            || ($attr == 'src' && preg_match('/^(img|source|input|video|audio)$/i', $tag))
             || ($tag == 'image' && $attr == 'href'); // SVG
     }
 
@@ -432,14 +432,14 @@
         do {
             switch ($node->nodeType) {
             case XML_ELEMENT_NODE: //Check element
-                $tagName = strtolower($node->tagName);
+                $tagName = strtolower($node->nodeName);
                 if ($callback = $this->handlers[$tagName]) {
                     $dump .= call_user_func($callback, $tagName,
                         $this->wash_attribs($node), $this->dumpHtml($node, $level), $this);
                 }
                 else if (isset($this->_html_elements[$tagName])) {
                     $content = $this->dumpHtml($node, $level);
-                    $dump .= '<' . $node->tagName;
+                    $dump .= '<' . $node->nodeName;
 
                     if ($tagName == 'svg') {
                         $xpath = new DOMXPath($node->ownerDocument);
@@ -449,6 +449,9 @@
                             }
                         }
                     }
+                    else if ($tagName == 'textarea' && strpos($content, '<') !== false) {
+                        $content = htmlspecialchars($content, ENT_QUOTES);
+                    }
 
                     $dump .= $this->wash_attribs($node);
 
@@ -456,14 +459,14 @@
                         $dump .= ' />';
                     }
                     else {
-                        $dump .= '>' . $content . '</' . $node->tagName . '>';
+                        $dump .= '>' . $content . '</' . $node->nodeName . '>';
                     }
                 }
                 else if (isset($this->_ignore_elements[$tagName])) {
-                    $dump .= '<!-- ' . htmlspecialchars($node->tagName, ENT_QUOTES) . ' not allowed -->';
+                    $dump .= '<!-- ' . htmlspecialchars($node->nodeName, ENT_QUOTES) . ' not allowed -->';
                 }
                 else {
-                    $dump .= '<!-- ' . htmlspecialchars($node->tagName, ENT_QUOTES) . ' ignored -->';
+                    $dump .= '<!-- ' . htmlspecialchars($node->nodeName, ENT_QUOTES) . ' ignored -->';
                     $dump .= $this->dumpHtml($node, $level); // ignore tags not its content
                 }
                 break;
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/addressbook/func.inc roundcubemail-1.2.7/program/steps/addressbook/func.inc
--- roundcubemail-1.2.3/program/steps/addressbook/func.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/addressbook/func.inc	2017-11-08 19:52:28.000000000 +0100
@@ -152,14 +152,18 @@
     else
         $CONTACTS->set_page(isset($_SESSION['page']) ? $_SESSION['page'] : 1);
 
-    if (!empty($_REQUEST['_gid']))
-        $CONTACTS->set_group(rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC));
+    if (!empty($_REQUEST['_gid'])) {
+        $group = rcube_utils::get_input_value('_gid', rcube_utils::INPUT_GPC);
+        $CONTACTS->set_group($group);
+    }
 
-    if (!$init_env)
+    if (!$init_env) {
         return $CONTACTS;
+    }
 
     $OUTPUT->set_env('readonly', $CONTACTS->readonly);
     $OUTPUT->set_env('source', (string) $source);
+    $OUTPUT->set_env('group', $group);
 
     // reduce/extend $CONTACT_COLTYPES with specification from the current $CONTACT object
     if (is_array($CONTACTS->coltypes)) {
@@ -666,8 +670,9 @@
                 }
 
                 // hack: create empty values array to force this field to be displayed
-                if (empty($values) && $colprop['visible'])
-                    $values[] = '';
+                if (empty($values) && $colprop['visible']) {
+                    $values = array('');
+                }
 
                 if (!is_array($values)) {
                     // $values can be an object, don't use (array)$values syntax
@@ -676,8 +681,9 @@
 
                 $rows = '';
                 foreach ($values as $i => $val) {
-                    if ($subtypes[$i])
+                    if ($subtypes[$i]) {
                         $subtype = $subtypes[$i];
+                    }
 
                     $colprop['id'] = 'ff_' . $col . intval($coltypes[$field]['count']);
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/addressbook/search.inc roundcubemail-1.2.7/program/steps/addressbook/search.inc
--- roundcubemail-1.2.3/program/steps/addressbook/search.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/addressbook/search.inc	2017-11-08 19:52:28.000000000 +0100
@@ -240,6 +240,16 @@
     // Re-set list header
     $OUTPUT->command('set_group_prop', null);
 
+    if ($adv) {
+        $OUTPUT->command('parent.set_env', array(
+                'search_request' => $search_request,
+                'pagecount'      => ceil($result->count / $PAGE_SIZE),
+                'search_id'      => $sid,
+                'source'         => '',
+                'group'          => '',
+        ));
+    }
+
     if (!$sid) {
         // unselect currently selected directory/group
         $OUTPUT->command('unselect_directory');
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/mail/autocomplete.inc roundcubemail-1.2.7/program/steps/mail/autocomplete.inc
--- roundcubemail-1.2.3/program/steps/mail/autocomplete.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/mail/autocomplete.inc	2017-11-08 19:52:28.000000000 +0100
@@ -30,10 +30,10 @@
         $result    = $abook->list_records($RCMAIL->config->get('contactlist_fields'));
         $members   = array();
 
-        while ($result && ($sql_arr = $result->iterate())) {
-            $emails = (array) $abook->get_col_values('email', $sql_arr, true);
+        while ($result && ($record = $result->iterate())) {
+            $emails = (array) $abook->get_col_values('email', $record, true);
             if (!empty($emails) && ($email = array_shift($emails))) {
-                $members[] = format_email_recipient($email, rcube_addressbook::compose_list_name($sql_arr));
+                $members[] = format_email_recipient($email, rcube_addressbook::compose_list_name($record));
             }
         }
 
@@ -70,9 +70,9 @@
         $abook->set_pagesize($MAXNUM);
 
         if ($result = $abook->search($RCMAIL->config->get('contactlist_fields'), $search, $mode, true, true, 'email')) {
-            while ($sql_arr = $result->iterate()) {
+            while ($record = $result->iterate()) {
                 // Contact can have more than one e-mail address
-                $email_arr = (array)$abook->get_col_values('email', $sql_arr, true);
+                $email_arr = (array)$abook->get_col_values('email', $record, true);
                 $email_cnt = count($email_arr);
                 $idx       = 0;
 
@@ -81,7 +81,7 @@
                         continue;
                     }
 
-                    $name    = rcube_addressbook::compose_list_name($sql_arr);
+                    $name    = rcube_addressbook::compose_list_name($record);
                     $contact = format_email_recipient($email, $name);
 
                     // skip entries that don't match
@@ -93,12 +93,17 @@
 
                     // skip duplicates
                     if (empty($contacts[$index])) {
-                        $contact = array('name' => $contact, 'type' => $sql_arr['_type']);
+                        $contact = array('name' => $contact, 'type' => $record['_type']);
 
-                        if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) {
+                        if (($display = rcube_addressbook::compose_search_name($record, $email, $name)) && $display != $contact['name']) {
                             $contact['display'] = $display;
                         }
 
+                        // groups with defined email address will not be expanded to its members' addresses
+                        if ($record['_type'] == 'group') {
+                            $contact['email'] = $email;
+                        }
+
                         $contacts[$index]  = $contact;
                         $sort_keys[$index] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++);
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/mail/func.inc roundcubemail-1.2.7/program/steps/mail/func.inc
--- roundcubemail-1.2.3/program/steps/mail/func.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/mail/func.inc	2017-11-08 19:52:28.000000000 +0100
@@ -860,6 +860,15 @@
         $washer->add_callback('style', 'rcmail_washtml_callback');
     }
 
+    // modify HTML links to open a new window if clicked
+    if (!$p['skip_washer_link_callback']) {
+        $washer->add_callback('a', 'rcmail_washtml_link_callback');
+        $washer->add_callback('area', 'rcmail_washtml_link_callback');
+
+        if ($p['safe'])
+            $washer->add_callback('link', 'rcmail_washtml_link_callback');
+    }
+
     // Remove non-UTF8 characters (#1487813)
     $html = rcube_charset::clean($html);
 
@@ -969,7 +978,7 @@
 
         // now check for evil strings like expression, behavior or url()
         if (!preg_match('/expression|behavior|javascript:|import[^a]/i', $stripped)) {
-            if (!$washtml->get_config('allow_remote') && stripos($stripped, 'url(')) {
+            if (!$washtml->get_config('allow_remote') && preg_match('/url\((?!data:image)/', $stripped)) {
                 $washtml->extlinks = true;
             }
             else {
@@ -1251,36 +1260,38 @@
                     rcmail_message_error($MESSAGE->uid);
                 }
 
-                // check if the message body is PGP encrypted
-                if (strpos($body, '-----BEGIN PGP MESSAGE-----') !== false) {
-                    $OUTPUT->set_env('is_pgp_content', '#message-part' . ($part_no + 1));
-                }
-
                 $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix',
                     array('part' => $part, 'prefix' => ''));
 
+                // Set attributes of the part container
+                $container_class  = $part->ctype_secondary == 'html' ? 'message-htmlpart' : 'message-part';
+                $container_id     = $container_class . (++$part_no);
+                $container_attrib = array('class' => $container_class, 'id' => $container_id);
+
+                // Assign container ID to a global variable for use in rcmail_washtml_link_callback()
+                $GLOBALS['rcmail_html_container_id'] = $container_id;
+
+                // Parse the part content for display
                 $body = rcmail_print_body($body, $part, array('safe' => $safe_mode, 'plain' => !$RCMAIL->config->get('prefer_html')));
 
+                // check if the message body is PGP encrypted
+                if (strpos($body, '-----BEGIN PGP MESSAGE-----') !== false) {
+                    $OUTPUT->set_env('is_pgp_content', '#' . $container_id);
+                }
+
                 if ($part->ctype_secondary == 'html') {
-                    $container_id = 'message-htmlpart' . (++$part_no);
-                    $body         = rcmail_html4inline($body, $container_id, 'rcmBody', $attrs, $safe_mode);
-                    $div_attr     = array('class' => 'message-htmlpart', 'id' => $container_id);
-                    $style        = array();
+                    $body  = rcmail_html4inline($body, $container_id, 'rcmBody', $container_attrib, $safe_mode);
+                    $style = array();
 
                     if (!empty($attrs)) {
                         foreach ($attrs as $a_idx => $a_val)
                             $style[] = $a_idx . ': ' . $a_val;
                         if (!empty($style))
-                            $div_attr['style'] = implode('; ', $style);
+                            $container_attrib['style'] = implode('; ', $style);
                     }
-
-                    $out .= html::div($div_attr, $plugin['prefix'] . $body);
-                }
-                else {
-                    $container_id = 'message-part' . (++$part_no);
-                    $div_attr     = array('class' => 'message-part', 'id' => $container_id);
-                    $out .= html::div($div_attr, $plugin['prefix'] . $body);
                 }
+
+                $out .= html::div($container_attrib, $plugin['prefix'] . $body);
             }
         }
     }
@@ -1427,11 +1438,6 @@
         $last_style_pos = $pos2 + strlen($styles) - $len;
     }
 
-    // modify HTML links to open a new window if clicked
-    $GLOBALS['rcmail_html_container_id'] = $container_id;
-    $body = preg_replace_callback('/<(a|link|area)\s+([^>]+)>/Ui', 'rcmail_alter_html_link', $body);
-    unset($GLOBALS['rcmail_html_container_id']);
-
     $body = preg_replace(array(
             // add comments arround html and other tags
             '/(<!DOCTYPE[^>]*>)/i',
@@ -1510,13 +1516,11 @@
 /**
  * parse link (a, link, area) attributes and set correct target
  */
-function rcmail_alter_html_link($matches)
+function rcmail_washtml_link_callback($tag, $attribs, $content, $washtml)
 {
     global $RCMAIL;
 
-    $tag    = strtolower($matches[1]);
-    $attrib = html::parse_attrib_string($matches[2]);
-    $end    = '>';
+    $attrib = html::parse_attrib_string($attribs);
 
     // Remove non-printable characters in URL (#1487805)
     if ($attrib['href'])
@@ -1559,7 +1563,7 @@
             $attrib['onclick'] = '';
         }
     }
-    else if (empty($attrib['href']) && !$attrib['name']) {
+    else if (empty($attrib['href']) && !isset($attrib['name'])) {
         $attrib['href']    = './#NOP';
         $attrib['onclick'] = 'return false';
     }
@@ -1576,7 +1580,7 @@
     $allow = array('href','name','target','onclick','id','class','style','title',
         'rel','type','media','alt','coords','nohref','hreflang','shape');
 
-    return "<$tag" . html::attrib_string($attrib, $allow) . $end;
+    return html::tag($tag, $attrib, $content, $allow);
 }
 
 /**
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/mail/get.inc roundcubemail-1.2.7/program/steps/mail/get.inc
--- roundcubemail-1.2.3/program/steps/mail/get.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/mail/get.inc	2017-11-08 19:52:28.000000000 +0100
@@ -54,6 +54,7 @@
     if ($part_id && ($part = $MESSAGE->mime_parts[$part_id])) {
         $filename = rcmail_attachment_name($part);
         $OUTPUT->set_pagetitle($filename);
+        $OUTPUT->set_env('mimetype', rcmail_fix_mimetype($part->mimetype));
     }
 
     // register UI objects
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/settings/edit_folder.inc roundcubemail-1.2.7/program/steps/settings/edit_folder.inc
--- roundcubemail-1.2.3/program/steps/settings/edit_folder.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/settings/edit_folder.inc	2017-11-08 19:52:28.000000000 +0100
@@ -86,20 +86,21 @@
 
     // Location (name)
     if ($options['protected']) {
-        $foldername = str_replace($delimiter, ' » ', rcube::Q($RCMAIL->localize_folderpath($mbox)));
+        $foldername = str_replace($delimiter, ' » ', rcube::Q($RCMAIL->localize_foldername($mbox, false, true)));
     }
     else if ($options['norename']) {
         $foldername = rcube::Q($folder);
     }
     else {
-        if (isset($_POST['_name']))
+        if (isset($_POST['_name'])) {
             $folder = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true));
+        }
 
         $foldername = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30));
         $foldername = $foldername->show($folder);
 
-        if ($options['special']) {
-            $foldername .= ' (' . rcube::Q($RCMAIL->localize_foldername($mbox)) .')';
+        if ($options['special'] && ($sname = $RCMAIL->localize_foldername($mbox, false, true)) != $folder) {
+            $foldername .= ' (' . rcube::Q($sname) .')';
         }
     }
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/settings/folders.inc roundcubemail-1.2.7/program/steps/settings/folders.inc
--- roundcubemail-1.2.3/program/steps/settings/folders.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/settings/folders.inc	2017-11-08 19:52:28.000000000 +0100
@@ -277,12 +277,13 @@
     foreach ($list_folders as $i => $folder) {
         $sub_key    = array_search($folder['id'], $a_subscribed);
         $subscribed = $sub_key !== false;
-        $protected  = $folder['id'] == 'INBOX' || ($protect_default && isset($special_folders[$folder['id']]));
+        $special    = $folder['id'] == 'INBOX' || isset($special_folders[$folder['id']]);
+        $protected  = $folder['id'] == 'INBOX' || ($protect_default && $special);
         $noselect   = false;
         $classes    = array();
 
         $folder_utf8    = rcube_charset::convert($folder['id'], 'UTF7-IMAP');
-        $display_folder = rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']);
+        $display_folder = rcube::Q($special ? $RCMAIL->localize_foldername($folder['id'], false, true) : $folder['name']);
 
         if ($folder['virtual']) {
             $classes[] = 'virtual';
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/settings/func.inc roundcubemail-1.2.7/program/steps/settings/func.inc
--- roundcubemail-1.2.3/program/steps/settings/func.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/settings/func.inc	2017-11-08 19:52:28.000000000 +0100
@@ -1386,6 +1386,8 @@
         array('command' => 'responses',   'type' => 'link', 'label' => 'responses',   'title' => 'manageresponses'),
     );
 
+    $disabled_actions = (array) $RCMAIL->config->get('disabled_actions');
+
     // get all identites from DB and define list of cols to be displayed
     $plugin = $RCMAIL->plugins->exec_hook('settings_actions', array(
         'actions' => $default_actions,
@@ -1397,6 +1399,11 @@
     $tabs    = array();
 
     foreach ($plugin['actions'] as $action) {
+        $task_action = $action['command'] ? $action['command'] : $action['action'];
+        if (in_array('settings.' . $task_action, $disabled_actions)) {
+            continue;
+        }
+
         if (!$action['command'] && !$action['href'] && $action['action']) {
             $action['href'] = $RCMAIL->url(array('_action' => $action['action']));
         }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/settings/save_identity.inc roundcubemail-1.2.7/program/steps/settings/save_identity.inc
--- roundcubemail-1.2.3/program/steps/settings/save_identity.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/settings/save_identity.inc	2017-11-08 19:52:28.000000000 +0100
@@ -96,7 +96,7 @@
     unset($_POST['_signature']);
 }
 
-// update an existing contact
+// update an existing identity
 if ($_POST['_iid']) {
     $iid = rcube_utils::get_input_value('_iid', rcube_utils::INPUT_POST);
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/program/steps/settings/upload.inc roundcubemail-1.2.7/program/steps/settings/upload.inc
--- roundcubemail-1.2.3/program/steps/settings/upload.inc	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/program/steps/settings/upload.inc	2017-11-08 19:52:28.000000000 +0100
@@ -25,7 +25,12 @@
 }
 
 $from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET);
-$type = str_replace('edit-', '', $from);
+$type = preg_replace('/(add|edit)-/', '', $from);
+
+// Plugins in Settings may use this file for some uploads (#5694)
+// Make sure it does not contain a dot, which is a special character
+// when using rcube_session::append() below
+$type = str_replace('.', '-', $type);
 
 if ($RCMAIL->action == 'upload-display') {
     $id = 'undefined';
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/.htaccess roundcubemail-1.2.7/public_html/.htaccess
--- roundcubemail-1.2.3/public_html/.htaccess	2016-11-27 17:08:56.000000000 +0100
+++ roundcubemail-1.2.7/public_html/.htaccess	2017-11-08 19:52:27.000000000 +0100
@@ -33,6 +33,8 @@
 RewriteRule ^(?!installer|\.well-known\/|[a-zA-Z0-9]{16})(\.?[^\.]+)$ - [F]
 # - deny access to some locations
 RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|program\/(include|lib|localization|steps)) - [F]
+# - deny access to composer binaries
+RewriteRule ^/vendor\/bin\/.* - [F]
 # - deny access to some documentation files
 RewriteRule /?(README\.md|composer\.json-dist|composer\.json|package\.xml|Dockerfile)$ - [F]
 </IfModule>
Only in roundcubemail-1.2.3/public_html/plugins/acl: tests
Only in roundcubemail-1.2.3/public_html/plugins/additional_message_headers: tests
Only in roundcubemail-1.2.3/public_html/plugins/archive: tests
Only in roundcubemail-1.2.3/public_html/plugins/autologon: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/database_attachments/database_attachments.php roundcubemail-1.2.7/public_html/plugins/database_attachments/database_attachments.php
--- roundcubemail-1.2.3/public_html/plugins/database_attachments/database_attachments.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/database_attachments/database_attachments.php	2017-11-08 19:52:27.000000000 +0100
@@ -85,6 +85,8 @@
             if ($args['data'] === false) {
                 return $args;
             }
+
+            $args['path'] = null;
         }
 
         $data   = base64_encode($args['data']);
@@ -131,10 +133,13 @@
         $cache = $this->get_cache();
         $data  = $cache->read($args['id']);
 
-        if ($data) {
+        if ($data !== null && $data !== false) {
             $args['data'] = base64_decode($data);
             $args['status'] = true;
         }
+        else {
+            $args['status'] = false;
+        }
 
         return $args;
     }
Only in roundcubemail-1.2.3/public_html/plugins/database_attachments: tests
Only in roundcubemail-1.2.3/public_html/plugins/debug_logger: tests
Only in roundcubemail-1.2.3/public_html/plugins/emoticons: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_driver_gnupg.php roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_driver_gnupg.php
--- roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_driver_gnupg.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_driver_gnupg.php	2017-11-08 19:52:27.000000000 +0100
@@ -281,6 +281,8 @@
      */
     public function gen_key($data)
     {
+        require_once 'Crypt/GPG/KeyGenerator.php';
+
         try {
             $debug  = $this->rc->config->get('enigma_debug');
             $keygen = new Crypt_GPG_KeyGenerator(array(
@@ -409,17 +411,20 @@
      */
     protected function parse_signature($sig)
     {
-        $user = $sig->getUserId();
-
         $data = new enigma_signature();
+
         $data->id          = $sig->getId();
         $data->valid       = $sig->isValid();
         $data->fingerprint = $sig->getKeyFingerprint();
         $data->created     = $sig->getCreationDate();
         $data->expires     = $sig->getExpirationDate();
-        $data->name        = $user->getName();
-        $data->comment     = $user->getComment();
-        $data->email       = $user->getEmail();
+
+        // In case of ERRSIG user may not be set
+        if ($user = $sig->getUserId()) {
+            $data->name    = $user->getName();
+            $data->comment = $user->getComment();
+            $data->email   = $user->getEmail();
+        }
 
         return $data;
     }
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_engine.php roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_engine.php
--- roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_engine.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_engine.php	2017-11-08 19:52:27.000000000 +0100
@@ -404,11 +404,6 @@
     {
         $part = $p['structure'];
 
-        // exit, if we're already inside a decrypted message
-        if (in_array($part->mime_id, $this->encrypted_parts)) {
-            return;
-        }
-
         // Get message body from IMAP server
         if ($body === null) {
             $body = $this->get_part_body($p['object'], $part);
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_ui.php roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_ui.php
--- roundcubemail-1.2.3/public_html/plugins/enigma/lib/enigma_ui.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/enigma/lib/enigma_ui.php	2017-11-08 19:52:27.000000000 +0100
@@ -116,14 +116,12 @@
      */
     function add_css()
     {
-        if ($this->css_loaded)
+        if ($this->css_loaded) {
             return;
-
-        $skin_path = $this->enigma->local_skin_path();
-        if (is_file($this->home . "/$skin_path/enigma.css")) {
-            $this->enigma->include_stylesheet("$skin_path/enigma.css");
         }
 
+        $skin_path = $this->enigma->local_skin_path();
+        $this->enigma->include_stylesheet("$skin_path/enigma.css");
         $this->css_loaded = true;
     }
 
@@ -185,17 +183,7 @@
      */
     function tpl_key_frame($attrib)
     {
-        if (!$attrib['id']) {
-            $attrib['id'] = 'rcmkeysframe';
-        }
-
-        $attrib['name'] = $attrib['id'];
-
-        $this->rc->output->set_env('contentframe', $attrib['name']);
-        $this->rc->output->set_env('blankpage', $attrib['src'] ?
-            $this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
-        return $this->rc->output->frame($attrib);
+        return $this->rc->output->frame($attrib, true);
     }
 
     /**
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/enigma/README roundcubemail-1.2.7/public_html/plugins/enigma/README
--- roundcubemail-1.2.3/public_html/plugins/enigma/README	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/enigma/README	2017-11-08 19:52:27.000000000 +0100
@@ -55,6 +55,12 @@
 There are some know issues with accepting key passphrases on various
 system configurations. This is caused by issues in PinEntry handling.
 Make sure that vendor/bin/crypt-gpg-pinentry works from command line.
+
 Possible reasons:
 - non-supported GnuPG version, i.e. >= 2.1
 - non-working loader in shebang (#! /usr/bin/env php)
+  Make sure it works for the user the php scripts are executed upon
+  (i.e. apache, www-date, etc.)
+- SELinux setting, try command: setsebool -P httpd_unified 0
+
+Note: for server use GnuPG developers still recommend version 1.4.
Only in roundcubemail-1.2.3/public_html/plugins/enigma: tests
Only in roundcubemail-1.2.3/public_html/plugins/example_addressbook: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/filesystem_attachments/filesystem_attachments.php roundcubemail-1.2.7/public_html/plugins/filesystem_attachments/filesystem_attachments.php
--- roundcubemail-1.2.3/public_html/plugins/filesystem_attachments/filesystem_attachments.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/filesystem_attachments/filesystem_attachments.php	2017-11-08 19:52:27.000000000 +0100
@@ -7,12 +7,19 @@
  * attachments of messages currently being composed, writing attachments
  * to disk when drafts with attachments are re-opened and writing
  * attachments to disk for inline display in current html compositions.
+ * It also handles uploaded files for other uses, so not only attachments.
  *
  * Developers may wish to extend this class when creating attachment
  * handler plugins:
  *   require_once('plugins/filesystem_attachments/filesystem_attachments.php');
  *   class myCustom_attachments extends filesystem_attachments
  *
+ * Note for developers: It is plugin's responsibility to care about security.
+ * So, e.g. if the plugin is asked about some file path it should check
+ * if it's really the storage path of the plugin and not e.g. /etc/passwd.
+ * It is done by setting 'status' flag on every plugin hook it uses.
+ * Roundcube core will trust the returned path if status=true.
+ *
  * @license GNU GPLv3+
  * @author Ziba Scott <ziba at umich.edu>
  * @author Thomas Bruederli <roundcube at gmail.com>
@@ -107,7 +114,7 @@
      */
     function remove($args)
     {
-        $args['status'] = @unlink($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && @unlink($args['path']);
         return $args;
     }
 
@@ -118,7 +125,7 @@
      */
     function display($args)
     {
-        $args['status'] = file_exists($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && file_exists($args['path']);
         return $args;
     }
 
@@ -129,6 +136,10 @@
      */
     function get($args)
     {
+        if (!$this->verify_path($args['path'])) {
+            $args['path'] = null;
+        }
+
         return $args;
     }
 
@@ -147,7 +158,7 @@
                 }
 
                 foreach ((array)$files as $filename) {
-                    if(file_exists($filename)) {
+                    if (file_exists($filename)) {
                         unlink($filename);
                     }
                 }
@@ -182,4 +193,34 @@
             }
         }
     }
+
+    /**
+     * For security we'll always verify the file path stored in session,
+     * as session entries can be faked in various ways e.g. #6026.
+     * We allow only files in Roundcube temp dir
+     */
+    protected function verify_path($path)
+    {
+        if (empty($path)) {
+            return false;
+        }
+
+        $rcmail    = rcube::get_instance();
+        $temp_dir  = $rcmail->config->get('temp_dir');
+        $file_path = pathinfo($path, PATHINFO_DIRNAME);
+
+        if ($temp_dir !== $file_path) {
+            rcube::raise_error(array(
+                    'code'    => 403,
+                    'file'    => __FILE__,
+                    'line'    => __LINE__,
+                    'message' => sprintf("%s can't read %s (not in temp_dir)",
+                        $rcmail->get_user_name(), substr($path, 0, 512))
+                ), true, false);
+
+            return false;
+        }
+
+        return true;
+    }
 }
Only in roundcubemail-1.2.3/public_html/plugins/filesystem_attachments: tests
Only in roundcubemail-1.2.3/public_html/plugins/help: tests
Only in roundcubemail-1.2.3/public_html/plugins/hide_blockquote: tests
Only in roundcubemail-1.2.3/public_html/plugins/http_authentication: tests
Only in roundcubemail-1.2.3/public_html/plugins/identity_select: tests
Only in roundcubemail-1.2.3/public_html/plugins/jqueryui: tests
Only in roundcubemail-1.2.3/public_html/plugins/krb_authentication: tests
Only in roundcubemail-1.2.3/public_html/plugins/legacy_browser: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/managesieve/Changelog roundcubemail-1.2.7/public_html/plugins/managesieve/Changelog
--- roundcubemail-1.2.3/public_html/plugins/managesieve/Changelog	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/managesieve/Changelog	2017-11-08 19:52:27.000000000 +0100
@@ -1,3 +1,7 @@
+- Fix parsing dot-staffed lines in multiline text (#5838)
+- Fix handling of scripts with nested rules (#5540)
+- Fix possible defect in handling \r\n in scripts (#5685)
+
 * version 8.6 [2016-04-06]
 -----------------------------------------------------------
 - Refactored script parser to be 100x faster
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php roundcubemail-1.2.7/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php
--- roundcubemail-1.2.3/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php	2017-11-08 19:52:27.000000000 +0100
@@ -562,7 +562,8 @@
                     $prefix .= $line . "\n";
                 }
 
-                $position = $endl + 1;
+                // skip empty lines after the comment (#5657)
+                $position = self::ltrim_position($script, $endl + 1);
             }
 
             // handle script header
@@ -805,6 +806,11 @@
             $token     = !empty($tokens) ? array_shift($tokens) : $separator;
 
             switch ($token) {
+            case 'if':
+                // nested 'if' conditions, ignore the whole rule (#5540)
+                $this->_parse_actions($content, $position);
+                continue 2;
+
             case 'discard':
             case 'keep':
             case 'stop':
@@ -890,8 +896,9 @@
                 break;
             }
 
-            if ($separator == $end)
+            if ($separator == $end) {
                 break;
+            }
         }
 
         return $result;
@@ -1208,7 +1215,7 @@
                         if ($str[$position] == "\n") {
                             $position++;
                         }
-                        else if ($str[$position] == "\r" && $str[$position] == "\n") {
+                        else if ($str[$position] == "\r" && $str[$position + 1] == "\n") {
                             $position += 2;
                         }
 
@@ -1224,11 +1231,16 @@
                             $text    .= substr($str, $position, $pos - $position);
                             $position = $pos + 2;
 
-                            if ($str[$pos] == "\n"
-                                || ($str[$pos] == "\r" && $str[$pos + 1] == "\n")
-                            ) {
+                            if ($str[$position] == "\n") {
+                                break;
+                            }
+
+                            if ($str[$position] == "\r" && $str[$position + 1] == "\n") {
+                                $position++;
                                 break;
                             }
+
+                            $text .= "\n.";
                         }
 
                         // remove dot-stuffing
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php roundcubemail-1.2.7/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
--- roundcubemail-1.2.3/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php	2017-11-08 19:52:27.000000000 +0100
@@ -395,8 +395,8 @@
         }
 
         if ($date_extension) {
-            $time_from   = new html_inputfield(array('name' => 'vacation_timefrom', 'id' => 'vacation_timefrom', 'size' => 6));
-            $time_to     = new html_inputfield(array('name' => 'vacation_timeto', 'id' => 'vacation_timeto', 'size' => 6));
+            $time_from   = new html_inputfield(array('name' => 'vacation_timefrom', 'id' => 'vacation_timefrom', 'size' => 7));
+            $time_to     = new html_inputfield(array('name' => 'vacation_timeto', 'id' => 'vacation_timeto', 'size' => 7));
             $time_format = $this->rc->config->get('time_format', 'H:i');
             $date_value  = array();
 
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/managesieve/managesieve.js roundcubemail-1.2.7/public_html/plugins/managesieve/managesieve.js
--- roundcubemail-1.2.3/public_html/plugins/managesieve/managesieve.js	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/managesieve/managesieve.js	2017-11-08 19:52:27.000000000 +0100
@@ -870,8 +870,8 @@
   for (i=0; i<format.length; i++) {
     c = format.charAt(i);
     switch (c) {
-      case 'a': time += hour > 12 ? 'am' : 'pm'; break;
-      case 'A': time += hour > 12 ? 'AM' : 'PM'; break;
+      case 'a': time += hour >= 12 ? 'pm' : 'am'; break;
+      case 'A': time += hour >= 12 ? 'PM' : 'AM'; break;
       case 'g':
       case 'h':
         h = hour == 0 ? 12 : hour > 12 ? hour - 12 : hour;
Only in roundcubemail-1.2.3/public_html/plugins/managesieve: tests
Only in roundcubemail-1.2.3/public_html/plugins/markasjunk: tests
Only in roundcubemail-1.2.3/public_html/plugins/newmail_notifier: tests
Only in roundcubemail-1.2.3/public_html/plugins/new_user_dialog: tests
Only in roundcubemail-1.2.3/public_html/plugins/new_user_identity: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/password/drivers/sasl.php roundcubemail-1.2.7/public_html/plugins/password/drivers/sasl.php
--- roundcubemail-1.2.3/public_html/plugins/password/drivers/sasl.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/password/drivers/sasl.php	2017-11-08 19:52:27.000000000 +0100
@@ -36,7 +36,7 @@
     function save($currpass, $newpass)
     {
         $curdir   = RCUBE_PLUGINS_DIR . 'password/helpers';
-        $username = escapeshellcmd($_SESSION['username']);
+        $username = escapeshellarg($_SESSION['username']);
         $args     = rcmail::get_instance()->config->get('password_saslpasswd_args', '');
 
         if ($fh = popen("$curdir/chgsaslpasswd -p $args $username", 'w')) {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/plugins/password/drivers/virtualmin.php roundcubemail-1.2.7/public_html/plugins/password/drivers/virtualmin.php
--- roundcubemail-1.2.3/public_html/plugins/password/drivers/virtualmin.php	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/plugins/password/drivers/virtualmin.php	2017-11-08 19:52:27.000000000 +0100
@@ -70,9 +70,9 @@
             $domain = $rcmail->user->get_username('domain');
         }
 
-        $username = escapeshellcmd($username);
-        $domain   = escapeshellcmd($domain);
-        $newpass  = escapeshellcmd($newpass);
+        $username = escapeshellarg($username);
+        $domain   = escapeshellarg($domain);
+        $newpass  = escapeshellarg($newpass);
         $curdir   = RCUBE_PLUGINS_DIR . 'password/helpers';
 
         exec("$curdir/chgvirtualminpasswd modify-user --domain $domain --user $username --pass $newpass", $output, $returnvalue);
Only in roundcubemail-1.2.3/public_html/plugins/password: tests
Only in roundcubemail-1.2.3/public_html/plugins/redundant_attachments: tests
Only in roundcubemail-1.2.3/public_html/plugins/show_additional_headers: tests
Only in roundcubemail-1.2.3/public_html/plugins/squirrelmail_usercopy: tests
Only in roundcubemail-1.2.3/public_html/plugins/subscriptions_option: tests
Only in roundcubemail-1.2.3/public_html/plugins/userinfo: tests
Only in roundcubemail-1.2.3/public_html/plugins/vcard_attachments: tests
Only in roundcubemail-1.2.3/public_html/plugins/virtuser_file: tests
Only in roundcubemail-1.2.3/public_html/plugins/virtuser_query: tests
Only in roundcubemail-1.2.3/public_html/plugins/zipdownload: tests
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/program/js/app.js roundcubemail-1.2.7/public_html/program/js/app.js
--- roundcubemail-1.2.3/public_html/program/js/app.js	2016-11-27 17:08:57.000000000 +0100
+++ roundcubemail-1.2.7/public_html/program/js/app.js	2017-11-08 19:52:27.000000000 +0100
@@ -339,8 +339,21 @@
           // init message compose form
           this.init_messageform();
         }
-        else if (this.env.action == 'get')
-          this.enable_command('download', 'print', true);
+        else if (this.env.action == 'get') {
+          this.enable_command('download', true);
+
+          // Mozilla's PDF.js viewer does not allow printing from host page (#5125)
+          // to minimize user confusion we disable the Print button
+          if (bw.mz && this.env.mimetype == 'application/pdf') {
+            n = 0; // there will be two onload events, first for the preload page
+            $(this.gui_objects.messagepartframe).on('load', function() {
+              if (n++) try { this.contentWindow.document; ref.enable_command('print', true); }
+                catch (e) {/* ignore */}
+            });
+          }
+          else
+            this.enable_command('print', true);
+        }
         // show printing dialog
         else if (this.env.action == 'print' && this.env.uid
           && !this.env.is_pgp_content && !this.env.pgp_mime_part
@@ -3228,7 +3241,8 @@
     var r_uids = [],
       post_data = this.selection_post_data({_uid: this.uids_to_list(a_uids), _flag: 'delete'}),
       lock = this.display_message(this.get_label('markingmessage'), 'loading'),
-      rows = this.message_list ? this.message_list.rows : {},
+      list = this.message_list,
+      rows = list ? list.rows : {},
       count = 0;
 
     for (var i=0, len=a_uids.length; i<len; i++) {
@@ -3239,7 +3253,7 @@
 
         if (this.env.skip_deleted) {
           count += this.update_thread(uid);
-          this.message_list.remove_row(uid, (this.env.display_next && i == this.message_list.selection.length-1));
+          list.remove_row(uid, (this.env.display_next && i == list.selection.length-1));
         }
         else
           this.set_message(uid, 'deleted', true);
@@ -3247,9 +3261,9 @@
     }
 
     // make sure there are no selected rows
-    if (this.env.skip_deleted && this.message_list) {
-      if (!this.env.display_next)
-        this.message_list.clear_selection();
+    if (this.env.skip_deleted && list) {
+      if (!this.env.display_next || !list.rowcount)
+        list.clear_selection();
       if (count < 0)
         post_data._count = (count*-1);
       else if (count > 0)
@@ -3987,6 +4001,8 @@
       // add signature according to selected identity
       // if we have HTML editor, signature is added in a callback
       if (input_from.prop('type') == 'select-one') {
+        // for some reason the caret initially is not at pos=0 in Firefox 51 (#5628)
+        this.set_caret_pos(input_message, 0);
         this.change_identity(input_from[0]);
       }
 
@@ -5572,6 +5588,9 @@
       url._search = this.env.search_request;
 
     this.http_request(this.env.task == 'mail' ? 'list-contacts' : 'list', url, lock);
+
+    if (this.env.task != 'mail')
+      this.update_state({_source: src, _page: page && page > 1 ? page : null, _gid: group});
   };
 
   this.list_contacts_clear = function()
@@ -5602,9 +5621,6 @@
 
       boxtitle.append($('<span>').text(prop ? prop.name : this.get_label('contacts')));
     }
-
-    if (prop)
-      this.triggerEvent('groupupdate', prop);
   };
 
   // load contact record
@@ -6030,6 +6046,7 @@
     else {
       $(this.treelist.get_item(key)).children().first().html(prop.name);
       this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name;
+      this.set_group_prop(prop);
     }
 
     // update list node and re-sort it
@@ -6502,7 +6519,7 @@
       .addEventListener('collapse', function(node) { ref.folder_collapsed(node) })
       .addEventListener('expand', function(node) { ref.folder_collapsed(node) })
       .addEventListener('search', function(p) { if (p.query) ref.subscription_select(); })
-      .draggable({cancel: 'li.mailbox.root'})
+      .draggable({cancel: 'li.mailbox.root,input,div.treetoggle'})
       .droppable({
         // @todo: find better way, accept callback is executed for every folder
         // on the list when dragging starts (and stops), this is slow, but
Only in roundcubemail-1.2.7/public_html/program/js/tinymce/plugins/media: moxieplayer.swf
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/skins/classic/common.css roundcubemail-1.2.7/public_html/skins/classic/common.css
--- roundcubemail-1.2.3/public_html/skins/classic/common.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/public_html/skins/classic/common.css	2017-11-08 19:52:28.000000000 +0100
@@ -104,7 +104,7 @@
   font-size: 12px;
   padding-left: 8px;
   padding-right: 8px;
-  background: url(images/buttons/bg.gif?v=30b2.196) repeat-x #f0f0f0;
+  background: url(images/buttons/bg.gif?v=0200.203) repeat-x #f0f0f0;
   border: 1px solid #a4a4a4;
 }
 
@@ -211,7 +211,7 @@
   color: #666666;
   text-decoration: none;
   padding: 6px 12px 6px 26px;
-  background: url(images/taskicons.gif?v=b8e0.1519) no-repeat;
+  background: url(images/taskicons.gif?v=9719.2207) no-repeat;
 }
 
 #taskbar a:hover
@@ -455,7 +455,7 @@
   margin: 1px;
   margin-top: 2px;
   overflow: hidden;
-  background: url(images/pagenav.gif?v=2e75.355) 0 0 no-repeat transparent;
+  background: url(images/pagenav.gif?v=8464.1147) 0 0 no-repeat transparent;
   opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */
 }
 
@@ -961,7 +961,7 @@
   width: 190px;
   height: 20px;
   text-align: right;
-  background: url(images/searchfield.gif?v=aaf8.313) top left no-repeat;
+  background: url(images/searchfield.gif?v=36a5.397) top left no-repeat;
 }
 
 #quicksearchbar
@@ -1406,7 +1406,7 @@
   height: 23px !important;
   height: 22px;
   overflow: hidden;
-  background: url(images/tabs-left.gif?v=0541.219) top left no-repeat;
+  background: url(images/tabs-left.gif?v=d7b0.230) top left no-repeat;
 }
 
 span.tablink
@@ -1433,7 +1433,7 @@
   overflow: hidden;
   text-overflow: ellipsis;
   -o-text-overflow: ellipsis;
-  background: url(images/tabs-right.gif?v=5414.733) top right no-repeat;
+  background: url(images/tabs-right.gif?v=5c83.1417) top right no-repeat;
 }
 
 span.tablink-selected a
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/buttons/bg.gif and roundcubemail-1.2.7/public_html/skins/classic/images/buttons/bg.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/pagenav.gif and roundcubemail-1.2.7/public_html/skins/classic/images/pagenav.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/searchfield.gif and roundcubemail-1.2.7/public_html/skins/classic/images/searchfield.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/tabs-left.gif and roundcubemail-1.2.7/public_html/skins/classic/images/tabs-left.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/tabs-right.gif and roundcubemail-1.2.7/public_html/skins/classic/images/tabs-right.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/taskicons.gif and roundcubemail-1.2.7/public_html/skins/classic/images/taskicons.gif differ
Binary files roundcubemail-1.2.3/public_html/skins/classic/images/watermark.gif and roundcubemail-1.2.7/public_html/skins/classic/images/watermark.gif differ
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/skins/classic/settings.css roundcubemail-1.2.7/public_html/skins/classic/settings.css
--- roundcubemail-1.2.3/public_html/skins/classic/settings.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/public_html/skins/classic/settings.css	2017-11-08 19:52:28.000000000 +0100
@@ -192,7 +192,7 @@
 {
   min-height: 200px;
   padding-bottom: 2em;
-  background: url(images/watermark.gif?v=4094.9288) no-repeat center;
+  background: url(images/watermark.gif?v=61d5.11081) no-repeat center;
 }
 
 #license .sysname
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/skins/larry/mail.css roundcubemail-1.2.7/public_html/skins/larry/mail.css
--- roundcubemail-1.2.3/public_html/skins/larry/mail.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/public_html/skins/larry/mail.css	2017-11-08 19:52:28.000000000 +0100
@@ -16,7 +16,7 @@
 	left: 0;
 	width: 200px;
 	bottom: 0;
-	z-index: 2;
+	z-index: 1; /* fixes scrolling in Edge (#5750) */
 }
 
 #mailview-right {
@@ -25,7 +25,6 @@
 	left: 212px;
 	right: 0;
 	bottom: 0;
-	z-index: 3;
 }
 
 #mailview-right.fullwidth {
@@ -224,7 +223,6 @@
 	left: 0;
 	height: 40px;
 	white-space: nowrap;
-	z-index: 10;
 }
 
 #messagetoolbar.fullwidth {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/public_html/skins/larry/ui.js roundcubemail-1.2.7/public_html/skins/larry/ui.js
--- roundcubemail-1.2.3/public_html/skins/larry/ui.js	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/public_html/skins/larry/ui.js	2017-11-08 19:52:28.000000000 +0100
@@ -131,6 +131,10 @@
       var ismin = $(document.body).toggleClass('minimal').hasClass('minimal');
       save_pref('minimalmode', ismin?1:0);
       $(window).resize();
+
+      // This hack fixes re-positioning of the fixed header of messages list (#5711)
+      if (bw.chrome)
+        $('#mailviewsplitterv').trigger('mousedown').trigger('mouseup');
     });
 
     /***  mail task  ***/
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/skins/classic/common.css roundcubemail-1.2.7/skins/classic/common.css
--- roundcubemail-1.2.3/skins/classic/common.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/skins/classic/common.css	2017-11-08 19:52:28.000000000 +0100
@@ -104,7 +104,7 @@
   font-size: 12px;
   padding-left: 8px;
   padding-right: 8px;
-  background: url(images/buttons/bg.gif?v=30b2.196) repeat-x #f0f0f0;
+  background: url(images/buttons/bg.gif?v=0200.203) repeat-x #f0f0f0;
   border: 1px solid #a4a4a4;
 }
 
@@ -211,7 +211,7 @@
   color: #666666;
   text-decoration: none;
   padding: 6px 12px 6px 26px;
-  background: url(images/taskicons.gif?v=b8e0.1519) no-repeat;
+  background: url(images/taskicons.gif?v=9719.2207) no-repeat;
 }
 
 #taskbar a:hover
@@ -455,7 +455,7 @@
   margin: 1px;
   margin-top: 2px;
   overflow: hidden;
-  background: url(images/pagenav.gif?v=2e75.355) 0 0 no-repeat transparent;
+  background: url(images/pagenav.gif?v=8464.1147) 0 0 no-repeat transparent;
   opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */
 }
 
@@ -961,7 +961,7 @@
   width: 190px;
   height: 20px;
   text-align: right;
-  background: url(images/searchfield.gif?v=aaf8.313) top left no-repeat;
+  background: url(images/searchfield.gif?v=36a5.397) top left no-repeat;
 }
 
 #quicksearchbar
@@ -1406,7 +1406,7 @@
   height: 23px !important;
   height: 22px;
   overflow: hidden;
-  background: url(images/tabs-left.gif?v=0541.219) top left no-repeat;
+  background: url(images/tabs-left.gif?v=d7b0.230) top left no-repeat;
 }
 
 span.tablink
@@ -1433,7 +1433,7 @@
   overflow: hidden;
   text-overflow: ellipsis;
   -o-text-overflow: ellipsis;
-  background: url(images/tabs-right.gif?v=5414.733) top right no-repeat;
+  background: url(images/tabs-right.gif?v=5c83.1417) top right no-repeat;
 }
 
 span.tablink-selected a
Binary files roundcubemail-1.2.3/skins/classic/images/buttons/bg.gif and roundcubemail-1.2.7/skins/classic/images/buttons/bg.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/pagenav.gif and roundcubemail-1.2.7/skins/classic/images/pagenav.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/searchfield.gif and roundcubemail-1.2.7/skins/classic/images/searchfield.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/tabs-left.gif and roundcubemail-1.2.7/skins/classic/images/tabs-left.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/tabs-right.gif and roundcubemail-1.2.7/skins/classic/images/tabs-right.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/taskicons.gif and roundcubemail-1.2.7/skins/classic/images/taskicons.gif differ
Binary files roundcubemail-1.2.3/skins/classic/images/watermark.gif and roundcubemail-1.2.7/skins/classic/images/watermark.gif differ
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/skins/classic/settings.css roundcubemail-1.2.7/skins/classic/settings.css
--- roundcubemail-1.2.3/skins/classic/settings.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/skins/classic/settings.css	2017-11-08 19:52:28.000000000 +0100
@@ -192,7 +192,7 @@
 {
   min-height: 200px;
   padding-bottom: 2em;
-  background: url(images/watermark.gif?v=4094.9288) no-repeat center;
+  background: url(images/watermark.gif?v=61d5.11081) no-repeat center;
 }
 
 #license .sysname
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/skins/larry/mail.css roundcubemail-1.2.7/skins/larry/mail.css
--- roundcubemail-1.2.3/skins/larry/mail.css	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/skins/larry/mail.css	2017-11-08 19:52:28.000000000 +0100
@@ -16,7 +16,7 @@
 	left: 0;
 	width: 200px;
 	bottom: 0;
-	z-index: 2;
+	z-index: 1; /* fixes scrolling in Edge (#5750) */
 }
 
 #mailview-right {
@@ -25,7 +25,6 @@
 	left: 212px;
 	right: 0;
 	bottom: 0;
-	z-index: 3;
 }
 
 #mailview-right.fullwidth {
@@ -224,7 +223,6 @@
 	left: 0;
 	height: 40px;
 	white-space: nowrap;
-	z-index: 10;
 }
 
 #messagetoolbar.fullwidth {
diff -ru -x '*.min.js' -x '*.min.css' roundcubemail-1.2.3/skins/larry/ui.js roundcubemail-1.2.7/skins/larry/ui.js
--- roundcubemail-1.2.3/skins/larry/ui.js	2016-11-27 17:08:58.000000000 +0100
+++ roundcubemail-1.2.7/skins/larry/ui.js	2017-11-08 19:52:28.000000000 +0100
@@ -131,6 +131,10 @@
       var ismin = $(document.body).toggleClass('minimal').hasClass('minimal');
       save_pref('minimalmode', ismin?1:0);
       $(window).resize();
+
+      // This hack fixes re-positioning of the fixed header of messages list (#5711)
+      if (bw.chrome)
+        $('#mailviewsplitterv').trigger('mousedown').trigger('mouseup');
     });
 
     /***  mail task  ***/


More information about the Pkg-roundcube-maintainers mailing list