1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2 */
3
4 #include "lib.h"
5
6 #include "sieve-execute.h"
7
8 struct sieve_execute_state {
9 void *dup_trans;
10 };
11
12 struct event_category event_category_sieve_execute = {
13 .parent = &event_category_sieve,
14 .name = "sieve-execute",
15 };
16
17 static struct sieve_execute_state *
sieve_execute_state_create(struct sieve_execute_env * eenv)18 sieve_execute_state_create(struct sieve_execute_env *eenv)
19 {
20 return p_new(eenv->pool, struct sieve_execute_state, 1);
21 }
22
23 static void
sieve_execute_state_free(struct sieve_execute_state ** _estate,struct sieve_execute_env * eenv)24 sieve_execute_state_free(struct sieve_execute_state **_estate,
25 struct sieve_execute_env *eenv)
26 {
27 struct sieve_execute_state *estate = *_estate;
28 const struct sieve_script_env *senv = eenv->scriptenv;
29
30 *_estate = NULL;
31
32 if (senv->duplicate_transaction_rollback != NULL)
33 senv->duplicate_transaction_rollback(&estate->dup_trans);
34 }
35
sieve_execute_init(struct sieve_execute_env * eenv,struct sieve_instance * svinst,pool_t pool,const struct sieve_message_data * msgdata,const struct sieve_script_env * senv,enum sieve_execute_flags flags)36 void sieve_execute_init(struct sieve_execute_env *eenv,
37 struct sieve_instance *svinst, pool_t pool,
38 const struct sieve_message_data *msgdata,
39 const struct sieve_script_env *senv,
40 enum sieve_execute_flags flags)
41 {
42 i_zero(eenv);
43 eenv->svinst = svinst;
44 eenv->pool = pool;
45 eenv->flags = flags;
46 eenv->msgdata = msgdata;
47 eenv->scriptenv = senv;
48
49 pool_ref(pool);
50 eenv->event = event_create(svinst->event);
51 event_add_category(eenv->event, &event_category_sieve_execute);
52 event_add_str(eenv->event, "message_id", msgdata->id);
53 if ((flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0) {
54 /* Make sure important envelope fields are available */
55 event_add_str(eenv->event, "mail_from",
56 smtp_address_encode(msgdata->envelope.mail_from));
57 event_add_str(eenv->event, "rcpt_to",
58 smtp_address_encode(msgdata->envelope.rcpt_to));
59 }
60
61 eenv->state = sieve_execute_state_create(eenv);
62
63 eenv->exec_status = senv->exec_status;
64 if (eenv->exec_status == NULL)
65 eenv->exec_status = p_new(pool, struct sieve_exec_status, 1);
66 else
67 i_zero(eenv->exec_status);
68 }
69
sieve_execute_finish(struct sieve_execute_env * eenv,int status)70 void sieve_execute_finish(struct sieve_execute_env *eenv, int status)
71 {
72 const struct sieve_script_env *senv = eenv->scriptenv;
73
74 if (status == SIEVE_EXEC_OK) {
75 if (senv->duplicate_transaction_commit != NULL) {
76 senv->duplicate_transaction_commit(
77 &eenv->state->dup_trans);
78 }
79 } else {
80 if (senv->duplicate_transaction_rollback != NULL) {
81 senv->duplicate_transaction_rollback(
82 &eenv->state->dup_trans);
83 }
84 }
85 }
86
sieve_execute_deinit(struct sieve_execute_env * eenv)87 void sieve_execute_deinit(struct sieve_execute_env *eenv)
88 {
89 sieve_execute_state_free(&eenv->state, eenv);
90 event_unref(&eenv->event);
91 pool_unref(&eenv->pool);
92 }
93
94 /*
95 * Checking for duplicates
96 */
97
98 static void *
sieve_execute_get_dup_transaction(const struct sieve_execute_env * eenv)99 sieve_execute_get_dup_transaction(const struct sieve_execute_env *eenv)
100 {
101 const struct sieve_script_env *senv = eenv->scriptenv;
102
103 if (senv->duplicate_transaction_begin == NULL)
104 return NULL;
105 if (eenv->state->dup_trans == NULL) {
106 eenv->state->dup_trans =
107 senv->duplicate_transaction_begin(senv);
108 }
109 return eenv->state->dup_trans;
110 }
111
sieve_execute_duplicate_check_available(const struct sieve_execute_env * eenv)112 bool sieve_execute_duplicate_check_available(
113 const struct sieve_execute_env *eenv)
114 {
115 const struct sieve_script_env *senv = eenv->scriptenv;
116
117 return (senv->duplicate_transaction_begin != NULL);
118 }
119
sieve_execute_duplicate_check(const struct sieve_execute_env * eenv,const void * id,size_t id_size,bool * duplicate_r)120 int sieve_execute_duplicate_check(const struct sieve_execute_env *eenv,
121 const void *id, size_t id_size,
122 bool *duplicate_r)
123 {
124 const struct sieve_script_env *senv = eenv->scriptenv;
125 void *dup_trans = sieve_execute_get_dup_transaction(eenv);
126 int ret;
127
128 *duplicate_r = FALSE;
129
130 if (senv->duplicate_check == NULL)
131 return SIEVE_EXEC_OK;
132
133 e_debug(eenv->svinst->event, "Check duplicate ID");
134
135 ret = senv->duplicate_check(dup_trans, senv, id, id_size);
136 switch (ret) {
137 case SIEVE_DUPLICATE_CHECK_RESULT_EXISTS:
138 *duplicate_r = TRUE;
139 break;
140 case SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND:
141 break;
142 case SIEVE_DUPLICATE_CHECK_RESULT_FAILURE:
143 return SIEVE_EXEC_FAILURE;
144 case SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE:
145 return SIEVE_EXEC_TEMP_FAILURE;
146 }
147 return SIEVE_EXEC_OK;
148 }
149
sieve_execute_duplicate_mark(const struct sieve_execute_env * eenv,const void * id,size_t id_size,time_t time)150 void sieve_execute_duplicate_mark(const struct sieve_execute_env *eenv,
151 const void *id, size_t id_size, time_t time)
152 {
153 const struct sieve_script_env *senv = eenv->scriptenv;
154 void *dup_trans = sieve_execute_get_dup_transaction(eenv);
155
156 if (senv->duplicate_mark == NULL)
157 return;
158
159 e_debug(eenv->svinst->event, "Mark ID as duplicate");
160
161 senv->duplicate_mark(dup_trans, senv, id, id_size, time);
162 }
163