cmd-store.c revision 45312f52ff3a3d4c137447be4c7556500c2f8bf2
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "seq-range-array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "commands.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "imap-search.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct imap_store_context {
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen struct client_command_context *cmd;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen uint64_t max_modseq;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen enum mail_flags flags;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct mail_keywords *keywords;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen enum modify_type modify_type;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen bool silent;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen};
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic bool
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenget_modify_type(struct imap_store_context *ctx, const char *type)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (*type == '+') {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ctx->modify_type = MODIFY_ADD;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen type++;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else if (*type == '-') {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen ctx->modify_type = MODIFY_REMOVE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen type++;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen } else {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen ctx->modify_type = MODIFY_REPLACE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (strncasecmp(type, "FLAGS", 5) != 0)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return FALSE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen ctx->silent = strcasecmp(type+5, ".SILENT") == 0;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (!ctx->silent && type[5] != '\0')
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return FALSE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return TRUE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainenstatic bool
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstore_parse_modifiers(struct imap_store_context *ctx,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const struct imap_arg *args)
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen{
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen const char *name;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen for (; args->type != IMAP_ARG_EOL; args++) {
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen if (args->type != IMAP_ARG_ATOM ||
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen args[1].type != IMAP_ARG_ATOM) {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen client_send_command_error(ctx->cmd,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen "STORE modifiers contain non-atoms.");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen name = IMAP_ARG_STR(args);
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen if (strcasecmp(name, "UNCHANGEDSINCE") == 0) {
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen args++;
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen ctx->max_modseq =
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen strtoull(imap_arg_string(args), NULL, 10);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen client_enable(ctx->cmd->client,
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen MAILBOX_FEATURE_CONDSTORE);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen client_send_command_error(ctx->cmd,
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen "Unknown STORE modifier");
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen return FALSE;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen }
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen}
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenstatic bool
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstore_parse_args(struct imap_store_context *ctx, const struct imap_arg *args)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct client_command_context *cmd = ctx->cmd;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen const char *type;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *const *keywords_list = NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ctx->max_modseq = (uint64_t)-1;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (args->type == IMAP_ARG_LIST) {
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (!store_parse_modifiers(ctx, IMAP_ARG_LIST_ARGS(args)))
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen return FALSE;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen args++;
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen }
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen type = imap_arg_string(args++);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (type == NULL || !get_modify_type(ctx, type)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen if (args->type == IMAP_ARG_LIST) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!client_parse_mail_flags(cmd, IMAP_ARG_LIST_ARGS(args),
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen &ctx->flags, &keywords_list))
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return FALSE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen } else {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (!client_parse_mail_flags(cmd, args,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen &ctx->flags, &keywords_list))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (keywords_list != NULL || ctx->modify_type == MODIFY_REPLACE) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (mailbox_keywords_create(cmd->client->mailbox, keywords_list,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen &ctx->keywords) < 0) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* invalid keywords */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen client_send_storage_error(cmd,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen mailbox_get_storage(cmd->client->mailbox));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return TRUE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenbool cmd_store(struct client_command_context *cmd)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct client *client = cmd->client;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const struct imap_arg *args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_args *search_args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_context *search_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_transaction_context *t;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail *mail;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct imap_store_context ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) modified_set, uids;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen enum mailbox_transaction_flags flags = 0;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen enum imap_sync_flags imap_sync_flags = 0;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *reply, *tagged_reply;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen string_t *str;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen int ret;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (!client_read_args(cmd, 0, 0, &args))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return FALSE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (!client_verify_open_mailbox(cmd))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return TRUE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (args->type != IMAP_ARG_ATOM) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = imap_search_get_seqset(cmd, IMAP_ARG_STR_NONULL(args),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd->uid, &search_args);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (ret <= 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return ret < 0;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen memset(&ctx, 0, sizeof(ctx));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ctx.cmd = cmd;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (!store_parse_args(&ctx, ++args))
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return TRUE;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (client->mailbox_examined) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (ctx.max_modseq < (uint64_t)-1)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen reply = "NO CONDSTORE failed: Mailbox is read-only.";
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen else
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen reply = "OK Store ignored with read-only mailbox.";
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return cmd_sync(cmd, MAILBOX_SYNC_FLAG_FAST |
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen (cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen 0, reply);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (ctx.silent)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen flags |= MAILBOX_TRANSACTION_FLAG_HIDE;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (ctx.max_modseq < (uint64_t)-1) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* update modseqs so we can check them early */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen flags |= MAILBOX_TRANSACTION_FLAG_REFRESH;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t = mailbox_transaction_begin(client->mailbox, flags);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen search_ctx = mailbox_search_init(t, search_args, NULL);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_search_args_unref(&search_args);
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen i_array_init(&modified_set, 64);
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen if (ctx.max_modseq < (uint32_t)-1) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* STORE UNCHANGEDSINCE is being used */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mailbox_transaction_set_max_modseq(t, ctx.max_modseq,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen &modified_set);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail = mail_alloc(t, MAIL_FETCH_FLAGS, NULL);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen while (mailbox_search_next(search_ctx, mail) > 0) {
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (ctx.max_modseq < (uint64_t)-1) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* check early so there's less work for transaction
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen commit if something has to be cancelled */
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (mail_get_modseq(mail) > ctx.max_modseq) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq_range_array_add(&modified_set, 0,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail->seq);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen continue;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (ctx.modify_type == MODIFY_REPLACE || ctx.flags != 0)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen mail_update_flags(mail, ctx.modify_type, ctx.flags);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (ctx.modify_type == MODIFY_REPLACE || ctx.keywords != NULL) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen mail_update_keywords(mail, ctx.modify_type,
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen ctx.keywords);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_free(&mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx.keywords != NULL)
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen mailbox_keywords_free(client->mailbox, &ctx.keywords);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret = mailbox_search_deinit(&search_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mailbox_transaction_rollback(&t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen ret = mailbox_transaction_commit(&t);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (ret < 0) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen array_free(&modified_set);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen client_send_storage_error(cmd,
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody mailbox_get_storage(client->mailbox));
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return TRUE;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen }
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (array_count(&modified_set) == 0)
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen tagged_reply = "OK Store completed.";
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen else {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (cmd->uid) {
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen i_array_init(&uids, array_count(&modified_set)*2);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mailbox_get_uid_range(client->mailbox, &modified_set,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen &uids);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen array_free(&modified_set);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody modified_set = uids;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody }
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str = str_new(cmd->pool, 256);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str_append(str, "OK [MODIFIED ");
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody imap_write_seq_range(str, &modified_set);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str_append(str, "] Conditional store failed.");
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody tagged_reply = str_c(str);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody }
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody array_free(&modified_set);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody /* With UID STORE we have to return UID for the flags as well.
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody Unfortunately we don't have the ability to separate those
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody flag changes that were caused by UID STORE and those that
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody came externally, so we'll just send the UID for all flag
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody changes that we see. */
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen if (cmd->uid && (!ctx.silent || (client->enabled_features &
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen MAILBOX_FEATURE_CONDSTORE) != 0))
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen imap_sync_flags |= IMAP_SYNC_FLAG_SEND_UID;
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen return cmd_sync(cmd, (cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen imap_sync_flags, tagged_reply);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody}
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen