Commit f24c25bf authored by Thomas Roessler's avatar Thomas Roessler

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 <brendan@kublai.com>)
parent 491856cb
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -37,7 +37,8 @@ enum
IMAP_EXPUNGE,
IMAP_BYE,
IMAP_OK_FAIL,
IMAP_REOPENED
IMAP_REOPENED,
IMAP_LOGOUT
};
enum
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment