Bug 272541: Empty disposition type treated as 'attachment'. r=jduell
authorjulian.reschke@greenbytes.de
Mon, 12 Sep 2011 20:14:16 -0700
changeset 76874 ddb49b079701d0a44947b087eda139a2401a6c73
parent 76873 1a84481f69875da535508041e90041f06bd2deae
child 76875 091bdb10d01717a68c730b2625d3d02a443ce1bf
push id340
push userclegnitto@mozilla.com
push dateTue, 08 Nov 2011 22:56:33 +0000
treeherdermozilla-esr52@c0983049bcaa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs272541
milestone9.0a1
Bug 272541: Empty disposition type treated as 'attachment'. r=jduell
js/src/xpconnect/src/xpc.msg
netwerk/base/public/nsNetError.h
netwerk/base/public/nsNetUtil.h
netwerk/mime/nsMIMEHeaderParamImpl.cpp
netwerk/test/unit/test_bug272541.js
netwerk/test/unit/xpcshell.ini
--- a/js/src/xpconnect/src/xpc.msg
+++ b/js/src/xpconnect/src/xpc.msg
@@ -170,16 +170,17 @@ XPC_MSG_DEF(NS_BINDING_REDIRECTED       
 XPC_MSG_DEF(NS_BINDING_RETARGETED                   , "The async request has been retargeted to a different handler")
 XPC_MSG_DEF(NS_ERROR_MALFORMED_URI                  , "The URI is malformed")
 XPC_MSG_DEF(NS_ERROR_UNKNOWN_PROTOCOL               , "The URI scheme corresponds to an unknown protocol handler")
 XPC_MSG_DEF(NS_ERROR_NO_CONTENT                     , "Channel opened successfully but no data will be returned")
 XPC_MSG_DEF(NS_ERROR_IN_PROGRESS                    , "The requested action could not be completed while the object is busy")
 XPC_MSG_DEF(NS_ERROR_ALREADY_OPENED                 , "Channel is already open")
 XPC_MSG_DEF(NS_ERROR_INVALID_CONTENT_ENCODING       , "The content encoding of the source document is incorrect")
 XPC_MSG_DEF(NS_ERROR_CORRUPTED_CONTENT              , "Corrupted content was received from server")
+XPC_MSG_DEF(NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "Couldn't extract first component from potentially corrupted header field")
 XPC_MSG_DEF(NS_ERROR_ALREADY_CONNECTED              , "The connection is already established")
 XPC_MSG_DEF(NS_ERROR_NOT_CONNECTED                  , "The connection does not exist")
 XPC_MSG_DEF(NS_ERROR_CONNECTION_REFUSED             , "The connection was refused")
 XPC_MSG_DEF(NS_ERROR_PROXY_CONNECTION_REFUSED       , "The connection to the proxy server was refused")
 XPC_MSG_DEF(NS_ERROR_NET_TIMEOUT                    , "The connection has timed out")
 XPC_MSG_DEF(NS_ERROR_OFFLINE                        , "The requested action could not be completed in the offline state")
 XPC_MSG_DEF(NS_ERROR_PORT_ACCESS_NOT_ALLOWED        , "Establishing a connection to an unsafe or otherwise banned port was prohibited")
 XPC_MSG_DEF(NS_ERROR_NET_RESET                      , "The connection was established, but no data was ever received")
--- a/netwerk/base/public/nsNetError.h
+++ b/netwerk/base/public/nsNetError.h
@@ -147,16 +147,27 @@
 /**
  * A transport level corruption was found in the source document. for example
  * a document with a calculated checksum that does not match the Content-MD5
  * http header.
  */
 #define NS_ERROR_CORRUPTED_CONTENT \
     NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 29)
 
+/**
+ * While parsing for the first component of a header field using
+ * syntax as in Content-Disposition or Content-Type, the first component
+ * was found to be empty, such as in:
+ *
+ * Content-Disposition: ; filename=foo
+ */
+#define NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY \
+    NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 34)
+
+
 /******************************************************************************
  * Connectivity error codes:
  */
 
 /**
  * The connection is already established.
  * XXX currently unused - consider removing.
  */
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -1938,18 +1938,23 @@ NS_GetContentDispositionFromHeader(const
     aChan->GetURI(getter_AddRefs(uri));
     if (uri)
       uri->GetOriginCharset(fallbackCharset);
   }
 
   nsAutoString dispToken;
   rv = mimehdrpar->GetParameter(aHeader, "", fallbackCharset, PR_TRUE, nsnull,
                                 dispToken);
