cmd-status.c revision 28a74c3bd54dc4b503262ebfaaeef9ce27944841
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "common.h"
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen#include "temp-string.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "commands.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen/* Returns status items, or -1 if error */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic MailboxStatusItems get_status_items(Client *client, ImapArgList *list)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const char *item;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen MailboxStatusItems items;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen items = 0;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen for (; list != NULL; list = list->next) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (list->arg.type != IMAP_ARG_ATOM) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* list may contain only atoms */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen client_send_command_error(client, "Status list "
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen "contains non-atoms.");
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return -1;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen str_ucase(list->arg.data.str);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen item = list->arg.data.str;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (strcmp(item, "MESSAGES") == 0)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen items |= STATUS_MESSAGES;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen else if (strcmp(item, "RECENT") == 0)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen items |= STATUS_RECENT;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen else if (strcmp(item, "UIDNEXT") == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen items |= STATUS_UIDNEXT;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen else if (strcmp(item, "UIDVALIDITY") == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen items |= STATUS_UIDVALIDITY;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen else if (strcmp(item, "UNSEEN") == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen items |= STATUS_UNSEEN;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen else {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen client_send_tagline(client, t_strconcat(
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen "BAD Invalid status item ", item, NULL));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return -1;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen }
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen }
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return items;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic int mailbox_name_equals(const char *box1, const char *box2)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (strcmp(box1, box2) == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return TRUE;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return strcasecmp(box1, "INBOX") == 0 && strcasecmp(box2, "INBOX") == 0;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen}
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic int get_mailbox_status(Client *client, const char *mailbox,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen MailboxStatusItems items, MailboxStatus *status)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen Mailbox *box;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen int failed;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (client->mailbox != NULL &&
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mailbox_name_equals(client->mailbox->name, mailbox)) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* this mailbox is selected */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen box = client->mailbox;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen } else {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* open the mailbox */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen box = client->storage->open_mailbox(client->storage,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mailbox, FALSE);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (box == NULL)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen failed = !box->get_status(box, items, status);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (box != client->mailbox)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen box->close(box);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return !failed;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen}
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenint cmd_status(Client *client)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ImapArg *args;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen MailboxStatus status;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen MailboxStatusItems items;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen const char *mailbox;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen TempString *str;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* <mailbox> <status items> */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (!client_read_args(client, 2, 0, &args))
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return FALSE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen mailbox = imap_arg_string(&args[0]);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (mailbox == NULL || args[1].type != IMAP_ARG_LIST) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen client_send_command_error(client, "Status items must be list.");
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* get the items client wants */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen items = get_status_items(client, args[1].data.list);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (items == (MailboxStatusItems)-1) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* error */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return TRUE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen }
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* get status */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (!get_mailbox_status(client, mailbox, items, &status)) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen client_send_storage_error(client);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return TRUE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen }
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen str = t_string_new(128);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen t_string_printfa(str, "* STATUS %s (", mailbox);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (items & STATUS_MESSAGES)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen t_string_printfa(str, "MESSAGES %u ", status.messages);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (items & STATUS_RECENT)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen t_string_printfa(str, "RECENT %u ", status.recent);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (items & STATUS_UIDNEXT)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen t_string_printfa(str, "UIDNEXT %u ", status.uidnext);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (items & STATUS_UIDVALIDITY)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen t_string_printfa(str, "UIDVALIDITY %u ", status.uidvalidity);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (items & STATUS_UNSEEN)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen t_string_printfa(str, "UNSEEN %u ", status.unseen);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (str->str[str->len-1] == ' ')
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen t_string_truncate(str, str->len-1);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen t_string_append_c(str, ')');
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen client_send_line(client, str->str);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen client_send_tagline(client, "OK Status completed.");
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen