Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/browser/download/download_util_unittest.cc

Issue 3043048: Clean up download code: (Closed)
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/download/download_util.cc ('k') | chrome/browser/download/save_package.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #if defined(OS_POSIX) && !defined(OS_MACOSX)
6 #include <locale.h>
7 #endif
8
9 #include "base/string_util.h"
10 #include "chrome/browser/download/download_util.h"
11 #include "googleurl/src/gurl.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 #if defined(OS_WIN)
15 #define JPEG_EXT L".jpg"
16 #define HTML_EXT L".htm"
17 #define TXT_EXT L".txt"
18 #define TAR_EXT L".tar"
19 #elif defined(OS_MACOSX)
20 #define JPEG_EXT L".jpeg"
21 #define HTML_EXT L".html"
22 #define TXT_EXT L".txt"
23 #define TAR_EXT L".tar"
24 #else
25 #define JPEG_EXT L".jpg"
26 #define HTML_EXT L".html"
27 #define TXT_EXT L".txt"
28 #define TAR_EXT L".tar"
29 #endif
30
31 namespace {
32
33 const struct {
34 const char* disposition;
35 const char* url;
36 const char* mime_type;
37 const wchar_t* expected_name;
38 } kGenerateFileNameTestCases[] = {
39 // No 'filename' keyword in the disposition, use the URL
40 {"a_file_name.txt",
41 "http://www.evil.com/my_download.txt",
42 "text/plain",
43 L"my_download.txt"},
44
45 // Disposition has relative paths, remove them
46 {"filename=../../../../././../a_file_name.txt",
47 "http://www.evil.com/my_download.txt",
48 "text/plain",
49 L"a_file_name.txt"},
50
51 // Disposition has parent directories, remove them
52 {"filename=dir1/dir2/a_file_name.txt",
53 "http://www.evil.com/my_download.txt",
54 "text/plain",
55 L"a_file_name.txt"},
56
57 // No useful information in disposition or URL, use default
58 {"", "http://www.truncated.com/path/", "text/plain",
59 L"download" TXT_EXT
60 },
61
62 // A normal avi should get .avi and not .avi.avi
63 {"", "https://blah.google.com/misc/2.avi", "video/x-msvideo", L"2.avi"},
64
65 // Spaces in the disposition file name
66 {"filename=My Downloaded File.exe",
67 "http://www.frontpagehacker.com/a_download.exe",
68 "application/octet-stream",
69 L"My Downloaded File.exe"},
70
71 // This block tests whether we append extensions based on MIME types;
72 // we don't do this on Linux, so we skip the tests rather than #ifdef
73 // them up.
74 #if !defined(OS_POSIX) || defined(OS_MACOSX)
75 {"filename=my-cat",
76 "http://www.example.com/my-cat",
77 "image/jpeg",
78 L"my-cat" JPEG_EXT
79 },
80
81 {"filename=my-cat",
82 "http://www.example.com/my-cat",
83 "text/plain",
84 L"my-cat.txt"},
85
86 {"filename=my-cat",
87 "http://www.example.com/my-cat",
88 "text/html",
89 L"my-cat" HTML_EXT
90 },
91
92 {"filename=my-cat",
93 "http://www.example.com/my-cat",
94 "dance/party",
95 L"my-cat"},
96 #endif // !defined(OS_POSIX) || defined(OS_MACOSX)
97
98 {"filename=my-cat.jpg",
99 "http://www.example.com/my-cat.jpg",
100 "text/plain",
101 L"my-cat.jpg"},
102
103 // .exe tests.
104 #if defined(OS_WIN)
105 {"filename=evil.exe",
106 "http://www.goodguy.com/evil.exe",
107 "image/jpeg",
108 L"evil.jpg"},
109
110 {"filename=ok.exe",
111 "http://www.goodguy.com/ok.exe",
112 "binary/octet-stream",
113 L"ok.exe"},
114
115 {"filename=evil.exe.exe",
116 "http://www.goodguy.com/evil.exe.exe",
117 "dance/party",
118 L"evil.exe.download"},
119
120 {"filename=evil.exe",
121 "http://www.goodguy.com/evil.exe",
122 "application/xml",
123 L"evil.xml"},
124
125 {"filename=evil.exe",
126 "http://www.goodguy.com/evil.exe",
127 "application/html+xml",
128 L"evil.download"},
129
130 {"filename=evil.exe",
131 "http://www.goodguy.com/evil.exe",
132 "application/rss+xml",
133 L"evil.download"},
134
135 // Test truncation of trailing dots and spaces
136 {"filename=evil.exe ",
137 "http://www.goodguy.com/evil.exe ",
138 "binary/octet-stream",
139 L"evil.exe"},
140
141 {"filename=evil.exe.",
142 "http://www.goodguy.com/evil.exe.",
143 "binary/octet-stream",
144 L"evil.exe"},
145
146 {"filename=evil.exe. . .",
147 "http://www.goodguy.com/evil.exe. . .",
148 "binary/octet-stream",
149 L"evil.exe"},
150
151 {"filename=evil.",
152 "http://www.goodguy.com/evil.",
153 "binary/octet-stream",
154 L"evil"},
155
156 {"filename=. . . . .",
157 "http://www.goodguy.com/. . . . .",
158 "binary/octet-stream",
159 L"download"},
160
161 #endif // OS_WIN
162
163 {"filename=utils.js",
164 "http://www.goodguy.com/utils.js",
165 "application/x-javascript",
166 L"utils.js"},
167
168 {"filename=contacts.js",
169 "http://www.goodguy.com/contacts.js",
170 "application/json",
171 L"contacts.js"},
172
173 {"filename=utils.js",
174 "http://www.goodguy.com/utils.js",
175 "text/javascript",
176 L"utils.js"},
177
178 {"filename=utils.js",
179 "http://www.goodguy.com/utils.js",
180 "text/javascript;version=2",
181 L"utils.js"},
182
183 {"filename=utils.js",
184 "http://www.goodguy.com/utils.js",
185 "application/ecmascript",
186 L"utils.js"},
187
188 {"filename=utils.js",
189 "http://www.goodguy.com/utils.js",
190 "application/ecmascript;version=4",
191 L"utils.js"},
192
193 {"filename=program.exe",
194 "http://www.goodguy.com/program.exe",
195 "application/foo-bar",
196 L"program.exe"},
197
198 {"filename=../foo.txt",
199 "http://www.evil.com/../foo.txt",
200 "text/plain",
201 L"foo.txt"},
202
203 {"filename=..\\foo.txt",
204 "http://www.evil.com/..\\foo.txt",
205 "text/plain",
206 #if defined(OS_WIN)
207 L"foo.txt"
208 #else
209 L"\\foo.txt"
210 #endif
211 },
212
213 {"filename=.hidden",
214 "http://www.evil.com/.hidden",
215 "text/plain",
216 L"hidden" TXT_EXT
217 },
218
219 {"filename=trailing.",
220 "http://www.evil.com/trailing.",
221 "dance/party",
222 L"trailing"
223 },
224
225 {"filename=trailing.",
226 "http://www.evil.com/trailing.",
227 "text/plain",
228 L"trailing" TXT_EXT
229 },
230
231 {"filename=.",
232 "http://www.evil.com/.",
233 "dance/party",
234 L"download"},
235
236 {"filename=..",
237 "http://www.evil.com/..",
238 "dance/party",
239 L"download"},
240
241 {"filename=...",
242 "http://www.evil.com/...",
243 "dance/party",
244 L"download"},
245
246 // Note that this one doesn't have "filename=" on it.
247 {"a_file_name.txt",
248 "http://www.evil.com/",
249 "image/jpeg",
250 L"download" JPEG_EXT
251 },
252
253 {"filename=",
254 "http://www.evil.com/",
255 "image/jpeg",
256 L"download" JPEG_EXT
257 },
258
259 {"filename=simple",
260 "http://www.example.com/simple",
261 "application/octet-stream",
262 L"simple"},
263
264 {"filename=COM1",
265 "http://www.goodguy.com/COM1",
266 "application/foo-bar",
267 #if defined(OS_WIN)
268 L"_COM1"
269 #else
270 L"COM1"
271 #endif
272 },
273
274 {"filename=COM4.txt",
275 "http://www.goodguy.com/COM4.txt",
276 "text/plain",
277 #if defined(OS_WIN)
278 L"_COM4.txt"
279 #else
280 L"COM4.txt"
281 #endif
282 },
283
284 {"filename=lpt1.TXT",
285 "http://www.goodguy.com/lpt1.TXT",
286 "text/plain",
287 #if defined(OS_WIN)
288 L"_lpt1.TXT"
289 #else
290 L"lpt1.TXT"
291 #endif
292 },
293
294 {"filename=clock$.txt",
295 "http://www.goodguy.com/clock$.txt",
296 "text/plain",
297 #if defined(OS_WIN)
298 L"_clock$.txt"
299 #else
300 L"clock$.txt"
301 #endif
302 },
303
304 {"filename=mycom1.foo",
305 "http://www.goodguy.com/mycom1.foo",
306 "text/plain",
307 L"mycom1.foo"},
308
309 {"filename=Setup.exe.local",
310 "http://www.badguy.com/Setup.exe.local",
311 "application/foo-bar",
312 #if defined(OS_WIN)
313 L"Setup.exe.download"
314 #else
315 L"Setup.exe.local"
316 #endif
317 },
318
319 {"filename=Setup.exe.local.local",
320 "http://www.badguy.com/Setup.exe.local",
321 "application/foo-bar",
322 #if defined(OS_WIN)
323 L"Setup.exe.local.download"
324 #else
325 L"Setup.exe.local.local"
326 #endif
327 },
328
329 {"filename=Setup.exe.lnk",
330 "http://www.badguy.com/Setup.exe.lnk",
331 "application/foo-bar",
332 #if defined(OS_WIN)
333 L"Setup.exe.download"
334 #else
335 L"Setup.exe.lnk"
336 #endif
337 },
338
339 {"filename=Desktop.ini",
340 "http://www.badguy.com/Desktop.ini",
341 "application/foo-bar",
342 #if defined(OS_WIN)
343 L"_Desktop.ini"
344 #else
345 L"Desktop.ini"
346 #endif
347 },
348
349 {"filename=Thumbs.db",
350 "http://www.badguy.com/Thumbs.db",
351 "application/foo-bar",
352 #if defined(OS_WIN)
353 L"_Thumbs.db"
354 #else
355 L"Thumbs.db"
356 #endif
357 },
358
359 {"filename=source.srf",
360 "http://www.hotmail.com",
361 "image/jpeg",
362 L"source.srf" JPEG_EXT
363 },
364
365 {"filename=source.jpg",
366 "http://www.hotmail.com",
367 "application/x-javascript",
368 #if defined(OS_WIN)
369 L"source.jpg"
370 #elif defined(OS_MACOSX)
371 L"source.jpg.js"
372 #else
373 L"source.jpg"
374 #endif
375 },
376
377 // NetUtilTest.{GetSuggestedFilename, GetFileNameFromCD} test these
378 // more thoroughly. Tested below are a small set of samples.
379 {"attachment; filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
380 "http://www.examples.com/",
381 "image/jpeg",
382 L"\uc608\uc220 \uc608\uc220.jpg"},
383
384 {"attachment; name=abc de.pdf",
385 "http://www.examples.com/q.cgi?id=abc",
386 "application/octet-stream",
387 L"abc de.pdf"},
388
389 {"filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
390 "http://www.example.com/path",
391 "image/png",
392 L"\x82b8\x8853" L"3.png"},
393
394 // The following two have invalid CD headers and filenames come
395 // from the URL.
396 {"attachment; filename==?iiso88591?Q?caf=EG?=",
397 "http://www.example.com/test%20123",
398 "image/jpeg",
399 L"test 123" JPEG_EXT
400 },
401
402 {"malformed_disposition",
403 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
404 "image/jpeg",
405 L"\uc608\uc220 \uc608\uc220.jpg"},
406
407 // Invalid C-D. No filename from URL. Falls back to 'download'.
408 {"attachment; filename==?iso88591?Q?caf=E3?",
409 "http://www.google.com/path1/path2/",
410 "image/jpeg",
411 L"download" JPEG_EXT
412 },
413
414 // Issue=5772.
415 {"",
416 "http://www.example.com/foo.tar.gz",
417 "application/x-tar",
418 L"foo.tar.gz"},
419
420 // Issue=7337.
421 {"",
422 "http://maged.lordaeron.org/blank.reg",
423 "text/x-registry",
424 L"blank.reg"},
425
426 {"",
427 "http://www.example.com/bar.tar",
428 "application/x-tar",
429 L"bar.tar"},
430
431 {"",
432 "http://www.example.com/bar.bogus",
433 "application/x-tar",
434 L"bar.bogus" TAR_EXT
435 },
436
437 // http://code.google.com/p/chromium/issues/detail?id=20337
438 {"filename=.download.txt",
439 "http://www.example.com/.download.txt",
440 "text/plain",
441 L"download.txt"},
442 };
443
444 // Tests to ensure that the file names we generate from hints from the server
445 // (content-disposition, URL name, etc) don't cause security holes.
446 TEST(DownloadUtilTest, GenerateFileName) {
447 #if defined(OS_POSIX) && !defined(OS_MACOSX)
448 // This test doesn't run when the locale is not UTF-8 becuase some of the
449 // string conversions fail. This is OK (we have the default value) but they
450 // don't match our expectations.
451 std::string locale = setlocale(LC_CTYPE, NULL);
452 StringToLowerASCII(&locale);
453 ASSERT_NE(std::string::npos, locale.find("utf-8"))
454 << "Your locale must be set to UTF-8 for this test to pass!";
455 #endif
456
457 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGenerateFileNameTestCases); ++i) {
458 FilePath generated_name;
459 download_util::GenerateFileName(GURL(kGenerateFileNameTestCases[i].url),
460 kGenerateFileNameTestCases[i].disposition,
461 "",
462 kGenerateFileNameTestCases[i].mime_type,
463 &generated_name);
464 EXPECT_EQ(kGenerateFileNameTestCases[i].expected_name,
465 generated_name.ToWStringHack());
466 }
467
468 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGenerateFileNameTestCases); ++i) {
469 FilePath generated_name;
470 download_util::GenerateFileName(GURL(kGenerateFileNameTestCases[i].url),
471 kGenerateFileNameTestCases[i].disposition,
472 "GBK",
473 kGenerateFileNameTestCases[i].mime_type,
474 &generated_name);
475 EXPECT_EQ(kGenerateFileNameTestCases[i].expected_name,
476 generated_name.ToWStringHack());
477 }
478
479 // A couple of cases with raw 8bit characters in C-D.
480 {
481 FilePath generated_name;
482 download_util::GenerateFileName(GURL("http://www.example.com/images?id=3"),
483 "attachment; filename=caf\xc3\xa9.png",
484 "iso-8859-1",
485 "image/png",
486 &generated_name);
487 EXPECT_EQ(L"caf\u00e9.png", generated_name.ToWStringHack());
488 }
489
490 {
491 FilePath generated_name;
492 download_util::GenerateFileName(GURL("http://www.example.com/images?id=3"),
493 "attachment; filename=caf\xe5.png",
494 "windows-1253",
495 "image/png",
496 &generated_name);
497 EXPECT_EQ(L"caf\u03b5.png", generated_name.ToWStringHack());
498 }
499 }
500
501 const struct {
502 const FilePath::CharType* path;
503 const char* mime_type;
504 const FilePath::CharType* expected_path;
505 } kSafeFilenameCases[] = {
506 #if defined(OS_WIN)
507 { FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
508 "text/html",
509 FILE_PATH_LITERAL("C:\\foo\\bar.htm") },
510 { FILE_PATH_LITERAL("C:\\foo\\bar.html"),
511 "text/html",
512 FILE_PATH_LITERAL("C:\\foo\\bar.html") },
513 { FILE_PATH_LITERAL("C:\\foo\\bar"),
514 "text/html",
515 FILE_PATH_LITERAL("C:\\foo\\bar.htm") },
516
517 { FILE_PATH_LITERAL("C:\\bar.html"),
518 "image/png",
519 FILE_PATH_LITERAL("C:\\bar.png") },
520 { FILE_PATH_LITERAL("C:\\bar"),
521 "image/png",
522 FILE_PATH_LITERAL("C:\\bar.png") },
523
524 { FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
525 "text/html",
526 FILE_PATH_LITERAL("C:\\foo\\bar.htm") },
527 { FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
528 "image/gif",
529 FILE_PATH_LITERAL("C:\\foo\\bar.gif") },
530
531 { FILE_PATH_LITERAL("C:\\foo\\google.com"),
532 "text/html",
533 FILE_PATH_LITERAL("C:\\foo\\google.htm") },
534
535 { FILE_PATH_LITERAL("C:\\foo\\con.htm"),
536 "text/html",
537 FILE_PATH_LITERAL("C:\\foo\\_con.htm") },
538 { FILE_PATH_LITERAL("C:\\foo\\con"),
539 "text/html",
540 FILE_PATH_LITERAL("C:\\foo\\_con.htm") },
541 #else
542 { FILE_PATH_LITERAL("/foo/bar.htm"),
543 "text/html",
544 FILE_PATH_LITERAL("/foo/bar.htm") },
545 { FILE_PATH_LITERAL("/foo/bar.html"),
546 "text/html",
547 FILE_PATH_LITERAL("/foo/bar.html") },
548 { FILE_PATH_LITERAL("/foo/bar"),
549 "text/html",
550 FILE_PATH_LITERAL("/foo/bar.html") },
551
552 { FILE_PATH_LITERAL("/bar.html"),
553 "image/png",
554 FILE_PATH_LITERAL("/bar.html.png") },
555 { FILE_PATH_LITERAL("/bar"),
556 "image/png",
557 FILE_PATH_LITERAL("/bar.png") },
558
559 { FILE_PATH_LITERAL("/foo/bar.exe"),
560 "text/html",
561 FILE_PATH_LITERAL("/foo/bar.html") },
562 { FILE_PATH_LITERAL("/foo/bar.exe"),
563 "image/gif",
564 FILE_PATH_LITERAL("/foo/bar.gif") },
565
566 { FILE_PATH_LITERAL("/foo/google.com"),
567 "text/html",
568 FILE_PATH_LITERAL("/foo/google.com.html") },
569
570 { FILE_PATH_LITERAL("/foo/con.htm"),
571 "text/html",
572 FILE_PATH_LITERAL("/foo/con.htm") },
573 { FILE_PATH_LITERAL("/foo/con"),
574 "text/html",
575 FILE_PATH_LITERAL("/foo/con.html") },
576 #endif // OS_WIN
577 };
578
579 TEST(DownloadUtilTest, GenerateSafeFileName) {
580 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSafeFilenameCases); ++i) {
581 FilePath path(kSafeFilenameCases[i].path);
582 download_util::GenerateSafeFileName(kSafeFilenameCases[i].mime_type, &path);
583 EXPECT_EQ(kSafeFilenameCases[i].expected_path, path.value());
584 }
585 }
586
587 } // namespace
588
OLDNEW
« no previous file with comments | « chrome/browser/download/download_util.cc ('k') | chrome/browser/download/save_package.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698