📄 rfc822.c
字号:
string = NIL; (adr = mail_newaddr ())->mailbox = cpystr ("INVALID_ADDRESS"); adr->host = cpystr (errhst); if (last) last = last->next = adr; else *lst = last = adr; break; } }}/* Parse RFC 2822 address * Accepts: address list to write to * tail of address list * pointer to input string * default host name * group nesting depth * Returns: new list tail */ADDRESS *rfc822_parse_address (ADDRESS **lst,ADDRESS *last,char **string, char *defaulthost,unsigned long depth){ ADDRESS *adr; if (!*string) return NIL; /* no string */ rfc822_skipws (string); /* skip leading WS */ if (!**string) return NIL; /* empty string */ if (adr = rfc822_parse_group (lst,last,string,defaulthost,depth)) last = adr; /* got an address? */ else if (adr = rfc822_parse_mailbox (string,defaulthost)) { if (!*lst) *lst = adr; /* yes, first time through? */ else last->next = adr; /* no, append to the list */ /* set for subsequent linking */ for (last = adr; last->next; last = last->next); } else if (*string) return NIL; return last;}/* Parse RFC 2822 group * Accepts: address list to write to * pointer to tail of address list * pointer to input string * default host name * group nesting depth */ADDRESS *rfc822_parse_group (ADDRESS **lst,ADDRESS *last,char **string, char *defaulthost,unsigned long depth){ char tmp[MAILTMPLEN]; char *p,*s; ADDRESS *adr; if (depth > MAXGROUPDEPTH) { /* excessively deep recursion? */ MM_LOG ("Ignoring excessively deep group recursion",PARSE); return NIL; /* probably abusive */ } if (!*string) return NIL; /* no string */ rfc822_skipws (string); /* skip leading WS */ if (!**string || /* trailing whitespace or not group */ ((*(p = *string) != ':') && !(p = rfc822_parse_phrase (*string)))) return NIL; s = p; /* end of candidate phrase */ rfc822_skipws (&s); /* find delimiter */ if (*s != ':') return NIL; /* not really a group */ *p = '\0'; /* tie off group name */ p = ++s; /* continue after the delimiter */ rfc822_skipws (&p); /* skip subsequent whitespace */ /* write as address */ (adr = mail_newaddr ())->mailbox = rfc822_cpy (*string); if (!*lst) *lst = adr; /* first time through? */ else last->next = adr; /* no, append to the list */ last = adr; /* set for subsequent linking */ *string = p; /* continue after this point */ while (*string && **string && (**string != ';')) { if (adr = rfc822_parse_address (lst,last,string,defaulthost,depth+1)) { last = adr; /* new tail address */ if (*string) { /* anything more? */ rfc822_skipws (string); /* skip whitespace */ switch (**string) { /* see what follows */ case ',': /* another address? */ ++*string; /* yes, skip past the comma */ case ';': /* end of group? */ case '\0': /* end of string */ break; default: sprintf (tmp,"Unexpected characters after address in group: %.80s", *string); MM_LOG (tmp,PARSE); *string = NIL; /* cancel remainder of parse */ last = last->next = mail_newaddr (); last->mailbox = cpystr ("UNEXPECTED_DATA_AFTER_ADDRESS_IN_GROUP"); last->host = cpystr (errhst); } } } else { /* bogon */ sprintf (tmp,"Invalid group mailbox list: %.80s",*string); MM_LOG (tmp,PARSE); *string = NIL; /* cancel remainder of parse */ (adr = mail_newaddr ())->mailbox = cpystr ("INVALID_ADDRESS_IN_GROUP"); adr->host = cpystr (errhst); last = last->next = adr; } } if (*string) { /* skip close delimiter */ if (**string == ';') ++*string; rfc822_skipws (string); } /* append end of address mark to the list */ last->next = (adr = mail_newaddr ()); last = adr; /* set for subsequent linking */ return last; /* return the tail */}/* Parse RFC 2822 mailbox * Accepts: pointer to string pointer * default host * Returns: address list * * Updates string pointer */ADDRESS *rfc822_parse_mailbox (char **string,char *defaulthost){ ADDRESS *adr = NIL; char *s,*end; parsephrase_t pp = (parsephrase_t) mail_parameters (NIL,GET_PARSEPHRASE,NIL); if (!*string) return NIL; /* no string */ rfc822_skipws (string); /* flush leading whitespace */ if (!**string) return NIL; /* empty string */ if (*(s = *string) == '<') /* note start, handle case of phraseless RA */ adr = rfc822_parse_routeaddr (s,string,defaulthost); /* otherwise, expect at least one word */ else if (end = rfc822_parse_phrase (s)) { if ((adr = rfc822_parse_routeaddr (end,string,defaulthost))) { /* phrase is a personal name */ if (adr->personal) fs_give ((void **) &adr->personal); *end = '\0'; /* tie off phrase */ adr->personal = rfc822_cpy (s); } /* call external phraseparser if phrase only */ else if (pp && rfc822_phraseonly (end) && (adr = (*pp) (s,end,defaulthost))) { *string = end; /* update parse pointer */ rfc822_skipws (string); /* skip WS in the normal way */ } else adr = rfc822_parse_addrspec (s,string,defaulthost); } return adr; /* return the address */}/* Check if address is a phrase only * Accepts: pointer to end of phrase * Returns: T if phrase only, else NIL; */long rfc822_phraseonly (char *end){ while (*end == ' ') ++end; /* call rfc822_skipws() instead?? */ switch (*end) { case '\0': case ',': case ';': return LONGT; /* is a phrase only */ } return NIL; /* something other than phase is here */}/* Parse RFC 2822 route-address * Accepts: string pointer * pointer to string pointer to update * Returns: address * * Updates string pointer */ADDRESS *rfc822_parse_routeaddr (char *string,char **ret,char *defaulthost){ char tmp[MAILTMPLEN]; ADDRESS *adr; char *s,*t,*adl; size_t adllen,i; if (!string) return NIL; rfc822_skipws (&string); /* flush leading whitespace */ /* must start with open broket */ if (*string != '<') return NIL; t = ++string; /* see if A-D-L there */ rfc822_skipws (&t); /* flush leading whitespace */ for (adl = NIL,adllen = 0; /* parse possible A-D-L */ (*t == '@') && (s = rfc822_parse_domain (t+1,&t));) { i = strlen (s) + 2; /* @ plus domain plus delimiter or NUL */ if (adl) { /* have existing A-D-L? */ fs_resize ((void **) &adl,adllen + i); sprintf (adl + adllen - 1,",@%s",s); } /* write initial A-D-L */ else sprintf (adl = (char *) fs_get (i),"@%s",s); adllen += i; /* new A-D-L length */ fs_give ((void **) &s); /* don't need domain any more */ rfc822_skipws (&t); /* skip WS */ if (*t != ',') break; /* put if not comma */ t++; /* skip the comma */ rfc822_skipws (&t); /* skip WS */ } if (adl) { /* got an A-D-L? */ if (*t != ':') { /* make sure syntax good */ sprintf (tmp,"Unterminated at-domain-list: %.80s%.80s",adl,t); MM_LOG (tmp,PARSE); } else string = ++t; /* continue parse from this point */ } /* parse address spec */ if (!(adr = rfc822_parse_addrspec (string,ret,defaulthost))) { if (adl) fs_give ((void **) &adl); return NIL; } if (adl) adr->adl = adl; /* have an A-D-L? */ if (*ret) if (**ret == '>') { /* make sure terminated OK */ ++*ret; /* skip past the broket */ rfc822_skipws (ret); /* flush trailing WS */ if (!**ret) *ret = NIL; /* wipe pointer if at end of string */ return adr; /* return the address */ } sprintf (tmp,"Unterminated mailbox: %.80s@%.80s",adr->mailbox, *adr->host == '@' ? "<null>" : adr->host); MM_LOG (tmp,PARSE); adr->next = mail_newaddr (); adr->next->mailbox = cpystr ("MISSING_MAILBOX_TERMINATOR"); adr->next->host = cpystr (errhst); return adr; /* return the address */}/* Parse RFC 2822 address-spec * Accepts: string pointer * pointer to string pointer to update * default host * Returns: address * * Updates string pointer */ADDRESS *rfc822_parse_addrspec (char *string,char **ret,char *defaulthost){ ADDRESS *adr; char c,*s,*t,*v,*end; if (!string) return NIL; /* no string */ rfc822_skipws (&string); /* flush leading whitespace */ if (!*string) return NIL; /* empty string */ /* find end of mailbox */ if (!(t = rfc822_parse_word (string,wspecials))) return NIL; adr = mail_newaddr (); /* create address block */ c = *t; /* remember delimiter */ *t = '\0'; /* tie off mailbox */ /* copy mailbox */ adr->mailbox = rfc822_cpy (string); *t = c; /* restore delimiter */ end = t; /* remember end of mailbox */ rfc822_skipws (&t); /* skip whitespace */ while (*t == '.') { /* some cretin taking RFC 822 too seriously? */ string = ++t; /* skip past the dot and any WS */ rfc822_skipws (&string); /* get next word of mailbox */ if (t = rfc822_parse_word (string,wspecials)) { end = t; /* remember new end of mailbox */ c = *t; /* remember delimiter */ *t = '\0'; /* tie off word */ s = rfc822_cpy (string); /* copy successor part */ *t = c; /* restore delimiter */ /* build new mailbox */ sprintf (v = (char *) fs_get (strlen (adr->mailbox) + strlen (s) + 2), "%s.%s",adr->mailbox,s); fs_give ((void **) &adr->mailbox); adr->mailbox = v; /* new host name */ rfc822_skipws (&t); /* skip WS after mailbox */ } else { /* barf */ MM_LOG ("Invalid mailbox part after .",PARSE); break; } } t = end; /* remember delimiter in case no host */ rfc822_skipws (&end); /* sniff ahead at what follows */#if RFC733 /* RFC 733 used "at" instead of "@" */ if (((*end == 'a') || (*end == 'A')) && ((end[1] == 't') || (end[1] == 'T')) && ((end[2] == ' ') || (end[2] == '\t') || (end[2] == '\015') || (end[2] == '\012') || (end[2] == '('))) *++end = '@';#endif if (*end != '@') end = t; /* host name missing */ /* otherwise parse host name */ else if (!(adr->host = rfc822_parse_domain (++end,&end))) adr->host = cpystr (errhst); /* default host if missing */ if (!adr->host) adr->host = cpystr (defaulthost); /* try person name in comments if missing */ if (end && !(adr->personal && *adr->personal)) { while (*end == ' ') ++end; /* see if we can find a person name here */ if ((*end == '(') && (s = rfc822_skip_comment (&end,LONGT)) && strlen (s)) adr->personal = rfc822_cpy (s); rfc822_skipws (&end); /* skip any other WS in the normal way */ } /* set return to end pointer */ *ret = (end && *end) ? end : NIL; return adr; /* return the address we got */}/* Parse RFC 2822 domain * Accepts: string pointer * pointer to return end of domain * Returns: domain name or NIL if failure */char *rfc822_parse_domain (char *string,char **end){ char *ret = NIL; char c,*s,*t,*v; rfc822_skipws (&string); /* skip whitespace */ if (*string == '[') { /* domain literal? */ if (!(*end = rfc822_parse_word (string + 1,"]\\"))) MM_LOG ("Empty domain literal",PARSE); else if (**end != ']') MM_LOG ("Unterminated domain literal",PARSE); else { size_t len = ++*end - string; strncpy (ret = (char *) fs_get (len + 1),string,len); ret[len] = '\0'; /* tie off literal */ } } /* search for end of host */ else if (t = rfc822_parse_word (string,wspecials)) { c = *t; /* remember delimiter */ *t = '\0'; /* tie off host */ ret = rfc822_cpy (string); /* copy host */ *t = c; /* restore delimiter */ *end = t; /* remember end of domain */ rfc822_skipws (&t); /* skip WS after host */ while (*t == '.') { /* some cretin taking RFC 822 too seriously? */ string = ++t; /* skip past the dot and any WS */ rfc822_skipws (&string); if (string = rfc822_parse_domain (string,&t)) { *end = t; /* remember new end of domain */ c = *t; /* remember delimiter */ *t = '\0'; /* tie off host */ s = rfc822_cpy (string);/* copy successor part */ *t = c; /* restore delimiter */ /* build new domain */ sprintf (v = (char *) fs_get (strlen (ret) + strlen (s) + 2), "%s.%s",ret,s); fs_give ((void **) &ret); ret = v; /* new host name */ rfc822_skipws (&t); /* skip WS after domain */ } else { /* barf */ MM_LOG ("Invalid domain part after .",PARSE); break; } } } else MM_LOG ("Missing or invalid host name after @",PARSE); return ret;}/* Parse RFC 2822 phrase * Accepts: string pointer * Returns: pointer to end of phrase */char *rfc822_parse_phrase (char *s){ char *curpos; if (!s) return NIL; /* no-op if no string */ /* find first word of phrase */ curpos = rfc822_parse_word (s,NIL); if (!curpos) return NIL; /* no words means no phrase */ if (!*curpos) return curpos; /* check if string ends with word */ s = curpos; /* sniff past the end of this word and WS */ rfc822_skipws (&s); /* skip whitespace */ /* recurse to see if any more */ return (s = rfc822_parse_phrase (s)) ? s : curpos;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -