From b46e5b7407940499964d8a553c3eada05850f29d Mon Sep 17 00:00:00 2001 From: thomascube Date: Wed, 9 Feb 2011 10:51:50 +0000 Subject: Apply more bugfixes from trunk for 0.5.1 --- CHANGELOG | 10 +++++++ config/main.inc.php.dist | 3 +++ index.php | 21 +++++++++++---- program/include/main.inc | 46 ++++++++++++++++++++++++++++++++ program/include/rcmail.php | 4 +-- program/include/rcube_config.php | 2 +- program/include/rcube_imap_generic.php | 6 ++--- program/include/rcube_ldap.php | 2 +- program/include/rcube_message.php | 10 +++++++ program/include/rcube_session.php | 2 ++ program/include/rcube_shared.inc | 2 +- program/include/rcube_smtp.php | 7 ++--- program/include/rcube_template.php | 2 +- program/js/common.js | 20 ++++++++++++-- program/lib/washtml.php | 4 +++ program/localization/de_DE/labels.inc | 6 ++--- program/steps/addressbook/import.inc | 2 +- program/steps/addressbook/save.inc | 4 +-- program/steps/mail/addcontact.inc | 2 +- program/steps/mail/compose.inc | 10 +++---- program/steps/mail/func.inc | 17 ++++++------ program/steps/mail/sendmail.inc | 6 ++--- program/steps/settings/edit_identity.inc | 6 ++--- program/steps/settings/func.inc | 2 +- program/steps/settings/save_identity.inc | 16 +++++------ program/steps/utils/error.inc | 7 +++++ program/steps/utils/modcss.inc | 12 ++++----- skins/default/common.css | 10 ++++++- skins/default/functions.js | 2 +- skins/default/mail.css | 2 +- 30 files changed, 182 insertions(+), 63 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c9ccc277b..9375dc769 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,16 @@ CHANGELOG Roundcube Webmail RELEASE 0.5.1 ------------- +- Security: add optional referer check to prevent CSRF in GET requests +- Fix email_dns_check setting not used for identities/contacts (#1487740) +- Fix ICANN example addresses doesn't validate (#1487742) +- Security: protect login form submission from CSRF +- Security: prevent from relaying malicious requests through modcss.inc +- Fix handling of non-image attachments in multipart/related messages (#1487750) +- Fix IDNA support when IDN/INTL modules are in use (#1487742) +- Fix handling of invalid HTML comments in messages (#1487759) +- Fix parsing FETCH response for very long headers (#1487753) +- Fix add/remove columns in message list when message_sort_order isn't set (#1487751) - Fix settings UI on IE 6 (#1487724) - Remove double borders in folder listing (#1487713) - Separate full message headers UI element from headers table (#1487715) diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index 144ca77b6..ea0092b0d 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -213,6 +213,9 @@ $rcmail_config['ip_check'] = false; // There have been problems reported with this feature. $rcmail_config['double_auth'] = false; +// check referer of incoming requests +$rcmail_config['referer_check'] = false; + // this key is used to encrypt the users imap password which is stored // in the session record (and the client cookie if remember password is enabled). // please provide a string of exactly 24 chars. diff --git a/index.php b/index.php index 89066b58d..f4e2a55a1 100644 --- a/index.php +++ b/index.php @@ -75,6 +75,8 @@ $RCMAIL->action = $startup['action']; // try to log in if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { + $request_valid = $_SESSION['temp'] && $RCMAIL->check_request(RCUBE_INPUT_POST, 'login'); + // purge the session in case of new login when a session already exists $RCMAIL->kill_session(); @@ -84,13 +86,14 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { 'pass' => get_input_value('_pass', RCUBE_INPUT_POST, true, $RCMAIL->config->get('password_charset', 'ISO-8859-1')), 'cookiecheck' => true, + 'valid' => $request_valid, )); // check if client supports cookies if ($auth['cookiecheck'] && empty($_COOKIE)) { $OUTPUT->show_message("cookiesdisabled", 'warning'); } - else if ($_SESSION['temp'] && !$auth['abort'] && + else if ($auth['valid'] && !$auth['abort'] && !empty($auth['host']) && !empty($auth['user']) && $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'])) { // create new session ID @@ -123,15 +126,15 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { else { $error_code = is_object($IMAP) ? $IMAP->get_error_code() : -1; - $OUTPUT->show_message($error_code < -1 ? 'imaperror' : 'loginfailed', 'warning'); + $OUTPUT->show_message($error_code < -1 ? 'imaperror' : (!$auth['valid'] ? 'invalidrequest' : 'loginfailed'), 'warning'); $RCMAIL->plugins->exec_hook('login_failed', array( 'code' => $error_code, 'host' => $auth['host'], 'user' => $auth['user'])); $RCMAIL->kill_session(); } } -// end session -else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id'])) { +// end session (after optional referer check) +else if ($RCMAIL->task == 'logout' && isset($_SESSION['user_id']) && (!$RCMAIL->config->get('referer_check') || rcube_check_referer())) { $userdata = array('user' => $_SESSION['username'], 'host' => $_SESSION['imap_host'], 'lang' => $RCMAIL->user->language); $OUTPUT->show_message('loggedout'); $RCMAIL->logout_actions(); @@ -167,7 +170,7 @@ if (empty($RCMAIL->user->ID)) { ); } - $OUTPUT->set_env('task', 'login'); + $RCMAIL->set_task('login'); $OUTPUT->send('login'); } // CSRF prevention @@ -187,6 +190,14 @@ else { $OUTPUT->show_message('invalidrequest', 'error'); $OUTPUT->send($RCMAIL->task); } + + // check referer if configured + if (!$request_check_whitelist[$RCMAIL->action] && $RCMAIL->config->get('referer_check') && !rcube_check_referer()) { + raise_error(array( + 'code' => 403, + 'type' => 'php', + 'message' => "Referer check failed"), true, true); + } } // handle special actions diff --git a/program/include/main.inc b/program/include/main.inc index b8d27d68c..f9cc4331b 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -1223,6 +1223,19 @@ function rcmail_remote_ip() } +/** + * Check whether the HTTP referer matches the current request + * + * @return boolean True if referer is the same host+path, false if not + */ +function rcube_check_referer() +{ + $uri = parse_url($_SERVER['REQUEST_URI']); + $referer = parse_url(rc_request_header('Referer')); + return $referer['host'] == rc_request_header('Host') && $referer['path'] == $uri['path']; +} + + /** * @access private * @return mixed @@ -1863,6 +1876,39 @@ function check_email($email, $dns_check=true) return false; } +/* + * Idn_to_ascii wrapper. + * Intl/Idn modules version of this function doesn't work with e-mail address + */ +function rcube_idn_to_ascii($str) +{ + return rcube_idn_convert($str, true); +} + +/* + * Idn_to_ascii wrapper. + * Intl/Idn modules version of this function doesn't work with e-mail address + */ +function rcube_idn_to_utf8($str) +{ + return rcube_idn_convert($str, false); +} + +function rcube_idn_convert($input, $is_utf=false) +{ + if ($at = strpos($input, '@')) { + $user = substr($input, 0, $at); + $domain = substr($input, $at+1); + } + else { + $domain = $input; + } + + $domain = $is_utf ? idn_to_ascii($domain) : idn_to_utf8($domain); + + return $at ? $user . '@' . $domain : $domain; +} + /** * Helper class to turn relative urls into absolute ones diff --git a/program/include/rcmail.php b/program/include/rcmail.php index e9f5b5fce..4ff790d85 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -691,12 +691,12 @@ class rcmail // Here we need IDNA ASCII // Only rcube_contacts class is using domain names in Unicode - $host = idn_to_ascii($host); + $host = rcube_idn_to_ascii($host); if (strpos($username, '@')) { // lowercase domain name list($local, $domain) = explode('@', $username); $username = $local . '@' . mb_strtolower($domain); - $username = idn_to_ascii($username); + $username = rcube_idn_to_ascii($username); } // user already registered -> overwrite username diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php index 76cf18307..15b9e3dd3 100644 --- a/program/include/rcube_config.php +++ b/program/include/rcube_config.php @@ -287,7 +287,7 @@ class rcube_config $domain = rcube_parse_host($this->prop['mail_domain']); if ($encode) - $domain = idn_to_ascii($domain); + $domain = rcube_idn_to_ascii($domain); return $domain; } diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php index 166a106a1..3b2e3ee87 100644 --- a/program/include/rcube_imap_generic.php +++ b/program/include/rcube_imap_generic.php @@ -1494,7 +1494,7 @@ class rcube_imap_generic // INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODYSTRUCTURE (...) // BODY[HEADER.FIELDS ... - if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/s', $line, $matches)) { + if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/sU', $line, $matches)) { $str = $matches[1]; // swap parents with quotes, then explode @@ -1531,7 +1531,7 @@ class rcube_imap_generic // BODYSTRUCTURE if ($bodystr) { - while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) { + while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/sU', $line, $m)) { $line2 = $this->readLine(1024); $line .= $this->multLine($line2, true); } @@ -1631,7 +1631,7 @@ class rcube_imap_generic break; case 'content-type': $ctype_parts = preg_split('/[; ]/', $string); - $result[$id]->ctype = array_shift($ctype_parts); + $result[$id]->ctype = strtolower(array_shift($ctype_parts)); if (preg_match('/charset\s*=\s*"?([a-z0-9\-\.\_]+)"?/i', $string, $regs)) { $result[$id]->charset = $regs[1]; } diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index d5cc13257..93b69649d 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -99,7 +99,7 @@ class rcube_ldap extends rcube_addressbook foreach ($this->prop['hosts'] as $host) { - $host = idn_to_ascii(rcube_parse_host($host)); + $host = rcube_idn_to_ascii(rcube_parse_host($host)); $this->_debug("C: Connect [$host".($this->prop['port'] ? ':'.$this->prop['port'] : '')."]"); if ($lc = @ldap_connect($host, $this->prop['port'])) diff --git a/program/include/rcube_message.php b/program/include/rcube_message.php index b6c865d1c..75b55fee0 100644 --- a/program/include/rcube_message.php +++ b/program/include/rcube_message.php @@ -506,6 +506,16 @@ class rcube_message ) { $this->attachments[] = $inline_object; } + // MS Outlook sometimes also adds non-image attachments as related + // We'll add all such attachments to the attachments list + // Warning: some browsers support pdf in + // @TODO: we should fetch HTML body and find attachment's content-id + // to handle also image attachments without reference in the body + if (!empty($inline_object->filename) + && !preg_match('/^image\/(gif|jpe?g|png|tiff|bmp|svg)/', $inline_object->mimetype) + ) { + $this->attachments[] = $inline_object; + } } // add replace array to each content part diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php index 4137b3714..59ce42379 100644 --- a/program/include/rcube_session.php +++ b/program/include/rcube_session.php @@ -154,6 +154,8 @@ class rcube_session sprintf("DELETE FROM %s WHERE sess_id = ?", get_table_name('session')), $key); + if ($key == $this->key) + $this->vars = false; return true; } diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index d6d91e03f..afaa15d69 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -700,7 +700,7 @@ if (!function_exists('idn_to_utf8')) $loaded = true; } - if ($idn && $domain && preg_match('/(^|@|\.)xn--/i', $domain)) { + if ($idn && $domain && preg_match('/(^|\.)xn--/i', $domain)) { try { $domain = $idn->decode($domain); } diff --git a/program/include/rcube_smtp.php b/program/include/rcube_smtp.php index 5d1d459e9..81f212dcf 100644 --- a/program/include/rcube_smtp.php +++ b/program/include/rcube_smtp.php @@ -101,7 +101,7 @@ class rcube_smtp $helo_host = 'localhost'; // IDNA Support - $smtp_host = idn_to_ascii($smtp_host); + $smtp_host = rcube_idn_to_ascii($smtp_host); $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); @@ -132,8 +132,9 @@ class rcube_smtp if ($smtp_user && $smtp_pass) { // IDNA Support - if (strpos($smtp_user, '@')) - $smtp_user = idn_to_ascii($smtp_user); + if (strpos($smtp_user, '@')) { + $smtp_user = rcube_idn_to_ascii($smtp_user); + } $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls, $smtp_authz); diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php index 5433dc202..5806d5185 100755 --- a/program/include/rcube_template.php +++ b/program/include/rcube_template.php @@ -1031,7 +1031,7 @@ class rcube_template extends rcube_html_page $username = $this->app->user->get_username(); } - return idn_to_utf8($username); + return rcube_idn_to_utf8($username); } diff --git a/program/js/common.js b/program/js/common.js index 76ddd7269..5c9102771 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -493,11 +493,27 @@ function rcube_check_email(input, inline) // 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+')', - domain = '([^@\\x2e]+\\x2e)+[a-z]{2,}', + // allow punycode in last domain part for ICANN test domains + domain = '([^@\\x2e]+\\x2e)+([a-z]{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', + '\\u4f8b\\u5b50\\x2e\\u6d4b\\u8bd5', + '\\u4f8b\\u5b50\\x2e\\u6e2c\\u8a66', + '\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3\\u03bc\\u03b1\\x2e\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae', + '\\u0909\\u0926\\u093e\\u0939\\u0930\\u0923\\x2e\\u092a\\u0930\\u0940\\u0915\\u094d\\u0937\\u093e', + '\\u4f8b\\u3048\\x2e\\u30c6\\u30b9\\u30c8', + '\\uc2e4\\ub840\\x2e\\ud14c\\uc2a4\\ud2b8', + '\\u0645\\u062b\\u0627\\u0644\\x2e\\u0622\\u0632\\u0645\\u0627\\u06cc\\u0634\u06cc', + '\\u043f\\u0440\\u0438\\u043c\\u0435\\u0440\\x2e\\u0438\\u0441\\u043f\\u044b\\u0442\\u0430\\u043d\\u0438\\u0435', + '\\u0b89\\u0ba4\\u0bbe\\u0bb0\\u0ba3\\u0bae\\u0bcd\\x2e\\u0baa\\u0bb0\\u0bbf\\u0b9f\\u0bcd\\u0b9a\\u0bc8', + '\\u05d1\\u05f2\\u05b7\\u05e9\\u05e4\\u05bc\\u05d9\\u05dc\\x2e\\u05d8\\u05e2\\u05e1\\u05d8' + ], + icann_addr = 'mailtest\\x40('+icann_domains.join('|')+')', word = '('+atom+'|'+quoted_string+')', delim = '[,;\s\n]', local_part = word+'(\\x2e'+word+')*', - addr_spec = local_part+'\\x40'+domain, + addr_spec = '(('+local_part+'\\x40'+domain+')|('+icann_addr+'))', reg1 = inline ? new RegExp('(^|<|'+delim+')'+addr_spec+'($|>|'+delim+')', 'i') : new RegExp('^'+addr_spec+'$', 'i'); return reg1.test(input) ? true : false; diff --git a/program/lib/washtml.php b/program/lib/washtml.php index 7f49fec28..f9daadbf5 100644 --- a/program/lib/washtml.php +++ b/program/lib/washtml.php @@ -75,6 +75,7 @@ * - changed $ignore_elements behaviour * - added RFC2397 support * - base URL support + * - invalid HTML comments removal before parsing */ class washtml @@ -271,6 +272,9 @@ class washtml else $this->config['base_url'] = ''; + // Remove invalid HTML comments (#1487759) + $html = preg_replace('/]*>/', '', $html); + @$node->loadHTML($html); return $this->dumpHtml($node); } diff --git a/program/localization/de_DE/labels.inc b/program/localization/de_DE/labels.inc index c88508cfd..517d27c4c 100644 --- a/program/localization/de_DE/labels.inc +++ b/program/localization/de_DE/labels.inc @@ -197,7 +197,7 @@ $labels['addcc'] = 'Cc hinzufügen'; $labels['addbcc'] = 'Bcc hinzufügen'; $labels['addreplyto'] = 'Antwortadresse hinzufügen'; $labels['addfollowupto'] = 'Followup-To hinzufügen'; -$labels['mdnrequest'] = 'Der Sender dieser Nachricht möchte gerne eine Lesebestätigung. Wollen Sie dieses bestätigen?'; +$labels['mdnrequest'] = 'Der Sender dieser Nachricht möchte gerne eine Empfangsbestätigung. Wollen Sie dieses bestätigen?'; $labels['receiptread'] = 'Empfangsbestätigung (gelesen)'; $labels['yourmessage'] = 'Dies ist eine Empfangsbestätigung für Ihre Nachricht'; $labels['receiptnote'] = 'Hinweis: Der Empfänger hat den Empfang der Nachricht bestätigt. Dies ist keine Garantie, dass die Nachricht gelesen und verstanden wurde.'; @@ -297,8 +297,8 @@ $labels['serversettings'] = 'Server-Einstellungen'; $labels['mailboxview'] = 'Mailbox-Ansicht'; $labels['mdnrequests'] = 'Empfangsbestätigung senden'; $labels['askuser'] = 'immer fragen'; -$labels['autosend'] = 'Lesebestätigung automatisch senden'; -$labels['autosendknown'] = 'Lesebestätigung nur an meine Kontakte senden'; +$labels['autosend'] = 'automatisch senden'; +$labels['autosendknown'] = 'nur an meine Kontakte senden'; $labels['autosendknownignore'] = 'für bekannte Absender, sonst ignorieren'; $labels['ignore'] = 'ignorieren'; $labels['readwhendeleted'] = 'Beim Löschen als gelesen markieren'; diff --git a/program/steps/addressbook/import.inc b/program/steps/addressbook/import.inc index ceb683227..7f979de82 100644 --- a/program/steps/addressbook/import.inc +++ b/program/steps/addressbook/import.inc @@ -136,7 +136,7 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name' } // We're using UTF8 internally - $email = idn_to_utf8($email); + $email = rcube_idn_to_utf8($email); if (!$replace) { // compare e-mail address diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 1c70b89b6..c3a3a69e9 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -49,8 +49,8 @@ foreach ($a_save_cols as $col) { } // Validity checks -$_email = idn_to_ascii($a_record['email']); -if (!check_email($_email, false)) { +$_email = rcube_idn_to_ascii($a_record['email']); +if (!check_email($_email)) { $OUTPUT->show_message('emailformaterror', 'warning', array('email' => $_email)); rcmail_overwrite_action($return_action); return; diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc index 613a63e39..21fbc2db2 100644 --- a/program/steps/mail/addcontact.inc +++ b/program/steps/mail/addcontact.inc @@ -46,7 +46,7 @@ if (!empty($_POST['_address']) && is_object($CONTACTS)) $OUTPUT->send(); } - $contact['email'] = idn_to_utf8($contact['email']); + $contact['email'] = rcube_idn_to_utf8($contact['email']); // use email address part for name if (empty($contact['name']) || $contact['name'] == $contact['email']) diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 45b95c937..eb42b2abe 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -321,7 +321,7 @@ function rcmail_compose_headers($attrib) if (empty($addr_part['mailto'])) continue; - $mailto = idn_to_utf8($addr_part['mailto']); + $mailto = rcube_idn_to_utf8($addr_part['mailto']); if (!in_array($mailto, $sa_recipients) && (!$MESSAGE->compose_from @@ -360,7 +360,7 @@ function rcmail_compose_headers($attrib) if (empty($addr_part['mailto'])) continue; - $mailto = idn_to_utf8($addr_part['mailto']); + $mailto = rcube_idn_to_utf8($addr_part['mailto']); if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) $string = format_email_recipient($mailto, $addr_part['name']); @@ -437,7 +437,7 @@ function rcmail_compose_header_from($attrib) // create SELECT element foreach ($user_identities as $sql_arr) { - $email = mb_strtolower(idn_to_utf8($sql_arr['email'])); + $email = mb_strtolower(rcube_idn_to_utf8($sql_arr['email'])); $identity_id = $sql_arr['identity_id']; $select_from->add(format_email_recipient($email, $sql_arr['name']), $identity_id); @@ -732,9 +732,9 @@ function rcmail_create_reply_body($body, $bodyIsHtml) global $RCMAIL, $MESSAGE, $LINE_LENGTH; // build reply prefix - $from = array_pop($RCMAIL->imap->decode_address_list($MESSAGE->get_header('from'))); + $from = array_pop($RCMAIL->imap->decode_address_list($MESSAGE->get_header('from'), 1, false)); $prefix = sprintf("On %s, %s wrote:", - $MESSAGE->headers->date, $from['name'] ? $from['name'] : idn_to_utf8($from['mailto'])); + $MESSAGE->headers->date, $from['name'] ? $from['name'] : rcube_idn_to_utf8($from['mailto'])); if (!$bodyIsHtml) { $body = preg_replace('/\r?\n/', "\n", $body); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index b62e8a86c..a4eb13175 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -56,9 +56,9 @@ if (!empty($_GET['_page'])) // set default sort col/order to session if (!isset($_SESSION['sort_col'])) - $_SESSION['sort_col'] = $CONFIG['message_sort_col']; + $_SESSION['sort_col'] = !empty($CONFIG['message_sort_col']) ? $CONFIG['message_sort_col'] : ''; if (!isset($_SESSION['sort_order'])) - $_SESSION['sort_order'] = $CONFIG['message_sort_order']; + $_SESSION['sort_order'] = strtoupper($CONFIG['message_sort_order']) == 'ASC' ? 'ASC' : 'DESC'; // set threads mode $a_threading = $RCMAIL->config->get('message_threading', array()); @@ -1194,15 +1194,16 @@ function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null */ function rcmail_alter_html_link($matches) { - global $EMAIL_ADDRESS_PATTERN; + global $RCMAIL, $EMAIL_ADDRESS_PATTERN; $tag = $matches[1]; $attrib = parse_attrib_string($matches[2]); $end = '>'; if ($tag == 'link' && preg_match('/^https?:\/\//i', $attrib['href'])) { - $attrib['href'] = "?_task=utils&_action=modcss&u=" . urlencode($attrib['href']) - . "&c=" . urlencode($GLOBALS['rcmail_html_container_id']); + $tempurl = 'tmp-' . md5($attrib['href']) . '.css'; + $_SESSION['modcssurls'][$tempurl] = $attrib['href']; + $attrib['href'] = $RCMAIL->url(array('task' => 'utils', 'action' => 'modcss', 'u' => $tempurl, 'c' => $GLOBALS['rcmail_html_container_id'])); $end = ' />'; } else if (preg_match('/^mailto:'.$EMAIL_ADDRESS_PATTERN.'(\?[^"\'>]+)?/i', $attrib['href'], $mailto)) { @@ -1250,10 +1251,10 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null) // IDNA ASCII to Unicode if ($name == $mailto) - $name = idn_to_utf8($name); + $name = rcube_idn_to_utf8($name); if ($string == $mailto) - $string = idn_to_utf8($string); - $mailto = idn_to_utf8($mailto); + $string = rcube_idn_to_utf8($string); + $mailto = rcube_idn_to_utf8($mailto); if ($PRINT_MODE) { $out .= sprintf('%s <%s>', Q($name), $mailto); diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 770660c1d..ecc7f3369 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -153,11 +153,11 @@ function rcmail_email_input_format($mailto, $count=false, $check=true) $item = trim($item); // address in brackets without name (do nothing) if (preg_match('/^<\S+@\S+>$/', $item)) { - $item = idn_to_ascii($item); + $item = rcube_idn_to_ascii($item); $result[] = $item; // address without brackets and without name (add brackets) } else if (preg_match('/^\S+@\S+$/', $item)) { - $item = idn_to_ascii($item); + $item = rcube_idn_to_ascii($item); $result[] = '<'.$item.'>'; // address with name (handle name) } else if (preg_match('/\S+@\S+>*$/', $item, $matches)) { @@ -168,7 +168,7 @@ function rcmail_email_input_format($mailto, $count=false, $check=true) && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) { $name = '"'.addcslashes($name, '"').'"'; } - $address = idn_to_ascii($address); + $address = rcube_idn_to_ascii($address); if (!preg_match('/^<\S+@\S+>$/', $address)) $address = '<'.$address.'>'; diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc index f458cbfee..a78ebc94f 100644 --- a/program/steps/settings/edit_identity.inc +++ b/program/steps/settings/edit_identity.inc @@ -94,9 +94,9 @@ function rcube_identity_form($attrib) $form['addressing']['content']['email']['class'] = 'disabled'; } - $IDENTITY_RECORD['email'] = idn_to_utf8($IDENTITY_RECORD['email']); - $IDENTITY_RECORD['reply-to'] = idn_to_utf8($IDENTITY_RECORD['reply-to']); - $IDENTITY_RECORD['bcc'] = idn_to_utf8($IDENTITY_RECORD['bcc']); + $IDENTITY_RECORD['email'] = rcube_idn_to_utf8($IDENTITY_RECORD['email']); + $IDENTITY_RECORD['reply-to'] = rcube_idn_to_utf8($IDENTITY_RECORD['reply-to']); + $IDENTITY_RECORD['bcc'] = rcube_idn_to_utf8($IDENTITY_RECORD['bcc']); // Allow plugins to modify identity form content $plugin = $RCMAIL->plugins->exec_hook('identity_form', array( diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 3a3d690bf..7ddfac43e 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -72,7 +72,7 @@ function rcmail_identities_list($attrib) // get identities list and define 'mail' column $list = $USER->list_identities(); foreach ($list as $idx => $row) - $list[$idx]['mail'] = trim($row['name'] . ' <' . idn_to_utf8($row['email']) .'>'); + $list[$idx]['mail'] = trim($row['name'] . ' <' . rcube_idn_to_utf8($row['email']) .'>'); // get all identites from DB and define list of cols to be displayed $plugin = $RCMAIL->plugins->exec_hook('identities_list', array( diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc index 30cc12495..c8d258fd7 100644 --- a/program/steps/settings/save_identity.inc +++ b/program/steps/settings/save_identity.inc @@ -59,8 +59,8 @@ if (IDENTITIES_LEVEL == 1 || IDENTITIES_LEVEL == 3) // Validate e-mail addresses foreach (array('email', 'reply-to', 'bcc') as $item) { if ($email = $save_data[$item]) { - $ascii_email = idn_to_ascii($email); - if (!check_email($ascii_email, false)) { + $ascii_email = rcube_idn_to_ascii($email); + if (!check_email($ascii_email)) { // show error message $OUTPUT->show_message('emailformaterror', 'error', array('email' => $email), false); rcmail_overwrite_action('edit-identity'); @@ -77,11 +77,11 @@ if ($_POST['_iid']) $save_data = $plugin['record']; if ($save_data['email']) - $save_data['email'] = idn_to_ascii($save_data['email']); + $save_data['email'] = rcube_idn_to_ascii($save_data['email']); if ($save_data['bcc']) - $save_data['bcc'] = idn_to_ascii($save_data['bcc']); + $save_data['bcc'] = rcube_idn_to_ascii($save_data['bcc']); if ($save_data['reply-to']) - $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']); + $save_data['reply-to'] = rcube_idn_to_ascii($save_data['reply-to']); if (!$plugin['abort']) $updated = $USER->update_identity($iid, $save_data); @@ -116,9 +116,9 @@ else if (IDENTITIES_LEVEL < 2) $plugin = $RCMAIL->plugins->exec_hook('identity_create', array('record' => $save_data)); $save_data = $plugin['record']; - $save_data['email'] = idn_to_ascii($save_data['email']); - $save_data['bcc'] = idn_to_ascii($save_data['bcc']); - $save_data['reply-to'] = idn_to_ascii($save_data['reply-to']); + $save_data['email'] = rcube_idn_to_ascii($save_data['email']); + $save_data['bcc'] = rcube_idn_to_ascii($save_data['bcc']); + $save_data['reply-to'] = rcube_idn_to_ascii($save_data['reply-to']); if (!$plugin['abort']) $insert_id = $save_data['email'] ? $USER->insert_identity($save_data) : null; diff --git a/program/steps/utils/error.inc b/program/steps/utils/error.inc index c472faa3e..4f4d6cbe7 100644 --- a/program/steps/utils/error.inc +++ b/program/steps/utils/error.inc @@ -47,6 +47,13 @@ else if ($ERROR_CODE==401) { "Please contact your server-administrator."; } +// forbidden due to request check +else if ($ERROR_CODE==403) { + $__error_title = "REQUEST CHECK FAILED"; + $__error_text = "Access to this service was denied due to failing security checks!
\n". + "Please contact your server-administrator."; +} + // failed request (wrong step in URL) else if ($ERROR_CODE==404) { $__error_title = "REQUEST FAILED/FILE NOT FOUND"; diff --git a/program/steps/utils/modcss.inc b/program/steps/utils/modcss.inc index 781779526..5572c9a21 100644 --- a/program/steps/utils/modcss.inc +++ b/program/steps/utils/modcss.inc @@ -5,7 +5,7 @@ | program/steps/utils/modcss.inc | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2007-2010, Roundcube Dev. - Switzerland | + | Copyright (C) 2007-2011, Roundcube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -21,14 +21,14 @@ $source = ''; -$url = preg_replace('![^a-z0-9:./\-_?$&=%]!i', '', $_GET['u']); -if ($url === null) { +$url = preg_replace('![^a-z0-9.-]!i', '', $_GET['_u']); +if ($url === null || !($realurl = $_SESSION['modcssurls'][$url])) { header('HTTP/1.1 403 Forbidden'); - echo $error; + echo "Unauthorized request"; exit; } -$a_uri = parse_url($url); +$a_uri = parse_url($realurl); $port = $a_uri['port'] ? $a_uri['port'] : 80; $host = $a_uri['host']; $path = $a_uri['path'] . ($a_uri['query'] ? '?'.$a_uri['query'] : ''); @@ -85,7 +85,7 @@ fclose($fp); $mimetype = strtolower($headers['content-type']); if (!empty($source) && in_array($mimetype, array('text/css','text/plain'))) { header('Content-Type: text/css'); - echo rcmail_mod_css_styles($source, preg_replace('/[^a-z0-9]/i', '', $_GET['c'])); + echo rcmail_mod_css_styles($source, preg_replace('/[^a-z0-9]/i', '', $_GET['_c'])); exit; } else diff --git a/skins/default/common.css b/skins/default/common.css index 4a45c60b7..2257ad4ec 100644 --- a/skins/default/common.css +++ b/skins/default/common.css @@ -9,7 +9,7 @@ body body.iframe { - margin: 0px; + margin: 20px 0 0 0; background-color: #FFF; } @@ -254,6 +254,14 @@ img float: right; } +body.iframe .boxtitle +{ + position: fixed; + top: 0; + left: 0; + width: 100%; +} + .boxcontent { padding: 15px 10px 10px 10px; diff --git a/skins/default/functions.js b/skins/default/functions.js index 00e97fd1a..3e06a54d4 100644 --- a/skins/default/functions.js +++ b/skins/default/functions.js @@ -49,7 +49,7 @@ function rcube_init_tabs(id, current) // create a tab a = $('').text(legend.text()).attr('href', '#'); tab = $('').attr({'id': 'tab'+idx, 'class': 'tablink'}) - .click(function() { return rcube_show_tab(id, idx); }) + .click(function() { rcube_show_tab(id, idx); return false }) // remove legend legend.remove(); diff --git a/skins/default/mail.css b/skins/default/mail.css index b5dfb80d0..b5630e342 100644 --- a/skins/default/mail.css +++ b/skins/default/mail.css @@ -1002,7 +1002,7 @@ td span.branch div.l3 div.messageheaderbox { - margin: 6px 8px 0px 8px; + margin: -14px 8px 0px 8px; border: 1px solid #ccc; } -- cgit v1.2.3