2 * escape_addresses.c -- Escape address components, hopefully per RFC 5322.
4 * This code is Copyright (c) 2012, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
15 escape_component (char *name, size_t namesize, char *chars);
19 escape_display_name (char *name, size_t namesize) {
20 char *specials = "\"(),.:;<>@[\\]";
21 escape_component (name, namesize, specials);
26 escape_local_part (char *name, size_t namesize) {
27 /* wsp (whitespace) is horizontal tab or space, according to
29 char *specials_less_dot_plus_wsp = " \"(),:;<>@[\\]";
30 escape_component (name, namesize, specials_less_dot_plus_wsp);
34 /* Escape an address component, hopefully per RFC 5322. Assumes
35 one-byte characters. The char array pointed to by the name
36 argument is modified in place. Its size is specified by the
37 namesize argument. The need_escape argument is a string of
38 characters that require that name be escaped. */
40 escape_component (char *name, size_t namesize, char *chars_to_escape) {
41 /* If name contains any chars_to_escape:
43 2) escape any embedded "
45 if (strpbrk(name, chars_to_escape)) {
47 /* Maximum space requirement would be if each character had
48 to be escaped, plus enclosing double quotes, plus null termintor.
49 E.g., 2 characters, "", would require 7, "\"\""0, where that 0
51 char *tmp = mh_xmalloc (2*strlen(name) + 3);
53 for (destp = tmp, srcp = name; *srcp; ++srcp) {
55 /* Insert initial double quote, if needed. */
60 /* Escape embedded, unescaped double quote. */
61 if (*srcp == '"' && *(srcp+1) != '\0' && *(srcp-1) != '\\') {
69 if (*(srcp+1) == '\0') {
70 /* Insert final double quote, if needed. */
79 if (strcmp (tmp, "\"")) {
80 /* assert (strlen(tmp) + 1 == destp - tmp); */
81 size_t len = destp - tmp;
82 strncpy (name, tmp, len <= namesize ? len : namesize);
84 /* Handle just " as special case here instead of above. */
85 strncpy (name, "\"\\\"\"", namesize);
88 name[namesize - 1] = '\0';