neutralts/bif/
parse_bif_redirect.rs

1#![doc = include_str!("../../doc/bif-redirect.md")]
2
3use crate::{bif::constants::*, bif::Bif, bif::BifError, constants::*};
4
5impl<'a> Bif<'a> {
6    /*
7        {:redirect; 301 >> /page :}
8        {:redirect; js:reload:top >> (none) :}
9    */
10    pub(crate) fn parse_bif_redirect(&mut self) -> Result<(), BifError> {
11        if self.mod_filter || self.mod_scope || self.mod_negate {
12            return Err(self.bif_error(BIF_ERROR_MODIFIER_NOT_ALLOWED));
13        }
14
15        if self.inherit.in_cache {
16            self.out = format!("{}{}{}", "{:!cache;", self.raw.to_string(), ":}");
17        } else {
18            self.out = EMPTY_STRING;
19        }
20
21        let status_code;
22        let has_status_params = self.extract_params_code(true);
23
24        if !self.flags.is_empty() {
25            return Err(self.bif_error(BIF_ERROR_FLAGS_NOT_ALLOWED));
26        }
27
28        if self.code.contains(BIF_OPEN) {
29            self.code = new_child_parse!(self, &self.code, false);
30        }
31
32        if has_status_params {
33            // When parameters are required or optional in BIF
34            status_code = match self.params.as_str() {
35                "301" => {
36                    if self.code.is_empty() {
37                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
38                    }
39
40                    "301"
41                }
42                "302" => {
43                    if self.code.is_empty() {
44                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
45                    }
46
47                    "302"
48                }
49                "303" => {
50                    if self.code.is_empty() {
51                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
52                    }
53
54                    "303"
55                }
56                "307" => {
57                    if self.code.is_empty() {
58                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
59                    }
60
61                    "307"
62                }
63                "308" => {
64                    if self.code.is_empty() {
65                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
66                    }
67
68                    "308"
69                }
70                "js:reload:top" => {
71                    self.shared.redirect_js = REDIR_JS_RELOAD_TOP.to_string();
72
73                    "200"
74                }
75                "js:reload:self" => {
76                    self.shared.redirect_js = REDIR_JS_RELOAD_SELF.to_string();
77
78                    "200"
79                }
80                "js:redirect:top" => {
81                    if self.code.is_empty() {
82                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
83                    }
84                    // TODO replace(['%2F','%3A','%3F','%3D','%26'], ['/',':','?','=','&'], url);
85                    self.shared.redirect_js =
86                        REDIR_JS_REDIRECT_TOP.replace("{}", &self.code).to_string();
87
88                    "200"
89                }
90                "js:redirect:self" => {
91                    if self.code.is_empty() {
92                        return Err(self.bif_error(BIF_ERROR_REDIRECT_REQUIRES_URL));
93                    }
94                    // TODO replace(['%2F','%3A','%3F','%3D','%26'], ['/',':','?','=','&'], url);
95                    self.shared.redirect_js =
96                        REDIR_JS_REDIRECT_SELF.replace("{}", &self.code).to_string();
97
98                    "200"
99                }
100                _ => {
101                    // Parameters are optional in js:reload:self and js:reload:top
102                    if !self.code.contains("js:reload:self") || !self.code.contains("js:reload:top")
103                    {
104                        return Err(self.bif_error(BIF_ERROR_STATUS_CODE_NOT_ALLOWED));
105                    } else {
106                        "200"
107                    }
108                }
109            };
110        } else {
111            // When parameters are not needed in BIF
112            status_code = match self.code.as_str() {
113                "js:reload:top" => {
114                    self.shared.redirect_js = REDIR_JS_RELOAD_TOP.to_string();
115
116                    "200"
117                }
118                "js:reload:self" => {
119                    self.shared.redirect_js = REDIR_JS_RELOAD_SELF.to_string();
120
121                    "200"
122                }
123                _ => return Err(self.bif_error(BIF_ERROR_REDIRECT_TYPE_NOT_ALLOWED)),
124            };
125        }
126
127        self.shared.status_param = self.code.to_string();
128        self.shared.status_code = status_code.to_string();
129
130        if let Some(text) = STATUS_CODES.get(status_code) {
131            self.shared.status_text = text.to_string();
132        } else {
133            self.shared.status_text = EMPTY_STRING;
134        }
135
136        self.shared.exit = true ^ self.mod_negate;
137
138        Ok(())
139    }
140}
141
142#[cfg(test)]
143#[path = "parse_bif_redirect_tests.rs"]
144mod tests;