web2pdf_lib/
util.rs

1use std::fmt;
2
3use chromiumoxide::cdp::browser_protocol::network::{CookieParam, CookieSameSite, TimeSinceEpoch};
4
5use crate::Result;
6
7/// Error for when parsing a cookie file
8#[derive(Debug, Clone)]
9struct CookieFileParseError {
10    error_message: String,
11}
12impl CookieFileParseError {
13    fn new(error_message: String) -> CookieFileParseError {
14        CookieFileParseError {
15            error_message: error_message,
16        }
17    }
18}
19impl fmt::Display for CookieFileParseError {
20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21        write!(f, "Error parsing Cookie file: {}", self.error_message)
22    }
23}
24impl std::error::Error for CookieFileParseError {
25    fn description(&self) -> &str {
26        &self.error_message
27    }
28}
29
30/// Parse a cookie file
31/// As specified in https://curl.se/docs/http-cookies.html
32///
33/// # Arguments
34/// * `file_contents` - The contents of the cookie file
35///
36/// # Returns
37/// * A vector of CookieParam structs
38pub fn parse_cookie_file(file_contents: &str) -> Result<Vec<CookieParam>> {
39    let mut cookies: Vec<CookieParam> = Vec::new();
40    // https://curl.se/docs/http-cookies.html
41    for line_unchanged in file_contents.lines() {
42        let mut cookie_builder = CookieParam::builder().source_port(-1);
43        let mut line = line_unchanged;
44
45        if line.starts_with("#HttpOnly_") {
46            line = &line[10..];
47            cookie_builder = cookie_builder.http_only(true);
48        } else if line.starts_with("#") {
49            continue;
50        }
51
52        let cookie_args: Vec<&str> = line.split('\t').collect();
53        if cookie_args.len() != 7 {
54            tracing::error!(
55                "Error parsing cookie line (Wrong number of arguments): '{}'",
56                line
57            );
58            return Err(Box::new(CookieFileParseError::new(format!(
59                "Error parsing cookie line (Wrong number of arguments): '{}'",
60                line
61            ))));
62        }
63
64        cookie_builder = cookie_builder
65            .domain(cookie_args[0].to_string())
66            .same_site(if cookie_args[1].eq("TRUE") {
67                CookieSameSite::Strict
68            } else {
69                CookieSameSite::Lax
70            })
71            .path(cookie_args[2].to_string())
72            .http_only(cookie_args[3].eq("TRUE"))
73            .expires(TimeSinceEpoch::new(match cookie_args[4].parse::<f64>() {
74                Ok(value) => value,
75                Err(err) => {
76                    return Err(Box::new(CookieFileParseError::new(format!(
77                        "Error parsing cookie line: '{}' Could not convert time: '{}'",
78                        line, err
79                    ))));
80                }
81            }))
82            .name(cookie_args[5].to_string())
83            .value(cookie_args[6].to_string());
84
85        let cookie = cookie_builder.build()?;
86
87        tracing::trace!("Parsed cookie line: {:?} to {:?}", line_unchanged, cookie);
88
89        cookies.push(cookie);
90    }
91    Ok(cookies)
92}