Postfix3.3.1
xtext.c
[詳解]
1 /*++
2 /* NAME
3 /* xtext 3
4 /* SUMMARY
5 /* quote/unquote text, xtext style.
6 /* SYNOPSIS
7 /* #include <xtext.h>
8 /*
9 /* VSTRING *xtext_quote(quoted, unquoted, special)
10 /* VSTRING *quoted;
11 /* const char *unquoted;
12 /* const char *special;
13 /*
14 /* VSTRING *xtext_quote_append(unquoted, quoted, special)
15 /* VSTRING *unquoted;
16 /* const char *quoted;
17 /* const char *special;
18 /*
19 /* VSTRING *xtext_unquote(unquoted, quoted)
20 /* VSTRING *unquoted;
21 /* const char *quoted;
22 /*
23 /* VSTRING *xtext_unquote_append(unquoted, quoted)
24 /* VSTRING *unquoted;
25 /* const char *quoted;
26 /* DESCRIPTION
27 /* xtext_quote() takes a null-terminated string and replaces characters
28 /* +, <33(10) and >126(10), as well as characters specified with "special"
29 /* by +XX, XX being the two-digit uppercase hexadecimal equivalent.
30 /*
31 /* xtext_quote_append() is like xtext_quote(), but appends the conversion
32 /* result to the result buffer.
33 /*
34 /* xtext_unquote() performs the opposite transformation. This function
35 /* understands lowercase, uppercase, and mixed case +XX sequences. The
36 /* result value is the unquoted argument in case of success, a null pointer
37 /* otherwise.
38 /*
39 /* xtext_unquote_append() is like xtext_unquote(), but appends
40 /* the conversion result to the result buffer.
41 /* BUGS
42 /* This module cannot process null characters in data.
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 /* Wietse Venema
54 /* Google, Inc.
55 /* 111 8th Avenue
56 /* New York, NY 10011, USA
57 /*--*/
58 
59 /* System library. */
60 
61 #include <sys_defs.h>
62 #include <string.h>
63 #include <ctype.h>
64 
65 /* Utility library. */
66 
67 #include "msg.h"
68 #include "vstring.h"
69 #include "xtext.h"
70 
71 /* Application-specific. */
72 
73 #define STR(x) vstring_str(x)
74 #define LEN(x) VSTRING_LEN(x)
75 
76 /* xtext_quote_append - append unquoted data to quoted data */
77 
78 VSTRING *xtext_quote_append(VSTRING *quoted, const char *unquoted,
79  const char *special)
80 {
81  const char *cp;
82  int ch;
83 
84  for (cp = unquoted; (ch = *(unsigned const char *) cp) != 0; cp++) {
85  if (ch != '+' && ch > 32 && ch < 127
86  && (*special == 0 || strchr(special, ch) == 0)) {
87  VSTRING_ADDCH(quoted, ch);
88  } else {
89  vstring_sprintf_append(quoted, "+%02X", ch);
90  }
91  }
92  VSTRING_TERMINATE(quoted);
93  return (quoted);
94 }
95 
96 /* xtext_quote - unquoted data to quoted */
97 
98 VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
99 {
100  VSTRING_RESET(quoted);
101  xtext_quote_append(quoted, unquoted, special);
102  return (quoted);
103 }
104 
105 /* xtext_unquote_append - quoted data to unquoted */
106 
107 VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted)
108 {
109  const unsigned char *cp;
110  int ch;
111 
112  for (cp = (const unsigned char *) quoted; (ch = *cp) != 0; cp++) {
113  if (ch == '+') {
114  if (ISDIGIT(cp[1]))
115  ch = (cp[1] - '0') << 4;
116  else if (cp[1] >= 'a' && cp[1] <= 'f')
117  ch = (cp[1] - 'a' + 10) << 4;
118  else if (cp[1] >= 'A' && cp[1] <= 'F')
119  ch = (cp[1] - 'A' + 10) << 4;
120  else
121  return (0);
122  if (ISDIGIT(cp[2]))
123  ch |= (cp[2] - '0');
124  else if (cp[2] >= 'a' && cp[2] <= 'f')
125  ch |= (cp[2] - 'a' + 10);
126  else if (cp[2] >= 'A' && cp[2] <= 'F')
127  ch |= (cp[2] - 'A' + 10);
128  else
129  return (0);
130  cp += 2;
131  }
132  VSTRING_ADDCH(unquoted, ch);
133  }
134  VSTRING_TERMINATE(unquoted);
135  return (unquoted);
136 }
137 /* xtext_unquote - quoted data to unquoted */
138 
139 VSTRING *xtext_unquote(VSTRING *unquoted, const char *quoted)
140 {
141  VSTRING_RESET(unquoted);
142  return (xtext_unquote_append(unquoted, quoted) ? unquoted : 0);
143 }
144 
145 #ifdef TEST
146 
147  /*
148  * Proof-of-concept test program: convert to quoted and back.
149  */
150 #include <vstream.h>
151 
152 #define BUFLEN 1024
153 
154 static ssize_t read_buf(VSTREAM *fp, VSTRING *buf)
155 {
156  ssize_t len;
157 
158  VSTRING_RESET(buf);
159  len = vstream_fread(fp, STR(buf), vstring_avail(buf));
160  VSTRING_AT_OFFSET(buf, len); /* XXX */
161  VSTRING_TERMINATE(buf);
162  return (len);
163 }
164 
165 int main(int unused_argc, char **unused_argv)
166 {
167  VSTRING *unquoted = vstring_alloc(BUFLEN);
168  VSTRING *quoted = vstring_alloc(100);
169  ssize_t len;
170 
171  /*
172  * Negative tests.
173  */
174  if (xtext_unquote(unquoted, "++1") != 0)
175  msg_warn("undetected error pattern 1");
176  if (xtext_unquote(unquoted, "+2+") != 0)
177  msg_warn("undetected error pattern 2");
178 
179  /*
180  * Positive tests.
181  */
182  while ((len = read_buf(VSTREAM_IN, unquoted)) > 0) {
183  xtext_quote(quoted, STR(unquoted), "+=");
184  if (xtext_unquote(unquoted, STR(quoted)) == 0)
185  msg_fatal("bad input: %.100s", STR(quoted));
186  if (LEN(unquoted) != len)
187  msg_fatal("len %ld != unquoted len %ld",
188  (long) len, (long) LEN(unquoted));
189  if (vstream_fwrite(VSTREAM_OUT, STR(unquoted), LEN(unquoted)) != LEN(unquoted))
190  msg_fatal("write error: %m");
191  }
193  vstring_free(unquoted);
194  vstring_free(quoted);
195  return (0);
196 }
197 
198 #endif
#define VSTREAM_OUT
Definition: vstream.h:67
VSTRING * xtext_quote_append(VSTRING *quoted, const char *unquoted, const char *special)
Definition: xtext.c:78
int main(int argc, char **argv)
Definition: anvil.c:1010
#define VSTREAM_IN
Definition: vstream.h:66
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
#define ISDIGIT(c)
Definition: sys_defs.h:1748
#define VSTRING_RESET(vp)
Definition: vstring.h:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define vstring_avail(vp)
Definition: vstring.h:86
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define LEN(x)
Definition: xtext.c:74
#define vstream_fread(v, b, n)
Definition: vstream.h:104
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
VSTRING * xtext_unquote(VSTRING *unquoted, const char *quoted)
Definition: xtext.c:139
#define vstream_fwrite(v, b, n)
Definition: vstream.h:105
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define VSTRING_AT_OFFSET(vp, offset)
Definition: vstring.h:92
VSTRING * xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
Definition: xtext.c:98
VSTRING * xtext_unquote_append(VSTRING *unquoted, const char *quoted)
Definition: xtext.c:107
#define STR(x)
Definition: xtext.c:73