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
23using Poco::Net::HTMLForm;
24using Poco::Net::PartSource;
25using Poco::Net::StringPartSource;
26using Poco::Net::PartHandler;
27using Poco::Net::HTTPRequest;
28using Poco::Net::HTTPMessage;
29using Poco::Net::MessageHeader;
30
31
32namespace
33{
34 class StringPartHandler: public PartHandler
35 {
36 public:
37 StringPartHandler()
38 {
39 }
40
41 void handlePart(const MessageHeader& header, 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
76HTMLFormTest::HTMLFormTest(const std::string& name): CppUnit::TestCase(name)
77{
78}
79
80
81HTMLFormTest::~HTMLFormTest()
82{
83}
84
85
86void 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
102void 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
159void 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
171void 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
194void 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
208void 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
222void 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
236void 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
279void 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
293void 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
308void 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
327void 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
342void 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
361void 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
377void 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
420void HTMLFormTest::setUp()
421{
422}
423
424
425void HTMLFormTest::tearDown()
426{
427}
428
429
430CppUnit::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