summaryrefslogtreecommitdiffstats
path: root/imap
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1999-09-06 09:16:50 +0000
committerThomas Roessler <roessler@does-not-exist.org>1999-09-06 09:16:50 +0000
commit54451b0ecb298233b8587273e5dad5b21b08749a (patch)
tree2a826c3b68bbbaee5a9b87b77e871479973cb465 /imap
parent48955dc7307aa3d8d54fa6043f4dc33b7d5b694d (diff)
* Small imap/Makefile.am tweak for make dist
* Hold on to mailbox flags, message flags, do update in one pass instead of two, halving traffic on mailbox sync. * Update message flags at fetch as well as header download, if the server thinks they've changed. Saves some unneeded updates on sync. * Move some structures out of imap_private.h into message.h, since they are local now. (From: Brendan Cully <brendan@kublai.com>)
Diffstat (limited to 'imap')
-rw-r--r--imap/Makefile.am4
-rw-r--r--imap/TODO26
-rw-r--r--imap/imap.c203
-rw-r--r--imap/imap.h6
-rw-r--r--imap/imap_private.h19
-rw-r--r--imap/message.c304
-rw-r--r--imap/message.h50
7 files changed, 426 insertions, 186 deletions
diff --git a/imap/Makefile.am b/imap/Makefile.am
index f4744300..33eca53e 100644
--- a/imap/Makefile.am
+++ b/imap/Makefile.am
@@ -2,8 +2,10 @@
AUTOMAKE_OPTIONS = foreign
+EXTRA_DIST = BUGS TODO
+
noinst_LIBRARIES = libimap.a
-noinst_HEADERS = imap_private.h imap_socket.h md5.h
+noinst_HEADERS = imap_private.h imap_socket.h md5.h message.h
libimap_a_SOURCES = imap.c imap.h auth.c browse.c md5c.c socket.c \
message.c
diff --git a/imap/TODO b/imap/TODO
index 1a0094ea..340071d7 100644
--- a/imap/TODO
+++ b/imap/TODO
@@ -1,5 +1,6 @@
IMAP enhancements/fixes, by priority:
+[ -- socket -- ]
* Smarter connection code. Mutt should handle dropped connections/routing
problems gracefully. It should be able to transparently reconnect. This
is facilitated by the next item.
@@ -12,19 +13,28 @@ IMAP enhancements/fixes, by priority:
PRIORITY: [***]
-* Optimise message updating. Two flags stores per message should be
- unnecessary. It could be brought to one easily. Better would be to use
- message ranges to store common flags en masse. This is facilitated by the
- next item.
+[ -- browsing -- ]
+* Investigate a new way of displaying folders with subfolders and messages.
+ Possibly we could use a tree-view in the browser, w/ expand, collapse.
+ For low-bandwidth lines we could defer getting subfolder lists until the
+ folder is expanded.
+
+[ -- new features -- ]
+* Implement server message COPY, instead of FETCH/APPEND.
+
+ PRIORITY: [** ]
+
+* Implement the received folder on IMAP. (Wait on COPY).
PRIORITY: [** ]
-* More complete mailbox caching. All the data for a message should be held
- locally so that updates can be done without requerying the server.
+* Commands for creating/deleting folders on the server, since users may not
+ otherwise be able to do this on IMAP servers.
PRIORITY: [** ]
-* Implement server message copy, instead of FETCH/APPEND.
+* Implement READ-ONLY support, and the x (quit without saving changes)
+ command.
PRIORITY: [** ]
@@ -45,4 +55,4 @@ IMAP enhancements/fixes, by priority:
PRIORITY: [* ]
Brendan Cully <brendan@kublai.com>
-Updated: 19990826
+Updated: 19990904
diff --git a/imap/imap.c b/imap/imap.c
index e4dcaacc..ea66c688 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -49,6 +49,8 @@ static int imap_wordcasecmp(const char *a, const char *b);
static void imap_parse_capabilities (IMAP_DATA *idata, char *s);
static int imap_reopen_mailbox (CONTEXT *ctx, int *index_hint);
static int imap_get_delim (IMAP_DATA *idata, CONNECTION *conn);
+static char* imap_get_flags (LIST** hflags, char* s);
+static int imap_has_flag (LIST* flag_list, const char* flag);
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);
@@ -869,6 +871,60 @@ int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn)
return 0;
}
+/* imap_get_flags: Make a simple list out of a FLAGS response.
+ * return stream following FLAGS response */
+static char* imap_get_flags (LIST** hflags, char* s)
+{
+ LIST* flags;
+ char* flag_word;
+ char ctmp;
+
+ /* sanity-check string */
+ if (mutt_strncasecmp ("FLAGS", s, 5) != 0)
+ {
+ dprint (1, (debugfile, "imap_get_flags: not a FLAGS response: %s\n",
+ s));
+ return NULL;
+ }
+ s += 5;
+ SKIPWS(s);
+ if (*s != '(')
+ {
+ dprint (1, (debugfile, "imap_get_flags: bogus FLAGS response: %s\n",
+ s));
+ return NULL;
+ }
+
+ /* create list, update caller's flags handle */
+ flags = mutt_new_list();
+ *hflags = flags;
+
+ while (*s && *s != ')')
+ {
+ s++;
+ SKIPWS(s);
+ flag_word = s;
+ while (*s && (*s != ')') && !ISSPACE (*s))
+ s++;
+ ctmp = *s;
+ *s = '\0';
+ mutt_add_list (flags, flag_word);
+ *s = ctmp;
+ }
+
+ /* note bad flags response */
+ if (*s != ')')
+ {
+ dprint (1, (debugfile,
+ "imap_get_flags: Unterminated FLAGS response: %s\n", s));
+ return NULL;
+ }
+
+ s++;
+
+ return s;
+}
+
int imap_open_mailbox (CONTEXT *ctx)
{
CONNECTION *conn;
@@ -940,18 +996,63 @@ int imap_open_mailbox (CONTEXT *ctx)
while (*pc && isdigit (*pc))
pc++;
- *pc++ = 0;
+ *pc++ = '\0';
n = atoi (pn);
SKIPWS (pc);
if (mutt_strncasecmp ("EXISTS", pc, 6) == 0)
count = n;
}
+ /* Obtain list of available flags here, may be overridden by a
+ * PERMANENTFLAGS tag in the OK response */
+ else if (mutt_strncasecmp ("FLAGS", pc, 5) == 0)
+ {
+ /* don't override PERMANENTFLAGS */
+ if (!idata->mailbox_flags)
+ {
+ dprint (2, (debugfile, "Getting mailbox FLAGS\n"));
+ if ((pc = imap_get_flags (&(idata->mailbox_flags), pc)) == NULL)
+ return -1;
+ }
+ }
+ /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
+ else if (mutt_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0)
+ {
+ dprint (2, (debugfile,
+ "Getting mailbox PERMANENTFLAGS\n"));
+ /* safe to call on NULL */
+ mutt_free_list (&(idata->mailbox_flags));
+ /* skip "OK [PERMANENT" so syntax is the same as FLAGS */
+ pc += 13;
+ if ((pc = imap_get_flags (&(idata->mailbox_flags), pc)) == NULL)
+ return -1;
+ }
else if (imap_handle_untagged (idata, buf) != 0)
return (-1);
}
}
while (mutt_strncmp (seq, buf, mutt_strlen (seq)) != 0);
+ /* dump the mailbox flags we've found */
+ if (debuglevel > 2)
+ {
+ if (!idata->mailbox_flags)
+ dprint (3, (debugfile, "No folder flags found\n"));
+ else
+ {
+ LIST* t = idata->mailbox_flags;
+
+ dprint (3, (debugfile, "Mailbox flags: "));
+
+ t = t->next;
+ while (t)
+ {
+ dprint (3, (debugfile, "[%s] ", t->data));
+ t = t->next;
+ }
+ dprint (3, (debugfile, "\n"));
+ }
+ }
+
if (!imap_code (buf))
{
char *s;
@@ -1160,18 +1261,52 @@ int imap_close_connection (CONTEXT *ctx)
return 0;
}
-static void _imap_set_flag (CONTEXT *ctx, int aclbit, int flag, const char *str,
- char *sf, char *uf)
+/* imap_has_flag: do a caseless comparison of the flag against a flag list,
+ * return 1 if found or flag list has '\*', 0 otherwise */
+static int imap_has_flag (LIST* flag_list, const char* flag)
{
- if (mutt_bit_isset (CTX_DATA->rights, aclbit))
+ if (!flag_list)
+ return 0;
+
+ flag_list = flag_list->next;
+ while (flag_list)
{
- if (flag)
- strcat (sf, str);
- else
- strcat (uf, str);
+ if (!mutt_strncasecmp (flag_list->data, flag, strlen (flag_list->data)))
+ return 1;
+
+ flag_list = flag_list->next;
+ }
+
+ return 0;
+}
+
+/* imap_stringify_flaglist: concatenate custom IMAP tags to list, if they
+ * appear in the folder flags list. Why wouldn't they? */
+static void imap_stringify_flaglist (LIST* flags, LIST* mailbox_flags, char *s)
+{
+ if (!mailbox_flags || !flags)
+ return;
+
+ flags = flags->next;
+ while (flags)
+ {
+ if (imap_has_flag (mailbox_flags, flags->data))
+ {
+ strcat (s, flags->data);
+ strcat (s, " ");
+ }
+ flags = flags->next;
}
}
+static void imap_set_flag (CONTEXT *ctx, int aclbit, int flag, const char *str,
+ char *flags)
+{
+ if (mutt_bit_isset (CTX_DATA->rights, aclbit))
+ if (flag)
+ strcat (flags, str);
+}
+
/* update the IMAP server to reflect message changes done within mutt.
* Arguments
* ctx: the current context
@@ -1180,8 +1315,7 @@ int imap_sync_mailbox (CONTEXT *ctx, int expunge)
{
char seq[8];
char buf[LONG_STRING];
- char set_flags[LONG_STRING];
- char unset_flags[LONG_STRING];
+ char flags[LONG_STRING];
int n;
/* save status changes */
@@ -1193,39 +1327,30 @@ int imap_sync_mailbox (CONTEXT *ctx, int expunge)
n+1, ctx->msgcount);
mutt_message (buf);
- *set_flags = '\0';
- *unset_flags = '\0';
+ flags[0] = '\0';
- _imap_set_flag (ctx, IMAP_ACL_SEEN, ctx->hdrs[n]->read, "\\Seen ", set_flags, unset_flags);
- _imap_set_flag (ctx, IMAP_ACL_WRITE, ctx->hdrs[n]->flagged, "\\Flagged ", set_flags, unset_flags);
- _imap_set_flag (ctx, IMAP_ACL_WRITE, ctx->hdrs[n]->replied, "\\Answered ", set_flags, unset_flags);
- _imap_set_flag (ctx, IMAP_ACL_DELETE, ctx->hdrs[n]->deleted, "\\Deleted", set_flags, unset_flags);
+ imap_set_flag (ctx, IMAP_ACL_SEEN, ctx->hdrs[n]->read, "\\Seen ",
+ flags);
+ imap_set_flag (ctx, IMAP_ACL_WRITE, ctx->hdrs[n]->flagged, "\\Flagged ",
+ flags);
+ imap_set_flag (ctx, IMAP_ACL_WRITE, ctx->hdrs[n]->replied,
+ "\\Answered ", flags);
+ imap_set_flag (ctx, IMAP_ACL_DELETE, ctx->hdrs[n]->deleted, "\\Deleted ",
+ flags);
+
+ /* now make sure we don't lose custom tags */
+ imap_stringify_flaglist (ctx->hdrs[n]->server_flags,
+ CTX_DATA->mailbox_flags, flags);
- mutt_remove_trailing_ws (set_flags);
- mutt_remove_trailing_ws (unset_flags);
+ mutt_remove_trailing_ws (flags);
- if (*set_flags)
- {
- imap_make_sequence (seq, sizeof (seq));
- snprintf (buf, sizeof (buf), "%s STORE %d +FLAGS.SILENT (%s)\r\n", seq,
- ctx->hdrs[n]->index + 1, set_flags);
- if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
- {
- imap_error ("imap_sync_mailbox()", buf);
- return (-1);
- }
- }
-
- if (*unset_flags)
+ imap_make_sequence (seq, sizeof (seq));
+ snprintf (buf, sizeof (buf), "%s STORE %d FLAGS.SILENT (%s)\r\n", seq,
+ ctx->hdrs[n]->index + 1, NONULL(flags));
+ if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
{
- imap_make_sequence (seq, sizeof (seq));
- snprintf (buf, sizeof (buf), "%s STORE %d -FLAGS.SILENT (%s)\r\n", seq,
- ctx->hdrs[n]->index + 1, unset_flags);
- if (imap_exec (buf, sizeof (buf), CTX_DATA, seq, buf, 0) != 0)
- {
- imap_error ("imap_sync_mailbox()", buf);
- return (-1);
- }
+ imap_error ("imap_sync_mailbox()", buf);
+ return (-1);
}
}
}
diff --git a/imap/imap.h b/imap/imap.h
index 88410492..52e71ada 100644
--- a/imap/imap.h
+++ b/imap/imap.h
@@ -22,9 +22,7 @@
#include "browser.h"
#include "mailbox.h"
-int imap_append_message (CONTEXT *ctx, MESSAGE *msg);
int imap_check_mailbox (CONTEXT *ctx, int *index_hint);
-int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno);
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,
@@ -40,4 +38,8 @@ int imap_complete (char* dest, size_t dlen, char* path);
void imap_qualify_path (char* dest, size_t len, const char* host, int port,
const char* path, const char* name);
+/* message.c */
+int imap_append_message (CONTEXT *ctx, MESSAGE *msg);
+int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno);
+
#endif
diff --git a/imap/imap_private.h b/imap/imap_private.h
index 1dd8ba4b..6b10bcbc 100644
--- a/imap/imap_private.h
+++ b/imap/imap_private.h
@@ -119,24 +119,6 @@ typedef struct
int noinferiors;
} IMAP_NAMESPACE_INFO;
-/* Linked list to hold header information while downloading message
- * headers
- */
-typedef struct imap_header_info
-{
- unsigned int read : 1;
- unsigned int old : 1;
- unsigned int deleted : 1;
- unsigned int flagged : 1;
- unsigned int replied : 1;
- unsigned int changed : 1;
- unsigned int number;
-
- time_t received;
- long content_length;
- struct imap_header_info *next;
-} IMAP_HEADER_INFO;
-
typedef struct
{
/* This data is specific to a CONNECTION to an IMAP server */
@@ -153,6 +135,7 @@ typedef struct
unsigned char rights[(RIGHTSMAX + 7)/8];
unsigned int newMailCount;
IMAP_CACHE cache[IMAP_CACHE_LEN];
+ LIST *mailbox_flags;
} IMAP_DATA;
/* -- macros -- */
diff --git a/imap/message.c b/imap/message.c
index 1d0d9959..5789d5da 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -25,6 +25,7 @@
#include "mutt.h"
#include "imap.h"
#include "imap_private.h"
+#include "message.h"
#include "mx.h"
#ifdef _PGPPATH
@@ -32,7 +33,8 @@
#endif
static void flush_buffer(char *buf, size_t *len, CONNECTION *conn);
-static int parse_fetch (IMAP_HEADER_INFO *h, char *s);
+static int msg_parse_fetch (IMAP_HEADER_INFO *h, char *s);
+static char* msg_parse_flags (IMAP_FLAGS* flags, char* s);
/* imap_read_headers:
* Changed to read many headers instead of just one. It will return the
@@ -66,8 +68,8 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
return (-1);
}
- h0=safe_malloc(sizeof(IMAP_HEADER_INFO));
- h=h0;
+ h0 = (IMAP_HEADER_INFO*) safe_malloc(sizeof(IMAP_HEADER_INFO));
+ h = h0;
for (msgno=msgbegin; msgno <= msgend ; msgno++)
{
snprintf (buf, sizeof (buf), _("Fetching message headers... [%d/%d]"),
@@ -168,7 +170,7 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
while ((msgno + 1) >= fetchlast && mutt_strncmp (seq, buf, SEQLEN) != 0);
h->content_length = -bytes;
- if (parse_fetch (h, fetchbuf) == -1)
+ if (msg_parse_fetch (h, fetchbuf) == -1)
return (-1);
/* subtract the header length; the total message size will be
@@ -202,20 +204,21 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend)
ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], 0);
ploc=ftell(fp);
- ctx->hdrs[msgno]->read = h->read;
- ctx->hdrs[msgno]->old = h->old;
- ctx->hdrs[msgno]->deleted = h->deleted;
- ctx->hdrs[msgno]->flagged = h->flagged;
- ctx->hdrs[msgno]->replied = h->replied;
- ctx->hdrs[msgno]->changed = h->changed;
+ ctx->hdrs[msgno]->read = h->flags.read;
+ ctx->hdrs[msgno]->old = h->flags.old;
+ ctx->hdrs[msgno]->deleted = h->flags.deleted;
+ ctx->hdrs[msgno]->flagged = h->flags.flagged;
+ ctx->hdrs[msgno]->replied = h->flags.replied;
+ ctx->hdrs[msgno]->changed = h->flags.changed;
+ ctx->hdrs[msgno]->server_flags = h->flags.server_flags;
ctx->hdrs[msgno]->received = h->received;
ctx->hdrs[msgno]->content->length = h->content_length;
- mx_update_context(ctx); /* increments ->msgcount */
+ mx_update_context (ctx); /* increments ->msgcount */
htemp=h;
h=h->next;
- safe_free((void **) &htemp);
+ safe_free ((void **) &htemp);
}
fclose(fp);
unlink(tempfile);
@@ -314,6 +317,37 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
}
pc = buf;
}
+ /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
+ * change (eg from \Unseen to \Seen) */
+ else if (strncasecmp ("FLAGS", pc, 5) == 0)
+ {
+ IMAP_FLAGS flags;
+ HEADER* h = ctx->hdrs[msgno];
+
+ flags.server_flags = NULL;
+
+ dprint (2, (debugfile, "imap_fetch_message: parsing FLAGS\n"));
+ if ((pc = msg_parse_flags (&flags, pc)) == NULL)
+ return -1;
+
+ /* update context sums */
+ ctx->new += ((flags.read | flags.old) ? 0 : 1) -
+ ((h->read | h->old) ? 0 : 1);
+ ctx->unread += h->read - flags.read;
+ ctx->deleted += h->deleted = flags.deleted;
+ ctx->flagged += h->flagged - flags.flagged;
+
+ /* now commit the new flags */
+ ctx->hdrs[msgno]->read = flags.read;
+ ctx->hdrs[msgno]->old = flags.old;
+ ctx->hdrs[msgno]->deleted = flags.deleted;
+ ctx->hdrs[msgno]->flagged = flags.flagged;
+ ctx->hdrs[msgno]->replied = flags.replied;
+ ctx->hdrs[msgno]->changed = flags.changed;
+
+ mutt_free_list (&(h->server_flags));
+ h->server_flags = flags.server_flags;
+ }
}
}
else if (imap_handle_untagged (CTX_DATA, buf) != 0)
@@ -471,129 +505,163 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
return 0;
}
-/* parse_fetch: handle headers returned from header fetch */
-static int parse_fetch (IMAP_HEADER_INFO *h, char *s)
+/* msg_parse_fetch: handle headers returned from header fetch */
+static int msg_parse_fetch (IMAP_HEADER_INFO *h, char *s)
{
char tmp[SHORT_STRING];
char *ptmp;
- int state = 0;
- int recent = 0;
if (!s)
return (-1);
- h->old = 0;
-
while (*s)
{
SKIPWS (s);
- switch (state)
+ if (mutt_strncasecmp ("FLAGS", s, 5) == 0)
{
- case 0:
- if (mutt_strncasecmp ("FLAGS", s, 5) == 0)
- {
- s += 5;
- SKIPWS (s);
- if (*s != '(')
- {
- dprint (1, (debugfile, "parse_fetch(): bogus FLAGS entry: %s\n", s));
- return (-1); /* parse error */
- }
- /* we're about to get a new set of headers, so clear the old ones. */
- h->deleted = 0;
- h->flagged = 0;
- h->replied = 0;
- h->read = 0;
- h->old = 0;
- h->changed = 0;
- recent = 0;
- s++;
- state = 1;
- }
- else if (mutt_strncasecmp ("INTERNALDATE", s, 12) == 0)
- {
- s += 12;
- SKIPWS (s);
- if (*s != '\"')
- {
- dprint (1, (debugfile, "parse_fetch(): bogus INTERNALDATE entry: %s\n", s));
- return (-1);
- }
- s++;
- ptmp = tmp;
- while (*s && *s != '\"')
- *ptmp++ = *s++;
- if (*s != '\"')
- return (-1);
- s++; /* skip past the trailing " */
- *ptmp = 0;
- h->received = imap_parse_date (tmp);
- }
- else if (mutt_strncasecmp ("RFC822.SIZE", s, 11) == 0)
- {
- s += 11;
- SKIPWS (s);
- ptmp = tmp;
- while (isdigit (*s))
- *ptmp++ = *s++;
- *ptmp = 0;
- h->content_length += atoi (tmp);
- }
- else if (*s == ')')
- s++; /* end of request */
- else if (*s)
- {
- /* got something i don't understand */
- imap_error ("parse_fetch()", s);
- return (-1);
- }
- break;
- case 1: /* flags */
- if (*s == ')')
- {
- s++;
- /* if a message is neither seen nor recent, it is OLD. */
- if (option (OPTMARKOLD) && !recent && !(h->read))
- h->old = 1;
- state = 0;
- }
- else if (mutt_strncasecmp ("\\deleted", s, 8) == 0)
- {
- s += 8;
- h->deleted = 1;
- }
- else if (mutt_strncasecmp ("\\flagged", s, 8) == 0)
- {
- s += 8;
- h->flagged = 1;
- }
- else if (mutt_strncasecmp ("\\answered", s, 9) == 0)
- {
- s += 9;
- h->replied = 1;
- }
- else if (mutt_strncasecmp ("\\seen", s, 5) == 0)
- {
- s += 5;
- h->read = 1;
- }
- else if (mutt_strncasecmp ("\\recent", s, 5) == 0)
- {
- s += 7;
- recent = 1;
- }
- else
- {
- while (*s && !ISSPACE (*s) && *s != ')')
- s++;
- }
- break;
+ h->flags.server_flags = NULL;
+ if ((s = msg_parse_flags (&(h->flags), s)) == NULL)
+ return -1;
+ }
+ else if (mutt_strncasecmp ("INTERNALDATE", s, 12) == 0)
+ {
+ s += 12;
+ SKIPWS (s);
+ if (*s != '\"')
+ {
+ dprint (1, (debugfile, "msg_parse_fetch(): bogus INTERNALDATE entry: %s\n", s));
+ return -1;
+ }
+ s++;
+ ptmp = tmp;
+ while (*s && *s != '\"')
+ *ptmp++ = *s++;
+ if (*s != '\"')
+ return -1;
+ s++; /* skip past the trailing " */
+ *ptmp = 0;
+ h->received = imap_parse_date (tmp);
+ }
+ else if (mutt_strncasecmp ("RFC822.SIZE", s, 11) == 0)
+ {
+ s += 11;
+ SKIPWS (s);
+ ptmp = tmp;
+ while (isdigit (*s))
+ *ptmp++ = *s++;
+ *ptmp = 0;
+ h->content_length += atoi (tmp);
+ }
+ else if (*s == ')')
+ s++; /* end of request */
+ else if (*s)
+ {
+ /* got something i don't understand */
+ imap_error ("msg_parse_fetch", s);
+ return (-1);
}
}
+
return 0;
}
+/* msg_parse_flags: fill out the message header according to the flags from the
+ * server. Expects a flags line of the form "FLAGS (flag flag ...)" */
+static char* msg_parse_flags (IMAP_FLAGS* flags, char* s)
+{
+ int recent = 0;
+
+ /* sanity-check string */
+ if (mutt_strncasecmp ("FLAGS", s, 5) != 0)
+ {
+ dprint (1, (debugfile, "msg_parse_flags: not a FLAGS response: %s\n",
+ s));
+ return NULL;
+ }
+ s += 5;
+ SKIPWS(s);
+ if (*s != '(')
+ {
+ dprint (1, (debugfile, "msg_parse_flags: bogus FLAGS response: %s\n",
+ s));
+ return NULL;
+ }
+ s++;
+
+ /* reset the current flags */
+ flags->deleted = 0;
+ flags->flagged = 0;
+ flags->replied = 0;
+ flags->read = 0;
+ flags->old = 0;
+ flags->changed = 0;
+
+ /* start parsing */
+ while (*s && *s != ')')
+ {
+ if (mutt_strncasecmp ("\\deleted", s, 8) == 0)
+ {
+ s += 8;
+ flags->deleted = 1;
+ }
+ else if (mutt_strncasecmp ("\\flagged", s, 8) == 0)
+ {
+ s += 8;
+ flags->flagged = 1;
+ }
+ else if (mutt_strncasecmp ("\\answered", s, 9) == 0)
+ {
+ s += 9;
+ flags->replied = 1;
+ }
+ else if (mutt_strncasecmp ("\\seen", s, 5) == 0)
+ {
+ s += 5;
+ flags->read = 1;
+ }
+ else if (mutt_strncasecmp ("\\recent", s, 5) == 0)
+ {
+ s += 7;
+ recent = 1;
+ }
+ else
+ {
+ /* store custom flags as well */
+ char ctmp;
+ char* flag_word = s;
+
+ if (!flags->server_flags)
+ flags->server_flags = mutt_new_list ();
+
+ while (*s && !ISSPACE (*s) && *s != ')')
+ s++;
+ ctmp = *s;
+ *s = '\0';
+ mutt_add_list (flags->server_flags, flag_word);
+ *s = ctmp;
+ }
+ SKIPWS(s);
+ }
+
+ /* wrap up, or note bad flags response */
+ if (*s == ')')
+ {
+ /* if a message is neither seen nor recent, it is OLD. */
+ if (option (OPTMARKOLD) && !recent && !(flags->read))
+ flags->old = 1;
+ s++;
+ }
+ else
+ {
+ dprint (1, (debugfile,
+ "msg_parse_flags: Unterminated FLAGS response: %s\n", s));
+ return NULL;
+ }
+
+ return s;
+}
+
static void flush_buffer(char *buf, size_t *len, CONNECTION *conn)
{
buf[*len] = '\0';
diff --git a/imap/message.h b/imap/message.h
new file mode 100644
index 00000000..1669d8c6
--- /dev/null
+++ b/imap/message.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
+ * Copyright (C) 1999 Brendan Cully <brendan@kublai.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* message.c data structures */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H 1
+
+/* Data from the FLAGS response */
+typedef struct imap_flags
+{
+ unsigned int read : 1;
+ unsigned int old : 1;
+ unsigned int deleted : 1;
+ unsigned int flagged : 1;
+ unsigned int replied : 1;
+ unsigned int changed : 1;
+
+ LIST* server_flags; /* flags mutt doesn't use, but the server does */
+} IMAP_FLAGS;
+
+/* Linked list to hold header information while downloading message
+ * headers */
+typedef struct imap_header_info
+{
+ IMAP_FLAGS flags;
+ unsigned int number;
+
+ time_t received;
+ long content_length;
+ struct imap_header_info *next;
+} IMAP_HEADER_INFO;
+
+#endif