From 848dbae248c88bebd028372394acc89616f7c247 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Sun, 17 Jul 2016 19:31:16 -0700 Subject: [PATCH] Add imap-fast-trash patch. This is based on the patch by Paul Miller. Modifications are: * Create a new flag, MUTT_TRASH for imap_make_msg_set(), rather than use MUTT_EXPIRED. * Change imap_make_msg_set(MUTT_TRASH) to only look at hdrs[n]->deleted && !hdrs[n]->purge, behaving like MUTT_TAG, rather than looking at the HEADER_DATA. * Reimplement imap_fast_trash() based on imap_copy_message(). It looks the old version was too, but it lacked handling of TRYCREATE and also queued the UID COPY but didn't exec it. (Presumably this happened in the subsequent sync). * Move the Context magic and mx_is_imap() checks outside of imap_fast_trash() --- imap/imap.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ imap/imap.h | 1 + mutt.h | 1 + mx.c | 8 +++++ 4 files changed, 109 insertions(+) diff --git a/imap/imap.c b/imap/imap.c index f5066b25..460a3d68 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -924,6 +924,10 @@ static int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, if (hdrs[n]->tagged) match = 1; break; + case MUTT_TRASH: + if (hdrs[n]->deleted && !hdrs[n]->purge) + match = 1; + break; } if (match && (!changed || hdrs[n]->changed)) @@ -2073,6 +2077,101 @@ int imap_complete(char* dest, size_t dlen, char* path) { return -1; } +/* imap_fast_trash: use server COPY command to copy deleted + * messages to the trash folder. + * Return codes: + * -1: error + * 0: success + * 1: non-fatal error - try fetch/append */ +int imap_fast_trash (CONTEXT* ctx, char* dest) +{ + IMAP_DATA* idata; + char mbox[LONG_STRING]; + char mmbox[LONG_STRING]; + char prompt[LONG_STRING]; + int rc; + IMAP_MBOX mx; + int triedcreate = 0; + + idata = (IMAP_DATA*) ctx->data; + + if (imap_parse_path (dest, &mx)) + { + dprint (1, (debugfile, "imap_fast_trash: bad destination %s\n", dest)); + return -1; + } + + /* check that the save-to folder is in the same account */ + if (!mutt_account_match (&(CTX_DATA->conn->account), &(mx.account))) + { + dprint (3, (debugfile, "imap_fast_trash: %s not same server as %s\n", + dest, ctx->path)); + return 1; + } + + imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); + if (!*mbox) + strfcpy (mbox, "INBOX", sizeof (mbox)); + imap_munge_mbox_name (idata, mmbox, sizeof (mmbox), mbox); + + /* loop in case of TRYCREATE */ + do + { + rc = imap_exec_msgset (idata, "UID COPY", mmbox, MUTT_TRASH, 0, 0); + if (!rc) + { + dprint (1, (debugfile, "imap_fast_trash: No messages to trash\n")); + rc = -1; + goto out; + } + else if (rc < 0) + { + dprint (1, (debugfile, "could not queue copy\n")); + goto out; + } + else + mutt_message (_("Copying %d messages to %s..."), rc, mbox); + + /* let's get it on */ + rc = imap_exec (idata, NULL, IMAP_CMD_FAIL_OK); + if (rc == -2) + { + if (triedcreate) + { + dprint (1, (debugfile, "Already tried to create mailbox %s\n", mbox)); + break; + } + /* bail out if command failed for reasons other than nonexistent target */ + if (ascii_strncasecmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11)) + break; + dprint (3, (debugfile, "imap_fast_trash: server suggests TRYCREATE\n")); + snprintf (prompt, sizeof (prompt), _("Create %s?"), mbox); + if (option (OPTCONFIRMCREATE) && mutt_yesorno (prompt, 1) < 1) + { + mutt_clear_error (); + goto out; + } + if (imap_create_mailbox (idata, mbox) < 0) + break; + triedcreate = 1; + } + } + while (rc == -2); + + if (rc != 0) + { + imap_error ("imap_fast_trash", idata->buf); + goto out; + } + + rc = 0; + + out: + FREE (&mx.mbox); + + return rc < 0 ? -1 : rc; +} + struct mx_ops mx_imap_ops = { .open = imap_open_mailbox, .close = imap_close_mailbox, diff --git a/imap/imap.h b/imap/imap.h index ff0a1ba0..891cc0bf 100644 --- a/imap/imap.h +++ b/imap/imap.h @@ -43,6 +43,7 @@ int imap_status (char *path, int queue); int imap_search (CONTEXT* ctx, const pattern_t* pat); int imap_subscribe (char *path, int subscribe); int imap_complete (char* dest, size_t dlen, char* path); +int imap_fast_trash (CONTEXT* ctx, char* dest); void imap_allow_reopen (CONTEXT *ctx); void imap_disallow_reopen (CONTEXT *ctx); diff --git a/mutt.h b/mutt.h index bd90a49b..18fb2d16 100644 --- a/mutt.h +++ b/mutt.h @@ -189,6 +189,7 @@ enum MUTT_LIMIT, MUTT_EXPIRED, MUTT_SUPERSEDED, + MUTT_TRASH, /* actions for mutt_pattern_comp/mutt_pattern_exec */ MUTT_AND, diff --git a/mx.c b/mx.c index 07f3b408..70f31f74 100644 --- a/mx.c +++ b/mx.c @@ -832,6 +832,14 @@ static int trash_append (CONTEXT *ctx) && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev) return 0; /* we are in the trash folder: simple sync */ +#ifdef USE_IMAP + if (Context->magic == MUTT_IMAP && mx_is_imap (TrashPath)) + { + if (!imap_fast_trash (Context, TrashPath)) + return 0; + } +#endif + if ((ctx_trash = mx_open_mailbox (TrashPath, MUTT_APPEND, NULL)) != NULL) { /* continue from initial scan above */ -- 2.40.0