1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/zip.h"
9 #include "base/logging.h"
10 #include "base/utf_string_conversions.h"
12 #if defined(USE_SYSTEM_MINIZIP)
13 #include <minizip/unzip.h>
14 #include <minizip/zip.h>
15 #include <minizip/ioapi.h>
17 #include "third_party/zlib/contrib/minizip/unzip.h"
18 #include "third_party/zlib/contrib/minizip/zip.h"
20 #include "third_party/zlib/contrib/minizip/iowin32.h"
21 #elif defined(OS_POSIX)
22 #include "third_party/zlib/contrib/minizip/ioapi.h"
23 #endif // defined(OS_POSIX)
24 #endif // defined(USE_SYSTEM_MINIZIP)
34 // This function is derived from third_party/minizip/iowin32.c.
35 // Its only difference is that it treats the char* as UTF8 and
36 // uses the Unicode version of CreateFile.
37 void* ZipOpenFunc(void *opaque
, const char* filename
, int mode
) {
38 DWORD desired_access
, creation_disposition
;
39 DWORD share_mode
, flags_and_attributes
;
43 desired_access
= share_mode
= flags_and_attributes
= 0;
45 if ((mode
& ZLIB_FILEFUNC_MODE_READWRITEFILTER
) == ZLIB_FILEFUNC_MODE_READ
) {
46 desired_access
= GENERIC_READ
;
47 creation_disposition
= OPEN_EXISTING
;
48 share_mode
= FILE_SHARE_READ
;
49 } else if (mode
& ZLIB_FILEFUNC_MODE_EXISTING
) {
50 desired_access
= GENERIC_WRITE
| GENERIC_READ
;
51 creation_disposition
= OPEN_EXISTING
;
52 } else if (mode
& ZLIB_FILEFUNC_MODE_CREATE
) {
53 desired_access
= GENERIC_WRITE
| GENERIC_READ
;
54 creation_disposition
= CREATE_ALWAYS
;
57 string16 filename16
= UTF8ToUTF16(filename
);
58 if ((filename
!= NULL
) && (desired_access
!= 0)) {
59 file
= CreateFile(filename16
.c_str(), desired_access
, share_mode
,
60 NULL
, creation_disposition
, flags_and_attributes
, NULL
);
63 if (file
== INVALID_HANDLE_VALUE
)
67 WIN32FILE_IOWIN file_ret
;
70 ret
= malloc(sizeof(WIN32FILE_IOWIN
));
74 *(static_cast<WIN32FILE_IOWIN
*>(ret
)) = file_ret
;
81 // Callback function for zlib that opens a file stream from a file descriptor.
82 void* FdOpenFileFunc(void* opaque
, const char* filename
, int mode
) {
84 const char* mode_fopen
= NULL
;
86 if ((mode
& ZLIB_FILEFUNC_MODE_READWRITEFILTER
) == ZLIB_FILEFUNC_MODE_READ
)
88 else if (mode
& ZLIB_FILEFUNC_MODE_EXISTING
)
90 else if (mode
& ZLIB_FILEFUNC_MODE_CREATE
)
93 if ((filename
!= NULL
) && (mode_fopen
!= NULL
))
94 file
= fdopen(*static_cast<int*>(opaque
), mode_fopen
);
99 // We don't actually close the file stream since that would close
100 // the underlying file descriptor, and we don't own it. We do free
101 // |opaque| since we malloc'ed it in FillFdOpenFileFunc.
102 int CloseFileFunc(void* opaque
, void* stream
) {
107 // Fills |pzlib_filecunc_def| appropriately to handle the zip file
108 // referred to by |fd|.
109 void FillFdOpenFileFunc(zlib_filefunc_def
* pzlib_filefunc_def
, int fd
) {
110 fill_fopen_filefunc(pzlib_filefunc_def
);
111 pzlib_filefunc_def
->zopen_file
= FdOpenFileFunc
;
112 pzlib_filefunc_def
->zclose_file
= CloseFileFunc
;
113 int* ptr_fd
= static_cast<int*>(malloc(sizeof(fd
)));
115 pzlib_filefunc_def
->opaque
= ptr_fd
;
117 #endif // defined(OS_POSIX)
119 // A struct that contains data required for zlib functions to extract files from
120 // a zip archive stored in memory directly. The following I/O API functions
121 // expect their opaque parameters refer to this struct.
123 const char* data
; // weak
128 // Opens the specified file. When this function returns a non-NULL pointer, zlib
129 // uses this pointer as a stream parameter while compressing or uncompressing
130 // data. (Returning NULL represents an error.) This function initializes the
131 // given opaque parameter and returns it because this parameter stores all
132 // information needed for uncompressing data. (This function does not support
133 // writing compressed data and it returns NULL for this case.)
134 void* OpenZipBuffer(void* opaque
, const char* /*filename*/, int mode
) {
135 if ((mode
& ZLIB_FILEFUNC_MODE_READWRITEFILTER
) != ZLIB_FILEFUNC_MODE_READ
) {
139 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
140 if (!buffer
|| !buffer
->data
|| !buffer
->length
)
146 // Reads compressed data from the specified stream. This function copies data
147 // refered by the opaque parameter and returns the size actually copied.
148 uLong
ReadZipBuffer(void* opaque
, void* /*stream*/, void* buf
, uLong size
) {
149 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
150 DCHECK_LE(buffer
->offset
, buffer
->length
);
151 size_t remaining_bytes
= buffer
->length
- buffer
->offset
;
152 if (!buffer
|| !buffer
->data
|| !remaining_bytes
)
154 size
= std::min(size
, static_cast<uLong
>(remaining_bytes
));
155 memcpy(buf
, &buffer
->data
[buffer
->offset
], size
);
156 buffer
->offset
+= size
;
160 // Writes compressed data to the stream. This function always returns zero
161 // because this implementation is only for reading compressed data.
162 uLong
WriteZipBuffer(void* /*opaque*/,
170 // Returns the offset from the beginning of the data.
171 long GetOffsetOfZipBuffer(void* opaque
, void* /*stream*/) {
172 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
175 return static_cast<long>(buffer
->offset
);
178 // Moves the current offset to the specified position.
179 long SeekZipBuffer(void* opaque
, void* /*stream*/, uLong offset
, int origin
) {
180 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
183 if (origin
== ZLIB_FILEFUNC_SEEK_CUR
) {
184 buffer
->offset
= std::min(buffer
->offset
+ static_cast<size_t>(offset
),
188 if (origin
== ZLIB_FILEFUNC_SEEK_END
) {
189 buffer
->offset
= (buffer
->length
> offset
) ? buffer
->length
- offset
: 0;
192 if (origin
== ZLIB_FILEFUNC_SEEK_SET
) {
193 buffer
->offset
= std::min(buffer
->length
, static_cast<size_t>(offset
));
200 // Closes the input offset and deletes all resources used for compressing or
201 // uncompressing data. This function deletes the ZipBuffer object referred by
202 // the opaque parameter since zlib deletes the unzFile object and it does not
203 // use this object any longer.
204 int CloseZipBuffer(void* opaque
, void* /*stream*/) {
210 // Returns the last error happened when reading or writing data. This function
211 // always returns zero, which means there are not any errors.
212 int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) {
221 unzFile
OpenForUnzipping(const std::string
& file_name_utf8
) {
222 zlib_filefunc_def
* zip_func_ptrs
= NULL
;
224 zlib_filefunc_def zip_funcs
;
225 fill_win32_filefunc(&zip_funcs
);
226 zip_funcs
.zopen_file
= ZipOpenFunc
;
227 zip_func_ptrs
= &zip_funcs
;
229 return unzOpen2(file_name_utf8
.c_str(), zip_func_ptrs
);
232 #if defined(OS_POSIX)
233 unzFile
OpenFdForUnzipping(int zip_fd
) {
234 zlib_filefunc_def zip_funcs
;
235 FillFdOpenFileFunc(&zip_funcs
, zip_fd
);
236 // Passing dummy "fd" filename to zlib.
237 return unzOpen2("fd", &zip_funcs
);
242 unzFile
PreprareMemoryForUnzipping(const std::string
& data
) {
246 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(malloc(sizeof(ZipBuffer
)));
249 buffer
->data
= data
.data();
250 buffer
->length
= data
.length();
253 zlib_filefunc_def zip_functions
;
254 zip_functions
.zopen_file
= OpenZipBuffer
;
255 zip_functions
.zread_file
= ReadZipBuffer
;
256 zip_functions
.zwrite_file
= WriteZipBuffer
;
257 zip_functions
.ztell_file
= GetOffsetOfZipBuffer
;
258 zip_functions
.zseek_file
= SeekZipBuffer
;
259 zip_functions
.zclose_file
= CloseZipBuffer
;
260 zip_functions
.zerror_file
= GetErrorOfZipBuffer
;
261 zip_functions
.opaque
= static_cast<void*>(buffer
);
262 return unzOpen2(NULL
, &zip_functions
);
265 zipFile
OpenForZipping(const std::string
& file_name_utf8
, int append_flag
) {
266 zlib_filefunc_def
* zip_func_ptrs
= NULL
;
268 zlib_filefunc_def zip_funcs
;
269 fill_win32_filefunc(&zip_funcs
);
270 zip_funcs
.zopen_file
= ZipOpenFunc
;
271 zip_func_ptrs
= &zip_funcs
;
273 return zipOpen2(file_name_utf8
.c_str(),
275 NULL
, // global comment
279 } // namespace internal