imap-commands-util.c revision 24e8feedfc223fcdddb2c9eb4605cbd98afce449
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher/* Maximum length for mailbox name, including it's path. This isn't fully
d71cd46ede9c57e3947c86c61306a9caddce242cLukas Slebodnik exact since the user can create folder hierarchy with small names, then
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher rename them to larger names. Mail storages should set more strict limits
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik to them, mbox/maildir currently allow paths only up to PATH_MAX. */
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozekclient_find_namespace(struct client_command_context *cmd, const char *mailbox,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_namespace *namespaces = cmd->client->user->namespaces;
f0ea3ed816182fadf77f3e7f7ddb298b287007adLukas Slebodnik const char *storage_name, *p;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher ns = mail_namespace_find(namespaces, &storage_name);
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina "NO Client tried to access nonexistent namespace. "
c481179da5d5b53ce16d8784c0bd2857ffc2f061Lukas Slebodnik "(Mailbox name should probably be prefixed with: %s)",
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher mail_namespace_find_inbox(namespaces)->prefix));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* make sure it even looks valid */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*storage_name == '\0' && !(*mailbox != '\0' && ns->list)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_tagline(cmd, "NO Empty mailbox name.");
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek storage_name[storage_name_len-1] == ns->real_sep) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* drop the extra trailing hierarchy separator */
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce storage_name = t_strndup(storage_name, storage_name_len-1);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* trying to open "ns prefix/" */
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek client_send_tagline(cmd, "NO Invalid mailbox name.");
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (ns->real_sep != ns->sep && ns->prefix_len < strlen(mailbox)) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* make sure there are no real separators used in the mailbox
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek "NO Character not allowed "
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik "in mailbox name: '%c'",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* make sure two hierarchy separators aren't next to each others */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (p = storage_name+1; *p != '\0'; p++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (p[0] == ns->real_sep && p[-1] == ns->real_sep) {
d921c1eba437662437847279f251a0a5d8f70127Maxim client_send_tagline(cmd, "NO Mailbox name too long.");
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* check what our storage thinks of it */
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer if (mailbox_list_get_mailbox_name_status(ns->list, storage_name,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid client_fail_mailbox_name_status(struct client_command_context *cmd,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "] Mailbox already exists: ",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke resp_code = t_strconcat("[", resp_code, "] ", NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "NO ", resp_code, "Mailbox doesn't exist: ",
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek "NO Invalid mailbox name: ",
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozek str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
e07a94a66985b674c5df11ca466792902164c4e2George McCollister "NO Parent mailbox doesn't allow child mailboxes.");
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bosebool client_verify_open_mailbox(struct client_command_context *cmd)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_tagline(cmd, "BAD No mailbox selected.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherimap_get_error_string(struct client_command_context *cmd,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *error_string, enum mail_error error)
c3889e5a101a075defe533d81f5296d5e680f639Lukas Slebodnik if ((cmd->cmd_flags & COMMAND_FLAG_USE_NONEXISTENT) != 0)
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik if (resp_code == NULL || *error_string == '[')
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik return t_strconcat("NO ", error_string, NULL);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return t_strdup_printf("NO [%s] %s", resp_code, error_string);
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnikvoid client_send_list_error(struct client_command_context *cmd,
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos error_string = mailbox_list_get_last_error(list, &error);
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos client_send_tagline(cmd, imap_get_error_string(cmd, error_string,
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozekvoid client_send_storage_error(struct client_command_context *cmd,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_is_inconsistent(cmd->client->mailbox)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we can't do forced CLOSE, so have to disconnect */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "IMAP session state is inconsistent, please relogin.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher error_string = mail_storage_get_last_error(storage, &error);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek client_send_tagline(cmd, imap_get_error_string(cmd, error_string,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid client_send_untagged_storage_error(struct client *client,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_is_inconsistent(client->mailbox)) {
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek /* we can't do forced CLOSE, so have to disconnect */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "IMAP session state is inconsistent, please relogin.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher error_string = mail_storage_get_last_error(storage, &error);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_line(client, t_strconcat("* NO ", error_string, NULL));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherbool client_parse_mail_flags(struct client_command_context *cmd,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek const char *const **keywords_r)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek const char *atom;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek "Flags list contains non-atoms.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* system flag */
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik "BAD Invalid system flag ",
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik /* keyword validity checks are done by lib-storage */
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek (void)array_append_space(&keywords); /* NULL-terminate */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikstatic const char *get_keywords_string(const ARRAY_TYPE(keywords) *keywords)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik const char *const *names;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik#define SYSTEM_FLAGS "\\Answered \\Flagged \\Deleted \\Seen \\Draft"
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikvoid client_send_mailbox_flags(struct client *client, bool selecting)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik unsigned int count = array_count(client->keywords.names);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (!selecting && count == client->keywords.announce_count) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* no changes to keywords and we're not selecting a mailbox */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik str = count == 0 ? "" : get_keywords_string(client->keywords.names);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik t_strconcat("* FLAGS ("SYSTEM_FLAGS, str, ")", NULL));
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik client_send_line(client, "* OK [PERMANENTFLAGS ()] "
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik "Read-only mailbox.");
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik bool star = mailbox_allow_new_keywords(client->mailbox);
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov t_strconcat("* OK [PERMANENTFLAGS ("SYSTEM_FLAGS, str,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid client_update_mailbox_flags(struct client *client,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozekconst char *const *
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozekclient_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek const unsigned int *kw_indexes;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek const char *const *all_names;
e07a94a66985b674c5df11ca466792902164c4e2George McCollister client_send_mailbox_flags(client, FALSE);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose /* convert indexes to names */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose all_names = array_get(client->keywords.names, &all_count);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce const struct mail_namespace *ns2, const char *name2)
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce struct mail_namespace *ns1 = mailbox_get_namespace(box1);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce const char *name1;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikvoid msgset_generator_init(struct msgset_generator_context *ctx, string_t *str)
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnikvoid msgset_generator_next(struct msgset_generator_context *ctx, uint32_t uid)
356eef72675cde4dc5627c1e2f1a01846ec6eb1dLukas Slebodnik str_printfa(ctx->str, "%u,", ctx->first_uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid msgset_generator_finish(struct msgset_generator_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_printfa(ctx->str, "%u", ctx->first_uid);