ttpkit_auth/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! Standard HTTP authorization schemes.
4
5mod challenge;
6
7pub mod basic;
8pub mod digest;
9
10use std::fmt::{self, Display, Formatter};
11
12use str_reader::StringReader;
13
14pub use ttpkit_utils::error::Error;
15
16pub use crate::challenge::{AuthChallenge, ChallengeParam};
17
18/// Helper struct for displaying escaped strings.
19struct DisplayEscaped<'a> {
20    inner: &'a str,
21}
22
23impl<'a> DisplayEscaped<'a> {
24    /// Create a new escaped string display.
25    const fn new(inner: &'a str) -> Self {
26        Self { inner }
27    }
28}
29
30impl Display for DisplayEscaped<'_> {
31    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
32        for c in self.inner.chars() {
33            match c {
34                '"' => f.write_str("\\\"")?,
35                '\\' => f.write_str("\\\\")?,
36                _ => Display::fmt(&c, f)?,
37            }
38        }
39
40        Ok(())
41    }
42}
43
44/// Helper trait.
45trait StringReaderExt {
46    /// Parse a quoted string.
47    fn parse_quoted_string(&mut self) -> Result<String, Error>;
48}
49
50impl StringReaderExt for StringReader<'_> {
51    fn parse_quoted_string(&mut self) -> Result<String, Error> {
52        let mut reader = StringReader::new(self.as_str());
53
54        reader.match_char('"').map_err(|_| {
55            Error::from_static_msg("quoted string does not start with the double quote sign")
56        })?;
57
58        let mut res = String::new();
59
60        while let Some(c) = reader.current_char() {
61            if c == '\\' {
62                reader.skip_char();
63
64                let c = reader.current_char().ok_or_else(|| {
65                    Error::from_static_msg("end of string within an escape sequence")
66                })?;
67
68                res.push(c);
69            } else if c == '"' {
70                break;
71            } else {
72                res.push(c);
73            }
74
75            reader.skip_char();
76        }
77
78        reader.match_char('"').map_err(|_| {
79            Error::from_static_msg("quoted string does not end with the double quote sign")
80        })?;
81
82        *self = reader;
83
84        Ok(res)
85    }
86}