1 /*
2 * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 */
9
10 #include <sm/gen.h>
11 SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.9 2006/08/24 21:26:13 ca Exp $")
12
13 #include <stdio.h>
14 #include <sm/sendmail.h>
15 #include <sm/assert.h>
16 #include <sm/heap.h>
17 #include <sm/string.h>
18 #include <sm/test.h>
19
20 extern bool SmTestVerbose;
21
22
23 void
show_diff(s1,s2)24 show_diff(s1, s2)
25 const char *s1;
26 const char *s2;
27 {
28 int i;
29
30 for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++)
31 {
32 if (s1[i] != s2[i])
33 {
34 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
35 i, (unsigned char) s1[i],
36 (unsigned char) s2[i]);
37 return;
38 }
39 }
40 if (s1[i] != s2[i])
41 {
42 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n",
43 i, (unsigned char) s1[i], (unsigned char) s2[i]);
44 }
45 }
46
47 char *quote_unquote __P((char *, char *, int, int));
48
49 char *
quote_unquote(in,out,outlen,exp)50 quote_unquote(in, out, outlen, exp)
51 char *in;
52 char *out;
53 int outlen;
54 int exp;
55 {
56 char *obp, *bp;
57 char line_back[1024];
58 char line_in[1024];
59 int cmp;
60
61 sm_strlcpy(line_in, in, sizeof(line_in));
62 obp = quote_internal_chars(in, out, &outlen);
63 bp = str2prt(line_in);
64 dequote_internal_chars(obp, line_back, sizeof(line_back));
65 cmp = strcmp(line_in, line_back);
66 SM_TEST(exp == cmp);
67 if (cmp != exp && !SmTestVerbose)
68 {
69 fprintf(stderr, "in: %s\n", bp);
70 bp = str2prt(line_back);
71 fprintf(stderr, "out:%s\n", bp);
72 fprintf(stderr, "cmp=%d\n", cmp);
73 show_diff(in, line_back);
74 }
75 if (SmTestVerbose)
76 {
77 fprintf(stderr, "%s -> ", bp);
78 bp = str2prt(obp);
79 fprintf(stderr, "%s\n", bp);
80 fprintf(stderr, "cmp=%d\n", cmp);
81 }
82 return obp;
83 }
84
85 struct sm_qic_S
86 {
87 char *qic_in;
88 char *qic_out;
89 int qic_exp;
90 };
91
92 typedef struct sm_qic_S sm_qic_T;
93
94
95 int
main(argc,argv)96 main(argc, argv)
97 int argc;
98 char *argv[];
99 {
100 char line_in[1024], line[256], line_out[32], *obp;
101 int i, los, cmp;
102 sm_qic_T inout[] = {
103 { "", "", 0 }
104 , { "abcdef", "abcdef", 0 }
105 , { "01234567890123456789", "01234567890123456789", 0 }
106 , { "01234567890123456789\001", "01234567890123456789\001",
107 0 }
108 , { "012345\2067890123456789", "012345\377\2067890123456789",
109 0 }
110 , { "\377", "\377\377", 0 }
111 , { "\240", "\240", 0 }
112 , { "\220", "\377\220", 0 }
113 , { "\240\220", "\240\377\220", 0 }
114 , { "\377\377", "\377\377\377\377", 0 }
115 , { "\377a\377b", "\377\377a\377\377b", 0 }
116 , { "\376a\377b", "\376a\377\377b", 0 }
117 , { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240",
118 "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240",
119 0 }
120 , { NULL, NULL, 0 }
121 };
122
123 sm_test_begin(argc, argv, "test meta quoting");
124 for (i = 0; i < sizeof(line_out); i++)
125 line_out[i] = '\0';
126 for (i = 0; i < sizeof(line_in); i++)
127 line_in[i] = '\0';
128 for (i = 0; i < sizeof(line_in) / 2; i++)
129 {
130 char ch;
131
132 ch = 0200 + i;
133 if ('\0' == ch)
134 ch = '0';
135 line_in[i] = ch;
136 }
137 los = sizeof(line_out) / 2;
138 obp = quote_unquote(line_in, line_out, los, 0);
139 if (obp != line_out)
140 SM_FREE(obp);
141
142 for (i = 0; i < sizeof(line_in); i++)
143 line_in[i] = '\0';
144 for (i = 0; i < sizeof(line_in) / 2; i++)
145 {
146 char ch;
147
148 ch = 0200 + i;
149 if ('\0' == ch)
150 ch = '0';
151 line_in[i] = ch;
152 }
153 los = sizeof(line_in);
154 obp = quote_unquote(line_in, line_in, los, 0);
155 if (obp != line_in)
156 SM_FREE(obp);
157
158 for (i = 0; inout[i].qic_in != NULL; i++)
159 {
160 los = sizeof(line_out) / 2;
161 obp = quote_unquote(inout[i].qic_in, line_out, los,
162 inout[i].qic_exp);
163 cmp = strcmp(inout[i].qic_out, obp);
164 SM_TEST(inout[i].qic_exp == cmp);
165 if (inout[i].qic_exp != cmp && !SmTestVerbose)
166 {
167 char *bp;
168
169 bp = str2prt(obp);
170 fprintf(stderr, "got: %s\n", bp);
171 bp = str2prt(inout[i].qic_out);
172 fprintf(stderr, "exp:%s\n", bp);
173 fprintf(stderr, "cmp=%d\n", cmp);
174 show_diff(inout[i].qic_in, inout[i].qic_out);
175 }
176 if (obp != line_out)
177 SM_FREE(obp);
178 }
179
180 /* use same buffer for in and out */
181 for (i = 0; inout[i].qic_in != NULL; i++)
182 {
183 bool same;
184
185 same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0;
186 los = sm_strlcpy(line, inout[i].qic_in, sizeof(line));
187 SM_TEST(los + 1 < sizeof(line));
188 ++los;
189 obp = quote_unquote(line, line, los, inout[i].qic_exp);
190 cmp = strcmp(inout[i].qic_out, obp);
191 SM_TEST(inout[i].qic_exp == cmp);
192 if (inout[i].qic_exp != cmp && !SmTestVerbose)
193 {
194 char *bp;
195
196 bp = str2prt(obp);
197 fprintf(stderr, "got: %s\n", bp);
198 bp = str2prt(inout[i].qic_out);
199 fprintf(stderr, "exp:%s\n", bp);
200 fprintf(stderr, "cmp=%d\n", cmp);
201 show_diff(inout[i].qic_in, inout[i].qic_out);
202 }
203 if (obp != line)
204 {
205 SM_TEST(!same);
206 if (same)
207 show_diff(obp, inout[i].qic_out);
208 SM_FREE(obp);
209 }
210 }
211
212 /* use NULL buffer for out */
213 for (i = 0; inout[i].qic_in != NULL; i++)
214 {
215 los = 0;
216 obp = quote_unquote(inout[i].qic_in, NULL, los,
217 inout[i].qic_exp);
218 SM_TEST(obp != NULL);
219 cmp = strcmp(inout[i].qic_out, obp);
220 SM_TEST(inout[i].qic_exp == cmp);
221 if (inout[i].qic_exp != cmp && !SmTestVerbose)
222 {
223 char *bp;
224
225 bp = str2prt(obp);
226 fprintf(stderr, "got: %s\n", bp);
227 bp = str2prt(inout[i].qic_out);
228 fprintf(stderr, "exp:%s\n", bp);
229 fprintf(stderr, "cmp=%d\n", cmp);
230 show_diff(inout[i].qic_in, inout[i].qic_out);
231 }
232 }
233
234 return sm_test_end();
235 }
236