neutralts/bif/
parse_bif_include.rs1#![doc = include_str!("../../doc/bif-include.md")]
2
3use crate::{bif::constants::*, bif::Bif, bif::BifError, constants::*, utils::*};
4use std::collections::HashSet;
5use std::fs;
6use std::path::Path;
7
8impl<'a> Bif<'a> {
9 pub(crate) fn parse_bif_include(&mut self) -> Result<(), BifError> {
14 if self.mod_filter || self.mod_scope {
15 return Err(self.bif_error(BIF_ERROR_MODIFIER_NOT_ALLOWED));
16 }
17
18 self.extract_params_code(true);
19
20 if !self.flags.is_empty() {
21 let flags_allowed: HashSet<&str> = ["require", "safe", "noparse"].into_iter().collect();
22
23 for f in self.flags.split('|').filter(|s| !s.is_empty()) {
24 if !flags_allowed.contains(f) {
25 return Err(self.bif_error(&format!("{} flag not allowed", f)));
26 }
27 }
28 }
29
30 self.file_path = self.code.clone();
31
32 if self.file_path.contains(BIF_OPEN) {
34 if !self.contains_allow(&self.file_path) {
35 return Err(self.bif_error(BIF_ERROR_INSECURE_FILE_NAME));
36 }
37 self.file_path = new_child_parse!(self, &self.code, false);
38 }
39
40 if let Some(stripped) = self.file_path.strip_prefix('#') {
41 self.file_path = format!("{}{}", self.inherit.current_dir, stripped);
42 }
43
44 let path = Path::new(&self.file_path);
45 if !path.exists() {
46 if self.flags.contains("|require|") {
47 return Err(self.bif_error(BIF_ERROR_FILE_NOT_FOUND));
48 } else {
49 return Ok(());
50 }
51 }
52
53 if let Some(parent) = path.parent() {
54 self.dir = parent.display().to_string();
55 }
56
57 let canonical_path = fs::canonicalize(path)
58 .unwrap()
59 .to_string_lossy()
60 .into_owned();
61
62 if self.mod_negate && self.inherit.include_files.contains(&canonical_path) {
63 self.out = EMPTY_STRING;
64
65 return Ok(());
66 }
67
68 if self.flags.contains("|safe|") {
69 self.code = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
70 self.code = escape_chars(&unescape_chars(&self.code, false), false).to_string();
71 self.code = self.code.replace(BIF_OPEN, BIF_SANITIZE_OPEN);
72 self.code = self.code.replace(BIF_CLOSE, BIF_SANITIZE_CLOSE);
73 self.out = self.code.clone();
74
75 return Ok(());
76 }
77
78 if self.flags.contains("|noparse|") {
79 self.code = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
80 self.out = self.code.clone();
81
82 return Ok(());
83 }
84
85 self.inherit.include_files.push(canonical_path);
86
87 let mut file_raw = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
88 if self.shared.comments.contains("remove") {
89 file_raw = remove_comments(&file_raw);
90 }
91
92 self.out = new_child_parse!(self, &file_raw, true);
93
94 Ok(())
95 }
96}
97
98#[cfg(test)]
99#[path = "parse_bif_include_tests.rs"]
100mod tests;