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