Skip to content

Commit

Permalink
Allow the percent character in the userinfo of an authority. (#269)
Browse files Browse the repository at this point in the history
The username and password in an authority are percent-encoded.
  • Loading branch information
arsing authored and seanmonstar committed Oct 30, 2018
1 parent 62f241e commit 638928f
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/uri/authority.rs
Expand Up @@ -91,6 +91,7 @@ impl Authority {
let mut colon_cnt = 0;
let mut start_bracket = false;
let mut end_bracket = false;
let mut has_percent = false;
let mut end = s.len();
let mut at_sign_pos = None;

Expand Down Expand Up @@ -118,7 +119,17 @@ impl Authority {
// Those weren't a port colon, but part of the
// userinfo, so it needs to be forgotten.
colon_cnt = 0;

has_percent = false;
}
0 if b == b'%' => {
// Per https://tools.ietf.org/html/rfc3986#section-3.2.1 and
// https://url.spec.whatwg.org/#authority-state
// the userinfo can have a percent-encoded username and password,
// so record that a `%` was found. If this turns out to be
// part of the userinfo, this flag will be cleared.
// If the flag hasn't been cleared at the end, that means this
// was part of the hostname, and will fail with an error.
has_percent = true;
}
0 => {
return Err(ErrorKind::InvalidUriChar.into());
Expand All @@ -141,6 +152,11 @@ impl Authority {
return Err(ErrorKind::InvalidAuthority.into());
}

if has_percent {
// Something after the userinfo has a `%`, so reject it.
return Err(ErrorKind::InvalidAuthority.into());
}

Ok(end)
}

Expand Down Expand Up @@ -564,4 +580,20 @@ mod tests {
assert!(authority > "abc.com".to_string());
assert!("abc.com".to_string() < authority);
}

#[test]
fn allows_percent_in_userinfo() {
let authority_str = "a%2f:b%2f@example.com";
let authority: Authority = authority_str.parse().unwrap();
assert_eq!(authority, authority_str);
}

#[test]
fn rejects_percent_in_hostname() {
let err = Authority::parse_non_empty(b"example%2f.com").unwrap_err();
assert_eq!(err.0, ErrorKind::InvalidAuthority);

let err = Authority::parse_non_empty(b"a%2f:b%2f@example%2f.com").unwrap_err();
assert_eq!(err.0, ErrorKind::InvalidAuthority);
}
}

0 comments on commit 638928f

Please sign in to comment.