Index: ChangeLog =================================================================== RCS file: /cvs/mailutils/ChangeLog,v retrieving revision 1.82 diff -u -r1.82 ChangeLog --- ChangeLog 2001/04/13 23:31:43 1.82 +++ ChangeLog 2001/04/13 23:53:29 @@ -1,5 +1,10 @@ 2001-04-13 Sam Roberts + * mailbox/parse822.c, include/mailutils/parse822.h: now can + quote the local-part of and addr-spec, and a string. + +2001-04-13 Sam Roberts + * doc/address.texi: updated docs, now they match the parse822. * mailbox/parse822.c: small tweaks to the new parser, the changes made during the tidying over the last month were: Index: include/mailutils/parse822.h =================================================================== RCS file: /cvs/mailutils/include/mailutils/parse822.h,v retrieving revision 1.2 diff -u -r1.2 parse822.h --- include/mailutils/parse822.h 2001/04/10 05:15:48 1.2 +++ include/mailutils/parse822.h 2001/04/13 23:53:30 @@ -37,9 +37,8 @@ #endif /** -* Reads an RFC822 defined lexical token from an input. If some of -* the names seem strange, they are taken from the names as defined -* in the extended BNF of the RFC. +* Reads an RFC822 defined lexical token from an input. All names are +* as close as possible to those used in the extended BNF of the RFC. */ /* From RFC 822, 3.3 Lexical Tokens */ @@ -69,6 +68,7 @@ extern int parse822_phrase __P ((const char** p, const char* e, char** phrase)); extern int parse822_d_text __P ((const char** p, const char* e, char** dtext)); + /* From RFC 822, 6.1 Address Specification Syntax */ extern int parse822_address_list __P ((address_t* a, const char* s)); @@ -83,6 +83,16 @@ extern int parse822_sub_domain __P ((const char** p, const char* e, char** sub_domain)); extern int parse822_domain_ref __P ((const char** p, const char* e, char** domain_ref)); extern int parse822_domain_literal __P ((const char** p, const char* e, char** domain_literal)); + +/* RFC 822 Quoting Functions +* Various elements must be quoted if then contain non-safe characters. What +* characters are allowed depend on the element. The following functions will +* allocate a quoted version of the raw element, it may not actually be +* quoted if no unsafe characters were in the raw string. +*/ + +extern int parse822_quote_string __P ((char** quoted, const char* raw)); +extern int parse822_quote_local_part __P ((char** quoted, const char* raw)); #ifdef __cplusplus } Index: mailbox/parse822.c =================================================================== RCS file: /cvs/mailutils/mailbox/parse822.c,v retrieving revision 1.4 diff -u -r1.4 parse822.c --- mailbox/parse822.c 2001/04/13 23:30:26 1.4 +++ mailbox/parse822.c 2001/04/13 23:53:32 @@ -198,12 +198,7 @@ && c != '\n'; } -/* - * Lexical Analysis - these tokens are all from RFC822, - * section 3.3, Lexical Tokens, though not all tokens are - * implemented. The names match those used int the extended - * BNF of the RFC where possible. - */ +/***** From RFC 822, 3.3 Lexical Tokens *****/ int parse822_skip_ws(const char** p, const char* e) { @@ -483,6 +478,8 @@ return rc; } +/***** From RFC 822, 6.1 Address Specification Syntax *****/ + static address_t new_mb(void) { return calloc(1, sizeof(struct _address)); } @@ -505,7 +502,7 @@ /* this is wrong, local must be quoted */ do { /* loop exists only to break out of */ - if((rc = str_append(&(*a)->email, local))) + if((rc = parse822_quote_local_part(&(*a)->email, local))) break; if((rc = str_append(&(*a)->email, "@"))) break; @@ -1032,6 +1029,9 @@ } #if 0 + +/***** From RFC 822, 3.2 Header Field Definitions *****/ + int parse822_field_name(const char** p, const char* e, char** fieldname) { /* field-name = 1* ":" */ @@ -1113,4 +1113,75 @@ return 1; } #endif + +/***** RFC 822 Quoting Functions *****/ + +int parse822_quote_string(char** quoted, const char* raw) +{ + /* quoted-string = <"> *(qtext/quoted-pair) <"> + * + * So double quote the string, and back quote anything that + * isn't qtext. + */ + + int rc = EOK; + const char* s; + + if(!raw || !quoted || *quoted) { + return EINVAL; + } + + s = raw; + + rc = str_append_char(quoted, '"'); + + while(!rc && *s) { + if(!parse822_is_q_text(*s)) { + rc = str_append_char(quoted, '\\'); + } + + if(!rc) { + rc = str_append_char(quoted, *s); + } + ++s; + } + + if(!rc) { + rc = str_append_char(quoted, '"'); + } + + if(rc) { + str_free(quoted); + } + return rc; +} + +int parse822_quote_local_part(char** quoted, const char* raw) +{ + /* local-part = word * ("." word) + * word = atom / quoted-string + * + * So, if any character isn't a "." or an atom character, we quote + * the whole thing as a string, for simplicity, otherwise just + * copy it. + */ + + const char* s = 0; + + if(!raw || !quoted || *quoted) { + return EINVAL; + } + s = raw; + + while(*s) { + if(*s != '.' && !parse822_is_atom_char(*s)) { + return parse822_quote_string(quoted, raw); + } + ++s; + } + + /* if we don't have to quote it, just copy it over */ + + return str_append(quoted, raw); +}