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

📄 parse.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-2000 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. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_regex.h"#include "mailbox.h"#include "mime.h"#include "rfc2047.h"#include "rfc2231.h"#include "mutt_crypt.h"#include "url.h"#include <string.h>#include <ctype.h>#include <sys/stat.h>#include <stdlib.h>/* Reads an arbitrarily long header field, and looks ahead for continuation * lines.  ``line'' must point to a dynamically allocated string; it is * increased if more space is required to fit the whole line. */char *mutt_read_rfc822_line (FILE *f, char *line, size_t *linelen){  char *buf = line;  char ch;  size_t offset = 0;  FOREVER  {    if (fgets (buf, *linelen - offset, f) == NULL ||	/* end of file or */	(ISSPACE (*line) && !offset))			/* end of headers */     {      *line = 0;      return (line);    }    buf += strlen (buf) - 1;    if (*buf == '\n')    {      /* we did get a full line. remove trailing space */      while (ISSPACE (*buf))	*buf-- = 0;	/* we cannot come beyond line's beginning because			 * it begins with a non-space */      /* check to see if the next line is a continuation line */      if ((ch = fgetc (f)) != ' ' && ch != '\t')      {	ungetc (ch, f);	return (line); /* next line is a separate header field or EOH */      }      /* eat tabs and spaces from the beginning of the continuation line */      while ((ch = fgetc (f)) == ' ' || ch == '\t')	;      ungetc (ch, f);      *++buf = ' '; /* string is still terminated because we removed		       at least one whitespace char above */    }    buf++;    offset = buf - line;    if (*linelen < offset + STRING)    {      /* grow the buffer */      *linelen += STRING;      safe_realloc (&line, *linelen);      buf = line + offset;    }  }  /* not reached */}static LIST *mutt_parse_references (char *s, int in_reply_to){  LIST *t, *lst = NULL;  int m, n = 0;  char *o = NULL, *new, *at;  while ((s = strtok (s, " \t;")) != NULL)  {    /*     * some mail clients add other garbage besides message-ids, so do a quick     * check to make sure this looks like a valid message-id     * some idiotic clients also break their message-ids between lines, deal     * with that too (give up if it's more than two lines, though)     */    t = NULL;    new = NULL;    if (*s == '<')    {      n = strlen (s);      if (s[n-1] != '>')      {	o = s;	s = NULL;	continue;      }      new = safe_strdup (s);    }    else if (o)    {      m = strlen (s);      if (s[m - 1] == '>')      {	new = safe_malloc (sizeof (char) * (n + m + 1));	strcpy (new, o);	/* __STRCPY_CHECKED__ */	strcpy (new + n, s);	/* __STRCPY_CHECKED__ */      }    }    if (new)    {      /* make sure that this really does look like a message-id.       * it should have exactly one @, and if we're looking at       * an in-reply-to header, make sure that the part before       * the @ has more than eight characters or it's probably       * an email address       */      if (!(at = strchr (new, '@')) || strchr (at + 1, '@')	  || (in_reply_to && at - new <= 8))	FREE (&new);      else      {	t = (LIST *) safe_malloc (sizeof (LIST));	t->data = new;	t->next = lst;	lst = t;      }    }    o = NULL;    s = NULL;  }  return (lst);}int mutt_check_encoding (const char *c){  if (ascii_strncasecmp ("7bit", c, sizeof ("7bit")-1) == 0)    return (ENC7BIT);  else if (ascii_strncasecmp ("8bit", c, sizeof ("8bit")-1) == 0)    return (ENC8BIT);  else if (ascii_strncasecmp ("binary", c, sizeof ("binary")-1) == 0)    return (ENCBINARY);  else if (ascii_strncasecmp ("quoted-printable", c, sizeof ("quoted-printable")-1) == 0)    return (ENCQUOTEDPRINTABLE);  else if (ascii_strncasecmp ("base64", c, sizeof("base64")-1) == 0)    return (ENCBASE64);  else if (ascii_strncasecmp ("x-uuencode", c, sizeof("x-uuencode")-1) == 0)    return (ENCUUENCODED);#ifdef SUN_ATTACHMENT  else if (ascii_strncasecmp ("uuencode", c, sizeof("uuencode")-1) == 0)    return (ENCUUENCODED);#endif  else    return (ENCOTHER);}static PARAMETER *parse_parameters (const char *s){  PARAMETER *head = 0, *cur = 0, *new;  char buffer[LONG_STRING];  const char *p;  size_t i;  dprint (2, (debugfile, "parse_parameters: `%s'\n", s));    while (*s)  {    if ((p = strpbrk (s, "=;")) == NULL)    {      dprint(1, (debugfile, "parse_parameters: malformed parameter: %s\n", s));      goto bail;    }    /* if we hit a ; now the parameter has no value, just skip it */    if (*p != ';')    {      i = p - s;      new = mutt_new_parameter ();      new->attribute = safe_malloc (i + 1);      memcpy (new->attribute, s, i);      new->attribute[i] = 0;      /* remove whitespace from the end of the attribute name */      while (ISSPACE (new->attribute[--i]))	new->attribute[i] = 0;      s = p + 1; /* skip over the = */      SKIPWS (s);      if (*s == '"')      {	s++;	for (i=0; *s && *s != '"' && i < sizeof (buffer) - 1; i++, s++)	{	  if (*s == '\\')	  {	    /* Quote the next character */	    buffer[i] = s[1];	    if (!*++s)	      break;	  }	  else	    buffer[i] = *s;	}	buffer[i] = 0;	if (*s)	  s++; /* skip over the " */      }      else      {	for (i=0; *s && *s != ' ' && *s != ';' && i < sizeof (buffer) - 1; i++, s++)	  buffer[i] = *s;	buffer[i] = 0;      }      new->value = safe_strdup (buffer);      dprint (2, (debugfile, "parse_parameter: `%s' = `%s'\n",		  new->attribute ? new->attribute : "",		  new->value ? new->value : ""));            /* Add this parameter to the list */      if (head)      {	cur->next = new;	cur = cur->next;      }      else	head = cur = new;    }    else    {      dprint (1, (debugfile, "parse_parameters(): parameter with no value: %s\n", s));      s = p;    }    /* Find the next parameter */    if (*s != ';' && (s = strchr (s, ';')) == NULL)	break; /* no more parameters */    do    {      s++;      /* Move past any leading whitespace */      SKIPWS (s);    }    while (*s == ';'); /* skip empty parameters */  }      bail:  rfc2231_decode_parameters (&head);  return (head);}int mutt_check_mime_type (const char *s){  if (ascii_strcasecmp ("text", s) == 0)    return TYPETEXT;  else if (ascii_strcasecmp ("multipart", s) == 0)    return TYPEMULTIPART;#ifdef SUN_ATTACHMENT   else if (ascii_strcasecmp ("x-sun-attachment", s) == 0)    return TYPEMULTIPART;#endif  else if (ascii_strcasecmp ("application", s) == 0)    return TYPEAPPLICATION;  else if (ascii_strcasecmp ("message", s) == 0)    return TYPEMESSAGE;  else if (ascii_strcasecmp ("image", s) == 0)    return TYPEIMAGE;  else if (ascii_strcasecmp ("audio", s) == 0)    return TYPEAUDIO;  else if (ascii_strcasecmp ("video", s) == 0)    return TYPEVIDEO;  else if (ascii_strcasecmp ("model", s) == 0)    return TYPEMODEL;  else if (ascii_strcasecmp ("*", s) == 0)    return TYPEANY;  else if (ascii_strcasecmp (".*", s) == 0)    return TYPEANY;  else    return TYPEOTHER;}void mutt_parse_content_type (char *s, BODY *ct){  char *pc;  char *subtype;  FREE (&ct->subtype);  mutt_free_parameter(&ct->parameter);  /* First extract any existing parameters */  if ((pc = strchr(s, ';')) != NULL)  {    *pc++ = 0;    while (*pc && ISSPACE (*pc))      pc++;    ct->parameter = parse_parameters(pc);    /* Some pre-RFC1521 gateways still use the "name=filename" convention,     * but if a filename has already been set in the content-disposition,     * let that take precedence, and don't set it here */    if ((pc = mutt_get_parameter( "name", ct->parameter)) != 0 && !ct->filename)      ct->filename = safe_strdup(pc);    #ifdef SUN_ATTACHMENT    /* this is deep and utter perversion */    if ((pc = mutt_get_parameter ("conversions", ct->parameter)) != 0)      ct->encoding = mutt_check_encoding (pc);#endif      }    /* Now get the subtype */  if ((subtype = strchr(s, '/')))  {    *subtype++ = '\0';    for(pc = subtype; *pc && !ISSPACE(*pc) && *pc != ';'; pc++)      ;    *pc = '\0';    ct->subtype = safe_strdup (subtype);  }  /* Finally, get the major type */  ct->type = mutt_check_mime_type (s);#ifdef SUN_ATTACHMENT  if (ascii_strcasecmp ("x-sun-attachment", s) == 0)      ct->subtype = safe_strdup ("x-sun-attachment");#endif  if (ct->type == TYPEOTHER)  {    ct->xtype = safe_strdup (s);  }  if (ct->subtype == NULL)  {    /* Some older non-MIME mailers (i.e., mailtool, elm) have a content-type     * field, so we can attempt to convert the type to BODY here.     */    if (ct->type == TYPETEXT)      ct->subtype = safe_strdup ("plain");    else if (ct->type == TYPEAUDIO)      ct->subtype = safe_strdup ("basic");    else if (ct->type == TYPEMESSAGE)      ct->subtype = safe_strdup ("rfc822");    else if (ct->type == TYPEOTHER)    {      char buffer[SHORT_STRING];      ct->type = TYPEAPPLICATION;      snprintf (buffer, sizeof (buffer), "x-%s", s);      ct->subtype = safe_strdup (buffer);    }    else      ct->subtype = safe_strdup ("x-unknown");  }  /* Default character set for text types. */  if (ct->type == TYPETEXT)  {    if (!(pc = mutt_get_parameter ("charset", ct->parameter)))      mutt_set_parameter ("charset", "us-ascii", &ct->parameter);  }}static void parse_content_disposition (char *s, BODY *ct){  PARAMETER *parms;  if (!ascii_strncasecmp ("inline", s, 6))    ct->disposition = DISPINLINE;  else if (!ascii_strncasecmp ("form-data", s, 9))    ct->disposition = DISPFORMDATA;  else    ct->disposition = DISPATTACH;  /* Check to see if a default filename was given */  if ((s = strchr (s, ';')) != NULL)  {    s++;    SKIPWS (s);    if ((s = mutt_get_parameter ("filename", (parms = parse_parameters (s)))) != 0)      mutt_str_replace (&ct->filename, s);    if ((s = mutt_get_parameter ("name", parms)) != 0)      ct->form_name = safe_strdup (s);    mutt_free_parameter (&parms);  }}/* args: *	fp	stream to read from * *	digest	1 if reading subparts of a multipart/digest, 0 *		otherwise */BODY *mutt_read_mime_header (FILE *fp, int digest){  BODY *p = mutt_new_body();  char *c;  char *line = safe_malloc (LONG_STRING);  size_t linelen = LONG_STRING;    p->hdr_offset  = ftello (fp);  p->encoding    = ENC7BIT; /* default from RFC1521 */  p->type        = digest ? TYPEMESSAGE : TYPETEXT;  p->disposition = DISPINLINE;    while (*(line = mutt_read_rfc822_line (fp, line, &linelen)) != 0)  {    /* Find the value of the current header */    if ((c = strchr (line, ':')))    {      *c = 0;      c++;      SKIPWS (c);      if (!*c)      {	dprint (1, (debugfile, "mutt_read_mime_header(): skipping empty header field: %s\n", line));	continue;      }    }    else    {      dprint (1, (debugfile, "read_mime_header: bogus MIME header: %s\n", line));      break;    }    if (!ascii_strncasecmp ("content-", line, 8))    {      if (!ascii_strcasecmp ("type", line + 8))	mutt_parse_content_type (c, p);      else if (!ascii_strcasecmp ("transfer-encoding", line + 8))	p->encoding = mutt_check_encoding (c);      else if (!ascii_strcasecmp ("disposition", line + 8))	parse_content_disposition (c, p);      else if (!ascii_strcasecmp ("description", line + 8))      {	mutt_str_replace (&p->description, c);	rfc2047_decode (&p->description);      }    } #ifdef SUN_ATTACHMENT    else if (!ascii_strncasecmp ("x-sun-", line, 6))    {      if (!ascii_strcasecmp ("data-type", line + 6))        mutt_parse_content_type (c, p);      else if (!ascii_strcasecmp ("encoding-info", line + 6))        p->encoding = mutt_check_encoding (c);      else if (!ascii_strcasecmp ("content-lines", line + 6))        mutt_set_parameter ("content-lines", c, &(p->parameter));      else if (!ascii_strcasecmp ("data-description", line + 6))      {	mutt_str_replace (&p->description, c);        rfc2047_decode (&p->description);      }    }#endif  }  p->offset = ftello (fp); /* Mark the start of the real data */  if (p->type == TYPETEXT && !p->subtype)    p->subtype = safe_strdup ("plain");  else if (p->type == TYPEMESSAGE && !p->subtype)    p->subtype = safe_strdup ("rfc822");  FREE (&line);  return (p);}void mutt_parse_part (FILE *fp, BODY *b){  char *bound = 0;  switch (b->type)  {    case TYPEMULTIPART:#ifdef SUN_ATTACHMENT      if ( !ascii_strcasecmp (b->subtype, "x-sun-attachment") )          bound = "--------";      else#endif          bound = mutt_get_parameter ("boundary", b->parameter);      fseeko (fp, b->offset, SEEK_SET);      b->parts =  mutt_parse_multipart (fp, bound, 					b->offset + b->length,					ascii_strcasecmp ("digest", b->subtype) == 0);      break;    case TYPEMESSAGE:      if (b->subtype)      {	fseeko (fp, b->offset, SEEK_SET);	if (mutt_is_message_type(b->type, b->subtype))	  b->parts = mutt_parse_messageRFC822 (fp, b);	else if (ascii_strcasecmp (b->subtype, "external-body") == 0)	  b->parts = mutt_read_mime_header (fp, 0);	else	  return;      }      break;    default:      return;  }  /* try to recover from parsing error */  if (!b->parts)  {    b->type = TYPETEXT;

⌨️ 快捷键说明

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