cmd-store.c revision fba0d7e7f265f83160229170de69b23d5f181847
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "common.h"
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "commands.h"
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenstatic int get_modify_type(struct client *client, const char *item,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen enum modify_type *modify_type, int *silent)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (*item == '+') {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen *modify_type = MODIFY_ADD;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen item++;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen } else if (*item == '-') {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen *modify_type = MODIFY_REMOVE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen item++;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen *modify_type = MODIFY_REPLACE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (strncasecmp(item, "FLAGS", 5) != 0) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen client_send_tagline(client, t_strconcat(
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen "NO Invalid item ", item, NULL));
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return FALSE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen *silent = strcasecmp(item+5, ".SILENT") == 0;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (!*silent && item[5] != '\0') {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen client_send_tagline(client, t_strconcat(
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen "NO Invalid item ", item, NULL));
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return FALSE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return TRUE;
a1de279d1c46f168e3fab6ad5b2e0cb4ddc4467cTimo Sirainen}
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenstatic int mail_send_flags(struct client *client, struct mail *mail)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen const struct mail_full_flags *flags;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen const char *str;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen flags = mail->get_flags(mail);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (flags == NULL)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen t_push();
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str = imap_write_flags(flags);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str = t_strdup_printf(client->cmd_uid ?
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen "* %u FETCH (FLAGS (%s) UID %u)" :
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen "* %u FETCH (FLAGS (%s))",
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen mail->seq, str, mail->uid);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen client_send_line(client, str);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen t_pop();
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen}
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainenint cmd_store(struct client *client)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen{
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct imap_arg *args;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen struct mail_full_flags flags;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen enum modify_type modify_type;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mailbox *box;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail_fetch_context *fetch_ctx;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail *mail;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen const char *messageset, *item;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen int silent, all_found, failed;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (!client_read_args(client, 0, 0, &args))
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return FALSE;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (!client_verify_open_mailbox(client))
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* validate arguments */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen messageset = imap_arg_string(&args[0]);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen item = imap_arg_string(&args[1]);
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (messageset == NULL || item == NULL) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen client_send_command_error(client, "Invalid arguments.");
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!get_modify_type(client, item, &modify_type, &silent))
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (args[2].type == IMAP_ARG_LIST) {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!client_parse_mail_flags(client,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen IMAP_ARG_LIST(&args[2])->args,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &client->mailbox_flags, &flags))
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!client_parse_mail_flags(client, args+2,
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen &client->mailbox_flags, &flags))
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return TRUE;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen /* and update the flags */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen box = client->mailbox;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen if (box->is_readonly(box)) {
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen /* read-only, don't every try to get write locking */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen failed = FALSE;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen } else {
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen failed = !box->lock(box, MAILBOX_LOCK_FLAGS |
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen MAILBOX_LOCK_READ);
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen fetch_ctx = failed ? NULL :
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen box->fetch_init(box, MAIL_FETCH_FLAGS, NULL,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen messageset, client->cmd_uid);
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (fetch_ctx == NULL)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen failed = TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen else {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen failed = FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen while ((mail = box->fetch_next(fetch_ctx)) != NULL) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!mail->update_flags(mail, &flags, modify_type)) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen failed = TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!silent) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!mail_send_flags(client, mail)) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen failed = TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen break;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!box->fetch_deinit(fetch_ctx, &all_found))
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen failed = TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen (void)box->lock(box, MAILBOX_LOCK_UNLOCK);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (!failed) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (client->cmd_uid)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen client_sync_full_fast(client);
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen else
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen client_sync_without_expunges(client);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen client_send_tagline(client, all_found ? "OK Store completed." :
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen "NO Some of the messages no longer exist.");
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen client_send_storage_error(client, client->mailbox->storage);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen