diff options
-rw-r--r-- | CHANGELOG | 10 | ||||
-rw-r--r-- | index.php | 15 | ||||
-rw-r--r-- | program/include/main.inc | 3 | ||||
-rw-r--r-- | program/include/rcmail_template.inc | 4 | ||||
-rw-r--r-- | program/include/rcube_imap.inc | 23 | ||||
-rw-r--r-- | program/js/app.js | 10 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 28 | ||||
-rw-r--r-- | program/steps/mail/get.inc | 4 | ||||
-rw-r--r-- | program/steps/mail/show.inc | 2 | ||||
-rw-r--r-- | program/steps/settings/manage_folders.inc | 4 |
10 files changed, 63 insertions, 40 deletions
@@ -1,6 +1,15 @@ CHANGELOG RoundCube Webmail --------------------------- +2007/08/09 (thomasb) +---------- +- Identify mailboxes case-sensitive +- Sort mailbox list case-insensitive (closes #1484338) +- Fix display of multipart messages from Apple Mail (closes #1484027) +- Protect AJAX request from being fetched by a foreign site (XSS) +- Make autocomplete for loginform configurable by the skin template + + 2007/07/09 (richs) ---------- - Fixed bug with buttons not dimming/enabling properly after switching folders @@ -13,6 +22,7 @@ CHANGELOG RoundCube Webmail - Increased "mailboxcontrols" mail.css width from 160 to 170px to fix non-english languages - Fixed empty-message sending with TinyMCE plain-text mode, or if it's not installed + 2007/07/03 (thomasb) ---------- - Added Macedonian (Slavic FYROM) localization @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ | RoundCube Webmail IMAP Client | - | Version 0.1-20070518 | + | Version 0.1-20070809 | | | | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | @@ -41,7 +41,7 @@ */ // application constants -define('RCMAIL_VERSION', '0.1-20070517'); +define('RCMAIL_VERSION', '0.1-20070809'); define('RCMAIL_CHARSET', 'UTF-8'); define('JS_OBJECT_NAME', 'rcmail'); @@ -218,6 +218,17 @@ if (empty($_SESSION['user_id'])) } +// check client X-header to verify request origin +if ($OUTPUT->ajax_call) +{ + $hdrs = getallheaders(); + if (empty($hdrs['X-RoundCube-Referer']) && empty($CONFIG['devel_mode'])) + { + header('HTTP/1.1 404 Not Found'); + die("Invalid Request"); + } +} + // set task and action to client $OUTPUT->set_env('task', $_task); diff --git a/program/include/main.inc b/program/include/main.inc index aa1de9754..4b8aa68d5 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -234,6 +234,9 @@ function rcmail_authenticate_session() // check session filetime if (!empty($CONFIG['session_lifetime']) && isset($SESS_CHANGED) && $SESS_CHANGED + $CONFIG['session_lifetime']*60 < time()) $valid = false; + + if (!$valid) + write_log('timeouts', $_SESSION + array('SESS_CLIENT_IP' => $SESS_CLIENT_IP, 'SESS_CHANGED' => $SESS_CHANGED, 'COOKIE' => $_COOKIE)); return $valid; } diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc index d158a019c..6057f2af3 100644 --- a/program/include/rcmail_template.inc +++ b/program/include/rcmail_template.inc @@ -745,8 +745,8 @@ function rcmail_login_form($attrib) $labels['pass'] = rcube_label('password'); $labels['host'] = rcube_label('server'); - $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off')); - $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30)); + $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib); + $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30) + $attrib); $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login')); $fields = array(); diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index 0cfda1573..eddbad91b 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -1374,7 +1374,7 @@ class rcube_imap // make sure mailbox exists if (!in_array($to_mbox, $this->_list_mailboxes())) { - if (in_array(strtolower($to_mbox), $this->default_folders)) + if (in_array($to_mbox, $this->default_folders)) $this->create_mailbox($to_mbox, TRUE); else return FALSE; @@ -1658,11 +1658,11 @@ class rcube_imap $abs_name = $this->_mod_mailbox($name); $a_mailbox_cache = $this->get_cache('mailboxes'); - if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array_nocase($abs_name, $a_mailbox_cache))) + if (strlen($abs_name) && (!is_array($a_mailbox_cache) || !in_array($abs_name, $a_mailbox_cache))) $result = iil_C_CreateFolder($this->conn, $abs_name); // try to subscribe it - if ($subscribe) + if ($result && $subscribe) $this->subscribe($name); return $result ? $name : FALSE; @@ -1768,17 +1768,10 @@ class rcube_imap foreach ($this->default_folders as $folder) { $abs_name = $this->_mod_mailbox($folder); - if (!in_array_nocase($abs_name, $a_subscribed)) - { - if (!in_array_nocase($abs_name, $a_folders)) - $this->create_mailbox($folder, TRUE); - else - $this->subscribe($folder); - } - else if (!in_array_nocase($abs_name, $a_folders)) - { - $this->create_mailbox($folder, FALSE); - } + if (!in_array_nocase($abs_name, $a_folders)) + $this->create_mailbox($folder, TRUE); + else if (!in_array_nocase($abs_name, $a_subscribed)) + $this->subscribe($folder); } } @@ -2433,7 +2426,7 @@ class rcube_imap $a_out[] = $folder; } - sort($a_out); + natcasesort($a_out); ksort($a_defaults); return array_merge($a_defaults, $a_out); diff --git a/program/js/app.js b/program/js/app.js index bda67002e..6cf9d4850 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -463,7 +463,7 @@ function rcube_webmail() break; case 'logout': - this.goto_url('logout'); + this.goto_url('logout', true); break; // commands to switch task @@ -3195,7 +3195,7 @@ function rcube_webmail() this.redirect = function(url, lock) { - if (lock || lock == NULL) + if (lock || lock === null) this.set_busy(true); if (this.env.framed && window.parent) @@ -3498,12 +3498,13 @@ function rcube_http_request() return false; } - var ref = this; + var _ref = this; this.url = url; this.busy = true; - this.xmlhttp.onreadystatechange = function(){ ref.xmlhttp_onreadystatechange(); }; + this.xmlhttp.onreadystatechange = function(){ _ref.xmlhttp_onreadystatechange(); }; this.xmlhttp.open('GET', url); + this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('sessid')); this.xmlhttp.send(null); }; @@ -3537,6 +3538,7 @@ function rcube_http_request() this.xmlhttp.onreadystatechange = function() { ref.xmlhttp_onreadystatechange(); }; this.xmlhttp.open('POST', url, true); this.xmlhttp.setRequestHeader('Content-Type', contentType); + this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('sessid')); this.xmlhttp.send(req_body); }; diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 8c5f987c3..730606265 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -646,6 +646,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE) foreach ($structure->parts as $p => $sub_part) { + $rel_parts = $attachmnts = null; $sub_ctype_primary = strtolower($sub_part->ctype_primary); $sub_ctype_secondary = strtolower($sub_part->ctype_secondary); @@ -656,19 +657,22 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE) $html_part = $p; else if ($sub_ctype_primary=='text' && $sub_ctype_secondary=='enriched') $enriched_part = $p; - else if ($sub_ctype_primary=='multipart' && $sub_ctype_secondary=='related') + else if ($sub_ctype_primary=='multipart' && ($sub_ctype_secondary=='related' || $sub_ctype_secondary=='mixed')) $related_part = $p; } - + // parse related part (alternative part could be in here) - if ($related_part!==NULL && $prefer_html) - { - list($parts, $attachmnts) = rcmail_parse_message($structure->parts[$related_part], $arg, TRUE); - $a_return_parts = array_merge($a_return_parts, $parts); + if ($related_part!==NULL) + { + list($rel_parts, $attachmnts) = rcmail_parse_message($structure->parts[$related_part], $arg, TRUE); $a_attachments = array_merge($a_attachments, $attachmnts); - } + } + + // merge related parts if any + if ($rel_parts && $prefer_html && !$html_part) + $a_return_parts = array_merge($a_return_parts, $rel_parts); - // print html/plain part + // choose html/plain part to print else if ($html_part!==NULL && $prefer_html) $print_part = &$structure->parts[$html_part]; else if ($enriched_part!==NULL) @@ -683,7 +687,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE) $a_return_parts[] = $print_part; } // show plaintext warning - else if ($html_part!==NULL) + else if ($html_part!==NULL && empty($a_return_parts)) { $c = new stdClass; $c->type = 'content'; @@ -913,8 +917,8 @@ function rcmail_message_body($attrib) $ctype_secondary = strtolower($MESSAGE['structure']->ctype_secondary); // list images after mail body - if (get_boolean($attrib['showimages']) && $ctype_primary=='multipart' && $ctype_secondary=='mixed' && - sizeof($MESSAGE['attachments']) && !strstr($message_body, '<html') && strlen($GET_URL)) + if (get_boolean($attrib['showimages']) && $ctype_primary=='multipart' && + !empty($MESSAGE['attachments']) && !strstr($message_body, '<html') && strlen($GET_URL)) { foreach ($MESSAGE['attachments'] as $attach_prop) { @@ -1239,7 +1243,7 @@ function rcmail_message_part_frame($attrib) $part = $MESSAGE['parts'][$_GET['_part']]; $ctype_primary = strtolower($part->ctype_primary); - $attrib['src'] = './?'.str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING']); + $attrib['src'] = Q('./?'.str_replace('_frame=', ($ctype_primary=='text' ? '_show=' : '_preload='), $_SERVER['QUERY_STRING'])); $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'src', 'width', 'height')); $out = '<iframe '. $attrib_str . "></iframe>"; diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 11688f125..cbf8e0c88 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -29,7 +29,7 @@ if ($_GET['_preload']) $message = rcube_label('loadingdata'); print "<html>\n<head>\n" . - '<meta http-equiv="refresh" content="0; url='.htmlspecialchars($url).'">' . + '<meta http-equiv="refresh" content="0; url='.Q($url).'">' . "\n</head>\n<body>" . $message . "\n</body>\n</html>"; @@ -107,7 +107,7 @@ else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) else { header(sprintf('Content-Disposition: %s; filename="%s";', - $part->disposition ? $part->disposition : 'attachment', + $_GET['_download'] ? 'attachment' : 'inline', $part->filename ? $part->filename : "roundcube.$ctype_secondary")); // turn off output buffering and print part content diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 6c247aea9..e25da03a6 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -48,7 +48,7 @@ if ($_GET['_uid']) // allow caching, unless remote images are present if ((bool)get_input_value('_safe', RCUBE_INPUT_GET)) send_nocacheing_headers(); - else + else if (empty($CONFIG['devel_mode'])) send_modified_header($_SESSION['login_time'], $etag); $MESSAGE['subject'] = rcube_imap::decode_mime_string($MESSAGE['headers']->subject, $MESSAGE['headers']->charset); diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc index 150b7cd72..b08d9ccc9 100644 --- a/program/steps/settings/manage_folders.inc +++ b/program/steps/settings/manage_folders.inc @@ -27,7 +27,7 @@ rcmail_imap_init(TRUE); if ($_action=='subscribe') { if ($mboxes = get_input_value('_mboxes', RCUBE_INPUT_POST)) - $IMAP->subscribe(array($mboxes)); + $IMAP->subscribe($mboxes); if ($OUTPUT->ajax_call) $OUTPUT->remote_response('// subscribed'); @@ -37,7 +37,7 @@ if ($_action=='subscribe') else if ($_action=='unsubscribe') { if ($mboxes = get_input_value('_mboxes', RCUBE_INPUT_POST)) - $IMAP->unsubscribe(array($mboxes)); + $IMAP->unsubscribe($mboxes); if ($OUTPUT->ajax_call) $OUTPUT->remote_response('// unsubscribed'); |