1/*
2 * Copyright (c) 2006 Proofpoint, 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>
11SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.10 2013-11-22 20:51:43 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
20extern bool SmTestVerbose;
21
22
23void
24show_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
47char *quote_unquote __P((char *, char *, int, int));
48
49char *
50quote_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
85struct sm_qic_S
86{
87	char		*qic_in;
88	char		*qic_out;
89	int		 qic_exp;
90};
91
92typedef struct sm_qic_S sm_qic_T;
93
94
95int
96main(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