]> diplodocus.org Git - nmh/blob - sbr/escape_addresses.c
6463ec616e626ad5ade8311d66a8d3922d35765a
[nmh] / sbr / escape_addresses.c
1 /* escape_addresses.c -- Escape address components, hopefully per RFC 5322.
2 *
3 * This code is Copyright (c) 2012, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "h/utils.h"
10
11 static void escape_component (char *name, size_t namesize, char *chars);
12
13
14 void
15 escape_display_name (char *name, size_t namesize)
16 {
17 char *specials = "\"(),.:;<>@[\\]";
18 escape_component (name, namesize, specials);
19 }
20
21
22 void
23 escape_local_part (char *name, size_t namesize)
24 {
25 /* wsp (whitespace) is horizontal tab or space, according to
26 RFC 5234. */
27 char *specials_less_dot_plus_wsp = " \"(),:;<>@[\\]";
28 escape_component (name, namesize, specials_less_dot_plus_wsp);
29 }
30
31
32 /* Escape an address component, hopefully per RFC 5322. Assumes
33 one-byte characters. The char array pointed to by the name
34 argument is modified in place. Its size is specified by the
35 namesize argument. The need_escape argument is a string of
36 characters that require that name be escaped. */
37 static void
38 escape_component (char *name, size_t namesize, char *chars_to_escape)
39 {
40 /* If name contains any chars_to_escape:
41 1) enclose it in ""
42 2) escape any embedded "
43 */
44 if (strpbrk(name, chars_to_escape)) {
45 char *destp, *srcp;
46 /* Maximum space requirement would be if each character had
47 to be escaped, plus enclosing double quotes, plus NUL terminator.
48 E.g., 2 characters, "", would require 7, "\"\""0, where that 0
49 is '\0'. */
50 char *tmp = mh_xmalloc (2*strlen(name) + 3);
51
52 for (destp = tmp, srcp = name; *srcp; ++srcp) {
53 if (srcp == name) {
54 /* Insert initial double quote, if needed. */
55 if (*srcp != '"') {
56 *destp++ = '"';
57 }
58 } else {
59 /* Escape embedded, unescaped double quote. */
60 if (*srcp == '"' && *(srcp+1) != '\0' && *(srcp-1) != '\\') {
61 *destp++ = '\\';
62 }
63 }
64
65 *destp++ = *srcp;
66
67 /* End of name. */
68 if (*(srcp+1) == '\0') {
69 /* Insert final double quote, if needed. */
70 if (*srcp != '"') {
71 *destp++ = '"';
72 }
73
74 *destp++ = '\0';
75 }
76 }
77
78 if (strcmp (tmp, "\"")) {
79 size_t len = destp - tmp;
80 assert ((ssize_t) strlen(tmp) + 1 == destp - tmp);
81 strncpy (name, tmp, min(len, namesize));
82 } else {
83 /* Handle just " as special case here instead of above. */
84 strncpy (name, "\"\\\"\"", namesize);
85 }
86
87 name[namesize - 1] = '\0';
88
89 free (tmp);
90 }
91 }