15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "third_party/zlib/google/zip_internal.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/time/time.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_MINIZIP) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <minizip/ioapi.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <minizip/unzip.h> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <minizip/zip.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/contrib/minizip/unzip.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/contrib/minizip/zip.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/contrib/minizip/iowin32.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/contrib/minizip/ioapi.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_POSIX) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(USE_SYSTEM_MINIZIP) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hf; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} WIN32FILE_IOWIN; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is derived from third_party/minizip/iowin32.c. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Its only difference is that it treats the char* as UTF8 and 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// uses the Unicode version of CreateFile. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* ZipOpenFunc(void *opaque, const char* filename, int mode) { 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DWORD desired_access = 0, creation_disposition = 0; 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DWORD share_mode = 0, flags_and_attributes = 0; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE file = 0; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* ret = NULL; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_access = GENERIC_READ; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_disposition = OPEN_EXISTING; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) share_mode = FILE_SHARE_READ; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_access = GENERIC_WRITE | GENERIC_READ; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_disposition = OPEN_EXISTING; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_access = GENERIC_WRITE | GENERIC_READ; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_disposition = CREATE_ALWAYS; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 filename16 = base::UTF8ToUTF16(filename); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((filename != NULL) && (desired_access != 0)) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file = CreateFile(filename16.c_str(), desired_access, share_mode, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, creation_disposition, flags_and_attributes, NULL); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file == INVALID_HANDLE_VALUE) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file = NULL; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file != NULL) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WIN32FILE_IOWIN file_ret; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_ret.hf = file; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_ret.error = 0; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = malloc(sizeof(WIN32FILE_IOWIN)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == NULL) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(file); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback function for zlib that opens a file stream from a file descriptor. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* FdOpenFileFunc(void* opaque, const char* filename, int mode) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file = NULL; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* mode_fopen = NULL; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode_fopen = "rb"; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode_fopen = "r+b"; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (mode & ZLIB_FILEFUNC_MODE_CREATE) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode_fopen = "wb"; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((filename != NULL) && (mode_fopen != NULL)) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file = fdopen(*static_cast<int*>(opaque), mode_fopen); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't actually close the file stream since that would close 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the underlying file descriptor, and we don't own it. However we do need to 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// flush buffers and free |opaque| since we malloc'ed it in FillFdOpenFileFunc. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseFileFunc(void* opaque, void* stream) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fflush(static_cast<FILE*>(stream)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(opaque); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fills |pzlib_filecunc_def| appropriately to handle the zip file 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// referred to by |fd|. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FillFdOpenFileFunc(zlib_filefunc_def* pzlib_filefunc_def, int fd) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fill_fopen_filefunc(pzlib_filefunc_def); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pzlib_filefunc_def->zopen_file = FdOpenFileFunc; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pzlib_filefunc_def->zclose_file = CloseFileFunc; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* ptr_fd = static_cast<int*>(malloc(sizeof(fd))); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr_fd = fd; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pzlib_filefunc_def->opaque = ptr_fd; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_POSIX) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Callback function for zlib that opens a file stream from a Windows handle. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* HandleOpenFileFunc(void* opaque, const char* filename, int mode) { 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WIN32FILE_IOWIN file_ret; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_ret.hf = static_cast<HANDLE>(opaque); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_ret.error = 0; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_ret.hf == INVALID_HANDLE_VALUE) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void* ret = malloc(sizeof(WIN32FILE_IOWIN)); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret != NULL) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A struct that contains data required for zlib functions to extract files from 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a zip archive stored in memory directly. The following I/O API functions 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expect their opaque parameters refer to this struct. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ZipBuffer { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data; // weak 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t offset; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opens the specified file. When this function returns a non-NULL pointer, zlib 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// uses this pointer as a stream parameter while compressing or uncompressing 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data. (Returning NULL represents an error.) This function initializes the 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// given opaque parameter and returns it because this parameter stores all 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// information needed for uncompressing data. (This function does not support 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writing compressed data and it returns NULL for this case.) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* OpenZipBuffer(void* opaque, const char* /*filename*/, int mode) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer || !buffer->data || !buffer->length) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset = 0; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return opaque; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads compressed data from the specified stream. This function copies data 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// refered by the opaque parameter and returns the size actually copied. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong ReadZipBuffer(void* opaque, void* /*stream*/, void* buf, uLong size) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(buffer->offset, buffer->length); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t remaining_bytes = buffer->length - buffer->offset; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer || !buffer->data || !remaining_bytes) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = std::min(size, static_cast<uLong>(remaining_bytes)); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(buf, &buffer->data[buffer->offset], size); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset += size; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Writes compressed data to the stream. This function always returns zero 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because this implementation is only for reading compressed data. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong WriteZipBuffer(void* /*opaque*/, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* /*stream*/, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* /*buf*/, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uLong /*size*/) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the offset from the beginning of the data. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long GetOffsetOfZipBuffer(void* opaque, void* /*stream*/) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<long>(buffer->offset); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Moves the current offset to the specified position. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)long SeekZipBuffer(void* opaque, void* /*stream*/, uLong offset, int origin) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin == ZLIB_FILEFUNC_SEEK_CUR) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset = std::min(buffer->offset + static_cast<size_t>(offset), 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->length); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin == ZLIB_FILEFUNC_SEEK_END) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin == ZLIB_FILEFUNC_SEEK_SET) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset = std::min(buffer->length, static_cast<size_t>(offset)); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Closes the input offset and deletes all resources used for compressing or 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// uncompressing data. This function deletes the ZipBuffer object referred by 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the opaque parameter since zlib deletes the unzFile object and it does not 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use this object any longer. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CloseZipBuffer(void* opaque, void* /*stream*/) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opaque) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(opaque); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the last error happened when reading or writing data. This function 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// always returns zero, which means there are not any errors. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Returns a zip_fileinfo struct with the time represented by |file_time|. 234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)zip_fileinfo TimeToZipFileInfo(const base::Time& file_time) { 235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Time::Exploded file_time_parts; 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) file_time.LocalExplode(&file_time_parts); 237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_fileinfo zip_info = {}; 239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (file_time_parts.year >= 1980) { 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // This if check works around the handling of the year value in 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // contrib/minizip/zip.c in function zip64local_TmzDateToDosDate 242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // It assumes that dates below 1980 are in the double digit format. 243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Hence the fail safe option is to leave the date unset. Some programs 244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // might show the unset date as 1980-0-0 which is invalid. 245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_year = file_time_parts.year; 246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_mon = file_time_parts.month - 1; 247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_mday = file_time_parts.day_of_month; 248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_hour = file_time_parts.hour; 249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_min = file_time_parts.minute; 250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_info.tmz_date.tm_sec = file_time_parts.second; 251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return zip_info; 254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace zip { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unzFile OpenForUnzipping(const std::string& file_name_utf8) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def* zip_func_ptrs = NULL; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def zip_funcs; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fill_win32_filefunc(&zip_funcs); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_funcs.zopen_file = ZipOpenFunc; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_func_ptrs = &zip_funcs; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return unzOpen2(file_name_utf8.c_str(), zip_func_ptrs); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unzFile OpenFdForUnzipping(int zip_fd) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def zip_funcs; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillFdOpenFileFunc(&zip_funcs, zip_fd); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Passing dummy "fd" filename to zlib. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return unzOpen2("fd", &zip_funcs); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)unzFile OpenHandleForUnzipping(HANDLE zip_handle) { 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zlib_filefunc_def zip_funcs; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fill_win32_filefunc(&zip_funcs); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zip_funcs.zopen_file = HandleOpenFileFunc; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zip_funcs.opaque = zip_handle; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return unzOpen2("fd", &zip_funcs); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)unzFile PrepareMemoryForUnzipping(const std::string& data) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data.empty()) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZipBuffer* buffer = static_cast<ZipBuffer*>(malloc(sizeof(ZipBuffer))); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->data = data.data(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->length = data.length(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->offset = 0; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def zip_functions; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zopen_file = OpenZipBuffer; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zread_file = ReadZipBuffer; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zwrite_file = WriteZipBuffer; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.ztell_file = GetOffsetOfZipBuffer; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zseek_file = SeekZipBuffer; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zclose_file = CloseZipBuffer; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.zerror_file = GetErrorOfZipBuffer; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_functions.opaque = static_cast<void*>(buffer); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return unzOpen2(NULL, &zip_functions); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def* zip_func_ptrs = NULL; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zlib_filefunc_def zip_funcs; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fill_win32_filefunc(&zip_funcs); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_funcs.zopen_file = ZipOpenFunc; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_func_ptrs = &zip_funcs; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zipOpen2(file_name_utf8.c_str(), 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) append_flag, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // global comment 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_func_ptrs); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_POSIX) 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)zipFile OpenFdForZipping(int zip_fd, int append_flag) { 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zlib_filefunc_def zip_funcs; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FillFdOpenFileFunc(&zip_funcs, zip_fd); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Passing dummy "fd" filename to zlib. 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return zipOpen2("fd", append_flag, NULL, &zip_funcs); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)zip_fileinfo GetFileInfoForZipping(const base::FilePath& path) { 338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Time file_time; 339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::File::Info file_info; 340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (base::GetFileInfo(path, &file_info)) 341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) file_time = file_info.last_modified; 342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return TimeToZipFileInfo(file_time); 343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ZipOpenNewFileInZip(zipFile zip_file, 346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& str_path, 347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const zip_fileinfo* file_info) { 348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Section 4.4.4 http://www.pkware.com/documents/casestudies/APPNOTE.TXT 349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Setting the Language encoding flag so the file is told to be in utf-8. 350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11; 351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (ZIP_OK != zipOpenNewFileInZip4( 353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) zip_file, // file 354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) str_path.c_str(), // filename 355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) file_info, // zipfi 356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NULL, // extrafield_local, 357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0u, // size_extrafield_local 358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NULL, // extrafield_global 359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0u, // size_extrafield_global 360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NULL, // comment 361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Z_DEFLATED, // method 362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Z_DEFAULT_COMPRESSION, // level 363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, // raw 364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) -MAX_WBITS, // windowBits 365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DEF_MEM_LEVEL, // memLevel 366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Z_DEFAULT_STRATEGY, // strategy 367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NULL, // password 368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, // crcForCrypting 369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, // versionMadeBy 370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) LANGUAGE_ENCODING_FLAG)) { // flagBase 371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DLOG(ERROR) << "Could not open zip file entry " << str_path; 372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return true; 375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace zip 379