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::().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, start_position: usize, encoding: EncodingOverride, + custom_encoding: Option Cow<[u8]>>>>, +} + +struct SilentDebug(T); + +impl fmt::Debug for SilentDebug { + 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(&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 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 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 { /// 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 { /// Parse a host: either an IPv6 address in [] square brackets, or a domain. /// - /// https://url.spec.whatwg.org/#host-parsing + /// pub fn parse(input: &str) -> Result { if input.starts_with('[') { if !input.ends_with(']') { @@ -158,6 +160,23 @@ Ok(Host::Domain(domain.into())) } } + + // + pub fn parse_opaque(input: &str) -> Result { + 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> fmt::Display for Host { @@ -309,8 +328,8 @@ } } -/// https://url.spec.whatwg.org/#ipv4-number-parser -fn parse_ipv4number(mut input: &str) -> Result { +/// +fn parse_ipv4number(mut input: &str) -> Result, ()> { 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 +/// fn parse_ipv4addr(input: &str) -> ParseResult> { if input.is_empty() { return Ok(None) @@ -344,15 +379,19 @@ return Ok(None); } let mut numbers: Vec = 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 +/// fn parse_ipv6addr(input: &str) -> ParseResult { 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::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(input: &str, iter: I) -> Result 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::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 () /// /// 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) -> 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 URL’s 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>(path: P) -> Result { 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>(path: P) -> Result { 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 { 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) -> Result { 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, } 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 #[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 + /// 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 + /// 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 = Result; 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(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 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 { - 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 { + 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::() != "//" }); @@ -371,6 +461,7 @@ } fn parse_file(mut self, input: Input, mut base_file_url: Option<&Url>) -> ParseResult { + 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::() != "//" }); @@ -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) { 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": "Can’t 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 it’s 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 it’s 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::().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::().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::().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://Go.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://0Xc0.0250.01", @@ -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"