1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.attachment;
16
17 import java.io.ByteArrayInputStream;
18 import java.io.InputStream;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.htmlunit.HttpWebConnectionTest;
23 import org.htmlunit.MockWebConnection;
24 import org.htmlunit.Page;
25 import org.htmlunit.SimpleWebTestCase;
26 import org.htmlunit.TextPage;
27 import org.htmlunit.WebClient;
28 import org.htmlunit.WebResponse;
29 import org.htmlunit.html.HtmlAnchor;
30 import org.htmlunit.html.HtmlElement;
31 import org.htmlunit.html.HtmlPage;
32 import org.htmlunit.junit.BrowserRunner;
33 import org.htmlunit.util.MimeType;
34 import org.htmlunit.util.NameValuePair;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37
38
39
40
41
42
43
44
45
46
47 @RunWith(BrowserRunner.class)
48 public class AttachmentTest extends SimpleWebTestCase {
49
50
51
52
53
54 @Test
55 public void basic() throws Exception {
56 final String content1 = DOCTYPE_HTML
57 + "<html><body>\n"
58 + "<form method='POST' name='form' action='" + URL_SECOND + "'>\n"
59 + "<input type='submit' value='ok'>\n"
60 + "</form>\n"
61 + "<a href='#' onclick='document.form.submit()'>click me</a>\n"
62 + "</body></html>";
63 final String content2 = "download file contents";
64
65 final WebClient client = getWebClient();
66 final List<Attachment> attachments = new ArrayList<>();
67 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
68
69 final List<NameValuePair> headers = new ArrayList<>();
70 headers.add(new NameValuePair("Content-Disposition", "attachment"));
71
72 final MockWebConnection conn = new MockWebConnection();
73 conn.setResponse(URL_FIRST, content1);
74 conn.setResponse(URL_SECOND, content2, 200, "OK", MimeType.TEXT_HTML, headers);
75 client.setWebConnection(conn);
76 assertTrue(attachments.isEmpty());
77
78 final HtmlPage result = client.getPage(URL_FIRST);
79 final HtmlAnchor anchor = result.getAnchors().get(0);
80 final Page clickResult = anchor.click();
81 assertEquals(result, clickResult);
82 assertEquals(1, attachments.size());
83 assertTrue(HtmlPage.class.isInstance(attachments.get(0).getPage()));
84
85 assertEquals(2, client.getWebWindows().size());
86
87 final Attachment attachment = attachments.get(0);
88 final Page attachedPage = attachment.getPage();
89 final WebResponse attachmentResponse = attachedPage.getWebResponse();
90 final InputStream attachmentStream = attachmentResponse.getContentAsStream();
91 HttpWebConnectionTest.assertEquals(new ByteArrayInputStream(content2.getBytes()), attachmentStream);
92 assertEquals(MimeType.TEXT_HTML, attachmentResponse.getContentType());
93 assertEquals(200, attachmentResponse.getStatusCode());
94 assertEquals(URL_SECOND, attachmentResponse.getWebRequest().getUrl());
95 }
96
97
98
99
100
101 @Test
102 public void contentDispositionCaseInsensitive() throws Exception {
103 final String content1 = DOCTYPE_HTML
104 + "<html><body>\n"
105 + "<form method='POST' name='form' action='" + URL_SECOND + "'>\n"
106 + "<input type='submit' value='ok'>\n"
107 + "</form>\n"
108 + "<a href='#' onclick='document.form.submit()'>click me</a>\n"
109 + "</body></html>";
110 final String content2 = "download file contents";
111
112 final WebClient client = getWebClient();
113 final List<Attachment> attachments = new ArrayList<>();
114 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
115
116 final List<NameValuePair> headers = new ArrayList<>();
117 headers.add(new NameValuePair("Content-Disposition", "AttachMent"));
118
119 final MockWebConnection conn = new MockWebConnection();
120 conn.setResponse(URL_FIRST, content1);
121 conn.setResponse(URL_SECOND, content2, 200, "OK", MimeType.TEXT_HTML, headers);
122 client.setWebConnection(conn);
123 assertTrue(attachments.isEmpty());
124
125 final HtmlPage result = client.getPage(URL_FIRST);
126 final HtmlAnchor anchor = result.getAnchors().get(0);
127 final Page clickResult = anchor.click();
128 assertEquals(result, clickResult);
129 assertEquals(1, attachments.size());
130 }
131
132
133
134
135
136 @Test
137 public void filename() throws Exception {
138 final String content = DOCTYPE_HTML + "<html>But is it really?</html>";
139
140 final WebClient client = getWebClient();
141 final MockWebConnection conn = new MockWebConnection();
142 client.setWebConnection(conn);
143 final List<Attachment> attachments = new ArrayList<>();
144 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
145
146 final List<NameValuePair> headers1 = new ArrayList<>();
147 headers1.add(new NameValuePair("Content-Disposition", "attachment;filename=\"hello.html\""));
148 conn.setResponse(URL_FIRST, content, 200, "OK", MimeType.TEXT_HTML, headers1);
149 client.getPage(URL_FIRST);
150 final Attachment result = attachments.get(0);
151 assertEquals(result.getSuggestedFilename(), "hello.html");
152 attachments.clear();
153
154 final List<NameValuePair> headers2 = new ArrayList<>();
155 headers2.add(new NameValuePair("Content-Disposition", "attachment; filename=hello2.html; something=else"));
156 conn.setResponse(URL_SECOND, content, 200, "OK", MimeType.TEXT_PLAIN, headers2);
157 client.getPage(URL_SECOND);
158 final Attachment result2 = attachments.get(0);
159 assertEquals(result2.getSuggestedFilename(), "hello2.html");
160 assertEquals(content, ((TextPage) result2.getPage()).getContent());
161 attachments.clear();
162
163 final List<NameValuePair> headers3 = new ArrayList<>();
164 headers3.add(new NameValuePair("Content-Disposition", "attachment; filename="));
165 conn.setResponse(URL_SECOND, content, 200, "OK", MimeType.TEXT_PLAIN, headers3);
166 client.getPage(URL_SECOND);
167 final Attachment result3 = attachments.get(0);
168 assertNull(result3.getSuggestedFilename());
169 assertEquals(content, ((TextPage) result3.getPage()).getContent());
170 attachments.clear();
171
172 final List<NameValuePair> headers4 = new ArrayList<>();
173 headers4.add(new NameValuePair("Content-Disposition", "attachment"));
174 final byte[] contentb = new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE};
175 conn.setResponse(URL_THIRD, contentb, 200, "OK", "application/x-rubbish", headers4);
176 client.getPage(URL_THIRD);
177 final Attachment result4 = attachments.get(0);
178 final InputStream result4Stream = result4.getPage().getWebResponse().getContentAsStream();
179 assertNull(result4.getSuggestedFilename());
180 assertEquals(result4.getPage().getWebResponse().getContentType(), "application/x-rubbish");
181 HttpWebConnectionTest.assertEquals(new ByteArrayInputStream(contentb), result4Stream);
182 attachments.clear();
183 }
184
185
186
187
188 @Test
189 public void filenameFromAnchor() throws Exception {
190 final WebClient client = getWebClient();
191 final MockWebConnection conn = new MockWebConnection();
192 client.setWebConnection(conn);
193 final List<Attachment> attachments = new ArrayList<>();
194 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
195
196 final String content = DOCTYPE_HTML
197 + "<html>\n"
198 + "<head>\n"
199 + "<script>\n"
200 + "var blob = new Blob(['foo'], {type: 'text/plain'}),\n"
201 + " url = URL.createObjectURL(blob),\n"
202 + " elem = document.createElement('a');\n"
203 + "elem.href = url, elem.download = 'foo.txt', elem.click();\n"
204 + "</script>\n"
205 + "</head>\n"
206 + "</html>\n";
207
208 conn.setResponse(URL_FIRST, content);
209 client.getPage(URL_FIRST);
210
211 final Attachment result = attachments.get(0);
212 assertEquals(result.getSuggestedFilename(), "foo.txt");
213 assertEquals("foo", ((TextPage) result.getPage()).getContent());
214 attachments.clear();
215 }
216
217
218
219
220 @Test
221 public void filenameFromFile() throws Exception {
222 final WebClient client = getWebClient();
223 final MockWebConnection conn = new MockWebConnection();
224 client.setWebConnection(conn);
225 final List<Attachment> attachments = new ArrayList<>();
226 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
227
228 final String content = DOCTYPE_HTML
229 + "<html>\n"
230 + "<head>\n"
231 + "<script>\n"
232 + "var blob = new File(['bar'], 'bar.txt', {type: 'text/plain'}),\n"
233 + " url = URL.createObjectURL(blob),\n"
234 + " elem = document.createElement('a');\n"
235 + "elem.href = url, elem.download = '', elem.click();\n"
236 + "</script>\n"
237 + "</head>\n"
238 + "</html>\n";
239
240 conn.setResponse(URL_FIRST, content);
241 client.getPage(URL_FIRST);
242
243 final Attachment result = attachments.get(0);
244 assertEquals(result.getSuggestedFilename(), "bar.txt");
245 assertEquals("bar", ((TextPage) result.getPage()).getContent());
246 attachments.clear();
247 }
248
249
250
251
252
253
254 @Test
255 public void filenameFromFilePrioritizeAnchorDownloadOverFileName() throws Exception {
256 final WebClient client = getWebClient();
257 final MockWebConnection conn = new MockWebConnection();
258 client.setWebConnection(conn);
259 final List<Attachment> attachments = new ArrayList<>();
260 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
261
262 final String content = DOCTYPE_HTML
263 + "<html>\n"
264 + "<head>\n"
265 + "<script>\n"
266 + "var blob = new File(['bar'], 'bar.txt', {type: 'text/plain'}),\n"
267 + " url = URL.createObjectURL(blob),\n"
268 + " elem = document.createElement('a');\n"
269 + "elem.href = url, elem.download = 'foobar.txt', elem.click();\n"
270 + "</script>\n"
271 + "</head>\n"
272 + "</html>\n";
273
274 conn.setResponse(URL_FIRST, content);
275 client.getPage(URL_FIRST);
276
277 final Attachment result = attachments.get(0);
278 assertEquals(result.getSuggestedFilename(), "foobar.txt");
279 assertEquals("bar", ((TextPage) result.getPage()).getContent());
280 attachments.clear();
281 }
282
283
284
285
286
287
288 @Test
289 public void jsChangeLocationAfterReceptionOfAttachment() throws Exception {
290 final String html = DOCTYPE_HTML
291 + "<html><body>\n"
292 + "<form action='action'>\n"
293 + "<input type='submit' onclick='window.location=\"foo\"; return false'>\n"
294 + "</form>\n"
295 + "<a href='" + URL_SECOND + "'>download</a>\n"
296 + "</body></html>";
297
298 final WebClient client = getWebClient();
299 final List<Attachment> attachments = new ArrayList<>();
300 client.setAttachmentHandler(new CollectingAttachmentHandler(attachments));
301
302 final List<NameValuePair> headers = new ArrayList<>();
303 headers.add(new NameValuePair("Content-Disposition", "attachment"));
304
305 final MockWebConnection conn = getMockWebConnection();
306 conn.setDefaultResponse("");
307 conn.setResponse(URL_SECOND, "some text", 200, "OK", MimeType.TEXT_PLAIN, headers);
308
309 final HtmlPage page = loadPage(html);
310
311 page.getAnchors().get(0).click();
312 assertEquals(1, attachments.size());
313
314 final HtmlElement htmlElement = (HtmlElement) page.getFirstByXPath("//input");
315 htmlElement.click();
316 }
317
318
319
320
321
322 @Test
323 public void handleResponseFromHandler() throws Exception {
324 final String content1 = DOCTYPE_HTML
325 + "<html><body>\n"
326 + "<form method='POST' name='form' action='" + URL_SECOND + "'>\n"
327 + "<input type='submit' value='ok'>\n"
328 + "</form>\n"
329 + "<a href='#' onclick='document.form.submit()'>click me</a>\n"
330 + "</body></html>";
331 final String content2 = "download file contents";
332
333 final WebClient client = getWebClient();
334 final List<WebResponse> attachments = new ArrayList<>();
335 final List<String> attachmentFilenames = new ArrayList<>();
336
337 client.setAttachmentHandler(new AttachmentHandler() {
338 @Override
339 public boolean handleAttachment(final WebResponse response, final String attachmentFilename) {
340 attachments.add(response);
341 attachmentFilenames.add(attachmentFilename);
342 return true;
343 }
344
345 @Override
346 public void handleAttachment(final Page page, final String attachmentFilename) {
347 throw new IllegalAccessError("handleAttachment(Page, String) called");
348 }
349 });
350
351 final List<NameValuePair> headers = new ArrayList<>();
352 headers.add(new NameValuePair("Content-Disposition", "attachment"));
353
354 final MockWebConnection conn = new MockWebConnection();
355 conn.setResponse(URL_FIRST, content1);
356 conn.setResponse(URL_SECOND, content2, 200, "OK", MimeType.TEXT_HTML, headers);
357 client.setWebConnection(conn);
358 assertTrue(attachments.isEmpty());
359 assertTrue(attachmentFilenames.isEmpty());
360
361 final HtmlPage result = client.getPage(URL_FIRST);
362 final HtmlAnchor anchor = result.getAnchors().get(0);
363 final Page clickResult = anchor.click();
364 assertEquals(result, clickResult);
365 assertEquals(1, attachments.size());
366 assertEquals(1, attachmentFilenames.size());
367 assertEquals(1, client.getWebWindows().size());
368
369 final WebResponse attachmentResponse = attachments.get(0);
370 final InputStream attachmentStream = attachmentResponse.getContentAsStream();
371 HttpWebConnectionTest.assertEquals(new ByteArrayInputStream(content2.getBytes()), attachmentStream);
372 assertEquals(MimeType.TEXT_HTML, attachmentResponse.getContentType());
373 assertEquals(200, attachmentResponse.getStatusCode());
374 assertEquals(URL_SECOND, attachmentResponse.getWebRequest().getUrl());
375
376 assertNull(attachmentFilenames.get(0));
377 }
378
379
380
381
382
383 @Test
384 public void handleResponseFromHandlerWithFileName() throws Exception {
385 final String content1 = DOCTYPE_HTML
386 + "<html><body>\n"
387 + "<form method='POST' name='form' action='" + URL_SECOND + "'>\n"
388 + "<input type='submit' value='ok'>\n"
389 + "</form>\n"
390 + "<a href='#' onclick='document.form.submit()'>click me</a>\n"
391 + "</body></html>";
392 final String content2 = "download file contents";
393
394 final WebClient client = getWebClient();
395 final List<WebResponse> attachments = new ArrayList<>();
396 final List<String> attachmentFilenames = new ArrayList<>();
397
398 client.setAttachmentHandler(new AttachmentHandler() {
399 @Override
400 public boolean handleAttachment(final WebResponse response, final String attachmentFilename) {
401 attachments.add(response);
402 attachmentFilenames.add(attachmentFilename);
403 return true;
404 }
405
406 @Override
407 public void handleAttachment(final Page page, final String attachmentFilename) {
408 throw new IllegalAccessError("handleAttachment(Page, String) called");
409 }
410 });
411
412 final List<NameValuePair> headers = new ArrayList<>();
413 headers.add(new NameValuePair("Content-Disposition", "attachment; filename=htmlunit.zip"));
414
415 final MockWebConnection conn = new MockWebConnection();
416 conn.setResponse(URL_FIRST, content1);
417 conn.setResponse(URL_SECOND, content2, 200, "OK", MimeType.TEXT_HTML, headers);
418 client.setWebConnection(conn);
419 assertTrue(attachments.isEmpty());
420 assertTrue(attachmentFilenames.isEmpty());
421
422 final HtmlPage result = client.getPage(URL_FIRST);
423 final HtmlAnchor anchor = result.getAnchors().get(0);
424 final Page clickResult = anchor.click();
425 assertEquals(result, clickResult);
426 assertEquals(1, attachments.size());
427 assertEquals(1, attachmentFilenames.size());
428 assertEquals(1, client.getWebWindows().size());
429
430 final WebResponse attachmentResponse = attachments.get(0);
431 final InputStream attachmentStream = attachmentResponse.getContentAsStream();
432 HttpWebConnectionTest.assertEquals(new ByteArrayInputStream(content2.getBytes()), attachmentStream);
433 assertEquals(MimeType.TEXT_HTML, attachmentResponse.getContentType());
434 assertEquals(200, attachmentResponse.getStatusCode());
435 assertEquals(URL_SECOND, attachmentResponse.getWebRequest().getUrl());
436
437 assertEquals("htmlunit.zip", attachmentFilenames.get(0));
438 }
439
440
441
442
443
444 @Test
445 public void handleResponseOnlyApplicationOctetstream() throws Exception {
446 final String content1 = DOCTYPE_HTML
447 + "<html><body>\n"
448 + "<form method='POST' name='form' action='" + URL_SECOND + "'>\n"
449 + "<input type='submit' value='ok'>\n"
450 + "</form>\n"
451 + "<a href='#' onclick='document.form.submit()'>click me</a>\n"
452 + "</body></html>";
453 final String content2 = "download file contents";
454
455 final WebClient client = getWebClient();
456 final List<WebResponse> attachments = new ArrayList<>();
457 final List<String> attachmentFilenames = new ArrayList<>();
458
459 client.setAttachmentHandler(new AttachmentHandler() {
460 @Override
461 public boolean handleAttachment(final WebResponse response, final String attachmentFilename) {
462 attachments.add(response);
463 attachmentFilenames.add(attachmentFilename);
464 return true;
465 }
466
467 @Override
468 public void handleAttachment(final Page page, final String attachmentFilename) {
469 throw new IllegalAccessError("handleAttachment(Page, String) called");
470 }
471 });
472
473 final List<NameValuePair> headers = new ArrayList<>();
474 headers.add(new NameValuePair("Content-Type", MimeType.APPLICATION_OCTET_STREAM));
475
476 final MockWebConnection conn = new MockWebConnection();
477 conn.setResponse(URL_FIRST, content1);
478 conn.setResponse(URL_SECOND, content2, 200, "OK", MimeType.TEXT_HTML, headers);
479 client.setWebConnection(conn);
480 assertTrue(attachments.isEmpty());
481 assertTrue(attachmentFilenames.isEmpty());
482
483 final HtmlPage result = client.getPage(URL_FIRST);
484 final HtmlAnchor anchor = result.getAnchors().get(0);
485 final Page clickResult = anchor.click();
486 assertEquals(result, clickResult);
487 assertEquals(1, attachments.size());
488 assertEquals(1, attachmentFilenames.size());
489 assertEquals(1, client.getWebWindows().size());
490
491 final WebResponse attachmentResponse = attachments.get(0);
492 final InputStream attachmentStream = attachmentResponse.getContentAsStream();
493 HttpWebConnectionTest.assertEquals(new ByteArrayInputStream(content2.getBytes()), attachmentStream);
494 assertEquals(MimeType.APPLICATION_OCTET_STREAM, attachmentResponse.getContentType());
495 assertEquals(200, attachmentResponse.getStatusCode());
496 assertEquals(URL_SECOND, attachmentResponse.getWebRequest().getUrl());
497
498 assertNull(attachmentFilenames.get(0));
499 }
500 }