blaze822: blaze822_addr: rewrite address parsing

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

@ -128,109 +128,168 @@ 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))
s++;
if (!*s) { memset(addr, 0, sizeof addr);
if (dispo) *dispo = 0; memset(disp, 0, sizeof disp);
if (addro) *addro = 0;
return 0;
}
c = disp;
e = disp + sizeof disp - 1;
*disp = 0; char ttok[1024] = { 0 };
*addr = 0; char *tc = ttok;
char *te = ttok + sizeof ttok;
while (*s && c < e) { int not_addr = 0;
startover:
if (*s == '<') {
char *c = addr;
char *e = addr + sizeof addr;
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 (!*addr && !*disp) {
if (dispo) *dispo = 0;
if (addro) *addro = 0;
return 0;
}
break;
}
if (*s == ',' || *s == ';') {
s++;
if (*addr || *disp)
break;
}
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 = 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 {
*c++ = *s++; if (iswsp(*s))
s++;
else
*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) if (memchr(tok, '@', c - tok))
*c-- = 0; not_addr = 1; // @ inside "" is never an addr
while (c > disp && iswsp(*c))
*c-- = 0; if (tc != ttok)
c++; tc += safe_append_space(ttok, sizeof ttok);
memcpy(addr, disp, (c - disp) + 1); tc += safe_append(ttok, sizeof ttok, tok, c);
c = disp; } else if (*s == '(') {
*c = 0; 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;
while (*s && c < e && *s != ')')
*c++ = *s++;
if (*s == ')')
s++;
} else if (*s == '\\') {
s++;
if (*s)
*c++ = *s++;
} else if (*s == ':') { } else if (*s == ':') {
s++; if (memchr(ttok, '[', tc - ttok)) {
while (iswsp(*s)) // in ipv6 address
if (tc < te)
*tc++ = *s++;
} else { // ignore group name and start over
s++; s++;
c = disp; // forget already read group name tc = ttok;
} else if (*s == ',' || *s == ';') { memset(addr, 0, sizeof addr);
s++; memset(disp, 0, sizeof disp);
break; *ttok = 0;
not_addr = 0;
}
} else { } else {
*c++ = *s++; 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, '@');
char *u; char *u;
if (host && (u = strpbrk(addr, "()<>[]:;@\\,\"")) && u < host) { if (host && (u = strpbrk(addr, "()<>[]:;@\\,\"")) && u < host) {

Loading…
Cancel
Save