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

📄 rfc822.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 5 页
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	RFC 2822 and MIME routines * * Author:	Mark Crispin *		UW Technology *		University of Washington *		Seattle, WA  98195 *		Internet: MRC@Washington.EDU * * Date:	27 July 1988 * Last Edited:	14 May 2008 * * This original version of this file is * Copyright 1988 Stanford University * and was developed in the Symbolic Systems Resources Group of the Knowledge * Systems Laboratory at Stanford University in 1987-88, and was funded by the * Biomedical Research Technology Program of the NationalInstitutes of Health * under grant number RR-00785. */#include <ctype.h>#include <stdio.h>#include <time.h>#include "c-client.h"/* Support for deprecated features in earlier specifications.  Note that this * module follows RFC 2822, and all use of "rfc822" in function names is * for compatibility.  Only the code identified by the conditionals below * follows the earlier documents. */#define RFC733 1		/* parse "at" */#define RFC822 0		/* generate A-D-L (MUST be 0 for 2822) *//* RFC-822 static data */#define RFC822CONT "    "	/* RFC 2822 continuation */				/* should have been "Remailed-" */#define RESENTPREFIX "ReSent-"static char *resentprefix = RESENTPREFIX;				/* syntax error host string */static const char *errhst = ERRHOST;/* Body formats constant strings, must match definitions in mail.h */char *body_types[TYPEMAX+1] = {  "TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO",  "MODEL", "X-UNKNOWN"};char *body_encodings[ENCMAX+1] = {  "7BIT", "8BIT", "BINARY", "BASE64", "QUOTED-PRINTABLE", "X-UNKNOWN"};/* Token delimiting special characters */				/* RFC 2822 specials */const char *specials = " ()<>@,;:\\\"[].\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177";				/* RFC 2822 phrase specials (no space) */const char *rspecials = "()<>@,;:\\\"[].\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177";				/* RFC 2822 dot-atom specials (no dot) */const char *wspecials = " ()<>@,;:\\\"[]\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177";				/* RFC 2045 MIME body token specials */const char *tspecials = " ()<>@,;:\\\"[]/?=\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177";/* Subtype defaulting (a no-no, but regretably necessary...) * Accepts: type code * Returns: default subtype name */char *rfc822_default_subtype (unsigned short type){  switch (type) {  case TYPETEXT:		/* default is TEXT/PLAIN */    return "PLAIN";  case TYPEMULTIPART:		/* default is MULTIPART/MIXED */    return "MIXED";  case TYPEMESSAGE:		/* default is MESSAGE/RFC822 */    return "RFC822";  case TYPEAPPLICATION:		/* default is APPLICATION/OCTET-STREAM */    return "OCTET-STREAM";  case TYPEAUDIO:		/* default is AUDIO/BASIC */    return "BASIC";  default:			/* others have no default subtype */    return "UNKNOWN";  }}/* RFC 2822 parsing routines *//* Parse an RFC 2822 message * Accepts: pointer to return envelope *	    pointer to return body *	    pointer to header *	    header byte count *	    pointer to body stringstruct *	    pointer to local host name *	    recursion depth *	    source driver flags */void rfc822_parse_msg_full (ENVELOPE **en,BODY **bdy,char *s,unsigned long i,			    STRING *bs,char *host,unsigned long depth,			    unsigned long flags){  char c,*t,*d;  char *tmp = (char *) fs_get ((size_t) i + 100);  ENVELOPE *env = (*en = mail_newenvelope ());  BODY *body = bdy ? (*bdy = mail_newbody ()) : NIL;  long MIMEp = -1;		/* flag that MIME semantics are in effect */  parseline_t pl = (parseline_t) mail_parameters (NIL,GET_PARSELINE,NIL);  if (!host) host = BADHOST;	/* make sure that host is non-null */  while (i && *s != '\n') {	/* until end of header */    t = tmp;			/* initialize buffer pointer */    c = ' ';			/* and previous character */    while (i && c) {		/* collect text until logical end of line */      switch (c = *s++) {	/* slurp a character */      case '\015':		/* return, possible end of logical line */	if (*s == '\n') break;	/* ignore if LF follows */      case '\012':		/* LF, possible end of logical line */				/* tie off unless next line starts with WS */	if (*s != ' ' && *s != '\t') *t++ = c = '\0';	break;      case '\t':		/* tab */	*t++ = ' ';		/* coerce to space */	break;      default:			/* all other characters */	*t++ = c;		/* insert the character into the line */	break;      }      if (!--i) *t++ = '\0';	/* see if end of header */    }				/* find header item type */    if (t = d = strchr (tmp,':')) {      *d++ = '\0';		/* tie off header item, point at its data */      while (*d == ' ') d++;	/* flush whitespace */      while ((tmp < t--) && (*t == ' ')) *t = '\0';      ucase (tmp);		/* coerce to uppercase */				/* external callback */      if (pl) (*pl) (env,tmp,d,host);      switch (*tmp) {		/* dispatch based on first character */      case '>':			/* possible >From: */	if (!strcmp (tmp+1,"FROM")) rfc822_parse_adrlist (&env->from,d,host);	break;      case 'B':			/* possible bcc: */	if (!strcmp (tmp+1,"CC")) rfc822_parse_adrlist (&env->bcc,d,host);	break;      case 'C':			/* possible cc: or Content-<mumble>*/	if (!strcmp (tmp+1,"C")) rfc822_parse_adrlist (&env->cc,d,host);	else if ((tmp[1] == 'O') && (tmp[2] == 'N') && (tmp[3] == 'T') &&		 (tmp[4] == 'E') && (tmp[5] == 'N') && (tmp[6] == 'T') &&		 (tmp[7] == '-') && body)	  switch (MIMEp) {	  case -1:		/* unknown if MIME or not */	    if (!(MIMEp =	/* see if MIME-Version header exists */		  search ((unsigned char *) s-1,i,			  (unsigned char *)"\012MIME-Version",(long) 13))) {#if 1	      /* This is a disgusting kludge, and most of the messages which	       * benefit from it are spam.	       */	      if (!strcmp (tmp+8,"TRANSFER-ENCODING") ||		  (!strcmp (tmp+8,"TYPE") && strchr (d,'/'))) {		MM_LOG ("Warning: MIME header encountered in non-MIME message",			PARSE);		MIMEp = 1;	/* declare MIME now */	      }	      else#endif		break;		/* non-MIME message */	    }	  case T:		/* definitely MIME */	    rfc822_parse_content_header (body,tmp+8,d);	  }	break;      case 'D':			/* possible Date: */	if (!env->date && !strcmp (tmp+1,"ATE")) env->date = cpystr (d);	break;      case 'F':			/* possible From: */	if (!strcmp (tmp+1,"ROM")) rfc822_parse_adrlist (&env->from,d,host);	else if (!strcmp (tmp+1,"OLLOWUP-TO")) {	  t = env->followup_to = (char *) fs_get (1 + strlen (d));	  while (c = *d++) if (c != ' ') *t++ = c;	  *t++ = '\0';	}	break;      case 'I':			/* possible In-Reply-To: */	if (!env->in_reply_to && !strcmp (tmp+1,"N-REPLY-TO"))	  env->in_reply_to = cpystr (d);	break;      case 'M':			/* possible Message-ID: or MIME-Version: */	if (!env->message_id && !strcmp (tmp+1,"ESSAGE-ID"))	  env->message_id = cpystr (d);	else if (!strcmp (tmp+1,"IME-VERSION")) {				/* tie off at end of phrase */	  if (t = rfc822_parse_phrase (d)) *t = '\0';	  rfc822_skipws (&d);	/* skip whitespace */				/* known version? */	  if (strcmp (d,"1.0") && strcmp (d,"RFC-XXXX"))	    MM_LOG ("Warning: message has unknown MIME version",PARSE);	  MIMEp = T;		/* note that we are MIME */	}	break;      case 'N':			/* possible Newsgroups: */	if (!env->newsgroups && !strcmp (tmp+1,"EWSGROUPS")) {	  t = env->newsgroups = (char *) fs_get (1 + strlen (d));	  while (c = *d++) if (c != ' ') *t++ = c;	  *t++ = '\0';	}	break;      case 'R':			/* possible Reply-To: */	if (!strcmp (tmp+1,"EPLY-TO"))	  rfc822_parse_adrlist (&env->reply_to,d,host);	else if (!env->references && !strcmp (tmp+1,"EFERENCES"))	  env->references = cpystr (d);	break;      case 'S':			/* possible Subject: or Sender: */	if (!env->subject && !strcmp (tmp+1,"UBJECT"))	  env->subject = cpystr (d);	else if (!strcmp (tmp+1,"ENDER"))	  rfc822_parse_adrlist (&env->sender,d,host);	break;      case 'T':			/* possible To: */	if (!strcmp (tmp+1,"O")) rfc822_parse_adrlist (&env->to,d,host);	break;      default:	break;      }    }  }  fs_give ((void **) &tmp);	/* done with scratch buffer */				/* default Sender: and Reply-To: to From: */  if (!env->sender) env->sender = rfc822_cpy_adr (env->from);  if (!env->reply_to) env->reply_to = rfc822_cpy_adr (env->from);				/* now parse the body */  if (body) rfc822_parse_content (body,bs,host,depth,flags);}/* Parse a message body content * Accepts: pointer to body structure *	    body string *	    pointer to local host name *	    recursion depth *	    source driver flags */void rfc822_parse_content (BODY *body,STRING *bs,char *h,unsigned long depth,			   unsigned long flags){  char c,c1,*s,*s1;  int f;  unsigned long i,j,k,m;  PARAMETER *param;  PART *part = NIL;  if (depth > MAXMIMEDEPTH) {	/* excessively deep recursion? */    body->type = TYPETEXT;	/* yes, probably a malicious MIMEgram */    MM_LOG ("Ignoring excessively deep MIME recursion",PARSE);  }  if (!body->subtype)		/* default subtype if still unknown */    body->subtype = cpystr (rfc822_default_subtype (body->type));				/* note offset and sizes */  body->contents.offset = GETPOS (bs);				/* note internal body size in all cases */  body->size.bytes = body->contents.text.size = i = SIZE (bs);  if (!(flags & DR_CRLF)) body->size.bytes = strcrlflen (bs);  switch (body->type) {		/* see if anything else special to do */  case TYPETEXT:		/* text content */    if (!body->parameter) {	/* no parameters set */      body->parameter = mail_newbody_parameter ();      body->parameter->attribute = cpystr ("CHARSET");      while (i--) {		/* count lines and guess charset */	c = SNX (bs);		/* get current character */				/* charset still unknown? */	if (!body->parameter->value) {	  if ((c == I2C_ESC) && (i && i--) && ((c = SNX (bs)) == I2C_MULTI) &&	      (i && i--) && (((c = SNX (bs)) == I2CS_94x94_JIS_NEW) ||			     (c == I2CS_94x94_JIS_OLD)))	    body->parameter->value = cpystr ("ISO-2022-JP");	  else if (c & 0x80) body->parameter->value = cpystr ("X-UNKNOWN");	}	if (c == '\n') body->size.lines++;      }				/* 7-bit content */      if (!body->parameter->value) switch (body->encoding) {      case ENC7BIT:		/* unadorned 7-bit */      case ENC8BIT:		/* unadorned 8-bit (but 7-bit content) */      case ENCBINARY:		/* binary (but 7-bit content( */	body->parameter->value = cpystr ("US-ASCII");	break;      default:			/* QUOTED-PRINTABLE, BASE64, etc. */	body->parameter->value = cpystr ("X-UNKNOWN");	break;      }    }				/* just count lines */    else while (i--) if ((SNX (bs)) == '\n') body->size.lines++;    break;  case TYPEMESSAGE:		/* encapsulated message */				/* encapsulated RFC-822 message? */    if (!strcmp (body->subtype,"RFC822")) {      body->nested.msg = mail_newmsg ();      switch (body->encoding) {	/* make sure valid encoding */      case ENC7BIT:		/* these are valid nested encodings */      case ENC8BIT:      case ENCBINARY:	break;      default:	MM_LOG ("Ignoring nested encoding of message contents",PARSE);      }				/* hunt for blank line */      for (c = '\012',j = 0; (i > j) && ((c != '\012') || (CHR(bs) != '\012'));	   j++) if ((c1 = SNX (bs)) != '\015') c = c1;      if (i > j) {		/* unless no more text */	c1 = SNX (bs);		/* body starts here */	j++;			/* advance count */      }				/* note body text offset and header size */      body->nested.msg->header.text.size = j;      body->nested.msg->text.text.size = body->contents.text.size - j;      body->nested.msg->text.offset = GETPOS (bs);      body->nested.msg->full.offset = body->nested.msg->header.offset =	body->contents.offset;      body->nested.msg->full.text.size = body->contents.text.size;				/* copy header string */      SETPOS (bs,body->contents.offset);      s = (char *) fs_get ((size_t) j + 1);      for (s1 = s,k = j; k--; *s1++ = SNX (bs));      s[j] = '\0';		/* tie off string (not really necessary) */				/* now parse the body */      rfc822_parse_msg_full (&body->nested.msg->env,&body->nested.msg->body,s,			     j,bs,h,depth+1,flags);      fs_give ((void **) &s);	/* free header string */				/* restore position */      SETPOS (bs,body->contents.offset);    }				/* count number of lines */    while (i--) if (SNX (bs) == '\n') body->size.lines++;    break;  case TYPEMULTIPART:		/* multiple parts */    switch (body->encoding) {	/* make sure valid encoding */    case ENC7BIT:		/* these are valid nested encodings */    case ENC8BIT:    case ENCBINARY:      break;    default:      MM_LOG ("Ignoring nested encoding of multipart contents",PARSE);    }				/* remember if digest */    f = !strcmp (body->subtype,"DIGEST");				/* find cookie */    for (s1 = NIL,param = body->parameter; param && !s1; param = param->next)      if (!strcmp (param->attribute,"BOUNDARY")) s1 = param->value;    if (!s1) s1 = "-";		/* yucky default */    j = strlen (s1) + 2;	/* length of cookie and header */    c = '\012';			/* initially at beginning of line */    while (i > j) {		/* examine data */      if (m = GETPOS (bs)) m--;	/* get position in front of character */      switch (c) {		/* examine each line */

⌨️ 快捷键说明

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