vex2pdf/lib_utils/
env_vars.rs

1use log::info;
2
3/// Environment variable names used in the application
4pub enum EnvVarNames {
5    /// Standard HOME environment variable
6    Home,
7    /// Controls whether to display "No Vulnerabilities reported" message
8    /// When set to "false", the Vulnerabilities section will be omitted completely
9    /// if no vulnerabilities exist.
10    /// When set to "true" or not set (default), the "No Vulnerabilities reported"
11    /// message will be displayed when no vulnerabilities are present.
12    NoVulnsMsg,
13    /// USER CANNOT YET OVERRIDE THIS OPTION
14    ProcessJson,
15    /// USER CANNOT YET OVERRIDE THIS OPTION
16    ProcessXml,
17    /// Shows OSS License Information if set to true
18    #[deprecated(
19        since = "0.9.0",
20        note = "replaced with argument variable. will be removed at a future minor release"
21    )]
22    ShowOssLicenses,
23    /// Shows Software version and copyright Information if set to true
24    #[deprecated(
25        since = "0.9.0",
26        note = "replaced with argument variable. will be removed at a future minor release"
27    )]
28    VersionInfo,
29    /// Controls the title shown in the PDF when it is generated
30    ReportTitle,
31    /// Controls the metadata name which is usually displayed in window headers of readers
32    PdfName,
33    /// When set, treats the document as a pure CycloneDX BoM without the vulnerabilities section
34    /// Which would entail only listing the components and their versions
35    PureBomNoVulns,
36    /// Controls whether to show the list of components after the vulnerabilities; the default is `true`
37    ShowComponentList,
38    /// Working path which could be a dir in which case the tool will automatically scan all files in that directory with only one depth level
39    /// or it could be a file in which case that single file is converted. This is optional and set by default to the working directory
40    WorkingPath,
41    /// Overrides the output directory for the generated files, by default they get generated in the working directory
42    OutputDir,
43    /// Max Number of Jobs:
44    /// - NOT SET or `0`: runs in default mode which is maximum parallelism
45    /// - 1 runs in single-threaded mode which means no threads are spawned and the jobs are run in the main thread
46    /// - Any integer `N` would be the number of threads the tool runs with, this saturates at [`std::thread::available_parallelism`] which is the default number of jobs if no Job number is passed or set
47    MaxJobs,
48}
49
50#[allow(deprecated)]
51impl EnvVarNames {
52    pub const fn as_str(&self) -> &'static str {
53        match self {
54            EnvVarNames::Home => "HOME",
55            EnvVarNames::NoVulnsMsg => "VEX2PDF_NOVULNS_MSG",
56            EnvVarNames::ProcessJson => "VEX2PDF_JSON",
57            EnvVarNames::ProcessXml => "VEX2PDF_XML",
58            EnvVarNames::ShowOssLicenses => "VEX2PDF_SHOW_OSS_LICENSES",
59            EnvVarNames::VersionInfo => "VEX2PDF_VERSION_INFO",
60            EnvVarNames::ReportTitle => "VEX2PDF_REPORT_TITLE",
61            EnvVarNames::PdfName => "VEX2PDF_PDF_META_NAME",
62            EnvVarNames::PureBomNoVulns => "VEX2PDF_PURE_BOM_NOVULNS",
63            EnvVarNames::ShowComponentList => "VEX2PDF_SHOW_COMPONENTS",
64            EnvVarNames::OutputDir => "VEX2PDF_OUTPUT_DIR",
65            EnvVarNames::WorkingPath => "VEX2PDF_WORKING_PATH",
66            EnvVarNames::MaxJobs => "VEX2PDF_MAX_JOBS",
67        }
68    }
69    /// this is useful for environment variables which should be on by default
70    pub fn is_on_or_unset(&self) -> bool {
71        match std::env::var(self.as_str()) {
72            Ok(value) => self.is_value_on(&value),
73            Err(_) => true, // Variable isn't set, default to ON
74        }
75    }
76
77    pub fn is_on(&self) -> bool {
78        match std::env::var(self.as_str()) {
79            Ok(value) => self.is_value_on(&value),
80            Err(_) => false, // Variable isn't set, so we are off
81        }
82    }
83
84    /// Prints information about currently used pdf titles
85    pub fn print_report_titles_info() {
86        info!("");
87        match EnvVarNames::ReportTitle.get_value() {
88            Some(title) => {
89                info!("Overriding report title to {title}");
90            }
91            None => {
92                info!("Using default report title");
93                info!(
94                    "to override this set the {} environment variable to the desired title",
95                    EnvVarNames::ReportTitle.as_str()
96                );
97            }
98        };
99        info!("");
100        match EnvVarNames::PdfName.get_value() {
101            Some(title) => {
102                info!("Overriding pdf metadata title to {title}");
103            }
104            None => {
105                info!("Using default pdf metadata title");
106                info!(
107                    "to override this set the {} environment variable to the desired title",
108                    EnvVarNames::PdfName.as_str()
109                );
110            }
111        };
112        info!("");
113    }
114
115    // Helper method to determine if a value represents "on"
116    fn is_value_on(&self, value: &str) -> bool {
117        !(value.eq_ignore_ascii_case("false")
118            || value.eq_ignore_ascii_case("off")
119            || value.eq_ignore_ascii_case("no")
120            || value.eq_ignore_ascii_case("0"))
121    }
122
123    /// Helper method to get the value of the variable
124    pub fn get_value(&self) -> Option<String> {
125        std::env::var(self.as_str()).ok()
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::EnvVarNames;
132
133    // tests for private functions that cannot be tested in lib
134    #[test]
135    fn test_is_value_on_private() {
136        // Test is_value_on directly
137        {
138            let var = EnvVarNames::ProcessJson; // must be different than the tests under lib.rs to not cause race conditions
139
140            // True values
141            for value in &[
142                "true",
143                "True",
144                "TRUE",
145                "yes",
146                "YES",
147                "1",
148                "on",
149                "ON",
150                "anything_else",
151            ] {
152                assert_eq!(
153                    var.is_value_on(value),
154                    true,
155                    "is_value_on() failed for value: {}",
156                    value
157                );
158            }
159
160            // False values
161            for value in &["false", "False", "FALSE", "no", "NO", "0", "off", "OFF"] {
162                assert_eq!(
163                    var.is_value_on(value),
164                    false,
165                    "is_value_on() failed for value: {}",
166                    value
167                );
168            }
169        }
170    }
171}