blaze822: blaze822_addr: rewrite address parsing

This hopefully fixes many bugs and subtleties related to extracting
adresses.
pull/82/head
Leah Neukirchen 7 years ago
parent ed16bee191
commit a5026c9b99

@ -128,107 +128,166 @@ fail:
return -1; return -1;
} }
static char *
skip_comment(char *s)
{
if (*s != '(')
return s;
long d = 0;
do {
if (!*s)
break;
else if (*s == '(')
d++;
else if (*s == ')')
d--;
s++;
} while (d > 0);
return s;
}
// always 0 terminates
// never writes more than dstmax to dst
// returns how many bytes were appended
static size_t
safe_append(char *dst, size_t dstmax, char *strbeg, char *strend)
{
size_t dstlen = strlen(dst);
if (dstmax - dstlen - 1 < strend - strbeg)
strend = strbeg + (dstmax - dstlen - 1);
memcpy(dst + dstlen, strbeg, strend - strbeg);
dst[dstlen + (strend - strbeg) + 1] = 0;
return strend - strbeg;
}
static size_t
safe_append_space(char *dst, size_t dstmax)
{
char sp[] = " ";
char *se = sp + 1;
return safe_append(dst, dstmax, sp, se);
}
char * char *
blaze822_addr(char *s, char **dispo, char **addro) blaze822_addr(char *s, char **dispo, char **addro)
{ {
static char disp[1024]; static char disp[1024];
static char addr[1024]; static char addr[1024];
char *c, *e;
while (iswsp(*s)) memset(addr, 0, sizeof addr);
s++; memset(disp, 0, sizeof disp);
char ttok[1024] = { 0 };
char *tc = ttok;
char *te = ttok + sizeof ttok;
int not_addr = 0;
while (1) {
if (!*s || iswsp(*s) || *s == ',' || *s == ';') {
if (tc != ttok) {
if (!*addr && !not_addr && memchr(ttok, '@', tc - ttok)) {
safe_append(addr, sizeof addr, ttok, tc);
} else {
if (*disp)
safe_append_space(disp, sizeof disp);
safe_append(disp, sizeof disp,
ttok, tc);
}
tc = ttok;
not_addr = 0;
}
if (!*s) { if (!*s) {
if (!*addr && !*disp) {
if (dispo) *dispo = 0; if (dispo) *dispo = 0;
if (addro) *addro = 0; if (addro) *addro = 0;
return 0; return 0;
} }
break;
c = disp; }
e = disp + sizeof disp - 1; if (*s == ',' || *s == ';') {
s++;
*disp = 0; if (*addr || *disp)
*addr = 0; break;
}
while (*s && c < e) { s++;
startover: } else if (*s == '<') {
if (*s == '<') { char tok[1024] = { 0 };
char *c = addr; char *c = tok;
char *e = addr + sizeof addr; char *e = tok + sizeof tok;
s++; s++;
while (*s && c < e && *s != '>') { while (*s && c < e && *s != '>') {
if (*s == '<') { s = skip_comment(s);
goto startover; if (*s == '"') {
} else if (*s == '"') {
// local part may be quoted, allow all // local part may be quoted, allow all
s++; s++;
while (*s && c < e && *s != '"') while (*s && c < e && *s != '"') {
if (*s == '\\')
s++;
*c++ = *s++; *c++ = *s++;
}
if (*s == '"') if (*s == '"')
s++; s++;
} else { } else {
if (iswsp(*s))
s++;
else
*c++ = *s++; *c++ = *s++;
} }
} }
if (*s == '>') if (*s == '>')
s++; s++;
while (iswsp(*s)) safe_append(addr, sizeof addr, tok, c);
s++;
*c = 0;
} else if (*s == '"') { } else if (*s == '"') {
char tok[1024] = { 0 };
char *c = tok;
char *e = tok + sizeof tok;
s++; s++;
while (*s && c < e && *s != '"') { while (*s && c < e && *s != '"') {
if (*s == '\\' && *(s+1)) if (*s == '\\')
s++; s++;
*c++ = *s++; *c++ = *s++;
} }
if (*s == '"') if (*s == '"')
s++; s++;
} else if (*s == '(') { // XXX recurse to conform?
s++;
if (!*addr) { // assume: user@host (name)
*c-- = 0;
while (c > disp && iswsp(*c))
*c-- = 0;
c++;
memcpy(addr, disp, (c - disp) + 1);
c = disp;
*c = 0;
}
while (*s && c < e && *s != ')') if (memchr(tok, '@', c - tok))
*c++ = *s++; not_addr = 1; // @ inside "" is never an addr
if (*s == ')')
s++; if (tc != ttok)
} else if (*s == '\\') { tc += safe_append_space(ttok, sizeof ttok);
s++; tc += safe_append(ttok, sizeof ttok, tok, c);
if (*s) } else if (*s == '(') {
*c++ = *s++; char *z = skip_comment(s);
if (!*disp && *addr) // user@host (name)
safe_append(disp, sizeof disp, s + 1, z - 1);
else if (*disp) { // copy comment
safe_append_space(disp, sizeof disp);
safe_append(disp, sizeof disp, s, z);
}
s = z;
} else if (*s == ':') { } else if (*s == ':') {
if (memchr(ttok, '[', tc - ttok)) {
// in ipv6 address
if (tc < te)
*tc++ = *s++;
} else { // ignore group name and start over
s++; s++;
while (iswsp(*s)) tc = ttok;
s++; memset(addr, 0, sizeof addr);
c = disp; // forget already read group name memset(disp, 0, sizeof disp);
} else if (*s == ',' || *s == ';') { *ttok = 0;
s++; not_addr = 0;
break;
} else {
*c++ = *s++;
} }
} else {
if (*s == '\\' && *(s+1))
s++;
if (tc < te)
*tc++ = *s++;
} }
*c-- = 0;
// strip trailing ws
while (c > disp && iswsp(*c))
*c-- = 0;
if (*disp && !*addr && strchr(disp, '@')) {
// just mail address was given
c++;
memcpy(addr, disp, (c - disp) + 1);
*disp = 0;
} }
char *host = strrchr(addr, '@'); char *host = strrchr(addr, '@');

Loading…
Cancel
Save