OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "third_party/zlib/google/zip_reader.h" | 5 #include "third_party/zlib/google/zip_reader.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file.h" | 8 #include "base/files/file.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "base/thread_task_runner_handle.h" | |
13 #include "third_party/zlib/google/zip_internal.h" | 14 #include "third_party/zlib/google/zip_internal.h" |
14 | 15 |
15 #if defined(USE_SYSTEM_MINIZIP) | 16 #if defined(USE_SYSTEM_MINIZIP) |
16 #include <minizip/unzip.h> | 17 #include <minizip/unzip.h> |
17 #else | 18 #else |
18 #include "third_party/zlib/contrib/minizip/unzip.h" | 19 #include "third_party/zlib/contrib/minizip/unzip.h" |
19 #if defined(OS_WIN) | 20 #if defined(OS_WIN) |
20 #include "third_party/zlib/contrib/minizip/iowin32.h" | 21 #include "third_party/zlib/contrib/minizip/iowin32.h" |
21 #endif // defined(OS_WIN) | 22 #endif // defined(OS_WIN) |
22 #endif // defined(USE_SYSTEM_MINIZIP) | 23 #endif // defined(USE_SYSTEM_MINIZIP) |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 // TODO(satorux): The implementation assumes that file names in zip files | 124 // TODO(satorux): The implementation assumes that file names in zip files |
124 // are encoded in UTF-8. This is true for zip files created by Zip() | 125 // are encoded in UTF-8. This is true for zip files created by Zip() |
125 // function in zip.h, but not true for user-supplied random zip files. | 126 // function in zip.h, but not true for user-supplied random zip files. |
126 ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip, | 127 ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip, |
127 const unz_file_info& raw_file_info) | 128 const unz_file_info& raw_file_info) |
128 : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)), | 129 : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)), |
129 is_directory_(false) { | 130 is_directory_(false) { |
130 original_size_ = raw_file_info.uncompressed_size; | 131 original_size_ = raw_file_info.uncompressed_size; |
131 | 132 |
132 // Directory entries in zip files end with "/". | 133 // Directory entries in zip files end with "/". |
133 is_directory_ = EndsWith(file_name_in_zip, "/", false); | 134 is_directory_ = base::EndsWith(file_name_in_zip, "/", |
135 base::CompareCase::INSENSITIVE_ASCII); | |
viettrungluu
2016/01/28 21:32:46
The case insensitivity seems kind of stupid here (
| |
134 | 136 |
135 // Check the file name here for directory traversal issues. | 137 // Check the file name here for directory traversal issues. |
136 is_unsafe_ = file_path_.ReferencesParent(); | 138 is_unsafe_ = file_path_.ReferencesParent(); |
137 | 139 |
138 // We also consider that the file name is unsafe, if it's invalid UTF-8. | 140 // We also consider that the file name is unsafe, if it's invalid UTF-8. |
139 base::string16 file_name_utf16; | 141 base::string16 file_name_utf16; |
140 if (!base::UTF8ToUTF16(file_name_in_zip.data(), file_name_in_zip.size(), | 142 if (!base::UTF8ToUTF16(file_name_in_zip.data(), file_name_in_zip.size(), |
141 &file_name_utf16)) { | 143 &file_name_utf16)) { |
142 is_unsafe_ = true; | 144 is_unsafe_ = true; |
143 } | 145 } |
144 | 146 |
145 // We also consider that the file name is unsafe, if it's absolute. | 147 // We also consider that the file name is unsafe, if it's absolute. |
146 // On Windows, IsAbsolute() returns false for paths starting with "/". | 148 // On Windows, IsAbsolute() returns false for paths starting with "/". |
147 if (file_path_.IsAbsolute() || StartsWithASCII(file_name_in_zip, "/", false)) | 149 if (file_path_.IsAbsolute() || |
150 base::StartsWithASCII(file_name_in_zip, "/", false)) | |
148 is_unsafe_ = true; | 151 is_unsafe_ = true; |
149 | 152 |
150 // Construct the last modified time. The timezone info is not present in | 153 // Construct the last modified time. The timezone info is not present in |
151 // zip files, so we construct the time as local time. | 154 // zip files, so we construct the time as local time. |
152 base::Time::Exploded exploded_time = {}; // Zero-clear. | 155 base::Time::Exploded exploded_time = {}; // Zero-clear. |
153 exploded_time.year = raw_file_info.tmu_date.tm_year; | 156 exploded_time.year = raw_file_info.tmu_date.tm_year; |
154 // The month in zip file is 0-based, whereas ours is 1-based. | 157 // The month in zip file is 0-based, whereas ours is 1-based. |
155 exploded_time.month = raw_file_info.tmu_date.tm_mon + 1; | 158 exploded_time.month = raw_file_info.tmu_date.tm_mon + 1; |
156 exploded_time.day_of_month = raw_file_info.tmu_date.tm_mday; | 159 exploded_time.day_of_month = raw_file_info.tmu_date.tm_mday; |
157 exploded_time.hour = raw_file_info.tmu_date.tm_hour; | 160 exploded_time.hour = raw_file_info.tmu_date.tm_hour; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 const base::FilePath& output_file_path, | 351 const base::FilePath& output_file_path, |
349 const SuccessCallback& success_callback, | 352 const SuccessCallback& success_callback, |
350 const FailureCallback& failure_callback, | 353 const FailureCallback& failure_callback, |
351 const ProgressCallback& progress_callback) { | 354 const ProgressCallback& progress_callback) { |
352 DCHECK(zip_file_); | 355 DCHECK(zip_file_); |
353 DCHECK(current_entry_info_.get()); | 356 DCHECK(current_entry_info_.get()); |
354 | 357 |
355 // If this is a directory, just create it and return. | 358 // If this is a directory, just create it and return. |
356 if (current_entry_info()->is_directory()) { | 359 if (current_entry_info()->is_directory()) { |
357 if (base::CreateDirectory(output_file_path)) { | 360 if (base::CreateDirectory(output_file_path)) { |
358 base::MessageLoopProxy::current()->PostTask(FROM_HERE, success_callback); | 361 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
362 success_callback); | |
359 } else { | 363 } else { |
360 DVLOG(1) << "Unzip failed: unable to create directory."; | 364 DVLOG(1) << "Unzip failed: unable to create directory."; |
361 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); | 365 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
366 failure_callback); | |
362 } | 367 } |
363 return; | 368 return; |
364 } | 369 } |
365 | 370 |
366 if (unzOpenCurrentFile(zip_file_) != UNZ_OK) { | 371 if (unzOpenCurrentFile(zip_file_) != UNZ_OK) { |
367 DVLOG(1) << "Unzip failed: unable to open current zip entry."; | 372 DVLOG(1) << "Unzip failed: unable to open current zip entry."; |
368 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); | 373 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, failure_callback); |
369 return; | 374 return; |
370 } | 375 } |
371 | 376 |
372 base::FilePath output_dir_path = output_file_path.DirName(); | 377 base::FilePath output_dir_path = output_file_path.DirName(); |
373 if (!base::CreateDirectory(output_dir_path)) { | 378 if (!base::CreateDirectory(output_dir_path)) { |
374 DVLOG(1) << "Unzip failed: unable to create containing directory."; | 379 DVLOG(1) << "Unzip failed: unable to create containing directory."; |
375 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); | 380 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, failure_callback); |
376 return; | 381 return; |
377 } | 382 } |
378 | 383 |
379 const int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; | 384 const int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; |
380 base::File output_file(output_file_path, flags); | 385 base::File output_file(output_file_path, flags); |
381 | 386 |
382 if (!output_file.IsValid()) { | 387 if (!output_file.IsValid()) { |
383 DVLOG(1) << "Unzip failed: unable to create platform file at " | 388 DVLOG(1) << "Unzip failed: unable to create platform file at " |
384 << output_file_path.value(); | 389 << output_file_path.value(); |
385 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); | 390 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, failure_callback); |
386 return; | 391 return; |
387 } | 392 } |
388 | 393 |
389 base::MessageLoop::current()->PostTask( | 394 base::MessageLoop::current()->PostTask( |
390 FROM_HERE, | 395 FROM_HERE, |
391 base::Bind(&ZipReader::ExtractChunk, | 396 base::Bind(&ZipReader::ExtractChunk, |
392 weak_ptr_factory_.GetWeakPtr(), | 397 weak_ptr_factory_.GetWeakPtr(), |
393 Passed(output_file.Pass()), | 398 Passed(output_file.Pass()), |
394 success_callback, | 399 success_callback, |
395 failure_callback, | 400 failure_callback, |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 } | 535 } |
531 | 536 |
532 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { | 537 bool FileWriterDelegate::WriteBytes(const char* data, int num_bytes) { |
533 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); | 538 int bytes_written = file_->WriteAtCurrentPos(data, num_bytes); |
534 if (bytes_written > 0) | 539 if (bytes_written > 0) |
535 file_length_ += bytes_written; | 540 file_length_ += bytes_written; |
536 return bytes_written == num_bytes; | 541 return bytes_written == num_bytes; |
537 } | 542 } |
538 | 543 |
539 } // namespace zip | 544 } // namespace zip |
OLD | NEW |