Commit fdd1855d fdd1855d418748f65b7dc52aeaa418e4c00a6688 by Alain Magloire

* mailbox/parse822.c, include/mailutils/parse822.h: now can

	  quote the local-part of and addr-spec, and a string.
1 parent ec3516f1
...@@ -37,9 +37,8 @@ extern "C" { ...@@ -37,9 +37,8 @@ extern "C" {
37 #endif 37 #endif
38 38
39 /** 39 /**
40 * Reads an RFC822 defined lexical token from an input. If some of 40 * Reads an RFC822 defined lexical token from an input. All names are
41 * the names seem strange, they are taken from the names as defined 41 * as close as possible to those used in the extended BNF of the RFC.
42 * in the extended BNF of the RFC.
43 */ 42 */
44 43
45 /* From RFC 822, 3.3 Lexical Tokens */ 44 /* From RFC 822, 3.3 Lexical Tokens */
...@@ -69,6 +68,7 @@ extern int parse822_word __P ((const char** p, const char* e, char** w ...@@ -69,6 +68,7 @@ extern int parse822_word __P ((const char** p, const char* e, char** w
69 extern int parse822_phrase __P ((const char** p, const char* e, char** phrase)); 68 extern int parse822_phrase __P ((const char** p, const char* e, char** phrase));
70 extern int parse822_d_text __P ((const char** p, const char* e, char** dtext)); 69 extern int parse822_d_text __P ((const char** p, const char* e, char** dtext));
71 70
71
72 /* From RFC 822, 6.1 Address Specification Syntax */ 72 /* From RFC 822, 6.1 Address Specification Syntax */
73 73
74 extern int parse822_address_list __P ((address_t* a, const char* s)); 74 extern int parse822_address_list __P ((address_t* a, const char* s));
...@@ -84,6 +84,16 @@ extern int parse822_sub_domain __P ((const char** p, const char* e, char** s ...@@ -84,6 +84,16 @@ extern int parse822_sub_domain __P ((const char** p, const char* e, char** s
84 extern int parse822_domain_ref __P ((const char** p, const char* e, char** domain_ref)); 84 extern int parse822_domain_ref __P ((const char** p, const char* e, char** domain_ref));
85 extern int parse822_domain_literal __P ((const char** p, const char* e, char** domain_literal)); 85 extern int parse822_domain_literal __P ((const char** p, const char* e, char** domain_literal));
86 86
87 /* RFC 822 Quoting Functions
88 * Various elements must be quoted if then contain non-safe characters. What
89 * characters are allowed depend on the element. The following functions will
90 * allocate a quoted version of the raw element, it may not actually be
91 * quoted if no unsafe characters were in the raw string.
92 */
93
94 extern int parse822_quote_string __P ((char** quoted, const char* raw));
95 extern int parse822_quote_local_part __P ((char** quoted, const char* raw));
96
87 #ifdef __cplusplus 97 #ifdef __cplusplus
88 } 98 }
89 #endif 99 #endif
......
...@@ -198,12 +198,7 @@ int parse822_is_smtp_q(char c) ...@@ -198,12 +198,7 @@ int parse822_is_smtp_q(char c)
198 && c != '\n'; 198 && c != '\n';
199 } 199 }
200 200
201 /* 201 /***** From RFC 822, 3.3 Lexical Tokens *****/
202 * Lexical Analysis - these tokens are all from RFC822,
203 * section 3.3, Lexical Tokens, though not all tokens are
204 * implemented. The names match those used int the extended
205 * BNF of the RFC where possible.
206 */
207 202
208 int parse822_skip_ws(const char** p, const char* e) 203 int parse822_skip_ws(const char** p, const char* e)
209 { 204 {
...@@ -483,6 +478,8 @@ int parse822_phrase(const char** p, const char* e, char** phrase) ...@@ -483,6 +478,8 @@ int parse822_phrase(const char** p, const char* e, char** phrase)
483 return rc; 478 return rc;
484 } 479 }
485 480
481 /***** From RFC 822, 6.1 Address Specification Syntax *****/
482
486 static address_t new_mb(void) { 483 static address_t new_mb(void) {
487 return calloc(1, sizeof(struct _address)); 484 return calloc(1, sizeof(struct _address));
488 } 485 }
...@@ -505,7 +502,7 @@ static int fill_mb( ...@@ -505,7 +502,7 @@ static int fill_mb(
505 /* this is wrong, local must be quoted */ 502 /* this is wrong, local must be quoted */
506 do { 503 do {
507 /* loop exists only to break out of */ 504 /* loop exists only to break out of */
508 if((rc = str_append(&(*a)->email, local))) 505 if((rc = parse822_quote_local_part(&(*a)->email, local)))
509 break; 506 break;
510 if((rc = str_append(&(*a)->email, "@"))) 507 if((rc = str_append(&(*a)->email, "@")))
511 break; 508 break;
...@@ -1032,6 +1029,9 @@ int parse822_domain_literal(const char** p, const char* e, char** domain_literal ...@@ -1032,6 +1029,9 @@ int parse822_domain_literal(const char** p, const char* e, char** domain_literal
1032 } 1029 }
1033 1030
1034 #if 0 1031 #if 0
1032
1033 /***** From RFC 822, 3.2 Header Field Definitions *****/
1034
1035 int parse822_field_name(const char** p, const char* e, char** fieldname) 1035 int parse822_field_name(const char** p, const char* e, char** fieldname)
1036 { 1036 {
1037 /* field-name = 1*<any char, excluding ctlS, space, and ":"> ":" */ 1037 /* field-name = 1*<any char, excluding ctlS, space, and ":"> ":" */
...@@ -1114,3 +1114,74 @@ int parse822_field_body(const char** p, const char* e, Rope& fieldbody) ...@@ -1114,3 +1114,74 @@ int parse822_field_body(const char** p, const char* e, Rope& fieldbody)
1114 } 1114 }
1115 #endif 1115 #endif
1116 1116
1117 /***** RFC 822 Quoting Functions *****/
1118
1119 int parse822_quote_string(char** quoted, const char* raw)
1120 {
1121 /* quoted-string = <"> *(qtext/quoted-pair) <">
1122 *
1123 * So double quote the string, and back quote anything that
1124 * isn't qtext.
1125 */
1126
1127 int rc = EOK;
1128 const char* s;
1129
1130 if(!raw || !quoted || *quoted) {
1131 return EINVAL;
1132 }
1133
1134 s = raw;
1135
1136 rc = str_append_char(quoted, '"');
1137
1138 while(!rc && *s) {
1139 if(!parse822_is_q_text(*s)) {
1140 rc = str_append_char(quoted, '\\');
1141 }
1142
1143 if(!rc) {
1144 rc = str_append_char(quoted, *s);
1145 }
1146 ++s;
1147 }
1148
1149 if(!rc) {
1150 rc = str_append_char(quoted, '"');
1151 }
1152
1153 if(rc) {
1154 str_free(quoted);
1155 }
1156 return rc;
1157 }
1158
1159 int parse822_quote_local_part(char** quoted, const char* raw)
1160 {
1161 /* local-part = word * ("." word)
1162 * word = atom / quoted-string
1163 *
1164 * So, if any character isn't a "." or an atom character, we quote
1165 * the whole thing as a string, for simplicity, otherwise just
1166 * copy it.
1167 */
1168
1169 const char* s = 0;
1170
1171 if(!raw || !quoted || *quoted) {
1172 return EINVAL;
1173 }
1174 s = raw;
1175
1176 while(*s) {
1177 if(*s != '.' && !parse822_is_atom_char(*s)) {
1178 return parse822_quote_string(quoted, raw);
1179 }
1180 ++s;
1181 }
1182
1183 /* if we don't have to quote it, just copy it over */
1184
1185 return str_append(quoted, raw);
1186 }
1187
......