📄 rfc822.c
字号:
/* Parse RFC 2822 word * Accepts: string pointer * delimiter (or NIL for phrase word parsing) * Returns: pointer to end of word */char *rfc822_parse_word (char *s,const char *delimiters){ char *st,*str; if (!s) return NIL; /* no string */ rfc822_skipws (&s); /* flush leading whitespace */ if (!*s) return NIL; /* empty string */ str = s; /* hunt pointer for strpbrk */ while (T) { /* look for delimiter, return if none */ if (!(st = strpbrk (str,delimiters ? delimiters : wspecials))) return str + strlen (str); /* ESC in phrase */ if (!delimiters && (*st == I2C_ESC)) { str = ++st; /* always skip past ESC */ switch (*st) { /* special hack for RFC 1468 (ISO-2022-JP) */ case I2C_MULTI: /* multi byte sequence */ switch (*++st) { case I2CS_94x94_JIS_OLD:/* old JIS (1978) */ case I2CS_94x94_JIS_NEW:/* new JIS (1983) */ str = ++st; /* skip past the shift to JIS */ while (st = strchr (st,I2C_ESC)) if ((*++st == I2C_G0_94) && ((st[1] == I2CS_94_ASCII) || (st[1] == I2CS_94_JIS_ROMAN) || (st[1] == I2CS_94_JIS_BUGROM))) { str = st += 2; /* skip past the shift back to ASCII */ break; } /* eats entire text if no shift back */ if (!st || !*st) return str + strlen (str); } break; case I2C_G0_94: /* single byte sequence */ switch (st[1]) { case I2CS_94_ASCII: /* shift to ASCII */ case I2CS_94_JIS_ROMAN: /* shift to JIS-Roman */ case I2CS_94_JIS_BUGROM:/* old buggy definition of JIS-Roman */ str = st + 2; /* skip past the shift */ break; } } } else switch (*st) { /* dispatch based on delimiter */ case '"': /* quoted string */ /* look for close quote */ while (*++st != '"') switch (*st) { case '\0': /* unbalanced quoted string */ return NIL; /* sick sick sick */ case '\\': /* quoted character */ if (!*++st) return NIL; /* skip the next character */ default: /* ordinary character */ break; /* no special action */ } str = ++st; /* continue parse */ break; case '\\': /* quoted character */ /* This is wrong; a quoted-pair can not be part of a word. However, * domain-literal is parsed as a word and quoted-pairs can be used * *there*. Either way, it's pretty pathological. */ if (st[1]) { /* not on NUL though... */ str = st + 2; /* skip quoted character and go on */ break; } default: /* found a word delimiter */ return (st == s) ? NIL : st; } }}/* Copy an RFC 2822 format string * Accepts: string * Returns: copy of string */char *rfc822_cpy (char *src){ /* copy and unquote */ return rfc822_quote (cpystr (src));}/* Unquote an RFC 2822 format string * Accepts: string * Returns: string */char *rfc822_quote (char *src){ char *ret = src; if (strpbrk (src,"\\\"")) { /* any quoting in string? */ char *dst = ret; while (*src) { /* copy string */ if (*src == '\"') src++; /* skip double quote entirely */ else { if (*src == '\\') src++;/* skip over single quote, copy next always */ *dst++ = *src++; /* copy character */ } } *dst = '\0'; /* tie off string */ } return ret; /* return our string */}/* Copy address list * Accepts: address list * Returns: address list */ADDRESS *rfc822_cpy_adr (ADDRESS *adr){ ADDRESS *dadr; ADDRESS *ret = NIL; ADDRESS *prev = NIL; while (adr) { /* loop while there's still an MAP adr */ dadr = mail_newaddr (); /* instantiate a new address */ if (!ret) ret = dadr; /* note return */ if (prev) prev->next = dadr;/* tie on to the end of any previous */ dadr->personal = cpystr (adr->personal); dadr->adl = cpystr (adr->adl); dadr->mailbox = cpystr (adr->mailbox); dadr->host = cpystr (adr->host); prev = dadr; /* this is now the previous */ adr = adr->next; /* go to next address in list */ } return (ret); /* return the MTP address list */}/* Skips RFC 2822 whitespace * Accepts: pointer to string pointer */void rfc822_skipws (char **s){ while (T) switch (**s) { case ' ': case '\t': case '\015': case '\012': ++*s; /* skip all forms of LWSP */ break; case '(': /* start of comment */ if (rfc822_skip_comment (s,(long) NIL)) break; default: return; /* end of whitespace */ }}/* Skips RFC 2822 comment * Accepts: pointer to string pointer * trim flag * Returns: pointer to first non-blank character of comment */char *rfc822_skip_comment (char **s,long trim){ char *ret,tmp[MAILTMPLEN]; char *s1 = *s; char *t = NIL; /* skip past whitespace */ for (ret = ++s1; *ret == ' '; ret++); do switch (*s1) { /* get character of comment */ case '(': /* nested comment? */ if (!rfc822_skip_comment (&s1,(long) NIL)) return NIL; t = --s1; /* last significant char at end of comment */ break; case ')': /* end of comment? */ *s = ++s1; /* skip past end of comment */ if (trim) { /* if level 0, must trim */ if (t) t[1] = '\0'; /* tie off comment string */ else *ret = '\0'; /* empty comment */ } return ret; case '\\': /* quote next character? */ if (*++s1) { /* next character non-null? */ t = s1; /* update last significant character pointer */ break; /* all OK */ } case '\0': /* end of string */ sprintf (tmp,"Unterminated comment: %.80s",*s); MM_LOG (tmp,PARSE); **s = '\0'; /* nuke duplicate messages in case reparse */ return NIL; /* this is wierd if it happens */ case ' ': /* whitespace isn't significant */ break; default: /* random character */ t = s1; /* update last significant character pointer */ break; } while (s1++); return NIL; /* impossible, but pacify lint et al */}/* Buffered output routines *//* Output character to buffer * Accepts: buffer * character to write * Returns: T if success, NIL if error */static long rfc822_output_char (RFC822BUFFER *buf,int c){ if ((buf->cur == buf->end) && !rfc822_output_flush (buf)) return NIL; *buf->cur++ = c; /* add character, soutr buffer if full */ return (buf->cur == buf->end) ? rfc822_output_flush (buf) : LONGT;}/* Output data to buffer * Accepts: buffer * data to write * size of data * Returns: T if success, NIL if error */static long rfc822_output_data (RFC822BUFFER *buf,char *string,long len){ while (len) { /* until request satified */ long i; if (i = min (len,buf->end - buf->cur)) { memcpy (buf->cur,string,i); buf->cur += i; /* blat data */ string += i; len -= i; } /* soutr buffer now if full */ if ((len || (buf->cur == buf->end)) && !rfc822_output_flush (buf)) return NIL; } return LONGT;}/* Output string to buffer * Accepts: buffer * string to write * Returns: T if success, NIL if error */static long rfc822_output_string (RFC822BUFFER *buf,char *string){ return rfc822_output_data (buf,string,strlen (string));}/* Flush buffer * Accepts: buffer * I/O routine * stream for I/O routine * Returns: T if success, NIL if error */long rfc822_output_flush (RFC822BUFFER *buf){ *buf->cur = '\0'; /* tie off buffer at this point */ return (*buf->f) (buf->s,buf->cur = buf->beg);}/* Message writing routines *//* Output RFC 822 message * Accepts: temporary buffer as a SIZEDTEXT * envelope * body * I/O routine * stream for I/O routine * non-zero if 8-bit output desired * Returns: T if successful, NIL if failure * * This routine always uses standard specials for phrases and does not write * bcc entries, since it is called from the SMTP and NNTP routines. If you * need to do something different you need to arm an rfc822outfull_t and/or * rfc822out_t function. */long rfc822_output_full (RFC822BUFFER *buf,ENVELOPE *env,BODY *body,long ok8){ rfc822outfull_t r822of = (rfc822outfull_t) mail_parameters (NIL,GET_RFC822OUTPUTFULL,NIL); rfc822out_t r822o = (rfc822out_t) mail_parameters (NIL,GET_RFC822OUTPUT,NIL); /* call external RFC 2822 output generator */ if (r822of) return (*r822of) (buf,env,body,ok8); else if (r822o) return (*r822o) (buf->cur,env,body,buf->f,buf->s,ok8); /* encode body as necessary */ if (ok8) rfc822_encode_body_8bit (env,body); else rfc822_encode_body_7bit (env,body); /* output header and body */ return rfc822_output_header (buf,env,body,NIL,NIL) && rfc822_output_text (buf,body) && rfc822_output_flush (buf);}/* Output RFC 822 header * Accepts: buffer * envelope * body * non-standard specials to be used for phrases if non-NIL * flags (non-zero to include bcc * Returns: T if success, NIL if failure */long rfc822_output_header (RFC822BUFFER *buf,ENVELOPE *env,BODY *body, const char *specials,long flags){ long i = env->remail ? strlen (env->remail) : 0; return /* write header */ (!i || /* snip extra CRLF from remail header */ rfc822_output_data (buf,env->remail, ((i > 4) && (env->remail[i-4] == '\015')) ? i - 2 : i)) && rfc822_output_header_line (buf,"Newsgroups",i,env->newsgroups) && rfc822_output_header_line (buf,"Date",i,env->date) && rfc822_output_address_line (buf,"From",i,env->from,specials) && rfc822_output_address_line (buf,"Sender",i,env->sender,specials) && rfc822_output_address_line (buf,"Reply-To",i,env->reply_to,specials) && rfc822_output_header_line (buf,"Subject",i,env->subject) && ((env->bcc && !(env->to || env->cc)) ? rfc822_output_string (buf,"To: undisclosed recipients: ;\015\012") : LONGT) && rfc822_output_address_line (buf,"To",i,env->to,specials) && rfc822_output_address_line (buf,"cc",i,env->cc,specials) && (flags ? rfc822_output_address_line (buf,"bcc",i,env->bcc,specials) : T) && rfc822_output_header_line (buf,"In-Reply-To",i,env->in_reply_to) && rfc822_output_header_line (buf,"Message-ID",i,env->message_id) && rfc822_output_header_line (buf,"Followup-to",i,env->followup_to) && rfc822_output_header_line (buf,"References",i,env->references) && (env->remail || !body || (rfc822_output_string (buf,"MIME-Version: 1.0\015\012") && rfc822_output_body_header (buf,body))) && /* write terminating blank line */ rfc822_output_string (buf,"\015\012");}/* Output RFC 2822 header text line * Accepts: buffer * pointer to header type * non-NIL if resending * pointer to text * Returns: T if success, NIL if failure */long rfc822_output_header_line (RFC822BUFFER *buf,char *type,long resent, char *text){ return !text || ((resent ? rfc822_output_string (buf,resentprefix) : LONGT) && rfc822_output_string (buf,type) && rfc822_output_string (buf,": ") && rfc822_output_string (buf,text) && rfc822_output_string (buf,"\015\012"));}/* Output RFC 2822 header address line * Accepts: buffer * pointer to header type * non-NIL if resending * address(s) to interpret * non-standard specials to be used for phrases if non-NIL * Returns: T if success, NIL if failure */long rfc822_output_address_line (RFC822BUFFER *buf,char *type,long resent, ADDRESS *adr,const char *specials){ long pretty = strlen (type); return !adr || ((resent ? rfc822_output_string (buf,resentprefix) : LONGT) && rfc822_output_data (buf,type,pretty) && rfc822_output_string (buf,": ") && rfc822_output_address_list (buf,adr, resent ? pretty + sizeof (RESENTPREFIX) - 1 : pretty,specials) && rfc822_output_string (buf,"\015\012"));}/* Output RFC 2822 address list * Accepts: buffer * pointer to address list * non-zero if pretty-printing * non-standard specials to be used for phrases if non-NIL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -