sieve/compiler/grammar/actions/
action_fileinto.rs

1/*
2 * Copyright (c) 2020-2023, Stalwart Labs Ltd.
3 *
4 * This file is part of the Stalwart Sieve Interpreter.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 * in the LICENSE file at the top-level directory of this distribution.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 *
19 * You can be released from the requirements of the AGPLv3 license by
20 * purchasing a commercial license. Please contact licensing@stalw.art
21 * for more details.
22*/
23
24use serde::{Deserialize, Serialize};
25
26use crate::compiler::{
27    grammar::{
28        instruction::{CompilerState, Instruction},
29        Capability,
30    },
31    lexer::{word::Word, Token},
32    CompileError, Value,
33};
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36pub struct FileInto {
37    pub copy: bool,
38    pub create: bool,
39    pub folder: Value,
40    pub flags: Vec<Value>,
41    pub mailbox_id: Option<Value>,
42    pub special_use: Option<Value>,
43}
44
45impl<'x> CompilerState<'x> {
46    pub(crate) fn parse_fileinto(&mut self) -> Result<(), CompileError> {
47        let folder;
48        let mut copy = false;
49        let mut create = false;
50        let mut flags = Vec::new();
51        let mut mailbox_id = None;
52        let mut special_use = None;
53
54        loop {
55            let token_info = self.tokens.unwrap_next()?;
56            match token_info.token {
57                Token::Tag(Word::Copy) => {
58                    self.validate_argument(
59                        1,
60                        Capability::Copy.into(),
61                        token_info.line_num,
62                        token_info.line_pos,
63                    )?;
64                    copy = true;
65                }
66                Token::Tag(Word::Create) => {
67                    self.validate_argument(
68                        2,
69                        Capability::Mailbox.into(),
70                        token_info.line_num,
71                        token_info.line_pos,
72                    )?;
73                    create = true;
74                }
75                Token::Tag(Word::Flags) => {
76                    self.validate_argument(
77                        3,
78                        Capability::Imap4Flags.into(),
79                        token_info.line_num,
80                        token_info.line_pos,
81                    )?;
82                    flags = self.parse_strings(false)?;
83                }
84                Token::Tag(Word::MailboxId) => {
85                    self.validate_argument(
86                        4,
87                        Capability::Mailbox.into(),
88                        token_info.line_num,
89                        token_info.line_pos,
90                    )?;
91                    mailbox_id = self.parse_string()?.into();
92                }
93                Token::Tag(Word::SpecialUse) => {
94                    self.validate_argument(
95                        5,
96                        Capability::SpecialUse.into(),
97                        token_info.line_num,
98                        token_info.line_pos,
99                    )?;
100                    special_use = self.parse_string()?.into();
101                }
102                _ => {
103                    folder = self.parse_string_token(token_info)?;
104                    break;
105                }
106            }
107        }
108
109        self.instructions.push(Instruction::FileInto(FileInto {
110            folder,
111            copy,
112            create,
113            flags,
114            mailbox_id,
115            special_use,
116        }));
117        Ok(())
118    }
119}