1 /* zipunzip.cpp -- IO for compress .zip files using zlib
2 Version 1.01e, February 12th, 2005
4 Copyright (C) 1998-2005 Gilles Vollant
6 This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
7 WinZip, InfoZip tools and compatible.
8 Multi volume ZipFile (span) are not supported.
9 Encryption compatible with pkzip 2.04g only supported
10 Old compressions used by old PKZip 1.x are not supported
12 For uncompress .zip file, look at unzip.h
15 I WAIT FEEDBACK at mail info@winimage.com
16 Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
18 Condition of use and distribution are the same than zlib :
20 This software is provided 'as-is', without any express or implied
21 warranty. In no event will the authors be held liable for any damages
22 arising from the use of this software.
24 Permission is granted to anyone to use this software for any purpose,
25 including commercial applications, and to alter it and redistribute it
26 freely, subject to the following restrictions:
28 1. The origin of this software must not be misrepresented; you must not
29 claim that you wrote the original software. If you use this software
30 in a product, an acknowledgment in the product documentation would be
31 appreciated but is not required.
32 2. Altered source versions must be plainly marked as such, and must not be
33 misrepresented as being the original software.
34 3. This notice may not be removed or altered from any source distribution.
39 /* for more info about .ZIP format, see
40 http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
41 http://www.info-zip.org/pub/infozip/doc/
42 PkWare has also a specification at :
43 ftp://ftp.pkware.com/probdesc.zip
47 // The original minizip.c and miniunz.c distributed with minizip provide
48 // two command line tools minizip and miniunz. This file combines these two
49 // files and modifies the interface to provide two functions zipFiles and
50 // unzipToDir. This file is covered by the original minizip license.
58 #include "support/FileName.h"
66 #ifdef HAVE_SYS_TYPES_H
67 # include <sys/types.h>
69 #ifdef HAVE_SYS_STAT_H
70 # include <sys/stat.h>
75 #ifdef HAVE_SYS_UTIME_H
76 # include <sys/utime.h>
91 #define WRITEBUFFERSIZE (16384)
92 #define MAXFILENAME (256)
95 using lyx::support::FileName;
99 uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
105 WIN32_FIND_DATA ff32;
107 hFind = FindFirstFile(f,&ff32);
108 if (hFind != INVALID_HANDLE_VALUE)
110 FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
111 FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
121 uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/)
124 struct stat s; /* results of stat() */
128 if (strcmp(f,"-")!=0) {
129 char name[MAXFILENAME+1];
131 if (len > MAXFILENAME)
134 strncpy(name, f,MAXFILENAME-1);
135 /* strncpy doesnt append the trailing NULL, of the string is too long. */
136 name[ MAXFILENAME ] = '\0';
138 if (name[len - 1] == '/')
139 name[len - 1] = '\0';
140 /* not all systems allow stat'ing a file with / appended */
141 if (stat(name,&s)==0) {
146 filedate = localtime(&tm_t);
148 tmzip->tm_sec = filedate->tm_sec;
149 tmzip->tm_min = filedate->tm_min;
150 tmzip->tm_hour = filedate->tm_hour;
151 tmzip->tm_mday = filedate->tm_mday;
152 tmzip->tm_mon = filedate->tm_mon ;
153 tmzip->tm_year = filedate->tm_year;
160 uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
167 bool zipFiles(string const & zipfile, vector<pair<string, string> > const & files)
174 int size_buf = WRITEBUFFERSIZE;
175 buf = (void*)malloc(size_buf);
177 printf("Error allocating memory\n");
180 const char * fname = zipfile.c_str();
183 zlib_filefunc_def ffunc;
184 fill_win32_filefunc(&ffunc);
186 zf = zipOpen2(fname, false, NULL, &ffunc);
188 zf = zipOpen(fname, false);
195 for (vector<pair<string, string> >::const_iterator it = files.begin(); it != files.end(); ++it) {
199 const char * diskfilename = it->first.c_str();
200 const char * filenameinzip = it->second.c_str();
201 unsigned long crcFile=0;
203 zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
204 zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
208 filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);
210 err = zipOpenNewFileInZip3(zf, filenameinzip, &zi,
211 NULL,0,NULL,0,NULL /* comment*/,
213 Z_DEFAULT_COMPRESSION, // compression level
215 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
216 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
221 printf("error in opening %s in zipfile\n",filenameinzip);
224 fin = fopen(diskfilename, "rb");
231 size_read = (int)fread(buf, 1, size_buf, fin);
232 if (size_read < size_buf)
234 printf("error in reading %s\n",filenameinzip);
239 err = zipWriteInFileInZip (zf, buf, size_read);
241 printf("error in writing %s in the zipfile\n",
246 } while ((err == ZIP_OK) && (size_read>0));
251 err = zipCloseFileInZip(zf);
253 printf("error in closing %s in the zipfile\n",
258 errclose = zipClose(zf, NULL);
259 if (errclose != ZIP_OK) {
260 printf("error in closing zip file\n");
267 // adapted from miniunz.c
269 /* change_file_date : change the date/time of a file
270 filename : the filename of the file where date/time must be modified
271 dosdate : the new date at the MSDos format (4 bytes)
272 tmu_date : the SAME new date at the tm_unz format */
273 void change_file_date(const char * filename, uLong dosdate, tm_unz tmu_date)
277 FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
279 hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
280 0,NULL,OPEN_EXISTING,0,NULL);
281 GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
282 DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
283 LocalFileTimeToFileTime(&ftLocal,&ftm);
284 SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
291 newdate.tm_sec = tmu_date.tm_sec;
292 newdate.tm_min=tmu_date.tm_min;
293 newdate.tm_hour=tmu_date.tm_hour;
294 newdate.tm_mday=tmu_date.tm_mday;
295 newdate.tm_mon=tmu_date.tm_mon;
296 if (tmu_date.tm_year > 1900)
297 newdate.tm_year=tmu_date.tm_year - 1900;
299 newdate.tm_year=tmu_date.tm_year ;
302 ut.actime=ut.modtime=mktime(&newdate);
309 int do_extract_currentfile(unzFile uf,
310 const int * popt_extract_without_path,
311 int * popt_overwrite,
312 const char * password,
313 const char * dirname)
315 char full_path[1024];
316 char* filename_inzip = full_path;
317 char* filename_withoutpath;
324 strcpy(full_path, dirname);
325 while ((*filename_inzip) != '\0') filename_inzip++;
326 if (*(filename_inzip-1) != '/' && *(filename_inzip-1) != '\\') {
327 *filename_inzip = '/';
328 *(++filename_inzip) = '\0';
331 unz_file_info file_info;
333 err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,256,NULL,0,NULL,0);
336 printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
340 size_buf = WRITEBUFFERSIZE;
341 buf = (void*)malloc(size_buf);
343 printf("Error allocating memory\n");
344 return UNZ_INTERNALERROR;
347 p = filename_withoutpath = filename_inzip;
348 while ((*p) != '\0') {
349 if (((*p)=='/') || ((*p)=='\\'))
350 filename_withoutpath = p+1;
353 // this is a directory
354 if ((*filename_withoutpath)=='\0') {
355 if ((*popt_extract_without_path)==0) {
356 printf("Create directory %s\n", filename_inzip);
357 FileName(filename_inzip).createPath();
360 // this is a filename
362 err = unzOpenCurrentFilePassword(uf,password);
364 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
366 fout=fopen(full_path, "wb");
368 /* some zipfile don't contain directory alone before file */
369 if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
370 (filename_withoutpath!=(char*)filename_inzip)) {
371 char c=*(filename_withoutpath-1);
372 *(filename_withoutpath-1)='\0';
373 printf("Create directory %s\n", full_path);
374 FileName(full_path).createPath();
375 *(filename_withoutpath-1)=c;
376 fout=fopen(full_path,"wb");
380 printf("error opening %s\n", full_path);
387 err = unzReadCurrentFile(uf,buf,size_buf);
389 printf("error %d with zipfile in unzReadCurrentFile\n",err);
393 if (fwrite(buf,err,1,fout)!=1) {
394 printf("error in writing extracted file\n");
403 change_file_date(full_path, file_info.dosDate,
408 err = unzCloseCurrentFile (uf);
410 printf("error %d with zipfile in unzCloseCurrentFile\n",err);
414 unzCloseCurrentFile(uf); /* don't lose the error */
422 bool unzipToDir(string const & zipfile, string const & dirname)
426 zlib_filefunc_def ffunc;
429 const char * zipfilename = zipfile.c_str();
432 fill_win32_filefunc(&ffunc);
433 uf = unzOpen2(zipfilename, &ffunc);
435 uf = unzOpen(zipfilename);
446 int opt_extract_without_path = 0;
447 int opt_overwrite = 1;
448 char * password = NULL;
450 err = unzGetGlobalInfo (uf, &gi);
452 printf("error %d with zipfile in unzGetGlobalInfo \n",err);
456 for (i=0; i < gi.number_entry; i++) {
457 if (do_extract_currentfile(uf, &opt_extract_without_path,
459 password, dirname.c_str()) != UNZ_OK)
462 if ((i+1)<gi.number_entry) {
463 err = unzGoToNextFile(uf);
465 printf("error %d with zipfile in unzGoToNextFile\n",err);
471 unzCloseCurrentFile(uf);