X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=imap%2Fmessage.c;h=62f4b21dd9f65438130c777e569b8f4310d9ab6b;hp=75089b7f23efbd4299d5bc3a14ff8ddf6135ee22;hb=f5a370338d87eba00bc8696636a90f6c50b05d14;hpb=ad29f4688c8a43e718f4cf25ab9337459fc472de diff --git a/imap/message.c b/imap/message.c index 75089b7..62f4b21 100644 --- a/imap/message.c +++ b/imap/message.c @@ -1,49 +1,36 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-9 Brandon Long * Copyright (C) 1999-2002 Brendan Cully - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ /* message parsing/updating functions */ -#include -#include -#include +#include + +#include +#include +#include #include "mutt.h" -#include "mutt_curses.h" #include "imap_private.h" #include "message.h" -#include "mx.h" - -#ifdef HAVE_PGP -#include "pgp.h" -#endif -static void flush_buffer(char* buf, size_t* len, CONNECTION* conn); -static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, - FILE* fp); -static int msg_has_flag (LIST* flag_list, const char* flag); -static int msg_parse_fetch (IMAP_HEADER* h, char* s); -static char* msg_parse_flags (IMAP_HEADER* h, char* s); - -#if USE_HCACHE -static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, - FILE* fp); -static size_t imap_hcache_keylen (const char *fn); +static void flush_buffer (char *buf, size_t * len, CONNECTION * conn); +static int msg_fetch_header (CONTEXT * ctx, IMAP_HEADER * h, char *buf, + FILE * fp); +static int msg_has_flag (string_list_t * flag_list, const char *flag); +static int msg_parse_fetch (IMAP_HEADER * h, char *s); +static char *msg_parse_flags (IMAP_HEADER * h, char *s); + +#ifdef USE_HCACHE +static int msg_fetch_header_fetch (CONTEXT * ctx, IMAP_HEADER * h, char *buf, + FILE * fp); +static ssize_t imap_hcache_keylen (const char *fn); #endif /* USE_HCACHE */ /* imap_read_headers: @@ -51,9 +38,9 @@ static size_t imap_hcache_keylen (const char *fn); * msgno of the last message read. It will return a value other than * msgend if mail comes in while downloading headers (in theory). */ -int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) +int imap_read_headers (IMAP_DATA * idata, int msgbegin, int msgend) { - CONTEXT* ctx; + CONTEXT *ctx; char buf[LONG_STRING]; char hdrreq[STRING]; FILE *fp; @@ -62,53 +49,43 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) IMAP_HEADER h; int rc, mfhrc, oldmsgcount; int fetchlast = 0; - const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE CONTENT-DESCRIPTION IN-REPLY-TO REPLY-TO LINES LIST-POST X-LABEL"; + const char *want_headers = + "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE CONTENT-DESCRIPTION IN-REPLY-TO REPLY-TO LINES LIST-POST X-LABEL"; -#if USE_HCACHE - void *hc = NULL; - uint64_t *uid_validity = NULL; +#ifdef USE_HCACHE + hcache_t *hc = NULL; + long *uid_validity = NULL; char uid_buf[64]; #endif /* USE_HCACHE */ ctx = idata->ctx; -#if USE_HCACHE - hc = mutt_hcache_open (HeaderCache, ctx->path); -#endif /* USE_HCACHE */ - - if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) - { - snprintf (hdrreq, sizeof (hdrreq), "BODY.PEEK[HEADER.FIELDS (%s%s%s)]", - want_headers, ImapHeaders ? " " : "", ImapHeaders ? ImapHeaders : ""); - } - else if (mutt_bit_isset (idata->capabilities,IMAP4)) - { - snprintf (hdrreq, sizeof (hdrreq), "RFC822.HEADER.LINES (%s%s%s)", - want_headers, ImapHeaders ? " " : "", ImapHeaders ? ImapHeaders : ""); + if (mutt_bit_isset (idata->capabilities, IMAP4REV1)) { + snprintf (hdrreq, sizeof (hdrreq), "BODY.PEEK[HEADER.FIELDS (%s%s%s)]", + want_headers, ImapHeaders ? " " : "", + ImapHeaders ? ImapHeaders : ""); } - else - { /* Unable to fetch headers for lower versions */ + else if (mutt_bit_isset (idata->capabilities, IMAP4)) { + snprintf (hdrreq, sizeof (hdrreq), "RFC822.HEADER.LINES (%s%s%s)", + want_headers, ImapHeaders ? " " : "", + ImapHeaders ? ImapHeaders : ""); + } + else { /* Unable to fetch headers for lower versions */ mutt_error _("Unable to fetch headers from this IMAP server version."); - mutt_sleep (2); /* pause a moment to let the user see the error */ -#if USE_HCACHE - mutt_hcache_close (hc); -#endif /* USE_HCACHE */ + + mutt_sleep (2); /* pause a moment to let the user see the error */ return -1; } /* instead of downloading all headers and then parsing them, we parse them * as they come in. */ - mutt_mktemp (tempfile); - if (!(fp = safe_fopen (tempfile, "w+"))) - { - mutt_error (_("Could not create temporary file %s"), tempfile); - mutt_sleep (2); -#if USE_HCACHE - mutt_hcache_close (hc); -#endif /* USE_HCACHE */ + fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(mod_core.tmpdir), NULL); + if (!fp) { + mutt_error(_("Could not create temporary file")); + mutt_sleep(2); return -1; } - unlink (tempfile); + unlink(tempfile); /* make sure context has room to hold the mailbox */ while ((msgend) >= idata->ctx->hdrmax) @@ -118,94 +95,90 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) idata->reopen &= ~IMAP_NEWMAIL_PENDING; idata->newMailCount = 0; -#if USE_HCACHE - snprintf (buf, sizeof (buf), - "FETCH %d:%d (UID FLAGS)", msgbegin + 1, msgend + 1); - fetchlast = msgend + 1; +#ifdef USE_HCACHE + if ((hc = mutt_hcache_open (HeaderCache, ctx->path))) { - imap_cmd_start (idata, buf); + snprintf (buf, sizeof (buf), + "FETCH %d:%d (UID FLAGS)", msgbegin + 1, msgend + 1); + fetchlast = msgend + 1; - for (msgno = msgbegin; msgno <= msgend ; msgno++) - { - if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) - mutt_message (_("Evaluating cache... [%d/%d]"), msgno + 1, - msgend + 1); + imap_cmd_start (idata, buf); - rewind (fp); - memset (&h, 0, sizeof (h)); - h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); - do - { - mfhrc = 0; + for (msgno = msgbegin; msgno <= msgend; msgno++) { + if (ReadInc && (!msgno || ((msgno + 1) % ReadInc == 0))) + mutt_message (_("Evaluating cache... [%d/%d]"), msgno + 1, msgend + 1); - rc = imap_cmd_step (idata); - if (rc != IMAP_CMD_CONTINUE) - break; + rewind (fp); + p_clear(&h, 1); + h.data = p_new(IMAP_HEADER_DATA, 1); + do { + mfhrc = 0; + + rc = imap_cmd_step (idata); + if (rc != IMAP_CMD_CONTINUE) + break; + + if ((mfhrc = + msg_fetch_header_fetch (idata->ctx, &h, idata->cmd.buf.data, fp)) == -1) + continue; + else if (mfhrc < 0) + break; + + /* make sure we don't get remnants from older larger message headers */ + fputs ("\n\n", fp); + + sprintf (uid_buf, "/%u", h.data->uid); /* XXX --tg 21:41 04-07-11 */ + uid_validity = mutt_hcache_fetch (hc, uid_buf, &imap_hcache_keylen); + + if (uid_validity != NULL && *uid_validity == idata->uid_validity) { + ctx->hdrs[msgno] = mutt_hcache_restore(uid_validity, 0); + ctx->hdrs[msgno]->index = h.sid - 1; + /* 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; + ctx->hdrs[msgno]->flagged = h.flagged; + ctx->hdrs[msgno]->replied = h.replied; + ctx->hdrs[msgno]->changed = h.changed; + /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ + ctx->hdrs[msgno]->data = (void *) (h.data); + + ctx->msgcount++; + } - if ((mfhrc = msg_fetch_header_fetch (idata->ctx, &h, idata->cmd.buf, fp)) == -1) - continue; - else if (mfhrc < 0) - break; + rewind (fp); - /* make sure we don't get remnants from older larger message headers */ - fputs ("\n\n", fp); + p_delete(&uid_validity); - sprintf(uid_buf, "/%u", h.data->uid); /* XXX --tg 21:41 04-07-11 */ - uid_validity = (uint64_t *) mutt_hcache_fetch (hc, uid_buf, &imap_hcache_keylen); - - if (uid_validity != NULL - && *uid_validity == idata->uid_validity) { - ctx->hdrs[msgno] = mutt_hcache_restore((unsigned char *) uid_validity, 0); - ctx->hdrs[msgno]->index = h.sid - 1; - if (h.sid != ctx->msgcount + 1) - dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); - /* 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; - ctx->hdrs[msgno]->flagged = h.flagged; - ctx->hdrs[msgno]->replied = h.replied; - ctx->hdrs[msgno]->changed = h.changed; - /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ - ctx->hdrs[msgno]->data = (void *) (h.data); - - ctx->msgcount++; } - rewind (fp); - - FREE(&uid_validity); + while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || + ((msgno + 1) >= fetchlast))); + if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) { + imap_free_header_data((void *)&h.data); + m_fclose(&fp); + mutt_hcache_close (&hc); + return -1; + } } - while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || - ((msgno + 1) >= fetchlast))); - if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) - { - imap_free_header_data ((void**) &h.data); - fclose (fp); - mutt_hcache_close (hc); - return -1; - } + fetchlast = msgbegin; } - - fetchlast = msgbegin; #endif /* USE_HCACHE */ - for (msgno = msgbegin; msgno <= msgend ; msgno++) - { - if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) + for (msgno = msgbegin; msgno <= msgend; msgno++) { + if (ReadInc && (!msgno || ((msgno + 1) % ReadInc == 0))) mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, - msgend + 1); + msgend + 1); if (ctx->hdrs[msgno]) continue; - if (msgno + 1 > fetchlast) - { + if (msgno + 1 > fetchlast) { fetchlast = msgno + 1; - while((fetchlast <= msgend) && (! ctx->hdrs[fetchlast])) + while ((fetchlast <= msgend) && (!ctx->hdrs[fetchlast])) fetchlast++; /* @@ -216,43 +189,41 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) * request for all the new messages. */ snprintf (buf, sizeof (buf), - "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, - fetchlast, hdrreq); + "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", + msgno + 1, fetchlast, hdrreq); imap_cmd_start (idata, buf); } /* freshen fp, h */ rewind (fp); - memset (&h, 0, sizeof (h)); - h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); + p_clear(&h, 1); + h.data = p_new(IMAP_HEADER_DATA, 1); /* this DO loop does two things: * 1. handles untagged messages, so we can try again on the same msg * 2. fetches the tagged response at the end of the last message. */ - do - { + do { mfhrc = 0; rc = imap_cmd_step (idata); if (rc != IMAP_CMD_CONTINUE) - break; + break; - if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, fp)) == -1) - continue; + if ((mfhrc = + msg_fetch_header (idata->ctx, &h, idata->cmd.buf.data, fp)) == -1) + continue; else if (mfhrc < 0) - break; + break; /* make sure we don't get remnants from older larger message headers */ fputs ("\n\n", fp); /* update context with message header */ - ctx->hdrs[msgno] = mutt_new_header (); + ctx->hdrs[msgno] = header_new(); ctx->hdrs[msgno]->index = h.sid - 1; - if (h.sid != ctx->msgcount + 1) - dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); /* messages which have not been expunged are ACTIVE (borrowed from mh * folders) */ ctx->hdrs[msgno]->active = 1; @@ -269,46 +240,45 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends * on h.received being set */ ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], - 0, 0); + 0, 0); /* content built as a side-effect of mutt_read_rfc822_header */ ctx->hdrs[msgno]->content->length = h.content_length; -#if USE_HCACHE - sprintf(uid_buf, "/%u", h.data->uid); - mutt_hcache_store(hc, uid_buf, ctx->hdrs[msgno], idata->uid_validity, &imap_hcache_keylen); +#ifdef USE_HCACHE + sprintf (uid_buf, "/%u", h.data->uid); + mutt_hcache_store (hc, uid_buf, ctx->hdrs[msgno], idata->uid_validity, + &imap_hcache_keylen); #endif /* USE_HCACHE */ ctx->msgcount++; } while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || - ((msgno + 1) >= fetchlast))); + ((msgno + 1) >= fetchlast))); - if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) - { - imap_free_header_data ((void**) &h.data); - fclose (fp); -#if USE_HCACHE - mutt_hcache_close (hc); + if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) { + imap_free_header_data ((void *)&h.data); + m_fclose(&fp); +#ifdef USE_HCACHE + mutt_hcache_close (&hc); #endif /* USE_HCACHE */ return -1; } - + /* in case we get new mail while fetching the headers */ - if (idata->reopen & IMAP_NEWMAIL_PENDING) - { + if (idata->reopen & IMAP_NEWMAIL_PENDING) { msgend = idata->newMailCount - 1; while ((msgend) >= ctx->hdrmax) - mx_alloc_memory (ctx); + mx_alloc_memory (ctx); idata->reopen &= ~IMAP_NEWMAIL_PENDING; idata->newMailCount = 0; } } -#if USE_HCACHE - mutt_hcache_close (hc); +#ifdef USE_HCACHE + mutt_hcache_close (&hc); #endif /* USE_HCACHE */ - fclose(fp); + m_fclose(&fp); if (ctx->msgcount > oldmsgcount) mx_update_context (ctx, ctx->msgcount - oldmsgcount); @@ -316,10 +286,55 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) return msgend; } -int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) +/* move all the headers from extra not present in base into base */ +static void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra) { - IMAP_DATA* idata; - HEADER* h; + /* copies each existing element if necessary, and sets the element + * to NULL in the source so that envelope_delete doesn't leave us + * with dangling pointers. */ +#define MOVE_ELEM(h) if (!base->h) { base->h = (*extra)->h; (*extra)->h = NULL; } + MOVE_ELEM(return_path); + MOVE_ELEM(from); + MOVE_ELEM(to); + MOVE_ELEM(cc); + MOVE_ELEM(bcc); + MOVE_ELEM(sender); + MOVE_ELEM(reply_to); + MOVE_ELEM(mail_followup_to); + MOVE_ELEM(list_post); + MOVE_ELEM(message_id); + MOVE_ELEM(supersedes); + MOVE_ELEM(date); + MOVE_ELEM(x_label); + if (!base->refs_changed) { + MOVE_ELEM(references); + } + if (!base->irt_changed) { + MOVE_ELEM(in_reply_to); + } + /* real_subj is subordinate to subject */ + if (!base->subject) { + base->subject = (*extra)->subject; + base->real_subj = (*extra)->real_subj; + (*extra)->subject = NULL; + (*extra)->real_subj = NULL; + } + /* spam and user headers should never be hashed, and the new envelope may + * have better values. Use new versions regardless. */ + mutt_buffer_free (&base->spam); + string_list_wipe(&base->userhdrs); + MOVE_ELEM(spam); + MOVE_ELEM(userhdrs); +#undef MOVE_ELEM + + envelope_delete(extra); +} + +int imap_fetch_message (MESSAGE * msg, CONTEXT * ctx, int msgno) +{ + IMAP_DATA *idata; + HEADER *h; + ENVELOPE* newenv; char buf[LONG_STRING]; char path[_POSIX_PATH_MAX]; char *pc; @@ -327,112 +342,98 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) int uid; int cacheno; IMAP_CACHE *cache; - int read; + int isread; int rc; + progress_t bar; + /* Sam's weird courier server returns an OK response even when FETCH * fails. Thanks Sam. */ short fetched = 0; - idata = (IMAP_DATA*) ctx->data; + idata = (IMAP_DATA *) ctx->data; h = ctx->hdrs[msgno]; /* see if we already have the message in our cache */ - cacheno = HEADER_DATA(h)->uid % IMAP_CACHE_LEN; + cacheno = HEADER_DATA (h)->uid % IMAP_CACHE_LEN; cache = &idata->cache[cacheno]; - if (cache->path) - { - if (cache->uid == HEADER_DATA(h)->uid) - { - /* yes, so just return a pointer to the message */ - if (!(msg->fp = fopen (cache->path, "r"))) - { - mutt_perror (cache->path); - return (-1); - } + if (cache->path) { + /* don't treat cache errors as fatal, just fall back. */ + if (cache->uid == HEADER_DATA(h)->uid && (msg->fp = fopen (cache->path, "r"))) return 0; - } - else - { - /* clear the previous entry */ + else { unlink (cache->path); - FREE (&cache->path); + p_delete(&cache->path); } } - if (!isendwin()) + if (!isendwin ()) mutt_message _("Fetching message..."); - cache->uid = HEADER_DATA(h)->uid; - mutt_mktemp (path); - cache->path = safe_strdup (path); - if (!(msg->fp = safe_fopen (path, "w+"))) - { - FREE (&cache->path); + cache->uid = HEADER_DATA (h)->uid; + msg->fp = m_tempfile(path, sizeof(path), NONULL(mod_core.tmpdir), NULL); + if (!msg->fp) { return -1; } + cache->path = m_strdup(path); /* mark this header as currently inactive so the command handler won't * also try to update it. HACK until all this code can be moved into the * command handler */ h->active = 0; - - snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA(h)->uid, - (mutt_bit_isset (idata->capabilities, IMAP4REV1) ? - (option (OPTIMAPPEEK) ? "BODY.PEEK[]" : "BODY[]") : - "RFC822")); + + snprintf (buf, sizeof (buf), "UID FETCH %u %s", HEADER_DATA (h)->uid, + (mutt_bit_isset (idata->capabilities, IMAP4REV1) ? + "BODY.PEEK[]" : "RFC822")); imap_cmd_start (idata, buf); - do - { + do { if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) break; - pc = idata->cmd.buf; + pc = idata->cmd.buf.data; pc = imap_next_word (pc); pc = imap_next_word (pc); - if (!ascii_strncasecmp ("FETCH", pc, 5)) - { - while (*pc) - { - pc = imap_next_word (pc); - if (pc[0] == '(') - pc++; - if (ascii_strncasecmp ("UID", pc, 3) == 0) - { - pc = imap_next_word (pc); - uid = atoi (pc); - if (uid != HEADER_DATA(h)->uid) - mutt_error (_("The message index is incorrect. Try reopening the mailbox.")); - } - else if ((ascii_strncasecmp ("RFC822", pc, 6) == 0) || - (ascii_strncasecmp ("BODY[]", pc, 6) == 0)) - { - pc = imap_next_word (pc); - if (imap_get_literal_count(pc, &bytes) < 0) - { - imap_error ("imap_fetch_message()", buf); - goto bail; - } - if (imap_read_literal (msg->fp, idata, bytes) < 0) - goto bail; - /* pick up trailing line */ - if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) - goto bail; - pc = idata->cmd.buf; - - fetched = 1; - } - /* UW-IMAP will provide a FLAGS update here if the FETCH causes a - * change (eg from \Unseen to \Seen). - * Uncommitted changes in mutt take precedence. If we decide to - * incrementally update flags later, this won't stop us syncing */ - else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed) - { - if ((pc = imap_set_flags (idata, h, pc)) == NULL) - goto bail; - } + if (!ascii_strncasecmp ("FETCH", pc, 5)) { + while (*pc) { + pc = imap_next_word (pc); + if (pc[0] == '(') + pc++; + if (ascii_strncasecmp ("UID", pc, 3) == 0) { + pc = imap_next_word (pc); + uid = atoi (pc); + if (uid != HEADER_DATA(h)->uid) + mutt_error (_ + ("The message index is incorrect. Try reopening the mailbox.")); + } + else if ((ascii_strncasecmp ("RFC822", pc, 6) == 0) || + (ascii_strncasecmp ("BODY[]", pc, 6) == 0)) { + pc = imap_next_word (pc); + if (imap_get_literal_count (pc, &bytes) < 0) { + imap_error ("imap_fetch_message()", buf); + goto bail; + } + bar.size = bytes; + bar.msg = _("Fetching message..."); + mutt_progress_bar (&bar, 0); + if (imap_read_literal (msg->fp, idata, bytes, &bar) < 0) + goto bail; + /* pick up trailing line */ + if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) + goto bail; + pc = idata->cmd.buf.data; + + fetched = 1; + } + /* UW-IMAP will provide a FLAGS update here if the FETCH causes a + * change (eg from \Unseen to \Seen). + * Uncommitted changes in mutt take precedence. If we decide to + * incrementally update flags later, this won't stop us syncing */ + else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed) { + if ((pc = imap_set_flags (idata, h, pc)) == NULL) + goto bail; + } } } } @@ -441,12 +442,18 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) /* see comment before command start. */ h->active = 1; + fflush (msg->fp); + if (ferror (msg->fp)) { + mutt_perror (cache->path); + goto bail; + } + if (rc != IMAP_CMD_OK) goto bail; - if (!fetched || !imap_code (idata->cmd.buf)) + if (!fetched || !imap_code (idata->cmd.buf.data)) goto bail; - + /* Update the header information. Previously, we only downloaded a * portion of the headers, those required for the main display. */ @@ -456,83 +463,68 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) * the server's notion of 'read' and if it differs from the message info * picked up in mutt_read_rfc822_header, we mark the message (and context * changed). Another possiblity: ignore Status on IMAP?*/ - read = h->read; - /* I hate do this here, since it's so low-level, but I'm not sure where - * I can abstract it. Problem: the id and subj hashes lose their keys when - * mutt_free_envelope gets called, but keep their spots in the hash. This - * confuses threading. Alternatively we could try to merge the new - * envelope into the old one. Also messy and lowlevel. */ - if (ctx->id_hash && h->env->message_id) - hash_delete (ctx->id_hash, h->env->message_id, h, NULL); - if (ctx->subj_hash && h->env->real_subj) - hash_delete (ctx->subj_hash, h->env->real_subj, h, NULL); - mutt_free_envelope (&h->env); - h->env = mutt_read_rfc822_header (msg->fp, h, 0, 0); - if (ctx->id_hash && h->env->message_id) - hash_insert (ctx->id_hash, h->env->message_id, h, 0); - if (ctx->subj_hash && h->env->real_subj) - hash_insert (ctx->subj_hash, h->env->real_subj, h, 1); + isread = h->read; + newenv = mutt_read_rfc822_header (msg->fp, h, 0, 0); + mutt_merge_envelopes(h->env, &newenv); /* see above. We want the new status in h->read, so we unset it manually * and let mutt_set_flag set it correctly, updating context. */ - if (read != h->read) - { - h->read = read; - mutt_set_flag (ctx, h, M_NEW, read); + if (isread != h->read) { + h->read = isread; + mutt_set_flag (ctx, h, M_NEW, isread); } h->lines = 0; fgets (buf, sizeof (buf), msg->fp); - while (!feof (msg->fp)) - { + while (!feof (msg->fp)) { h->lines++; fgets (buf, sizeof (buf), msg->fp); } - h->content->length = ftell (msg->fp) - h->content->offset; + h->content->length = ftello (msg->fp) - h->content->offset; /* This needs to be done in case this is a multipart message */ #if defined(HAVE_PGP) || defined(HAVE_SMIME) h->security = crypt_query (h->content); #endif - mutt_clear_error(); + mutt_clear_error (); rewind (msg->fp); return 0; bail: - safe_fclose (&msg->fp); - if (cache->path) - { + m_fclose(&msg->fp); + if (cache->path) { unlink (cache->path); - FREE (&cache->path); + p_delete(&cache->path); } return -1; } -int imap_append_message (CONTEXT *ctx, MESSAGE *msg) +int imap_append_message (CONTEXT * ctx, MESSAGE * msg) { - IMAP_DATA* idata; + IMAP_DATA *idata; FILE *fp; char buf[LONG_STRING]; char mbox[LONG_STRING]; - char mailbox[LONG_STRING]; + char mailbox[LONG_STRING]; size_t len; int c, last; IMAP_MBOX mx; int rc; + progress_t bar; + size_t sent; - idata = (IMAP_DATA*) ctx->data; + idata = (IMAP_DATA *) ctx->data; if (imap_parse_path (ctx->path, &mx)) return -1; imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); - - if ((fp = fopen (msg->path, "r")) == NULL) - { + + if ((fp = fopen (msg->path, "r")) == NULL) { mutt_perror (msg->path); goto fail; } @@ -543,17 +535,26 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg) * expensive (it'd be nice if we had the file size passed in already * by the code that writes the file, but that's a lot of changes. * Ideally we'd have a HEADER structure with flag info here... */ - for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) - { - if(c == '\n' && last != '\r') + for (last = EOF, len = 0; (c = fgetc (fp)) != EOF; last = c) { + if (c == '\n' && last != '\r') len++; len++; } rewind (fp); - + + bar.msg = _("Uploading message..."); + bar.size = len; + mutt_progress_bar (&bar, 0); + imap_munge_mbox_name (mbox, sizeof (mbox), mailbox); - snprintf (buf, sizeof (buf), "APPEND %s (\\Seen) {%lu}", mbox, len); + snprintf (buf, sizeof (buf), "APPEND %s (%s%s%s%s%s) {%lu}", mbox, + msg->flags.read ? "\\Seen" : "", + msg->flags.read && (msg->flags.replied + || msg->flags.flagged) ? " " : "", + msg->flags.replied ? "\\Answered" : "", msg->flags.replied + && msg->flags.flagged ? " " : "", + msg->flags.flagged ? "\\Flagged" : "", (unsigned long) len); imap_cmd_start (idata, buf); @@ -561,64 +562,55 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg) rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); - if (rc != IMAP_CMD_RESPOND) - { + if (rc != IMAP_CMD_RESPOND) { char *pc; - dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", - idata->cmd.buf)); - - pc = idata->cmd.buf + SEQLEN; - SKIPWS (pc); + pc = vskipspaces(idata->cmd.buf.data + SEQLEN); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (1); - fclose (fp); + m_fclose(&fp); goto fail; } - mutt_message _("Uploading message ..."); - - for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) - { + for (last = EOF, sent = len = 0; (c = fgetc (fp)) != EOF; last = c) { if (c == '\n' && last != '\r') buf[len++] = '\r'; buf[len++] = c; - if (len > sizeof(buf) - 3) - flush_buffer(buf, &len, idata->conn); + if (len > sizeof (buf) - 3) { + sent += len; + flush_buffer (buf, &len, idata->conn); + mutt_progress_bar (&bar, sent); + } } - + if (len) - flush_buffer(buf, &len, idata->conn); + flush_buffer (buf, &len, idata->conn); mutt_socket_write (idata->conn, "\r\n"); - fclose (fp); + m_fclose(&fp); do rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); - if (!imap_code (idata->cmd.buf)) - { + if (!imap_code (idata->cmd.buf.data)) { char *pc; - dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", - idata->cmd.buf)); - pc = idata->cmd.buf + SEQLEN; - SKIPWS (pc); + pc = vskipspaces(idata->cmd.buf.data + SEQLEN); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (1); goto fail; } - FREE (&mx.mbox); + p_delete(&mx.mbox); return 0; - fail: - FREE (&mx.mbox); +fail: + p_delete(&mx.mbox); return -1; } @@ -628,72 +620,79 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg) * -1: error * 0: success * 1: non-fatal error - try fetch/append */ -int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) +int imap_copy_messages (CONTEXT * ctx, HEADER * h, char *dest, int delete) { - IMAP_DATA* idata; - BUFFER cmd; + IMAP_DATA *idata; + BUFFER cmd, sync_cmd; char uid[11]; char mbox[LONG_STRING]; char mmbox[LONG_STRING]; int rc; int n; IMAP_MBOX mx; + int err_continue = M_NO; - idata = (IMAP_DATA*) ctx->data; + idata = (IMAP_DATA *) ctx->data; - if (imap_parse_path (dest, &mx)) - { - dprint (1, (debugfile, "imap_copy_messages: bad destination %s\n", dest)); + if (imap_parse_path (dest, &mx)) { return -1; } /* check that the save-to folder is in the same account */ - if (!mutt_account_match (&(CTX_DATA->conn->account), &(mx.account))) - { - dprint (3, (debugfile, "imap_copy_messages: %s not same server as %s\n", - dest, ctx->path)); + if (!mutt_account_match (&(CTX_DATA->conn->account), &(mx.account))) { return 1; } - if (h && h->attach_del) - { - dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); + if (h && h->attach_del) { return 1; } - + imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); - memset (&cmd, 0, sizeof (cmd)); + p_clear(&sync_cmd, 1); + p_clear(&cmd, 1); mutt_buffer_addstr (&cmd, "UID COPY "); /* Null HEADER* means copy tagged messages */ - if (!h) - { + if (!h) { /* if any messages have attachments to delete, fall through to FETCH * and APPEND. TODO: Copy what we can with COPY, fall through for the * remainder. */ - for (n = 0; n < ctx->msgcount; n++) - { - if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->attach_del) + for (n = 0; n < ctx->msgcount; n++) { + if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->attach_del) { + return 1; + } + + if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active && + ctx->hdrs[n]->changed) { - dprint (3, (debugfile, "imap_copy_messages: Message contains attachments to be deleted\n")); - return 1; + rc = imap_sync_message (idata, ctx->hdrs[n], &sync_cmd, &err_continue); + if (rc < 0) + { + goto fail; + } } } rc = imap_make_msg_set (idata, &cmd, M_TAG, 0); - if (!rc) - { - dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n")); + if (!rc) { goto fail; } mutt_message (_("Copying %d messages to %s..."), rc, mbox); } - else - { - mutt_message (_("Copying message %d to %s..."), h->index+1, mbox); + else { + mutt_message (_("Copying message %d to %s..."), h->index + 1, mbox); snprintf (uid, sizeof (uid), "%u", HEADER_DATA (h)->uid); mutt_buffer_addstr (&cmd, uid); + + if (h->active && h->changed) + { + rc = imap_sync_message (idata, h, &sync_cmd, &err_continue); + if (rc < 0) + { + goto fail; + } + } } /* let's get it on */ @@ -702,18 +701,15 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) mutt_buffer_addstr (&cmd, mmbox); rc = imap_exec (idata, cmd.data, IMAP_CMD_FAIL_OK); - if (rc == -2) - { + if (rc == -2) { /* bail out if command failed for reasons other than nonexistent target */ - if (ascii_strncasecmp (imap_get_qualifier (idata->cmd.buf), "[TRYCREATE]", 11)) - { - imap_error ("imap_copy_messages", idata->cmd.buf); + if (ascii_strncasecmp + (imap_get_qualifier (idata->cmd.buf.data), "[TRYCREATE]", 11)) { + imap_error ("imap_copy_messages", idata->cmd.buf.data); goto fail; } - dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n")); snprintf (mmbox, sizeof (mmbox), _("Create %s?"), mbox); - if (option (OPTCONFIRMCREATE) && mutt_yesorno (mmbox, 1) < 1) - { + if (option (OPTCONFIRMCREATE) && mutt_yesorno (mmbox, 1) < 1) { mutt_clear_error (); goto fail; } @@ -723,28 +719,23 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) /* try again */ rc = imap_exec (idata, cmd.data, 0); } - if (rc != 0) - { - imap_error ("imap_copy_messages", idata->cmd.buf); + if (rc != 0) { + imap_error ("imap_copy_messages", idata->cmd.buf.data); goto fail; } /* cleanup */ - if (delete) - { + if (delete) { if (!h) - for (n = 0; n < ctx->msgcount; n++) - { - if (ctx->hdrs[n]->tagged) - { + for (n = 0; n < ctx->msgcount; n++) { + if (ctx->hdrs[n]->tagged) { mutt_set_flag (ctx, ctx->hdrs[n], M_DELETE, 1); - mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1); + mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1); if (option (OPTDELETEUNTAG)) mutt_set_flag (ctx, ctx->hdrs[n], M_TAG, 0); } } - else - { + else { mutt_set_flag (ctx, h, M_DELETE, 1); mutt_set_flag (ctx, h, M_APPENDED, 1); if (option (OPTDELETEUNTAG)) @@ -752,74 +743,71 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) } } - if (cmd.data) - FREE (&cmd.data); - FREE (&mx.mbox); + p_delete(&cmd.data); + p_delete(&sync_cmd.data); + p_delete(&mx.mbox); return 0; - fail: - if (cmd.data) - FREE (&cmd.data); - FREE (&mx.mbox); +fail: + p_delete(&cmd.data); + p_delete(&sync_cmd.data); + p_delete(&mx.mbox); return -1; } /* imap_add_keywords: concatenate custom IMAP tags to list, if they * appear in the folder flags list. Why wouldn't they? */ -void imap_add_keywords (char* s, HEADER* h, LIST* mailbox_flags, size_t slen) +void imap_add_keywords (char *s, HEADER * h, string_list_t * mailbox_flags, + size_t slen) { - LIST *keywords; + string_list_t *keywords; - if (!mailbox_flags || !HEADER_DATA(h) || !HEADER_DATA(h)->keywords) + if (!mailbox_flags || !HEADER_DATA (h) || !HEADER_DATA (h)->keywords) return; - keywords = HEADER_DATA(h)->keywords->next; + keywords = HEADER_DATA (h)->keywords->next; - while (keywords) - { - if (msg_has_flag (mailbox_flags, keywords->data)) - { - safe_strcat (s, slen, keywords->data); - safe_strcat (s, slen, " "); + while (keywords) { + if (msg_has_flag (mailbox_flags, keywords->data)) { + m_strcat(s, slen, keywords->data); + m_strcat(s, slen, " "); } keywords = keywords->next; } } /* imap_free_header_data: free IMAP_HEADER structure */ -void imap_free_header_data (void** data) +void imap_free_header_data (void **data) { /* this should be safe even if the list wasn't used */ - mutt_free_list (&(((IMAP_HEADER_DATA*) *data)->keywords)); + string_list_wipe(&(((IMAP_HEADER_DATA *) * data)->keywords)); - FREE (data); + p_delete(data); } /* imap_set_flags: fill out the message header according to the flags from * the server. Expects a flags line of the form "FLAGS (flag flag ...)" */ -char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s) +char *imap_set_flags (IMAP_DATA * idata, HEADER * h, char *s) { - CONTEXT* ctx = idata->ctx; + CONTEXT *ctx = idata->ctx; IMAP_HEADER newh; unsigned char readonly; - memset (&newh, 0, sizeof (newh)); - newh.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); + p_clear(&newh, 1); + newh.data = p_new(IMAP_HEADER_DATA, 1); - dprint (2, (debugfile, "imap_fetch_message: parsing FLAGS\n")); - if ((s = msg_parse_flags (&newh, s)) == NULL) - { - FREE (&newh.data); + if ((s = msg_parse_flags (&newh, s)) == NULL) { + p_delete(&newh.data); return NULL; } - + /* YAUH (yet another ugly hack): temporarily set context to * read-write even if it's read-only, so *server* updates of * flags can be processed by mutt_set_flag. ctx->changed must * be restored afterwards */ readonly = ctx->readonly; ctx->readonly = 0; - + mutt_set_flag (ctx, h, M_NEW, !(newh.read || newh.old)); mutt_set_flag (ctx, h, M_OLD, newh.old); mutt_set_flag (ctx, h, M_READ, newh.read); @@ -833,9 +821,9 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s) ctx->changed &= ~readonly; ctx->readonly = readonly; - mutt_free_list (&(HEADER_DATA(h)->keywords)); - HEADER_DATA(h)->keywords = newh.data->keywords; - FREE(&newh.data); + string_list_wipe(&(HEADER_DATA (h)->keywords)); + HEADER_DATA (h)->keywords = newh.data->keywords; + p_delete(&newh.data); return s; } @@ -847,17 +835,18 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s) * 0 on success * -1 if the string is not a fetch response * -2 if the string is a corrupt fetch response */ -static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) +static int msg_fetch_header (CONTEXT * ctx, IMAP_HEADER * h, char *buf, + FILE * fp) { - IMAP_DATA* idata; + IMAP_DATA *idata; long bytes; - int rc = -1; /* default now is that string isn't FETCH response*/ + int rc = -1; /* default now is that string isn't FETCH response */ - idata = (IMAP_DATA*) ctx->data; + idata = (IMAP_DATA *) ctx->data; if (buf[0] != '*') return rc; - + /* skip to message number */ buf = imap_next_word (buf); h->sid = atoi (buf); @@ -867,7 +856,7 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) if (ascii_strncasecmp ("FETCH", buf, 5)) return rc; - rc = -2; /* we've got a FETCH response, for better or worse */ + rc = -2; /* we've got a FETCH response, for better or worse */ if (!(buf = strchr (buf, '('))) return rc; buf++; @@ -876,10 +865,9 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) * read header lines and call it again. Silly. */ if (msg_parse_fetch (h, buf) != -2) return rc; - - if (imap_get_literal_count (buf, &bytes) == 0) - { - imap_read_literal (fp, idata, bytes); + + if (imap_get_literal_count (buf, &bytes) == 0) { + imap_read_literal (fp, idata, bytes, NULL); /* we may have other fields of the FETCH _after_ the literal * (eg Domino puts FLAGS here). Nothing wrong with that, either. @@ -887,13 +875,13 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) * interchangeably at any time. */ if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE) return rc; - - if (msg_parse_fetch (h, idata->cmd.buf) == -1) + + if (msg_parse_fetch (h, idata->cmd.buf.data) == -1) return rc; } - rc = 0; /* success */ - + rc = 0; /* success */ + /* subtract headers from message size - unfortunately only the subset of * headers we've requested. */ h->content_length -= bytes; @@ -901,10 +889,10 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) return rc; } -#if USE_HCACHE -static size_t imap_hcache_keylen (const char *fn) +#ifdef USE_HCACHE +static ssize_t imap_hcache_keylen (const char *fn) { - return mutt_strlen(fn); + return m_strlen(fn); } /* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER. @@ -913,13 +901,13 @@ static size_t imap_hcache_keylen (const char *fn) * 0 on success * -1 if the string is not a fetch response * -2 if the string is a corrupt fetch response */ -static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) +static int msg_fetch_header_fetch (CONTEXT * ctx, IMAP_HEADER * h, char *buf, + FILE * fp __attribute__ ((unused))) { - IMAP_DATA* idata; - long bytes; - int rc = -1; /* default now is that string isn't FETCH response*/ + IMAP_DATA *idata; + int rc = -1; /* default now is that string isn't FETCH response */ - idata = (IMAP_DATA*) ctx->data; + idata = (IMAP_DATA *) ctx->data; if (buf[0] != '*') return rc; @@ -933,13 +921,13 @@ static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE if (ascii_strncasecmp ("FETCH", buf, 5)) return rc; - rc = -2; /* we've got a FETCH response, for better or worse */ + rc = -2; /* we've got a FETCH response, for better or worse */ if (!(buf = strchr (buf, '('))) return rc; buf++; if (msg_parse_fetch (h, buf) < 0) { - return -2; + return -2; } if (!(buf = strchr (buf, ')'))) @@ -953,15 +941,14 @@ static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE /* msg_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 msg_has_flag (LIST* flag_list, const char* flag) +static int msg_has_flag (string_list_t * flag_list, const char *flag) { if (!flag_list) return 0; flag_list = flag_list->next; - while (flag_list) - { - if (!ascii_strncasecmp (flag_list->data, flag, strlen (flag_list->data))) + while (flag_list) { + if (!ascii_strncasecmp (flag_list->data, flag, m_strlen(flag_list->data))) return 1; flag_list = flag_list->next; @@ -971,38 +958,30 @@ static int msg_has_flag (LIST* flag_list, const char* flag) } /* msg_parse_fetch: handle headers returned from header fetch */ -static int msg_parse_fetch (IMAP_HEADER *h, char *s) +static int msg_parse_fetch (IMAP_HEADER * h, char *s) { - char tmp[SHORT_STRING]; + char tmp[STRING]; char *ptmp; if (!s) return -1; - while (*s) - { - SKIPWS (s); + while (*s) { + s = vskipspaces(s); - if (ascii_strncasecmp ("FLAGS", s, 5) == 0) - { + if (ascii_strncasecmp ("FLAGS", s, 5) == 0) { if ((s = msg_parse_flags (h, s)) == NULL) return -1; } - else if (ascii_strncasecmp ("UID", s, 3) == 0) - { - s += 3; - SKIPWS (s); + else if (ascii_strncasecmp ("UID", s, 3) == 0) { + s = vskipspaces(s + 3); h->data->uid = (unsigned int) atoi (s); s = imap_next_word (s); } - else if (ascii_strncasecmp ("INTERNALDATE", s, 12) == 0) - { - s += 12; - SKIPWS (s); - if (*s != '\"') - { - dprint (1, (debugfile, "msg_parse_fetch(): bogus INTERNALDATE entry: %s\n", s)); + else if (ascii_strncasecmp ("INTERNALDATE", s, 12) == 0) { + s = vskipspaces(s + 12); + if (*s != '\"') { return -1; } s++; @@ -1011,14 +990,12 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s) *ptmp++ = *s++; if (*s != '\"') return -1; - s++; /* skip past the trailing " */ + s++; /* skip past the trailing " */ *ptmp = 0; h->received = imap_parse_date (tmp); } - else if (ascii_strncasecmp ("RFC822.SIZE", s, 11) == 0) - { - s += 11; - SKIPWS (s); + else if (ascii_strncasecmp ("RFC822.SIZE", s, 11) == 0) { + s = vskipspaces(s + 11); ptmp = tmp; while (isdigit ((unsigned char) *s)) *ptmp++ = *s++; @@ -1026,15 +1003,13 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s) h->content_length = atoi (tmp); } else if (!ascii_strncasecmp ("BODY", s, 4) || - !ascii_strncasecmp ("RFC822.HEADER", s, 13)) - { + !ascii_strncasecmp ("RFC822.HEADER", s, 13)) { /* handle above, in msg_fetch_header */ return -2; } else if (*s == ')') - s++; /* end of request */ - else if (*s) - { + s++; /* end of request */ + else if (*s) { /* got something i don't understand */ imap_error ("msg_parse_fetch", s); return -1; @@ -1045,63 +1020,49 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s) } /* msg_parse_flags: read a FLAGS token into an IMAP_HEADER */ -static char* msg_parse_flags (IMAP_HEADER* h, char* s) +static char *msg_parse_flags (IMAP_HEADER * h, char *s) { int recent = 0; /* sanity-check string */ - if (ascii_strncasecmp ("FLAGS", s, 5) != 0) - { - dprint (1, (debugfile, "msg_parse_flags: not a FLAGS response: %s\n", - s)); + if (ascii_strncasecmp ("FLAGS", s, 5) != 0) { return NULL; } - s += 5; - SKIPWS(s); - if (*s != '(') - { - dprint (1, (debugfile, "msg_parse_flags: bogus FLAGS response: %s\n", - s)); + s = vskipspaces(s + 5); + if (*s != '(') { return NULL; } s++; /* start parsing */ - while (*s && *s != ')') - { - if (ascii_strncasecmp ("\\deleted", s, 8) == 0) - { + while (*s && *s != ')') { + if (ascii_strncasecmp ("\\deleted", s, 8) == 0) { s += 8; h->deleted = 1; } - else if (ascii_strncasecmp ("\\flagged", s, 8) == 0) - { + else if (ascii_strncasecmp ("\\flagged", s, 8) == 0) { s += 8; h->flagged = 1; } - else if (ascii_strncasecmp ("\\answered", s, 9) == 0) - { + else if (ascii_strncasecmp ("\\answered", s, 9) == 0) { s += 9; h->replied = 1; } - else if (ascii_strncasecmp ("\\seen", s, 5) == 0) - { + else if (ascii_strncasecmp ("\\seen", s, 5) == 0) { s += 5; h->read = 1; } - else if (ascii_strncasecmp ("\\recent", s, 5) == 0) - { + else if (ascii_strncasecmp ("\\recent", s, 5) == 0) { s += 7; recent = 1; } - else - { + else { /* store custom flags as well */ char ctmp; - char* flag_word = s; + char *flag_word = s; if (!h->data->keywords) - h->data->keywords = mutt_new_list (); + h->data->keywords = string_item_new(); while (*s && !ISSPACE (*s) && *s != ')') s++; @@ -1110,30 +1071,26 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s) mutt_add_list (h->data->keywords, flag_word); *s = ctmp; } - SKIPWS(s); + s = vskipspaces(s); } /* wrap up, or note bad flags response */ - if (*s == ')') - { + if (*s == ')') { /* if a message is neither seen nor recent, it is OLD. */ if (option (OPTMARKOLD) && !recent && !(h->read)) h->old = 1; s++; } - else - { - dprint (1, (debugfile, - "msg_parse_flags: Unterminated FLAGS response: %s\n", s)); + else { return NULL; } return s; } -static void flush_buffer(char *buf, size_t *len, CONNECTION *conn) +static void flush_buffer (char *buf, size_t * len, CONNECTION * conn) { buf[*len] = '\0'; - mutt_socket_write(conn, buf); + mutt_socket_write (conn, buf); *len = 0; }