static TOKEN append_to_token( TOKEN old, const char *buf, size_t length ) { size_t n = strlen(old->data); TOKEN t; t = xmalloc( sizeof *t + n + length ); t->next = old->next; t->type = old->type; memcpy( t->data, old->data, n ); memcpy( t->data+n, buf, length ); t->data[n+length] = 0; old->next = NULL; release_token_list(old); return t; }
void rfc822parse_release_field (rfc822parse_field_t ctx) { if (ctx) release_token_list (ctx); }
/* Parse a field into tokens as defined by rfc822. */ static TOKEN parse_field (HDR_LINE hdr) { static const char specials[] = "<>@.,;:\\[]\"()"; static const char specials2[] = "<>@.,;:"; static const char tspecials[] = "/?=<>@,;:\\[]\"()"; static const char tspecials2[] = "/?=<>@.,;:"; /* FIXME: really include '.'?*/ static struct { const unsigned char *name; size_t namelen; } tspecial_header[] = { { "Content-Type", 12}, { "Content-Transfer-Encoding", 25}, { "Content-Disposition", 19}, { NULL, 0} }; const char *delimiters; const char *delimiters2; const unsigned char *line, *s, *s2; size_t n; int i, invalid = 0; TOKEN t, tok, *tok_tail; errno = 0; if (!hdr) return NULL; tok = NULL; tok_tail = &tok; line = hdr->line; if (!(s = strchr (line, ':'))) return NULL; /* oops */ n = s - line; if (!n) return NULL; /* oops: invalid name */ delimiters = specials; delimiters2 = specials2; for (i = 0; tspecial_header[i].name; i++) { if (n == tspecial_header[i].namelen && !memcmp (line, tspecial_header[i].name, n)) { delimiters = tspecials; delimiters2 = tspecials2; break; } } s++; /* Move over the colon. */ for (;;) { while (!*s) { if (!hdr->next || !hdr->next->cont) return tok; /* Ready. */ /* Next item is a header continuation line. */ hdr = hdr->next; s = hdr->line; } if (*s == '(') { int level = 1; int in_quote = 0; invalid = 0; for (s++;; s++) { while (!*s) { if (!hdr->next || !hdr->next->cont) goto oparen_out; /* Next item is a header continuation line. */ hdr = hdr->next; s = hdr->line; } if (in_quote) { if (*s == '\"') in_quote = 0; else if (*s == '\\' && s[1]) /* what about continuation? */ s++; } else if (*s == ')') { if (!--level) break; } else if (*s == '(') level++; else if (*s == '\"') in_quote = 1; } oparen_out: if (!*s) ; /* Actually this is an error, but we don't care about it. */ else s++; } else if (*s == '\"' || *s == '[') { /* We do not check for non-allowed nesting of domainliterals */ int term = *s == '\"' ? '\"' : ']'; invalid = 0; s++; t = NULL; for (;;) { for (s2 = s; *s2; s2++) { if (*s2 == term) break; else if (*s2 == '\\' && s2[1]) /* what about continuation? */ s2++; } t = (t ? append_to_token (t, s, s2 - s) : new_token (term == '\"'? tQUOTED : tDOMAINLIT, s, s2 - s)); if (!t) goto failure; if (*s2 || !hdr->next || !hdr->next->cont) break; /* Next item is a header continuation line. */ hdr = hdr->next; s = hdr->line; } *tok_tail = t; tok_tail = &t->next; s = s2; if (*s) s++; /* skip the delimiter */ } else if ((s2 = strchr (delimiters2, *s))) { /* Special characters which are not handled above. */ invalid = 0; t = new_token (tSPECIAL, s, 1); if (!t) goto failure; *tok_tail = t; tok_tail = &t->next; s++; } else if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') { invalid = 0; s = skip_ws (s + 1); } else if (*s > 0x20 && !(*s & 128)) { /* Atom. */ invalid = 0; for (s2 = s + 1; *s2 > 0x20 && !(*s2 & 128) && !strchr (delimiters, *s2); s2++) ; t = new_token (tATOM, s, s2 - s); if (!t) goto failure; *tok_tail = t; tok_tail = &t->next; s = s2; } else { /* Invalid character. */ if (!invalid) { /* For parsing we assume only one space. */ t = new_token (tSPACE, NULL, 0); if (!t) goto failure; *tok_tail = t; tok_tail = &t->next; invalid = 1; } s++; } } /*NOTREACHED*/ failure: { int save = errno; release_token_list (tok); errno = save; } return NULL; }
void rfc822_release_parse_ctx( RFC822_PARSE_CTX ctx ) { if( ctx ) release_token_list( ctx ); }