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