-  if (NS_FAILED(rv))
-    return nsIChannel::DISPOSITION_ATTACHMENT;
+
+  if (NS_FAILED(rv)) {
+    // special case (see bug 272541): empty disposition type handled as "inline"
+    return rv == NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY
+                 ? nsIChannel::DISPOSITION_INLINE
+                 : nsIChannel::DISPOSITION_ATTACHMENT;
+  }
 
   return NS_GetContentDispositionFromToken(dispToken);
 }
 
 /** Extracts the filename out of a content-disposition header
  * @param aFilename [out] The filename. Can be empty on error.
  * @param aDisposition Value of a Content-Disposition header
  * @param aURI Optional. Will be used to get a fallback charset for the
--- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp
+++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp
@@ -52,16 +52,17 @@
 #include "nsCOMPtr.h"
 #include "nsEscape.h"
 #include "nsIUTF8ConverterService.h"
 #include "nsUConvCID.h"
 #include "nsIServiceManager.h"
 #include "nsMIMEHeaderParamImpl.h"
 #include "nsReadableUtils.h"
 #include "nsNativeCharsetUtils.h"
+#include "nsNetError.h"
 
 // static functions declared below are moved from mailnews/mime/src/comi18n.cpp
   
 static char *DecodeQ(const char *, PRUint32);
 static PRBool Is7bitNonAsciiString(const char *, PRUint32);
 static void CopyRawHeader(const char *, PRUint32, const char *, nsACString &);
 static nsresult DecodeRFC2047Str(const char *, const char *, PRBool, nsACString&);
 
@@ -176,17 +177,18 @@ nsMIMEHeaderParamImpl::GetParameterInter
   // aParamName is empty. return the first (possibly) _unnamed_ 'parameter'
   // For instance, return 'inline' in the following case:
   // Content-Disposition: inline; filename=.....
   if (!aParamName || !*aParamName) 
     {
       for (; *str && *str != ';' && !nsCRT::IsAsciiSpace(*str); ++str)
         ;
       if (str == start)
-        return NS_ERROR_UNEXPECTED;
+        return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY;
+
       *aResult = (char *) nsMemory::Clone(start, (str - start) + 1);
       NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
       (*aResult)[str - start] = '\0';  // null-terminate
       return NS_OK;
     }
 
   /* Skip forward to first ';' */
   for (; *str && *str != ';' && *str != ','; ++str)
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug272541.js
@@ -0,0 +1,37 @@
+/**
+ * Test for bug 272541: - Empty disposition type treated as "attachment" 
+ */
+
+const Cr = Components.results
+
+var tests = [
+                 [ /* the actual bug */
+                  "; filename=foo.html", 
+                  Cr.NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY],
+                 [ /* regression check, but see bug 671204 */
+                  "filename=foo.html", 
+                  "filename=foo.html"],
+                 [ /* sanity check */
+                  "attachment; filename=foo.html", 
+                  "attachment"],
+                ];
+
+function run_test() {
+
+  var mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
+                      .getService(Components.interfaces.nsIMIMEHeaderParam);
+
+  var unused = { value : null };
+
+  for (var i = 0; i < tests.length; ++i) {
+    dump("Testing " + tests[i] + "\n");
+    try {
+      do_check_eq(mhp.getParameter(tests[i][0], "", "UTF-8", true, unused),
+                  tests[i][1]);
+    }
+    catch (e) {
+      do_check_eq(e.result, tests[i][1]);
+    }
+  }
+}
+
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -11,16 +11,17 @@ tail =
 # Bug 675039: test hangs consistently on Android
 skip-if = os == "android"
 [test_authpromptwrapper.js]
 [test_bug203271.js]
 [test_bug248970_cache.js]
 [test_bug248970_cookie.js]
 [test_bug261425.js]
 [test_bug263127.js]
+[test_bug272541.js]
 [test_bug321706.js]
 [test_bug331825.js]
 [test_bug336501.js]
 [test_bug337744.js]
 [test_bug365133.js]
 [test_bug368702.js]
 [test_bug369787.js]
 [test_bug371473.js]