Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / quote_821_local.c
blobefd386483e87afb42450bf649a2b96380832399d
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* quote_821_local 3
6 /* SUMMARY
7 /* quote local part of address
8 /* SYNOPSIS
9 /* #include "quote_821_local.h"
11 /* VSTRING *quote_821_local(dst, src)
12 /* VSTRING *dst;
13 /* char *src;
15 /* VSTRING *quote_821_local_flags(dst, src, flags)
16 /* VSTRING *dst;
17 /* const char *src;
18 /* int flags;
19 /* DESCRIPTION
20 /* quote_821_local() quotes the local part of a mailbox address and
21 /* returns a result that can be used in SMTP commands as specified
22 /* by RFC 821. It implements an 8-bit clean version of RFC 821.
24 /* quote_821_local_flags() provides finer control.
26 /* Arguments:
27 /* .IP dst
28 /* The result.
29 /* .IP src
30 /* The input address.
31 /* .IP flags
32 /* Bit-wise OR of zero or more of the following.
33 /* .RS
34 /* .IP QUOTE_FLAG_8BITCLEAN
35 /* In violation with RFCs, treat 8-bit text as ordinary text.
36 /* .IP QUOTE_FLAG_EXPOSE_AT
37 /* In violation with RFCs, treat `@' as an ordinary character.
38 /* .IP QUOTE_FLAG_APPEND
39 /* Append to the result buffer, instead of overwriting it.
40 /* .RE
41 /* STANDARDS
42 /* RFC 821 (SMTP protocol)
43 /* BUGS
44 /* The code assumes that the domain is RFC 821 clean.
45 /* LICENSE
46 /* .ad
47 /* .fi
48 /* The Secure Mailer license must be distributed with this software.
49 /* AUTHOR(S)
50 /* Wietse Venema
51 /* IBM T.J. Watson Research
52 /* P.O. Box 704
53 /* Yorktown Heights, NY 10598, USA
54 /*--*/
56 /* System library. */
58 #include <sys_defs.h>
59 #include <string.h>
60 #include <ctype.h>
62 /* Utility library. */
64 #include <vstring.h>
66 /* Global library. */
68 #include "quote_821_local.h"
70 /* Application-specific. */
72 #define YES 1
73 #define NO 0
75 /* is_821_dot_string - is this local-part an rfc 821 dot-string? */
77 static int is_821_dot_string(const char *local_part, const char *end, int flags)
79 const char *cp;
80 int ch;
83 * Detect any deviations from the definition of dot-string. We could use
84 * lookup tables to speed up some of the work, but hey, how large can a
85 * local-part be anyway?
87 if (local_part == end || local_part[0] == 0 || local_part[0] == '.')
88 return (NO);
89 for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
90 if (ch == '.' && cp[1] == '.')
91 return (NO);
92 if (ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
93 return (NO);
94 if (ch == ' ')
95 return (NO);
96 if (ISCNTRL(ch))
97 return (NO);
98 if (ch == '<' || ch == '>'
99 || ch == '(' || ch == ')'
100 || ch == '[' || ch == ']'
101 || ch == '\\' || ch == ','
102 || ch == ';' || ch == ':'
103 || (ch == '@' && !(flags & QUOTE_FLAG_EXPOSE_AT)) || ch == '"')
104 return (NO);
106 if (cp[-1] == '.')
107 return (NO);
108 return (YES);
111 /* make_821_quoted_string - make quoted-string from local-part */
113 static VSTRING *make_821_quoted_string(VSTRING *dst, const char *local_part,
114 const char *end, int flags)
116 const char *cp;
117 int ch;
120 * Put quotes around the result, and prepend a backslash to characters
121 * that need quoting when they occur in a quoted-string.
123 VSTRING_ADDCH(dst, '"');
124 for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
125 if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
126 || ch == '\r' || ch == '\n' || ch == '"' || ch == '\\')
127 VSTRING_ADDCH(dst, '\\');
128 VSTRING_ADDCH(dst, ch);
130 VSTRING_ADDCH(dst, '"');
131 VSTRING_TERMINATE(dst);
132 return (dst);
135 /* quote_821_local_flags - quote local part of address according to rfc 821 */
137 VSTRING *quote_821_local_flags(VSTRING *dst, const char *addr, int flags)
139 const char *at;
142 * According to RFC 821, a local-part is a dot-string or a quoted-string.
143 * We first see if the local-part is a dot-string. If it is not, we turn
144 * it into a quoted-string. Anything else would be too painful.
146 if ((at = strrchr(addr, '@')) == 0) /* just in case */
147 at = addr + strlen(addr); /* should not happen */
148 if ((flags & QUOTE_FLAG_APPEND) == 0)
149 VSTRING_RESET(dst);
150 if (is_821_dot_string(addr, at, flags)) {
151 return (vstring_strcat(dst, addr));
152 } else {
153 make_821_quoted_string(dst, addr, at, flags & QUOTE_FLAG_8BITCLEAN);
154 return (vstring_strcat(dst, at));
158 #ifdef TEST
161 * Test program for local-part quoting as per rfc 821
163 #include <stdlib.h>
164 #include <vstream.h>
165 #include <vstring_vstream.h>
166 #include "quote_821_local.h"
168 int main(void)
170 VSTRING *src = vstring_alloc(100);
171 VSTRING *dst = vstring_alloc(100);
173 while (vstring_fgets_nonl(src, VSTREAM_IN)) {
174 vstream_fprintf(VSTREAM_OUT, "%s\n",
175 vstring_str(quote_821_local(dst, vstring_str(src))));
176 vstream_fflush(VSTREAM_OUT);
178 exit(0);
181 #endif