132
static bool cmd_putscript_cancel(struct cmd_putscript_context *ctx, bool nonsync)
130
static bool cmd_putscript_cancel(struct cmd_putscript_context *ctx, bool skip)
134
132
ctx->client->input_skip_line = TRUE;
136
if (!nonsync) { /* Rediculous for managesieve */
137
135
cmd_putscript_finish(ctx);
141
139
/* we have to read the nonsynced literal so we don't treat the uploaded script
143
ctx->input = i_stream_create_limit(ctx->client->input, ctx->script_size);
145
141
ctx->client->command_pending = TRUE;
146
142
ctx->cmd->func = cmd_putscript_continue_cancel;
147
143
ctx->cmd->context = ctx;
153
149
struct client *client = cmd->client;
154
150
struct cmd_putscript_context *ctx = cmd->context;
155
struct managesieve_arg *args;
151
const struct managesieve_arg *args;
158
154
/* if error occurs, the CRLF is already read. */
159
155
client->input_skip_line = FALSE;
161
157
/* <script literal> */
162
ret = managesieve_parser_read_args(ctx->save_parser, 0,
163
MANAGESIEVE_PARSE_FLAG_LITERAL_SIZE, &args);
158
ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args);
164
159
if (ret == -1 || client->output->closed) {
165
160
if (ctx->storage != NULL)
166
161
client_send_command_error(cmd, NULL);
187
/* If quoted string, the size was not known until now */
188
if ( ctx->script_size == 0 ) {
189
/* Check quota; max size is already checked */
190
if ( ctx->scriptname != NULL && !managesieve_quota_check_all
191
(client, ctx->scriptname, ctx->script_size) ) {
192
cmd_putscript_finish(ctx);
194
197
/* Try to compile script */
196
199
struct sieve_error_handler *ehandler;
200
enum sieve_compile_flags cpflags =
201
SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED;
197
202
struct sieve_binary *sbin;
198
203
string_t *errors;
205
/* Mark this as an activation when we are replacing the active script */
206
if ( sieve_storage_save_will_activate(ctx->save_ctx) ) {
207
cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED;
200
210
/* Prepare error handler */
201
211
errors = str_new(default_pool, 1024);
202
212
ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE,
203
213
client->set->managesieve_max_compile_errors);
206
if ( (sbin=sieve_compile_script(script, ehandler, NULL)) == NULL ) {
216
if ( (sbin=sieve_compile_script
217
(script, ehandler, cpflags, NULL)) == NULL ) {
207
218
client_send_no(client, str_c(errors));
276
if (args->type != MANAGESIEVE_ARG_STRING) {
277
/* Validate the script argument */
278
if (args->type != MANAGESIEVE_ARG_LITERAL_SIZE ) {
279
client_send_command_error(cmd, "Invalid arguments.");
280
return cmd_putscript_cancel(ctx, FALSE);
286
/* Validate the script argument */
287
if ( !managesieve_arg_get_string_stream(args,&ctx->input) ) {
288
client_send_command_error(cmd, "Invalid arguments.");
289
return cmd_putscript_cancel(ctx, FALSE);
292
if ( i_stream_get_size(ctx->input, FALSE, &ctx->script_size) > 0 ) {
293
if ( ctx->script_size == 0 ) {
294
/* no script content, abort */
295
if ( ctx->scriptname != NULL )
296
client_send_no(client, "PUTSCRIPT aborted (empty script).");
298
client_send_no(client, "CHECKSCRIPT aborted (empty script).");
300
cmd_putscript_finish(ctx);
304
} else if ( ctx->scriptname == NULL ) {
305
if ( !managesieve_quota_check_validsize(client, ctx->script_size) )
306
return cmd_putscript_cancel(ctx, TRUE);
308
if ( !managesieve_quota_check_all
309
(client, ctx->scriptname, ctx->script_size) )
310
return cmd_putscript_cancel(ctx, TRUE);
283
ctx->script_size = MANAGESIEVE_ARG_LITERAL_SIZE(args);
286
/* FIXME: allow quoted strings */
287
client_send_no(client,
288
"This MANAGESIEVE implementation currently does not allow "
289
"quoted strings to be used for script contents.");
290
return cmd_putscript_cancel(ctx, FALSE);
293
if ( ctx->script_size == 0 ) {
294
/* no script content, abort */
295
if ( ctx->scriptname != NULL )
296
client_send_no(client, "PUTSCRIPT aborted (empty script).");
298
client_send_no(client, "CHECKSCRIPT aborted (empty script).");
300
cmd_putscript_finish(ctx);
314
ctx->max_script_size = managesieve_quota_max_script_size(client);
304
317
/* save the script */
305
ctx->input = i_stream_create_limit(client->input, ctx->script_size);
306
318
ctx->save_ctx = sieve_storage_save_init
307
319
(ctx->storage, ctx->scriptname, ctx->input);
309
321
if ( ctx->save_ctx == NULL ) {
310
322
/* save initialization failed */
311
323
client_send_storage_error(client, ctx->storage);
312
return cmd_putscript_cancel(ctx, nonsync);
316
if ( ctx->scriptname == NULL ) {
317
if ( !managesieve_quota_check_validsize(client, ctx->script_size) )
318
return cmd_putscript_cancel(ctx, nonsync);
320
if ( !managesieve_quota_check_all
321
(client, ctx->scriptname, ctx->script_size) )
322
return cmd_putscript_cancel(ctx, nonsync);
324
return cmd_putscript_cancel(ctx, TRUE);
325
327
/* after literal comes CRLF, if we fail make sure we eat it away */
335
337
struct client *client = cmd->client;
336
338
struct cmd_putscript_context *ctx = cmd->context;
341
342
if (ctx->save_ctx != NULL) {
342
while (ctx->input->v_offset != ctx->script_size) {
343
ret = i_stream_read(ctx->input);
343
while (ctx->script_size == 0 || ctx->input->v_offset != ctx->script_size) {
344
if ( ctx->max_script_size > 0 &&
345
ctx->input->v_offset > ctx->max_script_size ) {
346
(void)managesieve_quota_check_validsize(client, ctx->input->v_offset);
347
cmd_putscript_finish(ctx);
351
ret = i_stream_read(ctx->input);
344
352
if (sieve_storage_save_continue(ctx->save_ctx) < 0) {
345
353
/* we still have to finish reading the script
361
369
if (ctx->input->eof || client->input->closed) {
362
bool all_written = ctx->input->v_offset == ctx->script_size;
371
bool all_written = FALSE;
373
if ( ctx->script_size == 0 ) {
374
if ( ctx->input->stream_errno == EPROTO ) {
376
const char *parse_error;
378
parse_error = managesieve_parser_get_error(ctx->save_parser, &fatal);
379
if ( parse_error != NULL) {
380
client_send_command_error(cmd, parse_error);
381
client->input_skip_line = TRUE;
385
all_written = ( ctx->input->eof && ctx->input->stream_errno == 0 );
388
all_written = ( ctx->input->v_offset == ctx->script_size );
365
i_stream_unref(&ctx->input);
366
392
ctx->input = NULL;
368
if (ctx->save_ctx == NULL) {
370
client_send_storage_error(client, ctx->storage);
372
} else if (!all_written) {
373
/* client disconnected before it finished sending the
376
sieve_storage_save_cancel(&ctx->save_ctx);
377
client_disconnect(client, "EOF while appending in PUTSCRIPT/CHECKSCRIPT");
378
} else if (sieve_storage_save_finish(ctx->save_ctx) < 0) {
380
client_send_storage_error(client, ctx->storage);
382
failed = client->input->closed;
395
if (ctx->save_ctx == NULL) {
397
client_send_storage_error(client, ctx->storage);
399
} else if (!all_written) {
400
/* client disconnected before it finished sending the
403
sieve_storage_save_cancel(&ctx->save_ctx);
405
(client, "EOF while appending in PUTSCRIPT/CHECKSCRIPT");
406
} else if (sieve_storage_save_finish(ctx->save_ctx) < 0) {
408
client_send_storage_error(client, ctx->storage);
410
failed = client->input->closed;