Parse httpOnly cookies from cookie storage

This commit is contained in:
Fabrice Reix 2021-05-25 13:43:34 +02:00
parent 58c7b33ebc
commit 58e11a4acc
3 changed files with 38 additions and 28 deletions

View File

@ -27,6 +27,7 @@ use super::core::*;
use super::options::ClientOptions;
use super::request::*;
use super::response::*;
use std::str::FromStr;
use url::Url;
#[derive(Clone, Debug, PartialEq, Eq)]
@ -452,25 +453,12 @@ impl Client {
let list = self.handle.cookies().unwrap();
let mut cookies = vec![];
for cookie in list.iter() {
let line = str::from_utf8(cookie).unwrap().to_string();
let fields: Vec<&str> = line.split('\t').collect();
let domain = fields.get(0).unwrap().to_string();
let include_subdomain = fields.get(1).unwrap().to_string();
let path = fields.get(2).unwrap().to_string();
let https = fields.get(3).unwrap().to_string();
let expires = fields.get(4).unwrap().to_string();
let name = fields.get(5).unwrap().to_string();
let value = fields.get(6).unwrap().to_string();
cookies.push(Cookie {
domain,
include_subdomain,
path,
https,
expires,
name,
value,
});
let line = str::from_utf8(cookie).unwrap();
if let Ok(cookie) = Cookie::from_str(line) {
cookies.push(cookie);
} else {
eprintln!("warning: line <{}> can not be parsed as cookie", line);
}
}
cookies
}
@ -545,7 +533,6 @@ pub fn all_cookies(cookie_storage: Vec<Cookie>, request: &Request) -> Vec<Reques
///
pub fn match_cookie(cookie: &Cookie, url: &str) -> bool {
// is it possible to do it with libcurl?
let url = Url::parse(url).expect("valid url");
if let Some(domain) = url.domain() {
if cookie.include_subdomain == "FALSE" {
@ -658,6 +645,7 @@ mod tests {
expires: "".to_string(),
name: "".to_string(),
value: "".to_string(),
http_only: false,
};
assert_eq!(match_cookie(&cookie, "http://example.com/toto"), true);
assert_eq!(match_cookie(&cookie, "http://sub.example.com/tata"), false);
@ -671,6 +659,7 @@ mod tests {
expires: "".to_string(),
name: "".to_string(),
value: "".to_string(),
http_only: false,
};
assert_eq!(match_cookie(&cookie, "http://example.com/toto"), true);
assert_eq!(match_cookie(&cookie, "http://sub.example.com/toto"), true);

View File

@ -34,6 +34,7 @@ pub struct Cookie {
pub expires: String,
pub name: String,
pub value: String,
pub http_only: bool,
}
impl fmt::Display for Header {
@ -46,7 +47,8 @@ impl fmt::Display for Cookie {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}\t{}\t{}\t{}\t{}\t{}\t{}",
"{}{}\t{}\t{}\t{}\t{}\t{}\t{}",
if self.http_only { "#HttpOnly_" } else { "" },
self.domain,
self.include_subdomain,
self.path,
@ -66,8 +68,12 @@ impl FromStr for Cookie {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let tokens = s.split_ascii_whitespace().collect::<Vec<&str>>();
let domain = if let Some(&v) = tokens.get(0) {
v.to_string()
let (http_only, domain) = if let Some(&v) = tokens.get(0) {
if let Some(domain) = v.strip_prefix("#HttpOnly_") {
(true, domain.to_string())
} else {
(false, v.to_string())
}
} else {
return Err(ParseCookieError {});
};
@ -99,7 +105,7 @@ impl FromStr for Cookie {
let value = if let Some(&v) = tokens.get(6) {
v.to_string()
} else {
return Err(ParseCookieError {});
"".to_string()
};
Ok(Cookie {
domain,
@ -109,6 +115,7 @@ impl FromStr for Cookie {
expires,
name,
value,
http_only,
})
}
}
@ -136,9 +143,7 @@ mod tests {
#[test]
pub fn parse_cookie_from_str() {
assert_eq!(
Cookie::from_str("httpbin.org\tFALSE\t/\tFALSE\t0\tcookie1\tvalueA")
.ok()
.unwrap(),
Cookie::from_str("httpbin.org\tFALSE\t/\tFALSE\t0\tcookie1\tvalueA").unwrap(),
Cookie {
domain: "httpbin.org".to_string(),
include_subdomain: "FALSE".to_string(),
@ -146,9 +151,24 @@ mod tests {
https: "FALSE".to_string(),
expires: "0".to_string(),
name: "cookie1".to_string(),
value: "valueA".to_string()
value: "valueA".to_string(),
http_only: false,
}
);
assert_eq!(
Cookie::from_str("localhost\tFALSE\t/\tFALSE\t1\tcookie2\t").unwrap(),
Cookie {
domain: "localhost".to_string(),
include_subdomain: "FALSE".to_string(),
path: "/".to_string(),
https: "FALSE".to_string(),
expires: "1".to_string(),
name: "cookie2".to_string(),
value: "".to_string(),
http_only: false,
}
);
assert_eq!(Cookie::from_str("xxx").err().unwrap(), ParseCookieError {});
}
}

View File

@ -791,6 +791,7 @@ fn test_cookie_storage() {
expires: "0".to_string(),
name: "cookie2".to_string(),
value: "valueA".to_string(),
http_only: false
}
);