commands-util.c revision cb05ecbd96ddb5e53c1850d27434541138a3f284
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "common.h"
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen#include "array.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "buffer.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "str.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "str-sanitize.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "mail-storage.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "commands-util.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "imap-parser.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "imap-sync.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "imap-util.h"
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen#include "mail-namespace.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen/* Maximum length for mailbox name, including it's path. This isn't fully
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen exact since the user can create folder hierarchy with small names, then
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen rename them to larger names. Mail storages should set more strict limits
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen to them, mbox/maildir currently allow paths only up to PATH_MAX. */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen#define MAILBOX_MAX_NAME_LEN 512
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstruct mail_namespace *
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenclient_find_namespace(struct client_command_context *cmd, const char **mailbox)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = mail_namespace_find(cmd->client->namespaces, mailbox);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns != NULL)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, "NO Unknown namespace.");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return NULL;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen}
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstruct mail_storage *
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenclient_find_storage(struct client_command_context *cmd, const char **mailbox)
20e04227229970d148801c507946666e2a9bd838Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = client_find_namespace(cmd, mailbox);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return ns == NULL ? NULL : ns->storage;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen}
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenbool client_verify_mailbox_name(struct client_command_context *cmd,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen const char *mailbox,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen bool should_exist, bool should_not_exist)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mailbox_list *list;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen enum mailbox_name_status mailbox_status;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen const char *orig_mailbox, *p;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen orig_mailbox = mailbox;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = client_find_namespace(cmd, &mailbox);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns == NULL)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* make sure it even looks valid */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (*mailbox == '\0') {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, "NO Empty mailbox name.");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns->real_sep != ns->sep && ns->prefix_len < strlen(orig_mailbox)) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* make sure there are no real separators used in the mailbox
20e04227229970d148801c507946666e2a9bd838Timo Sirainen name. */
20e04227229970d148801c507946666e2a9bd838Timo Sirainen orig_mailbox += ns->prefix_len;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen for (p = orig_mailbox; *p != '\0'; p++) {
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (*p == ns->real_sep) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, t_strdup_printf(
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "NO Character not allowed "
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "in mailbox name: '%c'",
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns->real_sep));
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* make sure two hierarchy separators aren't next to each others */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen for (p = mailbox+1; *p != '\0'; p++) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (p[0] == ns->real_sep && p[-1] == ns->real_sep) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, "NO Invalid mailbox name.");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (strlen(mailbox) > MAILBOX_MAX_NAME_LEN) {
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen client_send_tagline(cmd, "NO Mailbox name too long.");
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen /* check what our storage thinks of it */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen list = mail_storage_get_list(ns->storage);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (mailbox_list_get_mailbox_name_status(list, mailbox,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen &mailbox_status) < 0) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_storage_error(cmd, ns->storage);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen switch (mailbox_status) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen case MAILBOX_NAME_EXISTS:
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (should_exist || !should_not_exist)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return TRUE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, "NO Mailbox exists.");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen break;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen case MAILBOX_NAME_VALID:
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (!should_exist)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return TRUE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_tagline(cmd, t_strconcat(
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen "NO [TRYCREATE] Mailbox doesn't exist: ",
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen str_sanitize(orig_mailbox, MAILBOX_MAX_NAME_LEN),
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen NULL));
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen break;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen case MAILBOX_NAME_INVALID:
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen client_send_tagline(cmd, t_strconcat(
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "NO Invalid mailbox name: ",
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen str_sanitize(orig_mailbox, MAILBOX_MAX_NAME_LEN),
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen NULL));
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen break;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen case MAILBOX_NAME_NOINFERIORS:
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen client_send_tagline(cmd,
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen "NO Mailbox parent doesn't allow inferior mailboxes.");
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen break;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen
20e04227229970d148801c507946666e2a9bd838Timo Sirainen default:
20e04227229970d148801c507946666e2a9bd838Timo Sirainen i_unreached();
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen return FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenbool client_verify_open_mailbox(struct client_command_context *cmd)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (cmd->client->mailbox != NULL)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return TRUE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen client_send_tagline(cmd, "BAD No mailbox selected.");
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenvoid client_send_list_error(struct client_command_context *cmd,
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen struct mailbox_list *list)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *error_string;
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen enum mail_error error;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen error_string = mailbox_list_get_last_error(list, &error);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen client_send_tagline(cmd, t_strconcat("NO ", error_string, NULL));
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenvoid client_send_storage_error(struct client_command_context *cmd,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct mail_storage *storage)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen{
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char *error_string;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen enum mail_error error;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (cmd->client->mailbox != NULL &&
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen mailbox_is_inconsistent(cmd->client->mailbox)) {
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen /* we can't do forced CLOSE, so have to disconnect */
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen client_disconnect_with_error(cmd->client,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen "Mailbox is in inconsistent state, please relogin.");
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen }
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen error_string = mail_storage_get_last_error(storage, &error);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen client_send_tagline(cmd, t_strconcat("NO ", error_string, NULL));
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenvoid client_send_untagged_storage_error(struct client *client,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct mail_storage *storage)
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen{
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen const char *error_string;
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen enum mail_error error;
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen if (client->mailbox != NULL &&
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen mailbox_is_inconsistent(client->mailbox)) {
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen /* we can't do forced CLOSE, so have to disconnect */
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen client_disconnect_with_error(client,
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen "Mailbox is in inconsistent state, please relogin.");
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen return;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen }
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen error_string = mail_storage_get_last_error(storage, &error);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen client_send_line(client, t_strconcat("* NO ", error_string, NULL));
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenbool client_parse_mail_flags(struct client_command_context *cmd,
6cc4cce2078aca138fbce19305e69e77edcee614Timo Sirainen const struct imap_arg *args,
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi enum mail_flags *flags_r,
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi const char *const **keywords_r)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *atom;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen ARRAY_DEFINE(keywords, const char *);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen *flags_r = 0;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *keywords_r = NULL;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen p_array_init(&keywords, cmd->pool, 16);
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi
ab5269901fa285cf66bc55dd068979d4fdbb4c23Timo Sirainen while (args->type != IMAP_ARG_EOL) {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (args->type != IMAP_ARG_ATOM) {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen client_send_command_error(cmd,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen "Flags list contains non-atoms.");
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen atom = IMAP_ARG_STR(args);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (*atom == '\\') {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen /* system flag */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen atom = t_str_ucase(atom);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (strcmp(atom, "\\ANSWERED") == 0)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen *flags_r |= MAIL_ANSWERED;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else if (strcmp(atom, "\\FLAGGED") == 0)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen *flags_r |= MAIL_FLAGGED;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else if (strcmp(atom, "\\DELETED") == 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *flags_r |= MAIL_DELETED;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else if (strcmp(atom, "\\SEEN") == 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *flags_r |= MAIL_SEEN;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else if (strcmp(atom, "\\DRAFT") == 0)
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen *flags_r |= MAIL_DRAFT;
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen else {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen client_send_tagline(cmd, t_strconcat(
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen "BAD Invalid system flag ",
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen atom, NULL));
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen /* keyword validity checks are done by lib-storage */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen array_append(&keywords, &atom, 1);
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi }
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi args++;
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (array_count(&keywords) == 0)
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen *keywords_r = NULL;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen (void)array_append_space(&keywords); /* NULL-terminate */
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen *keywords_r = array_idx(&keywords, 0);
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen }
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi return TRUE;
ab5269901fa285cf66bc55dd068979d4fdbb4c23Timo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic const char *get_keywords_string(const ARRAY_TYPE(keywords) *keywords)
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen string_t *str;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *const *names;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen unsigned int i, count;
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen if (array_count(keywords) == 0)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return "";
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen str = t_str_new(256);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen names = array_get(keywords, &count);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen for (i = 0; i < count; i++) {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen str_append_c(str, ' ');
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen str_append(str, names[i]);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return str_c(str);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#define SYSTEM_FLAGS "\\Answered \\Flagged \\Deleted \\Seen \\Draft"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenvoid client_send_mailbox_flags(struct client *client, struct mailbox *box,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const ARRAY_TYPE(keywords) *keywords)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *str;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen str = get_keywords_string(keywords);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen client_send_line(client,
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen t_strconcat("* FLAGS ("SYSTEM_FLAGS, str, ")", NULL));
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen if (mailbox_is_readonly(box)) {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen client_send_line(client, "* OK [PERMANENTFLAGS ()] "
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen "Read-only mailbox.");
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen } else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen client_send_line(client,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen t_strconcat("* OK [PERMANENTFLAGS ("SYSTEM_FLAGS, str,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen mailbox_allow_new_keywords(box) ?
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen " \\*" : "", ")] Flags permitted.", NULL));
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenbool client_save_keywords(struct mailbox_keywords *dest,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const ARRAY_TYPE(keywords) *keywords)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *const *names, *const *old_names;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen unsigned int i, count, old_count;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen bool changed;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen names = array_get(keywords, &count);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen /* first check if anything changes */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (!array_is_created(&dest->keywords))
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen changed = count != 0;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen old_names = array_get(&dest->keywords, &old_count);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (count != old_count)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen changed = TRUE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen changed = FALSE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen for (i = 0; i < count; i++) {
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen if (strcmp(names[i], old_names[i]) != 0) {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen changed = TRUE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen break;
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen }
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen }
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen }
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen }
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen if (!changed)
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen return FALSE;
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen p_clear(dest->pool);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen p_array_init(&dest->keywords, dest->pool, array_count(keywords));
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen for (i = 0; i < count; i++) {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *name = p_strdup(dest->pool, names[i]);
array_append(&dest->keywords, &name, 1);
}
return TRUE;
}
bool mailbox_equals(struct mailbox *box1, struct mail_storage *storage2,
const char *name2)
{
struct mail_storage *storage1 = mailbox_get_storage(box1);
const char *name1;
if (storage1 != storage2)
return FALSE;
name1 = mailbox_get_name(box1);
if (strcmp(name1, name2) == 0)
return TRUE;
return strcasecmp(name1, "INBOX") == 0 &&
strcasecmp(name2, "INBOX") == 0;
}
void msgset_generator_init(struct msgset_generator_context *ctx, string_t *str)
{
memset(ctx, 0, sizeof(*ctx));
ctx->str = str;
ctx->last_uid = (uint32_t)-1;
}
void msgset_generator_next(struct msgset_generator_context *ctx, uint32_t uid)
{
if (uid != ctx->last_uid+1) {
if (ctx->first_uid == 0)
;
else if (ctx->first_uid == ctx->last_uid)
str_printfa(ctx->str, "%u,", ctx->first_uid);
else {
str_printfa(ctx->str, "%u:%u,",
ctx->first_uid, ctx->last_uid);
}
ctx->first_uid = uid;
}
ctx->last_uid = uid;
}
void msgset_generator_finish(struct msgset_generator_context *ctx)
{
if (ctx->first_uid == ctx->last_uid)
str_printfa(ctx->str, "%u", ctx->first_uid);
else
str_printfa(ctx->str, "%u:%u", ctx->first_uid, ctx->last_uid);
}