Index: chrome/common/zip.cc |
diff --git a/chrome/common/zip.cc b/chrome/common/zip.cc |
index 008ff06d23e9727c10b1aaaacd23e4d6d96b47fa..c6dc6fa3d99b2958b62e8663fbdcd6517001b6e5 100644 |
--- a/chrome/common/zip.cc |
+++ b/chrome/common/zip.cc |
@@ -10,93 +10,13 @@ |
#include "base/string16.h" |
#include "base/string_util.h" |
#include "chrome/common/zip_internal.h" |
+#include "chrome/common/zip_reader.h" |
#include "net/base/file_stream.h" |
#include "third_party/zlib/contrib/minizip/unzip.h" |
#include "third_party/zlib/contrib/minizip/zip.h" |
namespace { |
-// Extract the 'current' selected file from the zip into dest_dir. |
-// Output filename is stored in out_file. Returns true on success. |
-bool ExtractCurrentFile(unzFile zip_file, |
- const FilePath& dest_dir) { |
- // We assume that the file names in zip files to be UTF-8. This is true |
- // for zip files created with Zip() and friends in the file. |
- char filename_in_zip_utf8[zip::internal::kZipMaxPath] = {0}; |
- unz_file_info file_info; |
- int err = unzGetCurrentFileInfo( |
- zip_file, &file_info, filename_in_zip_utf8, |
- sizeof(filename_in_zip_utf8) - 1, NULL, 0, NULL, 0); |
- if (err != UNZ_OK) |
- return false; |
- if (filename_in_zip_utf8[0] == '\0') |
- return false; |
- |
- err = unzOpenCurrentFile(zip_file); |
- if (err != UNZ_OK) |
- return false; |
- |
- // Use of "Unsafe" function looks not good, but there is no safe way to |
- // do this on Linux anyway. See file_path.h for details. |
- FilePath file_path_in_zip = FilePath::FromUTF8Unsafe(filename_in_zip_utf8); |
- |
- // Check the filename here for directory traversal issues. In the name of |
- // simplicity and security, we might reject a valid filename such as "a..b". |
- if (file_path_in_zip.value().find(FILE_PATH_LITERAL("..")) |
- != FilePath::StringType::npos) |
- return false; |
- |
- FilePath dest_file = dest_dir.Append(file_path_in_zip); |
- |
- // If this is a directory, just create it and return. |
- if (EndsWith(filename_in_zip_utf8, "/", false)) { |
- if (!file_util::CreateDirectory(dest_file)) |
- return false; |
- return true; |
- } |
- |
- // We can't rely on parent directory entries being specified in the zip, so we |
- // make sure they are created. |
- FilePath dir = dest_file.DirName(); |
- if (!file_util::CreateDirectory(dir)) |
- return false; |
- |
- net::FileStream stream; |
- int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE; |
- if (stream.Open(dest_file, flags) != 0) |
- return false; |
- |
- bool ret = true; |
- int num_bytes = 0; |
- char buf[zip::internal::kZipBufSize]; |
- do { |
- num_bytes = unzReadCurrentFile(zip_file, buf, zip::internal::kZipBufSize); |
- if (num_bytes < 0) { |
- // If num_bytes < 0, then it's a specific UNZ_* error code. |
- // While we're not currently handling these codes specifically, save |
- // it away in case we want to in the future. |
- err = num_bytes; |
- break; |
- } |
- if (num_bytes > 0) { |
- if (num_bytes != stream.Write(buf, num_bytes, |
- net::CompletionCallback())) { |
- ret = false; |
- break; |
- } |
- } |
- } while (num_bytes > 0); |
- |
- stream.Close(); |
- if (err == UNZ_OK) |
- err = unzCloseCurrentFile(zip_file); |
- else |
- unzCloseCurrentFile(zip_file); // Don't lose the original error code. |
- if (err != UNZ_OK) |
- ret = false; |
- return ret; |
-} |
- |
bool AddFileToZip(zipFile zip_file, const FilePath& src_dir) { |
net::FileStream stream; |
int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; |
@@ -170,36 +90,32 @@ bool ExcludeHiddenFilesFilter(const FilePath& file_path) { |
namespace zip { |
bool Unzip(const FilePath& src_file, const FilePath& dest_dir) { |
- unzFile zip_file = internal::OpenForUnzipping(src_file.AsUTF8Unsafe()); |
- if (!zip_file) { |
- DLOG(WARNING) << "couldn't create file " << src_file.value(); |
- return false; |
- } |
- unz_global_info zip_info; |
- int err; |
- err = unzGetGlobalInfo(zip_file, &zip_info); |
- if (err != UNZ_OK) { |
- DLOG(WARNING) << "couldn't open zip " << src_file.value(); |
+ ZipReader reader; |
+ if (!reader.Open(src_file)) { |
+ DLOG(WARNING) << "Failed to open " << src_file.value(); |
return false; |
} |
- bool ret = true; |
- for (unsigned int i = 0; i < zip_info.number_entry; ++i) { |
- if (!ExtractCurrentFile(zip_file, dest_dir)) { |
- ret = false; |
- break; |
+ while (reader.HasMore()) { |
+ if (!reader.OpenCurrentEntryInZip()) { |
+ DLOG(WARNING) << "Failed to open the current file in zip"; |
+ return false; |
} |
- |
- if (i + 1 < zip_info.number_entry) { |
- err = unzGoToNextFile(zip_file); |
- if (err != UNZ_OK) { |
- DLOG(WARNING) << "error %d in unzGoToNextFile"; |
- ret = false; |
- break; |
- } |
+ if (reader.current_entry_info()->is_unsafe()) { |
+ DLOG(WARNING) << "Found an unsafe file in zip " |
+ << reader.current_entry_info()->file_path().value(); |
+ return false; |
+ } |
+ if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) { |
+ DLOG(WARNING) << "Failed to extract " |
+ << reader.current_entry_info()->file_path().value(); |
+ return false; |
+ } |
+ if (!reader.AdvanceToNextEntry()) { |
+ DLOG(WARNING) << "Failed to advance to the next file"; |
+ return false; |
} |
} |
- unzClose(zip_file); |
- return ret; |
+ return true; |
} |
bool ZipWithFilterCallback(const FilePath& src_dir, const FilePath& dest_file, |