From f24c25bff3454897fbb8a6a888d1311e867f800e Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Wed, 8 Sep 1999 06:05:51 +0000 Subject: [PATCH] The attached patch: * gets Mutt to properly log off the IMAP server when quitting. Clients don't care, but it's polite and proper. * further updates the flags changes from yesterday * uses CLOSE instead of EXPUNGE when closing a mailbox and purging messages, for some slight speed gain. * purges all messages marked for deletion in one command (if purging), making for very cool speed gains switching mailboxes if you're on, say, a few high volume mailing lists. Yeah, baby! (I personally love this one). (From Brendan Cully ) --- curs_main.c | 14 +++++++ imap/imap.c | 95 ++++++++++++++++++++++++++++++++++++++++----- imap/imap.h | 2 + imap/imap_private.h | 3 +- mx.c | 50 ++++++++++++------------ 5 files changed, 129 insertions(+), 35 deletions(-) diff --git a/curs_main.c b/curs_main.c index c873e597..285f96b7 100644 --- a/curs_main.c +++ b/curs_main.c @@ -24,6 +24,11 @@ #include "sort.h" #include "buffy.h" +#ifdef USE_IMAP +#include "mx.h" +#include "imap.h" +#endif + #ifdef _PGPPATH @@ -746,6 +751,11 @@ int mutt_index_menu (void) if (query_quadoption (OPT_QUIT, _("Quit Mutt?")) == M_YES) { +#ifdef USE_IMAP + /* logout gracefully from the IMAP server */ + if (Context->magic == M_IMAP) + imap_set_logout (Context); +#endif if (!Context || mx_close_mailbox (Context) == 0) done = 1; else @@ -987,6 +997,10 @@ int mutt_index_menu (void) { if (Context) { +#ifdef USE_IMAP + if (Context->magic == M_IMAP) + imap_set_logout (Context); +#endif mx_fastclose_mailbox (Context); safe_free ((void **) &Context); } diff --git a/imap/imap.c b/imap/imap.c index b577de91..c1540451 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -54,6 +54,17 @@ static int imap_check_acl (IMAP_DATA *idata); static int imap_check_capabilities (IMAP_DATA *idata); static int imap_create_mailbox (IMAP_DATA *idata, char *mailbox); +void imap_error (const char *where, const char *msg) +{ + mutt_error (_("imap_error(): unexpected response in %s: %s\n"), where, msg); +} + +void imap_set_logout (CONTEXT *ctx) +{ + if (CTX_DATA) + CTX_DATA->status = IMAP_LOGOUT; +} + void imap_make_sequence (char *buf, size_t buflen) { static int sequence = 0; @@ -64,11 +75,6 @@ void imap_make_sequence (char *buf, size_t buflen) sequence = 0; } -void imap_error (const char *where, const char *msg) -{ - mutt_error (_("imap_error(): unexpected response in %s: %s\n"), where, msg); -} - /* imap_parse_date: date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */ time_t imap_parse_date (char *s) { @@ -354,7 +360,7 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s) } else { - dprint (1, (debugfile, "imap_unhandle_untagged(): unhandled request: %s\n", + dprint (1, (debugfile, "imap_handle_untagged(): unhandled request: %s\n", s)); } @@ -1277,7 +1283,64 @@ int imap_sync_mailbox (CONTEXT *ctx, int expunge) char seq[8]; char buf[LONG_STRING]; char flags[LONG_STRING]; + char tmp[LONG_STRING]; int n; + int setstart = 0; + + if (CTX_DATA->state != IMAP_SELECTED) + { + dprint (2, (debugfile, "imap_sync_mailbox: no mailbox selected\n")); + return -1; + } + + /* if we are expunging anyway, we can do deleted messages very quickly... */ + if (expunge && mutt_bit_isset (CTX_DATA->rights, IMAP_ACL_DELETE)) + { + buf[0] = '\0'; + for (n = 0; n < ctx->msgcount; n++) + { + if (ctx->hdrs[n]->changed && ctx->hdrs[n]->deleted) + { + if (setstart == 0) + { + setstart = n+1; + if (!buf[0]) + snprintf (buf, sizeof (buf), "%u", n+1); + else + { + strncpy (tmp, buf, sizeof (tmp)); + snprintf (buf, sizeof (buf), "%s,%u", tmp, n+1); + } + } + /* tie up if the last message is also deleted */ + else if (n == ctx->msgcount-1) + { + strncpy (tmp, buf, sizeof (tmp)); + snprintf (buf, sizeof (buf), "%s:%u", tmp, n+1); + } + /* the normal flag update can skip this message */ + ctx->hdrs[n]->changed = 0; + } + else if (setstart && (n > setstart)) + { + setstart = 0; + strncpy (tmp, buf, sizeof (tmp)); + snprintf (buf, sizeof (buf), "%s:%u", tmp, n); + } + } + /* if we have a message set, then let's delete */ + if (buf[0]) + { + snprintf (tmp, sizeof (tmp), _("Marking %d messages for deletion..."), ctx->deleted); + mutt_message (tmp); + imap_make_sequence (seq, sizeof (seq)); + snprintf (tmp, sizeof (tmp), "%s STORE %s +FLAGS.SILENT (\\Deleted)\r\n", + seq, buf); + if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, tmp, 0) != 0) + /* continue, let regular store try before giving up */ + dprint(2, (debugfile, "imap_sync_mailbox: fast delete failed\n")); + } + } /* save status changes */ for (n = 0; n < ctx->msgcount; n++) @@ -1337,7 +1400,20 @@ int imap_sync_mailbox (CONTEXT *ctx, int expunge) if (expunge == 1) { - if (mutt_bit_isset(CTX_DATA->rights, IMAP_ACL_DELETE)) + /* expunge is implicit if closing */ + if (ctx->closing) + { + mutt_message _("Closing mailbox..."); + imap_make_sequence (seq, sizeof (seq)); + snprintf (buf, sizeof (buf), "%s CLOSE\r\n", seq); + if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0) + { + imap_error ("imap_sync_mailbox()", buf); + return -1; + } + CTX_DATA->state = IMAP_AUTHENTICATED; + } + else if (mutt_bit_isset(CTX_DATA->rights, IMAP_ACL_DELETE)) { mutt_message _("Expunging messages from server..."); CTX_DATA->status = IMAP_EXPUNGE; @@ -1346,7 +1422,7 @@ int imap_sync_mailbox (CONTEXT *ctx, int expunge) if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0) { imap_error ("imap_sync_mailbox()", buf); - return (-1); + return -1; } CTX_DATA->status = 0; } @@ -1387,7 +1463,8 @@ void imap_fastclose_mailbox (CONTEXT *ctx) safe_free ((void **) &CTX_DATA->cache[i].path); } } - if (CTX_DATA->status == IMAP_BYE || CTX_DATA->status == IMAP_FATAL) + if (CTX_DATA->status == IMAP_BYE || CTX_DATA->status == IMAP_FATAL || + CTX_DATA->status == IMAP_LOGOUT) { imap_close_connection (ctx); CTX_DATA->conn->data = NULL; diff --git a/imap/imap.h b/imap/imap.h index 52e71ada..15395f01 100644 --- a/imap/imap.h +++ b/imap/imap.h @@ -23,11 +23,13 @@ #include "mailbox.h" int imap_check_mailbox (CONTEXT *ctx, int *index_hint); +int imap_close_connection (CONTEXT *ctx); int imap_open_mailbox (CONTEXT *ctx); int imap_open_mailbox_append (CONTEXT *ctx); int imap_parse_path (char *path, char *host, size_t hlen, int *port, char **mbox); int imap_select_mailbox (CONTEXT *ctx, const char* path); +void imap_set_logout (CONTEXT *ctx); int imap_sync_mailbox (CONTEXT *ctx, int expunge); void imap_fastclose_mailbox (CONTEXT *ctx); int imap_buffy_check (char *path); diff --git a/imap/imap_private.h b/imap/imap_private.h index 3fcfbc0d..618f9d4b 100644 --- a/imap/imap_private.h +++ b/imap/imap_private.h @@ -37,7 +37,8 @@ enum IMAP_EXPUNGE, IMAP_BYE, IMAP_OK_FAIL, - IMAP_REOPENED + IMAP_REOPENED, + IMAP_LOGOUT }; enum diff --git a/mx.c b/mx.c index b1ec0fd2..056a13dd 100644 --- a/mx.c +++ b/mx.c @@ -868,37 +868,37 @@ int mx_close_mailbox (CONTEXT *ctx) { if (imap_sync_mailbox (ctx, purge) == -1) return -1; + if (ctx->magic == M_IMAP && !purge) + mutt_message (_("%d kept."), ctx->msgcount); } + else #endif - if (!purge) { - for (i = 0; i < ctx->msgcount; i++) - ctx->hdrs[i]->deleted = 0; - ctx->deleted = 0; - } + if (!purge) + { + for (i = 0; i < ctx->msgcount; i++) + ctx->hdrs[i]->deleted = 0; + ctx->deleted = 0; + } - if (ctx->changed || ctx->deleted) - { - if (sync_mailbox (ctx) == -1) - return (-1); - } + if (ctx->changed || ctx->deleted) + { + if (sync_mailbox (ctx) == -1) + return -1; + } -#ifdef USE_IMAP - if (ctx->magic == M_IMAP && !purge) - mutt_message (_("%d kept."), ctx->msgcount); - else -#endif - if (move_messages) - mutt_message (_("%d kept, %d moved, %d deleted."), - ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted); - else - mutt_message (_("%d kept, %d deleted."), - ctx->msgcount - ctx->deleted, ctx->deleted); + if (move_messages) + mutt_message (_("%d kept, %d moved, %d deleted."), + ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted); + else + mutt_message (_("%d kept, %d deleted."), + ctx->msgcount - ctx->deleted, ctx->deleted); - if (ctx->msgcount == ctx->deleted && - (ctx->magic == M_MMDF || ctx->magic == M_MBOX) && - !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) - mx_unlink_empty (ctx->path); + if (ctx->msgcount == ctx->deleted && + (ctx->magic == M_MMDF || ctx->magic == M_MBOX) && + !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) + mx_unlink_empty (ctx->path); + } mx_fastclose_mailbox (ctx); -- 2.40.0