Split up increasingly unwieldy lib/test.c into multiple files.
[disorder] / lib / t-mime.c
CommitLineData
b90f122b
RK
1/*
2 * This file is part of DisOrder.
3 * Copyright (C) 2005, 2007, 2008 Richard Kettlewell
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20#include "test.h"
21
22static int test_multipart_callback(const char *s, void *u) {
23 struct vector *parts = u;
24
25 vector_append(parts, (char *)s);
26 return 0;
27}
28
29void test_mime(void) {
30 char *t, *n, *v;
31 struct vector parts[1];
32 struct kvp *k;
33
34 fprintf(stderr, "test_mime\n");
35
36 t = 0;
37 k = 0;
38 insist(!mime_content_type("text/plain", &t, &k));
39 check_string(t, "text/plain");
40 insist(k == 0);
41
42 insist(mime_content_type("TEXT ((broken) comment", &t, &k) < 0);
43 insist(mime_content_type("TEXT ((broken) comment\\", &t, &k) < 0);
44
45 t = 0;
46 k = 0;
47 insist(!mime_content_type("TEXT ((nested)\\ comment) /plain", &t, &k));
48 check_string(t, "text/plain");
49 insist(k == 0);
50
51 t = 0;
52 k = 0;
53 insist(!mime_content_type(" text/plain ; Charset=\"utf-\\8\"", &t, &k));
54 check_string(t, "text/plain");
55 insist(k != 0);
56 insist(k->next == 0);
57 check_string(k->name, "charset");
58 check_string(k->value, "utf-8");
59
60 t = 0;
61 k = 0;
62 insist(!mime_content_type("text/plain;charset = ISO-8859-1 ", &t, &k));
63 insist(k != 0);
64 insist(k->next == 0);
65 check_string(t, "text/plain");
66 check_string(k->name, "charset");
67 check_string(k->value, "ISO-8859-1");
68
69 t = n = v = 0;
70 insist(!mime_rfc2388_content_disposition("form-data; name=\"field1\"", &t, &n, &v));
71 check_string(t, "form-data");
72 check_string(n, "name");
73 check_string(v, "field1");
74
75 insist(!mime_rfc2388_content_disposition("inline", &t, &n, &v));
76 check_string(t, "inline");
77 insist(n == 0);
78 insist(v == 0);
79
80 /* Current versions of the code only understand a single arg to these
81 * headers. This is a bug at the level they work at but suffices for
82 * DisOrder's current purposes. */
83
84 insist(!mime_rfc2388_content_disposition(
85 "attachment; filename=genome.jpeg;\n"
86 "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\"",
87 &t, &n, &v));
88 check_string(t, "attachment");
89 check_string(n, "filename");
90 check_string(v, "genome.jpeg");
91
92 vector_init(parts);
93 insist(mime_multipart("--outer\r\n"
94 "Content-Type: text/plain\r\n"
95 "Content-Disposition: inline\r\n"
96 "Content-Description: text-part-1\r\n"
97 "\r\n"
98 "Some text goes here\r\n"
99 "\r\n"
100 "--outer\r\n"
101 "Content-Type: multipart/mixed; boundary=inner\r\n"
102 "Content-Disposition: attachment\r\n"
103 "Content-Description: multipart-2\r\n"
104 "\r\n"
105 "--inner\r\n"
106 "Content-Type: text/plain\r\n"
107 "Content-Disposition: inline\r\n"
108 "Content-Description: text-part-2\r\n"
109 "\r\n"
110 "Some more text here.\r\n"
111 "\r\n"
112 "--inner\r\n"
113 "Content-Type: image/jpeg\r\n"
114 "Content-Disposition: attachment\r\n"
115 "Content-Description: jpeg-1\r\n"
116 "\r\n"
117 "<jpeg data>\r\n"
118 "--inner--\r\n"
119 "--outer--\r\n",
120 test_multipart_callback,
121 "outer",
122 parts) == 0);
123 check_integer(parts->nvec, 2);
124 check_string(parts->vec[0],
125 "Content-Type: text/plain\r\n"
126 "Content-Disposition: inline\r\n"
127 "Content-Description: text-part-1\r\n"
128 "\r\n"
129 "Some text goes here\r\n");
130 check_string(parts->vec[1],
131 "Content-Type: multipart/mixed; boundary=inner\r\n"
132 "Content-Disposition: attachment\r\n"
133 "Content-Description: multipart-2\r\n"
134 "\r\n"
135 "--inner\r\n"
136 "Content-Type: text/plain\r\n"
137 "Content-Disposition: inline\r\n"
138 "Content-Description: text-part-2\r\n"
139 "\r\n"
140 "Some more text here.\r\n"
141 "\r\n"
142 "--inner\r\n"
143 "Content-Type: image/jpeg\r\n"
144 "Content-Disposition: attachment\r\n"
145 "Content-Description: jpeg-1\r\n"
146 "\r\n"
147 "<jpeg data>\r\n"
148 "--inner--");
149 /* No trailing CRLF is _correct_ - see RFC2046 5.1.1 note regarding CRLF
150 * preceding the boundary delimiter line. An implication of this is that we
151 * must cope with partial lines at the end of the input when recursively
152 * decomposing a multipart message. */
153 vector_init(parts);
154 insist(mime_multipart("--inner\r\n"
155 "Content-Type: text/plain\r\n"
156 "Content-Disposition: inline\r\n"
157 "Content-Description: text-part-2\r\n"
158 "\r\n"
159 "Some more text here.\r\n"
160 "\r\n"
161 "--inner\r\n"
162 "Content-Type: image/jpeg\r\n"
163 "Content-Disposition: attachment\r\n"
164 "Content-Description: jpeg-1\r\n"
165 "\r\n"
166 "<jpeg data>\r\n"
167 "--inner--",
168 test_multipart_callback,
169 "inner",
170 parts) == 0);
171 check_integer(parts->nvec, 2);
172 check_string(parts->vec[0],
173 "Content-Type: text/plain\r\n"
174 "Content-Disposition: inline\r\n"
175 "Content-Description: text-part-2\r\n"
176 "\r\n"
177 "Some more text here.\r\n");
178 check_string(parts->vec[1],
179 "Content-Type: image/jpeg\r\n"
180 "Content-Disposition: attachment\r\n"
181 "Content-Description: jpeg-1\r\n"
182 "\r\n"
183 "<jpeg data>");
184
185 /* XXX mime_parse */
186
187 check_string(mime_qp(""), "");
188 check_string(mime_qp("foobar"), "foobar");
189 check_string(mime_qp("foo=20bar"), "foo bar");
190 check_string(mime_qp("x \r\ny"), "x\r\ny");
191 check_string(mime_qp("x=\r\ny"), "xy");
192 check_string(mime_qp("x= \r\ny"), "xy");
193 check_string(mime_qp("x =\r\ny"), "x y");
194 check_string(mime_qp("x = \r\ny"), "x y");
195
196 check_string(mime_to_qp(""), "");
197 check_string(mime_to_qp("foobar\n"), "foobar\n");
198 check_string(mime_to_qp("foobar \n"), "foobar=20\n");
199 check_string(mime_to_qp("foobar\t\n"), "foobar=09\n");
200 check_string(mime_to_qp("foobar \t \n"), "foobar=20=09=20\n");
201 check_string(mime_to_qp(" foo=bar"), " foo=3Dbar\n");
202 check_string(mime_to_qp("copyright \xC2\xA9"), "copyright =C2=A9\n");
203 check_string(mime_to_qp("foo\nbar\nbaz\n"), "foo\nbar\nbaz\n");
204 check_string(mime_to_qp("wibble wobble wibble wobble wibble wobble wibble wobble wibble wobble wibble"), "wibble wobble wibble wobble wibble wobble wibble wobble wibble wobble wibb=\nle\n");
205
206 /* from RFC2045 */
207 check_string(mime_qp("Now's the time =\r\n"
208"for all folk to come=\r\n"
209" to the aid of their country."),
210 "Now's the time for all folk to come to the aid of their country.");
211
212#define check_base64(encoded, decoded) do { \
213 check_string(mime_base64(encoded, 0), decoded); \
214 check_string(mime_to_base64((const uint8_t *)decoded, \
215 (sizeof decoded) - 1), \
216 encoded); \
217 } while(0)
218
219
220 check_base64("", "");
221 check_base64("BBBB", "\x04\x10\x41");
222 check_base64("////", "\xFF\xFF\xFF");
223 check_base64("//BB", "\xFF\xF0\x41");
224 check_base64("BBBB//BB////",
225 "\x04\x10\x41" "\xFF\xF0\x41" "\xFF\xFF\xFF");
226 check_base64("BBBBBA==",
227 "\x04\x10\x41" "\x04");
228 check_base64("BBBBBBA=",
229 "\x04\x10\x41" "\x04\x10");
230
231 /* Check that decoding handles various kinds of rubbish OK */
232 check_string(mime_base64("B B B B / / B B / / / /", 0),
233 "\x04\x10\x41" "\xFF\xF0\x41" "\xFF\xFF\xFF");
234 check_string(mime_base64("B\r\nBBB.// B-B//~//", 0),
235 "\x04\x10\x41" "\xFF\xF0\x41" "\xFF\xFF\xFF");
236 check_string(mime_base64("BBBB BB==", 0),
237 "\x04\x10\x41" "\x04");
238 check_string(mime_base64("BBBB BB = =", 0),
239 "\x04\x10\x41" "\x04");
240 check_string(mime_base64("BBBB BBB=", 0),
241 "\x04\x10\x41" "\x04\x10");
242 check_string(mime_base64("BBBB BBB = ", 0),
243 "\x04\x10\x41" "\x04\x10");
244 check_string(mime_base64("BBBB=", 0),
245 "\x04\x10\x41");
246 check_string(mime_base64("BBBBBB==", 0),
247 "\x04\x10\x41" "\x04");
248 check_string(mime_base64("BBBBBBB=", 0),
249 "\x04\x10\x41" "\x04\x10");
250 /* Not actually valid base64 */
251 check_string(mime_base64("BBBBx=", 0),
252 "\x04\x10\x41");
253}
254
255/*
256Local Variables:
257c-basic-offset:2
258comment-column:40
259fill-column:79
260indent-tabs-mode:nil
261End:
262*/