|  |  | @ -32,7 +32,7 @@ impl QuoteForDigest for String { | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// Join a Vec of Display items using a separator
 |  |  |  | /// Join a Vec of Display items using a separator
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn join_vec<T : ToString>(vec : &Vec<T>, sep : &str) -> String { |  |  |  | fn join_vec<T: ToString>(vec: &Vec<T>, sep: &str) -> String { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     vec.iter() |  |  |  |     vec.iter() | 
			
		
	
		
		
			
				
					
					|  |  |  |         .map(ToString::to_string) |  |  |  |         .map(ToString::to_string) | 
			
		
	
		
		
			
				
					
					|  |  |  |         .collect::<Vec<_>>() |  |  |  |         .collect::<Vec<_>>() | 
			
		
	
	
		
		
			
				
					|  |  | @ -41,7 +41,7 @@ fn join_vec<T : ToString>(vec : &Vec<T>, sep : &str) -> String { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | enum NamedTag<'a> { |  |  |  | enum NamedTag<'a> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     Quoted(&'a str, Cow<'a, str>), |  |  |  |     Quoted(&'a str, Cow<'a, str>), | 
			
		
	
		
		
			
				
					
					|  |  |  |     Plain(&'a str, Cow<'a, str>) |  |  |  |     Plain(&'a str, Cow<'a, str>), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl Display for NamedTag<'_> { |  |  |  | impl Display for NamedTag<'_> { | 
			
		
	
	
		
		
			
				
					|  |  | @ -50,14 +50,11 @@ impl Display for NamedTag<'_> { | 
			
		
	
		
		
			
				
					
					|  |  |  |             NamedTag::Quoted(name, content) => { |  |  |  |             NamedTag::Quoted(name, content) => { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 write!(f, "{}=\"{}\"", name, content.quote_for_digest()) |  |  |  |                 write!(f, "{}=\"{}\"", name, content.quote_for_digest()) | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             NamedTag::Plain(name, content) => { |  |  |  |             NamedTag::Plain(name, content) => write!(f, "{}={}", name, content), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 write!(f, "{}={}", name, content) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | /// Helper func that parses the key-value string received from server
 |  |  |  | /// Helper func that parses the key-value string received from server
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_header_map(input: &str) -> Result<HashMap<String, String>> { |  |  |  | fn parse_header_map(input: &str) -> Result<HashMap<String, String>> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     #[derive(Debug)] |  |  |  |     #[derive(Debug)] | 
			
		
	
	
		
		
			
				
					|  |  | @ -148,7 +145,6 @@ fn parse_header_map(input: &str) -> Result<HashMap<String, String>> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(parsed) |  |  |  |     Ok(parsed) | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | /// Login attempt context
 |  |  |  | /// Login attempt context
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// All fields are borrowed to reduce runtime overhead; this struct should not be stored anywhere,
 |  |  |  | /// All fields are borrowed to reduce runtime overhead; this struct should not be stored anywhere,
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -174,25 +170,28 @@ impl<'a> AuthContext<'a> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Construct a new context with the GET verb and no payload body.
 |  |  |  |     /// Construct a new context with the GET verb and no payload body.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// See the other constructors if this does not fit your situation.
 |  |  |  |     /// See the other constructors if this does not fit your situation.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub fn new<UN, PW, UR>(username: UN, password: PW, uri: UR) -> Self |  |  |  |     pub fn new<UN, PW, UR>(username: UN, password: PW, uri: UR) -> Self | 
			
		
	
		
		
			
				
					
					|  |  |  |         where UN: Into<Cow<'a, str>>, |  |  |  |     where | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               PW: Into<Cow<'a, str>>, |  |  |  |         UN: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               UR: Into<Cow<'a, str>> |  |  |  |         PW: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         UR: Into<Cow<'a, str>>, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         Self::new_with_method(username, password, uri, Option::<&'a[u8]>::None, HttpMethod::GET) |  |  |  |         Self::new_with_method( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             username, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             password, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             uri, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Option::<&'a [u8]>::None, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             HttpMethod::GET, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Construct a new context with the POST verb and a payload body (may be None).
 |  |  |  |     /// Construct a new context with the POST verb and a payload body (may be None).
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// See the other constructors if this does not fit your situation.
 |  |  |  |     /// See the other constructors if this does not fit your situation.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub fn new_post<UN, PW, UR, BD>( |  |  |  |     pub fn new_post<UN, PW, UR, BD>(username: UN, password: PW, uri: UR, body: Option<BD>) -> Self | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         username: UN, |  |  |  |     where | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         password: PW, |  |  |  |         UN: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         uri: UR, |  |  |  |         PW: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         body: Option<BD>, |  |  |  |         UR: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     ) -> Self |  |  |  |         BD: Into<Cow<'a, [u8]>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         where UN: Into<Cow<'a, str>>, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |               PW: Into<Cow<'a, str>>, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |               UR: Into<Cow<'a, str>>, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |               BD: Into<Cow<'a, [u8]>>, |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         Self::new_with_method(username, password, uri, body, HttpMethod::POST) |  |  |  |         Self::new_with_method(username, password, uri, body, HttpMethod::POST) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					|  |  | @ -205,16 +204,17 @@ impl<'a> AuthContext<'a> { | 
			
		
	
		
		
			
				
					
					|  |  |  |         body: Option<BD>, |  |  |  |         body: Option<BD>, | 
			
		
	
		
		
			
				
					
					|  |  |  |         method: HttpMethod, |  |  |  |         method: HttpMethod, | 
			
		
	
		
		
			
				
					
					|  |  |  |     ) -> Self |  |  |  |     ) -> Self | 
			
		
	
		
		
			
				
					
					|  |  |  |         where UN: Into<Cow<'a, str>>, |  |  |  |     where | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               PW: Into<Cow<'a, str>>, |  |  |  |         UN: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               UR: Into<Cow<'a, str>>, |  |  |  |         PW: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               BD: Into<Cow<'a, [u8]>> |  |  |  |         UR: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         BD: Into<Cow<'a, [u8]>>, | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         Self { |  |  |  |         Self { | 
			
		
	
		
		
			
				
					
					|  |  |  |             username : username.into(), |  |  |  |             username: username.into(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             password : password.into(), |  |  |  |             password: password.into(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             uri : uri.into(), |  |  |  |             uri: uri.into(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             body : body.map(Into::into), |  |  |  |             body: body.map(Into::into), | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             method, |  |  |  |             method, | 
			
		
	
		
		
			
				
					
					|  |  |  |             cnonce: None, |  |  |  |             cnonce: None, | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
	
		
		
			
				
					|  |  | @ -223,7 +223,7 @@ impl<'a> AuthContext<'a> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Set cnonce to the given value
 |  |  |  |     /// Set cnonce to the given value
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub fn set_custom_cnonce<CN>(&mut self, cnonce: CN) |  |  |  |     pub fn set_custom_cnonce<CN>(&mut self, cnonce: CN) | 
			
		
	
		
		
			
				
					
					|  |  |  |     where |  |  |  |     where | 
			
		
	
		
		
			
				
					
					|  |  |  |         CN: Into<Cow<'a, str>> |  |  |  |         CN: Into<Cow<'a, str>>, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         self.cnonce = Some(cnonce.into()); |  |  |  |         self.cnonce = Some(cnonce.into()); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					|  |  | @ -269,10 +269,7 @@ impl FromStr for WwwAuthenticateHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  | impl WwwAuthenticateHeader { |  |  |  | impl WwwAuthenticateHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Generate an [`AuthorizationHeader`](struct.AuthorizationHeader.html) to be sent to the server in a new request.
 |  |  |  |     /// Generate an [`AuthorizationHeader`](struct.AuthorizationHeader.html) to be sent to the server in a new request.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// The [`self.nc`](struct.AuthorizationHeader.html#structfield.nc) field is incremented.
 |  |  |  |     /// The [`self.nc`](struct.AuthorizationHeader.html#structfield.nc) field is incremented.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub fn respond( |  |  |  |     pub fn respond(&mut self, secrets: &AuthContext) -> Result<AuthorizationHeader> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         &mut self, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         secrets: &AuthContext, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     ) -> Result<AuthorizationHeader> { |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         AuthorizationHeader::from_prompt(self, secrets) |  |  |  |         AuthorizationHeader::from_prompt(self, secrets) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -357,7 +354,10 @@ impl Display for WwwAuthenticateHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Plain("stale", "true".into())); |  |  |  |             entries.push(NamedTag::Plain("stale", "true".into())); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         entries.push(NamedTag::Plain("algorithm", self.algorithm.to_string().into())); |  |  |  |         entries.push(NamedTag::Plain( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             "algorithm", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             self.algorithm.to_string().into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )); | 
			
		
	
		
		
			
				
					
					|  |  |  |         entries.push(NamedTag::Quoted("nonce", (&self.nonce).into())); |  |  |  |         entries.push(NamedTag::Quoted("nonce", (&self.nonce).into())); | 
			
		
	
		
		
			
				
					
					|  |  |  |         if let Some(ref opaque) = self.opaque { |  |  |  |         if let Some(ref opaque) = self.opaque { | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Quoted("opaque", (opaque).into())); |  |  |  |             entries.push(NamedTag::Quoted("opaque", (opaque).into())); | 
			
		
	
	
		
		
			
				
					|  |  | @ -369,7 +369,9 @@ impl Display for WwwAuthenticateHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         for (i, e) in entries.iter().enumerate() { |  |  |  |         for (i, e) in entries.iter().enumerate() { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if i > 0 { f.write_str(", ")?; } |  |  |  |             if i > 0 { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 f.write_str(", ")?; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             f.write_str(&e.to_string())?; |  |  |  |             f.write_str(&e.to_string())?; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -385,15 +387,15 @@ impl Display for WwwAuthenticateHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  | #[derive(Debug, PartialEq, Clone)] |  |  |  | #[derive(Debug, PartialEq, Clone)] | 
			
		
	
		
		
			
				
					
					|  |  |  | pub struct AuthorizationHeader { |  |  |  | pub struct AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Authorization realm
 |  |  |  |     /// Authorization realm
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub realm : String, |  |  |  |     pub realm: String, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     /// Server nonce
 |  |  |  |     /// Server nonce
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub nonce: String, |  |  |  |     pub nonce: String, | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Server opaque
 |  |  |  |     /// Server opaque
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub opaque: Option<String>, |  |  |  |     pub opaque: Option<String>, | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Flag that userhash was used
 |  |  |  |     /// Flag that userhash was used
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub userhash : bool, |  |  |  |     pub userhash: bool, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     /// Hash algorithm
 |  |  |  |     /// Hash algorithm
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub algorithm : Algorithm, |  |  |  |     pub algorithm: Algorithm, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     /// Computed digest
 |  |  |  |     /// Computed digest
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub response: String, |  |  |  |     pub response: String, | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Username or hash (owned because of the computed hash)
 |  |  |  |     /// Username or hash (owned because of the computed hash)
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -428,7 +430,6 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |         prompt: &mut WwwAuthenticateHeader, |  |  |  |         prompt: &mut WwwAuthenticateHeader, | 
			
		
	
		
		
			
				
					
					|  |  |  |         context: &AuthContext, |  |  |  |         context: &AuthContext, | 
			
		
	
		
		
			
				
					
					|  |  |  |     ) -> Result<AuthorizationHeader> { |  |  |  |     ) -> Result<AuthorizationHeader> { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let qop = match &prompt.qop { |  |  |  |         let qop = match &prompt.qop { | 
			
		
	
		
		
			
				
					
					|  |  |  |             None => None, |  |  |  |             None => None, | 
			
		
	
		
		
			
				
					
					|  |  |  |             Some(vec) => { |  |  |  |             Some(vec) => { | 
			
		
	
	
		
		
			
				
					|  |  | @ -453,11 +454,15 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |             opaque: prompt.opaque.clone(), |  |  |  |             opaque: prompt.opaque.clone(), | 
			
		
	
		
		
			
				
					
					|  |  |  |             userhash: prompt.userhash, |  |  |  |             userhash: prompt.userhash, | 
			
		
	
		
		
			
				
					
					|  |  |  |             algorithm: prompt.algorithm, |  |  |  |             algorithm: prompt.algorithm, | 
			
		
	
		
		
			
				
					
					|  |  |  |             response : String::default(), |  |  |  |             response: String::default(), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             username : String::default(), |  |  |  |             username: String::default(), | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             uri: context.uri.as_ref().into(), |  |  |  |             uri: context.uri.as_ref().into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |             qop, |  |  |  |             qop, | 
			
		
	
		
		
			
				
					
					|  |  |  |             cnonce: context.cnonce.as_ref().map(AsRef::as_ref).map(ToOwned::to_owned), // Will be generated if needed, if build_hash is set and this is None
 |  |  |  |             cnonce: context | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .cnonce | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .as_ref() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .map(AsRef::as_ref) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .map(ToOwned::to_owned), // Will be generated if needed, if build_hash is set and this is None
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             nc: prompt.nc, |  |  |  |             nc: prompt.nc, | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -479,8 +484,7 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// - cnonce (if it was None before)
 |  |  |  |     /// - cnonce (if it was None before)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// - username copied from context
 |  |  |  |     /// - username copied from context
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// - response
 |  |  |  |     /// - response
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub fn digest(&mut self, context : &AuthContext) |  |  |  |     pub fn digest(&mut self, context: &AuthContext) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // figure out which QOP option to use
 |  |  |  |         // figure out which QOP option to use
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         let qop_algo = match self.qop { |  |  |  |         let qop_algo = match self.qop { | 
			
		
	
		
		
			
				
					
					|  |  |  |             None => QopAlgo::NONE, |  |  |  |             None => QopAlgo::NONE, | 
			
		
	
	
		
		
			
				
					|  |  | @ -492,9 +496,7 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |                     QopAlgo::AUTH |  |  |  |                     QopAlgo::AUTH | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             Some(Qop::AUTH) => { |  |  |  |             Some(Qop::AUTH) => QopAlgo::AUTH, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 QopAlgo::AUTH |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         let h = &self.algorithm; |  |  |  |         let h = &self.algorithm; | 
			
		
	
	
		
		
			
				
					|  |  | @ -554,7 +556,7 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |                     username = context.username, |  |  |  |                     username = context.username, | 
			
		
	
		
		
			
				
					
					|  |  |  |                     realm = self.realm |  |  |  |                     realm = self.realm | 
			
		
	
		
		
			
				
					
					|  |  |  |                 ) |  |  |  |                 ) | 
			
		
	
		
		
			
				
					
					|  |  |  |                     .as_bytes(), |  |  |  |                 .as_bytes(), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             ) |  |  |  |             ) | 
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             context.username.as_ref().to_owned() |  |  |  |             context.username.as_ref().to_owned() | 
			
		
	
	
		
		
			
				
					|  |  | @ -653,7 +655,7 @@ impl AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if auth.qop.is_some() { |  |  |  |         if auth.qop.is_some() { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if !auth.cnonce.is_some() { |  |  |  |             if !auth.cnonce.is_some() { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 return Err(MissingRequired("cnonce", input.into())) |  |  |  |                 return Err(MissingRequired("cnonce", input.into())); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             // cnonce must not be set if qop is not given, clear it.
 |  |  |  |             // cnonce must not be set if qop is not given, clear it.
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -676,9 +678,15 @@ impl Display for AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |         entries.push(NamedTag::Quoted("uri", (&self.uri).into())); |  |  |  |         entries.push(NamedTag::Quoted("uri", (&self.uri).into())); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if self.qop.is_some() && self.cnonce.is_some() { |  |  |  |         if self.qop.is_some() && self.cnonce.is_some() { | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Plain("qop", self.qop.as_ref().unwrap().to_string().into())); |  |  |  |             entries.push(NamedTag::Plain( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "qop", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.qop.as_ref().unwrap().to_string().into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             )); | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Plain("nc", format!("{:08x}", self.nc).into())); |  |  |  |             entries.push(NamedTag::Plain("nc", format!("{:08x}", self.nc).into())); | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Quoted("cnonce", self.cnonce.as_ref().unwrap().into())); |  |  |  |             entries.push(NamedTag::Quoted( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "cnonce", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.cnonce.as_ref().unwrap().into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             )); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         entries.push(NamedTag::Quoted("response", (&self.response).into())); |  |  |  |         entries.push(NamedTag::Quoted("response", (&self.response).into())); | 
			
		
	
	
		
		
			
				
					|  |  | @ -689,7 +697,10 @@ impl Display for AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // algorithm can be omitted if it is the default value (or in legacy compat mode)
 |  |  |  |         // algorithm can be omitted if it is the default value (or in legacy compat mode)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if self.qop.is_some() || self.algorithm.algo != AlgorithmType::MD5 { |  |  |  |         if self.qop.is_some() || self.algorithm.algo != AlgorithmType::MD5 { | 
			
		
	
		
		
			
				
					
					|  |  |  |             entries.push(NamedTag::Plain("algorithm", self.algorithm.to_string().into())); |  |  |  |             entries.push(NamedTag::Plain( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "algorithm", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.algorithm.to_string().into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             )); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if self.userhash { |  |  |  |         if self.userhash { | 
			
		
	
	
		
		
			
				
					|  |  | @ -697,7 +708,9 @@ impl Display for AuthorizationHeader { | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         for (i, e) in entries.iter().enumerate() { |  |  |  |         for (i, e) in entries.iter().enumerate() { | 
			
		
	
		
		
			
				
					
					|  |  |  |             if i > 0 { f.write_str(", ")?; } |  |  |  |             if i > 0 { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 f.write_str(", ")?; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             f.write_str(&e.to_string())?; |  |  |  |             f.write_str(&e.to_string())?; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -756,8 +769,7 @@ mod tests { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     #[test] |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |     fn test_parse_header_map2() |  |  |  |     fn test_parse_header_map2() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         let src = r#"realm="api@example.org""#; |  |  |  |         let src = r#"realm="api@example.org""#; | 
			
		
	
		
		
			
				
					
					|  |  |  |         let map = parse_header_map(src).unwrap(); |  |  |  |         let map = parse_header_map(src).unwrap(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert_eq!(map.get("realm").unwrap(), "api@example.org"); |  |  |  |         assert_eq!(map.get("realm").unwrap(), "api@example.org"); | 
			
		
	
	
		
		
			
				
					|  |  | @ -836,38 +848,47 @@ mod tests { | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert_eq!( |  |  |  |         assert_eq!( | 
			
		
	
		
		
			
				
					
					|  |  |  | r#"Digest realm="api@example.org", |  |  |  |             r#"Digest realm="api@example.org", | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   qop="auth", |  |  |  |   qop="auth", | 
			
		
	
		
		
			
				
					
					|  |  |  |   domain="/my/nice/url /login /logout", |  |  |  |   domain="/my/nice/url /login /logout", | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=SHA-512-256, |  |  |  |   algorithm=SHA-512-256, | 
			
		
	
		
		
			
				
					
					|  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", |  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", | 
			
		
	
		
		
			
				
					
					|  |  |  |   opaque="HRPCssKJSGjCrkzDg8OhwpzCiGPChXYjwrI2QmXDnsOS", |  |  |  |   opaque="HRPCssKJSGjCrkzDg8OhwpzCiGPChXYjwrI2QmXDnsOS", | 
			
		
	
		
		
			
				
					
					|  |  |  |   charset=UTF-8, |  |  |  |   charset=UTF-8, | 
			
		
	
		
		
			
				
					
					|  |  |  |   userhash=true"#.replace(",\n  ", ", "), hdr.to_string()); |  |  |  |   userhash=true"# | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .replace(",\n  ", ", "), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             hdr.to_string() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         hdr.stale=true; |  |  |  |         hdr.stale = true; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         hdr.userhash=false; |  |  |  |         hdr.userhash = false; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         hdr.opaque = None; |  |  |  |         hdr.opaque = None; | 
			
		
	
		
		
			
				
					
					|  |  |  |         hdr.qop = None; |  |  |  |         hdr.qop = None; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert_eq!( |  |  |  |         assert_eq!( | 
			
		
	
		
		
			
				
					
					|  |  |  | r#"Digest realm="api@example.org", |  |  |  |             r#"Digest realm="api@example.org", | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   domain="/my/nice/url /login /logout", |  |  |  |   domain="/my/nice/url /login /logout", | 
			
		
	
		
		
			
				
					
					|  |  |  |   stale=true, |  |  |  |   stale=true, | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=SHA-512-256, |  |  |  |   algorithm=SHA-512-256, | 
			
		
	
		
		
			
				
					
					|  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", |  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", | 
			
		
	
		
		
			
				
					
					|  |  |  |   charset=UTF-8"#.replace(",\n  ", ", "), hdr.to_string()); |  |  |  |   charset=UTF-8"# | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .replace(",\n  ", ", "), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             hdr.to_string() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         hdr.qop = Some(vec![Qop::AUTH, Qop::AUTH_INT]); |  |  |  |         hdr.qop = Some(vec![Qop::AUTH, Qop::AUTH_INT]); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert_eq!( |  |  |  |         assert_eq!( | 
			
		
	
		
		
			
				
					
					|  |  |  | r#"Digest realm="api@example.org", |  |  |  |             r#"Digest realm="api@example.org", | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   qop="auth, auth-int", |  |  |  |   qop="auth, auth-int", | 
			
		
	
		
		
			
				
					
					|  |  |  |   domain="/my/nice/url /login /logout", |  |  |  |   domain="/my/nice/url /login /logout", | 
			
		
	
		
		
			
				
					
					|  |  |  |   stale=true, |  |  |  |   stale=true, | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=SHA-512-256, |  |  |  |   algorithm=SHA-512-256, | 
			
		
	
		
		
			
				
					
					|  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", |  |  |  |   nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", | 
			
		
	
		
		
			
				
					
					|  |  |  |   charset=UTF-8"#.replace(",\n  ", ", "), hdr.to_string()); |  |  |  |   charset=UTF-8"# | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .replace(",\n  ", ", "), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             hdr.to_string() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     #[test] |  |  |  |     #[test] | 
			
		
	
	
		
		
			
				
					|  |  | @ -949,7 +970,7 @@ Digest username="Mufasa", | 
			
		
	
		
		
			
				
					
					|  |  |  |   response="1949323746fe6a43ef61f9606e7febea", |  |  |  |   response="1949323746fe6a43ef61f9606e7febea", | 
			
		
	
		
		
			
				
					
					|  |  |  |   opaque="5ccc069c403ebaf9f0171e9517f40e41" |  |  |  |   opaque="5ccc069c403ebaf9f0171e9517f40e41" | 
			
		
	
		
		
			
				
					
					|  |  |  | "# |  |  |  | "# | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .trim() |  |  |  |             .trim() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         ); |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Try round trip
 |  |  |  |         // Try round trip
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -992,7 +1013,7 @@ Digest username="Mufasa", | 
			
		
	
		
		
			
				
					
					|  |  |  |   opaque="5ccc069c403ebaf9f0171e9517f40e41", |  |  |  |   opaque="5ccc069c403ebaf9f0171e9517f40e41", | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=MD5 |  |  |  |   algorithm=MD5 | 
			
		
	
		
		
			
				
					
					|  |  |  | "# |  |  |  | "# | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .trim() |  |  |  |             .trim() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         ); |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Try round trip
 |  |  |  |         // Try round trip
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -1033,7 +1054,7 @@ Digest username="Mufasa", | 
			
		
	
		
		
			
				
					
					|  |  |  |   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", |  |  |  |   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=MD5 |  |  |  |   algorithm=MD5 | 
			
		
	
		
		
			
				
					
					|  |  |  | "# |  |  |  | "# | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .trim() |  |  |  |             .trim() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         ); |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Try round trip
 |  |  |  |         // Try round trip
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -1085,7 +1106,7 @@ Digest username="Mufasa", | 
			
		
	
		
		
			
				
					
					|  |  |  |   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", |  |  |  |   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", | 
			
		
	
		
		
			
				
					
					|  |  |  |   algorithm=SHA-256 |  |  |  |   algorithm=SHA-256 | 
			
		
	
		
		
			
				
					
					|  |  |  | "# |  |  |  | "# | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .trim() |  |  |  |             .trim() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         ); |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Try round trip
 |  |  |  |         // Try round trip
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |