decrypt_cookies/chromium/items/cookie/
mod.rs

1use chrono::prelude::*;
2
3use self::cookie_entities::cookies;
4use super::I64ToChromiumDateTime;
5use crate::browser::cookies::{CookiesInfo, SameSite};
6
7pub mod cookie_dao;
8pub mod cookie_entities;
9
10#[derive(Clone)]
11#[derive(Debug)]
12#[derive(PartialEq, Eq, PartialOrd, Ord)]
13#[non_exhaustive]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[cfg_attr(feature = "ffi", repr(C))]
16pub struct ChromiumCookie {
17    pub creation_utc: Option<DateTime<Utc>>,
18    pub host_key: String,
19    pub top_frame_site_key: String,
20    pub name: String,
21    pub value: String,
22    pub decrypted_value: Option<String>,
23    pub path: String,
24    /// <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires>
25    pub expires_utc: Option<DateTime<Utc>>,
26    pub is_secure: bool,
27    pub is_httponly: bool,
28    pub last_access_utc: Option<DateTime<Utc>>,
29    pub has_expires: bool,
30    pub is_persistent: bool,
31    pub priority: i32,
32    pub same_site: SameSite,
33    pub source_scheme: i32,
34    pub source_port: i32,
35    pub last_update_utc: Option<DateTime<Utc>>,
36}
37
38#[cfg(feature = "reqwest")]
39impl TryFrom<ChromiumCookie> for reqwest::header::HeaderValue {
40    type Error = reqwest::header::InvalidHeaderValue;
41
42    fn try_from(value: ChromiumCookie) -> Result<Self, Self::Error> {
43        Self::from_str(&value.set_cookie_header())
44    }
45}
46#[cfg(feature = "reqwest")]
47impl FromIterator<ChromiumCookie> for reqwest::cookie::Jar {
48    fn from_iter<T: IntoIterator<Item = ChromiumCookie>>(iter: T) -> Self {
49        let jar = Self::default();
50        for cookie in iter {
51            let set_cookie = cookie.set_cookie_header();
52            if let Ok(url) = reqwest::Url::parse(&cookie.url()) {
53                jar.add_cookie_str(&set_cookie, &url);
54            }
55        }
56        jar
57    }
58}
59
60impl CookiesInfo for ChromiumCookie {
61    fn name(&self) -> &str {
62        &self.name
63    }
64    fn path(&self) -> &str {
65        &self.path
66    }
67    fn value(&self) -> &str {
68        self.decrypted_value
69            .as_ref()
70            .unwrap_or(&self.value)
71    }
72    fn domain(&self) -> &str {
73        &self.host_key
74    }
75    fn expiry(&self) -> Option<String> {
76        self.expires_utc
77            .map(|expir| expir.to_rfc2822())
78    }
79    fn is_secure(&self) -> bool {
80        self.is_secure
81    }
82    fn same_site(&self) -> SameSite {
83        self.same_site
84    }
85    fn is_http_only(&self) -> bool {
86        self.is_httponly
87    }
88
89    fn creation(&self) -> Option<DateTime<Utc>> {
90        self.creation_utc
91    }
92
93    fn expires(&self) -> Option<DateTime<Utc>> {
94        self.expires_utc
95    }
96}
97
98impl From<cookies::Model> for ChromiumCookie {
99    fn from(value: cookies::Model) -> Self {
100        Self {
101            creation_utc: value
102                .creation_utc
103                .micros_to_chromium_utc(),
104            host_key: value.host_key,
105            top_frame_site_key: value.top_frame_site_key,
106            name: value.name,
107            value: value.value,
108            decrypted_value: None,
109            path: value.path,
110            expires_utc: value
111                .expires_utc
112                .micros_to_chromium_utc(),
113            is_secure: value.is_secure != 0,
114            is_httponly: value.is_httponly != 0,
115            last_access_utc: value
116                .last_access_utc
117                .micros_to_chromium_utc(),
118            has_expires: value.has_expires != 0,
119            is_persistent: value.is_persistent != 0,
120            priority: value.priority,
121            same_site: value.samesite.into(),
122            source_scheme: value.source_scheme,
123            source_port: value.source_port,
124            last_update_utc: value
125                .last_update_utc
126                .micros_to_chromium_utc(),
127        }
128    }
129}