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 "third_party/zlib/google/zip.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
12 #if defined(USE_SYSTEM_MINIZIP)
13 #include <minizip/ioapi.h>
14 #include <minizip/unzip.h>
15 #include <minizip/zip.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 base::string16 filename16
= base::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. However we do need to
101 // flush buffers and free |opaque| since we malloc'ed it in FillFdOpenFileFunc.
102 int CloseFileFunc(void* opaque
, void* stream
) {
103 fflush(static_cast<FILE*>(stream
));
108 // Fills |pzlib_filecunc_def| appropriately to handle the zip file
109 // referred to by |fd|.
110 void FillFdOpenFileFunc(zlib_filefunc_def
* pzlib_filefunc_def
, int fd
) {
111 fill_fopen_filefunc(pzlib_filefunc_def
);
112 pzlib_filefunc_def
->zopen_file
= FdOpenFileFunc
;
113 pzlib_filefunc_def
->zclose_file
= CloseFileFunc
;
114 int* ptr_fd
= static_cast<int*>(malloc(sizeof(fd
)));
116 pzlib_filefunc_def
->opaque
= ptr_fd
;
118 #endif // defined(OS_POSIX)
121 // Callback function for zlib that opens a file stream from a Windows handle.
122 void* HandleOpenFileFunc(void* opaque
, const char* filename
, int mode
) {
123 WIN32FILE_IOWIN file_ret
;
124 file_ret
.hf
= static_cast<HANDLE
>(opaque
);
126 if (file_ret
.hf
== INVALID_HANDLE_VALUE
)
129 void* ret
= malloc(sizeof(WIN32FILE_IOWIN
));
131 *(static_cast<WIN32FILE_IOWIN
*>(ret
)) = file_ret
;
136 // A struct that contains data required for zlib functions to extract files from
137 // a zip archive stored in memory directly. The following I/O API functions
138 // expect their opaque parameters refer to this struct.
140 const char* data
; // weak
145 // Opens the specified file. When this function returns a non-NULL pointer, zlib
146 // uses this pointer as a stream parameter while compressing or uncompressing
147 // data. (Returning NULL represents an error.) This function initializes the
148 // given opaque parameter and returns it because this parameter stores all
149 // information needed for uncompressing data. (This function does not support
150 // writing compressed data and it returns NULL for this case.)
151 void* OpenZipBuffer(void* opaque
, const char* /*filename*/, int mode
) {
152 if ((mode
& ZLIB_FILEFUNC_MODE_READWRITEFILTER
) != ZLIB_FILEFUNC_MODE_READ
) {
156 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
157 if (!buffer
|| !buffer
->data
|| !buffer
->length
)
163 // Reads compressed data from the specified stream. This function copies data
164 // refered by the opaque parameter and returns the size actually copied.
165 uLong
ReadZipBuffer(void* opaque
, void* /*stream*/, void* buf
, uLong size
) {
166 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
167 DCHECK_LE(buffer
->offset
, buffer
->length
);
168 size_t remaining_bytes
= buffer
->length
- buffer
->offset
;
169 if (!buffer
|| !buffer
->data
|| !remaining_bytes
)
171 size
= std::min(size
, static_cast<uLong
>(remaining_bytes
));
172 memcpy(buf
, &buffer
->data
[buffer
->offset
], size
);
173 buffer
->offset
+= size
;
177 // Writes compressed data to the stream. This function always returns zero
178 // because this implementation is only for reading compressed data.
179 uLong
WriteZipBuffer(void* /*opaque*/,
187 // Returns the offset from the beginning of the data.
188 long GetOffsetOfZipBuffer(void* opaque
, void* /*stream*/) {
189 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
192 return static_cast<long>(buffer
->offset
);
195 // Moves the current offset to the specified position.
196 long SeekZipBuffer(void* opaque
, void* /*stream*/, uLong offset
, int origin
) {
197 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(opaque
);
200 if (origin
== ZLIB_FILEFUNC_SEEK_CUR
) {
201 buffer
->offset
= std::min(buffer
->offset
+ static_cast<size_t>(offset
),
205 if (origin
== ZLIB_FILEFUNC_SEEK_END
) {
206 buffer
->offset
= (buffer
->length
> offset
) ? buffer
->length
- offset
: 0;
209 if (origin
== ZLIB_FILEFUNC_SEEK_SET
) {
210 buffer
->offset
= std::min(buffer
->length
, static_cast<size_t>(offset
));
217 // Closes the input offset and deletes all resources used for compressing or
218 // uncompressing data. This function deletes the ZipBuffer object referred by
219 // the opaque parameter since zlib deletes the unzFile object and it does not
220 // use this object any longer.
221 int CloseZipBuffer(void* opaque
, void* /*stream*/) {
227 // Returns the last error happened when reading or writing data. This function
228 // always returns zero, which means there are not any errors.
229 int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) {
238 unzFile
OpenForUnzipping(const std::string
& file_name_utf8
) {
239 zlib_filefunc_def
* zip_func_ptrs
= NULL
;
241 zlib_filefunc_def zip_funcs
;
242 fill_win32_filefunc(&zip_funcs
);
243 zip_funcs
.zopen_file
= ZipOpenFunc
;
244 zip_func_ptrs
= &zip_funcs
;
246 return unzOpen2(file_name_utf8
.c_str(), zip_func_ptrs
);
249 #if defined(OS_POSIX)
250 unzFile
OpenFdForUnzipping(int zip_fd
) {
251 zlib_filefunc_def zip_funcs
;
252 FillFdOpenFileFunc(&zip_funcs
, zip_fd
);
253 // Passing dummy "fd" filename to zlib.
254 return unzOpen2("fd", &zip_funcs
);
259 unzFile
OpenHandleForUnzipping(HANDLE zip_handle
) {
260 zlib_filefunc_def zip_funcs
;
261 fill_win32_filefunc(&zip_funcs
);
262 zip_funcs
.zopen_file
= HandleOpenFileFunc
;
263 zip_funcs
.opaque
= zip_handle
;
264 return unzOpen2("fd", &zip_funcs
);
269 unzFile
PreprareMemoryForUnzipping(const std::string
& data
) {
273 ZipBuffer
* buffer
= static_cast<ZipBuffer
*>(malloc(sizeof(ZipBuffer
)));
276 buffer
->data
= data
.data();
277 buffer
->length
= data
.length();
280 zlib_filefunc_def zip_functions
;
281 zip_functions
.zopen_file
= OpenZipBuffer
;
282 zip_functions
.zread_file
= ReadZipBuffer
;
283 zip_functions
.zwrite_file
= WriteZipBuffer
;
284 zip_functions
.ztell_file
= GetOffsetOfZipBuffer
;
285 zip_functions
.zseek_file
= SeekZipBuffer
;
286 zip_functions
.zclose_file
= CloseZipBuffer
;
287 zip_functions
.zerror_file
= GetErrorOfZipBuffer
;
288 zip_functions
.opaque
= static_cast<void*>(buffer
);
289 return unzOpen2(NULL
, &zip_functions
);
292 zipFile
OpenForZipping(const std::string
& file_name_utf8
, int append_flag
) {
293 zlib_filefunc_def
* zip_func_ptrs
= NULL
;
295 zlib_filefunc_def zip_funcs
;
296 fill_win32_filefunc(&zip_funcs
);
297 zip_funcs
.zopen_file
= ZipOpenFunc
;
298 zip_func_ptrs
= &zip_funcs
;
300 return zipOpen2(file_name_utf8
.c_str(),
302 NULL
, // global comment
306 #if defined(OS_POSIX)
307 zipFile
OpenFdForZipping(int zip_fd
, int append_flag
) {
308 zlib_filefunc_def zip_funcs
;
309 FillFdOpenFileFunc(&zip_funcs
, zip_fd
);
310 // Passing dummy "fd" filename to zlib.
311 return zipOpen2("fd", append_flag
, NULL
, &zip_funcs
);
315 } // namespace internal