diff --git a/.gitignore b/.gitignore index 30b18a9a40e..2d4e54deb96 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,11 @@ composer.json composer.phar composer.lock vendor + +# javascript dependencies +plugins/enigma/openpgp.min.js +plugins/managesieve/codemirror/ +program/js/jquery.min.js +program/js/jstz.min.js +program/js/publickey.js +program/js/tinymce/ diff --git a/CHANGELOG b/CHANGELOG index 9094637e5ba..49851229d60 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ CHANGELOG Roundcube Webmail =========================== +- Support logging to php://stdout (#5721) +- Add support for DelSp=Yes in format=flowed messages (#5702) +- Update to jQuery 3.2.1 +- Update to TinyMCE 4.5.6 - Plugin API: Call message_part_structure hook for sub-parts of multipart/alternative message (#5678) - Enigma: Always use detached signatures (#5624) - Enigma: Fix handling of messages with nested PGP encrypted parts (#5634) @@ -19,7 +23,15 @@ CHANGELOG Roundcube Webmail - 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) - Managesieve: Fix parser issue with empty lines between comments (#5657) +- Managesieve: Fix possible defect in handling \r\n in scripts (#5685) - Fix/rephrase "unsaved changes" warning when cancelling a draft (#5610) +- Fix XSS issue in handling of a style tag inside of an svg element [CVE-2017-6820] +- Fix bug where 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 undesired effects when postgres database uses different timezone than PHP host (#5708) +- Installer: Fix DB schema initialization on MS SQL Server +- Fix bug where base_dn setting was ignored inside group_filters (#5720) RELEASE 1.3-beta ---------------- @@ -372,7 +384,7 @@ RELEASE 1.1.1 - Fix fatal errors on systems without mbstring extension or mb_regex_encoding() function (#4769) - Fix cursor position on reply below the quote in HTML mode (#4759) - Fix so "over quota" errors are displayed also in message compose page -- Fix duplicate entries supression in autocomplete result (#4776) +- Fix duplicate entries suppression in autocomplete result (#4776) - Fix "Non-static method PEAR::isError() should not be called statically" errors (#4770) - Fix parsing invalid HTML messages with BOM after (#4777) - Fix duplicate entry on timezones list in rcube_config::timezone_name_from_abbr() (#4779) @@ -445,7 +457,7 @@ RELEASE 1.1-beta - Fix restoring draft messages from localStorage if editor mode differs (#4631) - Added config option/user preference to disable saving messages in localStorage (#4606) - Added config option 'imap_log_session' to enable Roundcube <-> IMAP session ID logging -- Added config option 'log_session_id' to control the lengh of the session identifer in logs +- Added config option 'log_session_id' to control the length of the session identifier in logs - Implemented 'storage_connected' API hook after successful IMAP login (#4638) - Intergrate Net_LDAP3 and rcube_ldap_generic classes - Add option (disabled_actions) to disable UI elements/actions (#4478) @@ -758,7 +770,7 @@ RELEASE 0.9.4 - Make identities matching case insensitive (#1881) - Fix issue where too big message data was stored in cache causing sql errors (#4325) - Fix iframe scrollbars on webkit desktop browsers (#4319) -- Fix issue where legacy config was overriden by default config (#4305) +- Fix issue where legacy config was overridden by default config (#4305) - Fix newmail_notifier issue where favicon wasn't changed back to default (#4324) - Fix setting of Junk and NonJunk flags by markasjunk plugin (#4303) - Fix lack of Reply-To address in header of forwarded message body (#4314) @@ -842,7 +854,7 @@ RELEASE 0.9.1 - Fix so Sender: address is added to Cc: field on reply to all (#4140) - Fix so addressbook_search_mode works also for group search (#4183) - Fix removal of a contact from a group in LDAP addressbook (#4185) -- Inlcude SQL query in the log on SQL error (#4172) +- Include SQL query in the log on SQL error (#4172) - Fix handling untagged responses in IMAP FETCH - "could not load message" error (#4180) - Fix very small window size in Chrome (#4087) - Fix list page reset when viewing a message in Larry skin (#4182) @@ -1129,7 +1141,7 @@ RELEASE 0.8-rc - Add IE8 hack for messages list issue (#3317) - Fix handling errors on draft auto-save - Fix importing vCard photo with ENCODING param specified (#3746) -- Support mutliple name/email pairs for Bcc and Reply-To identity settings (#3752) +- Support multiple name/email pairs for Bcc and Reply-To identity settings (#3752) - Set flexible width to login form fields (#3735) - Fix re-draw bug on list columns change in IE8 (#3318) - Allow mass-removal of addresses from a group (#3259) @@ -1625,7 +1637,7 @@ RELEASE 0.4.1 RELEASE 0.4 ----------- -- Fix disapearing upload form disapears when user selects a file on Safari (#2917) +- Fix disappearing upload form disappears when user selects a file on Safari (#2917) - Don't replace error messages with loading info (#2534) - Fix JS errors on compose mode switch (#2952) - Fix message structure parsing when it lacks optional fields (#2960) @@ -2288,7 +2300,7 @@ RELEASE 0.1-RC2 - Improve message compose screen (closes #1060) - Select next row after removing one from list (#1063) - Make smtp HELO/EHLO hostname configurable (#851) -- IPv6 Compatability (#1023), Patch #1484373 +- IPv6 Compatibility (#1023), Patch #1484373 - Unlock interface when message sending fails (#1188) - Eval PHP code in template includes (if configured) - Show message when folder is empty. Mo more static text in table (#1068) @@ -2394,7 +2406,7 @@ RELEASE 0.1-RC1 - Corrected date string in sent message header (closes #887) - Correclty choose "To" column in sent and draft mailboxes (closes #769) - Changed srong tooltips for message browse buttons (closes #757) -- Fixed signature delimeter character to be standard (Bug #830) +- Fixed signature delimiter character to be standard (Bug #830) - Fixed XSS vulnerability (Bug #877) - Remove newlines from mail headers (Bug #827) - Selection issues when moving/deleting (Bug #837) diff --git a/bin/install-jsdeps.sh b/bin/install-jsdeps.sh index c39f5bb8a06..7a27aeecdda 100755 --- a/bin/install-jsdeps.sh +++ b/bin/install-jsdeps.sh @@ -213,8 +213,12 @@ function extract_zipfile($package, $srcfile) $extract = $CACHEDIR . '/' . $package['lib'] . '-extract'; exec(sprintf('%s -o %s -d %s', $UNZIP, escapeshellarg($srcfile), $extract), $out, $retval); + // get the root folder of the extracted package + $extract_tree = glob("$extract/*", GLOB_ONLYDIR); + $sourcedir = $extract_tree[0]; + foreach ($package['map'] as $src => $dest) { - echo "Installing files $extract/$src into $destdir/$dest\n"; + echo "Installing files $sourcedir/$src into $destdir/$dest\n"; // make sure the destination's parent directory exists if (strpos($dest, '/') !== false) { @@ -225,11 +229,11 @@ function extract_zipfile($package, $srcfile) } // avoid copying source directory as a child into destination - if (is_dir($extract . '/' . $src) && is_dir($destdir . '/' . $dest)) { + if (is_dir($sourcedir . '/' . $src) && is_dir($destdir . '/' . $dest)) { exec(sprintf('rm -rf %s/%s', $destdir, $dest)); } - exec(sprintf('mv -f %s/%s %s/%s', $extract, $src, $destdir, $dest), $out, $retval); + exec(sprintf('mv -f %s/%s %s/%s', $sourcedir, $src, $destdir, $dest), $out, $retval); if ($retval !== 0) { echo "ERROR: Failed to move $src into $destdir/$dest; " . join('; ' . $out) . "\n"; } diff --git a/composer.json-dist b/composer.json-dist index 5cf87b3b254..6bedea9495c 100644 --- a/composer.json-dist +++ b/composer.json-dist @@ -3,10 +3,6 @@ "description": "The Roundcube Webmail suite", "license": "GPL-3.0+", "repositories": [ - { - "type": "pear", - "url": "https://pear.php.net/" - }, { "type": "composer", "url": "https://plugins.roundcube.net/" @@ -23,21 +19,21 @@ "require": { "php": ">=5.4.0", "pear/pear-core-minimal": "~1.10.1", - "roundcube/plugin-installer": "~0.1.6", - "pear-pear.php.net/net_socket": "~1.0.12", - "pear-pear.php.net/auth_sasl": "~1.0.6", - "pear-pear.php.net/net_idna2": "~0.1.1", - "pear-pear.php.net/mail_mime": "~1.10.0", - "pear-pear.php.net/net_smtp": "~1.7.1", - "pear-pear.php.net/crypt_gpg": "~1.6.0", + "pear/net_socket": "~1.2.1", + "pear/auth_sasl": "~1.1.0", + "pear/net_idna2": "~0.2.0", + "pear/mail_mime": "~1.10.0", + "pear/net_smtp": "~1.7.1", + "pear/crypt_gpg": "~1.6.0", "roundcube/net_sieve": "~1.5.0", + "roundcube/plugin-installer": "~0.1.6", "endroid/qrcode": "~1.6.5" }, "require-dev": { "phpunit/phpunit": "~5.7.15" }, "suggest": { - "pear-pear.php.net/net_ldap2": "~2.2.0 required for connecting to LDAP address books", - "kolab/Net_LDAP3": "dev-master required for connecting to LDAP address books" + "pear/net_ldap2": "~2.2.0 required for connecting to LDAP", + "kolab/Net_LDAP3": "dev-master required for connecting to LDAP" } } diff --git a/config/defaults.inc.php b/config/defaults.inc.php index e2db2b72648..bd6937c159c 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -66,7 +66,7 @@ // system error reporting, sum of: 1 = log; 4 = show $config['debug_level'] = 1; -// log driver: 'syslog' or 'file'. +// log driver: 'syslog', 'stdout' or 'file'. $config['log_driver'] = 'file'; // date format for log entries @@ -85,7 +85,7 @@ $config['syslog_facility'] = LOG_USER; // Activate this option if logs should be written to per-user directories. -// Data will only be logged if a directry // exists and is writable. +// Data will only be logged if a directory // exists and is writable. $config['per_user_logging'] = false; // Log sent messages to /sendmail or to syslog @@ -210,7 +210,7 @@ // Note: Because the list is cached, re-login is required after change. $config['imap_disabled_caps'] = array(); -// Log IMAP session identifers after each IMAP login. +// Log IMAP session identifiers after each IMAP login. // This is used to relate IMAP session with Roundcube user sessions $config['imap_log_session'] = false; @@ -351,7 +351,7 @@ // ONLY ENABLE IT IF YOU'RE REALLY SURE WHAT YOU'RE DOING! $config['enable_installer'] = false; -// don't allow these settings to be overriden by the user +// don't allow these settings to be overridden by the user $config['dont_override'] = array(); // List of disabled UI elements/actions @@ -1044,15 +1044,15 @@ // 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 -// valid timezone identifers are listed here: php.net/manual/en/timezones.php +// valid timezone identifiers are listed here: php.net/manual/en/timezones.php // 'auto' will use the browser's timezone settings $config['timezone'] = 'auto'; diff --git a/installer/client.js b/installer/client.js index b6095a91f99..2880ce34fba 100644 --- a/installer/client.js +++ b/installer/client.js @@ -1,6 +1,6 @@ /* +-----------------------------------------------------------------------+ - | Roundcube installer cleint function | + | Roundcube installer client function | | | | This file is part of the Roundcube web development suite | | Copyright (C) 2009-2012, The Roundcube Dev Team | diff --git a/installer/config.php b/installer/config.php index 19a65bbca86..75607187dab 100644 --- a/installer/config.php +++ b/installer/config.php @@ -216,11 +216,11 @@ '_log_driver', 'id' => "cfglogdriver")); -$select_log_driver->add(array('file', 'syslog'), array('file', 'syslog')); +$select_log_driver->add(array('file', 'syslog', 'stdout'), array('file', 'syslog', 'stdout')); echo $select_log_driver->show($RCI->getprop('log_driver', 'file')); ?> -
How to do logging? 'file' - write to files in the log directory, 'syslog' - use the syslog facility.
+
How to do logging? 'file' - write to files in the log directory, 'syslog' - use the syslog facility, 'stdout' writes to the process' STDOUT file descriptor.
log_dir
diff --git a/jsdeps.json b/jsdeps.json index 8b6cb0820a5..ff1f7b8f8a3 100644 --- a/jsdeps.json +++ b/jsdeps.json @@ -3,13 +3,13 @@ { "lib": "jquery", "name": "jQuery", - "version": "3.1.1", - "url": "https://code.jquery.com/jquery-3.1.1.min.js", + "version": "3.2.1", + "url": "https://code.jquery.com/jquery-3.2.1.min.js", "dest": "program/js/jquery.min.js", - "sha1": "f647a6d37dc4ca055ced3cf64bbc1f490070acba", + "sha1": "1055018c28ab41087ef9ccefe411606893dabea2", "license": "MIT", "copyright": "Copyright 2005, 2015 jQuery Foundation, Inc.", - "source": "https://github.com/jquery/jquery/tree/3.1.1" + "source": "https://github.com/jquery/jquery/tree/3.2.1" }, { "lib": "jstz", @@ -35,15 +35,15 @@ }, { "lib": "tinymce", - "version": "4.5.1", - "url": "http://download.ephox.com/tinymce/community/tinymce_4.5.1.zip", + "version": "4.5.6", + "url": "http://download.ephox.com/tinymce/community/tinymce_4.5.6.zip", "dest": "program/js", - "sha1": "e358301ac9fefafcd0ee21643c6aaed2c8b83470", + "sha1": "47e14121e2841072a5e7d1d952ded0b0368b9d57", "license": "LGPL", "copyright": "Copyright (c) 1999-2015 Ephox Corp. All rights reserved", "rm": "program/js/tinymce", "map": { - "tinymce/js/tinymce": "tinymce" + "js/tinymce": "tinymce" }, "omit": [ "tinymce/license.txt", @@ -55,7 +55,7 @@ }, { "lib": "tinymce-langs", - "version": "4.5.1", + "version": "4.5.6", "url": "https://tinymce-services.azurewebsites.net/1/i18n/download?langs=ar,hy,az,eu,be,bs,bg_BG,ca,zh_CN,zh_TW,hr,cs,cs_CZ,da,nl,en_CA,en_GB,eo,et,fo,fi,fr_FR,fr_CH,gd,gl,ka_GE,de,de_AT,el,he_IL,hi_IN,hu_HU,is_IS,id,ga,it,ja,kab,km_KH,ko_KR,ku,ku_IQ,lv,lt,lb,mk_MK,ml_IN,nb_NO,oc,fa,fa_IR,pl,pt_BR,pt_PT,ro,ru,sk,sl_SI,es,es_MX,sv_SE,tg,ta,ta_IN,tt,th_TH,tr,tr_TR,ug,uk,uk_UA,vi,vi_VN,cy", "dest": "program/js/tinymce" }, @@ -78,9 +78,9 @@ "sha1": "3b767c2e3acd6796e54ed19ed2ac0755fcf87984", "license": "MIT", "map": { - "*/lib": "lib", - "*/addon/selection": "addon/selection", - "*/mode/sieve": "mode/sieve" + "lib": "lib", + "addon/selection": "addon/selection", + "mode/sieve": "mode/sieve" } } ] diff --git a/plugins/acl/acl.js b/plugins/acl/acl.js index 1b92ed86d63..577625eb47d 100644 --- a/plugins/acl/acl.js +++ b/plugins/acl/acl.js @@ -368,7 +368,7 @@ rcube_webmail.prototype.acl_init_form = function(id) $('input:checked', type_list).focus(); } -// Returns class name according to ACL comparision result +// Returns class name according to ACL comparison result rcube_webmail.prototype.acl_class = function(acl1, acl2) { var i, len, found = 0; diff --git a/plugins/acl/acl.php b/plugins/acl/acl.php index 9896d7a13ae..31cb514f6dd 100644 --- a/plugins/acl/acl.php +++ b/plugins/acl/acl.php @@ -611,7 +611,7 @@ function acl2text($rights) * @param array $acl1 ACL rights array (or string) * @param array $acl2 ACL rights array (or string) * - * @param int Comparision result, 2 - full match, 1 - partial match, 0 - no match + * @param int Comparison result, 2 - full match, 1 - partial match, 0 - no match */ function acl_compare($acl1, $acl2) { diff --git a/plugins/attachment_reminder/attachment_reminder.php b/plugins/attachment_reminder/attachment_reminder.php index 74df25f61e4..633374621d1 100644 --- a/plugins/attachment_reminder/attachment_reminder.php +++ b/plugins/attachment_reminder/attachment_reminder.php @@ -1,6 +1,6 @@ =5.3.0", "roundcube/plugin-installer": "~0.1.6", - "pear-pear.php.net/crypt_gpg": "~1.6.0@beta" + "pear/crypt_gpg": "~1.6.0" } } diff --git a/plugins/filesystem_attachments/filesystem_attachments.php b/plugins/filesystem_attachments/filesystem_attachments.php index 164efa60034..4bca47e29ce 100644 --- a/plugins/filesystem_attachments/filesystem_attachments.php +++ b/plugins/filesystem_attachments/filesystem_attachments.php @@ -114,7 +114,7 @@ function remove($args) /** * When composing an html message, image attachments may be shown * For this plugin, the file is already in place, just check for - * the existance of the proper metadata + * the existence of the proper metadata */ function display($args) { diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog index 329738a81b5..397503cfcc2 100644 --- a/plugins/managesieve/Changelog +++ b/plugins/managesieve/Changelog @@ -1,4 +1,5 @@ - Fix handling of scripts with nested rules (#5540) +- Fix possible defect in handling \r\n in scripts (#5685) * version 8.8 [2016-11-27] ----------------------------------------------------------- diff --git a/plugins/managesieve/composer.json b/plugins/managesieve/composer.json index afdda5175d5..024ac4b4487 100644 --- a/plugins/managesieve/composer.json +++ b/plugins/managesieve/composer.json @@ -16,10 +16,6 @@ "type": "composer", "url": "https://plugins.roundcube.net" }, - { - "type": "pear", - "url": "https://pear.php.net/" - }, { "type": "vcs", "url": "https://github.com/roundcube/Net_Sieve.git" diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve.php b/plugins/managesieve/lib/Roundcube/rcube_sieve.php index 437a7db0383..75f94af7849 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve.php @@ -1,7 +1,7 @@ sieve->disconnect(); } @@ -178,15 +179,15 @@ public function save_script($name, $content = null) $this->errorLines[] = array("line" => $matches[1], "msg" => null); } } - } + } } - + return $this->_set_error(self::ERROR_INSTALL); } return true; } - + /** * Returns the current error line within the saved sieve script */ diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php index 9d1c7144534..774be462341 100644 --- a/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php +++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_script.php @@ -1,7 +1,7 @@ code != 0) { print "Cannot login: ". $mesg->error; } else { - # Wyszukanie usera wg filtra + # Wyszukanie users wg filtra $PAR{'filter'} =~ s/\%login/$PAR{'user'}/; my @search_args = ( base => $PAR{'base'}, diff --git a/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php b/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php index c038a329288..12fd5b54276 100644 --- a/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php +++ b/plugins/squirrelmail_usercopy/squirrelmail_usercopy.php @@ -192,7 +192,7 @@ private function read_squirrel_prefs($uname) } } - // parse addres book file + // parse address book file if (filesize($abookfile)) { foreach (file($abookfile) as $line) { $line = $this->convert_charset(rtrim($line), $file_charset); @@ -234,7 +234,7 @@ private function read_squirrel_prefs($uname) $sql_result = $db->query('SELECT * FROM ' . $db->quote_identifier($address_table) .' WHERE `owner` = ?', $uname); // ? is replaced with emailaddress - // parse addres book + // parse address book while ($sql_array = $db->fetch_assoc($sql_result) ) { // fetch one row from result $rec['name'] = rcube_charset::convert(rtrim($sql_array['nickname']), $db_charset); $rec['firstname'] = rcube_charset::convert(rtrim($sql_array['firstname']), $db_charset); diff --git a/program/include/rcmail.php b/program/include/rcmail.php index e88161c6287..208d1560e6e 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -493,7 +493,7 @@ public function session_init() } /** - * Perfom login to the mail server and to the webmail service. + * Perform login to the mail server and to the webmail service. * This will also create a new user entry if auto_create_user is configured. * * @param string $username Mail storage (IMAP) user name @@ -1194,7 +1194,7 @@ public function table_output($attrib, $table_data, $show_cols, $id_col) * * @param mixed $date Date representation (string, timestamp or DateTime object) * @param string $format Date format to use - * @param bool $convert Enables date convertion according to user timezone + * @param bool $convert Enables date conversion according to user timezone * * @return string Formatted date string */ @@ -1689,12 +1689,13 @@ public function folder_classname($folder_id) * 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'); @@ -1702,12 +1703,20 @@ public function localize_foldername($name, $with_path = false) 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 --git a/program/include/rcmail_output_html.php b/program/include/rcmail_output_html.php index 61d9d79585e..cc093d992de 100644 --- a/program/include/rcmail_output_html.php +++ b/program/include/rcmail_output_html.php @@ -277,7 +277,7 @@ private function load_skin($skin_path) { $this->skin_paths[] = $skin_path; - // read meta file and check for dependecies + // read meta file and check for dependencies $meta = @file_get_contents(RCUBE_INSTALL_PATH . $skin_path . '/meta.json'); $meta = @json_decode($meta, true); @@ -788,7 +788,7 @@ protected function parse_with_globals($input) } /** - * Callback funtion for preg_replace_callback() in parse_with_globals() + * Callback function for preg_replace_callback() in parse_with_globals() */ protected function globals_callback($matches) { diff --git a/program/js/app.js b/program/js/app.js index 9079b4ddd9e..17b9b301cc8 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -5407,6 +5407,12 @@ function rcube_webmail() return rcube_event.cancel(e); + case 9: // tab + if (rcube_event.get_modifier(e) == SHIFT_KEY || !this.ksearch_visible()) { + this.ksearch_hide(); + return; + } + case 13: // enter if (!this.ksearch_visible()) return false; @@ -5415,9 +5421,9 @@ function rcube_webmail() this.insert_recipient(this.ksearch_selected); this.ksearch_hide(); - return rcube_event.cancel(e); + // Don't cancel on Tab, we want to jump to the next field (#5659) + return key == 9 ? null : rcube_event.cancel(e); - case 9: // tab case 27: // escape this.ksearch_hide(); return; diff --git a/program/js/editor.js b/program/js/editor.js index f4dc555d80c..dc9a7ded403 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -39,7 +39,7 @@ function rcube_text_editor(config, id) abs_url = location.href.replace(/[?#].*$/, '').replace(/\/$/, ''), conf = { selector: '#' + ($('#' + id).is('.mce_editor') ? id : 'fake-editor-id'), - cache_suffix: 's=4050100', + cache_suffix: 's=4050600', theme: 'modern', language: config.lang, content_css: rcmail.assets_path('program/resources/tinymce/content.css'), diff --git a/program/js/treelist.js b/program/js/treelist.js index 7ea0d012c68..2f70e84ff63 100644 --- a/program/js/treelist.js +++ b/program/js/treelist.js @@ -32,7 +32,7 @@ /** * Roundcube Treelist widget class - * @contructor + * @constructor */ function rcube_treelist_widget(node, p) { diff --git a/program/lib/Roundcube/html.php b/program/lib/Roundcube/html.php index 2cad9df9953..cc163a6fcac 100644 --- a/program/lib/Roundcube/html.php +++ b/program/lib/Roundcube/html.php @@ -65,7 +65,7 @@ public function show() * * @param string $tagname Tag name * @param array $attrib Tag attributes as key/value pairs - * @param string $content Optinal Tag content (creates a container tag) + * @param string $content Optional Tag content (creates a container tag) * @param array $allowed List with allowed attributes, omit to allow all * * @return string The XHTML tag @@ -630,7 +630,7 @@ public function show($value = '', $attrib = null) * $select->add(array('Switzerland','Germany'), array('CH','DE')); * * // generate pulldown with selection 'Switzerland' and return html-code - * // as second argument the same attributes available to instanciate can be used + * // as second argument the same attributes available to instantiate can be used * print $select->show('CH'); * * diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index 3694c5c4b61..7c9d5ccd790 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -39,7 +39,7 @@ class rcube const DEBUG_LINE_LENGTH = 4096; /** - * Singleton instace of rcube + * Singleton instance of rcube * * @var rcube */ @@ -53,21 +53,21 @@ class rcube public $config; /** - * Instace of database class. + * Instance of database class. * * @var rcube_db */ public $db; /** - * Instace of Memcache class. + * Instance of Memcache class. * * @var Memcache */ public $memcache; /** - * Instace of rcube_session class. + * Instance of rcube_session class. * * @var rcube_session */ @@ -1221,6 +1221,13 @@ public static function write_log($name, $line) return syslog($prio, $line); } + // write message with file name when configured to log to STDOUT + if ($log_driver == 'stdout') { + $stdout = "php://stdout"; + $line = "$name: $line"; + return file_put_contents($stdout, $line, FILE_APPEND) !== false; + } + // log_driver == 'file' is assumed here $line = sprintf("[%s]: %s\n", $date, $line); diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index 7a028503738..e4b523dc76d 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -506,8 +506,11 @@ public static function compose_display_name($contact, $full_email = false) $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); @@ -557,6 +560,7 @@ public static function compose_list_name($contact) } $fn = trim($fn, ', '); + $fn = preg_replace('/\s+/', ' ', $fn); // fallbacks... if ($fn === '') { @@ -668,7 +672,7 @@ public static function compose_contact_key($contact, $sort_col) * @param string $search Search value * @param int $mode Search mode * - * @return bool Comparision result + * @return bool Comparison result */ protected function compare_search_value($colname, $value, $search, $mode) { diff --git a/program/lib/Roundcube/rcube_charset.php b/program/lib/Roundcube/rcube_charset.php index 2f87b826628..9ed6f946e66 100644 --- a/program/lib/Roundcube/rcube_charset.php +++ b/program/lib/Roundcube/rcube_charset.php @@ -144,7 +144,7 @@ public static function parse_charset($input) else if (!empty($aliases[$m[1]])) { $result = 'ISO-8859-'.$aliases[$m[1]]; } - // iconv requires convertion of e.g. LATIN-1 to LATIN1 + // iconv requires conversion of e.g. LATIN-1 to LATIN1 else { $result = $str; } diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php index 29965845fd5..b5409fb3c5d 100644 --- a/program/lib/Roundcube/rcube_db.php +++ b/program/lib/Roundcube/rcube_db.php @@ -47,6 +47,8 @@ class rcube_db // column/table quotes 'identifier_start' => '"', 'identifier_end' => '"', + // date/time input format + 'datetime_format' => 'Y-m-d H:i:s', ); const DEBUG_LINE_LENGTH = 4096; @@ -522,7 +524,7 @@ protected function query_parse($query) /** * Helper method to handle DB errors. - * This by default logs the error but could be overriden by a driver implementation + * This by default logs the error but could be overridden by a driver implementation * * @param string $query Query that triggered the error * @@ -778,7 +780,7 @@ public function rollbackTransaction() /** * Release resources related to the last query result. * When we know we don't need to access the last query result we can destroy it - * and release memory. Usefull especially if the query returned big chunk of data. + * and release memory. Useful especially if the query returned big chunk of data. */ public function reset() { @@ -818,6 +820,10 @@ public function quote($input, $type = null) return 'NULL'; } + if ($input instanceof DateTime) { + return $this->quote($input->format($this->options['datetime_format'])); + } + if ($type == 'ident') { return $this->quote_identifier($input); } @@ -970,10 +976,11 @@ public function unixtimestamp($field) * @param int $timestamp Unix timestamp * * @return string Date string in db-specific format + * @deprecated */ public function fromunixtime($timestamp) { - return date("'Y-m-d H:i:s'", $timestamp); + return $this->quote(date($this->options['datetime_format'], $timestamp)); } /** @@ -1319,19 +1326,32 @@ public function exec_script($sql) { $sql = $this->fix_table_names($sql); $buff = ''; + $exec = ''; foreach (explode("\n", $sql) as $line) { - if (preg_match('/^--/', $line) || trim($line) == '') + $trimmed = trim($line); + if ($trimmed == '' || preg_match('/^--/', $trimmed)) { continue; + } - $buff .= $line . "\n"; - if (preg_match('/(;|^GO)$/', trim($line))) { - $this->query($buff); + if ($trimmed == 'GO') { + $exec = $buff; + } + else if ($trimmed[strlen($trimmed)-1] == ';') { + $exec = $buff . substr(rtrim($line), 0, -1); + } + + if ($exec) { + $this->query($exec); $buff = ''; + $exec = ''; if ($this->db_error) { break; } } + else { + $buff .= $line . "\n"; + } } return !$this->db_error; diff --git a/program/lib/Roundcube/rcube_db_oracle.php b/program/lib/Roundcube/rcube_db_oracle.php index 21aea4cbd1b..fb1cd235168 100644 --- a/program/lib/Roundcube/rcube_db_oracle.php +++ b/program/lib/Roundcube/rcube_db_oracle.php @@ -191,7 +191,7 @@ protected function _query($query, $offset, $numrows, $params) /** * Helper method to handle DB errors. - * This by default logs the error but could be overriden by a driver implementation + * This by default logs the error but could be overridden by a driver implementation * * @param string Query that triggered the error * @return mixed Result to be stored and returned @@ -327,6 +327,10 @@ public function quote($input, $type = null) return 'NULL'; } + if ($input instanceof DateTime) { + return $this->quote($input->format($this->options['datetime_format'])); + } + if ($type == 'ident') { return $this->quote_identifier($input); } diff --git a/program/lib/Roundcube/rcube_db_pgsql.php b/program/lib/Roundcube/rcube_db_pgsql.php index aa7809370f9..d0d707a4a4e 100644 --- a/program/lib/Roundcube/rcube_db_pgsql.php +++ b/program/lib/Roundcube/rcube_db_pgsql.php @@ -28,6 +28,21 @@ class rcube_db_pgsql extends rcube_db { public $db_provider = 'postgres'; + /** + * Object constructor + * + * @param string $db_dsnw DSN for read/write operations + * @param string $db_dsnr Optional DSN for read only operations + * @param bool $pconn Enables persistent connections + */ + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false) + { + parent::__construct($db_dsnw, $db_dsnr, $pconn); + + // use date/time input format with timezone spec. + $this->options['datetime_format'] = 'c'; + } + /** * Driver-specific configuration of database connection * diff --git a/program/lib/Roundcube/rcube_html2text.php b/program/lib/Roundcube/rcube_html2text.php index ee625886a8e..bd57ca23a43 100644 --- a/program/lib/Roundcube/rcube_html2text.php +++ b/program/lib/Roundcube/rcube_html2text.php @@ -692,7 +692,7 @@ public function pre_preg_callback($matches) */ private function _toupper($str) { - // string can containg HTML tags + // string can containing HTML tags $chunks = preg_split('/(<[^>]*>)/', $str, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); // convert toupper only the text between HTML tags diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index 4d90d57118d..e2984c1c1b0 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -308,7 +308,7 @@ public function set_debug($dbg = true) /** * Set internal folder reference. - * All operations will be perfomed on this folder. + * All operations will be performed on this folder. * * @param string $folder Folder name */ @@ -2798,7 +2798,7 @@ public function expunge_message($uids, $folder = null, $clear_cache = true) /* -------------------------------- - * folder managment + * folder management * --------------------------------*/ /** diff --git a/program/lib/Roundcube/rcube_imap_cache.php b/program/lib/Roundcube/rcube_imap_cache.php index be9ef486f0c..926203c3a93 100644 --- a/program/lib/Roundcube/rcube_imap_cache.php +++ b/program/lib/Roundcube/rcube_imap_cache.php @@ -449,7 +449,7 @@ function get_message($mailbox, $uid, $update = true, $cache = true) * * @param string $mailbox Folder name * @param rcube_message_header $message Message data - * @param bool $force Skips message in-cache existance check + * @param bool $force Skips message in-cache existence check */ function add_message($mailbox, $message, $force = false) { diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php index d7245c2bbe3..3dac8a55c93 100644 --- a/program/lib/Roundcube/rcube_imap_generic.php +++ b/program/lib/Roundcube/rcube_imap_generic.php @@ -4065,7 +4065,7 @@ public function setDebug($debug, $handler = null) /** * Write the given debug text to the current debug output handler. * - * @param string $message Debug mesage text. + * @param string $message Debug message text. * * @since 0.5-stable */ diff --git a/program/lib/Roundcube/rcube_ldap.php b/program/lib/Roundcube/rcube_ldap.php index 201b677039e..e166df3b213 100644 --- a/program/lib/Roundcube/rcube_ldap.php +++ b/program/lib/Roundcube/rcube_ldap.php @@ -840,7 +840,7 @@ function search($fields, $value, $mode=0, $select=true, $nocount=false, $require } // 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 @@ -912,7 +912,7 @@ function count() 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 --git a/program/lib/Roundcube/rcube_ldap_generic.php b/program/lib/Roundcube/rcube_ldap_generic.php index 2c6c0739db2..a46fb897de9 100644 --- a/program/lib/Roundcube/rcube_ldap_generic.php +++ b/program/lib/Roundcube/rcube_ldap_generic.php @@ -100,7 +100,7 @@ public function log($level, $msg) /** * Returns the last LDAP error occurred * - * @return mixed Error message string or null if no error occured + * @return mixed Error message string or null if no error occurred */ function get_error() { diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php index 7ac31f8bcf1..eff9b47bc0b 100644 --- a/program/lib/Roundcube/rcube_message.php +++ b/program/lib/Roundcube/rcube_message.php @@ -28,7 +28,7 @@ class rcube_message { /** - * Instace of framework class. + * Instance of framework class. * * @var rcube */ diff --git a/program/lib/Roundcube/rcube_mime.php b/program/lib/Roundcube/rcube_mime.php index d9d9c55bef4..a6c09c84550 100644 --- a/program/lib/Roundcube/rcube_mime.php +++ b/program/lib/Roundcube/rcube_mime.php @@ -42,7 +42,7 @@ function __construct($default_charset = null) /** * Returns message/object character set name * - * @return string Characted set name + * @return string Character set name */ public static function get_charset() { @@ -437,12 +437,13 @@ public static function explode_header_string($separator, $str, $remove_comments /** * Interpret a format=flowed message body according to RFC 2646 * - * @param string $text Raw body formatted as flowed text - * @param string $mark Mark each flowed line with specified character + * @param string $text Raw body formatted as flowed text + * @param string $mark Mark each flowed line with specified character + * @param boolean $delsp Remove the trailing space of each flowed line * * @return string Interpreted text with unwrapped lines and stuffed space removed */ - public static function unfold_flowed($text, $mark = null) + public static function unfold_flowed($text, $mark = null, $delsp = false) { $text = preg_split('/\r?\n/', $text); $last = -1; @@ -464,6 +465,9 @@ public static function unfold_flowed($text, $mark = null) && isset($text[$last]) && $text[$last][strlen($text[$last])-1] == ' ' && !preg_match('/^>+ {0,1}$/', $text[$last]) ) { + if ($delsp) { + $text[$last] = substr($text[$last], 0, -1); + } $text[$last] .= $line; unset($text[$idx]); @@ -487,6 +491,9 @@ public static function unfold_flowed($text, $mark = null) && $text[$last] != '-- ' && $text[$last][strlen($text[$last])-1] == ' ' ) { + if ($delsp) { + $text[$last] = substr($text[$last], 0, -1); + } $text[$last] .= $line; unset($text[$idx]); diff --git a/program/lib/Roundcube/rcube_smtp.php b/program/lib/Roundcube/rcube_smtp.php index b5930495d05..2181a1d6c42 100644 --- a/program/lib/Roundcube/rcube_smtp.php +++ b/program/lib/Roundcube/rcube_smtp.php @@ -186,7 +186,7 @@ public function connect($host = null, $port = null, $user = null, $pass = null) * * @param string Sender e-Mail address * - * @param mixed Either a comma-seperated list of recipients + * @param mixed Either a comma-separated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. This may contain recipients not * specified in the headers, for Bcc:, resending @@ -448,7 +448,7 @@ private function _prepare_headers($headers) * bare addresses (forward paths) that can be passed to sendmail * or an smtp server with the rcpt to: command. * - * @param mixed Either a comma-seperated list of recipients + * @param mixed Either a comma-separated list of recipients * (RFC822 compliant), or an array of recipients, * each RFC822 valid. * diff --git a/program/lib/Roundcube/rcube_spellchecker.php b/program/lib/Roundcube/rcube_spellchecker.php index 29c9a93b59c..a0c340fd7f6 100644 --- a/program/lib/Roundcube/rcube_spellchecker.php +++ b/program/lib/Roundcube/rcube_spellchecker.php @@ -255,7 +255,7 @@ private function html2text($text) } /** - * Check if the specified word is an exception accoring to + * Check if the specified word is an exception according to * spellcheck options. * * @param string $word The word diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php index 387b3d09b83..d5bcf27a539 100644 --- a/program/lib/Roundcube/rcube_storage.php +++ b/program/lib/Roundcube/rcube_storage.php @@ -177,7 +177,7 @@ public function set_charset($cs) /** * Set internal folder reference. - * All operations will be perfomed on this folder. + * All operations will be performed on this folder. * * @param string $folder Folder name */ @@ -434,7 +434,7 @@ abstract function get_message_headers($uid, $folder = null, $force = false); * @param int $uid Message UID * @param string $part Part number * @param rcube_message_part $o_part Part object created by get_structure() - * @param mixed $print True to print part, ressource to write part contents in + * @param mixed $print True to print part, resource to write part contents in * @param resource $fp File pointer to save the message part * @param boolean $skip_charset_conv Disables charset conversion * @@ -608,7 +608,7 @@ protected function parse_uids($uids) /* -------------------------------- - * folder managment + * folder management * --------------------------------*/ /** @@ -849,7 +849,7 @@ public function get_special_folders($forced = false) */ public function set_special_folders($specials) { - // should be overriden by storage class if backend supports special folders (SPECIAL-USE) + // should be overridden by storage class if backend supports special folders (SPECIAL-USE) unset($this->icache['special-folders']); } diff --git a/program/lib/Roundcube/rcube_text2html.php b/program/lib/Roundcube/rcube_text2html.php index 73e8b788c74..ce8c377994c 100644 --- a/program/lib/Roundcube/rcube_text2html.php +++ b/program/lib/Roundcube/rcube_text2html.php @@ -48,6 +48,8 @@ class rcube_text2html 'space' => "\xC2\xA0", // enables format=flowed parser 'flowed' => false, + // enables delsp=yes parser + 'delsp' => false, // enables wrapping for non-flowed text 'wrap' => true, // line-break tag @@ -150,7 +152,8 @@ protected function _converter($text) if ($this->config['flowed']) { $flowed_char = 0x01; - $text = rcube_mime::unfold_flowed($text, chr($flowed_char)); + $delsp = $this->config['delsp']; + $text = rcube_mime::unfold_flowed($text, chr($flowed_char), $delsp); } // search for patterns like links and e-mail addresses and replace with tokens diff --git a/program/lib/Roundcube/rcube_user.php b/program/lib/Roundcube/rcube_user.php index 32679ead936..ad442436c00 100644 --- a/program/lib/Roundcube/rcube_user.php +++ b/program/lib/Roundcube/rcube_user.php @@ -503,10 +503,10 @@ function failed_login() $this->db->query( "UPDATE " . $this->db->table_name('users', true) - . " SET `failed_login` = " . $this->db->fromunixtime($failed_login->format('U')) + . " SET `failed_login` = ?" . ", `failed_login_counter` = " . ($counter ?: "`failed_login_counter` + 1") . " WHERE `user_id` = ?", - $this->ID); + $failed_login, $this->ID); } } diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index 10f96c7b427..ea2ef290635 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -493,26 +493,16 @@ public static function file2class($mimetype, $filename) */ public static function xss_entity_decode($content) { + $callback = function($matches) { return chr(hexdec($matches[1])); }; + $out = html_entity_decode(html_entity_decode($content)); - $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', - array(self, 'xss_entity_decode_callback'), $out); + $out = preg_replace_callback('/\\\([0-9a-f]{4})/i', $callback, $out); $out = preg_replace('#/\*.*\*/#Ums', '', $out); + $out = strip_tags($out); return $out; } - /** - * preg_replace_callback callback for xss_entity_decode - * - * @param array $matches Result from preg_replace_callback - * - * @return string Decoded entity - */ - public static function xss_entity_decode_callback($matches) - { - return chr(hexdec($matches[1])); - } - /** * Check if we can process not exceeding memory_limit * diff --git a/program/localization/index.inc b/program/localization/index.inc index 6fdb9db3575..bc822902690 100644 --- a/program/localization/index.inc +++ b/program/localization/index.inc @@ -20,7 +20,7 @@ +-----------------------------------------------------------------------+ */ -// langage codes according to ISO 639-1 +// language codes according to ISO 639-1 // country codes according to ISO 3166-1 (Alpha-2) // original names from http://www.mediaglyphs.org/mg/?p=langnames diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index b6f4195ad77..982cbb72732 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -910,7 +910,7 @@ function rcmail_compose_part_body($part, $isHtml = false) } // add HTML formatting - $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); + $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed', $part->ctype_parameters['delsp'] == 'yes'); } } else { @@ -927,7 +927,7 @@ function rcmail_compose_part_body($part, $isHtml = false) } else { if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') { - $body = rcube_mime::unfold_flowed($body); + $body = rcube_mime::unfold_flowed($body, null, $part->ctype_parameters['delsp'] == 'yes'); } // try to remove the signature diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 2cec5eafb66..e09ba636537 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -956,7 +956,9 @@ function rcmail_print_body($body, $part, $p = array()) // plaintext postprocessing if ($part->ctype_secondary == 'plain') { - $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); + $flowed = $part->ctype_parameters['format'] == 'flowed'; + $delsp = $part->ctype_parameters['delsp'] == 'yes'; + $body = rcmail_plain_body($body, $flowed, $delsp); } // allow post-processing of the message body @@ -974,9 +976,10 @@ function rcmail_print_body($body, $part, $p = array()) * * @return string Formatted HTML string */ -function rcmail_plain_body($body, $flowed = false) +function rcmail_plain_body($body, $flowed = false, $delsp = false) { - $options = array('flowed' => $flowed, 'wrap' => !$flowed, 'replacer' => 'rcmail_string_replacer'); + $options = array('flowed' => $flowed, 'wrap' => !$flowed, 'replacer' => 'rcmail_string_replacer', + 'delsp' => $delsp); $text2html = new rcube_text2html($body, false, $options); $body = $text2html->get_html(); @@ -1473,7 +1476,7 @@ function rcmail_html4inline($body, $container_id, $body_class='', &$attributes=a unset($GLOBALS['rcmail_html_container_id']); $body = preg_replace(array( - // add comments arround html and other tags + // add comments around html and other tags '/(]*>)/i', '/(<\?xml[^>]*>)/i', '/(<\/?html[^>]*>)/i', diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 62c9e437220..47977def014 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -87,7 +87,6 @@ if (!empty($_GET['_thumb']) && $attachment->is_valid()) { if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) { $mimetype = 'image/' . $imgtype; - unlink($orig_name); } else { // Resize failed, we need to check the file mimetype @@ -95,6 +94,8 @@ if (!empty($_GET['_thumb']) && $attachment->is_valid()) { $_GET['_thumb'] = 0; $_REQUEST['_embed'] = 1; } + + unlink($orig_name); } if (!empty($_GET['_thumb'])) { @@ -598,6 +599,7 @@ class rcmail_attachment_handler $this->body(0, $fp); $this->body_file = $filename; fclose($fp); + @chmod(filename, 0600); return true; } @@ -696,7 +698,7 @@ class rcmail_attachment_handler if ($error == rcube_imap_generic::ERROR_BAD) { ob_end_clean(); - // Get action is often executed simultanously. + // Get action is often executed simultaneously. // Some servers have MAXPERIP or other limits. // To workaround this we'll wait for some time // and try again (once). diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc index 2ee0fc808ef..a249c922f6c 100644 --- a/program/steps/mail/search_contacts.inc +++ b/program/steps/mail/search_contacts.inc @@ -12,7 +12,7 @@ | See the README file for a full license statement. | | | | PURPOSE: | - | Search contacts from the adress book widget | + | Search contacts from the address book widget | | | +-----------------------------------------------------------------------+ | Author: Thomas Bruederli | diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index afaa7ac842a..ce7020a60b9 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -12,9 +12,7 @@ | See the README file for a full license statement. | | | | PURPOSE: | - | Compose a new mail message with all headers and attachments | - | and send it using the PEAR::Net_SMTP class or with PHP mail() | - | | + | Compose a new mail message and send it or store as draft | +-----------------------------------------------------------------------+ | Author: Thomas Bruederli | +-----------------------------------------------------------------------+ diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc index 8ddc17e65ee..c16f2cabd07 100644 --- a/program/steps/settings/edit_folder.inc +++ b/program/steps/settings/edit_folder.inc @@ -86,20 +86,21 @@ function rcmail_folder_form($attrib) // 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 --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index 345eb47855b..a7fab763e58 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -277,12 +277,13 @@ function rcmail_subscription_form($attrib) 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 --git a/program/steps/settings/upload.inc b/program/steps/settings/upload.inc index 0cf7ae60cf1..5e91f1d20f4 100644 --- a/program/steps/settings/upload.inc +++ b/program/steps/settings/upload.inc @@ -27,6 +27,11 @@ if (!empty($_GET['_progress'])) { $from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_GET); $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 --git a/skins/larry/templates/compose.html b/skins/larry/templates/compose.html index 3dcc48c047c..92b0eecdac3 100644 --- a/skins/larry/templates/compose.html +++ b/skins/larry/templates/compose.html @@ -134,7 +134,7 @@

