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

📄 mbox.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org> *  *     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. */ /* This file contains code to parse ``mbox'' and ``mmdf'' style mailboxes */#if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mailbox.h"#include "mx.h"#include "sort.h"#include "copy.h"#include <sys/stat.h>#include <dirent.h>#include <string.h>#include <utime.h>#include <sys/file.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>/* struct used by mutt_sync_mailbox() to store new offsets */struct m_update_t{  short valid;  LOFF_T hdr;  LOFF_T body;  long lines;  LOFF_T length;};/* parameters: * ctx - context to lock * excl - exclusive lock? * retry - should retry if unable to lock? */int mbox_lock_mailbox (CONTEXT *ctx, int excl, int retry){  int r;  if ((r = mx_lock_file (ctx->path, fileno (ctx->fp), excl, 1, retry)) == 0)    ctx->locked = 1;  else if (retry && !excl)  {    ctx->readonly = 1;    return 0;  }    return (r);}void mbox_unlock_mailbox (CONTEXT *ctx){  if (ctx->locked)  {    fflush (ctx->fp);    mx_unlock_file (ctx->path, fileno (ctx->fp), 1);    ctx->locked = 0;  }}int mmdf_parse_mailbox (CONTEXT *ctx){  char buf[HUGE_STRING];  char return_path[LONG_STRING];  int count = 0, oldmsgcount = ctx->msgcount;  int lines;  time_t t, tz;  LOFF_T loc, tmploc;  HEADER *hdr;  struct stat sb;#ifdef NFS_ATTRIBUTE_HACK  struct utimbuf newtime;#endif  if (stat (ctx->path, &sb) == -1)  {    mutt_perror (ctx->path);    return (-1);  }  ctx->mtime = sb.st_mtime;  ctx->size = sb.st_size;#ifdef NFS_ATTRIBUTE_HACK  if (sb.st_mtime > sb.st_atime)  {    newtime.modtime = sb.st_mtime;    newtime.actime = time (NULL);    utime (ctx->path, &newtime);  }#endif  /* precompute the local timezone to speed up calculation of the     received time */  tz = mutt_local_tz (0);  buf[sizeof (buf) - 1] = 0;    FOREVER  {    if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)      break;    if (mutt_strcmp (buf, MMDF_SEP) == 0)    {      loc = ftello (ctx->fp);            count++;      if (!ctx->quiet && ReadInc && ((count % ReadInc == 0) || count == 1))	mutt_message (_("Reading %s... %d (%d%%)"), ctx->path, count,		      (int)(loc / (ctx->size / 100 + 1)));      if (ctx->msgcount == ctx->hdrmax)	mx_alloc_memory (ctx);      ctx->hdrs[ctx->msgcount] = hdr = mutt_new_header ();      hdr->offset = loc;      hdr->index = ctx->msgcount;      if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)      {	/* TODO: memory leak??? */	dprint (1, (debugfile, "mmdf_parse_mailbox: unexpected EOF\n"));	break;      }      return_path[0] = 0;      if (!is_from (buf, return_path, sizeof (return_path), &t))      {	if (fseeko (ctx->fp, loc, SEEK_SET) != 0)	{	  dprint (1, (debugfile, "mmdf_parse_mailbox: fseek() failed\n"));	  mutt_error _("Mailbox is corrupt!");	  return (-1);	}      }       else	hdr->received = t - tz;      hdr->env = mutt_read_rfc822_header (ctx->fp, hdr, 0, 0);      loc = ftello (ctx->fp);      if (hdr->content->length > 0 && hdr->lines > 0)      {	tmploc = loc + hdr->content->length;	if (0 < tmploc && tmploc < ctx->size)	{	  if (fseeko (ctx->fp, tmploc, SEEK_SET) != 0 ||	      fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL ||	      mutt_strcmp (MMDF_SEP, buf) != 0)	  {	    if (fseeko (ctx->fp, loc, SEEK_SET) != 0)	      dprint (1, (debugfile, "mmdf_parse_mailbox: fseek() failed\n"));	    hdr->content->length = -1;	  }	}	else	  hdr->content->length = -1;      }      else	hdr->content->length = -1;      if (hdr->content->length < 0)      {	lines = -1;	do {	  loc = ftello (ctx->fp);	  if (fgets (buf, sizeof (buf) - 1, ctx->fp) == NULL)	    break;	  lines++;	} while (mutt_strcmp (buf, MMDF_SEP) != 0);	hdr->lines = lines;	hdr->content->length = loc - hdr->content->offset;      }      if (!hdr->env->return_path && return_path[0])	hdr->env->return_path = rfc822_parse_adrlist (hdr->env->return_path, return_path);      if (!hdr->env->from)	hdr->env->from = rfc822_cpy_adr (hdr->env->return_path);      ctx->msgcount++;    }    else    {      dprint (1, (debugfile, "mmdf_parse_mailbox: corrupt mailbox!\n"));      mutt_error _("Mailbox is corrupt!");      return (-1);    }  }  if (ctx->msgcount > oldmsgcount)    mx_update_context (ctx, ctx->msgcount - oldmsgcount);  return (0);}/* Note that this function is also called when new mail is appended to the * currently open folder, and NOT just when the mailbox is initially read. * * NOTE: it is assumed that the mailbox being read has been locked before * this routine gets called.  Strange things could happen if it's not! */int mbox_parse_mailbox (CONTEXT *ctx){  struct stat sb;  char buf[HUGE_STRING], return_path[STRING];  HEADER *curhdr;  time_t t, tz;  int count = 0, lines = 0;  LOFF_T loc;#ifdef NFS_ATTRIBUTE_HACK  struct utimbuf newtime;#endif  /* Save information about the folder at the time we opened it. */  if (stat (ctx->path, &sb) == -1)  {    mutt_perror (ctx->path);    return (-1);  }  ctx->size = sb.st_size;  ctx->mtime = sb.st_mtime;#ifdef NFS_ATTRIBUTE_HACK  if (sb.st_mtime > sb.st_atime)  {    newtime.modtime = sb.st_mtime;    newtime.actime = time (NULL);    utime (ctx->path, &newtime);  }#endif  if (!ctx->readonly)    ctx->readonly = access (ctx->path, W_OK) ? 1 : 0;  /* precompute the local timezone to speed up calculation of the     date received */  tz = mutt_local_tz (0);  loc = ftello (ctx->fp);  while (fgets (buf, sizeof (buf), ctx->fp) != NULL)  {    if (is_from (buf, return_path, sizeof (return_path), &t))    {      /* Save the Content-Length of the previous message */      if (count > 0)      {#define PREV ctx->hdrs[ctx->msgcount-1]	if (PREV->content->length < 0)	{	  PREV->content->length = loc - PREV->content->offset - 1;	  if (PREV->content->length < 0)	    PREV->content->length = 0;	}	if (!PREV->lines)	  PREV->lines = lines ? lines - 1 : 0;      }      count++;      if (!ctx->quiet && ReadInc && ((count % ReadInc == 0) || count == 1))	mutt_message (_("Reading %s... %d (%d%%)"), ctx->path, count,		      (int)(ftell (ctx->fp) / (ctx->size / 100 + 1)));      if (ctx->msgcount == ctx->hdrmax)	mx_alloc_memory (ctx);            curhdr = ctx->hdrs[ctx->msgcount] = mutt_new_header ();      curhdr->received = t - tz;      curhdr->offset = loc;      curhdr->index = ctx->msgcount;	      curhdr->env = mutt_read_rfc822_header (ctx->fp, curhdr, 0, 0);      /* if we know how long this message is, either just skip over the body,       * or if we don't know how many lines there are, count them now (this will       * save time by not having to search for the next message marker).       */      if (curhdr->content->length > 0)      {	LOFF_T tmploc;	loc = ftello (ctx->fp);	tmploc = loc + curhdr->content->length + 1;	if (0 < tmploc && tmploc < ctx->size)	{	  /*	   * check to see if the content-length looks valid.  we expect to	   * to see a valid message separator at this point in the stream	   */	  if (fseeko (ctx->fp, tmploc, SEEK_SET) != 0 ||	      fgets (buf, sizeof (buf), ctx->fp) == NULL ||	      mutt_strncmp ("From ", buf, 5) != 0)	  {	    dprint (1, (debugfile, "mbox_parse_mailbox: bad content-length in message %d (cl=" OFF_T_FMT ")\n", curhdr->index, curhdr->content->length));	    dprint (1, (debugfile, "\tLINE: %s", buf));	    if (fseeko (ctx->fp, loc, SEEK_SET) != 0) /* nope, return the previous position */	    {	      dprint (1, (debugfile, "mbox_parse_mailbox: fseek() failed\n"));	    }	    curhdr->content->length = -1;	  }	}	else if (tmploc != ctx->size)	{	  /* content-length would put us past the end of the file, so it	   * must be wrong	   */	  curhdr->content->length = -1;	}	if (curhdr->content->length != -1)	{	  /* good content-length.  check to see if we know how many lines	   * are in this message.	   */	  if (curhdr->lines == 0)	  {	    int cl = curhdr->content->length;	    /* count the number of lines in this message */	    if (fseeko (ctx->fp, loc, SEEK_SET) != 0)	      dprint (1, (debugfile, "mbox_parse_mailbox: fseek() failed\n"));	    while (cl-- > 0)	    {	      if (fgetc (ctx->fp) == '\n')		curhdr->lines++;	    }	  }	  /* return to the offset of the next message separator */	  if (fseeko (ctx->fp, tmploc, SEEK_SET) != 0)	    dprint (1, (debugfile, "mbox_parse_mailbox: fseek() failed\n"));	}      }      ctx->msgcount++;      if (!curhdr->env->return_path && return_path[0])	curhdr->env->return_path = rfc822_parse_adrlist (curhdr->env->return_path, return_path);      if (!curhdr->env->from)	curhdr->env->from = rfc822_cpy_adr (curhdr->env->return_path);      lines = 0;    }    else      lines++;        loc = ftello (ctx->fp);  }    /*   * Only set the content-length of the previous message if we have read more   * than one message during _this_ invocation.  If this routine is called   * when new mail is received, we need to make sure not to clobber what   * previously was the last message since the headers may be sorted.   */  if (count > 0)  {    if (PREV->content->length < 0)    {      PREV->content->length = ftello (ctx->fp) - PREV->content->offset - 1;      if (PREV->content->length < 0)	PREV->content->length = 0;    }    if (!PREV->lines)      PREV->lines = lines ? lines - 1 : 0;    mx_update_context (ctx, count);  }  return (0);}#undef PREV/* open a mbox or mmdf style mailbox */int mbox_open_mailbox (CONTEXT *ctx){  int rc;  if ((ctx->fp = fopen (ctx->path, "r")) == NULL)  {    mutt_perror (ctx->path);    return (-1);  }  mutt_block_signals ();  if (mbox_lock_mailbox (ctx, 0, 1) == -1)  {    mutt_unblock_signals ();    return (-1);  }  if (ctx->magic == M_MBOX)    rc = mbox_parse_mailbox (ctx);  else if (ctx->magic == M_MMDF)    rc = mmdf_parse_mailbox (ctx);  else    rc = -1;  mbox_unlock_mailbox (ctx);  mutt_unblock_signals ();  return (rc);}/* return 1 if address lists are strictly identical */static int strict_addrcmp (const ADDRESS *a, const ADDRESS *b){  while (a && b)  {    if (mutt_strcmp (a->mailbox, b->mailbox) ||	mutt_strcmp (a->personal, b->personal))      return (0);    a = a->next;    b = b->next;  }  if (a || b)    return (0);  return (1);}static int strict_cmp_lists (const LIST *a, const LIST *b){  while (a && b)  {    if (mutt_strcmp (a->data, b->data))      return (0);    a = a->next;    b = b->next;  }  if (a || b)    return (0);  return (1);}static int strict_cmp_envelopes (const ENVELOPE *e1, const ENVELOPE *e2){  if (e1 && e2)  {    if (mutt_strcmp (e1->message_id, e2->message_id) ||	mutt_strcmp (e1->subject, e2->subject) ||	!strict_cmp_lists (e1->references, e2->references) ||	!strict_addrcmp (e1->from, e2->from) ||	!strict_addrcmp (e1->sender, e2->sender) ||	!strict_addrcmp (e1->reply_to, e2->reply_to) ||	!strict_addrcmp (e1->to, e2->to) ||	!strict_addrcmp (e1->cc, e2->cc) ||	!strict_addrcmp (e1->return_path, e2->return_path))      return (0);    else      return (1);  }  else  {    if (e1 == NULL && e2 == NULL)      return (1);    else      return (0);  }}static int strict_cmp_parameters (const PARAMETER *p1, const PARAMETER *p2){  while (p1 && p2)  {    if (mutt_strcmp (p1->attribute, p2->attribute) ||	mutt_strcmp (p1->value, p2->value))      return (0);    p1 = p1->next;    p2 = p2->next;  }  if (p1 || p2)    return (0);  return (1);}static int strict_cmp_bodies (const BODY *b1, const BODY *b2){  if (b1->type != b2->type ||      b1->encoding != b2->encoding ||      mutt_strcmp (b1->subtype, b2->subtype) ||      mutt_strcmp (b1->description, b2->description) ||      !strict_cmp_parameters (b1->parameter, b2->parameter) ||      b1->length != b2->length)    return (0);  return (1);}/* return 1 if headers are strictly identical */int mbox_strict_cmp_headers (const HEADER *h1, const HEADER *h2){  if (h1 && h2)  {    if (h1->received != h2->received ||	h1->date_sent != h2->date_sent ||	h1->content->length != h2->content->length ||	h1->lines != h2->lines ||	h1->zhours != h2->zhours ||	h1->zminutes != h2->zminutes ||	h1->zoccident != h2->zoccident ||	h1->mime != h2->mime ||	!strict_cmp_envelopes (h1->env, h2->env) ||	!strict_cmp_bodies (h1->content, h2->content))      return (0);    else      return (1);  }  else  {    if (h1 == NULL && h2 == NULL)      return (1);    else      return (0);  }}/* check to see if the mailbox has changed on disk. * * return values: *	M_REOPENED	mailbox has been reopened *	M_NEW_MAIL	new mail has arrived! *	M_LOCKED	couldn't lock the file *	0		no change *	-1		error */int mbox_check_mailbox (CONTEXT *ctx, int *index_hint){  struct stat st;  char buffer[LONG_STRING];  int unlock = 0;  int modified = 0;  if (stat (ctx->path, &st) == 0)  {    if (st.st_mtime == ctx->mtime && st.st_size == ctx->size)      return (0);    if (st.st_size == ctx->size)    {      /* the file was touched, but it is still the same length, so just exit */      ctx->mtime = st.st_mtime;      return (0);    }    if (st.st_size > ctx->size)    {      /* lock the file if it isn't already */      if (!ctx->locked)      {	mutt_block_signals ();	if (mbox_lock_mailbox (ctx, 0, 0) == -1)	{	  mutt_unblock_signals ();	  /* we couldn't lock the mailbox, but nothing serious happened:	   * probably the new mail arrived: no reason to wait till we can	   * parse it: we'll get it on the next pass	   */	  return (M_LOCKED);	}	unlock = 1;      }      /*       * Check to make sure that the only change to the mailbox is that        * message(s) were appended to this file.  My heuristic is that we should       * see the message separator at *exactly* what used to be the end of the       * folder.       */      if (fseeko (ctx->fp, ctx->size, SEEK_SET) != 0)	dprint (1, (debugfile, "mbox_check_mailbox: fseek() failed\n"));      if (fgets (buffer, sizeof (buffer), ctx->fp) != NULL)      {

⌨️ 快捷键说明

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