From b28a38c7575dd6068d9e1b7f95e391e214a52a78 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 14 Aug 2012 15:22:16 +0200 Subject: - Fix Remove from group option is active for contact search result (#1488608) --- program/js/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'program/js') diff --git a/program/js/app.js b/program/js/app.js index 214a5cb80..de61b21f1 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -4031,8 +4031,7 @@ function rcube_webmail() // if a group is currently selected, and there is at least one contact selected // thend we can enable the group-remove-selected command - this.enable_command('group-remove-selected', typeof this.env.group != 'undefined' && list.selection.length > 0); - + this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0); this.enable_command('compose', this.env.group || list.selection.length > 0); this.enable_command('edit', id && writable); this.enable_command('delete', list.selection.length && writable); -- cgit v1.2.3 From c086978f6a91eacb339fd2976202fca9dad2ef32 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 15 Aug 2012 11:20:40 +0200 Subject: Fix XSS issue where plain signatures wasn't secured in HTML mode (#1488613) --- CHANGELOG | 3 ++- program/js/app.js | 31 +++++-------------------------- program/steps/mail/compose.inc | 30 +++++++++++++++++++++++------- 3 files changed, 30 insertions(+), 34 deletions(-) (limited to 'program/js') diff --git a/CHANGELOG b/CHANGELOG index 932680645..37170fc65 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ CHANGELOG Roundcube Webmail =========================== -- Fix XSS issue with href="javascript:" not being removed (#1488613) +- Fix XSS issue where plain signatures wasn't secured in HTML mode (#1488613) +- Fix XSS issue where href="javascript:" wasn't secured (#1488613) - Fix impossible to create message with empty plain text part (#1488610) - Fix stripped apostrophes when replying in plain text to HTML message (#1488606) - Fix inactive Save search option after advanced search (#1488607) diff --git a/program/js/app.js b/program/js/app.js index de61b21f1..e8bb6c1a7 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -3298,8 +3298,7 @@ function rcube_webmail() input_message = $("[name='_message']"), message = input_message.val(), is_html = ($("input[name='_is_html']").val() == '1'), - sig = this.env.identity, - sig_separator = this.env.sig_above && (this.env.compose_mode == 'reply' || this.env.compose_mode == 'forward') ? '---' : '-- '; + sig = this.env.identity; // enable manual signature insert if (this.env.signatures && this.env.signatures[id]) { @@ -3312,25 +3311,18 @@ function rcube_webmail() if (!is_html) { // remove the 'old' signature if (show_sig && sig && this.env.signatures && this.env.signatures[sig]) { - - sig = this.env.signatures[sig].is_html ? this.env.signatures[sig].plain_text : this.env.signatures[sig].text; + sig = this.env.signatures[sig].text; sig = sig.replace(/\r\n/g, '\n'); - if (!sig.match(/^--[ -]\n/m)) - sig = sig_separator + '\n' + sig; - p = this.env.sig_above ? message.indexOf(sig) : message.lastIndexOf(sig); if (p >= 0) message = message.substring(0, p) + message.substring(p+sig.length, message.length); } // add the new signature string if (show_sig && this.env.signatures && this.env.signatures[id]) { - sig = this.env.signatures[id]['is_html'] ? this.env.signatures[id]['plain_text'] : this.env.signatures[id]['text']; + sig = this.env.signatures[id].text; sig = sig.replace(/\r\n/g, '\n'); - if (!sig.match(/^--[ -]\n/m)) - sig = sig_separator + '\n' + sig; - if (this.env.sig_above) { if (p >= 0) { // in place of removed signature message = message.substring(0, p) + sig + message.substring(p, message.length); @@ -3394,21 +3386,8 @@ function rcube_webmail() } } - if (this.env.signatures[id]) { - if (this.env.signatures[id].is_html) { - sig = this.env.signatures[id].text; - if (!this.env.signatures[id].plain_text.match(/^--[ -]\r?\n/m)) - sig = sig_separator + '
' + sig; - } - else { - sig = this.env.signatures[id].text; - if (!sig.match(/^--[ -]\r?\n/m)) - sig = sig_separator + '\n' + sig; - sig = '
' + sig + '
'; - } - - sigElem.innerHTML = sig; - } + if (this.env.signatures[id]) + sigElem.innerHTML = this.env.signatures[id].html; } this.env.identity = id; diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 71a1c0f21..1a1d244e1 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -529,7 +529,7 @@ function rcmail_compose_headers($attrib) function rcmail_compose_header_from($attrib) { - global $MESSAGE, $OUTPUT; + global $MESSAGE, $OUTPUT, $RCMAIL, $compose_mode; // pass the following attributes to the form class $field_attrib = array('name' => '_from'); @@ -540,6 +540,8 @@ function rcmail_compose_header_from($attrib) if (count($MESSAGE->identities)) { $a_signatures = array(); + $separator = $RCMAIL->config->get('sig_above') + && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- '; $field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)"; $select_from = new html_select($field_attrib); @@ -553,13 +555,27 @@ function rcmail_compose_header_from($attrib) // add signature to array if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig'])) { - $a_signatures[$identity_id]['text'] = $sql_arr['signature']; - $a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false; - if ($a_signatures[$identity_id]['is_html']) - { - $h2t = new html2text($a_signatures[$identity_id]['text'], false, false); - $a_signatures[$identity_id]['plain_text'] = trim($h2t->get_text()); + $text = $html = $sql_arr['signature']; + + if ($sql_arr['html_signature']) { + $h2t = new html2text($sql_arr['signature'], false, false); + $text = trim($h2t->get_text()); + } + else { + $html = htmlentities($html, ENT_NOQUOTES, RCMAIL_CHARSET); + } + + if (!preg_match('/^--[ -]\r?\n/m', $text)) { + $text = $separator . "\n" . $text; + $html = $separator . "
" . $html; + } + + if (!$sql_arr['html_signature']) { + $html = "
" . $html . "
"; } + + $a_signatures[$identity_id]['text'] = $text; + $a_signatures[$identity_id]['html'] = $html; } } -- cgit v1.2.3 From ae7027de029e28fdd3894efe919b6171b2b11eab Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 20 Aug 2012 09:32:25 +0200 Subject: Added session_path config option and unified cookies settings in javascript --- CHANGELOG | 1 + config/main.inc.php.dist | 7 +++++-- program/include/rcube.php | 5 +++++ program/include/rcube_output_html.php | 5 +++++ program/js/app.js | 8 ++++++++ program/js/common.js | 1 + program/js/googiespell.js | 4 ++-- skins/classic/splitter.js | 4 ++-- skins/larry/ui.js | 6 +++--- 9 files changed, 32 insertions(+), 9 deletions(-) (limited to 'program/js') diff --git a/CHANGELOG b/CHANGELOG index 6ea101e8f..4d18f64b7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Added session_path config option and unified cookies settings in javascript - Added "Undeleted" option to messages list filter - Rewritten test scripts for PHPUnit - Add new DB abstraction layer based on PHP PDO, supporting SQLite3 (#1488332) diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index 1e9c1fdcd..8d615f3b0 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -241,12 +241,15 @@ $rcmail_config['display_version'] = false; // must be greater than 'keep_alive'/60 $rcmail_config['session_lifetime'] = 10; -// session domain: .example.org +// Session domain: .example.org $rcmail_config['session_domain'] = ''; -// session name. Default: 'roundcube_sessid' +// Session name. Default: 'roundcube_sessid' $rcmail_config['session_name'] = null; +// Session path. Defaults to PHP session.cookie_path setting. +$rcmail_config['session_path'] = null; + // Backend to use for session storage. Can either be 'db' (default) or 'memcache' // If set to memcache, a list of servers need to be specified in 'memcache_hosts' // Make sure the Memcache extension (http://pecl.php.net/package/memcache) version >= 2.0.0 is installed diff --git a/program/include/rcube.php b/program/include/rcube.php index 84014ef5c..0e40b3c6b 100644 --- a/program/include/rcube.php +++ b/program/include/rcube.php @@ -405,12 +405,17 @@ class rcube $sess_name = $this->config->get('session_name'); $sess_domain = $this->config->get('session_domain'); + $sess_path = $this->config->get('session_path'); $lifetime = $this->config->get('session_lifetime', 0) * 60; // set session domain if ($sess_domain) { ini_set('session.cookie_domain', $sess_domain); } + // set session path + if ($sess_path) { + ini_set('session.cookie_path', $sess_path); + } // set session garbage collecting time according to session_lifetime if ($lifetime) { ini_set('session.gc_maxlifetime', $lifetime * 2); diff --git a/program/include/rcube_output_html.php b/program/include/rcube_output_html.php index 0a8f0e364..a071ee354 100644 --- a/program/include/rcube_output_html.php +++ b/program/include/rcube_output_html.php @@ -67,6 +67,11 @@ class rcube_output_html extends rcube_output $this->set_env('task', $task); $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin')); + // add cookie info + $this->set_env('cookie_domain', ini_get('session.cookie_domain')); + $this->set_env('cookie_path', ini_get('session.cookie_path')); + $this->set_env('cookie_secure', ini_get('session.cookie_secure')); + // load the correct skin (in case user-defined) $skin = $this->config->get('skin'); $this->set_skin($skin); diff --git a/program/js/app.js b/program/js/app.js index e8bb6c1a7..9ca16b39c 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -6585,6 +6585,12 @@ function rcube_webmail() return 0; }; + // Cookie setter + this.set_cookie = function(name, value, expires) + { + setCookie(name, value, expires, this.env.cookie_path, this.env.cookie_domain, this.env.cookie_secure); + } + } // end object rcube_webmail @@ -6615,6 +6621,8 @@ rcube_webmail.long_subject_title_ie = function(elem, indent) } }; +rcube_webmail.prototype.get_cookie = getCookie; + // copy event engine prototype rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; diff --git a/program/js/common.js b/program/js/common.js index fdef3453e..a08387ecb 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -635,6 +635,7 @@ function getCookie(name) return unescape(dc.substring(begin + prefix.length, end)); }; +// deprecated aliases, to be removed, use rcmail.set_cookie/rcmail.get_cookie roundcube_browser.prototype.set_cookie = setCookie; roundcube_browser.prototype.get_cookie = getCookie; diff --git a/program/js/googiespell.js b/program/js/googiespell.js index 9f1b41bb2..478858bac 100644 --- a/program/js/googiespell.js +++ b/program/js/googiespell.js @@ -25,7 +25,7 @@ var GOOGIE_CUR_LANG, function GoogieSpell(img_dir, server_url, has_dict) { var ref = this, - cookie_value = getCookie('language'); + cookie_value = rcmail.get_cookie('language'); GOOGIE_CUR_LANG = cookie_value != null ? cookie_value : GOOGIE_DEFAULT_LANG; @@ -150,7 +150,7 @@ this.setCurrentLanguage = function(lan_code) //Set cookie var now = new Date(); now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); - setCookie('language', lan_code, now); + rcmail.set_cookie('language', lan_code, now); }; this.setForceWidthHeight = function(width, height) diff --git a/skins/classic/splitter.js b/skins/classic/splitter.js index 59ebb5151..3f1c97302 100644 --- a/skins/classic/splitter.js +++ b/skins/classic/splitter.js @@ -47,7 +47,7 @@ function rcube_splitter(attrib) rcube_event.add_listener({element: window, event:'resize', object:this, method:'onResize'}); // read saved position from cookie - var cookie = bw.get_cookie(this.id); + var cookie = rcmail.get_cookie(this.id); if (cookie && !isNaN(cookie)) { this.pos = parseFloat(cookie); this.resize(); @@ -197,7 +197,7 @@ function rcube_splitter(attrib) { var exp = new Date(); exp.setYear(exp.getFullYear() + 1); - bw.set_cookie(this.id, this.pos, exp); + rcmail.set_cookie(this.id, this.pos, exp); }; } // end class rcube_splitter diff --git a/skins/larry/ui.js b/skins/larry/ui.js index b6056b6ee..ca1680759 100644 --- a/skins/larry/ui.js +++ b/skins/larry/ui.js @@ -461,7 +461,7 @@ function rcube_mail_ui() var button = $(e.target), frame = $('#mailpreviewframe'), visible = !frame.is(':visible'), - splitter = mailviewsplit.pos || parseInt(bw.get_cookie('mailviewsplitter') || 320), + splitter = mailviewsplit.pos || parseInt(rcmail.get_cookie('mailviewsplitter') || 320), topstyles, bottomstyles, uid; frame.toggle(); @@ -974,7 +974,7 @@ function rcube_splitter(p) $(window).resize(onResize); // read saved position from cookie - var cookie = bw.get_cookie(this.id); + var cookie = rcmail.get_cookie(this.id); if (cookie && !isNaN(cookie)) { this.pos = parseFloat(cookie); this.resize(); @@ -1135,7 +1135,7 @@ function rcube_splitter(p) { var exp = new Date(); exp.setYear(exp.getFullYear() + 1); - bw.set_cookie(this.id, this.pos, exp); + rcmail.set_cookie(this.id, this.pos, exp); }; } // end class rcube_splitter -- cgit v1.2.3 From ff805351cae78676927f76a1960b8e688558fe95 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Thu, 23 Aug 2012 20:08:37 +0200 Subject: Fix email address validation for addresses with IP address in domain part --- CHANGELOG | 1 + program/js/common.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'program/js') diff --git a/CHANGELOG b/CHANGELOG index 23fb7b720..d529169e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix email address validation for addresses with IP address in domain part - Fix Larry skin issues in IE7 compat. mode (#1488618) - Fix so subscribed non-existing/non-accessible shared folder can be unsubscribed - Added session_path config option and unified cookies settings in javascript diff --git a/program/js/common.js b/program/js/common.js index a08387ecb..2d8d9e176 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -494,12 +494,13 @@ function rcube_check_email(input, inline) atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', quoted_pair = '\\x5c[\\x00-\\x7f]', quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22', + ip_addr = '\\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\\]*', // Use simplified domain matching, because we need to allow Unicode characters here // So, e-mail address should be validated also on server side after idn_to_ascii() use //domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d', //sub_domain = '('+atom+'|'+domain_literal+')', // allow punycode/unicode top-level domain - domain = '([^@\\x2e]+\\x2e)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})', + domain = '(('+ip_addr+')|(([^@\\x2e]+\\x2e)+([^\\x00-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})))', // ICANN e-mail test (http://idn.icann.org/E-mail_test) icann_domains = [ '\\u0645\\u062b\\u0627\\u0644\\x2e\\u0625\\u062e\\u062a\\u0628\\u0627\\u0631', @@ -527,7 +528,6 @@ function rcube_check_email(input, inline) return false; }; - // recursively copy an object function rcube_clone_object(obj) { -- cgit v1.2.3 From da28121dcd160045c468b7028ee835b24f0cb965 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Fri, 24 Aug 2012 10:10:25 +0200 Subject: Improved email address validation with IPv6 support --- program/include/rcube_utils.php | 52 ++++++++++++++++++++++++++++++++++++++--- program/js/common.js | 4 +++- tests/Utils.php | 17 +++++++++++--- 3 files changed, 66 insertions(+), 7 deletions(-) (limited to 'program/js') diff --git a/program/include/rcube_utils.php b/program/include/rcube_utils.php index 9f18b79c4..defb2aed1 100644 --- a/program/include/rcube_utils.php +++ b/program/include/rcube_utils.php @@ -92,9 +92,9 @@ class rcube_utils return false; } - // Check domain part - if (preg_match('/^\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]*$/', $domain_part)) { - return true; // IP address + // Validate domain part + if (preg_match('/^\[((IPv6:[0-9a-f:.]+)|([0-9.]+))\]$/i', $domain_part, $matches)) { + return self::ip_check(preg_replace('/^IPv6:/i', '', $matches[1])); // valid IPv4 or IPv6 address } else { // If not an IP address @@ -146,6 +146,52 @@ class rcube_utils return false; } + + /** + * Validates IPv4 or IPv6 address + * + * @param string $ip IP address in v4 or v6 format + * + * @return bool True if the address is valid + */ + public static function ip_check($ip) + { + // IPv6, but there's no build-in IPv6 support + if (strpos($ip, ':') !== false && !defined('AF_INET6')) { + $parts = explode(':', $domain_part); + $count = count($parts); + + if ($count > 8 || $count < 2) { + return false; + } + + foreach ($parts as $idx => $part) { + $length = strlen($part); + if (!$length) { + // there can be only one :: + if ($found_empty) { + return false; + } + $found_empty = true; + } + // last part can be an IPv4 address + else if ($idx == $count - 1) { + if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) { + return @inet_pton($part) !== false; + } + } + else if (!preg_match('/^[0-9a-f]{1,4}$/i', $part)) { + return false; + } + } + + return true; + } + + return @inet_pton($ip) !== false; + } + + /** * Check whether the HTTP referer matches the current request * diff --git a/program/js/common.js b/program/js/common.js index 2d8d9e176..f9e945c05 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -494,7 +494,9 @@ function rcube_check_email(input, inline) atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', quoted_pair = '\\x5c[\\x00-\\x7f]', quoted_string = '\\x22('+qtext+'|'+quoted_pair+')*\\x22', - ip_addr = '\\[*(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\\]*', + ipv4 = '\\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\\]', + ipv6 = '\\[IPv6:[0-9a-f:.]+\\]', + ip_addr = '(' + ipv4 + ')|(' + ipv6 + ')', // Use simplified domain matching, because we need to allow Unicode characters here // So, e-mail address should be validated also on server side after idn_to_ascii() use //domain_literal = '\\x5b('+dtext+'|'+quoted_pair+')*\\x5d', diff --git a/tests/Utils.php b/tests/Utils.php index 648b39989..ad0aa1dde 100644 --- a/tests/Utils.php +++ b/tests/Utils.php @@ -18,8 +18,10 @@ class Utils extends PHPUnit_Framework_TestCase array('firstname.lastname@domain.com', 'Email contains dot in the address field'), array('email@subdomain.domain.com', 'Email contains dot with subdomain'), array('firstname+lastname@domain.com', 'Plus sign is considered valid character'), - array('email@123.123.123.123', 'Domain is valid IP address'), - array('email@[123.123.123.123]', 'Square bracket around IP address is considered valid'), + array('email@[123.123.123.123]', 'Square bracket around IP address'), + array('email@[IPv6:::1]', 'Square bracket around IPv6 address (1)'), + array('email@[IPv6:::1.2.3.4]', 'Square bracket around IPv6 address (2)'), + array('email@[IPv6:2001:2d12:c4fe:5afe::1]', 'Square bracket around IPv6 address (3)'), array('"email"@domain.com', 'Quotes around email is considered valid'), array('1234567890@domain.com', 'Digits in address are valid'), array('email@domain-one.com', 'Dash in domain name is valid'), @@ -50,7 +52,16 @@ class Utils extends PHPUnit_Framework_TestCase array('email@domain', 'Missing top level domain (.com/.net/.org/etc)'), array('email@-domain.com', 'Leading dash in front of domain is invalid'), // array('email@domain.web', '.web is not a valid top level domain'), - array('email@111.222.333.44444', 'Invalid IP format'), + array('email@123.123.123.123', 'IP address without brackets'), + array('email@2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets'), + array('email@IPv6:2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets (2)'), + array('email@[111.222.333.44444]', 'Invalid IP format'), + array('email@[111.222.255.257]', 'Invalid IP format (2)'), + array('email@[.222.255.257]', 'Invalid IP format (3)'), + array('email@[::1]', 'Invalid IPv6 format (1)'), + array('email@[IPv6:2001:23x2:1]', 'Invalid IPv6 format (2)'), + array('email@[IPv6:1111:2222:33333::4444:5555]', 'Invalid IPv6 format (3)'), + array('email@[IPv6:1111::3333::4444:5555]', 'Invalid IPv6 format (4)'), array('email@domain..com', 'Multiple dot in the domain portion is invalid'), ); } -- cgit v1.2.3 From 4d1515cb0b43117792a37c03a6ca35ea3ab65eee Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Fri, 24 Aug 2012 18:52:50 +0200 Subject: Fix javascript error on Reply-List action --- program/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'program/js') diff --git a/program/js/app.js b/program/js/app.js index 9ca16b39c..f14f22322 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -976,7 +976,7 @@ function rcube_webmail() // do reply-list, when list is detected and popup menu wasn't used url._all = (!props && this.commands['reply-list'] ? 'list' : 'all'); else if (command == 'reply-list') - url._all = list; + url._all = 'list'; this.goto_url('compose', url, true); } -- cgit v1.2.3 From 4877dbd4d2ca63d7f6b8857abcb4d2f895f2542e Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 26 Aug 2012 10:23:49 +0200 Subject: Fix Larry's messages list filter in IE (#1488632) --- CHANGELOG | 1 + program/js/app.js | 47 +++++++++++++++++++++-------------------------- 2 files changed, 22 insertions(+), 26 deletions(-) (limited to 'program/js') diff --git a/CHANGELOG b/CHANGELOG index 8af03d52e..05540a5a4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix Larry's messages list filter in IE (#1488632) - Fix more IE issues by disabling Compat. mode with X-UA-Compatible meta tag (#1488626) - Fix setting locales under Solaris - use additional .UTF-8 suffix (#1488628) - Fix email address validation for addresses with IP address in domain part diff --git a/program/js/app.js b/program/js/app.js index f14f22322..838f240f8 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1447,29 +1447,21 @@ function rcube_webmail() this.doc_mouse_up = function(e) { - var model, list, li, id; + var model, list, id; // ignore event if jquery UI dialog is open if ($(rcube_event.get_target(e)).closest('.ui-dialog, .ui-widget-overlay').length) return; - if (list = this.message_list) { - if (!rcube_mouse_is_over(e, list.list.parentNode)) - list.blur(); - else - list.focus(); + if (list = this.message_list) model = this.env.mailboxes; - } - else if (list = this.contact_list) { - if (!rcube_mouse_is_over(e, list.list.parentNode)) - list.blur(); - else - list.focus(); + else if (list = this.contact_list) model = this.env.contactfolders; - } - else if (this.ksearch_value) { + else if (this.ksearch_value) this.ksearch_blur(); - } + + if (list && !rcube_mouse_is_over(e, list.list.parentNode)) + list.blur(); // handle mouse release when dragging if (this.drag_active && model && this.env.last_folder_target) { @@ -2652,34 +2644,37 @@ function rcube_webmail() // set a specific flag to one or more messages this.mark_message = function(flag, uid) { - var a_uids = [], r_uids = [], len, n, id, - selection = this.message_list ? this.message_list.get_selection() : []; + var a_uids = [], r_uids = [], len, n, id, selection, + list = this.message_list; if (uid) a_uids[0] = uid; else if (this.env.uid) a_uids[0] = this.env.uid; - else if (this.message_list) { + else if (list) { + selection = list.get_selection(); for (n=0, len=selection.length; n Date: Wed, 29 Aug 2012 13:26:34 +0200 Subject: Fix so contentframe can have name != id --- program/js/app.js | 95 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 38 deletions(-) (limited to 'program/js') diff --git a/program/js/app.js b/program/js/app.js index 838f240f8..48de21764 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -1538,14 +1538,17 @@ function rcube_webmail() if (list.multi_selecting || !this.env.contentframe) return; - if (list.get_single_selection() && window.frames && window.frames[this.env.contentframe]) { - if (window.frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)>=0) { - if (this.preview_timer) - clearTimeout(this.preview_timer); - if (this.preview_read_timer) - clearTimeout(this.preview_read_timer); - this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, 200); - } + if (list.get_single_selection()) + return; + + var win = this.get_frame_window(this.env.contentframe); + + if (win && win.location.href.indexOf(this.env.blankpage)>=0) { + if (this.preview_timer) + clearTimeout(this.preview_timer); + if (this.preview_read_timer) + clearTimeout(this.preview_read_timer); + this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, 200); } }; @@ -1910,12 +1913,12 @@ function rcube_webmail() if (!id) return; - var target = window, + var win, target = window, action = preview ? 'preview': 'show', url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox); - if (preview && this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { - target = window.frames[this.env.contentframe]; + if (preview && (win = this.get_frame_window(this.env.contentframe))) { + target = win; url += '&_framed=1'; } @@ -1952,20 +1955,37 @@ function rcube_webmail() this.show_contentframe = function(show) { - var frm, win; - if (this.env.contentframe && (frm = $('#'+this.env.contentframe)) && frm.length) { - if (!show && (win = window.frames[this.env.contentframe])) { + var frame, win, name = this.env.contentframe; + + if (name && (frame = this.get_frame_element(name))) { + if (!show && (win = this.get_frame_window(name))) { if (win.location && win.location.href.indexOf(this.env.blankpage)<0) win.location.href = this.env.blankpage; } else if (!bw.safari && !bw.konq) - frm[show ? 'show' : 'hide'](); - } + $(frame)[show ? 'show' : 'hide'](); + } if (!show && this.busy) this.set_busy(false, null, this.env.frame_lock); }; + this.get_frame_element = function(id) + { + var frame; + + if (id && (frame = document.getElementById(id))) + return frame; + }; + + this.get_frame_window = function(id) + { + var frame = this.get_frame_element(id); + + if (frame && frame.name && window.frames) + return window.frames[frame.name]; + }; + this.lock_frame = function() { if (!this.env.frame_lock) @@ -2009,7 +2029,7 @@ function rcube_webmail() // list messages of a specific mailbox this.list_mailbox = function(mbox, page, sort, url) { - var target = window; + var win, target = window; if (typeof url != 'object') url = {}; @@ -2048,8 +2068,8 @@ function rcube_webmail() return; } - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { - target = window.frames[this.env.contentframe]; + if (win = this.get_frame_window(this.env.contentframe)) { + target = win; url._framed = 1; } @@ -4015,7 +4035,7 @@ function rcube_webmail() this.list_contacts = function(src, group, page) { - var folder, url = {}, + var win, folder, url = {}, target = window; if (!src) @@ -4047,8 +4067,8 @@ function rcube_webmail() return; } - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { - target = window.frames[this.env.contentframe]; + if (win = this.get_frame_window(this.env.contentframe)) { + target = win; url._framed = 1; } @@ -4104,11 +4124,11 @@ function rcube_webmail() // load contact record this.load_contact = function(cid, action, framed) { - var url = {}, target = window; + var win, url = {}, target = window; - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { + if (win = this.get_frame_window(this.env.contentframe)) { url._framed = 1; - target = window.frames[this.env.contentframe]; + target = win; this.show_contentframe(true); // load dummy content @@ -4726,11 +4746,11 @@ function rcube_webmail() // load advanced search page this.advanced_search = function() { - var url = {_form: 1, _action: 'search'}, target = window; + var win, url = {_form: 1, _action: 'search'}, target = window; - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { + if (win = this.get_frame_window(this.env.contentframe)) { url._framed = 1; - target = window.frames[this.env.contentframe]; + target = win; this.contact_list.clear_selection(); } @@ -4852,13 +4872,13 @@ function rcube_webmail() // preferences section select and load options frame this.section_select = function(list) { - var id = list.get_single_selection(), target = window, + var win, id = list.get_single_selection(), target = window, url = {_action: 'edit-prefs', _section: id}; if (id) { - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { + if (win = this.get_frame_window(this.env.contentframe)) { url._framed = 1; - target = window.frames[this.env.contentframe]; + target = win; } this.location_href(url, target, true); } @@ -4881,13 +4901,12 @@ function rcube_webmail() if (action == 'edit-identity' && (!id || id == this.env.iid)) return false; - var target = window, + var win, target = window, url = {_action: action, _iid: id}; - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { + if (win = this.get_frame_window(this.env.contentframe)) { url._framed = 1; - target = window.frames[this.env.contentframe]; - document.getElementById(this.env.contentframe).style.visibility = 'inherit'; + target = win; } if (action && (id || action == 'add-identity')) { @@ -5263,14 +5282,14 @@ function rcube_webmail() // when user select a folder in manager this.show_folder = function(folder, path, force) { - var target = window, + var win, target = window, url = '&_action=edit-folder&_mbox='+urlencode(folder); if (path) url += '&_path='+urlencode(path); - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { - target = window.frames[this.env.contentframe]; + if (win = this.get_frame_window(this.env.contentframe)) { + target = win; url += '&_framed=1'; } -- cgit v1.2.3 From e263994adc3f8f331c6167da1665c1920a5142f9 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Tue, 4 Sep 2012 19:29:16 +0200 Subject: Fix focus issue in IE when selecting message row (#1488620) --- CHANGELOG | 1 + program/js/list.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'program/js') diff --git a/CHANGELOG b/CHANGELOG index a13830450..0706009c4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix focus issue in IE when selecting message row (#1488620) - Remove (too big) min-width on mail screen - Add full headers view in message preview window (#1488538) - Fix message display page issues - unified with message preview (#1488590, #1488642) diff --git a/program/js/list.js b/program/js/list.js index e84124b7c..1457382a4 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -231,8 +231,8 @@ focus: function(e) } } - // Un-focus already focused elements - $(document.activeElement).blur(); + // Un-focus already focused elements (#1487123, #1487316, #1488600, #1488620) + $(':focus:not(body)').blur(); $('iframe').each(function() { this.blur(); }); if (e || (e = window.event)) -- cgit v1.2.3