7 /* quote local part of address
9 /* #include "quote_821_local.h"
11 /* VSTRING *quote_821_local(dst, src)
15 /* VSTRING *quote_821_local_flags(dst, src, flags)
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.
32 /* Bit-wise OR of zero or more of the following.
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.
42 /* RFC 821 (SMTP protocol)
44 /* The code assumes that the domain is RFC 821 clean.
48 /* The Secure Mailer license must be distributed with this software.
51 /* IBM T.J. Watson Research
53 /* Yorktown Heights, NY 10598, USA
62 /* Utility library. */
68 #include "quote_821_local.h"
70 /* Application-specific. */
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
)
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] == '.')
89 for (cp
= local_part
; cp
< end
&& (ch
= *(unsigned char *) cp
) != 0; cp
++) {
90 if (ch
== '.' && cp
[1] == '.')
92 if (ch
> 127 && !(flags
& QUOTE_FLAG_8BITCLEAN
))
98 if (ch
== '<' || ch
== '>'
99 || ch
== '(' || ch
== ')'
100 || ch
== '[' || ch
== ']'
101 || ch
== '\\' || ch
== ','
102 || ch
== ';' || ch
== ':'
103 || (ch
== '@' && !(flags
& QUOTE_FLAG_EXPOSE_AT
)) || ch
== '"')
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
)
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
);
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
)
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)
150 if (is_821_dot_string(addr
, at
, flags
)) {
151 return (vstring_strcat(dst
, addr
));
153 make_821_quoted_string(dst
, addr
, at
, flags
& QUOTE_FLAG_8BITCLEAN
);
154 return (vstring_strcat(dst
, at
));
161 * Test program for local-part quoting as per rfc 821
165 #include <vstring_vstream.h>
166 #include "quote_821_local.h"
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
);