1#![doc = include_str!("../README.md")]
2
3pub mod constants;
4mod default_json;
5pub mod doc;
6pub mod utils;
7
8use crate::constants::*;
9use crate::default_json::*;
10use crate::utils::*;
11
12use chrono::Utc;
13use md5::{Digest, Md5};
14use rand::Rng;
15use regex::Regex;
16use serde_json::json;
17use serde_json::Value;
18use std::env;
19use std::fs;
20use std::path::Path;
21use std::str;
22use std::time::Duration;
23use std::time::Instant;
24
25#[macro_use]
118mod macros {
119 macro_rules! new_child_parse {
120 ($self:expr, $source:expr, $scope:expr) => {{
121 let mut child_inherit = $self.inherit.clone();
122 let shared = &mut $self.shared;
123
124 child_inherit.alias = $self.alias.clone();
127
128 if !$self.file_path.is_empty() {
129 child_inherit.current_file = $self.file_path.clone();
130 }
131
132 if !$self.dir.is_empty() {
133 child_inherit.current_dir = $self.dir.clone();
134 }
135
136 if $scope {
140 $self.inherit.create_block_schema(shared);
141 }
142
143 let mut block = BlockParser::new(shared, &child_inherit);
144 let code = block.parse($source);
145
146 if $scope {
148 block.update_indir(&$self.inherit.indir);
151 }
152
153 code
154 }};
155 }
156}
157
158struct BifError {
159 code: i32,
160 msg: String,
161 name: String,
162 src: String,
163}
164
165struct Shared {
167 schema: Value,
168 lang: String,
169 comments: String,
170 bisf_count: u64,
171 bisf_max: u64,
172 flags: String,
173 exit: bool,
174 has_error: bool,
175 status_code: String,
176 status_text: String,
177 status_param: String,
178 redirect_js: String,
179 filter_all: bool,
180 }
182
183impl Shared {
184 fn new(mut schema: Value) -> Self {
185 let bisf_max = schema["config"]["infinite_loop_max_bifs"].as_u64().unwrap();
186 let comments = get_from_key(&schema["config"], "comments");
187 let lang = get_from_key(&schema["inherit"]["locale"], "current");
188 let working_dir = get_from_key(&schema["config"], "working_dir");
189 let filter_all = is_bool_key(&schema["config"], "filter_all");
190
191 if !working_dir.is_empty() {
192 env::set_current_dir(&working_dir).unwrap();
193 schema["data"]["CONTEXT"]["working_dir"] = json!(working_dir);
194 } else {
195 schema["data"]["CONTEXT"]["working_dir"] = json!(env::current_dir().unwrap());
196 }
197
198 Shared {
199 schema,
200 lang,
201 comments,
202 bisf_count: 0,
203 bisf_max,
204 flags: String::new(),
205 exit: false,
206 has_error: false,
207 status_code: "200".to_string(),
208 status_text: "OK".to_string(),
209 status_param: String::new(),
210 redirect_js: String::new(),
211 filter_all,
212 }
214 }
215}
216
217struct BlockInherit {
218 indir: String,
219 last_bif_out: bool,
220 last_coalesce_out: bool,
221 block_count: u64, bif_count: u64, alias: String,
224 current_file: String,
225 current_dir: String,
226 include_files: Vec<String>,
227 locale_files: Vec<String>,
228 data_files: Vec<String>,
229}
230
231impl Clone for BlockInherit {
232 fn clone(&self) -> Self {
233 BlockInherit {
234 indir: self.indir.clone(),
235 last_bif_out: self.last_bif_out,
236 last_coalesce_out: self.last_coalesce_out,
237 block_count: self.block_count,
238 bif_count: self.bif_count,
239 alias: self.alias.clone(),
240 current_file: self.current_file.clone(),
241 current_dir: self.current_dir.clone(),
242 include_files: self.include_files.clone(),
243 locale_files: self.locale_files.clone(),
244 data_files: self.data_files.clone(),
245 }
246 }
247}
248
249impl BlockInherit {
250 fn new() -> Self {
251 BlockInherit {
252 indir: "block_0".to_string(),
253 last_bif_out: false,
254 last_coalesce_out: false,
255 block_count: 0,
256 bif_count: 0,
257 alias: String::new(),
258 current_file: String::new(),
259 current_dir: String::new(),
260 include_files: Vec::new(),
261 locale_files: Vec::new(),
262 data_files: Vec::new(),
263 }
264 }
265
266 fn create_block_schema(&mut self, shared: &mut Shared) -> String {
272 let prev_id = self.indir.clone();
273 let block_id;
274
275 if self.block_count < 1 {
279 block_id = "block_1".to_string();
280 } else {
281 block_id = "block_".to_string() + self.block_count.to_string().as_str();
282 }
283
284 if prev_id != block_id {
287 shared.schema["__indir"][&block_id] = shared.schema["__indir"][&prev_id].clone();
291 }
292
293 self.indir = block_id.clone();
294
295 block_id
296 }
297}
298
299pub struct Template<'a> {
300 raw: String,
301 file_path: &'a str,
302 schema: Value,
303 shared: Shared,
304 time_start: Instant,
305 time_elapsed: Duration,
306 out: String,
307}
308
309impl<'a> Template<'a> {
313 pub fn new() -> Result<Self, String> {
317 let default_schema: Value = match serde_json::from_str(DEFAULT) {
318 Ok(value) => value,
319 Err(_) => return Err("const DEFAULT is not a valid JSON string".to_string()),
320 };
321 let shared = Shared::new(default_schema.clone());
322
323 Ok(Template {
324 raw: String::new(),
325 file_path: "",
326 schema: default_schema,
327 shared,
328 time_start: Instant::now(),
329 time_elapsed: Instant::now().elapsed(),
330 out: String::new(),
331 })
332 }
333
334 pub fn from_file_value(file_path: &'a str, schema: Value) -> Result<Self, String> {
346 let raw: String = match fs::read_to_string(file_path) {
347 Ok(s) => s,
348 Err(e) => {
349 eprintln!("Cannot be read: {}", file_path);
350 return Err(e.to_string());
351 }
352 };
353 let mut default_schema: Value = match serde_json::from_str(DEFAULT) {
354 Ok(value) => value,
355 Err(_) => {
356 eprintln!("Internal error in const DEFAULT {}, line: {}", file!(), line!());
357 return Err("const DEFAULT is not a valid JSON string".to_string());
358 }
359 };
360
361 merge_schema(&mut default_schema, &schema);
362 let shared = Shared::new(default_schema.clone());
363
364 Ok(Template {
365 raw,
366 file_path,
367 schema: default_schema,
368 shared,
369 time_start: Instant::now(),
370 time_elapsed: Instant::now().elapsed(),
371 out: String::new(),
372 })
373 }
374
375 pub fn set_src_path(&mut self, file_path: &'a str) -> Result<(), String> {
385 self.file_path = file_path;
386 self.raw = match fs::read_to_string(file_path) {
387 Ok(s) => s,
388 Err(e) => {
389 eprintln!("Cannot be read: {}", file_path);
390 return Err(e.to_string());
391 }
392 };
393
394 Ok(())
395 }
396
397 pub fn set_src_str(&mut self, source: &str) {
403 self.raw = source.to_string();
404 }
405
406 pub fn merge_schema_path(&mut self, schema_path: &str) -> Result<(), String> {
418 let schema_str: String = match fs::read_to_string(schema_path) {
419 Ok(s) => s,
420 Err(e) => {
421 eprintln!("Cannot be read: {}", schema_path);
422 return Err(e.to_string());
423 }
424 };
425 let schema_value: Value = match serde_json::from_str(&schema_str) {
426 Ok(value) => value,
427 Err(_) => {
428 return Err("Is not a valid JSON file".to_string());
429 }
430 };
431 merge_schema(&mut self.schema, &schema_value);
432
433 Ok(())
434 }
435
436 pub fn merge_schema_str(&mut self, schema: &str) -> Result<(), String> {
447 let schema_value: Value = match serde_json::from_str(schema) {
448 Ok(value) => value,
449 Err(_) => {
450 return Err("Is not a valid JSON string".to_string());
451 }
452 };
453 merge_schema(&mut self.schema, &schema_value);
454
455 Ok(())
456 }
457
458 pub fn merge_schema_value(&mut self, schema: Value) {
464 merge_schema(&mut self.schema, &schema);
465 }
466
467 pub fn render(&mut self) -> String {
476 let inherit = self.init_render();
477 self.out = BlockParser::new(&mut self.shared, &inherit).parse(&self.raw);
478 self.ends_render();
479
480 self.out.clone()
481 }
482
483 fn init_render(&mut self) -> BlockInherit {
485 self.time_start = Instant::now();
486 self.shared = Shared::new(self.schema.clone());
487
488 if self.shared.comments.contains("remove") {
489 self.raw = remove_comments(&self.raw);
490 }
491
492 let mut inherit = BlockInherit::new();
494 let indir = inherit.create_block_schema(&mut self.shared);
495 self.shared.schema["__moveto"] = json!({});
496 self.shared.schema["__error"] = json!([]);
497 self.shared.schema["__indir"] = json!({});
498 self.shared.schema["__indir"][&indir] = self.shared.schema["inherit"].clone();
499 inherit.current_file = self.file_path.to_string();
500
501 if !self.file_path.is_empty() {
502 let path = Path::new(&self.file_path);
503
504 if let Some(parent) = path.parent() {
505 inherit.current_dir = parent.display().to_string();
506 }
507 } else {
508 inherit.current_dir = self.shared.schema["data"]["CONTEXT"]["working_dir"].to_string();
509 }
510
511 inherit
512 }
513
514 fn ends_render(&mut self) {
516 self.set_moveto();
517 self.replacements();
518 self.set_status_code();
519 self.time_elapsed = self.time_start.elapsed();
520 }
521
522 fn set_status_code(&mut self) {
523 let status_code = self.shared.status_code.as_str();
524
525 if ("400"..="599").contains(&status_code) {
526 self.out = format!("{} {}", self.shared.status_code, self.shared.status_text);
527
528 return;
529 }
530
531 if status_code == "301"
532 || status_code == "302"
533 || status_code == "303"
534 || status_code == "307"
535 || status_code == "308"
536 {
537 self.out = format!(
538 "{} {}\n{}",
539 self.shared.status_code, self.shared.status_text, self.shared.status_param
540 );
541
542 return;
543 }
544
545 if !self.shared.redirect_js.is_empty() {
546 self.out = self.shared.redirect_js.clone();
547 }
548 }
549
550 fn set_moveto(&mut self) {
551 if let Value::Object(data_map) = &self.shared.schema["__moveto"] {
552 for (_key, value) in data_map {
553 if let Value::Object(inner_map) = value {
554 for (inner_key, inner_value) in inner_map {
555 let mut tag;
556
557 if !inner_key.starts_with("<") {
560 tag = format!("<{}", inner_key);
561 } else {
562 tag = inner_key.to_string();
563 }
564 if tag.ends_with(">") {
565 tag = tag[..tag.len() - 1].to_string();
566 }
567
568 let position = find_tag_position(&self.out, &tag);
570 if let Some(pos) = position {
571 let mut insert = inner_value.as_str().unwrap().to_string();
572 insert = insert.to_string();
573 self.out.insert_str(pos, &insert);
574 }
575 }
576 }
577 }
578 }
579 }
580
581 fn replacements(&mut self) {
582 let pattern = format!(r"\s*{}", BACKSPACE);
583 let re = Regex::new(&pattern).expect("Failed to create regex with constant pattern");
584 self.out = re.replace_all(&self.out, "").to_string();
585
586 self.out = self.out.replace(UNPRINTABLE, "");
588 }
589
590 pub fn get_status_code(&self) -> &String {
600 &self.shared.status_code
601 }
602
603 pub fn get_status_text(&self) -> &String {
611 &self.shared.status_text
612 }
613
614 pub fn get_status_param(&self) -> &String {
624 &self.shared.status_param
625 }
626
627 pub fn has_error(&self) -> bool {
635 self.shared.has_error
636 }
637
638 pub fn get_error(&self) -> Value {
644 self.shared.schema["__error"].clone()
645 }
646
647 pub fn get_time_duration(&self) -> Duration {
653 let duration: std::time::Duration = self.time_elapsed;
654
655 duration
656 }
657}
658
659struct BlockParser<'a> {
660 shared: &'a mut Shared,
661 inherit: BlockInherit,
662 _none: &'a str,
663}
664
665impl Drop for BlockParser<'_> {
666 fn drop(&mut self) {
667 let block_id = "block_".to_string() + self.inherit.block_count.to_string().as_str();
669 if block_id == self.inherit.indir && is_defined_key(&self.shared.schema["__indir"], &block_id) {
670 self.shared.schema["__indir"][&block_id] = json!({});
671 }
672 }
673}
674
675impl<'a> BlockParser<'a> {
676 fn new(shared: &'a mut Shared, inherit: &BlockInherit) -> Self {
677 let mut inherit = inherit.clone();
678 inherit.block_count += 1;
679
680 BlockParser {
681 shared,
682 inherit,
683 _none: "",
684 }
685 }
686
687 fn update_indir(&mut self, indir: &String) {
688 self.shared.schema["__indir"][indir] =
689 self.shared.schema["__indir"][&self.inherit.indir].clone();
690 }
691
692 fn parse(&mut self, raw_source: &'a str) -> String {
693 let blocks;
694
695 match extract_blocks(raw_source) {
696 Ok(b) => {
697 blocks = b;
698 }
699 Err(p) => {
700 self.shared.status_code = "500".to_string();
701 self.shared.status_param = format!("Unmatched block at position {}", p);
702 eprintln!("Unmatched block at position {}", p);
703
704 if let Some(text) = STATUS_CODES.get(self.shared.status_code.as_str()) {
705 self.shared.status_text = text.to_string();
706 } else {
707 self.shared.status_text = EMPTY_STRING;
708 }
709
710 return EMPTY_STRING;
711 }
712 }
713
714 let mut prev_end = 0;
715 let mut out = String::new();
716 for (start, end) in blocks {
717 let is_comment = raw_source[start..end].starts_with(BIF_COMMENT_OPEN);
718 let is_short_circuit_coalesce =
719 self.inherit.last_coalesce_out && self.inherit.alias == "coalesce";
720
721 if self.shared.exit {
722 return out.clone();
723 }
724
725 if prev_end < start {
726 out += &raw_source[prev_end..start];
727 }
728
729 if !is_comment && !is_short_circuit_coalesce {
730 let mut bif =
731 Bif::new(&raw_source[start..end], self.shared, &mut self.inherit);
732 out += &bif.parse();
733 }
734
735 prev_end = end;
736 }
737 out += &raw_source[prev_end..];
738
739 out.trim().to_string()
740 }
741}
742
743struct Bif<'a> {
744 raw: &'a str,
745 shared: &'a mut Shared,
746 inherit: &'a mut BlockInherit,
747 src: String,
748 name: String,
749 alias: String,
750 code: String,
751 params: String,
752 flags: String,
753 mod_filter: bool,
754 mod_negate: bool,
755 mod_upline: bool,
756 mod_scope: bool,
757 file_path: String,
758 dir: String,
759 out: String,
760 _none: &'a str,
761}
762
763impl<'a> Bif<'a> {
764 fn new(raw_source: &'a str, shared: &'a mut Shared, inherit: &'a mut BlockInherit) -> Self {
765 shared.bisf_count += 1;
766 let count = shared.bisf_count;
767 inherit.bif_count = shared.bisf_count;
768
769 if count > shared.bisf_max {
770 panic!(
771 "Infinite loop? {} bifs of {} max have been created.",
772 shared.bisf_max, count
773 );
774 }
775
776 Bif {
777 raw: raw_source, shared,
779 inherit,
780 src: String::new(),
781 name: String::new(),
782 alias: String::new(),
783 code: String::new(),
784 params: String::new(),
785 flags: String::new(),
786 mod_filter: false,
787 mod_negate: false,
788 mod_upline: false,
789 mod_scope: false,
790 file_path: String::new(),
791 dir: String::new(),
792 out: String::new(),
793 _none: "",
794 }
795 }
796
797 fn parse(&mut self) -> String {
799 let bif = strip_prefix_suffix(self.raw, BIF_OPEN, BIF_CLOSE);
800 let result;
801
802 if let Some((name, src)) = bif.split_once(BIF_NAME) {
803 self.name = name.to_string();
804 if name == "neutral" {
805 self.src = src.to_string();
806 } else {
807 self.src = src.trim().to_string();
808 }
809 } else {
810 let show_error = self.shared.schema["config"]["error"]["show"].as_bool().unwrap();
811 let error_line = format!("The delimiter was not found: {}", self.raw);
812 let error_line = error_line.replace(['\n', '\r'], " ");
813
814 if let Some(Value::Array(ref mut errors)) = self.shared.schema.get_mut("__error") {
815 errors.push(json!(error_line));
816 }
817
818 if show_error {
819 eprintln!("{}", error_line);
820 }
821
822 self.shared.has_error = true;
823
824 return EMPTY_STRING;
825 }
826 self.name = self.set_modifiers();
827 self.alias = self.name.clone();
828
829 match &self.name[..] {
831 "" => result = self.parse_bif_var(),
832 "allow" => result = self.parse_bif_allow(),
833 "array" => result = self.parse_bif_array(),
834 "bool" => result = self.parse_bif_bool(),
835 "coalesce" => result = self.parse_bif_coalesce(),
836 "code" => result = self.parse_bif_code(),
837 "count" => result = self.parse_bif_count(),
838 "data" => result = self.parse_bif_data(),
839 "date" => result = self.parse_bif_date(),
840 "declare" => result = self.parse_bif_declare(),
841 "defined" => result = self.parse_bif_defined(),
842 "each" => result = self.parse_bif_each(),
843 "else" => result = self.parse_bif_else(),
844 "eval" => result = self.parse_bif_eval(),
845 "exit" => result = self.parse_bif_exit(),
846 "filled" => result = self.parse_bif_filled(),
847 "flg" => result = self.parse_bif_flg(),
848 "for" => result = self.parse_bif_for(),
849 "hash" => result = self.parse_bif_hash(),
850 "include" => result = self.parse_bif_include(),
851 "lang" => result = self.parse_bif_lang(),
852 "locale" => result = self.parse_bif_locale(),
853 "moveto" => result = self.parse_bif_moveto(),
854 "neutral" => result = self.parse_bif_neutral(),
855 "param" => result = self.parse_bif_param(),
856 "rand" => result = self.parse_bif_rand(),
857 "redirect" => result = self.parse_bif_redirect(),
858 "replace" => result = self.parse_bif_replace(),
859 "same" => result = self.parse_bif_same(),
860 "snippet" => result = self.parse_bif_snippet(),
861 "snip" => result = self.parse_bif_snippet(),
862 "trans" => result = self.parse_bif_trans(),
863 _ => result = self.parse_bif_unknown(),
864 }
865
866 match result {
867 Ok(()) => (),
868 Err(e) => {
869 let show_error = self.shared.schema["config"]["error"]["show"].as_bool().unwrap();
870 let error_line = format!("Error {} ({}) {} src: {}", e.code, e.name, e.msg, e.src);
871 let error_line = error_line.replace(['\n', '\r'], " ");
872
873 if let Some(Value::Array(ref mut errors)) = self.shared.schema.get_mut("__error") {
874 errors.push(json!(error_line));
875 }
876
877 if show_error {
878 eprintln!("{}", error_line);
879 }
880
881 self.shared.has_error = true;
882 }
883 }
884
885 self.inherit.last_bif_out = !self.out.is_empty();
886 self.inherit.last_coalesce_out = self.inherit.last_bif_out;
887
888 if self.mod_upline {
889 self.out = BACKSPACE.to_string() + &self.out;
890 self.out.trim().to_string()
891 } else {
892 self.out.trim().to_string()
893 }
894 }
895
896 fn set_modifiers(&mut self) -> String {
904 let mut index = 0;
905 while index < self.name.len() {
906 let start = &self.name[index..index + 1];
907 if start == BIF_MOD_FILTER
908 || start == BIF_MOD_NEGATE
909 || start == BIF_MOD_UPLINE
910 || start == BIF_MOD_SCOPE
911 {
912 match start {
913 BIF_MOD_FILTER => self.mod_filter = true,
914 BIF_MOD_NEGATE => self.mod_negate = true,
915 BIF_MOD_UPLINE => self.mod_upline = true,
916 BIF_MOD_SCOPE => self.mod_scope = true,
917 _ => unreachable!(),
918 }
919 index += 1;
920 } else {
921 break;
922 }
923 }
924
925 self.name[index..].to_string()
926 }
927
928 fn get_data(&self, name: &str) -> String {
940 if name.starts_with("local::") {
941 let local_name = name.strip_prefix("local::").unwrap_or(name);
942 get_from_key(
943 &self.shared.schema["__indir"][&self.inherit.indir]["data"],
944 local_name,
945 )
946 } else {
947 get_from_key(&self.shared.schema["data"], name)
948 }
949 }
950
951 fn set_data(&mut self, name: &str, value: &str) {
959 self.shared.schema["data"][name] = json!(value);
960 }
961
962 fn get_trans(&self, text: &str) -> String {
981 get_from_key(
982 &self.shared.schema["__indir"][&self.inherit.indir]["locale"]["trans"]
983 [&self.shared.lang],
984 text,
985 )
986 }
987
988 fn contains_allow(&self, source: &str) -> bool {
995 for allow in BIF_ALLOWED {
996 if source.contains(allow) {
997 return true;
998 }
999 }
1000
1001 let source = &remove_comments(source);
1002 !(source.starts_with(BIF_VAR) && source.ends_with(BIF_CLOSE))
1003 }
1004
1005 fn extract_params_code(&mut self, parse: bool) -> bool {
1019 let position = get_code_position(&self.src);
1020 let has_code: bool = position.is_some();
1021
1022 if has_code {
1023 let code_pos = position.unwrap();
1024 self.params = self.src[0..code_pos].trim().to_string();
1025 self.code = self.src[code_pos + BIF_CODE.len()..].trim().to_string();
1026 } else {
1027 self.params = EMPTY_STRING;
1028 self.code = self.src.trim().to_string();
1029 }
1030
1031 if parse && self.params.contains(BIF_OPEN) {
1032 self.shared.flags = EMPTY_STRING;
1033 self.params = new_child_parse!(self, &self.params, false);
1034 self.flags = self.shared.flags.clone();
1035 }
1036
1037 has_code
1038 }
1039
1040 fn parse_bif_unknown(&mut self) -> Result<(), BifError> {
1044 self.alias = "unknown".to_string();
1045
1046 Err(BifError {
1047 code: 101,
1048 msg: "unknown bif".to_string(),
1049 name: self.alias.clone(),
1050 src: self.raw.to_string(),
1051 })
1052 }
1053
1054 fn parse_bif_var(&mut self) -> Result<(), BifError> {
1059 if self.mod_scope {
1060 return Err(BifError {
1061 code: 102,
1062 msg: "modifier not allowed".to_string(),
1063 name: self.alias.clone(),
1064 src: self.raw.to_string(),
1065 });
1066 }
1067
1068 if self.src.is_empty() {
1070 self.alias = "unprintable".to_string();
1073
1074 self.out = UNPRINTABLE.to_string();
1075
1076 return Ok(());
1077 }
1078
1079 self.alias = "var".to_string();
1081
1082 if self.src.contains(BIF_OPEN) {
1084 if !self.contains_allow(&self.src) {
1085 self.out = EMPTY_STRING;
1086
1087 return Err(BifError {
1088 code: 103,
1089 msg: "insecure varname".to_string(),
1090 name: self.alias.clone(),
1091 src: self.src.clone(),
1092 });
1093 }
1094
1095 let var_name = &new_child_parse!(self, &self.src, self.mod_scope);
1096 self.out = self.get_data(var_name).to_string();
1097
1098 return Ok(());
1099 }
1100
1101 let var_name = &self.src;
1102
1103 if (self.mod_filter || self.shared.filter_all || var_name.starts_with("CONTEXT->")) && !self.mod_negate {
1104 self.out = unescape_chars(&self.get_data(var_name), true).to_string();
1106 self.out = escape_chars(&self.out, true).to_string();
1107 } else {
1108 self.out = self.get_data(var_name).to_string();
1109 }
1110
1111 Ok(())
1112 }
1113
1114 fn parse_bif_allow(&mut self) -> Result<(), BifError> {
1118 if self.mod_filter || self.mod_scope {
1119 return Err(BifError {
1120 code: 104,
1121 msg: "modifier not allowed".to_string(),
1122 name: self.alias.clone(),
1123 src: self.raw.to_string(),
1124 });
1125 }
1126
1127 self.extract_params_code(true);
1128 let mut found = String::new();
1129 let words_string = get_from_key(
1130 &self.shared.schema["__indir"][&self.inherit.indir]["declare"],
1131 &self.params,
1132 );
1133
1134 if words_string.is_empty() {
1135 return Err(BifError {
1136 code: 105,
1137 msg: self.params.clone() + " declared is empty",
1138 name: self.alias.clone(),
1139 src: self.raw.to_string(),
1140 });
1141 }
1142
1143 let mut words_list: Vec<&str> = words_string.split_whitespace().collect();
1144 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1145
1146 for word in &mut words_list {
1147 let lower_haystack;
1148 let mut haystack = &self.code;
1149 let mut pattern = word.to_string().clone();
1150
1151 if self.flags.contains("|partial|") || self.flags.contains("|replace|") {
1152 pattern = format!("{}{}{}", "*", pattern, "*");
1153 }
1154
1155 if self.flags.contains("|casein|") {
1156 pattern = pattern.to_lowercase();
1157 lower_haystack = self.code.clone().to_lowercase();
1158 haystack = &lower_haystack;
1159 }
1160
1161 if wildcard_match(haystack, &pattern) {
1162 found = word.to_string();
1163 break;
1164 }
1165 }
1166
1167 if !found.is_empty() ^ self.mod_negate {
1168 if self.flags.contains("|replace|") {
1169 found = found.replace("~", "");
1170 found = found.replace("*", "");
1171 found = found.replace("?", "");
1172 found = found.replace(".", "");
1173 self.out = found.to_string();
1174 } else {
1175 self.out = self.code.to_string();
1176 }
1177 } else {
1178 self.out = EMPTY_STRING;
1179 }
1180
1181 Ok(())
1182 }
1183
1184 fn parse_bif_array(&mut self) -> Result<(), BifError> {
1188 if self.mod_filter {
1189 return Err(BifError {
1190 code: 106,
1191 msg: "modifier not allowed".to_string(),
1192 name: self.alias.clone(),
1193 src: self.raw.to_string(),
1194 });
1195 }
1196
1197 self.extract_params_code(true);
1198
1199 let mut varname = self.params.as_str();
1200 let mut schema = &self.shared.schema["data"];
1201
1202 if varname.starts_with("local::") {
1203 schema = &self.shared.schema["__indir"][&self.inherit.indir]["data"];
1204 varname = varname.strip_prefix("local::").unwrap_or(varname);
1205 }
1206
1207 if is_array_key(schema, varname) ^ self.mod_negate {
1208 if self.code.contains(BIF_OPEN) {
1209 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1210 }
1211 self.out = self.code.to_string();
1212 }
1213
1214 Ok(())
1215 }
1216
1217 fn parse_bif_bool(&mut self) -> Result<(), BifError> {
1221 if self.mod_filter {
1222 return Err(BifError {
1223 code: 107,
1224 msg: "modifier not allowed".to_string(),
1225 name: self.alias.clone(),
1226 src: self.raw.to_string(),
1227 });
1228 }
1229
1230 self.extract_params_code(true);
1231
1232 let mut varname = self.params.as_str();
1233 let mut schema = &self.shared.schema["data"];
1234
1235 if varname.starts_with("local::") {
1236 schema = &self.shared.schema["__indir"][&self.inherit.indir]["data"];
1237 varname = varname.strip_prefix("local::").unwrap_or(varname);
1238 }
1239
1240 if is_bool_key(schema, varname) ^ self.mod_negate {
1241 if self.code.contains(BIF_OPEN) {
1242 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1243 }
1244 self.out = self.code.to_string();
1245 }
1246
1247 Ok(())
1248 }
1249
1250 fn parse_bif_coalesce(&mut self) -> Result<(), BifError> {
1258 if self.mod_filter || self.mod_negate {
1259 return Err(BifError {
1260 code: 108,
1261 msg: "modifier not allowed".to_string(),
1262 name: self.alias.clone(),
1263 src: self.raw.to_string(),
1264 });
1265 }
1266
1267 self.inherit.last_coalesce_out = false;
1269 self.out = new_child_parse!(self, &self.src, self.mod_scope);
1270
1271 Ok(())
1272 }
1273
1274 fn parse_bif_code(&mut self) -> Result<(), BifError> {
1279 if self.mod_filter || self.mod_negate {
1280 return Err(BifError {
1281 code: 109,
1282 msg: "modifier not allowed".to_string(),
1283 name: self.alias.clone(),
1284 src: self.raw.to_string(),
1285 });
1286 }
1287
1288 self.extract_params_code(true);
1289
1290 if self.flags.contains("|safe|") {
1291 self.code = escape_chars(&unescape_chars(&self.code, false), false).to_string();
1292 self.code = self.code.replace(BIF_OPEN, BIF_SANITIZE_OPEN);
1293 self.code = self.code.replace(BIF_CLOSE, BIF_SANITIZE_CLOSE);
1294 } else {
1295 if self.flags.contains("|encode_tags|") {
1296 self.code = escape_chars(&unescape_chars(&self.code, false), false).to_string();
1297 }
1298
1299 if self.flags.contains("|encode_bifs|") {
1300 self.code = self.code.replace(BIF_OPEN, BIF_SANITIZE_OPEN);
1301 self.code = self.code.replace(BIF_CLOSE, BIF_SANITIZE_CLOSE);
1302 }
1303
1304 if !self.flags.contains("|noparse|") && self.code.contains(BIF_OPEN) {
1305 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1306 }
1307 }
1308
1309 if self.flags.contains("|encode_tags_after|") {
1310 self.code = escape_chars(&unescape_chars(&self.code, false), false).to_string();
1311 }
1312
1313 self.out = self.code.to_string();
1314
1315 Ok(())
1316 }
1317
1318 fn parse_bif_count(&mut self) -> Result<(), BifError> {
1323 if self.mod_filter || self.mod_negate || self.mod_scope {
1324 return Err(BifError {
1325 code: 110,
1326 msg: "modifier not allowed".to_string(),
1327 name: self.alias.clone(),
1328 src: self.raw.to_string(),
1329 });
1330 }
1331
1332 let is_set = self.extract_params_code(true);
1333
1334 if self.code.contains(BIF_OPEN) {
1335 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1336 }
1337
1338 if is_set {
1339 let count_name = self.params.clone();
1340 let count_value = match self.code.parse::<i32>() {
1341 Ok(num) => num,
1342 Err(_) => {
1343 return Err(BifError {
1344 code: 111,
1345 msg: "argument is not a number".to_string(),
1346 name: self.alias.clone(),
1347 src: self.raw.to_string(),
1348 });
1349 }
1350 };
1351
1352 self.set_data(&count_name, &count_value.to_string());
1353 self.out = EMPTY_STRING;
1354 } else {
1355 let count_name = self.code.clone();
1356 let count_value = match self.get_data(&count_name).parse::<i32>() {
1357 Ok(num) => num,
1358 Err(_) => {
1359 return Err(BifError {
1360 code: 112,
1361 msg: "argument is not a number".to_string(),
1362 name: self.alias.clone(),
1363 src: self.raw.to_string(),
1364 });
1365 }
1366 };
1367 let new_value = count_value + 1;
1368
1369 self.set_data(&count_name, &new_value.to_string());
1370 self.out = count_value.to_string();
1371 }
1372
1373 Ok(())
1374 }
1375
1376 fn parse_bif_data(&mut self) -> Result<(), BifError> {
1380 if self.mod_filter || self.mod_scope {
1381 return Err(BifError {
1382 code: 113,
1383 msg: "modifier not allowed".to_string(),
1384 name: self.alias.clone(),
1385 src: self.raw.to_string(),
1386 });
1387 }
1388
1389 self.extract_params_code(true);
1390
1391 if self.flags.contains("|inline|") {
1392 let data: Value = match serde_json::from_str(&self.code) {
1393 Ok(value) => value,
1394 Err(_) => {
1395 return Err(BifError {
1396 code: 116,
1397 msg: "not a valid JSON file".to_string(),
1398 name: self.alias.clone(),
1399 src: self.raw.to_string(),
1400 })
1401 }
1402 };
1403
1404 let indir = &self.inherit.create_block_schema(self.shared);
1405
1406 merge_schema(
1408 &mut self.shared.schema["__indir"][indir]["data"],
1409 &data["data"],
1410 );
1411
1412 self.out = UNPRINTABLE.to_string();
1413
1414 return Ok(());
1415 }
1416
1417 self.file_path = self.code.clone();
1418
1419 if self.file_path.contains(BIF_OPEN) {
1421 if !self.contains_allow(&self.file_path) {
1422 return Err(BifError {
1423 code: 114,
1424 msg: "insecure file name".to_string(),
1425 name: self.alias.clone(),
1426 src: self.raw.to_string(),
1427 });
1428 }
1429 self.file_path = new_child_parse!(self, &self.code, false);
1430 }
1431
1432 if self.file_path.starts_with("#") {
1433 self.file_path.remove(0);
1434 self.file_path = format!("{}{}", self.inherit.current_dir, self.file_path);
1435 }
1436
1437 let path = Path::new(&self.file_path);
1438 if !Path::new(path).exists() {
1439 if self.flags.contains("|require|") {
1440 return Err(BifError {
1441 code: 115,
1442 msg: "file not found".to_string(),
1443 name: self.alias.clone(),
1444 src: self.raw.to_string(),
1445 });
1446 } else {
1447 self.out = EMPTY_STRING;
1448
1449 return Ok(());
1450 }
1451 }
1452
1453 let canonical_path = fs::canonicalize(path)
1454 .unwrap()
1455 .to_string_lossy()
1456 .into_owned();
1457
1458 if self.mod_negate && self.inherit.data_files.contains(&canonical_path) {
1459 self.out = UNPRINTABLE.to_string();
1460
1461 return Ok(());
1462 }
1463
1464 self.inherit.data_files.push(canonical_path);
1465 let file_raw = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
1466
1467 let data: Value = match serde_json::from_str(&file_raw) {
1468 Ok(value) => value,
1469 Err(_) => {
1470 return Err(BifError {
1471 code: 116,
1472 msg: "not a valid JSON file".to_string(),
1473 name: self.alias.clone(),
1474 src: self.raw.to_string(),
1475 })
1476 }
1477 };
1478
1479 let indir = &self.inherit.create_block_schema(self.shared);
1480
1481 merge_schema(
1483 &mut self.shared.schema["__indir"][indir]["data"],
1484 &data["data"],
1485 );
1486
1487 self.out = UNPRINTABLE.to_string();
1488
1489 Ok(())
1490 }
1491
1492 fn parse_bif_date(&mut self) -> Result<(), BifError> {
1497 if self.mod_filter || self.mod_negate || self.mod_scope {
1498 return Err(BifError {
1499 code: 117,
1500 msg: "modifier not allowed".to_string(),
1501 name: self.alias.clone(),
1502 src: self.raw.to_string(),
1503 });
1504 }
1505
1506 self.extract_params_code(true);
1507
1508 let now = Utc::now();
1509
1510 if self.src.contains(BIF_OPEN) {
1511 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1512 } else {
1513 self.code = self.src.trim().to_string();
1514 }
1515
1516 if self.code.is_empty() {
1517 self.out = now.timestamp().to_string();
1518 } else {
1519 self.out = now.format(&self.src).to_string();
1520 }
1521
1522 Ok(())
1523 }
1524
1525 fn parse_bif_declare(&mut self) -> Result<(), BifError> {
1529 if self.mod_filter || self.mod_negate || self.mod_scope {
1530 return Err(BifError {
1531 code: 118,
1532 msg: "modifier not allowed".to_string(),
1533 name: self.alias.clone(),
1534 src: self.raw.to_string(),
1535 });
1536 }
1537
1538 self.extract_params_code(true);
1539
1540 if self.inherit.current_file.contains(SNIPPETS_FILES) {
1541 self.inherit.create_block_schema(self.shared);
1542 if self.code.contains(BIF_OPEN) {
1543 self.code = new_child_parse!(self, &self.code, false);
1544 self.code = self.code.replace(UNPRINTABLE, "");
1545 }
1546 self.shared.schema["__indir"][&self.inherit.indir]["declare"][&self.params] =
1547 json!(&self.code);
1548
1549 self.out = EMPTY_STRING;
1550 } else {
1551 return Err(BifError {
1552 code: 119,
1553 msg: "declare cannot be set here".to_string(),
1554 name: self.alias.clone(),
1555 src: self.raw.to_string(),
1556 });
1557 }
1558
1559 Ok(())
1560 }
1561
1562 fn parse_bif_defined(&mut self) -> Result<(), BifError> {
1566 if self.mod_filter {
1567 return Err(BifError {
1568 code: 120,
1569 msg: "modifier not allowed".to_string(),
1570 name: self.alias.clone(),
1571 src: self.raw.to_string(),
1572 });
1573 }
1574
1575 self.extract_params_code(true);
1576
1577 let mut varname = self.params.as_str();
1578 let mut schema = &self.shared.schema["data"];
1579
1580 if varname.starts_with("local::") {
1581 schema = &self.shared.schema["__indir"][&self.inherit.indir]["data"];
1582 varname = varname.strip_prefix("local::").unwrap_or(varname);
1583 }
1584
1585 if is_defined_key(schema, varname) ^ self.mod_negate {
1586 if self.code.contains(BIF_OPEN) {
1587 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1588 }
1589 self.out = self.code.to_string();
1590 }
1591
1592 Ok(())
1593 }
1594
1595 fn parse_bif_each(&mut self) -> Result<(), BifError> {
1601 if self.mod_filter || self.mod_negate || self.mod_scope {
1602 return Err(BifError {
1603 code: 121,
1604 msg: "modifier not allowed".to_string(),
1605 name: self.alias.clone(),
1606 src: self.raw.to_string(),
1607 });
1608 }
1609
1610 self.extract_params_code(true);
1611 let mut parts = self.params.split_whitespace();
1612
1613 let array_name = match parts.next() {
1614 Some(value) => value.to_string(),
1615 None => {
1616 return Err(BifError {
1617 code: 122,
1618 msg: "arguments not found".to_string(),
1619 name: self.alias.clone(),
1620 src: self.raw.to_string(),
1621 })
1622 }
1623 };
1624
1625 let key_name = match parts.next() {
1626 Some(value) => value.to_string(),
1627 None => {
1628 return Err(BifError {
1629 code: 123,
1630 msg: "arguments 'key' not found".to_string(),
1631 name: self.alias.clone(),
1632 src: self.raw.to_string(),
1633 })
1634 }
1635 };
1636
1637 let val_name = match parts.next() {
1638 Some(value) => value.to_string(),
1639 None => {
1640 return Err(BifError {
1641 code: 124,
1642 msg: "arguments 'value' not found".to_string(),
1643 name: self.alias.clone(),
1644 src: self.raw.to_string(),
1645 })
1646 }
1647 };
1648
1649 let tmp: String = format!("{}{}", "/", array_name);
1650 let mut array = tmp.replace(BIF_ARRAY, "/");
1651 let restore_key = self.get_data(&key_name);
1652 let restore_val = self.get_data(&val_name);
1653
1654 let data_storage;
1655 if array.starts_with("/local::") {
1656 array = array.replace("/local::", "/");
1657 data_storage = &self.shared.schema["__indir"][&self.inherit.indir]["data"];
1658 } else {
1659 data_storage = &self.shared.schema["data"];
1660 }
1661
1662 if let Some(data_value) = data_storage.pointer(&array) {
1663 match data_value.to_owned() {
1664 Value::Object(obj) => {
1665 for (key, val) in obj.iter() {
1666 self.parse_bif_each_iter(&key_name, &val_name, key, val);
1667 }
1668 }
1669 Value::Array(arr) => {
1670 for (key, val) in arr.iter().enumerate() {
1671 self.parse_bif_each_iter(&key_name, &val_name, &key.to_string(), val);
1672 }
1673 }
1674 _ => {}
1675 }
1676 }
1677
1678 self.set_data(&key_name, &restore_key);
1679 self.set_data(&val_name, &restore_val);
1680
1681 Ok(())
1682 }
1683
1684 fn parse_bif_each_iter(&mut self, key_name: &str, val_name: &str, key: &String, val: &Value) {
1685 self.shared.schema["data"][key_name] = json!(key);
1686 self.shared.schema["data"][val_name] = json!(val);
1687 self.out += &new_child_parse!(self, &self.code, false);
1688 }
1689
1690 fn parse_bif_else(&mut self) -> Result<(), BifError> {
1696 if self.mod_filter {
1697 return Err(BifError {
1698 code: 125,
1699 msg: "modifier not allowed".to_string(),
1700 name: self.alias.clone(),
1701 src: self.raw.to_string(),
1702 });
1703 }
1704
1705 self.extract_params_code(true);
1706
1707 if self.inherit.last_bif_out ^ self.mod_negate {
1708 self.out = EMPTY_STRING;
1709
1710 return Ok(());
1711 }
1712
1713 if self.code.contains(BIF_OPEN) {
1714 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1715 }
1716
1717 self.out = self.code.to_string();
1718
1719 Ok(())
1720 }
1721
1722 fn parse_bif_eval(&mut self) -> Result<(), BifError> {
1726 if self.mod_filter {
1727 return Err(BifError {
1728 code: 126,
1729 msg: "modifier not allowed".to_string(),
1730 name: self.alias.clone(),
1731 src: self.raw.to_string(),
1732 });
1733 }
1734
1735 self.extract_params_code(false);
1736
1737 if self.params.contains(BIF_OPEN) {
1738 self.params = new_child_parse!(self, &self.params, self.mod_scope);
1739 }
1740
1741 if (self.params != EMPTY_STRING) ^ self.mod_negate {
1742 if self.code.contains(BIF_OPEN) {
1743 let restore_eval = self.get_data("__eval__");
1744 self.set_data("__eval__", &self.params.clone());
1745 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1746 self.set_data("__eval__", &restore_eval);
1747 }
1748 self.out = self.code.clone();
1749 } else {
1750 self.out = EMPTY_STRING;
1751 }
1752
1753 Ok(())
1754 }
1755
1756 fn parse_bif_exit(&mut self) -> Result<(), BifError> {
1763 if self.mod_filter || self.mod_scope {
1764 return Err(BifError {
1765 code: 127,
1766 msg: "modifier not allowed".to_string(),
1767 name: self.alias.clone(),
1768 src: self.raw.to_string(),
1769 });
1770 }
1771
1772 let has_status_params = self.extract_params_code(true);
1773
1774 if self.code.contains(BIF_OPEN) {
1775 self.code = new_child_parse!(self, &self.src, false);
1776 }
1777
1778 let mut status_code = "200";
1779 let mut status_param = "";
1780
1781 if has_status_params {
1782 if !self.params.is_empty() {
1783 status_code = self.params.as_str();
1784 }
1785 status_param = &self.code;
1786 } else if !self.code.is_empty() {
1787 status_code = self.code.as_str();
1788 }
1789
1790 self.shared.status_code = status_code.to_string();
1791 self.shared.status_param = status_param.to_string();
1792
1793 if let Some(text) = STATUS_CODES.get(status_code) {
1794 self.shared.status_text = text.to_string();
1795 } else {
1796 self.shared.status_text = EMPTY_STRING;
1797 }
1798
1799 self.shared.exit = true ^ self.mod_negate;
1800 self.out = EMPTY_STRING;
1801
1802 Ok(())
1803 }
1804
1805 fn parse_bif_filled(&mut self) -> Result<(), BifError> {
1812 if self.mod_filter {
1813 return Err(BifError {
1814 code: 128,
1815 msg: "modifier not allowed".to_string(),
1816 name: self.alias.clone(),
1817 src: self.raw.to_string(),
1818 });
1819 }
1820
1821 self.extract_params_code(true);
1822
1823 let mut varname = self.params.as_str();
1824 let mut schema = &self.shared.schema["data"];
1825
1826 if varname.starts_with("local::") {
1827 schema = &self.shared.schema["__indir"][&self.inherit.indir]["data"];
1828 varname = varname.strip_prefix("local::").unwrap_or(varname);
1829 }
1830
1831 if !is_empty_key(schema, varname) ^ self.mod_negate {
1832 if self.code.contains(BIF_OPEN) {
1833 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1834 }
1835
1836 self.out = self.code.to_string();
1837 }
1838
1839 Ok(())
1840 }
1841
1842 fn parse_bif_flg(&mut self) -> Result<(), BifError> {
1847 if self.mod_filter || self.mod_negate || self.mod_upline || self.mod_scope {
1848 return Err(BifError {
1849 code: 129,
1850 msg: "modifier not allowed".to_string(),
1851 name: self.alias.clone(),
1852 src: self.raw.to_string(),
1853 });
1854 }
1855
1856 self.extract_params_code(true);
1857
1858 if self.code.contains(BIF_OPEN) {
1859 self.code = new_child_parse!(self, &self.code, false);
1860 }
1861
1862 let flags = format!(" {} ", self.code);
1863 self.shared.flags = flags.replace(" ", "|");
1864 self.out = EMPTY_STRING;
1865
1866 Ok(())
1867 }
1868
1869 fn parse_bif_for(&mut self) -> Result<(), BifError> {
1875 if self.mod_filter || self.mod_negate || self.mod_scope {
1876 return Err(BifError {
1877 code: 130,
1878 msg: "modifier not allowed".to_string(),
1879 name: self.alias.clone(),
1880 src: self.raw.to_string(),
1881 });
1882 }
1883
1884 self.extract_params_code(true);
1885 self.params = self.params.replace("..", " ");
1886 let mut parts = self.params.split_whitespace();
1887
1888 let var_name = match parts.next() {
1889 Some(value) => value.to_string(),
1890 None => {
1891 return Err(BifError {
1892 code: 131,
1893 msg: "arguments not found".to_string(),
1894 name: self.alias.clone(),
1895 src: self.raw.to_string(),
1896 })
1897 }
1898 };
1899
1900 let from = match parts.next() {
1901 Some(value) => match value.parse::<i32>() {
1902 Ok(num) => num,
1903 Err(_) => {
1904 return Err(BifError {
1905 code: 132,
1906 msg: "argument is not a number".to_string(),
1907 name: self.alias.clone(),
1908 src: self.raw.to_string(),
1909 })
1910 }
1911 },
1912 None => {
1913 return Err(BifError {
1914 code: 133,
1915 msg: "arguments 'from' and 'to' not found".to_string(),
1916 name: self.alias.clone(),
1917 src: self.raw.to_string(),
1918 })
1919 }
1920 };
1921
1922 let to = match parts.next() {
1923 Some(value) => match value.parse::<i32>() {
1924 Ok(num) => num,
1925 Err(_) => {
1926 return Err(BifError {
1927 code: 134,
1928 msg: "argument is not a number".to_string(),
1929 name: self.alias.clone(),
1930 src: self.raw.to_string(),
1931 })
1932 }
1933 },
1934 None => {
1935 return Err(BifError {
1936 code: 135,
1937 msg: "arguments 'to' not found".to_string(),
1938 name: self.alias.clone(),
1939 src: self.raw.to_string(),
1940 })
1941 }
1942 };
1943
1944 let range = if from > to {
1945 (to..=from).rev().collect::<Vec<i32>>()
1946 } else {
1947 (from..=to).collect::<Vec<i32>>()
1948 };
1949
1950 let restore_var = self.get_data(&var_name);
1951 for i in range {
1952 self.set_data(&var_name, &i.to_string());
1953 self.out += &new_child_parse!(self, &self.code, self.mod_scope);
1954 }
1955 self.set_data(&var_name, &restore_var);
1956
1957 Ok(())
1958 }
1959
1960 fn parse_bif_hash(&mut self) -> Result<(), BifError> {
1965 if self.mod_filter || self.mod_negate || self.mod_scope {
1966 return Err(BifError {
1967 code: 136,
1968 msg: "modifier not allowed".to_string(),
1969 name: self.alias.clone(),
1970 src: self.raw.to_string(),
1971 });
1972 }
1973
1974 self.code = self.src.trim().to_string();
1975
1976 if self.src.contains(BIF_OPEN) {
1977 self.code = new_child_parse!(self, &self.code, self.mod_scope);
1978 } else {
1979 self.code = self.code.trim().to_string();
1980 }
1981
1982 if self.code.is_empty() {
1983 let mut hasher = Md5::new();
1984 let mut rng = rand::rng();
1985 let rand = rng.random_range(100000000..=999999999).to_string();
1986 hasher.update(&rand);
1987 self.out = format!("{:x}", hasher.finalize())
1988 } else {
1989 let mut hasher = Md5::new();
1990 hasher.update(&self.code);
1991 self.out = format!("{:x}", hasher.finalize());
1992 }
1993
1994 Ok(())
1995 }
1996
1997 fn parse_bif_include(&mut self) -> Result<(), BifError> {
2002 if self.mod_filter || self.mod_scope {
2003 return Err(BifError {
2004 code: 137,
2005 msg: "modifier not allowed".to_string(),
2006 name: self.alias.clone(),
2007 src: self.raw.to_string(),
2008 });
2009 }
2010
2011 self.extract_params_code(true);
2012 self.file_path = self.code.clone();
2013
2014 if self.file_path.contains(BIF_OPEN) {
2016 if !self.contains_allow(&self.file_path) {
2017 return Err(BifError {
2018 code: 138,
2019 msg: "insecure file name".to_string(),
2020 name: self.alias.clone(),
2021 src: self.raw.to_string(),
2022 });
2023 }
2024 self.file_path = new_child_parse!(self, &self.code, false);
2025 }
2026
2027 if self.file_path.starts_with("#") {
2028 self.file_path.remove(0);
2029 self.file_path = format!("{}{}", self.inherit.current_dir, self.file_path);
2030 }
2031
2032 let path = Path::new(&self.file_path);
2033 if !path.exists() {
2034 if self.flags.contains("|require|") {
2035 return Err(BifError {
2036 code: 139,
2037 msg: "file not found".to_string(),
2038 name: self.alias.clone(),
2039 src: self.raw.to_string(),
2040 });
2041 } else {
2042 return Ok(());
2043 }
2044 }
2045
2046 if let Some(parent) = path.parent() {
2047 self.dir = parent.display().to_string();
2048 }
2049
2050 let canonical_path = fs::canonicalize(path)
2051 .unwrap()
2052 .to_string_lossy()
2053 .into_owned();
2054
2055 if self.mod_negate && self.inherit.include_files.contains(&canonical_path) {
2056 self.out = EMPTY_STRING;
2057
2058 return Ok(());
2059 }
2060
2061 if self.flags.contains("|safe|") {
2062 self.code = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
2063 self.code = escape_chars(&unescape_chars(&self.code, false), false).to_string();
2064 self.code = self.code.replace(BIF_OPEN, BIF_SANITIZE_OPEN);
2065 self.code = self.code.replace(BIF_CLOSE, BIF_SANITIZE_CLOSE);
2066 self.out = self.code.clone();
2067
2068 return Ok(());
2069 }
2070
2071 if self.flags.contains("|noparse|") {
2072 self.code = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
2073 self.out = self.code.clone();
2074
2075 return Ok(());
2076 }
2077
2078 self.inherit.include_files.push(canonical_path);
2079
2080 let mut file_raw = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
2081 if self.shared.comments.contains("remove") {
2082 file_raw = remove_comments(&file_raw);
2083 }
2084
2085 self.out = new_child_parse!(self, &file_raw, true);
2086
2087 Ok(())
2088 }
2089
2090 fn parse_bif_lang(&mut self) -> Result<(), BifError> {
2094 if self.mod_filter || self.mod_negate || self.mod_scope {
2095 return Err(BifError {
2096 code: 140,
2097 msg: "modifier not allowed".to_string(),
2098 name: self.alias.clone(),
2099 src: self.raw.to_string(),
2100 });
2101 }
2102
2103 self.out = self.shared.lang.to_string();
2104
2105 Ok(())
2106 }
2107
2108 fn parse_bif_locale(&mut self) -> Result<(), BifError> {
2112 if self.mod_filter || self.mod_scope {
2113 return Err(BifError {
2114 code: 141,
2115 msg: "modifier not allowed".to_string(),
2116 name: self.alias.clone(),
2117 src: self.raw.to_string(),
2118 });
2119 }
2120
2121 self.extract_params_code(true);
2122
2123 if self.flags.contains("|inline|") {
2124 if self.code.contains(BIF_OPEN) {
2126 self.code = new_child_parse!(self, &self.code, false);
2127 }
2128
2129 let locale: Value = match serde_json::from_str(&self.code) {
2130 Ok(value) => value,
2131 Err(_) => {
2132 return Err(BifError {
2133 code: 142,
2134 msg: "not a valid JSON string".to_string(),
2135 name: self.alias.clone(),
2136 src: self.raw.to_string(),
2137 })
2138 }
2139 };
2140
2141 let indir = &self.inherit.create_block_schema(self.shared);
2142
2143 merge_schema(&mut self.shared.schema["__indir"][indir]["locale"], &locale);
2145
2146 self.out = EMPTY_STRING;
2147
2148 return Ok(());
2149 }
2150
2151 self.file_path = self.code.clone();
2152
2153 if self.file_path.contains(BIF_OPEN) {
2155 if !self.contains_allow(&self.file_path) {
2156 return Err(BifError {
2157 code: 143,
2158 msg: "insecure file name".to_string(),
2159 name: self.alias.clone(),
2160 src: self.raw.to_string(),
2161 });
2162 }
2163 self.file_path = new_child_parse!(self, &self.code, false);
2164 }
2165
2166 if self.file_path.starts_with("#") {
2167 self.file_path.remove(0);
2168 self.file_path = format!("{}{}", self.inherit.current_dir, self.file_path);
2169 }
2170
2171 let path = Path::new(&self.file_path);
2172 if !Path::new(path).exists() {
2173 if self.flags.contains("|require|") {
2174 return Err(BifError {
2175 code: 144,
2176 msg: "file not found".to_string(),
2177 name: self.alias.clone(),
2178 src: self.raw.to_string(),
2179 });
2180 } else {
2181 return Ok(());
2182 }
2183 }
2184
2185 let canonical_path = fs::canonicalize(path)
2186 .unwrap()
2187 .to_string_lossy()
2188 .into_owned();
2189 if self.mod_negate && self.inherit.locale_files.contains(&canonical_path) {
2190 self.out = UNPRINTABLE.to_string();
2191
2192 return Ok(());
2193 }
2194
2195 self.inherit.locale_files.push(canonical_path);
2196 let mut file_raw = fs::read_to_string(&self.file_path).unwrap_or("".to_string());
2197
2198 if !self.flags.contains("|noparse|") {
2199 if file_raw.contains(BIF_OPEN) {
2201 file_raw = new_child_parse!(self, &file_raw, false);
2202 }
2203 }
2204
2205 let locale: Value = match serde_json::from_str(&file_raw) {
2206 Ok(value) => value,
2207 Err(_) => {
2208 return Err(BifError {
2209 code: 145,
2210 msg: "not a valid JSON file".to_string(),
2211 name: self.alias.clone(),
2212 src: self.raw.to_string(),
2213 })
2214 }
2215 };
2216
2217 let indir = &self.inherit.create_block_schema(self.shared);
2218
2219 merge_schema(&mut self.shared.schema["__indir"][indir]["locale"], &locale);
2221
2222 self.out = UNPRINTABLE.to_string();
2223
2224 Ok(())
2225 }
2226
2227 fn parse_bif_moveto(&mut self) -> Result<(), BifError> {
2232 if self.mod_filter || self.mod_negate || self.mod_scope {
2233 return Err(BifError {
2234 code: 146,
2235 msg: "modifier not allowed".to_string(),
2236 name: self.alias.clone(),
2237 src: self.raw.to_string(),
2238 });
2239 }
2240
2241 self.extract_params_code(true);
2242 let mut moveto = json!({});
2243 let mut hasher = Md5::new();
2244
2245 if self.code.contains(BIF_OPEN) {
2246 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2247 }
2248
2249 hasher.update(&self.code);
2251 let code_hash = hasher.finalize();
2252 let code_hash = format!("{:x}", code_hash);
2253
2254 moveto[&self.params] = json!(&self.code);
2255 self.shared.schema["__moveto"][&code_hash] = moveto;
2256 self.out = EMPTY_STRING;
2257
2258 Ok(())
2259 }
2260
2261 fn parse_bif_neutral(&mut self) -> Result<(), BifError> {
2265 if self.mod_filter || self.mod_negate || self.mod_scope {
2266 return Err(BifError {
2267 code: 147,
2268 msg: "modifier not allowed".to_string(),
2269 name: self.alias.clone(),
2270 src: self.raw.to_string(),
2271 });
2272 }
2273
2274 self.out = format!(
2275 "{}{}{}{}{}",
2276 BIF_OPEN, self.name, BIF_NAME, self.src, BIF_CLOSE
2277 );
2278
2279 Ok(())
2280 }
2281
2282 fn parse_bif_param(&mut self) -> Result<(), BifError> {
2287 if self.mod_filter || self.mod_negate || self.mod_scope {
2288 return Err(BifError {
2289 code: 148,
2290 msg: "modifier not allowed".to_string(),
2291 name: self.alias.clone(),
2292 src: self.raw.to_string(),
2293 });
2294 }
2295
2296 let is_set = self.extract_params_code(true);
2297 if is_set {
2298 if self.inherit.alias == "code" {
2299 if self.code.contains(BIF_OPEN) {
2300 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2301 }
2302
2303 self.inherit.create_block_schema(self.shared);
2304 self.shared.schema["__indir"][&self.inherit.indir]["params"][&self.params] =
2305 json!(&self.code);
2306 self.out = EMPTY_STRING;
2307
2308 Ok(())
2309 } else {
2310 Err(BifError {
2311 code: 149,
2312 msg: "param cannot be set here".to_string(),
2313 name: self.alias.clone(),
2314 src: self.raw.to_string(),
2315 })
2316 }
2317 } else {
2318 if self.code.contains(BIF_OPEN) {
2319 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2320 }
2321
2322 self.code = get_from_key(
2323 &self.shared.schema["__indir"][&self.inherit.indir]["params"],
2324 &self.code,
2325 );
2326 self.out = self.code.to_string();
2327
2328 Ok(())
2329 }
2330 }
2331
2332 fn parse_bif_rand(&mut self) -> Result<(), BifError> {
2337 if self.mod_filter || self.mod_negate || self.mod_scope {
2338 return Err(BifError {
2339 code: 150,
2340 msg: "modifier not allowed".to_string(),
2341 name: self.alias.clone(),
2342 src: self.raw.to_string(),
2343 });
2344 }
2345
2346 let mut rng = rand::rng();
2347 self.code = self.src.trim().to_string();
2348
2349 if self.src.contains(BIF_OPEN) {
2350 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2351 } else {
2352 self.code = self.src.trim().to_string();
2353 }
2354
2355 if self.code.is_empty() {
2356 self.out = rng.random_range(100000000..=999999999).to_string();
2357 } else {
2358 self.code = self.code.replace("..", " ");
2360 let mut parts = self.code.split_whitespace();
2361
2362 let from = match parts.next() {
2363 Some(value) => match value.parse::<i32>() {
2364 Ok(num) => num,
2365 Err(_) => {
2366 return Err(BifError {
2367 code: 151,
2368 msg: "argument is not a number".to_string(),
2369 name: self.alias.clone(),
2370 src: self.raw.to_string(),
2371 })
2372 }
2373 },
2374 None => {
2375 return Err(BifError {
2376 code: 152,
2377 msg: "arguments not found".to_string(),
2378 name: self.alias.clone(),
2379 src: self.raw.to_string(),
2380 })
2381 }
2382 };
2383
2384 let to = match parts.next() {
2385 Some(value) => match value.parse::<i32>() {
2386 Ok(num) => num,
2387 Err(_) => {
2388 return Err(BifError {
2389 code: 153,
2390 msg: "argument is not a number".to_string(),
2391 name: self.alias.clone(),
2392 src: self.raw.to_string(),
2393 })
2394 }
2395 },
2396 None => {
2397 return Err(BifError {
2398 code: 154,
2399 msg: "arguments not found".to_string(),
2400 name: self.alias.clone(),
2401 src: self.raw.to_string(),
2402 })
2403 }
2404 };
2405
2406 if from > to {
2407 return Err(BifError {
2408 code: 155,
2409 msg: "from > to".to_string(),
2410 name: self.alias.clone(),
2411 src: self.raw.to_string(),
2412 });
2413 }
2414
2415 self.out = rng.random_range(from..=to).to_string();
2416 }
2417
2418 Ok(())
2419 }
2420
2421 fn parse_bif_redirect(&mut self) -> Result<(), BifError> {
2426 if self.mod_filter || self.mod_scope || self.mod_negate {
2427 return Err(BifError {
2428 code: 156,
2429 msg: "modifier not allowed".to_string(),
2430 name: self.alias.clone(),
2431 src: self.raw.to_string(),
2432 });
2433 }
2434
2435 let status_code;
2436 let has_status_params = self.extract_params_code(true);
2437
2438 if self.code.contains(BIF_OPEN) {
2439 self.code = new_child_parse!(self, &self.src, false);
2440 }
2441
2442 if has_status_params {
2443 status_code = match self.params.as_str() {
2445 "301" => {
2446 if self.code.is_empty() {
2447 return Err(BifError {
2448 code: 157,
2449 msg: "this redirection requires URL".to_string(),
2450 name: self.alias.clone(),
2451 src: self.raw.to_string(),
2452 });
2453 }
2454
2455 "301"
2456 }
2457 "302" => {
2458 if self.code.is_empty() {
2459 return Err(BifError {
2460 code: 158,
2461 msg: "this redirection requires URL".to_string(),
2462 name: self.alias.clone(),
2463 src: self.raw.to_string(),
2464 });
2465 }
2466
2467 "302"
2468 }
2469 "303" => {
2470 if self.code.is_empty() {
2471 return Err(BifError {
2472 code: 159,
2473 msg: "this redirection requires URL".to_string(),
2474 name: self.alias.clone(),
2475 src: self.raw.to_string(),
2476 });
2477 }
2478
2479 "303"
2480 }
2481 "307" => {
2482 if self.code.is_empty() {
2483 return Err(BifError {
2484 code: 160,
2485 msg: "this redirection requires URL".to_string(),
2486 name: self.alias.clone(),
2487 src: self.raw.to_string(),
2488 });
2489 }
2490
2491 "307"
2492 }
2493 "308" => {
2494 if self.code.is_empty() {
2495 return Err(BifError {
2496 code: 161,
2497 msg: "this redirection requires URL".to_string(),
2498 name: self.alias.clone(),
2499 src: self.raw.to_string(),
2500 });
2501 }
2502
2503 "308"
2504 }
2505 "js:reload:top" => {
2506 self.shared.redirect_js = REDIR_JS_RELOAD_TOP.to_string();
2507
2508 "200"
2509 }
2510 "js:reload:self" => {
2511 self.shared.redirect_js = REDIR_JS_RELOAD_SELF.to_string();
2512
2513 "200"
2514 }
2515 "js:redirect:top" => {
2516 if self.code.is_empty() {
2517 return Err(BifError {
2518 code: 162,
2519 msg: "this redirection requires URL".to_string(),
2520 name: self.alias.clone(),
2521 src: self.raw.to_string(),
2522 });
2523 }
2524 self.shared.redirect_js =
2526 REDIR_JS_REDIRECT_TOP.replace("{}", &self.code).to_string();
2527
2528 "200"
2529 }
2530 "js:redirect:self" => {
2531 if self.code.is_empty() {
2532 return Err(BifError {
2533 code: 163,
2534 msg: "this redirection requires URL".to_string(),
2535 name: self.alias.clone(),
2536 src: self.raw.to_string(),
2537 });
2538 }
2539 self.shared.redirect_js =
2541 REDIR_JS_REDIRECT_SELF.replace("{}", &self.code).to_string();
2542
2543 "200"
2544 }
2545 _ => {
2546 if !self.code.contains("js:reload:self") || !self.code.contains("js:reload:top")
2548 {
2549 return Err(BifError {
2550 code: 164,
2551 msg: "status code not allowed".to_string(),
2552 name: self.alias.clone(),
2553 src: self.raw.to_string(),
2554 });
2555 } else {
2556 "200"
2557 }
2558 }
2559 };
2560 } else {
2561 status_code = match self.code.as_str() {
2563 "js:reload:top" => {
2564 self.shared.redirect_js = REDIR_JS_RELOAD_TOP.to_string();
2565
2566 "200"
2567 }
2568 "js:reload:self" => {
2569 self.shared.redirect_js = REDIR_JS_RELOAD_SELF.to_string();
2570
2571 "200"
2572 }
2573 _ => {
2574 return Err(BifError {
2575 code: 165,
2576 msg: "redirect type not allowed".to_string(),
2577 name: self.alias.clone(),
2578 src: self.raw.to_string(),
2579 })
2580 }
2581 };
2582 }
2583
2584 self.shared.status_param = self.code.to_string();
2585 self.shared.status_code = status_code.to_string();
2586
2587 if let Some(text) = STATUS_CODES.get(status_code) {
2588 self.shared.status_text = text.to_string();
2589 } else {
2590 self.shared.status_text = EMPTY_STRING;
2591 }
2592
2593 self.shared.exit = true ^ self.mod_negate;
2594 self.out = EMPTY_STRING;
2595
2596 Ok(())
2597 }
2598
2599 fn parse_bif_replace(&mut self) -> Result<(), BifError> {
2604 if self.mod_filter || self.mod_negate || self.mod_scope {
2605 return Err(BifError {
2606 code: 166,
2607 msg: "modifier not allowed".to_string(),
2608 name: self.alias.clone(),
2609 src: self.raw.to_string(),
2610 });
2611 }
2612
2613 self.extract_params_code(false);
2614
2615 let delim;
2616 if let Some(first_char) = self.params.chars().next() {
2617 delim = first_char;
2618 } else {
2619 return Err(BifError {
2620 code: 167,
2621 msg: "missing arguments".to_string(),
2622 name: self.alias.clone(),
2623 src: self.raw.to_string(),
2624 });
2625 }
2626
2627 let mut parts = self.params.split(delim);
2628
2629 parts.next();
2631
2632 let mut from = match parts.next() {
2633 Some(value) => value.to_string(),
2634 None => {
2635 return Err(BifError {
2636 code: 168,
2637 msg: "arguments not found".to_string(),
2638 name: self.alias.clone(),
2639 src: self.raw.to_string(),
2640 })
2641 }
2642 };
2643
2644 let mut to = match parts.next() {
2645 Some(value) => value.to_string(),
2646 None => {
2647 return Err(BifError {
2648 code: 169,
2649 msg: "arguments not found".to_string(),
2650 name: self.alias.clone(),
2651 src: self.raw.to_string(),
2652 })
2653 }
2654 };
2655
2656 if to.contains(BIF_OPEN) {
2657 to = new_child_parse!(self, &to, false);
2658 }
2659
2660 if from.contains(BIF_OPEN) {
2661 from = new_child_parse!(self, &from, false);
2662 }
2663
2664 if self.code.contains(BIF_OPEN) {
2665 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2666 }
2667
2668 self.out = self.code.replace(&from, &to);
2669
2670 Ok(())
2671 }
2672
2673 fn parse_bif_same(&mut self) -> Result<(), BifError> {
2677 if self.mod_filter {
2678 return Err(BifError {
2679 code: 120,
2680 msg: "modifier not allowed".to_string(),
2681 name: self.alias.clone(),
2682 src: self.raw.to_string(),
2683 });
2684 }
2685
2686 self.extract_params_code(false);
2687
2688 let delim;
2689 if let Some(first_char) = self.params.chars().next() {
2690 delim = first_char;
2691 } else {
2692 return Err(BifError {
2693 code: 173,
2694 msg: "missing arguments".to_string(),
2695 name: self.alias.clone(),
2696 src: self.raw.to_string(),
2697 });
2698 }
2699
2700 let mut parts = self.params.split(delim);
2701
2702 parts.next();
2704
2705 let mut param1 = match parts.next() {
2706 Some(value) => value.to_string(),
2707 None => {
2708 return Err(BifError {
2709 code: 174,
2710 msg: "arguments not found".to_string(),
2711 name: self.alias.clone(),
2712 src: self.raw.to_string(),
2713 })
2714 }
2715 };
2716
2717 let mut param2 = match parts.next() {
2718 Some(value) => value.to_string(),
2719 None => {
2720 return Err(BifError {
2721 code: 175,
2722 msg: "arguments not found".to_string(),
2723 name: self.alias.clone(),
2724 src: self.raw.to_string(),
2725 })
2726 }
2727 };
2728
2729 if param1.contains(BIF_OPEN) {
2730 param1 = new_child_parse!(self, ¶m1, false);
2731 }
2732
2733 if param2.contains(BIF_OPEN) {
2734 param2 = new_child_parse!(self, ¶m2, false);
2735 }
2736
2737 if (param1 == param2) ^ self.mod_negate {
2738 if self.code.contains(BIF_OPEN) {
2739 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2740 }
2741 self.out = self.code.to_string();
2742 } else {
2743 self.out = EMPTY_STRING;
2744 }
2745
2746 Ok(())
2747 }
2748
2749 fn parse_bif_snippet(&mut self) -> Result<(), BifError> {
2759 if self.mod_filter || self.mod_negate || self.mod_scope {
2760 return Err(BifError {
2761 code: 170,
2762 msg: "modifier not allowed".to_string(),
2763 name: self.alias.clone(),
2764 src: self.raw.to_string(),
2765 });
2766 }
2767
2768 self.alias = "snippet".to_string();
2769
2770 let is_set = self.extract_params_code(true);
2771 if is_set {
2772 if self.inherit.current_file.contains(SNIPPETS_FILES) || self.inherit.alias == "snippet"
2774 {
2775 if self.flags.contains("|static|") {
2776 self.code = new_child_parse!(self, &self.code, self.mod_scope);
2777 } else {
2778 self.inherit.create_block_schema(self.shared);
2780 }
2781 self.shared.schema["__indir"][&self.inherit.indir]["snippets"][&self.params] =
2782 json!(&self.code);
2783
2784 self.shared.schema["__indir"][&self.inherit.indir]["snippets_set_dir"][&self.params] =
2786 json!(&self.inherit.current_dir);
2787
2788 self.out = EMPTY_STRING;
2789
2790 Ok(())
2791 } else {
2792 Err(BifError {
2793 code: 171,
2794 msg: "snippet cannot be set here".to_string(),
2795 name: self.alias.clone(),
2796 src: self.raw.to_string(),
2797 })
2798 }
2799 } else {
2800 if self.code.contains(BIF_OPEN) {
2802 self.code = new_child_parse!(self, &self.code, false);
2803 }
2804 let snip_name = self.code.clone();
2805
2806 self.code = get_from_key(
2807 &self.shared.schema["__indir"][&self.inherit.indir]["snippets"],&self.code,
2808 );
2809
2810 if self.code.contains(BIF_OPEN) {
2811
2812 let set_dir = get_from_key(
2814 &self.shared.schema["__indir"][&self.inherit.indir]["snippets_set_dir"],&snip_name,
2815 );
2816
2817 if !set_dir.is_empty() {
2818 self.inherit.current_dir = set_dir;
2819 }
2820
2821 self.code = new_child_parse!(self, &self.code, self.code.contains("{:snip"));
2823 }
2824
2825 self.out = self.code.to_string();
2826
2827 Ok(())
2828 }
2829 }
2830
2831 fn parse_bif_trans(&mut self) -> Result<(), BifError> {
2835 if self.mod_filter || self.mod_scope {
2836 return Err(BifError {
2837 code: 172,
2838 msg: "modifier not allowed".to_string(),
2839 name: self.alias.clone(),
2840 src: self.raw.to_string(),
2841 });
2842 }
2843
2844 if self.src.contains(BIF_OPEN) {
2846 self.src = new_child_parse!(self, &self.src, self.mod_scope);
2847 }
2848
2849 let trans = self.get_trans(&self.src);
2850
2851 if trans.is_empty() {
2853 if self.mod_negate {
2854 self.out = EMPTY_STRING;
2855 } else {
2856 self.out = self.src.clone();
2857 }
2858 } else {
2859 self.out = trans;
2860 }
2861
2862 Ok(())
2863 }
2864}