diff options
author | Thomas Roessler <roessler@does-not-exist.org> | 1999-09-06 09:16:50 +0000 |
---|---|---|
committer | Thomas Roessler <roessler@does-not-exist.org> | 1999-09-06 09:16:50 +0000 |
commit | 54451b0ecb298233b8587273e5dad5b21b08749a (patch) | |
tree | 2a826c3b68bbbaee5a9b87b77e871479973cb465 /imap | |
parent | 48955dc7307aa3d8d54fa6043f4dc33b7d5b694d (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.am | 4 | ||||
-rw-r--r-- | imap/TODO | 26 | ||||
-rw-r--r-- | imap/imap.c | 203 | ||||
-rw-r--r-- | imap/imap.h | 6 | ||||
-rw-r--r-- | imap/imap_private.h | 19 | ||||
-rw-r--r-- | imap/message.c | 304 | ||||
-rw-r--r-- | imap/message.h | 50 |
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 @@ -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 |