static int cmd_setmetadata_entry(struct imap_setmetadata_context *ctx, const char *entry_name, const struct imap_arg *entry_value) { struct istream *inputs[2]; struct mail_attribute_value value; string_t *path; int ret; switch (entry_value->type) { case IMAP_ARG_NIL: case IMAP_ARG_ATOM: case IMAP_ARG_STRING: /* we have the value already */ if (ctx->failed) return 1; memset(&value, 0, sizeof(value)); value.value = imap_arg_as_nstring(entry_value); ret = imap_metadata_set(ctx->trans, entry_name, &value); if (ret < 0) { /* delay reporting the failure so we'll finish reading the command input */ ctx->storage_failure = TRUE; ctx->failed = TRUE; } return 1; case IMAP_ARG_LITERAL_SIZE: o_stream_nsend(ctx->cmd->client->output, "+ OK\r\n", 6); o_stream_nflush(ctx->cmd->client->output); o_stream_uncork(ctx->cmd->client->output); o_stream_cork(ctx->cmd->client->output); /* fall through */ case IMAP_ARG_LITERAL_SIZE_NONSYNC: i_free(ctx->entry_name); ctx->entry_name = i_strdup(entry_name); ctx->entry_value_len = imap_arg_as_literal_size(entry_value); inputs[0] = i_stream_create_limit(ctx->cmd->client->input, ctx->entry_value_len); inputs[1] = NULL; path = t_str_new(128); mail_user_set_get_temp_prefix(path, ctx->cmd->client->user->set); ctx->input = i_stream_create_seekable_path(inputs, METADATA_MAX_INMEM_SIZE, str_c(path)); i_stream_set_name(ctx->input, i_stream_get_name(inputs[0])); i_stream_unref(&inputs[0]); return cmd_setmetadata_entry_read_stream(ctx); case IMAP_ARG_LITERAL: case IMAP_ARG_LIST: case IMAP_ARG_EOL: break; } i_unreached(); }
static bool cmd_setmetadata_continue(struct client_command_context *cmd) { struct imap_setmetadata_context *ctx = cmd->context; const char *entry, *error_string; enum mail_error error; const struct imap_arg *value; int ret; if (cmd->cancel) { cmd_setmetadata_deinit(ctx); return TRUE; } if (ctx->input != NULL) { if ((ret = cmd_setmetadata_entry_read_stream(ctx)) == 0) return FALSE; if (ret < 0) { cmd_setmetadata_deinit(ctx); return TRUE; } } while ((ret = cmd_setmetadata_parse_entryvalue(ctx, &entry, &value)) > 0 && entry != NULL) { ret = ctx->failed ? 1 : cmd_setmetadata_entry(ctx, entry, value); imap_parser_reset(ctx->parser); if (ret <= 0) break; } if (ret == 0) return 0; if (ret < 0 || ctx->cmd_error_sent) { /* already sent the error to client */ ; } else if (ctx->storage_failure) { if (ctx->box == NULL) client_disconnect_if_inconsistent(cmd->client); error_string = imap_metadata_transaction_get_last_error (ctx->trans, &error); client_send_tagline(cmd, imap_get_error_string(cmd, error_string, error)); } else if (imap_metadata_transaction_commit(&ctx->trans, &error, &error_string) < 0) { if (ctx->box == NULL) client_disconnect_if_inconsistent(cmd->client); client_send_tagline(cmd, imap_get_error_string(cmd, error_string, error)); } else { client_send_tagline(cmd, "OK Setmetadata completed."); } cmd_setmetadata_deinit(ctx); return TRUE; }
static bool cmd_setmetadata_continue(struct client_command_context *cmd) { struct imap_setmetadata_context *ctx = cmd->context; const char *entry; const struct imap_arg *value; int ret; if (cmd->cancel) { cmd_setmetadata_deinit(ctx); return TRUE; } if (ctx->input != NULL) { if ((ret = cmd_setmetadata_entry_read_stream(ctx)) == 0) return FALSE; if (ret < 0) { cmd_setmetadata_deinit(ctx); return TRUE; } } while ((ret = cmd_setmetadata_parse_entryvalue(ctx, &entry, &value)) > 0 && entry != NULL) { ret = ctx->failed ? 1 : cmd_setmetadata_entry(ctx, entry, value); imap_parser_reset(ctx->parser); if (ret <= 0) break; } if (ret == 0) return 0; if (ret < 0 || ctx->cmd_error_sent) /* already sent the error to client */ ; else if (ctx->storage_failure) client_send_box_error(cmd, ctx->box); else if (mailbox_transaction_commit(&ctx->trans) < 0) client_send_box_error(cmd, ctx->box); else client_send_tagline(cmd, "OK Setmetadata completed."); cmd_setmetadata_deinit(ctx); return TRUE; }