diff --git a/faup/src/grammar.pest b/faup/src/grammar.pest index a16eb65..13b13b9 100644 --- a/faup/src/grammar.pest +++ b/faup/src/grammar.pest @@ -5,12 +5,14 @@ username = ${ (!(":" | "@" | WHITE_SPACE) ~ ANY)+ } password = ${ (!("@" | WHITE_SPACE) ~ ANY)+ } userinfo = ${ username ~ (":" ~ password)? ~ "@" } -host = ${ ipv4 | ipv6 | hostname } +// this rule is used to check if the hostname is actually +// a valid ipv4 address as hostname rule matches any ipv4 +ipv4 = ${ SOI ~ (ASCII_DIGIT{1, 3} ~ "."){3} ~ ASCII_DIGIT{1, 3} ~ EOI } +host = ${ ipv6 | hostname } domain_part = ${ (!(":" | "?" | "/" | "#" | "." | WHITE_SPACE) ~ ANY)+ } tld = ${ (!(":" | "?" | "/" | "#" | WHITE_SPACE) ~ ANY)+ } hostname = ${ (((domain_part ~ ".")+ ~ tld) | domain_part) } -ipv4 = ${ (ASCII_DIGIT{1, 3} ~ "."){3} ~ ASCII_DIGIT{1, 3} } ipv6 = ${ "[" ~ (ASCII_HEX_DIGIT{,4} ~ ":"){2, 7} ~ ASCII_HEX_DIGIT{,4} ~ "]" } encoded_char = ${ "%" ~ ASCII_DIGIT{2} } diff --git a/faup/src/lib.rs b/faup/src/lib.rs index a23bd0e..69ed4ac 100644 --- a/faup/src/lib.rs +++ b/faup/src/lib.rs @@ -597,15 +597,18 @@ impl<'url> Url<'url> { let host_pair = p.into_inner().next().unwrap(); match host_pair.as_rule() { Rule::hostname => { - host = Some(Host::Hostname(Hostname::from_str(host_pair.as_str()))) - } - Rule::ipv4 => { - host = Some( - Ipv4Addr::from_str(host_pair.as_str()) - .map(IpAddr::from) - .map(Host::Ip) - .map_err(|_| Error::InvalidIPv4)?, - ); + if let Ok(ipv4) = + UrlParser::parse(Rule::ipv4, host_pair.as_str()).map(|p| p.as_str()) + { + host = Some( + Ipv4Addr::from_str(ipv4) + .map(IpAddr::from) + .map(Host::Ip) + .map_err(|_| Error::InvalidIPv4)?, + ); + } else { + host = Some(Host::Hostname(Hostname::from_str(host_pair.as_str()))) + } } Rule::ipv6 => { @@ -984,6 +987,7 @@ mod tests { "http://full.custom-tld.test.b32.i2p", "https://alex:adore-la-quiche@avec-des-œufs.be#et-des-lardons", "https://%40lex:adore:la:quiche@%61vec-des-œufs.be/../../..some/directory/traversal/../#et-des-lardons", + "https://44.129.205.92.host.secureserver.net", ]; for url in test_urls {