servo/components/net/data_loader.rs
2019-01-25 14:02:56 +01:00

59 lines
1.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use base64;
use mime::Mime;
use servo_url::ServoUrl;
use url::percent_encoding::percent_decode;
use url::Position;
pub enum DecodeError {
InvalidDataUri,
NonBase64DataUri,
}
pub type DecodeData = (Mime, Vec<u8>);
pub fn decode(url: &ServoUrl) -> Result<DecodeData, DecodeError> {
assert_eq!(url.scheme(), "data");
// Split out content type and data.
let parts: Vec<&str> = url[Position::BeforePath..Position::AfterQuery]
.splitn(2, ',')
.collect();
if parts.len() != 2 {
return Err(DecodeError::InvalidDataUri);
}
// ";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.
let mut ct_str = parts[0];
let is_base64 = ct_str.ends_with(";base64");
if is_base64 {
ct_str = &ct_str[..ct_str.len() - ";base64".len()];
}
let ct_str = if ct_str.starts_with(";charset=") {
format!("text/plain{}", ct_str)
} else {
ct_str.to_owned()
};
let content_type = ct_str
.parse()
.unwrap_or_else(|_| "text/plain; charset=US-ASCII".parse().unwrap());
let mut bytes = percent_decode(parts[1].as_bytes()).collect::<Vec<_>>();
if is_base64 {
// FIXME(#2909): Its unclear what to do with non-alphabet characters,
// but Acid 3 apparently depends on spaces being ignored.
bytes = bytes
.into_iter()
.filter(|&b| b != b' ')
.collect::<Vec<u8>>();
match base64::decode_config(&bytes, base64::STANDARD.decode_allow_trailing_bits(true)) {
Err(..) => return Err(DecodeError::NonBase64DataUri),
Ok(data) => bytes = data,
}
}
Ok((content_type, bytes))
}