No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / quote_822_local.c
blobfe9a20a82186f951ae7690465106027df6db827a
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* quote_822_local 3
6 /* SUMMARY
7 /* quote local part of mailbox
8 /* SYNOPSIS
9 /* #include <quote_822_local.h>
11 /* VSTRING *quote_822_local(dst, src)
12 /* VSTRING *dst;
13 /* const char *src;
15 /* VSTRING *quote_822_local_flags(dst, src, flags)
16 /* VSTRING *dst;
17 /* const char *src;
18 /* int flags;
20 /* VSTRING *unquote_822_local(dst, src)
21 /* VSTRING *dst;
22 /* const char *src;
23 /* DESCRIPTION
24 /* quote_822_local() quotes the local part of a mailbox and
25 /* returns a result that can be used in message headers as
26 /* specified by RFC 822 (actually, an 8-bit clean version of
27 /* RFC 822). It implements an 8-bit clean version of RFC 822.
29 /* quote_822_local_flags() provides finer control.
31 /* unquote_822_local() transforms the local part of a mailbox
32 /* address to unquoted (internal) form.
34 /* Arguments:
35 /* .IP dst
36 /* The result.
37 /* .IP src
38 /* The input address.
39 /* .IP flags
40 /* Bit-wise OR of zero or more of the following.
41 /* .RS
42 /* .IP QUOTE_FLAG_8BITCLEAN
43 /* In violation with RFCs, treat 8-bit text as ordinary text.
44 /* .IP QUOTE_FLAG_EXPOSE_AT
45 /* In violation with RFCs, treat `@' as an ordinary character.
46 /* .IP QUOTE_FLAG_APPEND
47 /* Append to the result buffer, instead of overwriting it.
48 /* .RE
49 /* STANDARDS
50 /* RFC 822 (ARPA Internet Text Messages)
51 /* BUGS
52 /* The code assumes that the domain is RFC 822 clean.
53 /* LICENSE
54 /* .ad
55 /* .fi
56 /* The Secure Mailer license must be distributed with this software.
57 /* AUTHOR(S)
58 /* Wietse Venema
59 /* IBM T.J. Watson Research
60 /* P.O. Box 704
61 /* Yorktown Heights, NY 10598, USA
62 /*--*/
64 /* System library. */
66 #include <sys_defs.h>
67 #include <string.h>
68 #include <ctype.h>
70 /* Utility library. */
72 #include <vstring.h>
74 /* Global library. */
76 /* Application-specific. */
78 #include "quote_822_local.h"
80 /* Local stuff. */
82 #define YES 1
83 #define NO 0
85 /* is_822_dot_string - is this local-part an rfc 822 dot-string? */
87 static int is_822_dot_string(const char *local_part, const char *end, int flags)
89 const char *cp;
90 int ch;
93 * Detect any deviations from a sequence of atoms separated by dots. We
94 * could use lookup tables to speed up some of the work, but hey, how
95 * large can a local-part be anyway?
97 * RFC 822 expects 7-bit data. Rather than quoting every 8-bit character
98 * (and still passing it on as 8-bit data) we leave 8-bit data alone.
100 if (local_part == end || local_part[0] == 0 || local_part[0] == '.')
101 return (NO);
102 for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
103 if (ch == '.' && (cp + 1) < end && cp[1] == '.')
104 return (NO);
105 if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
106 return (NO);
107 if (ch == ' ')
108 return (NO);
109 if (ISCNTRL(ch))
110 return (NO);
111 if (ch == '(' || ch == ')'
112 || ch == '<' || ch == '>'
113 || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == ','
114 || ch == ';' || ch == ':'
115 || ch == '\\' || ch == '"'
116 || ch == '[' || ch == ']')
117 return (NO);
119 if (cp[-1] == '.')
120 return (NO);
121 return (YES);
124 /* make_822_quoted_string - make quoted-string from local-part */
126 static VSTRING *make_822_quoted_string(VSTRING *dst, const char *local_part,
127 const char *end, int flags)
129 const char *cp;
130 int ch;
133 * Put quotes around the result, and prepend a backslash to characters
134 * that need quoting when they occur in a quoted-string.
136 VSTRING_ADDCH(dst, '"');
137 for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
138 if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
139 || ch == '"' || ch == '\\' || ch == '\r')
140 VSTRING_ADDCH(dst, '\\');
141 VSTRING_ADDCH(dst, ch);
143 VSTRING_ADDCH(dst, '"');
144 return (dst);
147 /* quote_822_local_flags - quote local part of mailbox according to rfc 822 */
149 VSTRING *quote_822_local_flags(VSTRING *dst, const char *mbox, int flags)
151 const char *start; /* first byte of localpart */
152 const char *end; /* first byte after localpart */
153 const char *colon;
156 * According to RFC 822, a local-part is a dot-string or a quoted-string.
157 * We first see if the local-part is a dot-string. If it is not, we turn
158 * it into a quoted-string. Anything else would be too painful. But
159 * first, skip over any source route that precedes the local-part.
161 if (mbox[0] == '@' && (colon = strchr(mbox, ':')) != 0)
162 start = colon + 1;
163 else
164 start = mbox;
165 if ((end = strrchr(start, '@')) == 0)
166 end = start + strlen(start);
167 if ((flags & QUOTE_FLAG_APPEND) == 0)
168 VSTRING_RESET(dst);
169 if (is_822_dot_string(start, end, flags)) {
170 return (vstring_strcat(dst, mbox));
171 } else {
172 vstring_strncat(dst, mbox, start - mbox);
173 make_822_quoted_string(dst, start, end, flags & QUOTE_FLAG_8BITCLEAN);
174 return (vstring_strcat(dst, end));
178 /* unquote_822_local - unquote local part of mailbox according to rfc 822 */
180 VSTRING *unquote_822_local(VSTRING *dst, const char *mbox)
182 const char *start; /* first byte of localpart */
183 const char *end; /* first byte after localpart */
184 const char *colon;
185 const char *cp;
187 if (mbox[0] == '@' && (colon = strchr(mbox, ':')) != 0) {
188 start = colon + 1;
189 vstring_strncpy(dst, mbox, start - mbox);
190 } else {
191 start = mbox;
192 VSTRING_RESET(dst);
194 if ((end = strrchr(start, '@')) == 0)
195 end = start + strlen(start);
196 for (cp = start; cp < end; cp++) {
197 if (*cp == '"')
198 continue;
199 if (*cp == '\\') {
200 if (cp[1] == 0)
201 continue;
202 cp++;
204 VSTRING_ADDCH(dst, *cp);
206 if (*end)
207 vstring_strcat(dst, end);
208 else
209 VSTRING_TERMINATE(dst);
210 return (dst);
213 #ifdef TEST
216 * Proof-of-concept test program. Read an unquoted address from stdin, and
217 * show the quoted and unquoted results.
219 #include <vstream.h>
220 #include <vstring_vstream.h>
222 #define STR vstring_str
224 int main(int unused_argc, char **unused_argv)
226 VSTRING *raw = vstring_alloc(100);
227 VSTRING *quoted = vstring_alloc(100);
228 VSTRING *unquoted = vstring_alloc(100);
230 while (vstring_fgets_nonl(raw, VSTREAM_IN)) {
231 quote_822_local(quoted, STR(raw));
232 vstream_printf("quoted: %s\n", STR(quoted));
233 unquote_822_local(unquoted, STR(quoted));
234 vstream_printf("unquoted: %s\n", STR(unquoted));
235 vstream_fflush(VSTREAM_OUT);
237 vstring_free(unquoted);
238 vstring_free(quoted);
239 vstring_free(raw);
240 return (0);
243 #endif