static bool cmd_putscript_continue_script(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_putscript_context *ctx = cmd->context; size_t size; int ret; if (ctx->save_ctx != NULL) { while (ctx->script_size == 0 || ctx->input->v_offset != ctx->script_size) { if ( ctx->max_script_size > 0 && ctx->input->v_offset > ctx->max_script_size ) { (void)managesieve_quota_check_validsize(client, ctx->input->v_offset); cmd_putscript_finish(ctx); return TRUE; } ret = i_stream_read(ctx->input); if ((ret != -1 || ctx->input->stream_errno != EINVAL || client->input->eof) && sieve_storage_save_continue(ctx->save_ctx) < 0) { /* we still have to finish reading the script from client */ sieve_storage_save_cancel(&ctx->save_ctx); break; } if (ret == -1 || ret == 0) break; } } if (ctx->save_ctx == NULL) { (void)i_stream_read(ctx->input); (void)i_stream_get_data(ctx->input, &size); i_stream_skip(ctx->input, size); } if (ctx->input->eof || client->input->closed) { bool failed = FALSE; bool all_written = FALSE; if ( ctx->script_size == 0 ) { if ( !client->input->eof && ctx->input->stream_errno == EINVAL ) { client_send_command_error(cmd, t_strdup_printf( "Invalid input: %s", i_stream_get_error(ctx->input))); client->input_skip_line = TRUE; failed = TRUE; } all_written = ( ctx->input->eof && ctx->input->stream_errno == 0 ); } else { all_written = ( ctx->input->v_offset == ctx->script_size ); } /* finished */ ctx->input = NULL; if ( !failed ) { if (ctx->save_ctx == NULL) { /* failed above */ client_send_storage_error(client, ctx->storage); failed = TRUE; } else if (!all_written) { /* client disconnected before it finished sending the whole script. */ failed = TRUE; sieve_storage_save_cancel(&ctx->save_ctx); client_disconnect (client, "EOF while appending in PUTSCRIPT/CHECKSCRIPT"); } else if (sieve_storage_save_finish(ctx->save_ctx) < 0) { failed = TRUE; client_send_storage_error(client, ctx->storage); } else { failed = client->input->closed; } } if (failed) { cmd_putscript_finish(ctx); return TRUE; } /* finish */ client->command_pending = FALSE; managesieve_parser_reset(ctx->save_parser); cmd->func = cmd_putscript_finish_parsing; return cmd_putscript_finish_parsing(cmd); } return FALSE; }
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; }