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.
60 #include "support/FileName.h"
68 #ifdef HAVE_SYS_TYPES_H
69 # include <sys/types.h>
71 #ifdef HAVE_SYS_STAT_H
72 # include <sys/stat.h>
77 #ifdef HAVE_SYS_UTIME_H
78 # include <sys/utime.h>
93 #define WRITEBUFFERSIZE (16384)
94 #define MAXFILENAME (256)
97 using lyx::support::FileName;
101 uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
107 WIN32_FIND_DATA ff32;
109 hFind = FindFirstFile(f,&ff32);
110 if (hFind != INVALID_HANDLE_VALUE)
112 FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
113 FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
123 uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/)
126 struct stat s; /* results of stat() */
130 if (strcmp(f,"-")!=0) {
131 char name[MAXFILENAME+1];
133 if (len > MAXFILENAME)
136 strncpy(name, f,MAXFILENAME-1);
137 /* strncpy doesnt append the trailing NULL, of the string is too long. */
138 name[ MAXFILENAME ] = '\0';
140 if (name[len - 1] == '/')
141 name[len - 1] = '\0';
142 /* not all systems allow stat'ing a file with / appended */
143 if (stat(name,&s)==0) {
148 filedate = localtime(&tm_t);
150 tmzip->tm_sec = filedate->tm_sec;
151 tmzip->tm_min = filedate->tm_min;
152 tmzip->tm_hour = filedate->tm_hour;
153 tmzip->tm_mday = filedate->tm_mday;
154 tmzip->tm_mon = filedate->tm_mon ;
155 tmzip->tm_year = filedate->tm_year;
162 uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
169 bool zipFiles(string const & zipfile, vector<pair<string, string> > const & files)
176 int size_buf = WRITEBUFFERSIZE;
177 buf = (void*)malloc(size_buf);
179 printf("Error allocating memory\n");
182 const char * fname = zipfile.c_str();
185 zlib_filefunc_def ffunc;
186 fill_win32_filefunc(&ffunc);
188 zf = zipOpen2(fname, false, NULL, &ffunc);
190 zf = zipOpen(fname, false);
197 for (vector<pair<string, string> >::const_iterator it = files.begin(); it != files.end(); ++it) {
201 const char * diskfilename = it->first.c_str();
202 const char * filenameinzip = it->second.c_str();
203 unsigned long crcFile=0;
205 zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
206 zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
210 filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);
212 err = zipOpenNewFileInZip3(zf, filenameinzip, &zi,
213 NULL,0,NULL,0,NULL /* comment*/,
215 Z_DEFAULT_COMPRESSION, // compression level
217 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
218 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
223 printf("error in opening %s in zipfile\n",filenameinzip);
226 fin = fopen(diskfilename, "rb");
233 size_read = (int)fread(buf, 1, size_buf, fin);
234 if (size_read < size_buf)
236 printf("error in reading %s\n",filenameinzip);
241 err = zipWriteInFileInZip (zf, buf, size_read);
243 printf("error in writing %s in the zipfile\n",
248 } while ((err == ZIP_OK) && (size_read>0));
253 err = zipCloseFileInZip(zf);
255 printf("error in closing %s in the zipfile\n",
260 errclose = zipClose(zf, NULL);
261 if (errclose != ZIP_OK) {
262 printf("error in closing zip file\n");
269 // adapted from miniunz.c
271 /* change_file_date : change the date/time of a file
272 filename : the filename of the file where date/time must be modified
273 dosdate : the new date at the MSDos format (4 bytes)
274 tmu_date : the SAME new date at the tm_unz format */
275 void change_file_date(const char * filename, uLong /* dosdate */, tm_unz tmu_date)
279 FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
281 hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
282 0,NULL,OPEN_EXISTING,0,NULL);
283 GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
284 DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
285 LocalFileTimeToFileTime(&ftLocal,&ftm);
286 SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
293 newdate.tm_sec = tmu_date.tm_sec;
294 newdate.tm_min=tmu_date.tm_min;
295 newdate.tm_hour=tmu_date.tm_hour;
296 newdate.tm_mday=tmu_date.tm_mday;
297 newdate.tm_mon=tmu_date.tm_mon;
298 if (tmu_date.tm_year > 1900)
299 newdate.tm_year=tmu_date.tm_year - 1900;
301 newdate.tm_year=tmu_date.tm_year ;
304 ut.actime=ut.modtime=mktime(&newdate);
311 int do_extract_currentfile(unzFile uf,
312 const int * popt_extract_without_path,
313 int * /* popt_overwrite */,
314 const char * password,
315 const char * dirname)
317 char full_path[1024];
318 char* filename_inzip = full_path;
319 char* filename_withoutpath;
326 strcpy(full_path, dirname);
327 while ((*filename_inzip) != '\0') filename_inzip++;
328 if (*(filename_inzip-1) != '/' && *(filename_inzip-1) != '\\') {
329 *filename_inzip = '/';
330 *(++filename_inzip) = '\0';
333 unz_file_info file_info;
335 err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,256,NULL,0,NULL,0);
338 printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
342 size_buf = WRITEBUFFERSIZE;
343 buf = (void*)malloc(size_buf);
345 printf("Error allocating memory\n");
346 return UNZ_INTERNALERROR;
349 p = filename_withoutpath = filename_inzip;
350 while ((*p) != '\0') {
351 if (((*p)=='/') || ((*p)=='\\'))
352 filename_withoutpath = p+1;
355 // this is a directory
356 if ((*filename_withoutpath)=='\0') {
357 if ((*popt_extract_without_path)==0) {
358 printf("Create directory %s\n", filename_inzip);
359 FileName(filename_inzip).createPath();
362 // this is a filename
364 err = unzOpenCurrentFilePassword(uf,password);
366 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
368 fout=fopen(full_path, "wb");
370 /* some zipfile don't contain directory alone before file */
371 if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
372 (filename_withoutpath!=(char*)filename_inzip)) {
373 char c=*(filename_withoutpath-1);
374 *(filename_withoutpath-1)='\0';
375 printf("Create directory %s\n", full_path);
376 FileName(full_path).createPath();
377 *(filename_withoutpath-1)=c;
378 fout=fopen(full_path,"wb");
382 printf("error opening %s\n", full_path);
389 err = unzReadCurrentFile(uf,buf,size_buf);
391 printf("error %d with zipfile in unzReadCurrentFile\n",err);
395 if (fwrite(buf,err,1,fout)!=1) {
396 printf("error in writing extracted file\n");
405 change_file_date(full_path, file_info.dosDate,
410 err = unzCloseCurrentFile (uf);
412 printf("error %d with zipfile in unzCloseCurrentFile\n",err);
416 unzCloseCurrentFile(uf); /* don't lose the error */
424 bool unzipToDir(string const & zipfile, string const & dirname)
428 zlib_filefunc_def ffunc;
431 const char * zipfilename = zipfile.c_str();
434 fill_win32_filefunc(&ffunc);
435 uf = unzOpen2(zipfilename, &ffunc);
437 uf = unzOpen(zipfilename);
448 int opt_extract_without_path = 0;
449 int opt_overwrite = 1;
450 char * password = NULL;
452 err = unzGetGlobalInfo (uf, &gi);
454 printf("error %d with zipfile in unzGetGlobalInfo \n",err);
458 for (i=0; i < gi.number_entry; i++) {
459 if (do_extract_currentfile(uf, &opt_extract_without_path,
461 password, dirname.c_str()) != UNZ_OK)
464 if ((i+1)<gi.number_entry) {
465 err = unzGoToNextFile(uf);
467 printf("error %d with zipfile in unzGoToNextFile\n",err);
473 unzCloseCurrentFile(uf);