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