netscape_cookie_file_parser/cookie.rs
1/// One parsed cookie record from a Netscape cookie file.
2///
3/// String-like fields are byte buffers rather than `String`s because cookie jar
4/// files seen in the wild may contain non-UTF-8 octets.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Cookie {
7 /// Cookie domain bytes with one leading dot removed.
8 pub domain: Vec<u8>,
9 /// Whether the original tail-match field was `TRUE`, case-insensitively.
10 pub tail_match: bool,
11 /// Raw cookie path field bytes.
12 pub path: Vec<u8>,
13 /// Whether the original secure field was `TRUE`, case-insensitively.
14 pub secure: bool,
15 /// Expiration timestamp parsed as an unsigned integer.
16 pub expires: u64,
17 /// Raw cookie name bytes.
18 pub name: Vec<u8>,
19 /// Raw cookie value bytes.
20 pub value: Vec<u8>,
21 /// Whether this line used curl's `#HttpOnly_` cookie marker.
22 pub http_only: bool,
23 /// Recognized security prefix in the cookie name.
24 pub prefix: CookiePrefix,
25}
26
27/// Case-sensitive cookie name prefixes recognized by the parser.
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum CookiePrefix {
30 /// No recognized cookie prefix.
31 None,
32 /// Cookie name starts with `__Secure-`.
33 Secure,
34 /// Cookie name starts with `__Host-`.
35 Host,
36}
37
38// The prefix checks are intentionally case-sensitive: cookie prefixes are part
39// of the cookie name contract, not ordinary case-insensitive cookie metadata.
40pub(crate) fn cookie_prefix(name: &[u8]) -> CookiePrefix {
41 if name.starts_with(b"__Secure-") {
42 CookiePrefix::Secure
43 } else if name.starts_with(b"__Host-") {
44 CookiePrefix::Host
45 } else {
46 CookiePrefix::None
47 }
48}