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 					      &copy_tag, SIEVE_OPT_SIDE_EFFECT);
59 	sieve_validator_register_external_tag(valdtr, "fileinto", ext,
60 					      &copy_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", &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 = &copy_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, &copy_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 				   &copy_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