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