acdc_parser/
safe_mode.rs

1use std::str::FromStr;
2
3/// Safe mode to use when processing the document. This follows from what is described in
4/// <https://docs.asciidoctor.org/asciidoctor/latest/safe-modes/> and is intended to
5/// provide similar functionality as Asciidoctor.
6#[derive(Debug, Clone, Default, PartialOrd, PartialEq, Eq, Copy)]
7pub enum SafeMode {
8    /// The `UNSAFE` safe mode level disables all security measures.
9    #[default]
10    Unsafe = 0,
11
12    /// The `SAFE` safe mode level prevents access to files which reside outside of the
13    /// parent directory of the source file. Include directives (`include::[]`) are
14    /// enabled, but paths to include files must be within the parent directory. This mode
15    /// allows assets (such as the stylesheet) to be embedded in the document.
16    Safe,
17
18    /// The `SERVER` safe mode level disallows the document from setting attributes that
19    /// would affect conversion of the document. This level trims docfile to its relative
20    /// path and prevents the document from:
21    ///
22    /// - setting source-highlighter, doctype, docinfo and backend
23    /// - seeing docdir (as it can reveal information about the host filesystem)
24    ///
25    /// It allows icons and linkcss. No includes from a url are allowed unless the
26    /// `allow-uri-read` attribute is set.
27    Server,
28
29    /// The `SECURE` safe mode level disallows the document from attempting to read files
30    /// from the file system and including their contents into the document. Additionally,
31    /// it:
32    ///
33    /// - disables icons
34    /// - disables include directives (`include::[]`)
35    /// - data can not be retrieved from URIs
36    /// - prevents access to stylesheets and JavaScript files
37    /// - sets the backend to html5
38    /// - disables docinfo files
39    /// - disables data-uri
40    /// - disables interactive (opts=interactive) and inline (opts=inline) modes for SVGs
41    /// - disables docdir and docfile (as these can reveal information about the host
42    ///   filesystem)
43    /// - disables source highlighting
44    ///
45    /// Note: `GitHub` processes `AsciiDoc` files using the `SECURE` mode.
46    Secure,
47}
48
49impl FromStr for SafeMode {
50    type Err = String;
51
52    fn from_str(s: &str) -> Result<Self, Self::Err> {
53        match s.to_lowercase().as_str() {
54            "unsafe" => Ok(Self::Unsafe),
55            "safe" => Ok(Self::Safe),
56            "server" => Ok(Self::Server),
57            "secure" => Ok(Self::Secure),
58            _ => Err(format!(
59                "invalid safe mode: '{s}', expected: unsafe, safe, server, secure"
60            )),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_from_str() -> Result<(), String> {
71        assert_eq!(SafeMode::from_str("unsafe")?, SafeMode::Unsafe);
72        assert_eq!(SafeMode::from_str("UNSAFE")?, SafeMode::Unsafe);
73        assert_eq!(SafeMode::from_str("safe")?, SafeMode::Safe);
74        assert_eq!(SafeMode::from_str("server")?, SafeMode::Server);
75        assert_eq!(SafeMode::from_str("secure")?, SafeMode::Secure);
76        assert!(SafeMode::from_str("invalid").is_err());
77        Ok(())
78    }
79
80    #[test]
81    fn test_ordering() {
82        assert!(SafeMode::Unsafe < SafeMode::Safe);
83        assert!(SafeMode::Safe < SafeMode::Server);
84        assert!(SafeMode::Server < SafeMode::Secure);
85    }
86}