1
0
Fork 0
mirror of git://slackware.nl/current.git synced 2025-01-17 18:12:36 +01:00
slackware-current/source/xap/seamonkey/seamonkey.rust14x.diff

4280 lines
131 KiB
Diff
Raw Normal View History

diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/netwerk/base/rust-url-capi/Cargo.toml seamonkey-2.53.1/mozilla/netwerk/base/rust-url-capi/Cargo.toml
--- seamonkey-2.53.1.orig/mozilla/netwerk/base/rust-url-capi/Cargo.toml 2020-02-17 17:37:59.000000000 -0600
+++ seamonkey-2.53.1/mozilla/netwerk/base/rust-url-capi/Cargo.toml 2020-02-29 21:16:23.109772243 -0600
@@ -8,6 +8,6 @@
[dependencies]
libc = "0.2.0"
-url = "1.5.1"
+url = "1.7.2"
nsstring = { path = "../../../xpcom/rust/nsstring" }
nserror = { path = "../../../xpcom/rust/nserror" }
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/.cargo-checksum.json seamonkey-2.53.1/mozilla/third_party/rust/url/.cargo-checksum.json
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/.cargo-checksum.json 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/.cargo-checksum.json 2020-02-29 21:15:43.797770564 -0600
@@ -1 +1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"890af214187ffcba4732acb2d1af30d7adb9aade0679e9fdb06baae363240b8e","Cargo.toml":"ec586106c4d0625919a3591fe3ae915043e82c8bfdd1c9e747171ba5e21047e1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","Makefile":"bffd75d34654b2955d4f005f1a5e85c821c90becf1a8a52cbe10121972f43148","README.md":"eb3f4694003f408cbe3c7f3e9fbbc71241defb940cc55a816981f0f0f144c8eb","UPGRADING.md":"fbcc2d39bdf17db0745793db6626fcd5c909dddd4ce13b27566cfabece22c368","appveyor.yml":"c78486dbfbe6ebbf3d808afb9a19f7ec18c4704ce451c6305f0716999b70a1a6","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"f61e6271c1ea1aa113b64b356e994595fa548f0433f89948d747503ad22195cd","docs/index.html":"f61e6271c1ea1aa113b64b356e994595fa548f0433f89948d747503ad22195cd","github.png":"b432fd855efe7c430fe6a57ccf83935c1996f03a7cdc8d6e1b34154b8c43f6ec","rust-url-todo":"1192cee7b6cedf2133d97dc6074b593a1d19b0ee13fff6f28d6329855044e575","src/encoding.rs":"f3e109ca8ec5a9130da50cdfb3003530aedb6dd5a440f0790d76b71f6981119c","src/form_urlencoded.rs":"7ccaef7148e4bc2577154c50f8705db3a055b641269e24c22770f06222321e1e","src/host.rs":"281165d732ea87b6f01a98f7c68ffcb284c41f84b3ab6ed674fb8e57022d1019","src/lib.rs":"bd156e8bcfbd44f0cd52c8b394e03ec63fea012c0bf5ca554521352714838605","src/origin.rs":"7071dcc1070ccfae84cdcd43586b84a9706e35a9a099ff4dde128da0909bd0bc","src/parser.rs":"9d30868f0900586fec6f122a0322598a08116ab0b4c4d8caf5c35a720381a73a","src/path_segments.rs":"7bd3142eaa568863ef44e2255c181239141f9eeee337f889b9ffaaeab4ca669d","src/quirks.rs":"1231f965e22bb3632c22993e2a8d4c7470bcb4a8de25d049f31784303f0def03","src/slicing.rs":"4e539886b23945a92094625f3e531a4bff40daa44240b5d19ee8577478c4f7fe","tests/data.rs":"c333766897f6492fb6583ab5c8a511973b7a55f58ca550799432343da64d5ca7","tests/setters_tests.json":"ebcbdb52e9a4b5a565f8806d52ebc610d46a34df883e10b0be080d026468ff73","tests/unit.rs":"c2f206f433be619414d761d358a2a4a5a46cfe8a4fea5339adec5e9937d78de2","tests/urltestdata.json":"430c74aa3a31afaa57a92805544e00825f4dffe2def98c1e3c212c3db80268af"},"package":"eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"}
\ No newline at end of file
+{"files":{"Cargo.toml":"80d575ae6adad93cb0910b385b871e2d92d558078f58a3c8eafe95940d459f6b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","README.md":"eb3f4694003f408cbe3c7f3e9fbbc71241defb940cc55a816981f0f0f144c8eb","UPGRADING.md":"fbcc2d39bdf17db0745793db6626fcd5c909dddd4ce13b27566cfabece22c368","appveyor.yml":"c78486dbfbe6ebbf3d808afb9a19f7ec18c4704ce451c6305f0716999b70a1a6","benches/parse_url.rs":"821ecb051c3c6c40eb3b268ba7337b2988333627d0af0c8e1afc84734ffbbf2b","docs/404.html":"f61e6271c1ea1aa113b64b356e994595fa548f0433f89948d747503ad22195cd","docs/index.html":"f61e6271c1ea1aa113b64b356e994595fa548f0433f89948d747503ad22195cd","src/encoding.rs":"f3e109ca8ec5a9130da50cdfb3003530aedb6dd5a440f0790d76b71f6981119c","src/form_urlencoded.rs":"d8c35e92375cafcd7e12c4f0d5374bab62aa1f333629d55b007a9c3d5c3cb615","src/host.rs":"66a2c0c77a8add2da16bc690fbc82b130cf1367ac655fc36990a214e193a4d6c","src/lib.rs":"e09dcba401018169ee26764e1c2bccf0855a5d935707c2100fd8d8e77a1bbc91","src/origin.rs":"6e4821eb9600a32ef54d05c8e1a7937f6d9b4dd1e3bda7f36c7988f6a2bef78b","src/parser.rs":"76368cbe93308123c014a3502024cf97d97ca61dcfc7b6ecd710073867d6deca","src/path_segments.rs":"7bd3142eaa568863ef44e2255c181239141f9eeee337f889b9ffaaeab4ca669d","src/quirks.rs":"6cf1697bad363532cbcc60917a9b126560ac3ab3e1a77da0abcf4f2a40c8233a","src/slicing.rs":"4e539886b23945a92094625f3e531a4bff40daa44240b5d19ee8577478c4f7fe","tests/data.rs":"f2c1c6d1823e8d21aeeae31c786d7f4ef0d97352a896f8c5aeb03a41fedb9a48","tests/setters_tests.json":"08ddaa632ad19c81e83b904bfaa94bc971f26e2bdfcef27d2f93fd033ad57340","tests/unit.rs":"ead7185710ce06c8d68ea18700618477867ee355656eabcad26cfcfaaad361a0","tests/urltestdata.json":"1b0c7c727d8d7e79dfb0d0aa347ff05675ddb68bc4ead38f83fd8e89bc59cc32"},"package":"dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"}
\ No newline at end of file
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/.travis.yml seamonkey-2.53.1/mozilla/third_party/rust/url/.travis.yml
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/.travis.yml 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/.travis.yml 1969-12-31 18:00:00.000000000 -0600
@@ -1,9 +0,0 @@
-language: rust
-rust:
- - nightly
- - beta
- - stable
- - 1.17.0
-script: make test
-notifications:
- webhooks: http://build.servo.org:54856/travis
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/Cargo.toml seamonkey-2.53.1/mozilla/third_party/rust/url/Cargo.toml
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/Cargo.toml 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/Cargo.toml 2020-02-29 21:15:43.799770565 -0600
@@ -1,24 +1,31 @@
-[package]
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+[package]
name = "url"
-# When updating version, also modify html_root_url in the lib.rs
-version = "1.5.1"
+version = "1.7.2"
authors = ["The rust-url developers"]
-
description = "URL library for Rust, based on the WHATWG URL Standard"
documentation = "https://docs.rs/url"
-repository = "https://github.com/servo/rust-url"
readme = "README.md"
keywords = ["url", "parser"]
categories = ["parser-implementations", "web-programming", "encoding"]
license = "MIT/Apache-2.0"
+repository = "https://github.com/servo/rust-url"
+[package.metadata.docs.rs]
+features = ["query_encoding"]
-[badges]
-travis-ci = { repository = "servo/rust-url" }
-appveyor = { repository = "servo/rust-url" }
-
-[workspace]
-members = [".", "idna", "percent_encoding", "url_serde"]
+[lib]
+test = false
[[test]]
name = "unit"
@@ -27,23 +34,50 @@
name = "data"
harness = false
-[lib]
-test = false
+[[bench]]
+name = "parse_url"
+harness = false
+[dependencies.encoding]
+version = "0.2"
+optional = true
-[dev-dependencies]
-rustc-test = "0.1"
-rustc-serialize = "0.3"
-serde_json = ">=0.6.1, <0.9"
+[dependencies.heapsize]
+version = ">=0.4.1, <0.5"
+optional = true
+
+[dependencies.idna]
+version = "0.1.0"
+
+[dependencies.matches]
+version = "0.1"
+
+[dependencies.percent-encoding]
+version = "1.0.0"
+
+[dependencies.rustc-serialize]
+version = "0.3"
+optional = true
+
+[dependencies.serde]
+version = ">=0.6.1, <0.9"
+optional = true
+[dev-dependencies.bencher]
+version = "0.1"
+
+[dev-dependencies.rustc-serialize]
+version = "0.3"
+
+[dev-dependencies.rustc-test]
+version = "0.3"
+
+[dev-dependencies.serde_json]
+version = ">=0.6.1, <0.9"
[features]
-query_encoding = ["encoding"]
heap_size = ["heapsize"]
+query_encoding = ["encoding"]
+[badges.appveyor]
+repository = "Manishearth/rust-url"
-[dependencies]
-encoding = {version = "0.2", optional = true}
-heapsize = {version = ">=0.1.1, <0.5", optional = true}
-idna = { version = "0.1.0", path = "./idna" }
-matches = "0.1"
-percent-encoding = { version = "1.0.0", path = "./percent_encoding" }
-rustc-serialize = {version = "0.3", optional = true}
-serde = {version = ">=0.6.1, <0.9", optional = true}
+[badges.travis-ci]
+repository = "servo/rust-url"
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/Makefile seamonkey-2.53.1/mozilla/third_party/rust/url/Makefile
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/Makefile 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/Makefile 1969-12-31 18:00:00.000000000 -0600
@@ -1,6 +0,0 @@
-test:
- cargo test --features "query_encoding serde rustc-serialize heapsize"
- (cd idna && cargo test)
- (cd url_serde && cargo test)
-
-.PHONY: test
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/benches/parse_url.rs seamonkey-2.53.1/mozilla/third_party/rust/url/benches/parse_url.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/benches/parse_url.rs 1969-12-31 18:00:00.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/benches/parse_url.rs 2020-02-29 21:15:43.801770565 -0600
@@ -0,0 +1,18 @@
+#[macro_use]
+extern crate bencher;
+
+extern crate url;
+
+use bencher::{black_box, Bencher};
+
+use url::Url;
+
+fn short(bench: &mut Bencher) {
+ let url = "https://example.com/bench";
+
+ bench.bytes = url.len() as u64;
+ bench.iter(|| black_box(url).parse::<Url>().unwrap());
+}
+
+benchmark_group!(benches, short);
+benchmark_main!(benches);
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/rust-url-todo seamonkey-2.53.1/mozilla/third_party/rust/url/rust-url-todo
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/rust-url-todo 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/rust-url-todo 1969-12-31 18:00:00.000000000 -0600
@@ -1,14 +0,0 @@
-* standalone path parsing?
-* Test setters
- * Test trim C0/space
- * Test remove tab & newline
-
-
-
-#[test]
-fn test_path_segments() {
- let mut url = Url::parse("http://example.net").unwrap();
- url.push_path_segment("foo").unwrap();
- url.extend_path_segments(&["bar", "b/az"]).unwrap();
- assert_eq!(url.as_str(), "http://example.net/foo");
-}
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/form_urlencoded.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/form_urlencoded.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/form_urlencoded.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/form_urlencoded.rs 2020-02-29 21:15:43.802770565 -0600
@@ -16,6 +16,7 @@
use encoding::EncodingOverride;
use percent_encoding::{percent_encode_byte, percent_decode};
use std::borrow::{Borrow, Cow};
+use std::fmt;
use std::str;
@@ -216,6 +217,15 @@
target: Option<T>,
start_position: usize,
encoding: EncodingOverride,
+ custom_encoding: Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>,
+}
+
+struct SilentDebug<T>(T);
+
+impl<T> fmt::Debug for SilentDebug<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("…")
+ }
}
pub trait Target {
@@ -247,8 +257,16 @@
// * `Serializer` keeps its target in a private field
// * Unlike in other `Target` impls, `UrlQuery::finished` does not return `Self`.
impl<'a> Target for ::UrlQuery<'a> {
- fn as_mut_string(&mut self) -> &mut String { &mut self.url.serialization }
- fn finish(self) -> &'a mut ::Url { self.url }
+ fn as_mut_string(&mut self) -> &mut String {
+ &mut self.url.as_mut().unwrap().serialization
+ }
+
+ fn finish(mut self) -> &'a mut ::Url {
+ let url = self.url.take().unwrap();
+ url.restore_already_parsed_fragment(self.fragment.take());
+ url
+ }
+
type Finished = &'a mut ::Url;
}
@@ -272,6 +290,7 @@
target: Some(target),
start_position: start_position,
encoding: EncodingOverride::utf8(),
+ custom_encoding: None,
}
}
@@ -290,11 +309,20 @@
self
}
+ /// Set the character encoding to be used for names and values before percent-encoding.
+ pub fn custom_encoding_override<F>(&mut self, encode: F) -> &mut Self
+ where F: FnMut(&str) -> Cow<[u8]> + 'static
+ {
+ self.custom_encoding = Some(SilentDebug(Box::new(encode)));
+ self
+ }
+
/// Serialize and append a name/value pair.
///
/// Panics if called after `.finish()`.
pub fn append_pair(&mut self, name: &str, value: &str) -> &mut Self {
- append_pair(string(&mut self.target), self.start_position, self.encoding, name, value);
+ append_pair(string(&mut self.target), self.start_position, self.encoding,
+ &mut self.custom_encoding, name, value);
self
}
@@ -311,7 +339,8 @@
let string = string(&mut self.target);
for pair in iter {
let &(ref k, ref v) = pair.borrow();
- append_pair(string, self.start_position, self.encoding, k.as_ref(), v.as_ref());
+ append_pair(string, self.start_position, self.encoding,
+ &mut self.custom_encoding, k.as_ref(), v.as_ref());
}
}
self
@@ -324,6 +353,8 @@
/// Panics if called after `.finish()`.
#[cfg(feature = "query_encoding")]
pub fn append_charset(&mut self) -> &mut Self {
+ assert!(self.custom_encoding.is_none(),
+ "Cannot use both custom_encoding_override() and append_charset()");
{
let string = string(&mut self.target);
append_separator_if_needed(string, self.start_position);
@@ -361,9 +392,20 @@
}
fn append_pair(string: &mut String, start_position: usize, encoding: EncodingOverride,
+ custom_encoding: &mut Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>,
name: &str, value: &str) {
append_separator_if_needed(string, start_position);
- string.extend(byte_serialize(&encoding.encode(name.into())));
+ append_encoded(name, string, encoding, custom_encoding);
string.push('=');
- string.extend(byte_serialize(&encoding.encode(value.into())));
+ append_encoded(value, string, encoding, custom_encoding);
+}
+
+fn append_encoded(s: &str, string: &mut String, encoding: EncodingOverride,
+ custom_encoding: &mut Option<SilentDebug<Box<FnMut(&str) -> Cow<[u8]>>>>) {
+ let bytes = if let Some(SilentDebug(ref mut custom)) = *custom_encoding {
+ custom(s)
+ } else {
+ encoding.encode(s.into())
+ };
+ string.extend(byte_serialize(&bytes));
}
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/host.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/host.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/host.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/host.rs 2020-02-29 21:15:07.663769022 -0600
@@ -13,7 +13,7 @@
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
use std::vec;
use parser::{ParseResult, ParseError};
-use percent_encoding::percent_decode;
+use percent_encoding::{percent_decode, utf8_percent_encode, SIMPLE_ENCODE_SET};
use idna;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -73,7 +73,9 @@
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Host<S=String> {
/// A DNS domain name, as '.' dot-separated labels.
- /// Non-ASCII labels are encoded in punycode per IDNA.
+ /// Non-ASCII labels are encoded in punycode per IDNA if this is the host of
+ /// a special URL, or percent encoded for non-special URLs. Hosts for
+ /// non-special URLs are also called opaque hosts.
Domain(S),
/// An IPv4 address.
@@ -137,7 +139,7 @@
impl Host<String> {
/// Parse a host: either an IPv6 address in [] square brackets, or a domain.
///
- /// https://url.spec.whatwg.org/#host-parsing
+ /// <https://url.spec.whatwg.org/#host-parsing>
pub fn parse(input: &str) -> Result<Self, ParseError> {
if input.starts_with('[') {
if !input.ends_with(']') {
@@ -158,6 +160,23 @@
Ok(Host::Domain(domain.into()))
}
}
+
+ // <https://url.spec.whatwg.org/#concept-opaque-host-parser>
+ pub fn parse_opaque(input: &str) -> Result<Self, ParseError> {
+ if input.starts_with('[') {
+ if !input.ends_with(']') {
+ return Err(ParseError::InvalidIpv6Address)
+ }
+ return parse_ipv6addr(&input[1..input.len() - 1]).map(Host::Ipv6)
+ }
+ if input.find(|c| matches!(c,
+ '\0' | '\t' | '\n' | '\r' | ' ' | '#' | '/' | ':' | '?' | '@' | '[' | '\\' | ']'
+ )).is_some() {
+ return Err(ParseError::InvalidDomainCharacter)
+ }
+ let s = utf8_percent_encode(input, SIMPLE_ENCODE_SET).to_string();
+ Ok(Host::Domain(s))
+ }
}
impl<S: AsRef<str>> fmt::Display for Host<S> {
@@ -309,8 +328,8 @@
}
}
-/// https://url.spec.whatwg.org/#ipv4-number-parser
-fn parse_ipv4number(mut input: &str) -> Result<u32, ()> {
+/// <https://url.spec.whatwg.org/#ipv4-number-parser>
+fn parse_ipv4number(mut input: &str) -> Result<Option<u32>, ()> {
let mut r = 10;
if input.starts_with("0x") || input.starts_with("0X") {
input = &input[2..];
@@ -319,19 +338,35 @@
input = &input[1..];
r = 8;
}
+
+ // At the moment we can't know the reason why from_str_radix fails
+ // https://github.com/rust-lang/rust/issues/22639
+ // So instead we check if the input looks like a real number and only return
+ // an error when it's an overflow.
+ let valid_number = match r {
+ 8 => input.chars().all(|c| c >= '0' && c <='7'),
+ 10 => input.chars().all(|c| c >= '0' && c <='9'),
+ 16 => input.chars().all(|c| (c >= '0' && c <='9') || (c >='a' && c <= 'f') || (c >= 'A' && c <= 'F')),
+ _ => false
+ };
+
+ if !valid_number {
+ return Ok(None);
+ }
+
if input.is_empty() {
- return Ok(0);
+ return Ok(Some(0));
}
if input.starts_with('+') {
- return Err(())
+ return Ok(None);
}
match u32::from_str_radix(input, r) {
- Ok(number) => Ok(number),
+ Ok(number) => Ok(Some(number)),
Err(_) => Err(()),
}
}
-/// https://url.spec.whatwg.org/#concept-ipv4-parser
+/// <https://url.spec.whatwg.org/#concept-ipv4-parser>
fn parse_ipv4addr(input: &str) -> ParseResult<Option<Ipv4Addr>> {
if input.is_empty() {
return Ok(None)
@@ -344,15 +379,19 @@
return Ok(None);
}
let mut numbers: Vec<u32> = Vec::new();
+ let mut overflow = false;
for part in parts {
if part == "" {
return Ok(None);
}
- if let Ok(n) = parse_ipv4number(part) {
- numbers.push(n);
- } else {
- return Ok(None);
- }
+ match parse_ipv4number(part) {
+ Ok(Some(n)) => numbers.push(n),
+ Ok(None) => return Ok(None),
+ Err(()) => overflow = true
+ };
+ }
+ if overflow {
+ return Err(ParseError::InvalidIpv4Address);
}
let mut ipv4 = numbers.pop().expect("a non-empty list of numbers");
// Equivalent to: ipv4 >= 256 ** (4 numbers.len())
@@ -368,7 +407,7 @@
Ok(Some(Ipv4Addr::from(ipv4)))
}
-/// https://url.spec.whatwg.org/#concept-ipv6-parser
+/// <https://url.spec.whatwg.org/#concept-ipv6-parser>
fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
let input = input.as_bytes();
let len = input.len();
@@ -423,6 +462,9 @@
return Err(ParseError::InvalidIpv6Address)
}
i = start;
+ if piece_pointer > 6 {
+ return Err(ParseError::InvalidIpv6Address)
+ }
is_ip_v4 = true;
},
b':' => {
@@ -445,16 +487,24 @@
if piece_pointer > 6 {
return Err(ParseError::InvalidIpv6Address)
}
- let mut dots_seen = 0;
+ let mut numbers_seen = 0;
while i < len {
- let mut value = None;
+ if numbers_seen > 0 {
+ if numbers_seen < 4 && (i < len && input[i] == b'.') {
+ i += 1
+ } else {
+ return Err(ParseError::InvalidIpv6Address)
+ }
+ }
+
+ let mut ipv4_piece = None;
while i < len {
let digit = match input[i] {
c @ b'0' ... b'9' => c - b'0',
_ => break
};
- match value {
- None => value = Some(digit as u16),
+ match ipv4_piece {
+ None => ipv4_piece = Some(digit as u16),
Some(0) => return Err(ParseError::InvalidIpv6Address), // No leading zero
Some(ref mut v) => {
*v = *v * 10 + digit as u16;
@@ -465,24 +515,28 @@
}
i += 1;
}
- if dots_seen < 3 && !(i < len && input[i] == b'.') {
- return Err(ParseError::InvalidIpv6Address)
- }
- pieces[piece_pointer] = if let Some(v) = value {
+
+ pieces[piece_pointer] = if let Some(v) = ipv4_piece {
pieces[piece_pointer] * 0x100 + v
} else {
return Err(ParseError::InvalidIpv6Address)
};
- if dots_seen == 1 || dots_seen == 3 {
+ numbers_seen += 1;
+
+ if numbers_seen == 2 || numbers_seen == 4 {
piece_pointer += 1;
}
- i += 1;
- if dots_seen == 3 && i < len {
- return Err(ParseError::InvalidIpv6Address)
- }
- dots_seen += 1;
+ }
+
+ if numbers_seen != 4 {
+ return Err(ParseError::InvalidIpv6Address)
}
}
+
+ if i < len {
+ return Err(ParseError::InvalidIpv6Address)
+ }
+
match compress_pointer {
Some(compress_pointer) => {
let mut swaps = piece_pointer - compress_pointer;
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/lib.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/lib.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/lib.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/lib.rs 2020-02-29 21:15:43.804770565 -0600
@@ -104,7 +104,7 @@
# run().unwrap();
*/
-#![doc(html_root_url = "https://docs.rs/url/1.5.1")]
+#![doc(html_root_url = "https://docs.rs/url/1.7.0")]
#[cfg(feature="rustc-serialize")] extern crate rustc_serialize;
#[macro_use] extern crate matches;
@@ -112,12 +112,13 @@
#[cfg(feature="heapsize")] #[macro_use] extern crate heapsize;
pub extern crate idna;
+#[macro_use]
pub extern crate percent_encoding;
use encoding::EncodingOverride;
#[cfg(feature = "heapsize")] use heapsize::HeapSizeOf;
use host::HostInternal;
-use parser::{Parser, Context, SchemeType, to_u32};
+use parser::{Parser, Context, SchemeType, to_u32, ViolationFn};
use percent_encoding::{PATH_SEGMENT_ENCODE_SET, USERINFO_ENCODE_SET,
percent_encode, percent_decode, utf8_percent_encode};
use std::borrow::Borrow;
@@ -135,7 +136,7 @@
pub use origin::{Origin, OpaqueOrigin};
pub use host::{Host, HostAndPort, SocketAddrs};
pub use path_segments::PathSegmentsMut;
-pub use parser::ParseError;
+pub use parser::{ParseError, SyntaxViolation};
pub use slicing::Position;
mod encoding;
@@ -186,7 +187,7 @@
pub struct ParseOptions<'a> {
base_url: Option<&'a Url>,
encoding_override: encoding::EncodingOverride,
- log_syntax_violation: Option<&'a Fn(&'static str)>,
+ violation_fn: ViolationFn<'a>,
}
impl<'a> ParseOptions<'a> {
@@ -209,9 +210,47 @@
self
}
- /// Call the provided function or closure on non-fatal parse errors.
+ /// Call the provided function or closure on non-fatal parse errors, passing
+ /// a static string description. This method is deprecated in favor of
+ /// `syntax_violation_callback` and is implemented as an adaptor for the
+ /// latter, passing the `SyntaxViolation` description. Only the last value
+ /// passed to either method will be used by a parser.
+ #[deprecated]
pub fn log_syntax_violation(mut self, new: Option<&'a Fn(&'static str)>) -> Self {
- self.log_syntax_violation = new;
+ self.violation_fn = match new {
+ Some(f) => ViolationFn::OldFn(f),
+ None => ViolationFn::NoOp
+ };
+ self
+ }
+
+ /// Call the provided function or closure for a non-fatal `SyntaxViolation`
+ /// when it occurs during parsing. Note that since the provided function is
+ /// `Fn`, the caller might need to utilize _interior mutability_, such as with
+ /// a `RefCell`, to collect the violations.
+ ///
+ /// ## Example
+ /// ```
+ /// use std::cell::RefCell;
+ /// use url::{Url, SyntaxViolation};
+ /// # use url::ParseError;
+ /// # fn run() -> Result<(), url::ParseError> {
+ /// let violations = RefCell::new(Vec::new());
+ /// let url = Url::options()
+ /// .syntax_violation_callback(Some(&|v| violations.borrow_mut().push(v)))
+ /// .parse("https:////example.com")?;
+ /// assert_eq!(url.as_str(), "https://example.com/");
+ /// assert_eq!(violations.into_inner(),
+ /// vec!(SyntaxViolation::ExpectedDoubleSlash));
+ /// # Ok(())
+ /// # }
+ /// # run().unwrap();
+ /// ```
+ pub fn syntax_violation_callback(mut self, new: Option<&'a Fn(SyntaxViolation)>) -> Self {
+ self.violation_fn = match new {
+ Some(f) => ViolationFn::NewFn(f),
+ None => ViolationFn::NoOp
+ };
self
}
@@ -221,7 +260,7 @@
serialization: String::with_capacity(input.len()),
base_url: self.base_url,
query_encoding_override: self.encoding_override,
- log_syntax_violation: self.log_syntax_violation,
+ violation_fn: self.violation_fn,
context: Context::UrlParser,
}.parse_url(input)
}
@@ -229,11 +268,12 @@
impl<'a> Debug for ParseOptions<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "ParseOptions {{ base_url: {:?}, encoding_override: {:?}, log_syntax_violation: ", self.base_url, self.encoding_override)?;
- match self.log_syntax_violation {
- Some(_) => write!(f, "Some(Fn(&'static str)) }}"),
- None => write!(f, "None }}")
- }
+ write!(f,
+ "ParseOptions {{ base_url: {:?}, encoding_override: {:?}, \
+ violation_fn: {:?} }}",
+ self.base_url,
+ self.encoding_override,
+ self.violation_fn)
}
}
@@ -252,6 +292,13 @@
/// # }
/// # run().unwrap();
/// ```
+ ///
+ /// # Errors
+ ///
+ /// If the function can not parse an absolute URL from the given string,
+ /// a [`ParseError`] variant will be returned.
+ ///
+ /// [`ParseError`]: enum.ParseError.html
#[inline]
pub fn parse(input: &str) -> Result<Url, ::ParseError> {
Url::options().parse(input)
@@ -274,6 +321,13 @@
/// # }
/// # run().unwrap();
/// ```
+ ///
+ /// # Errors
+ ///
+ /// If the function can not parse an absolute URL from the given string,
+ /// a [`ParseError`] variant will be returned.
+ ///
+ /// [`ParseError`]: enum.ParseError.html
#[inline]
pub fn parse_with_params<I, K, V>(input: &str, iter: I) -> Result<Url, ::ParseError>
where I: IntoIterator,
@@ -301,7 +355,7 @@
/// ```rust
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let base = Url::parse("https://example.net/a/b.html")?;
/// let url = base.join("c.png")?;
@@ -314,6 +368,13 @@
/// # }
/// # run().unwrap();
/// ```
+ ///
+ /// # Errors
+ ///
+ /// If the function can not parse an URL from the given string
+ /// with this URL as the base URL, a [`ParseError`] variant will be returned.
+ ///
+ /// [`ParseError`]: enum.ParseError.html
#[inline]
pub fn join(&self, input: &str) -> Result<Url, ::ParseError> {
Url::options().base_url(Some(self)).parse(input)
@@ -342,7 +403,7 @@
ParseOptions {
base_url: None,
encoding_override: EncodingOverride::utf8(),
- log_syntax_violation: None,
+ violation_fn: ViolationFn::NoOp,
}
}
@@ -500,7 +561,7 @@
Ok(())
}
- /// Return the origin of this URL (https://url.spec.whatwg.org/#origin)
+ /// Return the origin of this URL (<https://url.spec.whatwg.org/#origin>)
///
/// Note: this returns an opaque origin for `file:` URLs, which causes
/// `url.origin() != url.origin()`.
@@ -1156,11 +1217,11 @@
/// assert_eq!(url.as_str(), "https://example.com/data.csv");
/// url.set_fragment(Some("cell=4,1-6,2"));
- /// assert_eq!(url.as_str(), "https://example.com/data.csv#cell=4,1-6,2");
+ /// assert_eq!(url.as_str(), "https://example.com/data.csv#cell=4,1-6,2");
/// assert_eq!(url.fragment(), Some("cell=4,1-6,2"));
///
/// url.set_fragment(None);
- /// assert_eq!(url.as_str(), "https://example.com/data.csv");
+ /// assert_eq!(url.as_str(), "https://example.com/data.csv");
/// assert!(url.fragment().is_none());
/// # Ok(())
/// # }
@@ -1213,7 +1274,7 @@
/// assert_eq!(url.as_str(), "https://example.com/products");
///
/// url.set_query(Some("page=2"));
- /// assert_eq!(url.as_str(), "https://example.com/products?page=2");
+ /// assert_eq!(url.as_str(), "https://example.com/products?page=2");
/// assert_eq!(url.query(), Some("page=2"));
/// # Ok(())
/// # }
@@ -1283,7 +1344,7 @@
self.serialization.push('?');
}
- let query = UrlQuery { url: self, fragment: fragment };
+ let query = UrlQuery { url: Some(self), fragment: fragment };
form_urlencoded::Serializer::for_suffix(query, query_start + "?".len())
}
@@ -1309,12 +1370,12 @@
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("https://example.com")?;
/// url.set_path("api/comments");
- /// assert_eq!(url.as_str(), "https://example.com/api/comments");
+ /// assert_eq!(url.as_str(), "https://example.com/api/comments");
/// assert_eq!(url.path(), "/api/comments");
///
/// let mut url = Url::parse("https://example.com/api")?;
/// url.set_path("data/report.csv");
- /// assert_eq!(url.as_str(), "https://example.com/data/report.csv");
+ /// assert_eq!(url.as_str(), "https://example.com/data/report.csv");
/// assert_eq!(url.path(), "/data/report.csv");
/// # Ok(())
/// # }
@@ -1406,7 +1467,8 @@
/// # run().unwrap();
/// ```
pub fn set_port(&mut self, mut port: Option<u16>) -> Result<(), ()> {
- if !self.has_host() || self.scheme() == "file" {
+ // has_host implies !cannot_be_a_base
+ if !self.has_host() || self.host() == Some(Host::Domain("")) || self.scheme() == "file" {
return Err(())
}
if port.is_some() && port == parser::default_port(self.scheme()) {
@@ -1448,9 +1510,6 @@
/// Change this URLs host.
///
- /// If this URL is cannot-be-a-base or there is an error parsing the given `host`,
- /// do nothing and return `Err`.
- ///
/// Removing the host (calling this with `None`)
/// will also remove any username, password, and port number.
///
@@ -1477,7 +1536,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("foo://example.net")?;
/// let result = url.set_host(None);
@@ -1493,7 +1552,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("https://example.net")?;
/// let result = url.set_host(None);
@@ -1509,7 +1568,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("mailto:rms@example.net")?;
///
@@ -1524,6 +1583,13 @@
/// # }
/// # run().unwrap();
/// ```
+ ///
+ /// # Errors
+ ///
+ /// If this URL is cannot-be-a-base or there is an error parsing the given `host`,
+ /// a [`ParseError`] variant will be returned.
+ ///
+ /// [`ParseError`]: enum.ParseError.html
pub fn set_host(&mut self, host: Option<&str>) -> Result<(), ParseError> {
if self.cannot_be_a_base() {
return Err(ParseError::SetHostOnCannotBeABaseUrl)
@@ -1533,7 +1599,11 @@
if host == "" && SchemeType::from(self.scheme()).is_special() {
return Err(ParseError::EmptyHost);
}
- self.set_host_internal(Host::parse(host)?, None)
+ if SchemeType::from(self.scheme()).is_special() {
+ self.set_host_internal(Host::parse(host)?, None)
+ } else {
+ self.set_host_internal(Host::parse_opaque(host)?, None)
+ }
} else if self.has_host() {
if SchemeType::from(self.scheme()).is_special() {
return Err(ParseError::EmptyHost)
@@ -1666,7 +1736,8 @@
/// # run().unwrap();
/// ```
pub fn set_password(&mut self, password: Option<&str>) -> Result<(), ()> {
- if !self.has_host() {
+ // has_host implies !cannot_be_a_base
+ if !self.has_host() || self.host() == Some(Host::Domain("")) || self.scheme() == "file" {
return Err(())
}
if let Some(password) = password {
@@ -1732,21 +1803,23 @@
/// ```
///
/// Setup username to user1
+ ///
/// ```rust
/// use url::{Url, ParseError};
///
/// # fn run() -> Result<(), ParseError> {
- /// let mut url = Url::parse("ftp://:secre1@example.com")?;
+ /// let mut url = Url::parse("ftp://:secre1@example.com/")?;
/// let result = url.set_username("user1");
/// assert!(result.is_ok());
/// assert_eq!(url.username(), "user1");
- /// assert_eq!(url.as_str(), "ftp://user1:secre1@example.com");
+ /// assert_eq!(url.as_str(), "ftp://user1:secre1@example.com/");
/// # Ok(())
/// # }
/// # run().unwrap();
/// ```
pub fn set_username(&mut self, username: &str) -> Result<(), ()> {
- if !self.has_host() {
+ // has_host implies !cannot_be_a_base
+ if !self.has_host() || self.host() == Some(Host::Domain("")) || self.scheme() == "file" {
return Err(())
}
let username_start = self.scheme_end + 3;
@@ -1805,7 +1878,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("https://example.net")?;
/// let result = url.set_scheme("foo");
@@ -1822,7 +1895,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("https://example.net")?;
/// let result = url.set_scheme("foõ");
@@ -1838,7 +1911,7 @@
/// ```
/// use url::Url;
/// # use url::ParseError;
- ///
+ ///
/// # fn run() -> Result<(), ParseError> {
/// let mut url = Url::parse("mailto:rms@example.net")?;
/// let result = url.set_scheme("https");
@@ -1887,7 +1960,7 @@
/// ```
/// # if cfg!(unix) {
/// use url::Url;
- ///
+ ///
/// # fn run() -> Result<(), ()> {
/// let url = Url::from_file_path("/tmp/foo.txt")?;
/// assert_eq!(url.as_str(), "file:///tmp/foo.txt");
@@ -1902,6 +1975,7 @@
/// # run().unwrap();
/// # }
/// ```
+ #[cfg(any(unix, windows, target_os="redox"))]
pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut serialization = "file://".to_owned();
let host_start = serialization.len() as u32;
@@ -1937,6 +2011,7 @@
///
/// Note that `std::path` does not consider trailing slashes significant
/// and usually does not include them (e.g. in `Path::parent()`).
+ #[cfg(any(unix, windows, target_os="redox"))]
pub fn from_directory_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut url = Url::from_file_path(path)?;
if !url.serialization.ends_with('/') {
@@ -2018,6 +2093,7 @@
/// (That is, if the percent-decoded path contains a NUL byte or,
/// for a Windows path, is not UTF-8.)
#[inline]
+ #[cfg(any(unix, windows, target_os="redox"))]
pub fn to_file_path(&self) -> Result<PathBuf, ()> {
if let Some(segments) = self.path_segments() {
let host = match self.host() {
@@ -2264,6 +2340,7 @@
Ok((host_end, host_internal))
}
+
#[cfg(any(unix, target_os = "redox"))]
fn file_url_segments_to_pathbuf(host: Option<&str>, segments: str::Split<char>) -> Result<PathBuf, ()> {
use std::ffi::OsStr;
@@ -2347,13 +2424,15 @@
/// Implementation detail of `Url::query_pairs_mut`. Typically not used directly.
#[derive(Debug)]
pub struct UrlQuery<'a> {
- url: &'a mut Url,
+ url: Option<&'a mut Url>,
fragment: Option<String>,
}
impl<'a> Drop for UrlQuery<'a> {
fn drop(&mut self) {
- self.url.restore_already_parsed_fragment(self.fragment.take())
+ if let Some(url) = self.url.take() {
+ url.restore_already_parsed_fragment(self.fragment.take())
+ }
}
}
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/origin.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/origin.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/origin.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/origin.rs 2020-02-29 21:14:51.284768322 -0600
@@ -49,7 +49,7 @@
/// - If the scheme is anything else, the origin is opaque, meaning
/// the URL does not have the same origin as any other URL.
///
-/// For more information see https://url.spec.whatwg.org/#origin
+/// For more information see <https://url.spec.whatwg.org/#origin>
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Origin {
/// A globally unique identifier
@@ -86,7 +86,7 @@
matches!(*self, Origin::Tuple(..))
}
- /// https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin
+ /// <https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin>
pub fn ascii_serialization(&self) -> String {
match *self {
Origin::Opaque(_) => "null".to_owned(),
@@ -100,7 +100,7 @@
}
}
- /// https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin
+ /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
pub fn unicode_serialization(&self) -> String {
match *self {
Origin::Opaque(_) => "null".to_owned(),
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/parser.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/parser.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/parser.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/parser.rs 2020-02-29 21:15:43.806770565 -0600
@@ -6,7 +6,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#[allow(unused_imports, deprecated)]
use std::ascii::AsciiExt;
+
use std::error::Error;
use std::fmt::{self, Formatter, Write};
use std::str;
@@ -20,6 +22,12 @@
PATH_SEGMENT_ENCODE_SET
};
+define_encode_set! {
+ // The backslash (\) character is treated as a path separator in special URLs
+ // so it needs to be additionally escaped in that case.
+ pub SPECIAL_PATH_SEGMENT_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'\\'}
+}
+
pub type ParseResult<T> = Result<T, ParseError>;
macro_rules! simple_enum_error {
@@ -70,6 +78,54 @@
fn from(_: ::idna::uts46::Errors) -> ParseError { ParseError::IdnaError }
}
+macro_rules! syntax_violation_enum {
+ ($($name: ident => $description: expr,)+) => {
+ /// Non-fatal syntax violations that can occur during parsing.
+ #[derive(PartialEq, Eq, Clone, Copy, Debug)]
+ pub enum SyntaxViolation {
+ $(
+ $name,
+ )+
+ }
+
+ impl SyntaxViolation {
+ pub fn description(&self) -> &'static str {
+ match *self {
+ $(
+ SyntaxViolation::$name => $description,
+ )+
+ }
+ }
+ }
+ }
+}
+
+syntax_violation_enum! {
+ Backslash => "backslash",
+ C0SpaceIgnored =>
+ "leading or trailing control or space character are ignored in URLs",
+ EmbeddedCredentials =>
+ "embedding authentication information (username or password) \
+ in an URL is not recommended",
+ ExpectedDoubleSlash => "expected //",
+ ExpectedFileDoubleSlash => "expected // after file:",
+ FileWithHostAndWindowsDrive => "file: with host and Windows drive letter",
+ NonUrlCodePoint => "non-URL code point",
+ NullInFragment => "NULL characters are ignored in URL fragment identifiers",
+ PercentDecode => "expected 2 hex digits after %",
+ TabOrNewlineIgnored => "tabs or newlines are ignored in URLs",
+ UnencodedAtSign => "unencoded @ sign in username or password",
+}
+
+#[cfg(feature = "heapsize")]
+known_heap_size!(0, SyntaxViolation);
+
+impl fmt::Display for SyntaxViolation {
+ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+ self.description().fmt(fmt)
+ }
+}
+
#[derive(Copy, Clone)]
pub enum SchemeType {
File,
@@ -112,18 +168,17 @@
impl<'i> Input<'i> {
pub fn new(input: &'i str) -> Self {
- Input::with_log(input, None)
+ Input::with_log(input, ViolationFn::NoOp)
}
- pub fn with_log(original_input: &'i str, log_syntax_violation: Option<&Fn(&'static str)>)
- -> Self {
+ pub fn with_log(original_input: &'i str, vfn: ViolationFn) -> Self {
let input = original_input.trim_matches(c0_control_or_space);
- if let Some(log) = log_syntax_violation {
+ if vfn.is_set() {
if input.len() < original_input.len() {
- log("leading or trailing control or space character are ignored in URLs")
+ vfn.call(SyntaxViolation::C0SpaceIgnored)
}
if input.chars().any(|c| matches!(c, '\t' | '\n' | '\r')) {
- log("tabs or newlines are ignored in URLs")
+ vfn.call(SyntaxViolation::TabOrNewlineIgnored)
}
}
Input { chars: input.chars() }
@@ -216,11 +271,60 @@
}
}
+/// Wrapper for syntax violation callback functions.
+#[derive(Copy, Clone)]
+pub enum ViolationFn<'a> {
+ NewFn(&'a (Fn(SyntaxViolation) + 'a)),
+ OldFn(&'a (Fn(&'static str) + 'a)),
+ NoOp
+}
+
+impl<'a> ViolationFn<'a> {
+ /// Call with a violation.
+ pub fn call(self, v: SyntaxViolation) {
+ match self {
+ ViolationFn::NewFn(f) => f(v),
+ ViolationFn::OldFn(f) => f(v.description()),
+ ViolationFn::NoOp => {}
+ }
+ }
+
+ /// Call with a violation, if provided test returns true. Avoids
+ /// the test entirely if `NoOp`.
+ pub fn call_if<F>(self, v: SyntaxViolation, test: F)
+ where F: Fn() -> bool
+ {
+ match self {
+ ViolationFn::NewFn(f) => if test() { f(v) },
+ ViolationFn::OldFn(f) => if test() { f(v.description()) },
+ ViolationFn::NoOp => {} // avoid test
+ }
+ }
+
+ /// True if not `NoOp`
+ pub fn is_set(self) -> bool {
+ match self {
+ ViolationFn::NoOp => false,
+ _ => true
+ }
+ }
+}
+
+impl<'a> fmt::Debug for ViolationFn<'a> {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ match *self {
+ ViolationFn::NewFn(_) => write!(f, "NewFn(Fn(SyntaxViolation))"),
+ ViolationFn::OldFn(_) => write!(f, "OldFn(Fn(&'static str))"),
+ ViolationFn::NoOp => write!(f, "NoOp")
+ }
+ }
+}
+
pub struct Parser<'a> {
pub serialization: String,
pub base_url: Option<&'a Url>,
pub query_encoding_override: EncodingOverride,
- pub log_syntax_violation: Option<&'a Fn(&'static str)>,
+ pub violation_fn: ViolationFn<'a>,
pub context: Context,
}
@@ -237,29 +341,14 @@
serialization: serialization,
base_url: None,
query_encoding_override: EncodingOverride::utf8(),
- log_syntax_violation: None,
+ violation_fn: ViolationFn::NoOp,
context: Context::Setter,
}
}
- fn syntax_violation(&self, reason: &'static str) {
- if let Some(log) = self.log_syntax_violation {
- log(reason)
- }
- }
-
- fn syntax_violation_if<F: Fn() -> bool>(&self, reason: &'static str, test: F) {
- // Skip test if not logging.
- if let Some(log) = self.log_syntax_violation {
- if test() {
- log(reason)
- }
- }
- }
-
/// https://url.spec.whatwg.org/#concept-basic-url-parser
pub fn parse_url(mut self, input: &str) -> ParseResult<Url> {
- let input = Input::with_log(input, self.log_syntax_violation);
+ let input = Input::with_log(input, self.violation_fn);
if let Ok(remaining) = self.parse_scheme(input.clone()) {
return self.parse_with_scheme(remaining)
}
@@ -310,12 +399,13 @@
}
fn parse_with_scheme(mut self, input: Input) -> ParseResult<Url> {
+ use SyntaxViolation::{ExpectedFileDoubleSlash, ExpectedDoubleSlash};
let scheme_end = to_u32(self.serialization.len())?;
let scheme_type = SchemeType::from(&self.serialization);
self.serialization.push(':');
match scheme_type {
SchemeType::File => {
- self.syntax_violation_if("expected // after file:", || !input.starts_with("//"));
+ self.violation_fn.call_if(ExpectedFileDoubleSlash, || !input.starts_with("//"));
let base_file_url = self.base_url.and_then(|base| {
if base.scheme() == "file" { Some(base) } else { None }
});
@@ -335,7 +425,7 @@
}
}
// special authority slashes state
- self.syntax_violation_if("expected //", || {
+ self.violation_fn.call_if(ExpectedDoubleSlash, || {
input.clone().take_while(|&c| matches!(c, '/' | '\\'))
.collect::<String>() != "//"
});
@@ -371,6 +461,7 @@
}
fn parse_file(mut self, input: Input, mut base_file_url: Option<&Url>) -> ParseResult<Url> {
+ use SyntaxViolation::Backslash;
// file state
debug_assert!(self.serialization.is_empty());
let (first_char, input_after_first_char) = input.split_first();
@@ -451,6 +542,7 @@
let scheme_end = "file".len() as u32;
let path_start = "file://".len() as u32;
let fragment_start = "file:///".len() as u32;
+ self.serialization.push('#');
self.parse_fragment(input_after_first_char);
Ok(Url {
serialization: self.serialization,
@@ -467,18 +559,18 @@
}
}
Some('/') | Some('\\') => {
- self.syntax_violation_if("backslash", || first_char == Some('\\'));
+ self.violation_fn.call_if(Backslash, || first_char == Some('\\'));
// file slash state
let (next_char, input_after_next_char) = input_after_first_char.split_first();
- self.syntax_violation_if("backslash", || next_char == Some('\\'));
+ self.violation_fn.call_if(Backslash, || next_char == Some('\\'));
if matches!(next_char, Some('/') | Some('\\')) {
// file host state
self.serialization.push_str("file://");
let scheme_end = "file".len() as u32;
let host_start = "file://".len() as u32;
- let (path_start, host, remaining) =
+ let (path_start, mut host, remaining) =
self.parse_file_host(input_after_next_char)?;
- let host_end = to_u32(self.serialization.len())?;
+ let mut host_end = to_u32(self.serialization.len())?;
let mut has_host = !matches!(host, HostInternal::None);
let remaining = if path_start {
self.parse_path_start(SchemeType::File, &mut has_host, remaining)
@@ -487,7 +579,13 @@
self.serialization.push('/');
self.parse_path(SchemeType::File, &mut has_host, path_start, remaining)
};
- // FIXME: deal with has_host
+ // For file URLs that have a host and whose path starts
+ // with the windows drive letter we just remove the host.
+ if !has_host {
+ self.serialization.drain(host_start as usize..host_end as usize);
+ host_end = host_start;
+ host = HostInternal::None;
+ }
let (query_start, fragment_start) =
self.parse_query_and_fragment(scheme_end, remaining)?;
Ok(Url {
@@ -616,7 +714,7 @@
Some('/') | Some('\\') => {
let (slashes_count, remaining) = input.count_matching(|c| matches!(c, '/' | '\\'));
if slashes_count >= 2 {
- self.syntax_violation_if("expected //", || {
+ self.violation_fn.call_if(SyntaxViolation::ExpectedDoubleSlash, || {
input.clone().take_while(|&c| matches!(c, '/' | '\\'))
.collect::<String>() != "//"
});
@@ -680,11 +778,9 @@
match c {
'@' => {
if last_at.is_some() {
- self.syntax_violation("unencoded @ sign in username or password")
+ self.violation_fn.call(SyntaxViolation::UnencodedAtSign)
} else {
- self.syntax_violation(
- "embedding authentification information (username or password) \
- in an URL is not recommended")
+ self.violation_fn.call(SyntaxViolation::EmbeddedCredentials)
}
last_at = Some((char_count, remaining.clone()))
},
@@ -701,14 +797,23 @@
};
let mut username_end = None;
+ let mut has_password = false;
+ let mut has_username = false;
while userinfo_char_count > 0 {
let (c, utf8_c) = input.next_utf8().unwrap();
userinfo_char_count -= 1;
if c == ':' && username_end.is_none() {
// Start parsing password
username_end = Some(to_u32(self.serialization.len())?);
- self.serialization.push(':');
+ // We don't add a colon if the password is empty
+ if userinfo_char_count > 0 {
+ self.serialization.push(':');
+ has_password = true;
+ }
} else {
+ if !has_password {
+ has_username = true;
+ }
self.check_url_code_point(c, &input);
self.serialization.extend(utf8_percent_encode(utf8_c, USERINFO_ENCODE_SET));
}
@@ -717,7 +822,9 @@
Some(i) => i,
None => to_u32(self.serialization.len())?,
};
- self.serialization.push('@');
+ if has_username || has_password {
+ self.serialization.push('@');
+ }
Ok((username_end, remaining))
}
@@ -783,6 +890,10 @@
if scheme_type.is_special() && host_str.is_empty() {
return Err(ParseError::EmptyHost)
}
+ if !scheme_type.is_special() {
+ let host = Host::parse_opaque(host_str)?;
+ return Ok((host, input));
+ }
let host = Host::parse(host_str)?;
Ok((host, input))
}
@@ -867,7 +978,7 @@
match input.split_first() {
(Some('/'), remaining) => input = remaining,
(Some('\\'), remaining) => if scheme_type.is_special() {
- self.syntax_violation("backslash");
+ self.violation_fn.call(SyntaxViolation::Backslash);
input = remaining
},
_ => {}
@@ -895,7 +1006,7 @@
},
'\\' if self.context != Context::PathSegmentSetter &&
scheme_type.is_special() => {
- self.syntax_violation("backslash");
+ self.violation_fn.call(SyntaxViolation::Backslash);
ends_with_slash = true;
break
},
@@ -905,18 +1016,14 @@
},
_ => {
self.check_url_code_point(c, &input);
- if c == '%' {
- let after_percent_sign = input.clone();
- if matches!(input.next(), Some('2')) &&
- matches!(input.next(), Some('E') | Some('e')) {
- self.serialization.push('.');
- continue
- }
- input = after_percent_sign
- }
if self.context == Context::PathSegmentSetter {
- self.serialization.extend(utf8_percent_encode(
- utf8_c, PATH_SEGMENT_ENCODE_SET));
+ if scheme_type.is_special() {
+ self.serialization.extend(utf8_percent_encode(
+ utf8_c, SPECIAL_PATH_SEGMENT_ENCODE_SET));
+ } else {
+ self.serialization.extend(utf8_percent_encode(
+ utf8_c, PATH_SEGMENT_ENCODE_SET));
+ }
} else {
self.serialization.extend(utf8_percent_encode(
utf8_c, DEFAULT_ENCODE_SET));
@@ -925,7 +1032,7 @@
}
}
match &self.serialization[segment_start..] {
- ".." => {
+ ".." | "%2e%2e" | "%2e%2E" | "%2E%2e" | "%2E%2E" | "%2e." | "%2E." | ".%2e" | ".%2E" => {
debug_assert!(self.serialization.as_bytes()[segment_start - 1] == b'/');
self.serialization.truncate(segment_start - 1); // Truncate "/.."
self.pop_path(scheme_type, path_start);
@@ -933,7 +1040,7 @@
self.serialization.push('/')
}
},
- "." => {
+ "." | "%2e" | "%2E" => {
self.serialization.truncate(segment_start);
},
_ => {
@@ -945,7 +1052,7 @@
self.serialization.push(':');
}
if *has_host {
- self.syntax_violation("file: with host and Windows drive letter");
+ self.violation_fn.call(SyntaxViolation::FileWithHostAndWindowsDrive);
*has_host = false; // FIXME account for this in callers
}
}
@@ -1087,7 +1194,7 @@
pub fn parse_fragment(&mut self, mut input: Input) {
while let Some((c, utf8_c)) = input.next_utf8() {
if c == '\0' {
- self.syntax_violation("NULL characters are ignored in URL fragment identifiers")
+ self.violation_fn.call(SyntaxViolation::NullInFragment)
} else {
self.check_url_code_point(c, &input);
self.serialization.extend(utf8_percent_encode(utf8_c,
@@ -1097,15 +1204,16 @@
}
fn check_url_code_point(&self, c: char, input: &Input) {
- if let Some(log) = self.log_syntax_violation {
+ let vfn = self.violation_fn;
+ if vfn.is_set() {
if c == '%' {
let mut input = input.clone();
if !matches!((input.next(), input.next()), (Some(a), Some(b))
if is_ascii_hex_digit(a) && is_ascii_hex_digit(b)) {
- log("expected 2 hex digits after %")
+ vfn.call(SyntaxViolation::PercentDecode)
}
} else if !is_url_code_point(c) {
- log("non-URL code point")
+ vfn.call(SyntaxViolation::NonUrlCodePoint)
}
}
}
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/quirks.rs seamonkey-2.53.1/mozilla/third_party/rust/url/src/quirks.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/src/quirks.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/src/quirks.rs 2020-02-29 21:15:07.670769022 -0600
@@ -46,7 +46,7 @@
/// Getter for https://url.spec.whatwg.org/#dom-url-origin
pub fn origin(url: &Url) -> String {
- url.origin().unicode_serialization()
+ url.origin().ascii_serialization()
}
/// Getter for https://url.spec.whatwg.org/#dom-url-protocol
@@ -152,7 +152,7 @@
{
// has_host implies !cannot_be_a_base
let scheme = url.scheme();
- if !url.has_host() || scheme == "file" {
+ if !url.has_host() || url.host() == Some(Host::Domain("")) || scheme == "file" {
return Err(())
}
result = Parser::parse_port(Input::new(new_port), || default_port(scheme), Context::Setter)
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/data.rs seamonkey-2.53.1/mozilla/third_party/rust/url/tests/data.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/data.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/tests/data.rs 2020-02-29 21:15:43.807770565 -0600
@@ -9,7 +9,7 @@
//! Data-driven tests
extern crate rustc_serialize;
-extern crate test;
+extern crate rustc_test as test;
extern crate url;
use rustc_serialize::json::{self, Json};
@@ -29,6 +29,7 @@
fn run_parsing(input: &str, base: &str, expected: Result<ExpectedAttributes, ()>) {
let base = match Url::parse(&base) {
Ok(base) => base,
+ Err(_) if expected.is_err() => return,
Err(message) => panic!("Error parsing base {:?}: {}", base, message)
};
let (url, expected) = match (base.join(&input), expected) {
@@ -188,11 +189,7 @@
{
let mut add_one = |name: String, run: test::TestFn| {
tests.push(test::TestDescAndFn {
- desc: test::TestDesc {
- name: test::DynTestName(name),
- ignore: false,
- should_panic: test::ShouldPanic::No,
- },
+ desc: test::TestDesc::new(test::DynTestName(name)),
testfn: run,
})
};
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/setters_tests.json seamonkey-2.53.1/mozilla/third_party/rust/url/tests/setters_tests.json
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/setters_tests.json 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/tests/setters_tests.json 2020-02-29 21:15:07.674769022 -0600
@@ -102,6 +102,31 @@
}
},
{
+ "comment": "Cant switch from file URL with no host",
+ "href": "file://localhost/",
+ "new_value": "http",
+ "expected": {
+ "href": "file:///",
+ "protocol": "file:"
+ }
+ },
+ {
+ "href": "file:///test",
+ "new_value": "gopher",
+ "expected": {
+ "href": "file:///test",
+ "protocol": "file:"
+ }
+ },
+ {
+ "href": "file:",
+ "new_value": "wss",
+ "expected": {
+ "href": "file:///",
+ "protocol": "file:"
+ }
+ },
+ {
"comment": "Spec deviation: from special scheme to not is not problematic. https://github.com/whatwg/url/issues/104",
"href": "http://example.net",
"new_value": "b",
@@ -176,6 +201,14 @@
}
},
{
+ "href": "javascript:alert(1)",
+ "new_value": "wario",
+ "expected": {
+ "href": "javascript:alert(1)",
+ "username": ""
+ }
+ },
+ {
"href": "http://example.net",
"new_value": "me",
"expected": {
@@ -224,6 +257,30 @@
"href": "http://%c3%89t%C3%A9@example.net/",
"username": "%c3%89t%C3%A9"
}
+ },
+ {
+ "href": "sc:///",
+ "new_value": "x",
+ "expected": {
+ "href": "sc:///",
+ "username": ""
+ }
+ },
+ {
+ "href": "file://test/",
+ "new_value": "test",
+ "expected": {
+ "href": "file://test/",
+ "username": ""
+ }
+ },
+ {
+ "href": "javascript://x/",
+ "new_value": "wario",
+ "expected": {
+ "href": "javascript://wario@x/",
+ "username": "wario"
+ }
}
],
"password": [
@@ -303,10 +360,106 @@
"href": "http://:%c3%89t%C3%A9@example.net/",
"password": "%c3%89t%C3%A9"
}
+ },
+ {
+ "href": "sc:///",
+ "new_value": "x",
+ "expected": {
+ "href": "sc:///",
+ "password": ""
+ }
+ },
+ {
+ "href": "file://test/",
+ "new_value": "test",
+ "expected": {
+ "href": "file://test/",
+ "password": ""
+ }
+ },
+ {
+ "href": "javascript://x/",
+ "new_value": "bowser",
+ "expected": {
+ "href": "javascript://:bowser@x/",
+ "password": "bowser"
+ }
}
],
"host": [
{
+ "href": "sc://x/",
+ "new_value": "\u0009",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "\u000A",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "\u000D",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "#",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "/",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "?",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "@",
+ "expected": {
+ "href": "sc://x/",
+ "host": "x",
+ "hostname": "x"
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "ß",
+ "expected": {
+ "href": "sc://%C3%9F/",
+ "host": "%C3%9F",
+ "hostname": "%C3%9F"
+ }
+ },
+ {
"comment": "Cannot-be-a-base means no host",
"href": "mailto:me@example.net",
"new_value": "example.com",
@@ -384,15 +537,6 @@
}
},
{
- "comment": "Path-only URLs can gain a host",
- "href": "a:/foo",
- "new_value": "example.net",
- "expected": {
- "href": "a://example.net/foo",
- "host": "example.net"
- }
- },
- {
"comment": "IPv4 address syntax is normalized",
"href": "http://example.net",
"new_value": "0x7F000001:8080",
@@ -536,7 +680,7 @@
}
},
{
- "comment": "\\ is not a delimiter for non-special schemes, and its invalid in a domain",
+ "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
"href": "view-source+http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
@@ -600,10 +744,119 @@
"hostname": "example.com",
"port": ""
}
+ },
+ {
+ "comment": "Broken IPv6",
+ "href": "http://example.net/",
+ "new_value": "[google.com]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.3.4x]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.3.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
}
],
"hostname": [
{
+ "href": "sc://x/",
+ "new_value": "\u0009",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "\u000A",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "\u000D",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "#",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "/",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "?",
+ "expected": {
+ "href": "sc:///",
+ "host": "",
+ "hostname": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "@",
+ "expected": {
+ "href": "sc://x/",
+ "host": "x",
+ "hostname": "x"
+ }
+ },
+ {
"comment": "Cannot-be-a-base means no host",
"href": "mailto:me@example.net",
"new_value": "example.com",
@@ -659,15 +912,6 @@
}
},
{
- "comment": "Path-only URLs can gain a host",
- "href": "a:/foo",
- "new_value": "example.net",
- "expected": {
- "href": "a://example.net/foo",
- "host": "example.net"
- }
- },
- {
"comment": "IPv4 address syntax is normalized",
"href": "http://example.net:8080",
"new_value": "0x7F000001",
@@ -756,7 +1000,7 @@
}
},
{
- "comment": "\\ is not a delimiter for non-special schemes, and its invalid in a domain",
+ "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
"href": "view-source+http://example.net/path",
"new_value": "example.com\\stuff",
"expected": {
@@ -765,6 +1009,52 @@
"hostname": "example.net",
"port": ""
}
+ },
+ {
+ "comment": "Broken IPv6",
+ "href": "http://example.net/",
+ "new_value": "[google.com]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.3.4x]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.3.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.2.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
+ },
+ {
+ "href": "http://example.net/",
+ "new_value": "[::1.]",
+ "expected": {
+ "href": "http://example.net/",
+ "host": "example.net",
+ "hostname": "example.net"
+ }
}
],
"port": [
@@ -779,7 +1069,7 @@
}
},
{
- "comment": "Port number is removed if empty in the new value: https://github.com/whatwg/url/pull/113",
+ "comment": "Port number is removed if empty is the new value",
"href": "http://example.net:8080",
"new_value": "",
"expected": {
@@ -920,6 +1210,65 @@
"hostname": "example.net",
"port": "8080"
}
+ },
+ {
+ "comment": "Port numbers are 16 bit integers, overflowing is an error",
+ "href": "non-special://example.net:8080/path",
+ "new_value": "65536",
+ "expected": {
+ "href": "non-special://example.net:8080/path",
+ "host": "example.net:8080",
+ "hostname": "example.net",
+ "port": "8080"
+ }
+ },
+ {
+ "href": "file://test/",
+ "new_value": "12",
+ "expected": {
+ "href": "file://test/",
+ "port": ""
+ }
+ },
+ {
+ "href": "file://localhost/",
+ "new_value": "12",
+ "expected": {
+ "href": "file:///",
+ "port": ""
+ }
+ },
+ {
+ "href": "non-base:value",
+ "new_value": "12",
+ "expected": {
+ "href": "non-base:value",
+ "port": ""
+ }
+ },
+ {
+ "href": "sc:///",
+ "new_value": "12",
+ "expected": {
+ "href": "sc:///",
+ "port": ""
+ }
+ },
+ {
+ "href": "sc://x/",
+ "new_value": "12",
+ "expected": {
+ "href": "sc://x:12/",
+ "port": "12"
+ }
+ },
+ {
+ "href": "javascript://x/",
+ "new_value": "12",
+ "expected": {
+ "href": "javascript://x:12/",
+ "port": "12"
+ }
}
],
"pathname": [
@@ -970,8 +1319,8 @@
"href": "view-source+http://example.net/home?lang=fr#nav",
"new_value": "\\a\\%2E\\b\\%2e.\\c",
"expected": {
- "href": "view-source+http://example.net/\\a\\.\\b\\..\\c?lang=fr#nav",
- "pathname": "/\\a\\.\\b\\..\\c"
+ "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav",
+ "pathname": "/\\a\\%2E\\b\\%2e.\\c"
}
},
{
@@ -984,12 +1333,48 @@
}
},
{
- "comment": "Bytes already percent-encoded are left as-is, except %2E.",
+ "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.",
"href": "http://example.net",
"new_value": "%2e%2E%c3%89té",
"expected": {
- "href": "http://example.net/..%c3%89t%C3%A9",
- "pathname": "/..%c3%89t%C3%A9"
+ "href": "http://example.net/%2e%2E%c3%89t%C3%A9",
+ "pathname": "/%2e%2E%c3%89t%C3%A9"
+ }
+ },
+ {
+ "comment": "? needs to be encoded",
+ "href": "http://example.net",
+ "new_value": "?",
+ "expected": {
+ "href": "http://example.net/%3F",
+ "pathname": "/%3F"
+ }
+ },
+ {
+ "comment": "# needs to be encoded",
+ "href": "http://example.net",
+ "new_value": "#",
+ "expected": {
+ "href": "http://example.net/%23",
+ "pathname": "/%23"
+ }
+ },
+ {
+ "comment": "? needs to be encoded, non-special scheme",
+ "href": "sc://example.net",
+ "new_value": "?",
+ "expected": {
+ "href": "sc://example.net/%3F",
+ "pathname": "/%3F"
+ }
+ },
+ {
+ "comment": "# needs to be encoded, non-special scheme",
+ "href": "sc://example.net",
+ "new_value": "#",
+ "expected": {
+ "href": "sc://example.net/%23",
+ "pathname": "/%23"
}
}
],
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/unit.rs seamonkey-2.53.1/mozilla/third_party/rust/url/tests/unit.rs
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/unit.rs 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/tests/unit.rs 2020-02-29 21:15:43.808770565 -0600
@@ -11,7 +11,9 @@
#[macro_use]
extern crate url;
+use std::ascii::AsciiExt;
use std::borrow::Cow;
+use std::cell::{Cell, RefCell};
use std::net::{Ipv4Addr, Ipv6Addr};
use std::path::{Path, PathBuf};
use url::{Host, HostAndPort, Url, form_urlencoded};
@@ -108,6 +110,17 @@
}
#[test]
+fn path_backslash_fun() {
+ let mut special_url = "http://foobar.com".parse::<Url>().unwrap();
+ special_url.path_segments_mut().unwrap().push("foo\\bar");
+ assert_eq!(special_url.as_str(), "http://foobar.com/foo%5Cbar");
+
+ let mut nonspecial_url = "thing://foobar.com".parse::<Url>().unwrap();
+ nonspecial_url.path_segments_mut().unwrap().push("foo\\bar");
+ assert_eq!(nonspecial_url.as_str(), "thing://foobar.com/foo\\bar");
+}
+
+#[test]
fn from_str() {
assert!("http://testing.com/this".parse::<Url>().is_ok());
}
@@ -221,7 +234,7 @@
("http://example.com/", "http://example.com/"),
("http://addslash.com", "http://addslash.com/"),
("http://@emptyuser.com/", "http://emptyuser.com/"),
- ("http://:@emptypass.com/", "http://:@emptypass.com/"),
+ ("http://:@emptypass.com/", "http://emptypass.com/"),
("http://user@user.com/", "http://user@user.com/"),
("http://user:pass@userpass.com/", "http://user:pass@userpass.com/"),
("http://slashquery.com/path/?q=something", "http://slashquery.com/path/?q=something"),
@@ -256,6 +269,15 @@
}
#[test]
+fn form_urlencoded_custom_encoding_override() {
+ let encoded = form_urlencoded::Serializer::new(String::new())
+ .custom_encoding_override(|s| s.as_bytes().to_ascii_uppercase().into())
+ .append_pair("foo", "bar")
+ .finish();
+ assert_eq!(encoded, "FOO=BAR");
+}
+
+#[test]
fn host_and_port_display() {
assert_eq!(
format!(
@@ -286,22 +308,6 @@
}
#[test]
-/// https://github.com/servo/rust-url/issues/25
-fn issue_25() {
- let filename = if cfg!(windows) { r"C:\run\pg.sock" } else { "/run/pg.sock" };
- let mut url = Url::from_file_path(filename).unwrap();
- url.check_invariants().unwrap();
- url.set_scheme("postgres").unwrap();
- url.check_invariants().unwrap();
- url.set_host(Some("")).unwrap();
- url.check_invariants().unwrap();
- url.set_username("me").unwrap();
- url.check_invariants().unwrap();
- let expected = format!("postgres://me@/{}run/pg.sock", if cfg!(windows) { "C:/" } else { "" });
- assert_eq!(url.as_str(), expected);
-}
-
-#[test]
/// https://github.com/servo/rust-url/issues/61
fn issue_61() {
let mut url = Url::parse("http://mozilla.org").unwrap();
@@ -372,6 +378,11 @@
let mut url = Url::parse("foobar://example.net/hello").unwrap();
url.set_host(None).unwrap();
assert_eq!(url.as_str(), "foobar:/hello");
+
+ let mut url = Url::parse("foo://ș").unwrap();
+ assert_eq!(url.as_str(), "foo://%C8%99/");
+ url.set_host(Some("goșu.ro")).unwrap();
+ assert_eq!(url.as_str(), "foo://go%C8%99u.ro/");
}
#[test]
@@ -478,3 +489,68 @@
let url = Url::from_file_path(Path::new(r"\\.\some\path\file.txt"));
assert!(url.is_err());
}
+
+// Test the now deprecated log_syntax_violation method for backward
+// compatibility
+#[test]
+#[allow(deprecated)]
+fn test_old_log_violation_option() {
+ let violation = Cell::new(None);
+ let url = Url::options()
+ .log_syntax_violation(Some(&|s| violation.set(Some(s.to_owned()))))
+ .parse("http:////mozilla.org:42").unwrap();
+ assert_eq!(url.port(), Some(42));
+
+ let violation = violation.take();
+ assert_eq!(violation, Some("expected //".to_string()));
+}
+
+#[test]
+fn test_syntax_violation_callback() {
+ use url::SyntaxViolation::*;
+ let violation = Cell::new(None);
+ let url = Url::options()
+ .syntax_violation_callback(Some(&|v| violation.set(Some(v))))
+ .parse("http:////mozilla.org:42").unwrap();
+ assert_eq!(url.port(), Some(42));
+
+ let v = violation.take().unwrap();
+ assert_eq!(v, ExpectedDoubleSlash);
+ assert_eq!(v.description(), "expected //");
+}
+
+#[test]
+fn test_syntax_violation_callback_lifetimes() {
+ use url::SyntaxViolation::*;
+ let violation = Cell::new(None);
+ let vfn = |s| violation.set(Some(s));
+
+ let url = Url::options()
+ .syntax_violation_callback(Some(&vfn))
+ .parse("http:////mozilla.org:42").unwrap();
+ assert_eq!(url.port(), Some(42));
+ assert_eq!(violation.take(), Some(ExpectedDoubleSlash));
+
+ let url = Url::options()
+ .syntax_violation_callback(Some(&vfn))
+ .parse("http://mozilla.org\\path").unwrap();
+ assert_eq!(url.path(), "/path");
+ assert_eq!(violation.take(), Some(Backslash));
+}
+
+#[test]
+fn test_options_reuse() {
+ use url::SyntaxViolation::*;
+ let violations = RefCell::new(Vec::new());
+ let vfn = |v| violations.borrow_mut().push(v);
+
+ let options = Url::options()
+ .syntax_violation_callback(Some(&vfn));
+ let url = options.parse("http:////mozilla.org").unwrap();
+
+ let options = options.base_url(Some(&url));
+ let url = options.parse("/sub\\path").unwrap();
+ assert_eq!(url.as_str(), "http://mozilla.org/sub/path");
+ assert_eq!(*violations.borrow(),
+ vec!(ExpectedDoubleSlash, Backslash));
+}
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/urltestdata.json seamonkey-2.53.1/mozilla/third_party/rust/url/tests/urltestdata.json
--- seamonkey-2.53.1.orig/mozilla/third_party/rust/url/tests/urltestdata.json 2020-02-17 17:39:21.000000000 -0600
+++ seamonkey-2.53.1/mozilla/third_party/rust/url/tests/urltestdata.json 2020-02-29 21:15:07.679769022 -0600
@@ -31,6 +31,66 @@
"hash": "#c"
},
{
+ "input": "https://test:@test",
+ "base": "about:blank",
+ "href": "https://test@test/",
+ "origin": "https://test",
+ "protocol": "https:",
+ "username": "test",
+ "password": "",
+ "host": "test",
+ "hostname": "test",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "https://:@test",
+ "base": "about:blank",
+ "href": "https://test/",
+ "origin": "https://test",
+ "protocol": "https:",
+ "username": "",
+ "password": "",
+ "host": "test",
+ "hostname": "test",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://test:@test/x",
+ "base": "about:blank",
+ "href": "non-special://test@test/x",
+ "origin": "null",
+ "protocol": "non-special:",
+ "username": "test",
+ "password": "",
+ "host": "test",
+ "hostname": "test",
+ "port": "",
+ "pathname": "/x",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://:@test/x",
+ "base": "about:blank",
+ "href": "non-special://test/x",
+ "origin": "null",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "test",
+ "hostname": "test",
+ "port": "",
+ "pathname": "/x",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "http:foo.com",
"base": "http://example.org/foo/bar",
"href": "http://example.org/foo/foo.com",
@@ -106,6 +166,20 @@
"hash": "# e"
},
{
+ "input": "lolscheme:x x#x x",
+ "base": "about:blank",
+ "href": "lolscheme:x x#x x",
+ "protocol": "lolscheme:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "x x",
+ "search": "",
+ "hash": "#x x"
+ },
+ {
"input": "http://f:/c",
"base": "http://example.org/foo/bar",
"href": "http://f/c",
@@ -201,6 +275,11 @@
"failure": true
},
{
+ "input": "non-special://f:999999/c",
+ "base": "http://example.org/foo/bar",
+ "failure": true
+ },
+ {
"input": "http://f: 21 / b ? d # e ",
"base": "http://example.org/foo/bar",
"failure": true
@@ -960,6 +1039,26 @@
"hash": ""
},
{
+ "input": "file://example:1/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://example:test/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://example%/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://[example]/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
"input": "ftps:/example.com/",
"base": "http://example.org/foo/bar",
"href": "ftps:/example.com/",
@@ -1785,7 +1884,7 @@
{
"input": "http://example.com/foo/%2e%2",
"base": "about:blank",
- "href": "http://example.com/foo/.%2",
+ "href": "http://example.com/foo/%2e%2",
"origin": "http://example.com",
"protocol": "http:",
"username": "",
@@ -1793,14 +1892,14 @@
"host": "example.com",
"hostname": "example.com",
"port": "",
- "pathname": "/foo/.%2",
+ "pathname": "/foo/%2e%2",
"search": "",
"hash": ""
},
{
"input": "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar",
"base": "about:blank",
- "href": "http://example.com/..bar",
+ "href": "http://example.com/%2e.bar",
"origin": "http://example.com",
"protocol": "http:",
"username": "",
@@ -1808,7 +1907,7 @@
"host": "example.com",
"hostname": "example.com",
"port": "",
- "pathname": "/..bar",
+ "pathname": "/%2e.bar",
"search": "",
"hash": ""
},
@@ -2189,11 +2288,6 @@
"hash": "# %C2%BB"
},
{
- "input": "http://[www.google.com]/",
- "base": "about:blank",
- "failure": true
- },
- {
"input": "http://www.google.com",
"base": "about:blank",
"href": "http://www.google.com/",
@@ -2226,7 +2320,7 @@
{
"input": "http://www/foo%2Ehtml",
"base": "about:blank",
- "href": "http://www/foo.html",
+ "href": "http://www/foo%2Ehtml",
"origin": "http://www",
"protocol": "http:",
"username": "",
@@ -2234,7 +2328,7 @@
"host": "www",
"hostname": "www",
"port": "",
- "pathname": "/foo.html",
+ "pathname": "/foo%2Ehtml",
"search": "",
"hash": ""
},
@@ -3096,7 +3190,7 @@
{
"input": "http:a:@www.example.com",
"base": "about:blank",
- "href": "http://a:@www.example.com/",
+ "href": "http://a@www.example.com/",
"origin": "http://www.example.com",
"protocol": "http:",
"username": "a",
@@ -3111,7 +3205,7 @@
{
"input": "http:/a:@www.example.com",
"base": "about:blank",
- "href": "http://a:@www.example.com/",
+ "href": "http://a@www.example.com/",
"origin": "http://www.example.com",
"protocol": "http:",
"username": "a",
@@ -3126,7 +3220,7 @@
{
"input": "http://a:@www.example.com",
"base": "about:blank",
- "href": "http://a:@www.example.com/",
+ "href": "http://a@www.example.com/",
"origin": "http://www.example.com",
"protocol": "http:",
"username": "a",
@@ -3171,7 +3265,7 @@
{
"input": "http://:@www.example.com",
"base": "about:blank",
- "href": "http://:@www.example.com/",
+ "href": "http://www.example.com/",
"origin": "http://www.example.com",
"protocol": "http:",
"username": "",
@@ -3465,6 +3559,22 @@
"search": "",
"hash": ""
},
+ "Leading and trailing C0 control or space",
+ {
+ "input": "\u0000\u001b\u0004\u0012 http://example.com/\u001f \u000d ",
+ "base": "about:blank",
+ "href": "http://example.com/",
+ "origin": "http://example.com",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.com",
+ "hostname": "example.com",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
"Ideographic full stop (full-width period for Chinese, etc.) should be treated as a dot. U+3002 is mapped to U+002E (dot)",
{
"input": "http://www.foo。bar.com",
@@ -3493,6 +3603,32 @@
"base": "http://other.com/",
"failure": true
},
+ "U+FFFD",
+ {
+ "input": "https://\ufffd",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://%EF%BF%BD",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://x/\ufffd?\ufffd#\ufffd",
+ "base": "about:blank",
+ "href": "https://x/%EF%BF%BD?%EF%BF%BD#%EF%BF%BD",
+ "origin": "https://x",
+ "protocol": "https:",
+ "username": "",
+ "password": "",
+ "host": "x",
+ "hostname": "x",
+ "port": "",
+ "pathname": "/%EF%BF%BD",
+ "search": "?%EF%BF%BD",
+ "hash": "#%EF%BF%BD"
+ },
"Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.",
{
"input": "http://.com",
@@ -3536,7 +3672,7 @@
"input": "http://你好你好",
"base": "http://other.com/",
"href": "http://xn--6qqa088eba/",
- "origin": "http://你好你好",
+ "origin": "http://xn--6qqa088eba",
"protocol": "http:",
"username": "",
"password": "",
@@ -3547,6 +3683,36 @@
"search": "",
"hash": ""
},
+ {
+ "input": "https://faß.ExAmPlE/",
+ "base": "about:blank",
+ "href": "https://xn--fa-hia.example/",
+ "origin": "https://xn--fa-hia.example",
+ "protocol": "https:",
+ "username": "",
+ "password": "",
+ "host": "xn--fa-hia.example",
+ "hostname": "xn--fa-hia.example",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "sc://faß.ExAmPlE/",
+ "base": "about:blank",
+ "href": "sc://fa%C3%9F.ExAmPlE/",
+ "origin": "null",
+ "protocol": "sc:",
+ "username": "",
+ "password": "",
+ "host": "fa%C3%9F.ExAmPlE",
+ "hostname": "fa%C3%9F.ExAmPlE",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
"Invalid escaped characters should fail and the percents should be escaped. https://www.w3.org/Bugs/Public/show_bug.cgi?id=24191",
{
"input": "http://%zz%66%a.com",
@@ -3600,18 +3766,23 @@
"base": "http://other.com/",
"failure": true
},
- "Invalid escaping should trigger the regular host error handling",
+ "Invalid escaping in hosts causes failure",
{
"input": "http://%3g%78%63%30%2e%30%32%35%30%2E.01",
"base": "http://other.com/",
"failure": true
},
- "Something that isn't exactly an IP should get treated as a host and spaces escaped",
+ "A space in a host causes failure",
{
"input": "http://192.168.0.1 hello",
"base": "http://other.com/",
"failure": true
},
+ {
+ "input": "https://x x:12",
+ "base": "about:blank",
+ "failure": true
+ },
"Fullwidth and escaped UTF-8 fullwidth should still be treated as IP",
{
"input": "http://",
@@ -3628,12 +3799,83 @@
"search": "",
"hash": ""
},
+ "Domains with empty labels",
+ {
+ "input": "http://./",
+ "base": "about:blank",
+ "href": "http://./",
+ "origin": "http://.",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": ".",
+ "hostname": ".",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://../",
+ "base": "about:blank",
+ "href": "http://../",
+ "origin": "http://..",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "..",
+ "hostname": "..",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://0..0x300/",
+ "base": "about:blank",
+ "href": "http://0..0x300/",
+ "origin": "http://0..0x300",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "0..0x300",
+ "hostname": "0..0x300",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
"Broken IPv6",
{
+ "input": "http://[www.google.com]/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
"input": "http://[google.com]",
"base": "http://other.com/",
"failure": true
},
+ {
+ "input": "http://[::1.2.3.4x]",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://[::1.2.3.]",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://[::1.2.]",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://[::1.]",
+ "base": "http://other.com/",
+ "failure": true
+ },
"Misc Unicode",
{
"input": "http://foo:💩@example.com/bar",
@@ -4176,22 +4418,91 @@
"search": "",
"hash": ""
},
- "# unknown schemes and non-ASCII domains",
+ "# unknown schemes and their hosts",
{
"input": "sc://ñ.test/",
"base": "about:blank",
- "href": "sc://xn--ida.test/",
+ "href": "sc://%C3%B1.test/",
"origin": "null",
"protocol": "sc:",
"username": "",
"password": "",
- "host": "xn--ida.test",
- "hostname": "xn--ida.test",
+ "host": "%C3%B1.test",
+ "hostname": "%C3%B1.test",
"port": "",
"pathname": "/",
"search": "",
"hash": ""
},
+ {
+ "input": "sc://\u001F!\"$&'()*+,-.;<=>^_`{|}~/",
+ "base": "about:blank",
+ "href": "sc://%1F!\"$&'()*+,-.;<=>^_`{|}~/",
+ "origin": "null",
+ "protocol": "sc:",
+ "username": "",
+ "password": "",
+ "host": "%1F!\"$&'()*+,-.;<=>^_`{|}~",
+ "hostname": "%1F!\"$&'()*+,-.;<=>^_`{|}~",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "sc://\u0000/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc:// /",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://%/",
+ "base": "about:blank",
+ "href": "sc://%/",
+ "protocol": "sc:",
+ "username": "",
+ "password": "",
+ "host": "%",
+ "hostname": "%",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "sc://[/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://\\/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://]/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "x",
+ "base": "sc://ñ",
+ "href": "sc://%C3%B1/x",
+ "origin": "null",
+ "protocol": "sc:",
+ "username": "",
+ "password": "",
+ "host": "%C3%B1",
+ "hostname": "%C3%B1",
+ "port": "",
+ "pathname": "/x",
+ "search": "",
+ "hash": ""
+ },
"# unknown schemes and backslashes",
{
"input": "sc:\\../",
@@ -4224,6 +4535,88 @@
"search": "",
"hash": ""
},
+ "# unknown scheme with bogus percent-encoding",
+ {
+ "input": "wow:%NBD",
+ "base": "about:blank",
+ "href": "wow:%NBD",
+ "origin": "null",
+ "protocol": "wow:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "%NBD",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "wow:%1G",
+ "base": "about:blank",
+ "href": "wow:%1G",
+ "origin": "null",
+ "protocol": "wow:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "%1G",
+ "search": "",
+ "hash": ""
+ },
+ "# Hosts and percent-encoding",
+ {
+ "input": "ftp://example.com%80/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "ftp://example.com%A0/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://example.com%80/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://example.com%A0/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "ftp://%e2%98%83",
+ "base": "about:blank",
+ "href": "ftp://xn--n3h/",
+ "origin": "ftp://xn--n3h",
+ "protocol": "ftp:",
+ "username": "",
+ "password": "",
+ "host": "xn--n3h",
+ "hostname": "xn--n3h",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "https://%e2%98%83",
+ "base": "about:blank",
+ "href": "https://xn--n3h/",
+ "origin": "https://xn--n3h",
+ "protocol": "https:",
+ "username": "",
+ "password": "",
+ "host": "xn--n3h",
+ "hostname": "xn--n3h",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
"# tests from jsdom/whatwg-url designed for code coverage",
{
"input": "http://127.0.0.1:10100/relative_import.html",
@@ -4371,75 +4764,1385 @@
"port": "",
"pathname": "/baz",
"search": "?qux",
- "searchParams": "",
+ "searchParams": "qux=",
"hash": "#foo%08bar"
},
- "# IPv6 compression and serialization",
+ "# IPv4 parsing (via https://github.com/nodejs/node/pull/10317)",
+ {
+ "input": "http://192.168.257",
+ "base": "http://other.com/",
+ "href": "http://192.168.1.1/",
+ "origin": "http://192.168.1.1",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "192.168.1.1",
+ "hostname": "192.168.1.1",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://192.168.257.com",
+ "base": "http://other.com/",
+ "href": "http://192.168.257.com/",
+ "origin": "http://192.168.257.com",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "192.168.257.com",
+ "hostname": "192.168.257.com",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://256",
+ "base": "http://other.com/",
+ "href": "http://0.0.1.0/",
+ "origin": "http://0.0.1.0",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "0.0.1.0",
+ "hostname": "0.0.1.0",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://256.com",
+ "base": "http://other.com/",
+ "href": "http://256.com/",
+ "origin": "http://256.com",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "256.com",
+ "hostname": "256.com",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://999999999",
+ "base": "http://other.com/",
+ "href": "http://59.154.201.255/",
+ "origin": "http://59.154.201.255",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "59.154.201.255",
+ "hostname": "59.154.201.255",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://999999999.com",
+ "base": "http://other.com/",
+ "href": "http://999999999.com/",
+ "origin": "http://999999999.com",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "999999999.com",
+ "hostname": "999999999.com",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://10000000000",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://10000000000.com",
+ "base": "http://other.com/",
+ "href": "http://10000000000.com/",
+ "origin": "http://10000000000.com",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "10000000000.com",
+ "hostname": "10000000000.com",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://4294967295",
+ "base": "http://other.com/",
+ "href": "http://255.255.255.255/",
+ "origin": "http://255.255.255.255",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "255.255.255.255",
+ "hostname": "255.255.255.255",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://4294967296",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://0xffffffff",
+ "base": "http://other.com/",
+ "href": "http://255.255.255.255/",
+ "origin": "http://255.255.255.255",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "255.255.255.255",
+ "hostname": "255.255.255.255",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://0xffffffff1",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://256.256.256.256",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://256.256.256.256.256",
+ "base": "http://other.com/",
+ "href": "http://256.256.256.256.256/",
+ "origin": "http://256.256.256.256.256",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "256.256.256.256.256",
+ "hostname": "256.256.256.256.256",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "https://0x.0x.0",
+ "base": "about:blank",
+ "href": "https://0.0.0.0/",
+ "origin": "https://0.0.0.0",
+ "protocol": "https:",
+ "username": "",
+ "password": "",
+ "host": "0.0.0.0",
+ "hostname": "0.0.0.0",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ "More IPv4 parsing (via https://github.com/jsdom/whatwg-url/issues/92)",
+ {
+ "input": "https://256.0.0.1/test",
+ "base": "about:blank",
+ "failure": true
+ },
+ "# file URLs containing percent-encoded Windows drive letters (shouldn't work)",
+ {
+ "input": "file:///C%3A/",
+ "base": "about:blank",
+ "href": "file:///C%3A/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C%3A/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file:///C%7C/",
+ "base": "about:blank",
+ "href": "file:///C%7C/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C%7C/",
+ "search": "",
+ "hash": ""
+ },
+ "# file URLs relative to other file URLs (via https://github.com/jsdom/whatwg-url/pull/60)",
+ {
+ "input": "pix/submit.gif",
+ "base": "file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html",
+ "href": "file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "..",
+ "base": "file:///C:/",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "..",
+ "base": "file:///",
+ "href": "file:///",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ "# More file URL tests by zcorpan and annevk",
+ {
+ "input": "/",
+ "base": "file:///C:/a/b",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "//d:",
+ "base": "file:///C:/a/b",
+ "href": "file:///d:",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/d:",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "//d:/..",
+ "base": "file:///C:/a/b",
+ "href": "file:///d:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/d:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "..",
+ "base": "file:///ab:/",
+ "href": "file:///",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "..",
+ "base": "file:///1:/",
+ "href": "file:///",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "",
+ "base": "file:///test?test#test",
+ "href": "file:///test?test",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?test",
+ "hash": ""
+ },
+ {
+ "input": "file:",
+ "base": "file:///test?test#test",
+ "href": "file:///test?test",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?test",
+ "hash": ""
+ },
+ {
+ "input": "?x",
+ "base": "file:///test?test#test",
+ "href": "file:///test?x",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?x",
+ "hash": ""
+ },
+ {
+ "input": "file:?x",
+ "base": "file:///test?test#test",
+ "href": "file:///test?x",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?x",
+ "hash": ""
+ },
+ {
+ "input": "#x",
+ "base": "file:///test?test#test",
+ "href": "file:///test?test#x",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?test",
+ "hash": "#x"
+ },
+ {
+ "input": "file:#x",
+ "base": "file:///test?test#test",
+ "href": "file:///test?test#x",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test",
+ "search": "?test",
+ "hash": "#x"
+ },
+ "# File URLs and many (back)slashes",
+ {
+ "input": "file:///localhost//cat",
+ "base": "about:blank",
+ "href": "file:///localhost//cat",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/localhost//cat",
+ "search": "",
+ "hash": ""
+ },
{
- "input": "http://[fe80:cd00::1257:0:211e:729c]/",
+ "input": "\\//pig",
+ "base": "file://lion/",
+ "href": "file:///pig",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/pig",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file://",
+ "base": "file://ape/",
+ "href": "file:///",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ "# Windows drive letter handling with the 'file:' base URL",
+ {
+ "input": "C|#",
+ "base": "file://host/dir/file",
+ "href": "file:///C:#",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C|?",
+ "base": "file://host/dir/file",
+ "href": "file:///C:?",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C|/",
+ "base": "file://host/dir/file",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C|\n/",
+ "base": "file://host/dir/file",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C|\\",
+ "base": "file://host/dir/file",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C",
+ "base": "file://host/dir/file",
+ "href": "file://host/dir/C",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "host",
+ "hostname": "host",
+ "port": "",
+ "pathname": "/dir/C",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "C|a",
+ "base": "file://host/dir/file",
+ "href": "file://host/dir/C|a",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "host",
+ "hostname": "host",
+ "port": "",
+ "pathname": "/dir/C|a",
+ "search": "",
+ "hash": ""
+ },
+ "# Windows drive letter quirk in the file slash state",
+ {
+ "input": "/c:/foo/bar",
+ "base": "file://host/path",
+ "href": "file:///c:/foo/bar",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/c:/foo/bar",
+ "search": "",
+ "hash": ""
+ },
+ "# Windows drive letter quirk (no host)",
+ {
+ "input": "file:/C|/",
"base": "about:blank",
- "href": "http://[fe80:cd00::1257:0:211e:729c]/",
- "origin": "http://[fe80:cd00::1257:0:211e:729c]",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file://C|/",
+ "base": "about:blank",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ "# Windows drive letter quirk with not empty host",
+ {
+ "input": "file://example.net/C:/",
+ "base": "about:blank",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file://1.2.3.4/C:/",
+ "base": "about:blank",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file://[1::8]/C:/",
+ "base": "about:blank",
+ "href": "file:///C:/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/C:/",
+ "search": "",
+ "hash": ""
+ },
+ "# file URLs without base URL by Rimas Misevičius",
+ {
+ "input": "file:",
+ "base": "about:blank",
+ "href": "file:///",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "file:?q=v",
+ "base": "about:blank",
+ "href": "file:///?q=v",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "?q=v",
+ "hash": ""
+ },
+ {
+ "input": "file:#frag",
+ "base": "about:blank",
+ "href": "file:///#frag",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": "#frag"
+ },
+ "# IPv6 tests",
+ {
+ "input": "http://[1:0::]",
+ "base": "http://example.net/",
+ "href": "http://[1::]/",
+ "origin": "http://[1::]",
"protocol": "http:",
"username": "",
"password": "",
- "host": "[fe80:cd00::1257:0:211e:729c]",
- "hostname": "[fe80:cd00::1257:0:211e:729c]",
+ "host": "[1::]",
+ "hostname": "[1::]",
"port": "",
"pathname": "/",
"search": "",
- "searchParams": "",
"hash": ""
},
- "# IPv6 compression and serialization: Compress sequences of two or more zeroes",
{
- "input": "http://[fe80:cd00:0:0:1257:0:211e:729c]/",
+ "input": "http://[0:1:2:3:4:5:6:7:8]",
+ "base": "http://example.net/",
+ "failure": true
+ },
+ {
+ "input": "https://[0::0::0]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:.0]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:0:]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:1:2:3:4:5:6:7.0.0.0.1]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:1.00.0.0.0]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:1.290.0.0.0]",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://[0:1.23.23]",
+ "base": "about:blank",
+ "failure": true
+ },
+ "# Empty host",
+ {
+ "input": "http://?",
"base": "about:blank",
- "href": "http://[fe80:cd00::1257:0:211e:729c]/",
- "origin": "http://[fe80:cd00::1257:0:211e:729c]",
+ "failure": true
+ },
+ {
+ "input": "http://#",
+ "base": "about:blank",
+ "failure": true
+ },
+ "Port overflow (2^32 + 81)",
+ {
+ "input": "http://f:4294967377/c",
+ "base": "http://example.org/",
+ "failure": true
+ },
+ "Port overflow (2^64 + 81)",
+ {
+ "input": "http://f:18446744073709551697/c",
+ "base": "http://example.org/",
+ "failure": true
+ },
+ "Port overflow (2^128 + 81)",
+ {
+ "input": "http://f:340282366920938463463374607431768211537/c",
+ "base": "http://example.org/",
+ "failure": true
+ },
+ "# Non-special-URL path tests",
+ {
+ "input": "///",
+ "base": "sc://x/",
+ "href": "sc:///",
+ "protocol": "sc:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "tftp://foobar.com/someconfig;mode=netascii",
+ "base": "about:blank",
+ "href": "tftp://foobar.com/someconfig;mode=netascii",
+ "origin": "null",
+ "protocol": "tftp:",
+ "username": "",
+ "password": "",
+ "host": "foobar.com",
+ "hostname": "foobar.com",
+ "port": "",
+ "pathname": "/someconfig;mode=netascii",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "telnet://user:pass@foobar.com:23/",
+ "base": "about:blank",
+ "href": "telnet://user:pass@foobar.com:23/",
+ "origin": "null",
+ "protocol": "telnet:",
+ "username": "user",
+ "password": "pass",
+ "host": "foobar.com:23",
+ "hostname": "foobar.com",
+ "port": "23",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "ut2004://10.10.10.10:7777/Index.ut2",
+ "base": "about:blank",
+ "href": "ut2004://10.10.10.10:7777/Index.ut2",
+ "origin": "null",
+ "protocol": "ut2004:",
+ "username": "",
+ "password": "",
+ "host": "10.10.10.10:7777",
+ "hostname": "10.10.10.10",
+ "port": "7777",
+ "pathname": "/Index.ut2",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz",
+ "base": "about:blank",
+ "href": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz",
+ "origin": "null",
+ "protocol": "redis:",
+ "username": "foo",
+ "password": "bar",
+ "host": "somehost:6379",
+ "hostname": "somehost",
+ "port": "6379",
+ "pathname": "/0",
+ "search": "?baz=bam&qux=baz",
+ "hash": ""
+ },
+ {
+ "input": "rsync://foo@host:911/sup",
+ "base": "about:blank",
+ "href": "rsync://foo@host:911/sup",
+ "origin": "null",
+ "protocol": "rsync:",
+ "username": "foo",
+ "password": "",
+ "host": "host:911",
+ "hostname": "host",
+ "port": "911",
+ "pathname": "/sup",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "git://github.com/foo/bar.git",
+ "base": "about:blank",
+ "href": "git://github.com/foo/bar.git",
+ "origin": "null",
+ "protocol": "git:",
+ "username": "",
+ "password": "",
+ "host": "github.com",
+ "hostname": "github.com",
+ "port": "",
+ "pathname": "/foo/bar.git",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "irc://myserver.com:6999/channel?passwd",
+ "base": "about:blank",
+ "href": "irc://myserver.com:6999/channel?passwd",
+ "origin": "null",
+ "protocol": "irc:",
+ "username": "",
+ "password": "",
+ "host": "myserver.com:6999",
+ "hostname": "myserver.com",
+ "port": "6999",
+ "pathname": "/channel",
+ "search": "?passwd",
+ "hash": ""
+ },
+ {
+ "input": "dns://fw.example.org:9999/foo.bar.org?type=TXT",
+ "base": "about:blank",
+ "href": "dns://fw.example.org:9999/foo.bar.org?type=TXT",
+ "origin": "null",
+ "protocol": "dns:",
+ "username": "",
+ "password": "",
+ "host": "fw.example.org:9999",
+ "hostname": "fw.example.org",
+ "port": "9999",
+ "pathname": "/foo.bar.org",
+ "search": "?type=TXT",
+ "hash": ""
+ },
+ {
+ "input": "ldap://localhost:389/ou=People,o=JNDITutorial",
+ "base": "about:blank",
+ "href": "ldap://localhost:389/ou=People,o=JNDITutorial",
+ "origin": "null",
+ "protocol": "ldap:",
+ "username": "",
+ "password": "",
+ "host": "localhost:389",
+ "hostname": "localhost",
+ "port": "389",
+ "pathname": "/ou=People,o=JNDITutorial",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "git+https://github.com/foo/bar",
+ "base": "about:blank",
+ "href": "git+https://github.com/foo/bar",
+ "origin": "null",
+ "protocol": "git+https:",
+ "username": "",
+ "password": "",
+ "host": "github.com",
+ "hostname": "github.com",
+ "port": "",
+ "pathname": "/foo/bar",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "urn:ietf:rfc:2648",
+ "base": "about:blank",
+ "href": "urn:ietf:rfc:2648",
+ "origin": "null",
+ "protocol": "urn:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "ietf:rfc:2648",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "tag:joe@example.org,2001:foo/bar",
+ "base": "about:blank",
+ "href": "tag:joe@example.org,2001:foo/bar",
+ "origin": "null",
+ "protocol": "tag:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "joe@example.org,2001:foo/bar",
+ "search": "",
+ "hash": ""
+ },
+ "# percent encoded hosts in non-special-URLs",
+ {
+ "input": "non-special://%E2%80%A0/",
+ "base": "about:blank",
+ "href": "non-special://%E2%80%A0/",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "%E2%80%A0",
+ "hostname": "%E2%80%A0",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://H%4fSt/path",
+ "base": "about:blank",
+ "href": "non-special://H%4fSt/path",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "H%4fSt",
+ "hostname": "H%4fSt",
+ "port": "",
+ "pathname": "/path",
+ "search": "",
+ "hash": ""
+ },
+ "# IPv6 in non-special-URLs",
+ {
+ "input": "non-special://[1:2:0:0:5:0:0:0]/",
+ "base": "about:blank",
+ "href": "non-special://[1:2:0:0:5::]/",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "[1:2:0:0:5::]",
+ "hostname": "[1:2:0:0:5::]",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://[1:2:0:0:0:0:0:3]/",
+ "base": "about:blank",
+ "href": "non-special://[1:2::3]/",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "[1:2::3]",
+ "hostname": "[1:2::3]",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://[1:2::3]:80/",
+ "base": "about:blank",
+ "href": "non-special://[1:2::3]:80/",
+ "protocol": "non-special:",
+ "username": "",
+ "password": "",
+ "host": "[1:2::3]:80",
+ "hostname": "[1:2::3]",
+ "port": "80",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "non-special://[:80/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "blob:https://example.com:443/",
+ "base": "about:blank",
+ "href": "blob:https://example.com:443/",
+ "protocol": "blob:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "https://example.com:443/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
+ "base": "about:blank",
+ "href": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
+ "protocol": "blob:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "d3958f5c-0777-0845-9dcf-2cb28783acaf",
+ "search": "",
+ "hash": ""
+ },
+ "Invalid IPv4 radix digits",
+ {
+ "input": "http://0177.0.0.0189",
+ "base": "about:blank",
+ "href": "http://0177.0.0.0189/",
"protocol": "http:",
"username": "",
"password": "",
- "host": "[fe80:cd00::1257:0:211e:729c]",
- "hostname": "[fe80:cd00::1257:0:211e:729c]",
+ "host": "0177.0.0.0189",
+ "hostname": "0177.0.0.0189",
"port": "",
"pathname": "/",
"search": "",
- "searchParams": "",
"hash": ""
},
- "# IPv6 compression and serialization: Compress longest sequence of zeroes",
{
- "input": "http://[fe80:0:0:1257:0:0:0:cd00]/",
+ "input": "http://0x7f.0.0.0x7g",
"base": "about:blank",
- "href": "http://[fe80:0:0:1257::cd00]/",
- "origin": "http://[fe80:0:0:1257::cd00]",
+ "href": "http://0x7f.0.0.0x7g/",
"protocol": "http:",
"username": "",
"password": "",
- "host": "[fe80:0:0:1257::cd00]",
- "hostname": "[fe80:0:0:1257::cd00]",
+ "host": "0x7f.0.0.0x7g",
+ "hostname": "0x7f.0.0.0x7g",
"port": "",
"pathname": "/",
"search": "",
- "searchParams": "",
"hash": ""
},
- "# IPv6 compression and serialization: Do not compress lone zeroes",
{
- "input": "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
+ "input": "http://0X7F.0.0.0X7G",
"base": "about:blank",
- "href": "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
- "origin": "http://[fe80:cd00:0:cde:1257:0:211e:729c]",
+ "href": "http://0x7f.0.0.0x7g/",
"protocol": "http:",
"username": "",
"password": "",
- "host": "[fe80:cd00:0:cde:1257:0:211e:729c]",
- "hostname": "[fe80:cd00:0:cde:1257:0:211e:729c]",
+ "host": "0x7f.0.0.0x7g",
+ "hostname": "0x7f.0.0.0x7g",
"port": "",
"pathname": "/",
"search": "",
- "searchParams": "",
"hash": ""
+ },
+ "Invalid IPv4 portion of IPv6 address",
+ {
+ "input": "http://[::127.0.0.0.1]",
+ "base": "about:blank",
+ "failure": true
+ },
+ "Uncompressed IPv6 addresses with 0",
+ {
+ "input": "http://[0:1:0:1:0:1:0:1]",
+ "base": "about:blank",
+ "href": "http://[0:1:0:1:0:1:0:1]/",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "[0:1:0:1:0:1:0:1]",
+ "hostname": "[0:1:0:1:0:1:0:1]",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://[1:0:1:0:1:0:1:0]",
+ "base": "about:blank",
+ "href": "http://[1:0:1:0:1:0:1:0]/",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "[1:0:1:0:1:0:1:0]",
+ "hostname": "[1:0:1:0:1:0:1:0]",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ "Percent-encoded query and fragment",
+ {
+ "input": "http://example.org/test?\u0022",
+ "base": "about:blank",
+ "href": "http://example.org/test?%22",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%22",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?\u0023",
+ "base": "about:blank",
+ "href": "http://example.org/test?#",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?\u003C",
+ "base": "about:blank",
+ "href": "http://example.org/test?%3C",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%3C",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?\u003E",
+ "base": "about:blank",
+ "href": "http://example.org/test?%3E",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%3E",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?\u2323",
+ "base": "about:blank",
+ "href": "http://example.org/test?%E2%8C%A3",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%E2%8C%A3",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?%23%23",
+ "base": "about:blank",
+ "href": "http://example.org/test?%23%23",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%23%23",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?%GH",
+ "base": "about:blank",
+ "href": "http://example.org/test?%GH",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?%GH",
+ "hash": ""
+ },
+ {
+ "input": "http://example.org/test?a#%EF",
+ "base": "about:blank",
+ "href": "http://example.org/test?a#%EF",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?a",
+ "hash": "#%EF"
+ },
+ {
+ "input": "http://example.org/test?a#%GH",
+ "base": "about:blank",
+ "href": "http://example.org/test?a#%GH",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?a",
+ "hash": "#%GH"
+ },
+ "Bad bases",
+ {
+ "input": "test-a.html",
+ "base": "a",
+ "failure": true
+ },
+ {
+ "input": "test-a-slash.html",
+ "base": "a/",
+ "failure": true
+ },
+ {
+ "input": "test-a-slash-slash.html",
+ "base": "a//",
+ "failure": true
+ },
+ {
+ "input": "test-a-colon.html",
+ "base": "a:",
+ "failure": true
+ },
+ {
+ "input": "test-a-colon-slash.html",
+ "base": "a:/",
+ "href": "a:/test-a-colon-slash.html",
+ "protocol": "a:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test-a-colon-slash.html",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "test-a-colon-slash-slash.html",
+ "base": "a://",
+ "href": "a:///test-a-colon-slash-slash.html",
+ "protocol": "a:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test-a-colon-slash-slash.html",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "test-a-colon-b.html",
+ "base": "a:b",
+ "failure": true
+ },
+ {
+ "input": "test-a-colon-slash-b.html",
+ "base": "a:/b",
+ "href": "a:/test-a-colon-slash-b.html",
+ "protocol": "a:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/test-a-colon-slash-b.html",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "test-a-colon-slash-slash-b.html",
+ "base": "a://b",
+ "href": "a://b/test-a-colon-slash-slash-b.html",
+ "protocol": "a:",
+ "username": "",
+ "password": "",
+ "host": "b",
+ "hostname": "b",
+ "port": "",
+ "pathname": "/test-a-colon-slash-slash-b.html",
+ "search": "",
+ "hash": ""
+ },
+ "Null code point in fragment",
+ {
+ "input": "http://example.org/test?a#b\u0000c",
+ "base": "about:blank",
+ "href": "http://example.org/test?a#bc",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/test",
+ "search": "?a",
+ "hash": "#bc"
}
]
diff -u -r --new-file seamonkey-2.53.1.orig/mozilla/toolkit/library/rust/Cargo.lock seamonkey-2.53.1/mozilla/toolkit/library/rust/Cargo.lock
--- seamonkey-2.53.1.orig/mozilla/toolkit/library/rust/Cargo.lock 2020-02-17 17:39:43.000000000 -0600
+++ seamonkey-2.53.1/mozilla/toolkit/library/rust/Cargo.lock 2020-02-29 21:16:23.120772244 -0600
@@ -808,7 +808,7 @@
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"nserror 0.1.0",
"nsstring 0.1.0",
- "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1154,7 +1154,7 @@
[[package]]
name = "url"
-version = "1.5.1"
+version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1383,7 +1383,7 @@
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
+"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"