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}