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/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 zip_file_ = internal::OpenHandleForUnzipping(zip_fd); | 100 zip_file_ = internal::OpenHandleForUnzipping(zip_fd); |
101 #endif | 101 #endif |
102 if (!zip_file_) { | 102 if (!zip_file_) { |
103 return false; | 103 return false; |
104 } | 104 } |
105 | 105 |
106 return OpenInternal(); | 106 return OpenInternal(); |
107 } | 107 } |
108 | 108 |
109 bool ZipReader::OpenFromString(const std::string& data) { | 109 bool ZipReader::OpenFromString(const std::string& data) { |
110 zip_file_ = internal::PreprareMemoryForUnzipping(data); | 110 zip_file_ = internal::PrepareMemoryForUnzipping(data); |
111 if (!zip_file_) | 111 if (!zip_file_) |
112 return false; | 112 return false; |
113 return OpenInternal(); | 113 return OpenInternal(); |
114 } | 114 } |
115 | 115 |
116 void ZipReader::Close() { | 116 void ZipReader::Close() { |
117 if (zip_file_) { | 117 if (zip_file_) { |
118 unzClose(zip_file_); | 118 unzClose(zip_file_); |
119 } | 119 } |
120 Reset(); | 120 Reset(); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 break; | 344 break; |
345 } | 345 } |
346 } | 346 } |
347 } | 347 } |
348 | 348 |
349 unzCloseCurrentFile(zip_file_); | 349 unzCloseCurrentFile(zip_file_); |
350 return success; | 350 return success; |
351 } | 351 } |
352 #endif // defined(OS_POSIX) | 352 #endif // defined(OS_POSIX) |
353 | 353 |
| 354 bool ZipReader::ExtractCurrentEntryToString( |
| 355 size_t max_read_bytes, |
| 356 std::string* output) const { |
| 357 DCHECK(output); |
| 358 DCHECK(zip_file_); |
| 359 DCHECK(max_read_bytes != 0); |
| 360 |
| 361 if (current_entry_info()->is_directory()) { |
| 362 output->clear(); |
| 363 return true; |
| 364 } |
| 365 |
| 366 const int open_result = unzOpenCurrentFile(zip_file_); |
| 367 if (open_result != UNZ_OK) |
| 368 return false; |
| 369 |
| 370 // The original_size() is the best hint for the real size, so it saves |
| 371 // doing reallocations for the common case when the uncompressed size is |
| 372 // correct. However, we need to assume that the uncompressed size could be |
| 373 // incorrect therefore this function needs to read as much data as possible. |
| 374 std::string contents; |
| 375 contents.reserve(std::min<size_t>( |
| 376 max_read_bytes, current_entry_info()->original_size()) + 1); |
| 377 |
| 378 size_t buffer_index = 0; |
| 379 bool success = true; |
| 380 while (true) { |
| 381 // This just sets size() to be equal to capacity() so the chars which are re
ad |
| 382 // ahead will not be erased by calling resize() later. |
| 383 contents.resize(contents.capacity()); |
| 384 |
| 385 const size_t bytes_to_read = contents.capacity() - buffer_index; |
| 386 const int bytes_to_read_really = std::min<int>(INT_MAX, bytes_to_read); |
| 387 const int bytes_read = unzReadCurrentFile( |
| 388 zip_file_, |
| 389 &(contents[buffer_index]), |
| 390 bytes_to_read_really); |
| 391 DCHECK(bytes_read <= bytes_to_read_really); |
| 392 |
| 393 if (bytes_read == 0) { |
| 394 contents.resize(buffer_index); |
| 395 // Reached the end of the file. |
| 396 break; |
| 397 } else if (bytes_read < 0) { |
| 398 // If num_bytes_read < 0, then it's a specific UNZ_* error code. |
| 399 success = false; |
| 400 break; |
| 401 } else { // if (num_bytes_read > 0) |
| 402 buffer_index += bytes_read; |
| 403 |
| 404 if (buffer_index > max_read_bytes) { |
| 405 success = false; |
| 406 break; |
| 407 } |
| 408 |
| 409 if (bytes_read == bytes_to_read_really) { |
| 410 // Filled up the buffer, no more space left, need to resize. |
| 411 if (static_cast<size_t>(bytes_to_read_really) == bytes_to_read) |
| 412 contents.reserve(contents.capacity() + internal::kZipBufSize); |
| 413 } else { |
| 414 contents.resize(buffer_index); |
| 415 // Read less bytes than asked. That means it reached end of file. |
| 416 break; |
| 417 } |
| 418 } |
| 419 } |
| 420 |
| 421 unzCloseCurrentFile(zip_file_); |
| 422 if (success) |
| 423 output->swap(contents); |
| 424 |
| 425 return success; |
| 426 } |
| 427 |
354 bool ZipReader::OpenInternal() { | 428 bool ZipReader::OpenInternal() { |
355 DCHECK(zip_file_); | 429 DCHECK(zip_file_); |
356 | 430 |
357 unz_global_info zip_info = {}; // Zero-clear. | 431 unz_global_info zip_info = {}; // Zero-clear. |
358 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { | 432 if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) { |
359 return false; | 433 return false; |
360 } | 434 } |
361 num_entries_ = zip_info.number_entry; | 435 num_entries_ = zip_info.number_entry; |
362 if (num_entries_ < 0) | 436 if (num_entries_ < 0) |
363 return false; | 437 return false; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 success_callback, | 491 success_callback, |
418 failure_callback, | 492 failure_callback, |
419 progress_callback, | 493 progress_callback, |
420 current_progress)); | 494 current_progress)); |
421 | 495 |
422 } | 496 } |
423 } | 497 } |
424 | 498 |
425 | 499 |
426 } // namespace zip | 500 } // namespace zip |
OLD | NEW |