summaryrefslogtreecommitdiffstats
path: root/imap
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>2000-07-28 08:52:36 +0000
committerThomas Roessler <roessler@does-not-exist.org>2000-07-28 08:52:36 +0000
commit8b8dc628b8e3ea057673e18035fe65b5478a5f22 (patch)
tree9487ab97a6f5e35c7a689c0702315faf2f46d1f3 /imap
parent841f1ff54e3c58ee63aadc6999145dd6d7ddf696 (diff)
Handle expunged messages. From Brendan Cully.
Diffstat (limited to 'imap')
-rw-r--r--imap/command.c48
-rw-r--r--imap/imap.c57
-rw-r--r--imap/imap_private.h8
-rw-r--r--imap/message.c13
-rw-r--r--imap/message.h7
5 files changed, 96 insertions, 37 deletions
diff --git a/imap/command.c b/imap/command.c
index c71d9841..12bacce2 100644
--- a/imap/command.c
+++ b/imap/command.c
@@ -23,6 +23,7 @@
#include "mutt.h"
#include "imap_private.h"
+#include "message.h"
#include "mx.h"
#include <ctype.h>
@@ -30,7 +31,8 @@
/* forward declarations */
static void cmd_make_sequence (char* buf, size_t buflen);
-static void cmd_parse_capabilities (IMAP_DATA *idata, char *s);
+static void cmd_parse_capabilities (IMAP_DATA* idata, char* s);
+static void cmd_parse_expunge (IMAP_DATA* idata, char* s);
static void cmd_parse_myrights (IMAP_DATA* idata, char* s);
static char *Capabilities[] = {"IMAP4", "IMAP4rev1", "STATUS", "ACL",
@@ -71,7 +73,6 @@ void imap_cmd_finish (IMAP_DATA* idata)
}
if ((idata->status == IMAP_NEW_MAIL ||
- idata->status == IMAP_EXPUNGE ||
(idata->reopen & (IMAP_REOPEN_PENDING|IMAP_NEWMAIL_PENDING)))
&& (idata->reopen & IMAP_REOPEN_ALLOW))
{
@@ -90,7 +91,7 @@ void imap_cmd_finish (IMAP_DATA* idata)
}
else
{
- imap_reopen_mailbox (idata->ctx, NULL);
+ imap_expunge_mailbox (idata);
idata->check_status = IMAP_REOPENED;
idata->reopen &= ~(IMAP_REOPEN_PENDING|IMAP_NEWMAIL_PENDING);
}
@@ -100,9 +101,6 @@ void imap_cmd_finish (IMAP_DATA* idata)
{
if (idata->status == IMAP_NEW_MAIL)
idata->reopen |= IMAP_NEWMAIL_PENDING;
-
- if (idata->status == IMAP_EXPUNGE)
- idata->reopen |= IMAP_REOPEN_PENDING;
}
idata->status = 0;
@@ -196,7 +194,8 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s)
/* new mail arrived */
count = atoi (pn);
- if ( (idata->status != IMAP_EXPUNGE) && count < idata->ctx->msgcount)
+ if ( !(idata->reopen & IMAP_REOPEN_PENDING) &&
+ count < idata->ctx->msgcount)
{
/* something is wrong because the server reported fewer messages
* than we previously saw
@@ -213,7 +212,7 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s)
"imap_handle_untagged: superfluous EXISTS message.\n"));
else
{
- if (idata->status != IMAP_EXPUNGE)
+ if (!(idata->reopen & IMAP_REOPEN_PENDING))
{
dprint (2, (debugfile,
"imap_handle_untagged: New mail in %s - %d messages total.\n",
@@ -224,7 +223,8 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s)
}
}
else if (mutt_strncasecmp ("EXPUNGE", s, 7) == 0)
- idata->status = IMAP_EXPUNGE;
+ /* pn vs. s: need initial seqno */
+ cmd_parse_expunge (idata, pn);
}
else if (mutt_strncasecmp ("CAPABILITY", s, 10) == 0)
cmd_parse_capabilities (idata, s);
@@ -248,7 +248,7 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s)
{
/* Display the warning message from the server */
mutt_error ("%s", s+3);
- sleep (1);
+ sleep (2);
}
else
dprint (1, (debugfile, "imap_handle_untagged(): unhandled request: %s\n",
@@ -270,7 +270,7 @@ static void cmd_make_sequence (char* buf, size_t buflen)
/* cmd_parse_capabilities: set capability bits according to CAPABILITY
* response */
-static void cmd_parse_capabilities (IMAP_DATA *idata, char *s)
+static void cmd_parse_capabilities (IMAP_DATA* idata, char* s)
{
int x;
@@ -286,6 +286,32 @@ static void cmd_parse_capabilities (IMAP_DATA *idata, char *s)
}
}
+/* cmd_parse_expunge: mark headers with new sequence ID and mark idata to
+ * be reopened at our earliest convenience */
+static void cmd_parse_expunge (IMAP_DATA* idata, char* s)
+{
+ int expno, cur;
+ HEADER* h;
+
+ expno = atoi (s);
+
+ /* walk headers, zero seqno of expunged message, decrement seqno of those
+ * above. Possibly we could avoid walking the whole list by resorting
+ * and guessing a good starting point, but I'm guessing the resort would
+ * nullify the gains */
+ for (cur = 0; cur < idata->ctx->msgcount; cur++)
+ {
+ h = idata->ctx->hdrs[cur];
+
+ if (HEADER_DATA (h)->sid == expno)
+ HEADER_DATA (h)->sid = 0;
+ else if (HEADER_DATA (h)->sid > expno)
+ HEADER_DATA (h)->sid--;
+ }
+
+ idata->reopen |= IMAP_REOPEN_PENDING;
+}
+
/* cmd_parse_myrights: set rights bits according to MYRIGHTS response */
static void cmd_parse_myrights (IMAP_DATA* idata, char* s)
{
diff --git a/imap/imap.c b/imap/imap.c
index 3ffeb945..7f9738cc 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -27,6 +27,7 @@
#include "globals.h"
#include "sort.h"
#include "browser.h"
+#include "message.h"
#include "imap_private.h"
#include <unistd.h>
@@ -186,6 +187,40 @@ int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes)
return 0;
}
+/* imap_expunge_mailbox: Purge IMAP portion of expunged messages from the
+ * context. Must not be done while something has a handle on any headers
+ * (eg inside pager or editor). mx_update_tables and mutt_sort_headers
+ * must be called afterwards. */
+void imap_expunge_mailbox (IMAP_DATA* idata)
+{
+ HEADER* h;
+ int i, cacheno;
+
+ for (i = 0; i < idata->ctx->msgcount; i++)
+ {
+ h = idata->ctx->hdrs[i];
+
+ if (!HEADER_DATA(h)->sid)
+ {
+ dprint (2, (debugfile, "Expunging message UID %d.\n", HEADER_DATA (h)->uid));
+
+ h->active = 0;
+
+ /* free cached body from disk, if neccessary */
+ cacheno = HEADER_DATA(h)->uid % IMAP_CACHE_LEN;
+ if (idata->cache[cacheno].uid == HEADER_DATA(h)->uid &&
+ idata->cache[cacheno].path)
+ {
+ unlink (idata->cache[cacheno].path);
+ FREE (&idata->cache[cacheno].path);
+ }
+
+ imap_free_header_data (&h->data);
+ }
+ }
+}
+
+#if 0
/* imap_reopen_mailbox: Reopen an imap mailbox. This is used when the
* server sends an EXPUNGE message, indicating that some messages may have
* been deleted. This is a heavy handed approach, as it reparses all of the
@@ -193,9 +228,10 @@ int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes)
* something to actually only remove the messages that are marked
* EXPUNGE.
*/
-int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
+int imap_reopen_mailbox (IMAP_DATA* idata)
{
HEADER **old_hdrs;
+ CONTEXT* ctx;
int old_msgcount;
char buf[LONG_STRING];
char bufout[LONG_STRING];
@@ -206,6 +242,8 @@ int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
int i, j;
int index_hint_set;
+ ctx = idata->ctx;
+
ctx->quiet = 1;
if (Sort != SORT_ORDER)
@@ -304,7 +342,7 @@ int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
ctx->msgcount = 0;
count = imap_read_headers (ctx, 0, count - 1) + 1;
- index_hint_set = (index_hint == NULL);
+ index_hint_set = 1;
if (!ctx->readonly)
{
@@ -343,8 +381,10 @@ int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
if (found)
{
/* this is best done here */
+/*
if (!index_hint_set && *index_hint == j)
*index_hint = i;
+*/
if (old_hdrs[j]->changed)
{
@@ -382,6 +422,7 @@ int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint)
return 0;
}
+#endif
static int imap_get_delim (IMAP_DATA *idata)
{
@@ -1095,23 +1136,11 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
mutt_bit_isset(idata->rights, IMAP_ACL_DELETE))
{
mutt_message _("Expunging messages from server...");
- /* FIXME: these status changes seem dubious */
- idata->status = IMAP_EXPUNGE;
if (imap_exec (buf, sizeof (buf), CTX_DATA, "EXPUNGE", 0) != 0)
{
imap_error ("imap_sync_mailbox: EXPUNGE failed", buf);
return -1;
}
- idata->status = 0;
- }
-
- for (n = 0; n < IMAP_CACHE_LEN; n++)
- {
- if (CTX_DATA->cache[n].path)
- {
- unlink (CTX_DATA->cache[n].path);
- safe_free ((void **) &CTX_DATA->cache[n].path);
- }
}
return 0;
diff --git a/imap/imap_private.h b/imap/imap_private.h
index 35545ce3..9aa65605 100644
--- a/imap/imap_private.h
+++ b/imap/imap_private.h
@@ -49,7 +49,6 @@ enum
{
IMAP_FATAL = 1,
IMAP_NEW_MAIL,
- IMAP_EXPUNGE,
IMAP_BYE,
IMAP_REOPENED
};
@@ -122,8 +121,8 @@ enum
/* -- data structures -- */
typedef struct
{
- unsigned int index;
- char *path;
+ unsigned int uid;
+ char* path;
} IMAP_CACHE;
typedef struct
@@ -175,7 +174,8 @@ time_t imap_parse_date (char* s);
int imap_parse_list_response(IMAP_DATA* idata, char* buf, int buflen,
char** name, int* noselect, int* noinferiors, char* delim);
int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes);
-int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint);
+void imap_expunge_mailbox (IMAP_DATA* idata);
+int imap_reopen_mailbox (IMAP_DATA* idata);
void imap_logout (IMAP_DATA* idata);
/* auth.c */
diff --git a/imap/message.c b/imap/message.c
index 954a1d67..3c798ac7 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -141,6 +141,9 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
ctx->hdrs[ctx->msgcount] = mutt_new_header ();
ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
+ /* messages which have not been expunged are ACTIVE (borrowed from
+ * mh folders) */
+ ctx->hdrs[msgno]->active = 1;
ctx->hdrs[msgno]->read = h->read;
ctx->hdrs[msgno]->old = h->old;
ctx->hdrs[msgno]->deleted = h->deleted;
@@ -189,14 +192,16 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
char *pc;
long bytes;
int uid;
+ int cacheno;
IMAP_CACHE *cache;
/* see if we already have the message in our cache */
- cache = &CTX_DATA->cache[ctx->hdrs[msgno]->index % IMAP_CACHE_LEN];
+ cacheno = HEADER_DATA(ctx->hdrs[msgno])->uid % IMAP_CACHE_LEN;
+ cache = &CTX_DATA->cache[cacheno];
if (cache->path)
{
- if (cache->index == ctx->hdrs[msgno]->index)
+ if (cache->uid == HEADER_DATA(ctx->hdrs[msgno])->uid)
{
/* yes, so just return a pointer to the message */
if (!(msg->fp = fopen (cache->path, "r")))
@@ -216,7 +221,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
mutt_message _("Fetching message...");
- cache->index = ctx->hdrs[msgno]->index;
+ cache->uid = HEADER_DATA(ctx->hdrs[msgno])->uid;
mutt_mktemp (path);
cache->path = safe_strdup (path);
if (!(msg->fp = safe_fopen (path, "w+")))
@@ -628,7 +633,7 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp)
/* skip to message number */
buf = imap_next_word (buf);
- h->number = atoi (buf);
+ h->data->sid = atoi (buf);
/* find FETCH tag */
buf = imap_next_word (buf);
diff --git a/imap/message.h b/imap/message.h
index ea4d1424..af7ebd7f 100644
--- a/imap/message.h
+++ b/imap/message.h
@@ -26,12 +26,11 @@
/* IMAP-specific header data, stored as HEADER->data */
typedef struct imap_header_data
{
+ unsigned int sid; /* server message sequence number */
unsigned int uid; /* 32-bit Message UID */
LIST *keywords;
} IMAP_HEADER_DATA;
-/* Linked list to hold header information while downloading message
- * headers */
typedef struct
{
unsigned int read : 1;
@@ -42,7 +41,6 @@ typedef struct
unsigned int changed : 1;
IMAP_HEADER_DATA* data;
- unsigned int number;
time_t received;
long content_length;
@@ -50,4 +48,5 @@ typedef struct
/* -- macros -- */
#define HEADER_DATA(ph) ((IMAP_HEADER_DATA*) ((ph)->data))
-#endif
+
+#endif /* MESSAGE_H */