1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2 */
3
4 /* Extension copy
5 * --------------
6 *
7 * Authors: Stephan Bosch
8 * Specification: RFC 3894
9 * Implementation: full
10 * Status: testing
11 *
12 */
13
14 #include "sieve-common.h"
15
16 #include "sieve-code.h"
17 #include "sieve-extensions.h"
18 #include "sieve-actions.h"
19 #include "sieve-commands.h"
20 #include "sieve-validator.h"
21 #include "sieve-generator.h"
22 #include "sieve-interpreter.h"
23 #include "sieve-result.h"
24
25 #include "sieve-ext-copy.h"
26
27 /*
28 * Forward declarations
29 */
30
31 static const struct sieve_argument_def copy_tag;
32 static const struct sieve_operand_def copy_side_effect_operand;
33
34 /*
35 * Extension
36 */
37
38 static bool
39 ext_copy_validator_load(const struct sieve_extension *ext,
40 struct sieve_validator *valdtr);
41
42 const struct sieve_extension_def copy_extension = {
43 .name = "copy",
44 .validator_load = ext_copy_validator_load,
45 SIEVE_EXT_DEFINE_OPERAND(copy_side_effect_operand),
46 };
47
48 static bool
ext_copy_validator_load(const struct sieve_extension * ext,struct sieve_validator * valdtr)49 ext_copy_validator_load(const struct sieve_extension *ext,
50 struct sieve_validator *valdtr)
51 {
52 /* Register copy tag with redirect and fileinto commands and we don't
53 care whether these commands are registered or even whether they will
54 be registered at all. The validator handles either situation
55 gracefully.
56 */
57 sieve_validator_register_external_tag(valdtr, "redirect", ext,
58 ©_tag, SIEVE_OPT_SIDE_EFFECT);
59 sieve_validator_register_external_tag(valdtr, "fileinto", ext,
60 ©_tag, SIEVE_OPT_SIDE_EFFECT);
61 return TRUE;
62 }
63
64 /*
65 * Side effect
66 */
67
68 static void
69 seff_copy_print(const struct sieve_side_effect *seffect,
70 const struct sieve_action *action,
71 const struct sieve_result_print_env *rpenv, bool *keep);
72 static int
73 seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED,
74 const struct sieve_action_exec_env *aenv ATTR_UNUSED,
75 void *tr_context ATTR_UNUSED,
76 void *se_tr_context ATTR_UNUSED, bool *keep);
77
78 const struct sieve_side_effect_def copy_side_effect = {
79 SIEVE_OBJECT("copy", ©_side_effect_operand, 0),
80 .to_action = &act_store,
81 .print = seff_copy_print,
82 .post_execute = seff_copy_post_execute,
83 };
84
85 /*
86 * Tagged argument
87 */
88
89 static bool
90 tag_copy_validate(struct sieve_validator *valdtr,
91 struct sieve_ast_argument **arg, struct sieve_command *cmd);
92 static bool
93 tag_copy_generate(const struct sieve_codegen_env *cgenv,
94 struct sieve_ast_argument *arg, struct sieve_command *cmd);
95
96 static const struct sieve_argument_def copy_tag = {
97 .identifier = "copy",
98 .validate = tag_copy_validate,
99 .generate = tag_copy_generate,
100 };
101
102 /*
103 * Operand
104 */
105
106 static const struct sieve_extension_objects ext_side_effects =
107 SIEVE_EXT_DEFINE_SIDE_EFFECT(copy_side_effect);
108
109 static const struct sieve_operand_def copy_side_effect_operand = {
110 .name = "copy operand",
111 .ext_def = ©_extension,
112 .class = &sieve_side_effect_operand_class,
113 .interface = &ext_side_effects,
114 };
115
116 /*
117 * Tag registration
118 */
119
sieve_ext_copy_register_tag(struct sieve_validator * valdtr,const struct sieve_extension * copy_ext,const char * command)120 void sieve_ext_copy_register_tag(struct sieve_validator *valdtr,
121 const struct sieve_extension *copy_ext,
122 const char *command)
123 {
124 if (sieve_validator_extension_loaded(valdtr, copy_ext)) {
125 sieve_validator_register_external_tag(
126 valdtr, command, copy_ext, ©_tag,
127 SIEVE_OPT_SIDE_EFFECT);
128 }
129 }
130
131 /*
132 * Tag validation
133 */
134
135 static bool
tag_copy_validate(struct sieve_validator * valdtr ATTR_UNUSED,struct sieve_ast_argument ** arg ATTR_UNUSED,struct sieve_command * cmd ATTR_UNUSED)136 tag_copy_validate(struct sieve_validator *valdtr ATTR_UNUSED,
137 struct sieve_ast_argument **arg ATTR_UNUSED,
138 struct sieve_command *cmd ATTR_UNUSED)
139 {
140 *arg = sieve_ast_argument_next(*arg);
141
142 return TRUE;
143 }
144
145 /*
146 * Code generation
147 */
148
149 static bool
tag_copy_generate(const struct sieve_codegen_env * cgenv,struct sieve_ast_argument * arg,struct sieve_command * cmd ATTR_UNUSED)150 tag_copy_generate(const struct sieve_codegen_env *cgenv,
151 struct sieve_ast_argument *arg,
152 struct sieve_command *cmd ATTR_UNUSED)
153 {
154 if (sieve_ast_argument_type(arg) != SAAT_TAG)
155 return FALSE;
156
157 sieve_opr_side_effect_emit(cgenv->sblock, sieve_argument_ext(arg),
158 ©_side_effect);
159 return TRUE;
160 }
161
162 /*
163 * Side effect implementation
164 */
165
166 static void
seff_copy_print(const struct sieve_side_effect * seffect ATTR_UNUSED,const struct sieve_action * action ATTR_UNUSED,const struct sieve_result_print_env * rpenv,bool * keep)167 seff_copy_print(const struct sieve_side_effect *seffect ATTR_UNUSED,
168 const struct sieve_action *action ATTR_UNUSED,
169 const struct sieve_result_print_env *rpenv, bool *keep)
170 {
171 sieve_result_seffect_printf(rpenv, "preserve implicit keep");
172 *keep = TRUE;
173 }
174
175 static int
seff_copy_post_execute(const struct sieve_side_effect * seffect ATTR_UNUSED,const struct sieve_action_exec_env * aenv ATTR_UNUSED,void * tr_context ATTR_UNUSED,void * se_tr_context ATTR_UNUSED,bool * keep)176 seff_copy_post_execute(const struct sieve_side_effect *seffect ATTR_UNUSED,
177 const struct sieve_action_exec_env *aenv ATTR_UNUSED,
178 void *tr_context ATTR_UNUSED,
179 void *se_tr_context ATTR_UNUSED, bool *keep)
180 {
181 *keep = TRUE;
182 return SIEVE_EXEC_OK;
183 }
184