1 /* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2 */
3
4 #include "lib.h"
5 #include "str.h"
6
7 #include "sieve.h"
8 #include "sieve-script.h"
9 #include "sieve-storage.h"
10
11 #include "managesieve-common.h"
12 #include "managesieve-commands.h"
13
14 static void
cmd_setactive_activate(struct client_command_context * cmd,const char * scriptname)15 cmd_setactive_activate(struct client_command_context *cmd,
16 const char *scriptname)
17 {
18 struct client *client = cmd->client;
19 struct sieve_storage *storage = client->storage;
20 struct sieve_script *script;
21 string_t *errors = NULL;
22 const char *errormsg = NULL;
23 unsigned int warning_count = 0, error_count = 0;
24 bool success = TRUE;
25 int ret;
26
27 event_add_str(cmd->event, "script_name", scriptname);
28
29 script = sieve_storage_open_script(storage, scriptname, NULL);
30 if (script == NULL) {
31 client_command_storage_error(
32 cmd, "Failed to open script `%s' for activation",
33 scriptname);
34 return;
35 }
36
37 if (sieve_script_is_active(script) <= 0) T_BEGIN {
38 /* Script is first being activated; compile it again without the
39 UPLOAD flag. */
40 struct sieve_error_handler *ehandler;
41 enum sieve_compile_flags cpflags =
42 SIEVE_COMPILE_FLAG_NOGLOBAL |
43 SIEVE_COMPILE_FLAG_ACTIVATED;
44 struct sieve_binary *sbin;
45 enum sieve_error error;
46
47 /* Prepare error handler */
48 errors = str_new(default_pool, 1024);
49 ehandler = sieve_strbuf_ehandler_create(
50 client->svinst, errors, TRUE,
51 client->set->managesieve_max_compile_errors);
52
53 /* Compile */
54 sbin = sieve_compile_script(script, ehandler, cpflags, &error);
55 if (sbin == NULL) {
56 if (error != SIEVE_ERROR_NOT_VALID) {
57 errormsg = sieve_script_get_last_error(
58 script, &error);
59 if (error == SIEVE_ERROR_NONE)
60 errormsg = NULL;
61 }
62 success = FALSE;
63 } else {
64 sieve_close(&sbin);
65 }
66
67 warning_count = sieve_get_warnings(ehandler);
68 error_count = sieve_get_errors(ehandler);
69 sieve_error_handler_unref(&ehandler);
70 } T_END;
71
72 /* Activate only when script is valid (or already active) */
73 if (success) {
74 /* Refresh activation no matter what; this can also
75 resolve some erroneous situations. */
76 ret = sieve_script_activate(script, (time_t)-1);
77 if (ret < 0) {
78 client_command_storage_error(
79 cmd, "Failed to activate script `%s'",
80 scriptname);
81 } else {
82 struct event_passthrough *e =
83 client_command_create_finish_event(cmd)->
84 add_int("compile_warnings", warning_count);
85 e_debug(e->event(), "Activated script `%s' "
86 " (%u warnings%s)",
87 scriptname, warning_count,
88 (ret == 0 ? ", redundant" : ""));
89
90 if (warning_count > 0) {
91 client_send_okresp(
92 client, "WARNINGS",
93 str_c(errors));
94 } else {
95 client_send_ok(client,
96 (ret > 0 ?
97 "Setactive completed." :
98 "Script is already active."));
99 }
100 }
101 } else if (errormsg == NULL) {
102 struct event_passthrough *e =
103 client_command_create_finish_event(cmd)->
104 add_str("error", "Compilation failed")->
105 add_int("compile_errors", error_count)->
106 add_int("compile_warnings", warning_count);
107 e_debug(e->event(), "Failed to activate script `%s': "
108 "Compilation failed (%u errors, %u warnings)",
109 scriptname, error_count, warning_count);
110
111 client_send_no(client, str_c(errors));
112 } else {
113 struct event_passthrough *e =
114 client_command_create_finish_event(cmd)->
115 add_str("error", errormsg);
116 e_debug(e->event(), "Failed to activate script `%s': %s",
117 scriptname, errormsg);
118
119 client_send_no(client, errormsg);
120 }
121
122 if (errors != NULL)
123 str_free(&errors);
124 sieve_script_unref(&script);
125 }
126
127 static void
cmd_setactive_deactivate(struct client_command_context * cmd)128 cmd_setactive_deactivate(struct client_command_context *cmd)
129 {
130 struct client *client = cmd->client;
131 struct sieve_storage *storage = client->storage;
132 int ret;
133
134 ret = sieve_storage_deactivate(storage, (time_t)-1);
135 if (ret < 0) {
136 client_command_storage_error(
137 cmd, "Failed to deactivate script");
138 return;
139 }
140
141 struct event_passthrough *e =
142 client_command_create_finish_event(cmd);
143 e_debug(e->event(), "Deactivated script");
144
145 client_send_ok(client, (ret > 0 ?
146 "Active script is now deactivated." :
147 "No scripts currently active."));
148 }
149
cmd_setactive(struct client_command_context * cmd)150 bool cmd_setactive(struct client_command_context *cmd)
151 {
152 const char *scriptname;
153
154 /* <scriptname> */
155 if (!client_read_string_args(cmd, TRUE, 1, &scriptname))
156 return FALSE;
157
158 /* Activate, or deactivate */
159 if (*scriptname != '\0')
160 cmd_setactive_activate(cmd, scriptname);
161 else
162 cmd_setactive_deactivate(cmd);
163
164 return TRUE;
165 }
166