Auto merge of #7836 - 6112:master, r=mbrubeck

interpret empty data URI as plain text

Fixes #7803. As @eefriedman pointed out, RFC 2397 says:

> If <mediatype> is omitted, it defaults to text/plain;charset=US-ASCII.  As a shorthand, "text/plain" can be omitted but the charset parameter supplied.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7836)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-10-03 12:23:57 -06:00
commit f30f40b12d
2 changed files with 33 additions and 6 deletions

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use hyper::mime::Mime; use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use mime_classifier::MIMEClassifier; use mime_classifier::MIMEClassifier;
use net_traits::ProgressMsg::{Done, Payload}; use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata}; use net_traits::{LoadConsumer, LoadData, Metadata};
@ -48,15 +48,23 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) {
// ";base64" must come at the end of the content type, per RFC 2397. // ";base64" must come at the end of the content type, per RFC 2397.
// rust-http will fail to parse it because there's no =value part. // rust-http will fail to parse it because there's no =value part.
let mut is_base64 = false; let mut is_base64 = false;
let mut ct_str = parts[0]; let mut ct_str = parts[0].to_owned();
if ct_str.ends_with(";base64") { if ct_str.ends_with(";base64") {
is_base64 = true; is_base64 = true;
ct_str = &ct_str[..ct_str.as_bytes().len() - 7]; let end_index = ct_str.len() - 7;
ct_str.truncate(end_index);
}
if ct_str.starts_with(";charset=") {
ct_str = format!("text/plain{}", ct_str);
} }
// Parse the content type using rust-http. // Parse the content type using rust-http.
// FIXME: this can go into an infinite loop! (rust-http #25) // FIXME: this can go into an infinite loop! (rust-http #25)
let content_type: Option<Mime> = ct_str.parse().ok(); let mut content_type: Option<Mime> = ct_str.parse().ok();
if content_type == None {
content_type = Some(Mime(TopLevel::Text, SubLevel::Plain,
vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))));
}
metadata.set_content_type(content_type.as_ref()); metadata.set_content_type(content_type.as_ref());
let progress_chan = start_sending(start_chan, metadata); let progress_chan = start_sending(start_chan, metadata);

View file

@ -47,7 +47,11 @@ fn empty_invalid() {
#[test] #[test]
fn plain() { fn plain() {
assert_parse("data:,hello%20world", None, None, Some(b"hello world".iter().map(|&x| x).collect())); assert_parse(
"data:,hello%20world",
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain,
vec!((Attr::Charset, Value::Ext("us-ascii".to_owned())))))),
Some("US-ASCII".to_owned()), Some(b"hello world".iter().map(|&x| x).collect()));
} }
#[test] #[test]
@ -68,9 +72,24 @@ fn plain_charset() {
Some("latin1".to_string()), Some(b"hello".iter().map(|&x| x).collect())); Some("latin1".to_string()), Some(b"hello".iter().map(|&x| x).collect()));
} }
#[test]
fn plain_only_charset() {
assert_parse(
"data:;charset=utf-8,hello",
Some(ContentType(Mime(TopLevel::Text,
SubLevel::Plain,
vec!((Attr::Charset, Value::Utf8))))),
Some("utf-8".to_string()), Some(b"hello".iter().map(|&x| x).collect()));
}
#[test] #[test]
fn base64() { fn base64() {
assert_parse("data:;base64,C62+7w==", None, None, Some(vec!(0x0B, 0xAD, 0xBE, 0xEF))); assert_parse(
"data:;base64,C62+7w==",
Some(ContentType(Mime(TopLevel::Text,
SubLevel::Plain,
vec!((Attr::Charset, Value::Ext("us-ascii".to_owned())))))),
Some("US-ASCII".to_owned()), Some(vec!(0x0B, 0xAD, 0xBE, 0xEF)));
} }
#[test] #[test]