Index: third_party/zlib/google/zip_internal.cc |
diff --git a/third_party/zlib/google/zip_internal.cc b/third_party/zlib/google/zip_internal.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..77f2b174819a8ba6e907980c806a83a2d46ad43f |
--- /dev/null |
+++ b/third_party/zlib/google/zip_internal.cc |
@@ -0,0 +1,390 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "third_party/zlib/google/zip_internal.h" |
+ |
+#include <stddef.h> |
+ |
+#include <algorithm> |
+ |
+#include "base/files/file_util.h" |
+#include "base/logging.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/time/time.h" |
+#include "build/build_config.h" |
+ |
+#if defined(USE_SYSTEM_MINIZIP) |
+#include <minizip/ioapi.h> |
+#include <minizip/unzip.h> |
+#include <minizip/zip.h> |
+#else |
+#include "third_party/zlib/contrib/minizip/unzip.h" |
+#include "third_party/zlib/contrib/minizip/zip.h" |
+#if defined(OS_WIN) |
+#include "third_party/zlib/contrib/minizip/iowin32.h" |
+#elif defined(OS_POSIX) |
+#include "third_party/zlib/contrib/minizip/ioapi.h" |
+#endif // defined(OS_POSIX) |
+#endif // defined(USE_SYSTEM_MINIZIP) |
+ |
+namespace { |
+ |
+#if defined(OS_WIN) |
+typedef struct { |
+ HANDLE hf; |
+ int error; |
+} WIN32FILE_IOWIN; |
+ |
+// This function is derived from third_party/minizip/iowin32.c. |
+// Its only difference is that it treats the char* as UTF8 and |
+// uses the Unicode version of CreateFile. |
+void* ZipOpenFunc(void *opaque, const char* filename, int mode) { |
+ DWORD desired_access = 0, creation_disposition = 0; |
+ DWORD share_mode = 0, flags_and_attributes = 0; |
+ HANDLE file = 0; |
+ void* ret = NULL; |
+ |
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) { |
+ desired_access = GENERIC_READ; |
+ creation_disposition = OPEN_EXISTING; |
+ share_mode = FILE_SHARE_READ; |
+ } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { |
+ desired_access = GENERIC_WRITE | GENERIC_READ; |
+ creation_disposition = OPEN_EXISTING; |
+ } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { |
+ desired_access = GENERIC_WRITE | GENERIC_READ; |
+ creation_disposition = CREATE_ALWAYS; |
+ } |
+ |
+ base::string16 filename16 = base::UTF8ToUTF16(filename); |
+ if ((filename != NULL) && (desired_access != 0)) { |
+ file = CreateFile(filename16.c_str(), desired_access, share_mode, |
+ NULL, creation_disposition, flags_and_attributes, NULL); |
+ } |
+ |
+ if (file == INVALID_HANDLE_VALUE) |
+ file = NULL; |
+ |
+ if (file != NULL) { |
+ WIN32FILE_IOWIN file_ret; |
+ file_ret.hf = file; |
+ file_ret.error = 0; |
+ ret = malloc(sizeof(WIN32FILE_IOWIN)); |
+ if (ret == NULL) |
+ CloseHandle(file); |
+ else |
+ *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret; |
+ } |
+ return ret; |
+} |
+#endif |
+ |
+#if defined(OS_POSIX) |
+// Callback function for zlib that opens a file stream from a file descriptor. |
+// Since we do not own the file descriptor, dup it so that we can fdopen/fclose |
+// a file stream. |
+void* FdOpenFileFunc(void* opaque, const char* filename, int mode) { |
+ FILE* file = NULL; |
+ const char* mode_fopen = NULL; |
+ |
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) |
+ mode_fopen = "rb"; |
+ else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) |
+ mode_fopen = "r+b"; |
+ else if (mode & ZLIB_FILEFUNC_MODE_CREATE) |
+ mode_fopen = "wb"; |
+ |
+ if ((filename != NULL) && (mode_fopen != NULL)) { |
+ int fd = dup(*static_cast<int*>(opaque)); |
+ if (fd != -1) |
+ file = fdopen(fd, mode_fopen); |
+ } |
+ |
+ return file; |
+} |
+ |
+int FdCloseFileFunc(void* opaque, void* stream) { |
+ fclose(static_cast<FILE*>(stream)); |
+ free(opaque); // malloc'ed in FillFdOpenFileFunc() |
+ return 0; |
+} |
+ |
+// Fills |pzlib_filecunc_def| appropriately to handle the zip file |
+// referred to by |fd|. |
+void FillFdOpenFileFunc(zlib_filefunc_def* pzlib_filefunc_def, int fd) { |
+ fill_fopen_filefunc(pzlib_filefunc_def); |
+ pzlib_filefunc_def->zopen_file = FdOpenFileFunc; |
+ pzlib_filefunc_def->zclose_file = FdCloseFileFunc; |
+ int* ptr_fd = static_cast<int*>(malloc(sizeof(fd))); |
+ *ptr_fd = fd; |
+ pzlib_filefunc_def->opaque = ptr_fd; |
+} |
+#endif // defined(OS_POSIX) |
+ |
+#if defined(OS_WIN) |
+// Callback function for zlib that opens a file stream from a Windows handle. |
+// Does not take ownership of the handle. |
+void* HandleOpenFileFunc(void* opaque, const char* filename, int mode) { |
+ WIN32FILE_IOWIN file_ret; |
+ file_ret.hf = static_cast<HANDLE>(opaque); |
+ file_ret.error = 0; |
+ if (file_ret.hf == INVALID_HANDLE_VALUE) |
+ return NULL; |
+ |
+ void* ret = malloc(sizeof(WIN32FILE_IOWIN)); |
+ if (ret != NULL) |
+ *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret; |
+ return ret; |
+} |
+ |
+int HandleCloseFileFunc(void* opaque, void* stream) { |
+ free(stream); // malloc'ed in HandleOpenFileFunc() |
+ return 0; |
+} |
+#endif |
+ |
+// A struct that contains data required for zlib functions to extract files from |
+// a zip archive stored in memory directly. The following I/O API functions |
+// expect their opaque parameters refer to this struct. |
+struct ZipBuffer { |
+ const char* data; // weak |
+ size_t length; |
+ size_t offset; |
+}; |
+ |
+// Opens the specified file. When this function returns a non-NULL pointer, zlib |
+// uses this pointer as a stream parameter while compressing or uncompressing |
+// data. (Returning NULL represents an error.) This function initializes the |
+// given opaque parameter and returns it because this parameter stores all |
+// information needed for uncompressing data. (This function does not support |
+// writing compressed data and it returns NULL for this case.) |
+void* OpenZipBuffer(void* opaque, const char* /*filename*/, int mode) { |
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) { |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+ ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); |
+ if (!buffer || !buffer->data || !buffer->length) |
+ return NULL; |
+ buffer->offset = 0; |
+ return opaque; |
+} |
+ |
+// Reads compressed data from the specified stream. This function copies data |
+// refered by the opaque parameter and returns the size actually copied. |
+uLong ReadZipBuffer(void* opaque, void* /*stream*/, void* buf, uLong size) { |
+ ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); |
+ DCHECK_LE(buffer->offset, buffer->length); |
+ size_t remaining_bytes = buffer->length - buffer->offset; |
+ if (!buffer || !buffer->data || !remaining_bytes) |
+ return 0; |
+ size = std::min(size, static_cast<uLong>(remaining_bytes)); |
+ memcpy(buf, &buffer->data[buffer->offset], size); |
+ buffer->offset += size; |
+ return size; |
+} |
+ |
+// Writes compressed data to the stream. This function always returns zero |
+// because this implementation is only for reading compressed data. |
+uLong WriteZipBuffer(void* /*opaque*/, |
+ void* /*stream*/, |
+ const void* /*buf*/, |
+ uLong /*size*/) { |
+ NOTREACHED(); |
+ return 0; |
+} |
+ |
+// Returns the offset from the beginning of the data. |
+long GetOffsetOfZipBuffer(void* opaque, void* /*stream*/) { |
+ ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); |
+ if (!buffer) |
+ return -1; |
+ return static_cast<long>(buffer->offset); |
+} |
+ |
+// Moves the current offset to the specified position. |
+long SeekZipBuffer(void* opaque, void* /*stream*/, uLong offset, int origin) { |
+ ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); |
+ if (!buffer) |
+ return -1; |
+ if (origin == ZLIB_FILEFUNC_SEEK_CUR) { |
+ buffer->offset = std::min(buffer->offset + static_cast<size_t>(offset), |
+ buffer->length); |
+ return 0; |
+ } |
+ if (origin == ZLIB_FILEFUNC_SEEK_END) { |
+ buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0; |
+ return 0; |
+ } |
+ if (origin == ZLIB_FILEFUNC_SEEK_SET) { |
+ buffer->offset = std::min(buffer->length, static_cast<size_t>(offset)); |
+ return 0; |
+ } |
+ NOTREACHED(); |
+ return -1; |
+} |
+ |
+// Closes the input offset and deletes all resources used for compressing or |
+// uncompressing data. This function deletes the ZipBuffer object referred by |
+// the opaque parameter since zlib deletes the unzFile object and it does not |
+// use this object any longer. |
+int CloseZipBuffer(void* opaque, void* /*stream*/) { |
+ if (opaque) |
+ free(opaque); |
+ return 0; |
+} |
+ |
+// Returns the last error happened when reading or writing data. This function |
+// always returns zero, which means there are not any errors. |
+int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) { |
+ return 0; |
+} |
+ |
+// Returns a zip_fileinfo struct with the time represented by |file_time|. |
+zip_fileinfo TimeToZipFileInfo(const base::Time& file_time) { |
+ base::Time::Exploded file_time_parts; |
+ file_time.LocalExplode(&file_time_parts); |
+ |
+ zip_fileinfo zip_info = {}; |
+ if (file_time_parts.year >= 1980) { |
+ // This if check works around the handling of the year value in |
+ // contrib/minizip/zip.c in function zip64local_TmzDateToDosDate |
+ // It assumes that dates below 1980 are in the double digit format. |
+ // Hence the fail safe option is to leave the date unset. Some programs |
+ // might show the unset date as 1980-0-0 which is invalid. |
+ zip_info.tmz_date.tm_year = file_time_parts.year; |
+ zip_info.tmz_date.tm_mon = file_time_parts.month - 1; |
+ zip_info.tmz_date.tm_mday = file_time_parts.day_of_month; |
+ zip_info.tmz_date.tm_hour = file_time_parts.hour; |
+ zip_info.tmz_date.tm_min = file_time_parts.minute; |
+ zip_info.tmz_date.tm_sec = file_time_parts.second; |
+ } |
+ |
+ return zip_info; |
+} |
+} // namespace |
+ |
+namespace zip { |
+namespace internal { |
+ |
+unzFile OpenForUnzipping(const std::string& file_name_utf8) { |
+ zlib_filefunc_def* zip_func_ptrs = NULL; |
+#if defined(OS_WIN) |
+ zlib_filefunc_def zip_funcs; |
+ fill_win32_filefunc(&zip_funcs); |
+ zip_funcs.zopen_file = ZipOpenFunc; |
+ zip_func_ptrs = &zip_funcs; |
+#endif |
+ return unzOpen2(file_name_utf8.c_str(), zip_func_ptrs); |
+} |
+ |
+#if defined(OS_POSIX) |
+unzFile OpenFdForUnzipping(int zip_fd) { |
+ zlib_filefunc_def zip_funcs; |
+ FillFdOpenFileFunc(&zip_funcs, zip_fd); |
+ // Passing dummy "fd" filename to zlib. |
+ return unzOpen2("fd", &zip_funcs); |
+} |
+#endif |
+ |
+#if defined(OS_WIN) |
+unzFile OpenHandleForUnzipping(HANDLE zip_handle) { |
+ zlib_filefunc_def zip_funcs; |
+ fill_win32_filefunc(&zip_funcs); |
+ zip_funcs.zopen_file = HandleOpenFileFunc; |
+ zip_funcs.zclose_file = HandleCloseFileFunc; |
+ zip_funcs.opaque = zip_handle; |
+ return unzOpen2("fd", &zip_funcs); |
+} |
+#endif |
+ |
+// static |
+unzFile PrepareMemoryForUnzipping(const std::string& data) { |
+ if (data.empty()) |
+ return NULL; |
+ |
+ ZipBuffer* buffer = static_cast<ZipBuffer*>(malloc(sizeof(ZipBuffer))); |
+ if (!buffer) |
+ return NULL; |
+ buffer->data = data.data(); |
+ buffer->length = data.length(); |
+ buffer->offset = 0; |
+ |
+ zlib_filefunc_def zip_functions; |
+ zip_functions.zopen_file = OpenZipBuffer; |
+ zip_functions.zread_file = ReadZipBuffer; |
+ zip_functions.zwrite_file = WriteZipBuffer; |
+ zip_functions.ztell_file = GetOffsetOfZipBuffer; |
+ zip_functions.zseek_file = SeekZipBuffer; |
+ zip_functions.zclose_file = CloseZipBuffer; |
+ zip_functions.zerror_file = GetErrorOfZipBuffer; |
+ zip_functions.opaque = static_cast<void*>(buffer); |
+ return unzOpen2(NULL, &zip_functions); |
+} |
+ |
+zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag) { |
+ zlib_filefunc_def* zip_func_ptrs = NULL; |
+#if defined(OS_WIN) |
+ zlib_filefunc_def zip_funcs; |
+ fill_win32_filefunc(&zip_funcs); |
+ zip_funcs.zopen_file = ZipOpenFunc; |
+ zip_func_ptrs = &zip_funcs; |
+#endif |
+ return zipOpen2(file_name_utf8.c_str(), |
+ append_flag, |
+ NULL, // global comment |
+ zip_func_ptrs); |
+} |
+ |
+#if defined(OS_POSIX) |
+zipFile OpenFdForZipping(int zip_fd, int append_flag) { |
+ zlib_filefunc_def zip_funcs; |
+ FillFdOpenFileFunc(&zip_funcs, zip_fd); |
+ // Passing dummy "fd" filename to zlib. |
+ return zipOpen2("fd", append_flag, NULL, &zip_funcs); |
+} |
+#endif |
+ |
+zip_fileinfo GetFileInfoForZipping(const base::FilePath& path) { |
+ base::Time file_time; |
+ base::File::Info file_info; |
+ if (base::GetFileInfo(path, &file_info)) |
+ file_time = file_info.last_modified; |
+ return TimeToZipFileInfo(file_time); |
+} |
+ |
+bool ZipOpenNewFileInZip(zipFile zip_file, |
+ const std::string& str_path, |
+ const zip_fileinfo* file_info) { |
+ // Section 4.4.4 http://www.pkware.com/documents/casestudies/APPNOTE.TXT |
+ // Setting the Language encoding flag so the file is told to be in utf-8. |
+ const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11; |
+ |
+ if (ZIP_OK != zipOpenNewFileInZip4( |
+ zip_file, // file |
+ str_path.c_str(), // filename |
+ file_info, // zipfi |
+ NULL, // extrafield_local, |
+ 0u, // size_extrafield_local |
+ NULL, // extrafield_global |
+ 0u, // size_extrafield_global |
+ NULL, // comment |
+ Z_DEFLATED, // method |
+ Z_DEFAULT_COMPRESSION, // level |
+ 0, // raw |
+ -MAX_WBITS, // windowBits |
+ DEF_MEM_LEVEL, // memLevel |
+ Z_DEFAULT_STRATEGY, // strategy |
+ NULL, // password |
+ 0, // crcForCrypting |
+ 0, // versionMadeBy |
+ LANGUAGE_ENCODING_FLAG)) { // flagBase |
+ DLOG(ERROR) << "Could not open zip file entry " << str_path; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // namespace internal |
+} // namespace zip |