/*
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
* Copyright (C) 1999-2001 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
/* message parsing/updating functions */
#include <stdlib.h>
#include <ctype.h>
#include "mutt.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);
/* imap_read_headers:
* Changed to read many headers instead of just one. It will return the
* 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)
{
CONTEXT* ctx;
char buf[LONG_STRING];
char hdrreq[STRING];
FILE *fp;
char tempfile[_POSIX_PATH_MAX];
int msgno;
IMAP_HEADER h;
int rc, mfhrc;
int fetchlast = 0;
const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL";
ctx = idata->ctx;
if (mutt_bit_isset (idata->capabilities,IMAP4REV1))
{
snprintf (hdrreq, sizeof (hdrreq), "BODY.PEEK[HEADER.FIELDS (%s)]",
want_headers);
}
else if (mutt_bit_isset (idata->capabilities,IMAP4))
{
snprintf (hdrreq, sizeof (hdrreq), "RFC822.HEADER.LINES (%s)",
want_headers);
}
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 */
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+")))
return -1;
unlink (tempfile);
/* make sure context has room to hold the mailbox */
while ((msgend) >= idata->ctx->hdrmax)
mx_alloc_memory (idata->ctx);
for (msgno = msgbegin; msgno <= msgend ; msgno++)
{
if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0)))
mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1,
msgend + 1);
if (msgno + 1 > fetchlast)
{
/*
* Make one request for everything. This makes fetching headers an
* order of magnitude faster if you have a large mailbox.
*
* If we get more messages while doing this, we make another
* request for all the new messages.
*/
snprintf (buf, sizeof (buf),
"FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1,
msgend + 1, hdrreq);
imap_cmd_start (idata, buf);
fetchlast = msgend + 1;
}
/* freshen fp, h */
rewind (fp);
memset (&h, 0, sizeof (h));
h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
/* 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
{
mfhrc = 0;
rc = imap_cmd_step (idata);
if (rc != IMAP_CMD_CONTINUE)
break;
if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, fp)) == -1)
continue;
else if (mfhrc < 0)
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]->index = ctx->msgcount;
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]