/* * Parse a source route (at-domain-list) */ static int parseaddr_route(char **inp, char **routep) { int c; char *src = *inp; char *dst; SKIPWHITESPACE(src); *routep = dst = src; for (;;) { c = *src++; if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ',' || c == '@') { *dst++ = c; } else if (c == '.') { if (dst > *routep && dst[-1] != '.') *dst++ = c; } else if (Uisspace(c) || c == '(') { src--; SKIPWHITESPACE(src); } else { while (dst > *routep && (dst[-1] == '.' || dst[-1] == ',' || dst[-1] == '@')) dst--; *dst = '\0'; *inp = src; return c; } } }
/* * Parse an RFC 822 "phrase", stopping at 'specials' */ static int parseaddr_phrase(char **inp, char **phrasep, const char *specials) { int c; char *src = *inp; char *dst; SKIPWHITESPACE(src); *phrasep = dst = src; for (;;) { c = *src++; if (c == '"') { while ((c = *src)) { src++; if (c == '\r' && *src == '\n') { /* CR+LF combination */ src++; if (*src == ' ' || *src == '\t') { /* CR+LF+WSP - folded header field, * unfold it by skipping ONLY the CR+LF */ continue; } /* otherwise we have CR+LF at the end of a header * field, which means we have an unbalanced " */ goto fail; } if (c == '\r' || c == '\n') goto fail; /* invalid chars */ if (c == '"') break; /* end of quoted string */ if (c == '\\') { if (!(c = *src)) goto fail; src++; } *dst++ = c; } if (c != '"') goto fail; /* unbalanced " */ } else if (Uisspace(c) || c == '(') { src--; SKIPWHITESPACE(src); *dst++ = ' '; } else if (!c || strchr(specials, c)) { if (dst > *phrasep && dst[-1] == ' ') dst--; *dst = '\0'; *inp = src; return c; } else { *dst++ = c; } } fail: /* simulate end-of-string */ *phrasep = ""; return 0; }
/* * Parse a domain. If 'commentp' is non-nil, parses any trailing comment. * If the domain is invalid, set invalid to non-zero. */ static int parseaddr_domain(char **inp, char **domainp, char **commentp, int *invalid) { int c; char *src = *inp; char *dst; char *cdst; int comment; if (commentp) *commentp = 0; SKIPWHITESPACE(src); *domainp = dst = src; for (;;) { c = *src++; if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ':') { *dst++ = c; if (commentp) *commentp = 0; } else if (c == '.') { if (dst > *domainp && dst[-1] != '.') *dst++ = c; if (commentp) *commentp = 0; } else if (c == '(') { if (commentp) { *commentp = cdst = src; comment = 1; while (comment && (c = *src)) { src++; if (c == '(') comment++; else if (c == ')') comment--; else if (c == '\\' && (c = *src)) src++; if (comment) *cdst++ = c; } *cdst = '\0'; } else { src--; SKIPWHITESPACE(src); } } else if (c == '@') { /* This domain name is garbage. Continue eating up the characters * until we get to a sane state. */ *invalid = 1; *dst++ = c; if (commentp) *commentp = 0; } else if (!Uisspace(c)) { if (dst > *domainp && dst[-1] == '.') dst--; *dst = '\0'; *inp = src; return c; } } }
/* * Parse a domain. If 'commentp' is non-nil, parses any trailing comment */ static int parseaddr_domain(char **inp, char **domainp, char **commentp) { char c; char *src = *inp; char *dst; char *cdst; int comment; if (commentp) *commentp = 0; SKIPWHITESPACE(src); *domainp = dst = src; for (;;) { c = *src++; if (isalnum((int)(unsigned char)c) || c == '-' || c == '[' || c == ']') { *dst++ = c; if (commentp) *commentp = 0; } else if (c == '.') { if (dst > *domainp && dst[-1] != '.') *dst++ = c; if (commentp) *commentp = 0; } else if (c == '(') { if (commentp) { *commentp = cdst = src; comment = 1; while (comment && (c = *src)) { src++; if (c == '(') comment++; else if (c == ')') comment--; else if (c == '\\' && (c = *src)) src++; if (comment) *cdst++ = c; } *cdst = '\0'; } else { src--; SKIPWHITESPACE(src); } } else if (!isspace((int)(unsigned char)c)) { if (dst > *domainp && dst[-1] == '.') dst--; *dst = '\0'; *inp = src; return c; } } }
/* * Parse an RFC 822 "phrase", stopping at 'specials' */ static int parseaddr_phrase(char **inp, char **phrasep, char *specials) { int c; char *src = *inp; char *dst; SKIPWHITESPACE(src); *phrasep = dst = src; for (;;) { c = *src++; if (c == '\"') { while ((c = *src)) { src++; if (c == '\"') break; if (c == '\\') { if (!(c = *src)) break; src++; } *dst++ = c; } } else if (isspace((int)(unsigned char)c) || c == '(') { src--; SKIPWHITESPACE(src); *dst++ = ' '; } else if (!c || strchr(specials, c)) { if (dst > *phrasep && dst[-1] == ' ') dst--; *dst = '\0'; *inp = src; return c; } else { *dst++ = c; } } }