1 | // |
2 | // HTMLFormTest.cpp |
3 | // |
4 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "HTMLFormTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "Poco/Net/HTMLForm.h" |
15 | #include "Poco/Net/PartSource.h" |
16 | #include "Poco/Net/StringPartSource.h" |
17 | #include "Poco/Net/PartHandler.h" |
18 | #include "Poco/Net/HTTPRequest.h" |
19 | #include "Poco/Net/NetException.h" |
20 | #include <sstream> |
21 | |
22 | |
23 | using Poco::Net::HTMLForm; |
24 | using Poco::Net::PartSource; |
25 | using Poco::Net::StringPartSource; |
26 | using Poco::Net::PartHandler; |
27 | using Poco::Net::HTTPRequest; |
28 | using Poco::Net::HTTPMessage; |
29 | using Poco::Net::MessageHeader; |
30 | |
31 | |
32 | namespace |
33 | { |
34 | class StringPartHandler: public PartHandler |
35 | { |
36 | public: |
37 | StringPartHandler() |
38 | { |
39 | } |
40 | |
41 | void handlePart(const MessageHeader& , std::istream& stream) |
42 | { |
43 | _disp = header["Content-Disposition" ]; |
44 | _type = header["Content-Type" ]; |
45 | int ch = stream.get(); |
46 | while (ch > 0) |
47 | { |
48 | _data += (char) ch; |
49 | ch = stream.get(); |
50 | } |
51 | } |
52 | |
53 | const std::string& data() const |
54 | { |
55 | return _data; |
56 | } |
57 | |
58 | const std::string& disp() const |
59 | { |
60 | return _disp; |
61 | } |
62 | |
63 | const std::string& type() const |
64 | { |
65 | return _type; |
66 | } |
67 | |
68 | private: |
69 | std::string _data; |
70 | std::string _disp; |
71 | std::string _type; |
72 | }; |
73 | } |
74 | |
75 | |
76 | HTMLFormTest::HTMLFormTest(const std::string& name): CppUnit::TestCase(name) |
77 | { |
78 | } |
79 | |
80 | |
81 | HTMLFormTest::~HTMLFormTest() |
82 | { |
83 | } |
84 | |
85 | |
86 | void HTMLFormTest::testWriteUrl() |
87 | { |
88 | HTMLForm form; |
89 | form.set("field1" , "value1" ); |
90 | form.set("field2" , "value 2" ); |
91 | form.set("field3" , "value=3" ); |
92 | form.set("field4" , "value&4" ); |
93 | form.set("field5" , "value+5" ); |
94 | |
95 | std::ostringstream ostr; |
96 | form.write(ostr); |
97 | std::string s = ostr.str(); |
98 | assertTrue (s == "field1=value1&field2=value%202&field3=value%3D3&field4=value%264&field5=value%2B5" ); |
99 | } |
100 | |
101 | |
102 | void HTMLFormTest::testWriteMultipart() |
103 | { |
104 | HTMLForm form(HTMLForm::ENCODING_MULTIPART); |
105 | form.set("field1" , "value1" ); |
106 | form.set("field2" , "value 2" ); |
107 | form.set("field3" , "value=3" ); |
108 | form.set("field4" , "value&4" ); |
109 | |
110 | form.addPart("attachment1" , new StringPartSource("This is an attachment" )); |
111 | StringPartSource* pSPS = new StringPartSource("This is another attachment" , "text/plain" , "att2.txt" ); |
112 | pSPS->headers().set("Content-ID" , "1234abcd" ); |
113 | form.addPart("attachment2" , pSPS); |
114 | |
115 | std::ostringstream ostr; |
116 | form.write(ostr, "MIME_boundary_0123456789" ); |
117 | std::string s = ostr.str(); |
118 | assertTrue (s == |
119 | "--MIME_boundary_0123456789\r\n" |
120 | "Content-Disposition: form-data; name=\"field1\"\r\n" |
121 | "\r\n" |
122 | "value1\r\n" |
123 | "--MIME_boundary_0123456789\r\n" |
124 | "Content-Disposition: form-data; name=\"field2\"\r\n" |
125 | "\r\n" |
126 | "value 2\r\n" |
127 | "--MIME_boundary_0123456789\r\n" |
128 | "Content-Disposition: form-data; name=\"field3\"\r\n" |
129 | "\r\n" |
130 | "value=3\r\n" |
131 | "--MIME_boundary_0123456789\r\n" |
132 | "Content-Disposition: form-data; name=\"field4\"\r\n" |
133 | "\r\n" |
134 | "value&4\r\n" |
135 | "--MIME_boundary_0123456789\r\n" |
136 | "Content-Disposition: form-data; name=\"attachment1\"\r\n" |
137 | "Content-Type: text/plain\r\n" |
138 | "\r\n" |
139 | "This is an attachment\r\n" |
140 | "--MIME_boundary_0123456789\r\n" |
141 | "Content-ID: 1234abcd\r\n" |
142 | "Content-Disposition: form-data; name=\"attachment2\"; filename=\"att2.txt\"\r\n" |
143 | "Content-Type: text/plain\r\n" |
144 | "\r\n" |
145 | "This is another attachment\r\n" |
146 | "--MIME_boundary_0123456789--\r\n" |
147 | ); |
148 | assertTrue (s.length() == form.calculateContentLength()); |
149 | |
150 | const HTMLForm::PartVec& parts = form.getPartList(); |
151 | assertTrue (parts.size() == 2); |
152 | assertTrue (parts[0].name() == "attachment1" ); |
153 | assertTrue (parts[1].name() == "attachment2" ); |
154 | assertTrue (parts[1].filename() == "att2.txt" ); |
155 | assertTrue (parts[1].headers()["Content-ID" ] == "1234abcd" ); |
156 | } |
157 | |
158 | |
159 | void HTMLFormTest::testReadUrlGET() |
160 | { |
161 | HTTPRequest req("GET" , "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
162 | HTMLForm form(req); |
163 | assertTrue (form.size() == 4); |
164 | assertTrue (form["field1" ] == "value1" ); |
165 | assertTrue (form["field2" ] == "value 2" ); |
166 | assertTrue (form["field3" ] == "value=3" ); |
167 | assertTrue (form["field4" ] == "value&4" ); |
168 | } |
169 | |
170 | |
171 | void HTMLFormTest::testReadUrlGETMultiple() |
172 | { |
173 | HTTPRequest req("GET" , "/form.cgi?field1=value1&field1=value%202&field1=value%3D3&field1=value%264" ); |
174 | HTMLForm form(req); |
175 | assertTrue (form.size() == 4); |
176 | |
177 | HTMLForm::ConstIterator it = form.find("field1" ); |
178 | assertTrue (it != form.end()); |
179 | assertTrue (it->first == "field1" && it->second == "value1" ); |
180 | ++it; |
181 | assertTrue (it != form.end()); |
182 | assertTrue (it->first == "field1" && it->second == "value 2" ); |
183 | ++it; |
184 | assertTrue (it != form.end()); |
185 | assertTrue (it->first == "field1" && it->second == "value=3" ); |
186 | ++it; |
187 | assertTrue (it != form.end()); |
188 | assertTrue (it->first == "field1" && it->second == "value&4" ); |
189 | ++it; |
190 | assertTrue (it == form.end()); |
191 | } |
192 | |
193 | |
194 | void HTMLFormTest::testReadUrlPOST() |
195 | { |
196 | HTTPRequest req("POST" , "/form.cgi?field0=value0" ); |
197 | std::istringstream istr("field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
198 | HTMLForm form(req, istr); |
199 | assertTrue (form.size() == 5); |
200 | assertTrue (form["field0" ] == "value0" ); |
201 | assertTrue (form["field1" ] == "value1" ); |
202 | assertTrue (form["field2" ] == "value 2" ); |
203 | assertTrue (form["field3" ] == "value=3" ); |
204 | assertTrue (form["field4" ] == "value&4" ); |
205 | } |
206 | |
207 | |
208 | void HTMLFormTest::testReadUrlPUT() |
209 | { |
210 | HTTPRequest req("PUT" , "/form.cgi?field0=value0" ); |
211 | std::istringstream istr("field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
212 | HTMLForm form(req, istr); |
213 | assertTrue (form.size() == 5); |
214 | assertTrue (form["field0" ] == "value0" ); |
215 | assertTrue (form["field1" ] == "value1" ); |
216 | assertTrue (form["field2" ] == "value 2" ); |
217 | assertTrue (form["field3" ] == "value=3" ); |
218 | assertTrue (form["field4" ] == "value&4" ); |
219 | } |
220 | |
221 | |
222 | void HTMLFormTest::testReadUrlBOM() |
223 | { |
224 | HTTPRequest req("PUT" , "/form.cgi?field0=value0" ); |
225 | std::istringstream istr("\357\273\277field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
226 | HTMLForm form(req, istr); |
227 | assertTrue (form.size() == 5); |
228 | assertTrue (form["field0" ] == "value0" ); |
229 | assertTrue (form["field1" ] == "value1" ); |
230 | assertTrue (form["field2" ] == "value 2" ); |
231 | assertTrue (form["field3" ] == "value=3" ); |
232 | assertTrue (form["field4" ] == "value&4" ); |
233 | } |
234 | |
235 | |
236 | void HTMLFormTest::testReadMultipart() |
237 | { |
238 | std::istringstream istr( |
239 | "\r\n" |
240 | "--MIME_boundary_0123456789\r\n" |
241 | "Content-Disposition: form-data; name=\"field1\"\r\n" |
242 | "\r\n" |
243 | "value1\r\n" |
244 | "--MIME_boundary_0123456789\r\n" |
245 | "Content-Disposition: form-data; name=\"field2\"\r\n" |
246 | "\r\n" |
247 | "value 2\r\n" |
248 | "--MIME_boundary_0123456789\r\n" |
249 | "Content-Disposition: form-data; name=\"field3\"\r\n" |
250 | "\r\n" |
251 | "value=3\r\n" |
252 | "--MIME_boundary_0123456789\r\n" |
253 | "Content-Disposition: form-data; name=\"field4\"\r\n" |
254 | "\r\n" |
255 | "value&4\r\n" |
256 | "--MIME_boundary_0123456789\r\n" |
257 | "Content-Disposition: file; name=\"attachment1\"; filename=\"att1.txt\"\r\n" |
258 | "Content-Type: text/plain\r\n" |
259 | "\r\n" |
260 | "This is an attachment\r\n" |
261 | "--MIME_boundary_0123456789--\r\n" |
262 | ); |
263 | HTTPRequest req("POST" , "/form.cgi" ); |
264 | req.setContentType(HTMLForm::ENCODING_MULTIPART + "; boundary=\"MIME_boundary_0123456789\"" ); |
265 | StringPartHandler sah; |
266 | HTMLForm form(req, istr, sah); |
267 | assertTrue (form.size() == 4); |
268 | assertTrue (form["field1" ] == "value1" ); |
269 | assertTrue (form["field2" ] == "value 2" ); |
270 | assertTrue (form["field3" ] == "value=3" ); |
271 | assertTrue (form["field4" ] == "value&4" ); |
272 | |
273 | assertTrue (sah.type() == "text/plain" ); |
274 | assertTrue (sah.disp() == "file; name=\"attachment1\"; filename=\"att1.txt\"" ); |
275 | assertTrue (sah.data() == "This is an attachment" ); |
276 | } |
277 | |
278 | |
279 | void HTMLFormTest::testSubmit1() |
280 | { |
281 | HTMLForm form; |
282 | form.set("field1" , "value1" ); |
283 | form.set("field2" , "value 2" ); |
284 | form.set("field3" , "value=3" ); |
285 | form.set("field4" , "value&4" ); |
286 | |
287 | HTTPRequest req("GET" , "/form.cgi" ); |
288 | form.prepareSubmit(req); |
289 | assertTrue (req.getURI() == "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
290 | } |
291 | |
292 | |
293 | void HTMLFormTest::testSubmit2() |
294 | { |
295 | HTMLForm form; |
296 | form.set("field1" , "value1" ); |
297 | form.set("field2" , "value 2" ); |
298 | form.set("field3" , "value=3" ); |
299 | form.set("field4" , "value&4" ); |
300 | |
301 | HTTPRequest req("POST" , "/form.cgi" ); |
302 | form.prepareSubmit(req); |
303 | assertTrue (req.getContentType() == HTMLForm::ENCODING_URL); |
304 | assertTrue (req.getContentLength() == 64); |
305 | } |
306 | |
307 | |
308 | void HTMLFormTest::testSubmit3() |
309 | { |
310 | HTMLForm form(HTMLForm::ENCODING_MULTIPART); |
311 | form.set("field1" , "value1" ); |
312 | form.set("field2" , "value 2" ); |
313 | form.set("field3" , "value=3" ); |
314 | form.set("field4" , "value&4" ); |
315 | |
316 | HTTPRequest req("POST" , "/form.cgi" , HTTPMessage::HTTP_1_1); |
317 | form.prepareSubmit(req); |
318 | std::string expCT(HTMLForm::ENCODING_MULTIPART); |
319 | expCT.append("; boundary=\"" ); |
320 | expCT.append(form.boundary()); |
321 | expCT.append("\"" ); |
322 | assertTrue (req.getContentType() == expCT); |
323 | assertTrue (req.getChunkedTransferEncoding()); |
324 | } |
325 | |
326 | |
327 | void HTMLFormTest::testSubmit4() |
328 | { |
329 | HTMLForm form; |
330 | form.add("field1" , "value1" ); |
331 | form.add("field1" , "value 2" ); |
332 | form.add("field1" , "value=3" ); |
333 | form.add("field1" , "value&4" ); |
334 | |
335 | HTTPRequest req("GET" , "/form.cgi" ); |
336 | form.prepareSubmit(req); |
337 | |
338 | assertTrue (req.getURI() == "/form.cgi?field1=value1&field1=value%202&field1=value%3D3&field1=value%264" ); |
339 | } |
340 | |
341 | |
342 | void HTMLFormTest::testSubmit5() |
343 | { |
344 | HTMLForm form(HTMLForm::ENCODING_MULTIPART); |
345 | form.set("field1" , "value1" ); |
346 | form.set("field2" , "value 2" ); |
347 | form.set("field3" , "value=3" ); |
348 | form.set("field4" , "value&4" ); |
349 | |
350 | HTTPRequest req("POST" , "/form.cgi" , HTTPMessage::HTTP_1_1); |
351 | form.prepareSubmit(req, HTMLForm::OPT_USE_CONTENT_LENGTH); |
352 | std::string expCT(HTMLForm::ENCODING_MULTIPART); |
353 | expCT.append("; boundary=\"" ); |
354 | expCT.append(form.boundary()); |
355 | expCT.append("\"" ); |
356 | assertTrue (req.getContentType() == expCT); |
357 | assertTrue (req.getContentLength() == 403); |
358 | } |
359 | |
360 | |
361 | void HTMLFormTest::testFieldLimitUrl() |
362 | { |
363 | HTTPRequest req("GET" , "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264" ); |
364 | HTMLForm form; |
365 | form.setFieldLimit(3); |
366 | try |
367 | { |
368 | form.load(req); |
369 | fail("field limit violated - must throw" ); |
370 | } |
371 | catch (Poco::Net::HTMLFormException&) |
372 | { |
373 | } |
374 | } |
375 | |
376 | |
377 | void HTMLFormTest::testFieldLimitMultipart() |
378 | { |
379 | std::istringstream istr( |
380 | "\r\n" |
381 | "--MIME_boundary_0123456789\r\n" |
382 | "Content-Disposition: form-data; name=\"field1\"\r\n" |
383 | "\r\n" |
384 | "value1\r\n" |
385 | "--MIME_boundary_0123456789\r\n" |
386 | "Content-Disposition: form-data; name=\"field2\"\r\n" |
387 | "\r\n" |
388 | "value 2\r\n" |
389 | "--MIME_boundary_0123456789\r\n" |
390 | "Content-Disposition: form-data; name=\"field3\"\r\n" |
391 | "\r\n" |
392 | "value=3\r\n" |
393 | "--MIME_boundary_0123456789\r\n" |
394 | "Content-Disposition: form-data; name=\"field4\"\r\n" |
395 | "\r\n" |
396 | "value&4\r\n" |
397 | "--MIME_boundary_0123456789\r\n" |
398 | "Content-Disposition: file; name=\"attachment1\"; filename=\"att1.txt\"\r\n" |
399 | "Content-Type: text/plain\r\n" |
400 | "\r\n" |
401 | "This is an attachment\r\n" |
402 | "--MIME_boundary_0123456789--\r\n" |
403 | ); |
404 | HTTPRequest req("POST" , "/form.cgi" ); |
405 | req.setContentType(HTMLForm::ENCODING_MULTIPART + "; boundary=\"MIME_boundary_0123456789\"" ); |
406 | StringPartHandler sah; |
407 | HTMLForm form; |
408 | form.setFieldLimit(3); |
409 | try |
410 | { |
411 | form.load(req, istr, sah); |
412 | fail("field limit violated - must throw" ); |
413 | } |
414 | catch (Poco::Net::HTMLFormException&) |
415 | { |
416 | } |
417 | } |
418 | |
419 | |
420 | void HTMLFormTest::setUp() |
421 | { |
422 | } |
423 | |
424 | |
425 | void HTMLFormTest::tearDown() |
426 | { |
427 | } |
428 | |
429 | |
430 | CppUnit::Test* HTMLFormTest::suite() |
431 | { |
432 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTMLFormTest" ); |
433 | |
434 | CppUnit_addTest(pSuite, HTMLFormTest, testWriteUrl); |
435 | CppUnit_addTest(pSuite, HTMLFormTest, testWriteMultipart); |
436 | CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGET); |
437 | CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGETMultiple); |
438 | CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPOST); |
439 | CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPUT); |
440 | CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlBOM); |
441 | CppUnit_addTest(pSuite, HTMLFormTest, testReadMultipart); |
442 | CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1); |
443 | CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); |
444 | CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3); |
445 | CppUnit_addTest(pSuite, HTMLFormTest, testSubmit4); |
446 | CppUnit_addTest(pSuite, HTMLFormTest, testSubmit5); |
447 | CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitUrl); |
448 | CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitMultipart); |
449 | |
450 | return pSuite; |
451 | } |
452 | |