# HG changeset patch # User Timo Sirainen # Date 1226775594 -7200 # Node ID abd0ef855a33daa7eef9d16d2424b7a8457dd879 # Parent 3c0d14ec17a5f1d6fa55f701ba2f585abed93f64 Implemented imap-response-codes draft. diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap-login/client-authenticate.c --- a/src/imap-login/client-authenticate.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap-login/client-authenticate.c Sat Nov 15 20:59:54 2008 +0200 @@ -18,6 +18,7 @@ #include #define IMAP_SERVICE_NAME "imap" +#define IMAP_AUTH_FAILED_MSG "[AUTHENTICATIONFAILED] "AUTH_FAILED_MSG const char *client_authenticate_get_capabilities(bool secured) { @@ -178,10 +179,12 @@ reply = t_str_new(128); if (reason != NULL) str_printfa(reply, "NO %s", reason); - else if (temp || proxy_self) - str_append(reply, "NO "AUTH_TEMP_FAILED_MSG); - else - str_append(reply, "NO "AUTH_FAILED_MSG); + else if (temp || proxy_self) { + str_append(reply, "NO [UNAVAILABLE] " + AUTH_TEMP_FAILED_MSG); + } else { + str_append(reply, "NO "IMAP_AUTH_FAILED_MSG); + } client_send_tagline(client, str_c(reply)); } else { /* normal login/failure */ @@ -227,8 +230,8 @@ } msg = reply == SASL_SERVER_REPLY_AUTH_FAILED ? "NO " : "BAD "; - msg = t_strconcat(msg, data != NULL ? data : AUTH_FAILED_MSG, - NULL); + msg = t_strconcat(msg, data != NULL ? data : + IMAP_AUTH_FAILED_MSG, NULL); client_send_tagline(client, msg); if (!client->destroyed) @@ -334,7 +337,8 @@ "* BAD [ALERT] Plaintext authentication is disabled, " "but your client sent password in plaintext anyway. " "If anyone was listening, the password was exposed."); - client_send_tagline(client, "NO "AUTH_PLAINTEXT_DISABLED_MSG); + client_send_tagline(client, "NO [CLIENTBUG] " + AUTH_PLAINTEXT_DISABLED_MSG); return 1; } diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/client.c --- a/src/imap/client.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/client.c Sat Nov 15 20:59:54 2008 +0200 @@ -409,8 +409,8 @@ } if (broken_client) { - client_send_line(cmd->client, - "* BAD Command pipelining results in ambiguity."); + client_send_line(cmd->client, "* BAD [CLIENTBUG] " + "Command pipelining results in ambiguity."); } return TRUE; diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/cmd-copy.c --- a/src/imap/cmd-copy.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/cmd-copy.c Sat Nov 15 20:59:54 2008 +0200 @@ -171,8 +171,8 @@ return cmd_sync(cmd, sync_flags, imap_flags, msg); else if (ret == 0) { /* some messages were expunged, sync them */ - return cmd_sync(cmd, 0, 0, - "NO Some of the requested messages no longer exist."); + return cmd_sync(cmd, 0, 0, "NO [EXPUNGEISSUED] " + "Some of the requested messages no longer exist."); } else { client_send_storage_error(cmd, storage); return TRUE; diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/cmd-fetch.c --- a/src/imap/cmd-fetch.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/cmd-fetch.c Sat Nov 15 20:59:54 2008 +0200 @@ -131,6 +131,11 @@ struct client_command_context *cmd = ctx->cmd; static const char *ok_message = "OK Fetch completed."; + if (ctx->partial_fetch) { + ok_message = "OK [EXPUNGEISSUED] " + "Some messages were already expunged."; + } + if (imap_fetch_deinit(ctx) < 0) ctx->failed = TRUE; diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/cmd-search.c --- a/src/imap/cmd-search.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/cmd-search.c Sat Nov 15 20:59:54 2008 +0200 @@ -366,7 +366,7 @@ const struct seq_range *range; unsigned int count; uint32_t id, id_min, id_max; - bool tryagain, minmax; + bool tryagain, minmax, lost_data; if (cmd->cancel) { (void)imap_search_deinit(ctx); @@ -440,6 +440,7 @@ } } + lost_data = mailbox_search_seen_lost_data(ctx->search_ctx); if (imap_search_deinit(ctx) < 0) { client_send_storage_error(cmd, mailbox_get_storage(cmd->client->mailbox)); @@ -459,7 +460,8 @@ if (!cmd->uid || ctx->have_seqsets) sync_flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES; return cmd_sync(cmd, sync_flags, 0, - t_strdup_printf("OK Search completed (%d.%03d secs).", + t_strdup_printf("OK %sSearch completed (%d.%03d secs).", + lost_data ? "[EXPUNGEISSUED] " : "", (int)end_time.tv_sec, (int)(end_time.tv_usec/1000))); } diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/cmd-status.c --- a/src/imap/cmd-status.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/cmd-status.c Sat Nov 15 20:59:54 2008 +0200 @@ -13,6 +13,7 @@ enum mailbox_status_items items; struct mail_storage *storage; const char *mailbox, *real_mailbox; + bool selected_mailbox; /* */ if (!client_read_args(cmd, 2, 0, &args)) @@ -33,13 +34,19 @@ if (storage == NULL) return TRUE; + selected_mailbox = client->mailbox != NULL && + mailbox_equals(client->mailbox, storage, real_mailbox); if (!imap_status_get(client, storage, real_mailbox, items, &status)) { client_send_storage_error(cmd, storage); return TRUE; } imap_status_send(client, mailbox, items, &status); - client_send_tagline(cmd, "OK Status completed."); - + if (!selected_mailbox) + client_send_tagline(cmd, "OK Status completed."); + else { + client_send_tagline(cmd, "OK [CLIENTBUG] " + "Status on selected mailbox completed."); + } return TRUE; } diff -r 3c0d14ec17a5 -r abd0ef855a33 src/imap/commands-util.c --- a/src/imap/commands-util.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/imap/commands-util.c Sat Nov 15 20:59:54 2008 +0200 @@ -143,6 +143,46 @@ } } +static const char * +get_error_string(const char *error_string, enum mail_error error) +{ + const char *resp_code = NULL; + + switch (error) { + case MAIL_ERROR_NONE: + break; + case MAIL_ERROR_TEMP: + resp_code = "SERVERBUG"; + break; + case MAIL_ERROR_NOTPOSSIBLE: + case MAIL_ERROR_PARAMS: + resp_code = "CANNOT"; + break; + case MAIL_ERROR_PERM: + resp_code = "ACL"; + break; + case MAIL_ERROR_NOSPACE: + resp_code = "OVERQUOTA"; + break; + case MAIL_ERROR_NOTFOUND: + resp_code = "NONEXISTENT"; + break; + case MAIL_ERROR_EXISTS: + resp_code = "ALREADYEXISTS"; + break; + case MAIL_ERROR_EXPUNGED: + resp_code = "EXPUNGEISSUED"; + break; + case MAIL_ERROR_INUSE: + resp_code = "INUSE"; + break; + } + if (resp_code == NULL || *error_string == '[') + return t_strconcat("NO ", error_string, NULL); + else + return t_strdup_printf("NO [%s] %s", resp_code, error_string); +} + void client_send_list_error(struct client_command_context *cmd, struct mailbox_list *list) { @@ -150,7 +190,7 @@ enum mail_error error; error_string = mailbox_list_get_last_error(list, &error); - client_send_tagline(cmd, t_strconcat("NO ", error_string, NULL)); + client_send_tagline(cmd, get_error_string(error_string, error)); } void client_send_storage_error(struct client_command_context *cmd, @@ -168,7 +208,7 @@ } error_string = mail_storage_get_last_error(storage, &error); - client_send_tagline(cmd, t_strconcat("NO ", error_string, NULL)); + client_send_tagline(cmd, get_error_string(error_string, error)); } void client_send_untagged_storage_error(struct client *client, diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/index/cydir/cydir-storage.c --- a/src/lib-storage/index/cydir/cydir-storage.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/index/cydir/cydir-storage.c Sat Nov 15 20:59:54 2008 +0200 @@ -224,7 +224,7 @@ path = mailbox_list_get_path(_storage->list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -293,7 +293,7 @@ } if (!unlinked_something) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, t_strdup_printf("Directory %s isn't empty, " "can't delete it.", name)); return -1; diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/index/dbox/dbox-storage.c --- a/src/lib-storage/index/dbox/dbox-storage.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/index/dbox/dbox-storage.c Sat Nov 15 20:59:54 2008 +0200 @@ -344,7 +344,7 @@ directory ? MAILBOX_LIST_PATH_TYPE_DIR : MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -355,7 +355,7 @@ it. */ alt_path = directory ? NULL : dbox_get_alt_path(storage, path); if (alt_path != NULL && stat(alt_path, &st) == 0) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -426,7 +426,7 @@ } if (!unlinked_something) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, t_strdup_printf("Directory %s isn't empty, " "can't delete it.", name)); return -1; @@ -501,7 +501,7 @@ else if (errno == ENOTEMPTY) { if (deleted) return 0; - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, t_strdup_printf("Directory %s isn't empty, " "can't delete it.", name)); } else if (!mailbox_list_set_error_from_errno(list)) { @@ -547,7 +547,7 @@ if (stat(alt_newpath, &st) == 0) { /* race condition or a directory left there lying around? safest to just report error. */ - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_EXISTS, "Target mailbox already exists"); return -1; } else if (errno != ENOENT) { diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/index/index-search.c --- a/src/lib-storage/index/index-search.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/index/index-search.c Sat Nov 15 20:59:54 2008 +0200 @@ -1207,6 +1207,9 @@ } else T_BEGIN { ret = search_match_next(ctx) ? 1 : 0; + if (ctx->mail->expunged) + _ctx->seen_lost_data = TRUE; + if (ret == 0 && search_has_static_nonmatches(_ctx->args->args)) { /* if there are saved search results remember diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/index/maildir/maildir-storage.c --- a/src/lib-storage/index/maildir/maildir-storage.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/index/maildir/maildir-storage.c Sat Nov 15 20:59:54 2008 +0200 @@ -312,7 +312,7 @@ if (errno == EEXIST) { if (verify) return 0; - mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); } else if (errno == ENOENT) { mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND, @@ -370,7 +370,7 @@ ret = maildir_check_tmp(storage, dir); if (ret > 0) { if (!verify) { - mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -718,7 +718,7 @@ } if (!unlinked_something) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, t_strdup_printf("Directory %s isn't empty, " "can't delete it.", name)); return -1; diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/index/mbox/mbox-storage.c --- a/src/lib-storage/index/mbox/mbox-storage.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/index/mbox/mbox-storage.c Sat Nov 15 20:59:54 2008 +0200 @@ -715,7 +715,7 @@ path = mailbox_list_get_path(_storage->list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX); if (stat(path, &st) == 0) { - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); return -1; } @@ -760,7 +760,7 @@ if (errno == EEXIST) { /* mailbox was just created between stat() and open() call.. */ - mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE, + mail_storage_set_error(_storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); } else if (!mail_storage_set_error_from_errno(_storage)) { mail_storage_set_critical(_storage, @@ -947,7 +947,7 @@ mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(name)); } else if (errno == ENOTEMPTY) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND, t_strdup_printf("Directory %s isn't empty, " "can't delete it.", name)); } else if (!mailbox_list_set_error_from_errno(list)) { diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/list/mailbox-list-fs.c --- a/src/lib-storage/list/mailbox-list-fs.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/list/mailbox-list-fs.c Sat Nov 15 20:59:54 2008 +0200 @@ -305,7 +305,7 @@ possibility that someone actually tries to rename two mailboxes to same new one */ if (lstat(newpath, &st) == 0) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_EXISTS, "Target mailbox already exists"); return -1; } else if (errno == ENOTDIR) { diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/list/mailbox-list-maildir.c --- a/src/lib-storage/list/mailbox-list-maildir.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/list/mailbox-list-maildir.c Sat Nov 15 20:59:54 2008 +0200 @@ -426,7 +426,7 @@ } if (EDESTDIREXISTS(errno)) { - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_EXISTS, "Target mailbox already exists"); } else { mailbox_list_set_critical(list, "rename(%s, %s) failed: %m", diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/mail-error.h --- a/src/lib-storage/mail-error.h Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/mail-error.h Sat Nov 15 20:59:54 2008 +0200 @@ -26,10 +26,15 @@ MAIL_ERROR_PERM, /* Out of disk space or quota */ MAIL_ERROR_NOSPACE, - /* Item (eg. mailbox) doesn't exist or it's not visible to us */ + /* Item (e.g. mailbox) doesn't exist or it's not visible to us */ MAIL_ERROR_NOTFOUND, + /* Item (e.g. mailbox) already exists */ + MAIL_ERROR_EXISTS, /* Tried to access an expunged message */ - MAIL_ERROR_EXPUNGED + MAIL_ERROR_EXPUNGED, + /* Operation cannot be done because another session prevents it + (e.g. lock timeout) */ + MAIL_ERROR_INUSE }; /* Convert errno to mail_error and an error string. Returns TRUE if successful, diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/mail-storage-private.h --- a/src/lib-storage/mail-storage-private.h Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/mail-storage-private.h Sat Nov 15 20:59:54 2008 +0200 @@ -311,6 +311,8 @@ uint32_t seq; ARRAY_DEFINE(module_contexts, union mail_search_module_context *); + + unsigned int seen_lost_data:1; }; struct mail_save_context { diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/mail-storage.c Sat Nov 15 20:59:54 2008 +0200 @@ -699,6 +699,11 @@ return ret; } +bool mailbox_search_seen_lost_data(struct mail_search_context *ctx) +{ + return ctx->seen_lost_data; +} + int mailbox_search_result_build(struct mailbox_transaction_context *t, struct mail_search_args *args, enum mailbox_search_result_flags flags, diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/mail-storage.h Sat Nov 15 20:59:54 2008 +0200 @@ -431,6 +431,10 @@ finished, and TRUE if more results will by calling the function again. */ int mailbox_search_next_nonblock(struct mail_search_context *ctx, struct mail *mail, bool *tryagain_r); +/* Returns TRUE if some messages were already expunged and we couldn't + determine correctly if those messages should have been returned in this + search. */ +bool mailbox_search_seen_lost_data(struct mail_search_context *ctx); /* Remember the search result for future use. This must be called before the first mailbox_search_next*() call. */ diff -r 3c0d14ec17a5 -r abd0ef855a33 src/lib-storage/mailbox-list.c --- a/src/lib-storage/mailbox-list.c Sat Nov 15 20:23:46 2008 +0200 +++ b/src/lib-storage/mailbox-list.c Sat Nov 15 20:59:54 2008 +0200 @@ -554,7 +554,7 @@ if (errno == ENOTEMPTY) { /* We're most likely using NFS and we can't delete .nfs* files. */ - mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE, + mailbox_list_set_error(list, MAIL_ERROR_INUSE, "Mailbox is still open in another session, " "can't delete it."); } else {