?? rfc822.c
字號(hào):
/* * Program: RFC-822 routines (originally from SMTP) * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 27 July 1988 * Last Edited: 13 July 1999 * * Sponsorship: The original version of this work 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 National * Institutes of Health under grant number RR-00785. * * Original version Copyright 1988 by The Leland Stanford Junior University * Copyright 1999 by the University of Washington * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notices appear in all copies and that both the * above copyright notices and this permission notice appear in supporting * documentation, and that the name of the University of Washington or The * Leland Stanford Junior University not be used in advertising or publicity * pertaining to distribution of the software without specific, written prior * permission. This software is made available "as is", and * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE, * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */#include <ctype.h>#include <stdio.h>#include <time.h>#include "mail.h"#include "osdep.h"#include "rfc822.h"#include "misc.h"/* RFC-822 static data */char *errhst = ERRHOST; /* syntax error host string *//* 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 */ /* full RFC-822 specials */const char *rspecials = "()<>@,;:\\\"[]."; /* body token specials */const char *tspecials = " ()<>@,;:\\\"[]./?=";/* Once upon a time, CSnet had a mailer which assigned special semantics to * dot in e-mail addresses. For the sake of that mailer, dot was added to * the RFC-822 definition of `specials', even though it had numerous bad side * effects: * 1) It broke mailbox names on systems which had dots in user names, such as * Multics and TOPS-20. RFC-822's syntax rules require that `Admin . MRC' * be considered equivalent to `Admin.MRC'. Fortunately, few people ever * tried this in practice. * 2) It required that all personal names with an initial be quoted, a widely * detested user interface misfeature. * 3) It made the parsing of host names be non-atomic for no good reason. * To work around these problems, the following alternate specials lists are * defined. hspecials and wspecials are used in lieu of rspecials, and * ptspecials are used in lieu of tspecials. These alternate specials lists * make the parser work a lot better in the real world. It ain't politically * correct, but it lets the users get their job done! */ /* parse-word specials */const char *wspecials = " ()<>@,;:\\\"[]"; /* parse-token specials for parsing */const char *ptspecials = " ()<>@,;:\\\"[]/?=";/* RFC822 writing routines *//* Write RFC822 header from message structure * Accepts: scratch buffer to write into * message envelope * message body */void rfc822_header (char *header,ENVELOPE *env,BODY *body){ if (env->remail) { /* if remailing */ long i = strlen (env->remail); strcpy (header,env->remail);/* start with remail header */ /* flush extra blank line */ if (i > 4 && header[i-4] == '\015') header[i-2] = '\0'; } else *header = '\0'; /* else initialize header to null */ rfc822_header_line (&header,"Newsgroups",env,env->newsgroups); rfc822_header_line (&header,"Date",env,env->date); rfc822_address_line (&header,"From",env,env->from); rfc822_address_line (&header,"Sender",env,env->sender); rfc822_address_line (&header,"Reply-To",env,env->reply_to); rfc822_header_line (&header,"Subject",env,env->subject); if (env->bcc && !(env->to || env->cc)) strcat (header,"To: undisclosed recipients: ;\015\012"); rfc822_address_line (&header,"To",env,env->to); rfc822_address_line (&header,"cc",env,env->cc);/* bcc's are never written... * rfc822_address_line (&header,"bcc",env,env->bcc); */ rfc822_header_line (&header,"In-Reply-To",env,env->in_reply_to); rfc822_header_line (&header,"Message-ID",env,env->message_id); rfc822_header_line (&header,"Followup-to",env,env->followup_to); rfc822_header_line (&header,"References",env,env->references); if (body && !env->remail) { /* not if remail or no body structure */ strcat (header,"MIME-Version: 1.0\015\012"); rfc822_write_body_header (&header,body); } strcat (header,"\015\012"); /* write terminating blank line */}/* Write RFC822 address from header line * Accepts: pointer to destination string pointer * pointer to header type * message to interpret * address to interpret */void rfc822_address_line (char **header,char *type,ENVELOPE *env,ADDRESS *adr){ char *s = (*header += strlen (*header)); if (adr) { /* do nothing if no addresses */ if (env && env->remail) strcat (s,"ReSent-"); strcat (s,type); /* write header name */ strcat (s,": "); s = rfc822_write_address_full (s + strlen (s),adr,*header); /* tie off header line */ *s++ = '\015'; *s++ = '\012'; *s = '\0'; *header = s; /* set return value */ }}/* Write RFC822 text from header line * Accepts: pointer to destination string pointer * pointer to header type * message to interpret * pointer to text */void rfc822_header_line (char **header,char *type,ENVELOPE *env,char *text){ if (text) sprintf ((*header += strlen (*header)),"%s%s: %s\015\012", env->remail ? "ReSent-" : "",type,text);}/* Write RFC822 address list * Accepts: pointer to destination string * address to interpret * header base if pretty-printing * Returns: end of destination string */ /* RFC822 continuation, must start with CRLF */#define RFC822CONT "\015\012 "char *rfc822_write_address_full (char *dest,ADDRESS *adr,char *base){ long i,n; for (n = 0; adr; adr = adr->next) { if (adr->host) { /* ordinary address? */ if (!(base && n)) { /* only write if exact form or not in group */ /* simple case? */ if (!(adr->personal || adr->adl)) rfc822_address (dest,adr); else { /* no, must use phrase <route-addr> form */ if (adr->personal) rfc822_cat (dest,adr->personal,rspecials); strcat (dest," <"); /* write address delimiter */ rfc822_address (dest,adr); strcat (dest,">"); /* closing delimiter */ } if (adr->next && adr->next->mailbox) strcat (dest,", "); } } else if (adr->mailbox) { /* start of group? */ /* yes, write group name */ rfc822_cat (dest,adr->mailbox,rspecials); strcat (dest,": "); /* write group identifier */ n++; /* in a group */ } else if (n) { /* must be end of group (but be paranoid) */ strcat (dest,";"); /* no longer in that group */ if (!--n && adr->next && adr->next->mailbox) strcat (dest,", "); } i = strlen (dest); /* length of what we just wrote */ /* write continuation if doesn't fit */ if (base && (dest > (base + 4)) && ((dest + i) > (base + 78))) { memmove (dest + sizeof (RFC822CONT) - 1,dest,i + 1); memcpy (dest,RFC822CONT,sizeof (RFC822CONT) - 1); base = dest + 2; /* new base */ dest += i + sizeof (RFC822CONT) - 1; } else dest += i; /* new end of string */ } return dest; /* return end of string */}/* Write RFC822 route-address to string * Accepts: pointer to destination string * address to interpret */void rfc822_address (char *dest,ADDRESS *adr){ if (adr && adr->host) { /* no-op if no address */ if (adr->adl) { /* have an A-D-L? */ strcat (dest,adr->adl); strcat (dest,":"); } /* write mailbox name */ rfc822_cat (dest,adr->mailbox,wspecials); if (*adr->host != '@') { /* unless null host (HIGHLY discouraged!) */ strcat (dest,"@"); /* host delimiter */ strcat (dest,adr->host); /* write host name */ } }}/* Concatenate RFC822 string * Accepts: pointer to destination string * pointer to string to concatenate * list of special characters */void rfc822_cat (char *dest,char *src,const char *specials){ char *s; if (strpbrk (src,specials)) { /* any specials present? */ strcat (dest,"\""); /* opening quote */ /* truly bizarre characters in there? */ while (s = strpbrk (src,"\\\"")) { strncat (dest,src,s-src); /* yes, output leader */ strcat (dest,"\\"); /* quoting */ strncat (dest,s,1); /* output the bizarre character */ src = ++s; /* continue after the bizarre character */ } if (*src) strcat (dest,src);/* output non-bizarre string */ strcat (dest,"\""); /* closing quote */ } else strcat (dest,src); /* otherwise it's the easy case */}/* Write body content header * Accepts: pointer to destination string pointer * pointer to body to interpret */void rfc822_write_body_header (char **dst,BODY *body){ char *s; STRINGLIST *stl; PARAMETER *param = body->parameter; sprintf (*dst += strlen (*dst),"Content-Type: %s",body_types[body->type]); s = body->subtype ? body->subtype : rfc822_default_subtype (body->type); sprintf (*dst += strlen (*dst),"/%s",s); if (param) do { sprintf (*dst += strlen (*dst),"; %s=",param->attribute); rfc822_cat (*dst,param->value,tspecials); } while (param = param->next); else if (body->type == TYPETEXT) strcat (*dst,"; CHARSET=US-ASCII"); strcpy (*dst += strlen (*dst),"\015\012"); if (body->encoding) /* note: encoding 7BIT never output! */ sprintf (*dst += strlen (*dst),"Content-Transfer-Encoding: %s\015\012", body_encodings[body->encoding]); if (body->id) sprintf (*dst += strlen (*dst),"Content-ID: %s\015\012", body->id); if (body->description) sprintf (*dst += strlen (*dst),"Content-Description: %s\015\012", body->description); if (body->md5) sprintf (*dst += strlen (*dst),"Content-MD5: %s\015\012",body->md5); if (stl = body->language) { strcpy (*dst += strlen (*dst),"Content-Language: "); do { rfc822_cat (*dst,(char *) stl->text.data,tspecials); if (stl = stl->next) strcat (*dst += strlen (*dst),", "); } while (stl); strcpy (*dst += strlen (*dst),"\015\012"); } if (body->disposition.type) { sprintf (*dst += strlen (*dst),"Content-Disposition: %s", body->disposition.type); if (param = body->disposition.parameter) do { sprintf (*dst += strlen (*dst),"; %s=",param->attribute); rfc822_cat (*dst,param->value,tspecials); } while (param = param->next); strcpy (*dst += strlen (*dst),"\015\012"); }}/* 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"; }}/* RFC822 parsing routines *//* Parse an RFC822 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
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -