⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 message.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-9 Brandon Long <blong@fiction.net> * Copyright (C) 1999-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. * */ /* message parsing/updating functions */#if HAVE_CONFIG_H# include "config.h"#endif#include <errno.h>#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#if USE_HCACHE#include "hcache.h"#endif#include "bcache.h"static FILE* msg_cache_get (IMAP_DATA* idata, HEADER* h);static FILE* msg_cache_put (IMAP_DATA* idata, HEADER* h);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_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;  IMAP_STATUS* status;  int rc, mfhrc, oldmsgcount;  int fetchlast = 0;  int maxuid = 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";#if USE_HCACHE  header_cache_t *hc = NULL;  unsigned int *uid_validity = NULL;  unsigned int *uidnext = NULL;  int evalhc = 0;  char uid_buf[64];#endif /* USE_HCACHE */  ctx = idata->ctx;  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 : "");  }  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+")))  {    mutt_error (_("Could not create temporary file %s"), tempfile);    mutt_sleep (2);    return -1;  }  unlink (tempfile);  /* make sure context has room to hold the mailbox */  while ((msgend) >= idata->ctx->hdrmax)    mx_alloc_memory (idata->ctx);  oldmsgcount = ctx->msgcount;  idata->reopen &= ~IMAP_NEWMAIL_PENDING;  idata->newMailCount = 0;#if USE_HCACHE  if (!msgbegin)    hc = mutt_hcache_open (HeaderCache, ctx->path);  if (hc)  {    uid_validity = mutt_hcache_fetch_raw (hc, "/UIDVALIDITY", imap_hcache_keylen);    uidnext = mutt_hcache_fetch_raw (hc, "/UIDNEXT", imap_hcache_keylen);    if (uid_validity && uidnext && *uid_validity == idata->uid_validity        && *uidnext > 0)      evalhc = 1;    FREE (&uid_validity);  }  if (evalhc)  {    snprintf (buf, sizeof (buf),      "UID FETCH 1:%u (UID FLAGS)", *uidnext - 1);    FREE (&uidnext);      imap_cmd_start (idata, buf);      for (msgno = msgbegin; msgno <= msgend ; msgno++)    {      if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0)))        mutt_message (_("Evaluating cache... [%d/%d]"), msgno + 1,          msgend + 1);        memset (&h, 0, sizeof (h));      h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));      do      {        mfhrc = 0;        rc = imap_cmd_step (idata);        if (rc != IMAP_CMD_CONTINUE)	{	  imap_free_header_data ((void**) &h.data);          break;	}        if ((mfhrc = msg_fetch_header (ctx, &h, idata->buf, NULL)) == -1)          continue;        else if (mfhrc < 0)	{	  imap_free_header_data ((void**) &h.data);          break;	}        sprintf(uid_buf, "/%u", h.data->uid); /* XXX --tg 21:41 04-07-11 */        uid_validity = (unsigned int*)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.data->read;          ctx->hdrs[msgno]->old = h.data->old;          ctx->hdrs[msgno]->deleted = h.data->deleted;          ctx->hdrs[msgno]->flagged = h.data->flagged;          ctx->hdrs[msgno]->replied = h.data->replied;          ctx->hdrs[msgno]->changed = h.data->changed;          /*  ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */          ctx->hdrs[msgno]->data = (void *) (h.data);          ctx->msgcount++;        }	else	  /* bad header in the cache, we'll have to refetch.	   * TODO: consider the possibility of a holey cache. */	  imap_free_header_data((void**) &h.data);          FREE(&uid_validity);      }      while (rc != IMAP_CMD_OK && mfhrc == -1);      if (rc == IMAP_CMD_OK)        break;      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;  }#endif /* USE_HCACHE */  for (msgno = msgbegin; msgno <= msgend ; msgno++)  {    if (ctx->hdrs[msgno])    {      msgbegin++;      continue;    }    if (ReadInc && (msgno == msgbegin || ((msgno+1) % ReadInc == 0)))      mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1,        msgend + 1);    if (msgno + 1 > fetchlast)    {      fetchlast = msgno + 1;      while((fetchlast <= msgend) && (! ctx->hdrs[fetchlast]))        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,        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));    /* 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 (ctx, &h, idata->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 = 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.data->read;      ctx->hdrs[msgno]->old = h.data->old;      ctx->hdrs[msgno]->deleted = h.data->deleted;      ctx->hdrs[msgno]->flagged = h.data->flagged;      ctx->hdrs[msgno]->replied = h.data->replied;      ctx->hdrs[msgno]->changed = h.data->changed;      ctx->hdrs[msgno]->received = h.received;      ctx->hdrs[msgno]->data = (void *) (h.data);      if (maxuid < h.data->uid)        maxuid = h.data->uid;      rewind (fp);      /* 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);      /* 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);#endif /* USE_HCACHE */      ctx->msgcount++;    }    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);#if 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)    {      msgend = idata->newMailCount - 1;      while ((msgend) >= ctx->hdrmax)	mx_alloc_memory (ctx);      idata->reopen &= ~IMAP_NEWMAIL_PENDING;      idata->newMailCount = 0;    }  }  if (maxuid && (status = imap_mboxcache_get (idata, idata->mailbox)))  status->uidnext = maxuid + 1;#if USE_HCACHE  mutt_hcache_store_raw (hc, "/UIDVALIDITY", &idata->uid_validity,                         sizeof (idata->uid_validity), imap_hcache_keylen);  if (maxuid && idata->uidnext < maxuid + 1)  {    dprint (2, (debugfile, "Overriding UIDNEXT: %u -> %u\n", idata->uidnext, maxuid + 1));    idata->uidnext = maxuid + 1;  }  if (idata->uidnext > 1)    mutt_hcache_store_raw (hc, "/UIDNEXT", &idata->uidnext,			   sizeof (idata->uidnext), imap_hcache_keylen);  mutt_hcache_close (hc);#endif /* USE_HCACHE */  fclose(fp);  if (ctx->msgcount > oldmsgcount)  {    mx_alloc_memory(ctx);    mx_update_context (ctx, ctx->msgcount - oldmsgcount);  }  return msgend;}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;  long bytes;  progress_t progressbar;  int uid;  int cacheno;  IMAP_CACHE *cache;  int read;  int rc;  /* Sam's weird courier server returns an OK response even when FETCH   * fails. Thanks Sam. */  short fetched = 0;  idata = (IMAP_DATA*) ctx->data;  h = ctx->hdrs[msgno];  if ((msg->fp = msg_cache_get (idata, h)))  {    if (HEADER_DATA(h)->parsed)      return 0;    else      goto parsemsg;  }  /* we still do some caching even if imap_cachedir is unset */  /* see if we already have the message in our cache */  cacheno = HEADER_DATA(h)->uid % IMAP_CACHE_LEN;  cache = &idata->cache[cacheno];  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    {      unlink (cache->path);      FREE (&cache->path);    }  }  if (!isendwin())

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -