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