Bug 781693 - Accept ';' as delimiter after 'base64' keyword. r=bz
authorjulian.reschke@gmx.de
Wed, 22 Aug 2012 06:57:02 -0400
changeset 105062 5f0e24568cbb5801171fd94807f526f195f7f0dd
parent 105061 8e4f89f8c4513069ca75bfb634d59b1b64c789b6
child 105063 d62929fa43251d582362225df3dcc9033b8c19be
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersbz
bugs781693
milestone17.0a1
Bug 781693 - Accept ';' as delimiter after 'base64' keyword. r=bz
netwerk/protocol/data/nsDataHandler.cpp
netwerk/test/unit/test_data_protocol.js
--- a/netwerk/protocol/data/nsDataHandler.cpp
+++ b/netwerk/protocol/data/nsDataHandler.cpp
@@ -158,19 +158,26 @@ nsDataHandler::ParseURI(nsCString& spec,
     char *comma = strchr(buffer, ',');
     if (!comma)
         return NS_ERROR_MALFORMED_URI;
 
     *comma = '\0';
 
     // determine if the data is base64 encoded.
     char *base64 = PL_strcasestr(buffer, BASE64_EXTENSION);
-    if (base64 && *(base64 + strlen(BASE64_EXTENSION))==0) {
-        isBase64 = true;
-        *base64 = '\0';
+    if (base64) {
+        char *beyond = base64 + strlen(BASE64_EXTENSION);
+        // per the RFC 2397 grammar, "base64" MUST be followed by a comma
+        // previously substituted by '\0', but we also allow it in between
+        // parameters so a subsequent ";" is ok as well (this deals with
+        // *broken* data URIs, see bug 781693 for an example)
+        if (*beyond == '\0' || *beyond == ';') {
+            isBase64 = true;
+            *base64 = '\0';
+        }
     }
 
     if (comma == buffer) {
         // nothing but data
         contentType.AssignLiteral("text/plain");
         contentCharset.AssignLiteral("US-ASCII");
     } else {
         // everything else is content type
--- a/netwerk/test/unit/test_data_protocol.js
+++ b/netwerk/test/unit/test_data_protocol.js
@@ -6,37 +6,40 @@ const Cr = Components.results;
 
 // The behaviour wrt spaces is:
 // - Textual content keeps all spaces
 // - Other content strips unescaped spaces
 // - Base64 content strips escaped and unescaped spaces
 var urls = [
   ["data:,foo",                                     "text/plain",               "foo"],
   ["data:application/octet-stream,foo bar",         "application/octet-stream", "foobar"],
-  ["data:application/octet-stream;base64=y,foobar",         "application/octet-stream", "foobar"],
   ["data:application/octet-stream,foo%20bar",       "application/octet-stream", "foo bar"],
   ["data:application/xhtml+xml,foo bar",            "application/xhtml+xml",    "foo bar"],
   ["data:application/xhtml+xml,foo%20bar",          "application/xhtml+xml",    "foo bar"],
   ["data:text/plain,foo%00 bar",                    "text/plain",               "foo\x00 bar"],
   ["data:text/plain;base64,Zm9 vI%20GJ%0Dhc%0Ag==", "text/plain",               "foo bar"],
-  ["DATA:TEXT/PLAIN;BASE64,Zm9 vI%20GJ%0Dhc%0Ag==", "text/plain",               "foo bar"]
+  ["DATA:TEXT/PLAIN;BASE64,Zm9 vI%20GJ%0Dhc%0Ag==", "text/plain",               "foo bar"],
+  // Bug 774240
+  ["data:application/octet-stream;base64=y,foobar", "application/octet-stream", "foobar"],
+  // Bug 781693
+  ["data:text/plain;base64;x=y,dGVzdA==",           "text/plain",               "test"]
 ];
 
 function run_test() {
   dump("*** run_test\n");
 
   function on_read_complete(request, data, idx) {
     dump("*** run_test.on_read_complete\n");
 
     if (request.nsIChannel.contentType != urls[idx][1])
       do_throw("Type mismatch! Is <" + chan.contentType + ">, should be <" + urls[idx][1] + ">");
 
     /* read completed successfully.  now compare the data. */
     if (data != urls[idx][2])
-      do_throw("Stream contents do not match with direct read!");
+      do_throw("Stream contents do not match with direct read! Is <" + data + ">, should be <" + urls[idx][2] + ">");
     do_test_finished();
   }
 
   var ios = Cc["@mozilla.org/network/io-service;1"].
             getService(Ci.nsIIOService);
   for (var i = 0; i < urls.length; ++i) {
     dump("*** opening channel " + i + "\n");
     do_test_pending();