static bool cmd_putscript_finish_parsing(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_putscript_context *ctx = cmd->context; const struct managesieve_arg *args; int ret; /* if error occurs, the CRLF is already read. */ client->input_skip_line = FALSE; /* <script literal> */ ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args); if (ret == -1 || client->output->closed) { if (ctx->storage != NULL) client_send_command_error(cmd, NULL); cmd_putscript_finish(ctx); return TRUE; } if (ret < 0) { /* need more data */ return FALSE; } if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) { struct sieve_script *script; bool success = TRUE; /* Eat away the trailing CRLF */ client->input_skip_line = TRUE; /* Obtain script object for uploaded script */ script = sieve_storage_save_get_tempscript(ctx->save_ctx); /* Check result */ if ( script == NULL ) { client_send_storage_error(client, ctx->storage); cmd_putscript_finish(ctx); return TRUE; } /* If quoted string, the size was not known until now */ if ( ctx->script_size == 0 ) { if (sieve_script_get_size(script, &ctx->script_size) < 0) { client_send_storage_error(client, ctx->storage); cmd_putscript_finish(ctx); return TRUE; } /* Check quota; max size is already checked */ if ( ctx->scriptname != NULL && !managesieve_quota_check_all (client, ctx->scriptname, ctx->script_size) ) { cmd_putscript_finish(ctx); return TRUE; } } /* Try to compile script */ T_BEGIN { struct sieve_error_handler *ehandler; enum sieve_compile_flags cpflags = SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED; struct sieve_binary *sbin; enum sieve_error error; string_t *errors; /* Mark this as an activation when we are replacing the active script */ if ( sieve_storage_save_will_activate(ctx->save_ctx) ) { cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED; } /* Prepare error handler */ errors = str_new(default_pool, 1024); ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE, client->set->managesieve_max_compile_errors); /* Compile */ if ( (sbin=sieve_compile_script (script, ehandler, cpflags, &error)) == NULL ) { if ( error != SIEVE_ERROR_NOT_VALID ) { const char *errormsg = sieve_script_get_last_error(script, &error); if ( error != SIEVE_ERROR_NONE ) client_send_no(client, errormsg); else client_send_no(client, str_c(errors)); } else { client_send_no(client, str_c(errors)); } success = FALSE; } else { sieve_close(&sbin); /* Commit to save only when this is a putscript command */ if ( ctx->scriptname != NULL ) { ret = sieve_storage_save_commit(&ctx->save_ctx); /* Check commit */ if (ret < 0) { client_send_storage_error(client, ctx->storage); success = FALSE; } } } /* Finish up */ cmd_putscript_finish(ctx); /* Report result to user */ if ( success ) { if ( ctx->scriptname != NULL ) { client->put_count++; client->put_bytes += ctx->script_size; } else { client->check_count++; client->check_bytes += ctx->script_size; } if ( sieve_get_warnings(ehandler) > 0 ) client_send_okresp(client, "WARNINGS", str_c(errors)); else { if ( ctx->scriptname != NULL ) client_send_ok(client, "PUTSCRIPT completed."); else client_send_ok(client, "Script checked successfully."); } } sieve_error_handler_unref(&ehandler); str_free(&errors); } T_END; return TRUE; } client_send_command_error(cmd, "Too many command arguments."); cmd_putscript_finish(ctx); return TRUE; }
static int sieve_attribute_set_sieve(struct mail_storage *storage, const char *key, const struct mail_attribute_value *value) { struct sieve_storage *svstorage; struct sieve_storage_save_context *save_ctx; struct istream *input; const char *scriptname; int ret; if ((ret = mail_sieve_user_init(storage->user, &svstorage)) <= 0) { if (ret == 0) { mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, "Sieve not enabled for user"); } return -1; } if (strcmp(key, MAILBOX_ATTRIBUTE_SIEVE_DEFAULT) == 0) return sieve_attribute_set_default(storage, svstorage, value); if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES)) != 0) { mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, "Nonexistent sieve attribute"); return -1; } scriptname = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES); if (value->value != NULL) { input = i_stream_create_from_data(value->value, strlen(value->value)); save_ctx = sieve_storage_save_init(svstorage, scriptname, input); i_stream_unref(&input); } else if (value->value_stream != NULL) { input = value->value_stream; save_ctx = sieve_storage_save_init(svstorage, scriptname, input); } else { return sieve_attribute_unset_script(storage, svstorage, scriptname); } if (save_ctx == NULL) { /* save initialization failed */ mail_storage_set_critical(storage, "Failed to save sieve script '%s': %s", scriptname, sieve_storage_get_last_error(svstorage, NULL)); return -1; } sieve_storage_save_set_mtime(save_ctx, value->last_change); ret = 0; while (i_stream_read(input) > 0) { if (sieve_storage_save_continue(save_ctx) < 0) { mail_storage_set_critical(storage, "Failed to save sieve script '%s': %s", scriptname, sieve_storage_get_last_error(svstorage, NULL)); ret = -1; break; } } i_assert(input->eof || ret < 0); if (input->stream_errno != 0) { errno = input->stream_errno; mail_storage_set_critical(storage, "Saving sieve script: read(%s) failed: %m", i_stream_get_name(input)); ret = -1; } if (ret == 0 && sieve_storage_save_finish(save_ctx) < 0) { mail_storage_set_critical(storage, "Failed to save sieve script '%s': %s", scriptname, sieve_storage_get_last_error(svstorage, NULL)); ret = -1; } if (ret < 0) sieve_storage_save_cancel(&save_ctx); else if (sieve_storage_save_commit(&save_ctx) < 0) { mail_storage_set_critical(storage, "Failed to save sieve script '%s': %s", scriptname, sieve_storage_get_last_error(svstorage, NULL)); ret = -1; } return ret; }