cmd-setmetadata.c revision 3858a7a5da361c35f1e6e50c8e3214dc0cf379d6
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void cmd_setmetadata_deinit(struct imap_setmetadata_context *ctx)
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen o_stream_set_flush_callback(ctx->cmd->client->output,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_metadata_transaction_rollback(&ctx->trans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (ctx->box != NULL && ctx->box != ctx->cmd->client->mailbox)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainencmd_setmetadata_parse_entryvalue(struct imap_setmetadata_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen const char **entry_r,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* parse the entry name */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* ')' found */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen "Entry name isn't astring");
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen error = imap_parser_get_error(ctx->parser, &fatal);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen client_disconnect_with_error(ctx->cmd->client, error);
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen client_send_command_error(ctx->cmd, "Entry value missing");
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen client_send_command_error(ctx->cmd, "Entry value can't be a list");
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch !imap_metadata_verify_entry_name(name, &error)) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* client won't see "+ OK", so we can abort
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen immediately */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* entry names are case-insensitive. handle this by using only
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen lowercase names. */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainencmd_setmetadata_entry_read_stream(struct imap_setmetadata_context *ctx)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen const unsigned char *data;
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while ((ret = i_stream_read_more(ctx->input, &data, &size)) > 0)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (ctx->input->v_offset == ctx->entry_value_len) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* finished reading the value */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imap_metadata_set(ctx->trans, ctx->entry_name, &value) < 0) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* delay reporting the failure so we'll finish
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen reading the command input */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* client disconnected */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainencmd_setmetadata_entry(struct imap_setmetadata_context *ctx,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* we have the value already */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen value.value = imap_arg_as_nstring(entry_value);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ret = imap_metadata_set(ctx->trans, entry_name, &value);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* delay reporting the failure so we'll finish
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen reading the command input */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* fall through */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->entry_value_len = imap_arg_as_literal_size(entry_value);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen inputs[0] = i_stream_create_limit(ctx->cmd->client->input,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen mail_user_set_get_temp_prefix(path, ctx->cmd->client->user->set);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx->input = i_stream_create_seekable_path(inputs,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_stream_set_name(ctx->input, i_stream_get_name(inputs[0]));
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return cmd_setmetadata_entry_read_stream(ctx);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic bool cmd_setmetadata_continue(struct client_command_context *cmd)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct imap_setmetadata_context *ctx = cmd->context;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if ((ret = cmd_setmetadata_entry_read_stream(ctx)) == 0)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen while ((ret = cmd_setmetadata_parse_entryvalue(ctx, &entry, &value)) > 0 &&
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* already sent the error to client */ ;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch client_disconnect_if_inconsistent(cmd->client);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch error_string = imap_metadata_transaction_get_last_error
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_get_error_string(cmd, error_string, error));
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch } else if (imap_metadata_transaction_commit(&ctx->trans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch client_disconnect_if_inconsistent(cmd->client);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_get_error_string(cmd, error_string, error));
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen client_send_tagline(cmd, "OK Setmetadata completed.");
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschcmd_setmetadata_start(struct imap_setmetadata_context *ctx)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct client_command_context *cmd = ctx->cmd;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* we support large literals, so read the values from client
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch asynchronously the same way as APPEND does. */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->parser = imap_parser_create(client->input, client->output,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch o_stream_unset_flush_callback(client->output);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschcmd_setmetadata_server(struct imap_setmetadata_context *ctx)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->trans = imap_metadata_transaction_begin_server(ctx->cmd->client->user);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschcmd_setmetadata_mailbox(struct imap_setmetadata_context *ctx,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct client_command_context *cmd = ctx->cmd;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (client->mailbox != NULL && !client->mailbox_examined &&
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->box = mailbox_alloc(ns->list, mailbox, 0);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ctx->trans = imap_metadata_transaction_begin(ctx->box);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenbool cmd_setmetadata(struct client_command_context *cmd)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (!imap_arg_get_astring(&args[0], &mailbox) ||
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen client_send_command_error(cmd, "Invalid arguments.");
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen client_send_command_error(cmd, "METADATA disabled.");
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ctx = p_new(cmd->pool, struct imap_setmetadata_context, 1);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* server attribute */