From 719a257f0c8fd750a4984ed56273dc653565729e Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Fri, 10 Aug 2007 04:27:40 -0400
Subject: [PATCH] Some bugfixes, security issues + minor improvements

---
 CHANGELOG                                 |   10 +++++
 index.php                                 |   15 ++++++-
 program/include/rcmail_template.inc       |    4 +-
 program/include/main.inc                  |    3 +
 program/steps/mail/func.inc               |   28 ++++++++------
 program/steps/mail/show.inc               |    2 
 program/steps/mail/get.inc                |    4 +-
 program/steps/settings/manage_folders.inc |    4 +-
 program/js/app.js                         |   10 +++--
 program/include/rcube_imap.inc            |   23 ++++-------
 10 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 786be4e..1c1810b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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 @@
 - 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
diff --git a/index.php b/index.php
index 9908cf2..6e8b7ff 100644
--- a/index.php
+++ b/index.php
@@ -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 @@
 }
 
 
+// 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 aa1de97..4b8aa68 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -234,6 +234,9 @@
   // 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 d158a01..6057f2a 100644
--- a/program/include/rcmail_template.inc
+++ b/program/include/rcmail_template.inc
@@ -745,8 +745,8 @@
   $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 0cfda15..eddbad9 100644
--- a/program/include/rcube_imap.inc
+++ b/program/include/rcube_imap.inc
@@ -1374,7 +1374,7 @@
     // 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 @@
     $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 @@
     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 @@
         $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 bda6700..6cf9d48 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -463,7 +463,7 @@
         break;
 
       case 'logout':
-        this.goto_url('logout');
+        this.goto_url('logout', true);
         break;      
 
       // commands to switch task
@@ -3195,7 +3195,7 @@
 
   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 @@
       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 @@
     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 8c5f987..7306062 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -646,6 +646,7 @@
     
     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 @@
         $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 @@
       $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 @@
   $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 @@
   $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 11688f1..cbf8e0c 100644
--- a/program/steps/mail/get.inc
+++ b/program/steps/mail/get.inc
@@ -29,7 +29,7 @@
   $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
       {
       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 6c247ae..e25da03 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -48,7 +48,7 @@
   // 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 150b7cd..b08d9cc 100644
--- a/program/steps/settings/manage_folders.inc
+++ b/program/steps/settings/manage_folders.inc
@@ -27,7 +27,7 @@
 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 @@
 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');

--
Gitblit v1.9.1