1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 *************************************************************************/
28 /* unzip.c -- IO for uncompress .zip files using zlib
29 Version 1.01e, February 12th, 2005
31 Copyright (C) 1998-2005 Gilles Vollant
33 Read unzip.h for more info
36 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
37 compatibility with older software. The following is from the original crypt.c. Code
38 woven in by Terry Thorsen 1/2003.
41 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
43 See the accompanying file LICENSE, version 2000-Apr-09 or later
44 (the contents of which are also included in zip.h) for terms of use.
45 If, for some reason, all these files are missing, the Info-ZIP license
46 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
49 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
51 The encryption/decryption parts of this source code (as opposed to the
52 non-echoing password parts) were originally written in Europe. The
53 whole source package can be freely distributed, including from the USA.
54 (Prior to January 2000, re-export from the US was a violation of US law.)
58 This encryption code is a direct transcription of the algorithm from
59 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
60 file (appnote.txt) is distributed with the PKZIP program (even in the
61 version without encryption capabilities).
87 /* compile with -Dlocal if your debugger can't find static symbols */
90 #ifndef CASESENSITIVITYDEFAULT_NO
91 # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
92 # define CASESENSITIVITYDEFAULT_NO
98 #define UNZ_BUFSIZE (16384)
101 #ifndef UNZ_MAXFILENAMEINZIP
102 #define UNZ_MAXFILENAMEINZIP (256)
106 # define ALLOC(size) (malloc(size))
109 # define TRYFREE(p) {if (p) free(p);}
112 #define SIZECENTRALDIRITEM (0x2e)
113 #define SIZEZIPLOCALHEADER (0x1e)
118 const char unz_copyright[] =
119 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
121 /* unz_file_info_interntal contain internal info about a file in zipfile*/
122 typedef struct unz_file_info_internal_s
124 uLong offset_curfile;/* relative offset of local header 4 bytes */
125 } unz_file_info_internal;
128 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
129 when reading and decompress it */
132 char *read_buffer; /* internal buffer for compressed data */
133 z_stream stream; /* zLib stream structure for inflate */
135 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
136 uLong stream_initialised; /* flag set if stream structure is initialised*/
138 uLong offset_local_extrafield;/* offset of the local extra field */
139 uInt size_local_extrafield;/* size of the local extra field */
140 uLong pos_local_extrafield; /* position in the local extra field in read*/
142 uLong crc32; /* crc32 of all data uncompressed */
143 uLong crc32_wait; /* crc32 we must obtain after decompress all */
144 uLong rest_read_compressed; /* number of byte to be decompressed */
145 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
146 zlib_filefunc_def z_filefunc;
147 voidpf filestream; /* io structore of the zipfile */
148 uLong compression_method; /* compression method (0==store) */
149 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
151 } file_in_zip_read_info_s;
154 /* unz_s contain internal information about the zipfile
158 zlib_filefunc_def z_filefunc;
159 voidpf filestream; /* io structore of the zipfile */
160 unz_global_info gi; /* public global information */
161 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
162 uLong num_file; /* number of the current file in the zipfile*/
163 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
164 uLong current_file_ok; /* flag about the usability of the current file*/
165 uLong central_pos; /* position of the beginning of the central dir*/
167 uLong size_central_dir; /* size of the central directory */
168 uLong offset_central_dir; /* offset of start of central directory with
169 respect to the starting disk number */
171 unz_file_info cur_file_info; /* public info about the current file in zip*/
172 unz_file_info_internal cur_file_info_internal; /* private info about it*/
173 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
174 file if we are decompressing it */
180 /* ===========================================================================
181 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
183 IN assertion: the stream s has been sucessfully opened for reading.
187 local int unzlocal_getByte OF((
188 const zlib_filefunc_def* pzlib_filefunc_def,
192 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
193 const zlib_filefunc_def* pzlib_filefunc_def;
198 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
206 if (ZERROR(*pzlib_filefunc_def,filestream))
214 /* ===========================================================================
215 Reads a long in LSB order from the given gz_stream. Sets
217 local int unzlocal_getShort OF((
218 const zlib_filefunc_def* pzlib_filefunc_def,
222 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
223 const zlib_filefunc_def* pzlib_filefunc_def;
231 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
235 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
245 local int unzlocal_getLong OF((
246 const zlib_filefunc_def* pzlib_filefunc_def,
250 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
251 const zlib_filefunc_def* pzlib_filefunc_def;
259 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
263 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
267 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
271 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
282 /* My own strcmpi / strcasecmp */
283 local int strcmpcasenosensitive_internal (fileName1,fileName2)
284 const char* fileName1;
285 const char* fileName2;
289 char c1=*(fileName1++);
290 char c2=*(fileName2++);
291 if ((c1>='a') && (c1<='z'))
293 if ((c2>='a') && (c2<='z'))
296 return ((c2=='\0') ? 0 : -1);
307 #ifdef CASESENSITIVITYDEFAULT_NO
308 #define CASESENSITIVITYDEFAULTVALUE 2
310 #define CASESENSITIVITYDEFAULTVALUE 1
313 #ifndef STRCMPCASENOSENTIVEFUNCTION
314 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
318 Compare two filename (fileName1,fileName2).
319 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
320 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
322 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
323 (like 1 on Unix, 2 on Windows)
326 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
327 const char* fileName1;
328 const char* fileName2;
329 int iCaseSensitivity;
331 if (iCaseSensitivity==0)
332 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
334 if (iCaseSensitivity==1)
335 return strcmp(fileName1,fileName2);
337 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
340 #ifndef BUFREADCOMMENT
341 #define BUFREADCOMMENT (0x400)
345 Locate the Central directory of a zipfile (at the end, just before
348 local uLong unzlocal_SearchCentralDir OF((
349 const zlib_filefunc_def* pzlib_filefunc_def,
352 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
353 const zlib_filefunc_def* pzlib_filefunc_def;
359 uLong uMaxBack=0xffff; /* maximum size of global comment */
362 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
366 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
368 if (uMaxBack>uSizeFile)
369 uMaxBack = uSizeFile;
371 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
376 while (uBackRead<uMaxBack)
378 uLong uReadSize,uReadPos ;
380 if (uBackRead+BUFREADCOMMENT>uMaxBack)
381 uBackRead = uMaxBack;
383 uBackRead+=BUFREADCOMMENT;
384 uReadPos = uSizeFile-uBackRead ;
386 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
387 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
388 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
391 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
394 for (i=(int)uReadSize-3; (i--)>0;)
395 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
396 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
398 uPosFound = uReadPos+i;
410 Open a Zip file. path contain the full pathname (by example,
411 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
413 If the zipfile cannot be opened (file doesn't exist or in not valid), the
414 return value is NULL.
415 Else, the return value is a unzFile Handle, usable with other function
416 of this unzip package.
418 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
420 zlib_filefunc_def* pzlib_filefunc_def;
424 uLong central_pos,uL;
426 uLong number_disk; /* number of the current dist, used for
427 spaning ZIP, unsupported, always 0*/
428 uLong number_disk_with_CD; /* number the the disk with central dir, used
429 for spaning ZIP, unsupported, always 0*/
430 uLong number_entry_CD; /* total number of entries in
432 (same than number_entry on nospan) */
436 if (unz_copyright[0]!=' ')
439 if (pzlib_filefunc_def==NULL)
440 fill_fopen_filefunc(&us.z_filefunc);
442 us.z_filefunc = *pzlib_filefunc_def;
444 us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
446 ZLIB_FILEFUNC_MODE_READ |
447 ZLIB_FILEFUNC_MODE_EXISTING);
448 if (us.filestream==NULL)
451 central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
455 if (ZSEEK(us.z_filefunc, us.filestream,
456 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
459 /* the signature, already checked */
460 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
463 /* number of this disk */
464 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
467 /* number of the disk with the start of the central directory */
468 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
471 /* total number of entries in the central dir on this disk */
472 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
475 /* total number of entries in the central dir */
476 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
479 if ((number_entry_CD!=us.gi.number_entry) ||
480 (number_disk_with_CD!=0) ||
484 /* size of the central directory */
485 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
488 /* offset of start of central directory with respect to the
489 starting disk number */
490 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
493 /* zipfile comment length */
494 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
497 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
503 ZCLOSE(us.z_filefunc, us.filestream);
507 us.byte_before_the_zipfile = central_pos -
508 (us.offset_central_dir+us.size_central_dir);
509 us.central_pos = central_pos;
510 us.pfile_in_zip_read = NULL;
514 s=(unz_s*)ALLOC(sizeof(unz_s));
516 unzGoToFirstFile((unzFile)s);
521 extern unzFile ZEXPORT unzOpen (path)
524 return unzOpen2(path, NULL);
528 Close a ZipFile opened with unzipOpen.
529 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
530 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
531 return UNZ_OK if there is no problem. */
532 extern int ZEXPORT unzClose (file)
537 return UNZ_PARAMERROR;
540 if (s->pfile_in_zip_read!=NULL)
541 unzCloseCurrentFile(file);
543 ZCLOSE(s->z_filefunc, s->filestream);
550 Write info about the ZipFile in the *pglobal_info structure.
551 No preparation of the structure is needed
552 return UNZ_OK if there is no problem. */
553 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
555 unz_global_info *pglobal_info;
559 return UNZ_PARAMERROR;
567 Translate date/time from Dos format to tm_unz (readable more easilty)
569 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
574 uDate = (uLong)(ulDosDate>>16);
575 ptm->tm_mday = (uInt)(uDate&0x1f) ;
576 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
577 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
579 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
580 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
581 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
585 Get Info about the current file in the zipfile, with internal only info
587 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
588 unz_file_info *pfile_info,
589 unz_file_info_internal
590 *pfile_info_internal,
592 uLong fileNameBufferSize,
594 uLong extraFieldBufferSize,
596 uLong commentBufferSize));
598 local int unzlocal_GetCurrentFileInfoInternal (file,
601 szFileName, fileNameBufferSize,
602 extraField, extraFieldBufferSize,
603 szComment, commentBufferSize)
605 unz_file_info *pfile_info;
606 unz_file_info_internal *pfile_info_internal;
608 uLong fileNameBufferSize;
610 uLong extraFieldBufferSize;
612 uLong commentBufferSize;
615 unz_file_info file_info;
616 unz_file_info_internal file_info_internal;
622 return UNZ_PARAMERROR;
624 if (ZSEEK(s->z_filefunc, s->filestream,
625 s->pos_in_central_dir+s->byte_before_the_zipfile,
626 ZLIB_FILEFUNC_SEEK_SET)!=0)
630 /* we check the magic */
632 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
634 else if (uMagic!=0x02014b50)
638 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
641 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
644 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
647 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
650 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
653 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
655 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
658 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
661 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
664 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
667 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
670 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
673 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
676 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
679 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
682 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
685 lSeek+=file_info.size_filename;
686 if ((err==UNZ_OK) && (szFileName!=NULL))
689 if (file_info.size_filename<fileNameBufferSize)
691 *(szFileName+file_info.size_filename)='\0';
692 uSizeRead = file_info.size_filename;
695 uSizeRead = fileNameBufferSize;
697 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
698 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
704 if ((err==UNZ_OK) && (extraField!=NULL))
707 if (file_info.size_file_extra<extraFieldBufferSize)
708 uSizeRead = file_info.size_file_extra;
710 uSizeRead = extraFieldBufferSize;
713 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
718 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
719 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
721 lSeek += file_info.size_file_extra - uSizeRead;
724 lSeek+=file_info.size_file_extra;
727 if ((err==UNZ_OK) && (szComment!=NULL))
730 if (file_info.size_file_comment<commentBufferSize)
732 *(szComment+file_info.size_file_comment)='\0';
733 uSizeRead = file_info.size_file_comment;
736 uSizeRead = commentBufferSize;
739 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
744 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
745 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
747 lSeek+=file_info.size_file_comment - uSizeRead;
750 lSeek+=file_info.size_file_comment;
752 if ((err==UNZ_OK) && (pfile_info!=NULL))
753 *pfile_info=file_info;
755 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
756 *pfile_info_internal=file_info_internal;
764 Write info about the ZipFile in the *pglobal_info structure.
765 No preparation of the structure is needed
766 return UNZ_OK if there is no problem.
768 extern int ZEXPORT unzGetCurrentFileInfo (file,
770 szFileName, fileNameBufferSize,
771 extraField, extraFieldBufferSize,
772 szComment, commentBufferSize)
774 unz_file_info *pfile_info;
776 uLong fileNameBufferSize;
778 uLong extraFieldBufferSize;
780 uLong commentBufferSize;
782 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
783 szFileName,fileNameBufferSize,
784 extraField,extraFieldBufferSize,
785 szComment,commentBufferSize);
789 Set the current file of the zipfile to the first file.
790 return UNZ_OK if there is no problem
792 extern int ZEXPORT unzGoToFirstFile (file)
798 return UNZ_PARAMERROR;
800 s->pos_in_central_dir=s->offset_central_dir;
802 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
803 &s->cur_file_info_internal,
804 NULL,0,NULL,0,NULL,0);
805 s->current_file_ok = (err == UNZ_OK);
810 Set the current file of the zipfile to the next file.
811 return UNZ_OK if there is no problem
812 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
814 extern int ZEXPORT unzGoToNextFile (file)
821 return UNZ_PARAMERROR;
823 if (!s->current_file_ok)
824 return UNZ_END_OF_LIST_OF_FILE;
825 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
826 if (s->num_file+1==s->gi.number_entry)
827 return UNZ_END_OF_LIST_OF_FILE;
829 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
830 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
832 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
833 &s->cur_file_info_internal,
834 NULL,0,NULL,0,NULL,0);
835 s->current_file_ok = (err == UNZ_OK);
841 Try locate the file szFileName in the zipfile.
842 For the iCaseSensitivity signification, see unzipStringFileNameCompare
845 UNZ_OK if the file is found. It becomes the current file.
846 UNZ_END_OF_LIST_OF_FILE if the file is not found
848 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
850 const char *szFileName;
851 int iCaseSensitivity;
856 /* We remember the 'current' position in the file so that we can jump
857 * back there if we fail.
859 unz_file_info cur_file_infoSaved;
860 unz_file_info_internal cur_file_info_internalSaved;
862 uLong pos_in_central_dirSaved;
866 return UNZ_PARAMERROR;
868 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
869 return UNZ_PARAMERROR;
872 if (!s->current_file_ok)
873 return UNZ_END_OF_LIST_OF_FILE;
875 /* Save the current state */
876 num_fileSaved = s->num_file;
877 pos_in_central_dirSaved = s->pos_in_central_dir;
878 cur_file_infoSaved = s->cur_file_info;
879 cur_file_info_internalSaved = s->cur_file_info_internal;
881 err = unzGoToFirstFile(file);
883 while (err == UNZ_OK)
885 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
886 err = unzGetCurrentFileInfo(file,NULL,
887 szCurrentFileName,sizeof(szCurrentFileName)-1,
891 if (unzStringFileNameCompare(szCurrentFileName,
892 szFileName,iCaseSensitivity)==0)
894 err = unzGoToNextFile(file);
898 /* We failed, so restore the state of the 'current file' to where we
901 s->num_file = num_fileSaved ;
902 s->pos_in_central_dir = pos_in_central_dirSaved ;
903 s->cur_file_info = cur_file_infoSaved;
904 s->cur_file_info_internal = cur_file_info_internalSaved;
910 ///////////////////////////////////////////
911 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
912 // I need random access
914 // Further optimization could be realized by adding an ability
915 // to cache the directory in memory. The goal being a single
916 // comprehensive file read to put the file I need in a memory.
920 typedef struct unz_file_pos_s
922 uLong pos_in_zip_directory; // offset in file
923 uLong num_of_file; // # of file
927 extern int ZEXPORT unzGetFilePos(file, file_pos)
929 unz_file_pos* file_pos;
933 if (file==NULL || file_pos==NULL)
934 return UNZ_PARAMERROR;
936 if (!s->current_file_ok)
937 return UNZ_END_OF_LIST_OF_FILE;
939 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
940 file_pos->num_of_file = s->num_file;
945 extern int ZEXPORT unzGoToFilePos(file, file_pos)
947 unz_file_pos* file_pos;
952 if (file==NULL || file_pos==NULL)
953 return UNZ_PARAMERROR;
956 /* jump to the right spot */
957 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
958 s->num_file = file_pos->num_of_file;
960 /* set the current file */
961 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
962 &s->cur_file_info_internal,
963 NULL,0,NULL,0,NULL,0);
965 s->current_file_ok = (err == UNZ_OK);
970 // Unzip Helper Functions - should be here?
971 ///////////////////////////////////////////
975 Read the local header of the current zipfile
976 Check the coherency of the local header and info in the end of central
977 directory about this file
978 store in *piSizeVar the size of extra info in local header
979 (filename and size of extra field data)
981 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
982 poffset_local_extrafield,
983 psize_local_extrafield)
986 uLong *poffset_local_extrafield;
987 uInt *psize_local_extrafield;
989 uLong uMagic,uData,uFlags;
991 uLong size_extra_field;
995 *poffset_local_extrafield = 0;
996 *psize_local_extrafield = 0;
998 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
999 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1004 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1006 else if (uMagic!=0x04034b50)
1010 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1013 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1016 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1019 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1021 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1024 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1025 (s->cur_file_info.compression_method!=Z_DEFLATED))
1028 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1031 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1033 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1037 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1039 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1043 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1045 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1050 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1052 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1055 *piSizeVar += (uInt)size_filename;
1057 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1059 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1060 SIZEZIPLOCALHEADER + size_filename;
1061 *psize_local_extrafield = (uInt)size_extra_field;
1063 *piSizeVar += (uInt)size_extra_field;
1069 Open for reading data the current file in the zipfile.
1070 If there is no error and the file is opened, the return value is UNZ_OK.
1072 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1077 const char* password;
1082 file_in_zip_read_info_s* pfile_in_zip_read_info;
1083 uLong offset_local_extrafield; /* offset of the local extra field */
1084 uInt size_local_extrafield; /* size of the local extra field */
1085 if (password != NULL)
1086 return UNZ_PARAMERROR;
1089 return UNZ_PARAMERROR;
1091 if (!s->current_file_ok)
1092 return UNZ_PARAMERROR;
1094 if (s->pfile_in_zip_read != NULL)
1095 unzCloseCurrentFile(file);
1097 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1098 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1099 return UNZ_BADZIPFILE;
1101 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1102 ALLOC(sizeof(file_in_zip_read_info_s));
1103 if (pfile_in_zip_read_info==NULL)
1104 return UNZ_INTERNALERROR;
1106 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1107 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1108 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1109 pfile_in_zip_read_info->pos_local_extrafield=0;
1110 pfile_in_zip_read_info->raw=raw;
1112 if (pfile_in_zip_read_info->read_buffer==NULL)
1114 TRYFREE(pfile_in_zip_read_info);
1115 return UNZ_INTERNALERROR;
1118 pfile_in_zip_read_info->stream_initialised=0;
1121 *method = (int)s->cur_file_info.compression_method;
1126 switch (s->cur_file_info.flag & 0x06)
1128 case 6 : *level = 1; break;
1129 case 4 : *level = 2; break;
1130 case 2 : *level = 9; break;
1134 if ((s->cur_file_info.compression_method!=0) &&
1135 (s->cur_file_info.compression_method!=Z_DEFLATED))
1138 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1139 pfile_in_zip_read_info->crc32=0;
1140 pfile_in_zip_read_info->compression_method =
1141 s->cur_file_info.compression_method;
1142 pfile_in_zip_read_info->filestream=s->filestream;
1143 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1144 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1146 pfile_in_zip_read_info->stream.total_out = 0;
1148 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1151 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1152 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1153 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1154 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1155 pfile_in_zip_read_info->stream.avail_in = 0;
1157 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1159 pfile_in_zip_read_info->stream_initialised=1;
1162 TRYFREE(pfile_in_zip_read_info);
1165 /* windowBits is passed < 0 to tell that there is no zlib header.
1166 * Note that in this case inflate *requires* an extra "dummy" byte
1167 * after the compressed stream in order to complete decompression and
1168 * return Z_STREAM_END.
1169 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1170 * size of both compressed and uncompressed data
1173 pfile_in_zip_read_info->rest_read_compressed =
1174 s->cur_file_info.compressed_size ;
1175 pfile_in_zip_read_info->rest_read_uncompressed =
1176 s->cur_file_info.uncompressed_size ;
1179 pfile_in_zip_read_info->pos_in_zipfile =
1180 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1183 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1185 s->pfile_in_zip_read = pfile_in_zip_read_info;
1190 extern int ZEXPORT unzOpenCurrentFile (file)
1193 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1196 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1198 const char* password;
1200 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1203 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1209 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1213 Read bytes from the current file.
1214 buf contain buffer where data must be copied
1215 len the size of buf.
1217 return the number of byte copied if somes bytes are copied
1218 return 0 if the end of file was reached
1219 return <0 with error code if there is an error
1220 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1222 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1230 file_in_zip_read_info_s* pfile_in_zip_read_info;
1232 return UNZ_PARAMERROR;
1234 pfile_in_zip_read_info=s->pfile_in_zip_read;
1236 if (pfile_in_zip_read_info==NULL)
1237 return UNZ_PARAMERROR;
1240 if ((pfile_in_zip_read_info->read_buffer == NULL))
1241 return UNZ_END_OF_LIST_OF_FILE;
1245 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1247 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1249 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1250 (!(pfile_in_zip_read_info->raw)))
1251 pfile_in_zip_read_info->stream.avail_out =
1252 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1254 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1255 pfile_in_zip_read_info->stream.avail_in) &&
1256 (pfile_in_zip_read_info->raw))
1257 pfile_in_zip_read_info->stream.avail_out =
1258 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1259 pfile_in_zip_read_info->stream.avail_in;
1261 while (pfile_in_zip_read_info->stream.avail_out>0)
1263 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1264 (pfile_in_zip_read_info->rest_read_compressed>0))
1266 uInt uReadThis = UNZ_BUFSIZE;
1267 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1268 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1271 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1272 pfile_in_zip_read_info->filestream,
1273 pfile_in_zip_read_info->pos_in_zipfile +
1274 pfile_in_zip_read_info->byte_before_the_zipfile,
1275 ZLIB_FILEFUNC_SEEK_SET)!=0)
1277 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1278 pfile_in_zip_read_info->filestream,
1279 pfile_in_zip_read_info->read_buffer,
1280 uReadThis)!=uReadThis)
1286 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1288 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1290 pfile_in_zip_read_info->stream.next_in =
1291 (Bytef*)pfile_in_zip_read_info->read_buffer;
1292 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1295 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1299 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1300 (pfile_in_zip_read_info->rest_read_compressed == 0))
1301 return (iRead==0) ? UNZ_EOF : iRead;
1303 if (pfile_in_zip_read_info->stream.avail_out <
1304 pfile_in_zip_read_info->stream.avail_in)
1305 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1307 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1309 for (i=0;i<uDoCopy;i++)
1310 *(pfile_in_zip_read_info->stream.next_out+i) =
1311 *(pfile_in_zip_read_info->stream.next_in+i);
1313 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1314 pfile_in_zip_read_info->stream.next_out,
1316 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1317 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1318 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1319 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1320 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1321 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1326 uLong uTotalOutBefore,uTotalOutAfter;
1327 const Bytef *bufBefore;
1329 int flush=Z_SYNC_FLUSH;
1331 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1332 bufBefore = pfile_in_zip_read_info->stream.next_out;
1335 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1336 pfile_in_zip_read_info->stream.avail_out) &&
1337 (pfile_in_zip_read_info->rest_read_compressed == 0))
1340 err=inflate(&pfile_in_zip_read_info->stream,flush);
1342 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1345 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1346 uOutThis = uTotalOutAfter-uTotalOutBefore;
1348 pfile_in_zip_read_info->crc32 =
1349 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1352 pfile_in_zip_read_info->rest_read_uncompressed -=
1355 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1357 if (err==Z_STREAM_END)
1358 return (iRead==0) ? UNZ_EOF : iRead;
1371 Give the current position in uncompressed data
1373 extern z_off_t ZEXPORT unztell (file)
1377 file_in_zip_read_info_s* pfile_in_zip_read_info;
1379 return UNZ_PARAMERROR;
1381 pfile_in_zip_read_info=s->pfile_in_zip_read;
1383 if (pfile_in_zip_read_info==NULL)
1384 return UNZ_PARAMERROR;
1386 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1391 return 1 if the end of file was reached, 0 elsewhere
1393 extern int ZEXPORT unzeof (file)
1397 file_in_zip_read_info_s* pfile_in_zip_read_info;
1399 return UNZ_PARAMERROR;
1401 pfile_in_zip_read_info=s->pfile_in_zip_read;
1403 if (pfile_in_zip_read_info==NULL)
1404 return UNZ_PARAMERROR;
1406 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1415 Read extra field from the current file (opened by unzOpenCurrentFile)
1416 This is the local-header version of the extra field (sometimes, there is
1417 more info in the local-header version than in the central-header)
1419 if buf==NULL, it return the size of the local extra field that can be read
1421 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1423 the return value is the number of bytes copied in buf, or (if <0)
1426 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1432 file_in_zip_read_info_s* pfile_in_zip_read_info;
1437 return UNZ_PARAMERROR;
1439 pfile_in_zip_read_info=s->pfile_in_zip_read;
1441 if (pfile_in_zip_read_info==NULL)
1442 return UNZ_PARAMERROR;
1444 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1445 pfile_in_zip_read_info->pos_local_extrafield);
1448 return (int)size_to_read;
1450 if (len>size_to_read)
1451 read_now = (uInt)size_to_read;
1453 read_now = (uInt)len ;
1458 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1459 pfile_in_zip_read_info->filestream,
1460 pfile_in_zip_read_info->offset_local_extrafield +
1461 pfile_in_zip_read_info->pos_local_extrafield,
1462 ZLIB_FILEFUNC_SEEK_SET)!=0)
1465 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1466 pfile_in_zip_read_info->filestream,
1467 buf,read_now)!=read_now)
1470 return (int)read_now;
1474 Close the file in zip opened with unzipOpenCurrentFile
1475 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1477 extern int ZEXPORT unzCloseCurrentFile (file)
1483 file_in_zip_read_info_s* pfile_in_zip_read_info;
1485 return UNZ_PARAMERROR;
1487 pfile_in_zip_read_info=s->pfile_in_zip_read;
1489 if (pfile_in_zip_read_info==NULL)
1490 return UNZ_PARAMERROR;
1493 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1494 (!pfile_in_zip_read_info->raw))
1496 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1501 TRYFREE(pfile_in_zip_read_info->read_buffer);
1502 pfile_in_zip_read_info->read_buffer = NULL;
1503 if (pfile_in_zip_read_info->stream_initialised)
1504 inflateEnd(&pfile_in_zip_read_info->stream);
1506 pfile_in_zip_read_info->stream_initialised = 0;
1507 TRYFREE(pfile_in_zip_read_info);
1509 s->pfile_in_zip_read=NULL;
1516 Get the global comment string of the ZipFile, in the szComment buffer.
1517 uSizeBuf is the size of the szComment buffer.
1518 return the number of byte copied or an error code <0
1520 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1529 return UNZ_PARAMERROR;
1532 uReadThis = uSizeBuf;
1533 if (uReadThis>s->gi.size_comment)
1534 uReadThis = s->gi.size_comment;
1536 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1542 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1546 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1547 *(szComment+s->gi.size_comment)='\0';
1548 return (int)uReadThis;
1551 /* Additions by RX '2004 */
1552 extern uLong ZEXPORT unzGetOffset (file)
1558 return UNZ_PARAMERROR;
1560 if (!s->current_file_ok)
1562 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1563 if (s->num_file==s->gi.number_entry)
1565 return s->pos_in_central_dir;
1568 extern int ZEXPORT unzSetOffset (file, pos)
1576 return UNZ_PARAMERROR;
1579 s->pos_in_central_dir = pos;
1580 s->num_file = s->gi.number_entry; /* hack */
1581 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1582 &s->cur_file_info_internal,
1583 NULL,0,NULL,0,NULL,0);
1584 s->current_file_ok = (err == UNZ_OK);