- +

diff --git a/tests/Framework/Mime.php b/tests/Framework/Mime.php index f3f0d0b8154..bbab0e64b77 100644 --- a/tests/Framework/Mime.php +++ b/tests/Framework/Mime.php @@ -170,6 +170,20 @@ function test_unfold_flowed2() $this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines [2]"); } + /** + * Test format=flowed delsp=yes unfolding (RFC3676) + */ + function test_unfold_flowed_delsp() + { + $flowed = "そしてジョバンニはすぐうしろの天気輪の柱が \r\n" + ."いつかぼんやりした三角標の形になって、しば \r\n" + ."らく蛍のように、ぺかぺか消えたりともったり \r\n" + ."しているのを見ました。"; + $unfolded = "そしてジョバンニはすぐうしろの天気輪の柱がいつかぼんやりした三角標の形になって、しばらく蛍のように、ぺかぺか消えたりともったりしているのを見ました。"; + + $this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed, null, true), "Test correct unfolding of flowed DelSp=Yes lines"); + } + /** * Test wordwrap() */ diff --git a/tests/Framework/Text2Html.php b/tests/Framework/Text2Html.php index 03c4bd097d0..c85e44a4c42 100644 --- a/tests/Framework/Text2Html.php +++ b/tests/Framework/Text2Html.php @@ -19,6 +19,7 @@ function data_text2html() 'break' => '
', 'links' => false, 'flowed' => false, + 'delsp' => false, 'wrap' => false, 'space' => '_', // replace UTF-8 non-breaking space for simpler testing 'nobr_start' => '>', @@ -70,7 +71,30 @@ function data_text2html() $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
aaaa bbbb
>cccc_dddd<", $options); $data[] = array("\x02\x03", ">\x02\x03<", $options); + $options['flowed'] = true; + $options['delsp'] = true; + + $data[] = array(" aaaa", "aaaa", $options); + $data[] = array("aaaa aaaa", ">aaaa_aaaa<", $options); + $data[] = array("aaaa aaaa", ">aaaa__aaaa<", $options); + $data[] = array("aaaa aaaa", ">aaaa___aaaa<", $options); + $data[] = array("aaaa\taaaa", ">aaaa____aaaa<", $options); + $data[] = array("aaaa\naaaa", "aaaa
aaaa", $options); + $data[] = array("aaaa\n aaaa", "aaaa
aaaa", $options); + $data[] = array("aaaa\n aaaa", "aaaa
>_aaaa<", $options); + $data[] = array("aaaa\n aaaa", "aaaa
>__aaaa<", $options); + $data[] = array("\taaaa", ">____aaaa<", $options); + $data[] = array("\naaaa", "
aaaa", $options); + $data[] = array("\n aaaa", "
aaaa", $options); + $data[] = array("\n aaaa", "
>_aaaa<", $options); + $data[] = array("\n aaaa", "
>__aaaa<", $options); + $data[] = array("aaaa\n\nbbbb", "aaaa

bbbb", $options); + $data[] = array(">aaaa \n>aaaa", "
aaaaaaaa
", $options); + $data[] = array(">aaaa\n>aaaa", "
aaaa
aaaa
", $options); + $data[] = array(">aaaa \n>bbbb\ncccc dddd", "
aaaabbbb
>cccc_dddd<", $options); + $options['flowed'] = false; + $options['delsp'] = false; $options['wrap'] = true; $data[] = array(">>aaaa bbbb\n>>\n>>>\n>cccc\n\ndddd eeee", diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php index ba04e15454d..ad81f64049c 100644 --- a/tests/Framework/Utils.php +++ b/tests/Framework/Utils.php @@ -220,6 +220,15 @@ function test_mod_css_styles_xss() $this->assertEquals("#rcmbody { background-image: url(data:image/png;base64,123); }", $mod, "Data URIs in url() allowed"); } + function test_xss_entity_decode() + { + $mod = rcube_utils::xss_entity_decode("<img/src=x onerror=alert(1)// "); + $this->assertNotContains('";}'); + $this->assertNotContains('