1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unzip.m,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 *************************************************************************/
31 /* unzip.c -- IO for uncompress .zip files using zlib
32 Version 1.01e, February 12th, 2005
34 Copyright (C) 1998-2005 Gilles Vollant
36 Read unzip.h for more info
39 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
40 compatibility with older software. The following is from the original crypt.c. Code
41 woven in by Terry Thorsen 1/2003.
44 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
46 See the accompanying file LICENSE, version 2000-Apr-09 or later
47 (the contents of which are also included in zip.h) for terms of use.
48 If, for some reason, all these files are missing, the Info-ZIP license
49 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
52 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
54 The encryption/decryption parts of this source code (as opposed to the
55 non-echoing password parts) were originally written in Europe. The
56 whole source package can be freely distributed, including from the USA.
57 (Prior to January 2000, re-export from the US was a violation of US law.)
61 This encryption code is a direct transcription of the algorithm from
62 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
63 file (appnote.txt) is distributed with the PKZIP program (even in the
64 version without encryption capabilities).
90 /* compile with -Dlocal if your debugger can't find static symbols */
93 #ifndef CASESENSITIVITYDEFAULT_NO
94 # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
95 # define CASESENSITIVITYDEFAULT_NO
101 #define UNZ_BUFSIZE (16384)
104 #ifndef UNZ_MAXFILENAMEINZIP
105 #define UNZ_MAXFILENAMEINZIP (256)
109 # define ALLOC(size) (malloc(size))
112 # define TRYFREE(p) {if (p) free(p);}
115 #define SIZECENTRALDIRITEM (0x2e)
116 #define SIZEZIPLOCALHEADER (0x1e)
121 const char unz_copyright[] =
122 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
124 /* unz_file_info_interntal contain internal info about a file in zipfile*/
125 typedef struct unz_file_info_internal_s
127 uLong offset_curfile;/* relative offset of local header 4 bytes */
128 } unz_file_info_internal;
131 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
132 when reading and decompress it */
135 char *read_buffer; /* internal buffer for compressed data */
136 z_stream stream; /* zLib stream structure for inflate */
138 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
139 uLong stream_initialised; /* flag set if stream structure is initialised*/
141 uLong offset_local_extrafield;/* offset of the local extra field */
142 uInt size_local_extrafield;/* size of the local extra field */
143 uLong pos_local_extrafield; /* position in the local extra field in read*/
145 uLong crc32; /* crc32 of all data uncompressed */
146 uLong crc32_wait; /* crc32 we must obtain after decompress all */
147 uLong rest_read_compressed; /* number of byte to be decompressed */
148 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
149 zlib_filefunc_def z_filefunc;
150 voidpf filestream; /* io structore of the zipfile */
151 uLong compression_method; /* compression method (0==store) */
152 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
154 } file_in_zip_read_info_s;
157 /* unz_s contain internal information about the zipfile
161 zlib_filefunc_def z_filefunc;
162 voidpf filestream; /* io structore of the zipfile */
163 unz_global_info gi; /* public global information */
164 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
165 uLong num_file; /* number of the current file in the zipfile*/
166 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
167 uLong current_file_ok; /* flag about the usability of the current file*/
168 uLong central_pos; /* position of the beginning of the central dir*/
170 uLong size_central_dir; /* size of the central directory */
171 uLong offset_central_dir; /* offset of start of central directory with
172 respect to the starting disk number */
174 unz_file_info cur_file_info; /* public info about the current file in zip*/
175 unz_file_info_internal cur_file_info_internal; /* private info about it*/
176 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
177 file if we are decompressing it */
183 /* ===========================================================================
184 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
186 IN assertion: the stream s has been sucessfully opened for reading.
190 local int unzlocal_getByte OF((
191 const zlib_filefunc_def* pzlib_filefunc_def,
195 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
196 const zlib_filefunc_def* pzlib_filefunc_def;
201 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
209 if (ZERROR(*pzlib_filefunc_def,filestream))
217 /* ===========================================================================
218 Reads a long in LSB order from the given gz_stream. Sets
220 local int unzlocal_getShort OF((
221 const zlib_filefunc_def* pzlib_filefunc_def,
225 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
226 const zlib_filefunc_def* pzlib_filefunc_def;
234 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
238 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
248 local int unzlocal_getLong OF((
249 const zlib_filefunc_def* pzlib_filefunc_def,
253 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
254 const zlib_filefunc_def* pzlib_filefunc_def;
262 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
266 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
270 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
274 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
285 /* My own strcmpi / strcasecmp */
286 local int strcmpcasenosensitive_internal (fileName1,fileName2)
287 const char* fileName1;
288 const char* fileName2;
292 char c1=*(fileName1++);
293 char c2=*(fileName2++);
294 if ((c1>='a') && (c1<='z'))
296 if ((c2>='a') && (c2<='z'))
299 return ((c2=='\0') ? 0 : -1);
310 #ifdef CASESENSITIVITYDEFAULT_NO
311 #define CASESENSITIVITYDEFAULTVALUE 2
313 #define CASESENSITIVITYDEFAULTVALUE 1
316 #ifndef STRCMPCASENOSENTIVEFUNCTION
317 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
321 Compare two filename (fileName1,fileName2).
322 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
323 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
325 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
326 (like 1 on Unix, 2 on Windows)
329 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
330 const char* fileName1;
331 const char* fileName2;
332 int iCaseSensitivity;
334 if (iCaseSensitivity==0)
335 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
337 if (iCaseSensitivity==1)
338 return strcmp(fileName1,fileName2);
340 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
343 #ifndef BUFREADCOMMENT
344 #define BUFREADCOMMENT (0x400)
348 Locate the Central directory of a zipfile (at the end, just before
351 local uLong unzlocal_SearchCentralDir OF((
352 const zlib_filefunc_def* pzlib_filefunc_def,
355 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
356 const zlib_filefunc_def* pzlib_filefunc_def;
362 uLong uMaxBack=0xffff; /* maximum size of global comment */
365 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
369 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
371 if (uMaxBack>uSizeFile)
372 uMaxBack = uSizeFile;
374 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
379 while (uBackRead<uMaxBack)
381 uLong uReadSize,uReadPos ;
383 if (uBackRead+BUFREADCOMMENT>uMaxBack)
384 uBackRead = uMaxBack;
386 uBackRead+=BUFREADCOMMENT;
387 uReadPos = uSizeFile-uBackRead ;
389 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
390 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
391 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
394 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
397 for (i=(int)uReadSize-3; (i--)>0;)
398 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
399 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
401 uPosFound = uReadPos+i;
413 Open a Zip file. path contain the full pathname (by example,
414 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
416 If the zipfile cannot be opened (file doesn't exist or in not valid), the
417 return value is NULL.
418 Else, the return value is a unzFile Handle, usable with other function
419 of this unzip package.
421 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
423 zlib_filefunc_def* pzlib_filefunc_def;
427 uLong central_pos,uL;
429 uLong number_disk; /* number of the current dist, used for
430 spaning ZIP, unsupported, always 0*/
431 uLong number_disk_with_CD; /* number the the disk with central dir, used
432 for spaning ZIP, unsupported, always 0*/
433 uLong number_entry_CD; /* total number of entries in
435 (same than number_entry on nospan) */
439 if (unz_copyright[0]!=' ')
442 if (pzlib_filefunc_def==NULL)
443 fill_fopen_filefunc(&us.z_filefunc);
445 us.z_filefunc = *pzlib_filefunc_def;
447 us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
449 ZLIB_FILEFUNC_MODE_READ |
450 ZLIB_FILEFUNC_MODE_EXISTING);
451 if (us.filestream==NULL)
454 central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
458 if (ZSEEK(us.z_filefunc, us.filestream,
459 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
462 /* the signature, already checked */
463 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
466 /* number of this disk */
467 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
470 /* number of the disk with the start of the central directory */
471 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
474 /* total number of entries in the central dir on this disk */
475 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
478 /* total number of entries in the central dir */
479 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
482 if ((number_entry_CD!=us.gi.number_entry) ||
483 (number_disk_with_CD!=0) ||
487 /* size of the central directory */
488 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
491 /* offset of start of central directory with respect to the
492 starting disk number */
493 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
496 /* zipfile comment length */
497 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
500 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
506 ZCLOSE(us.z_filefunc, us.filestream);
510 us.byte_before_the_zipfile = central_pos -
511 (us.offset_central_dir+us.size_central_dir);
512 us.central_pos = central_pos;
513 us.pfile_in_zip_read = NULL;
517 s=(unz_s*)ALLOC(sizeof(unz_s));
519 unzGoToFirstFile((unzFile)s);
524 extern unzFile ZEXPORT unzOpen (path)
527 return unzOpen2(path, NULL);
531 Close a ZipFile opened with unzipOpen.
532 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
533 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
534 return UNZ_OK if there is no problem. */
535 extern int ZEXPORT unzClose (file)
540 return UNZ_PARAMERROR;
543 if (s->pfile_in_zip_read!=NULL)
544 unzCloseCurrentFile(file);
546 ZCLOSE(s->z_filefunc, s->filestream);
553 Write info about the ZipFile in the *pglobal_info structure.
554 No preparation of the structure is needed
555 return UNZ_OK if there is no problem. */
556 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
558 unz_global_info *pglobal_info;
562 return UNZ_PARAMERROR;
570 Translate date/time from Dos format to tm_unz (readable more easilty)
572 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
577 uDate = (uLong)(ulDosDate>>16);
578 ptm->tm_mday = (uInt)(uDate&0x1f) ;
579 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
580 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
582 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
583 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
584 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
588 Get Info about the current file in the zipfile, with internal only info
590 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
591 unz_file_info *pfile_info,
592 unz_file_info_internal
593 *pfile_info_internal,
595 uLong fileNameBufferSize,
597 uLong extraFieldBufferSize,
599 uLong commentBufferSize));
601 local int unzlocal_GetCurrentFileInfoInternal (file,
604 szFileName, fileNameBufferSize,
605 extraField, extraFieldBufferSize,
606 szComment, commentBufferSize)
608 unz_file_info *pfile_info;
609 unz_file_info_internal *pfile_info_internal;
611 uLong fileNameBufferSize;
613 uLong extraFieldBufferSize;
615 uLong commentBufferSize;
618 unz_file_info file_info;
619 unz_file_info_internal file_info_internal;
625 return UNZ_PARAMERROR;
627 if (ZSEEK(s->z_filefunc, s->filestream,
628 s->pos_in_central_dir+s->byte_before_the_zipfile,
629 ZLIB_FILEFUNC_SEEK_SET)!=0)
633 /* we check the magic */
635 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
637 else if (uMagic!=0x02014b50)
641 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
644 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
647 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
650 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
653 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
656 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
658 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
661 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
664 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
667 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
670 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
673 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
676 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
679 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
682 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
685 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
688 lSeek+=file_info.size_filename;
689 if ((err==UNZ_OK) && (szFileName!=NULL))
692 if (file_info.size_filename<fileNameBufferSize)
694 *(szFileName+file_info.size_filename)='\0';
695 uSizeRead = file_info.size_filename;
698 uSizeRead = fileNameBufferSize;
700 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
701 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
707 if ((err==UNZ_OK) && (extraField!=NULL))
710 if (file_info.size_file_extra<extraFieldBufferSize)
711 uSizeRead = file_info.size_file_extra;
713 uSizeRead = extraFieldBufferSize;
716 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
721 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
722 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
724 lSeek += file_info.size_file_extra - uSizeRead;
727 lSeek+=file_info.size_file_extra;
730 if ((err==UNZ_OK) && (szComment!=NULL))
733 if (file_info.size_file_comment<commentBufferSize)
735 *(szComment+file_info.size_file_comment)='\0';
736 uSizeRead = file_info.size_file_comment;
739 uSizeRead = commentBufferSize;
742 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
747 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
748 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
750 lSeek+=file_info.size_file_comment - uSizeRead;
753 lSeek+=file_info.size_file_comment;
755 if ((err==UNZ_OK) && (pfile_info!=NULL))
756 *pfile_info=file_info;
758 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
759 *pfile_info_internal=file_info_internal;
767 Write info about the ZipFile in the *pglobal_info structure.
768 No preparation of the structure is needed
769 return UNZ_OK if there is no problem.
771 extern int ZEXPORT unzGetCurrentFileInfo (file,
773 szFileName, fileNameBufferSize,
774 extraField, extraFieldBufferSize,
775 szComment, commentBufferSize)
777 unz_file_info *pfile_info;
779 uLong fileNameBufferSize;
781 uLong extraFieldBufferSize;
783 uLong commentBufferSize;
785 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
786 szFileName,fileNameBufferSize,
787 extraField,extraFieldBufferSize,
788 szComment,commentBufferSize);
792 Set the current file of the zipfile to the first file.
793 return UNZ_OK if there is no problem
795 extern int ZEXPORT unzGoToFirstFile (file)
801 return UNZ_PARAMERROR;
803 s->pos_in_central_dir=s->offset_central_dir;
805 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
806 &s->cur_file_info_internal,
807 NULL,0,NULL,0,NULL,0);
808 s->current_file_ok = (err == UNZ_OK);
813 Set the current file of the zipfile to the next file.
814 return UNZ_OK if there is no problem
815 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
817 extern int ZEXPORT unzGoToNextFile (file)
824 return UNZ_PARAMERROR;
826 if (!s->current_file_ok)
827 return UNZ_END_OF_LIST_OF_FILE;
828 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
829 if (s->num_file+1==s->gi.number_entry)
830 return UNZ_END_OF_LIST_OF_FILE;
832 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
833 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
835 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
836 &s->cur_file_info_internal,
837 NULL,0,NULL,0,NULL,0);
838 s->current_file_ok = (err == UNZ_OK);
844 Try locate the file szFileName in the zipfile.
845 For the iCaseSensitivity signification, see unzipStringFileNameCompare
848 UNZ_OK if the file is found. It becomes the current file.
849 UNZ_END_OF_LIST_OF_FILE if the file is not found
851 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
853 const char *szFileName;
854 int iCaseSensitivity;
859 /* We remember the 'current' position in the file so that we can jump
860 * back there if we fail.
862 unz_file_info cur_file_infoSaved;
863 unz_file_info_internal cur_file_info_internalSaved;
865 uLong pos_in_central_dirSaved;
869 return UNZ_PARAMERROR;
871 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
872 return UNZ_PARAMERROR;
875 if (!s->current_file_ok)
876 return UNZ_END_OF_LIST_OF_FILE;
878 /* Save the current state */
879 num_fileSaved = s->num_file;
880 pos_in_central_dirSaved = s->pos_in_central_dir;
881 cur_file_infoSaved = s->cur_file_info;
882 cur_file_info_internalSaved = s->cur_file_info_internal;
884 err = unzGoToFirstFile(file);
886 while (err == UNZ_OK)
888 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
889 err = unzGetCurrentFileInfo(file,NULL,
890 szCurrentFileName,sizeof(szCurrentFileName)-1,
894 if (unzStringFileNameCompare(szCurrentFileName,
895 szFileName,iCaseSensitivity)==0)
897 err = unzGoToNextFile(file);
901 /* We failed, so restore the state of the 'current file' to where we
904 s->num_file = num_fileSaved ;
905 s->pos_in_central_dir = pos_in_central_dirSaved ;
906 s->cur_file_info = cur_file_infoSaved;
907 s->cur_file_info_internal = cur_file_info_internalSaved;
913 ///////////////////////////////////////////
914 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
915 // I need random access
917 // Further optimization could be realized by adding an ability
918 // to cache the directory in memory. The goal being a single
919 // comprehensive file read to put the file I need in a memory.
923 typedef struct unz_file_pos_s
925 uLong pos_in_zip_directory; // offset in file
926 uLong num_of_file; // # of file
930 extern int ZEXPORT unzGetFilePos(file, file_pos)
932 unz_file_pos* file_pos;
936 if (file==NULL || file_pos==NULL)
937 return UNZ_PARAMERROR;
939 if (!s->current_file_ok)
940 return UNZ_END_OF_LIST_OF_FILE;
942 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
943 file_pos->num_of_file = s->num_file;
948 extern int ZEXPORT unzGoToFilePos(file, file_pos)
950 unz_file_pos* file_pos;
955 if (file==NULL || file_pos==NULL)
956 return UNZ_PARAMERROR;
959 /* jump to the right spot */
960 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
961 s->num_file = file_pos->num_of_file;
963 /* set the current file */
964 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
965 &s->cur_file_info_internal,
966 NULL,0,NULL,0,NULL,0);
968 s->current_file_ok = (err == UNZ_OK);
973 // Unzip Helper Functions - should be here?
974 ///////////////////////////////////////////
978 Read the local header of the current zipfile
979 Check the coherency of the local header and info in the end of central
980 directory about this file
981 store in *piSizeVar the size of extra info in local header
982 (filename and size of extra field data)
984 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
985 poffset_local_extrafield,
986 psize_local_extrafield)
989 uLong *poffset_local_extrafield;
990 uInt *psize_local_extrafield;
992 uLong uMagic,uData,uFlags;
994 uLong size_extra_field;
998 *poffset_local_extrafield = 0;
999 *psize_local_extrafield = 0;
1001 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1002 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1007 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1009 else if (uMagic!=0x04034b50)
1013 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1016 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1019 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1022 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1024 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1027 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1028 (s->cur_file_info.compression_method!=Z_DEFLATED))
1031 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1034 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1036 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1040 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1042 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1046 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1048 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1053 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1055 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1058 *piSizeVar += (uInt)size_filename;
1060 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1062 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1063 SIZEZIPLOCALHEADER + size_filename;
1064 *psize_local_extrafield = (uInt)size_extra_field;
1066 *piSizeVar += (uInt)size_extra_field;
1072 Open for reading data the current file in the zipfile.
1073 If there is no error and the file is opened, the return value is UNZ_OK.
1075 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1080 const char* password;
1085 file_in_zip_read_info_s* pfile_in_zip_read_info;
1086 uLong offset_local_extrafield; /* offset of the local extra field */
1087 uInt size_local_extrafield; /* size of the local extra field */
1088 if (password != NULL)
1089 return UNZ_PARAMERROR;
1092 return UNZ_PARAMERROR;
1094 if (!s->current_file_ok)
1095 return UNZ_PARAMERROR;
1097 if (s->pfile_in_zip_read != NULL)
1098 unzCloseCurrentFile(file);
1100 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1101 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1102 return UNZ_BADZIPFILE;
1104 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1105 ALLOC(sizeof(file_in_zip_read_info_s));
1106 if (pfile_in_zip_read_info==NULL)
1107 return UNZ_INTERNALERROR;
1109 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1110 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1111 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1112 pfile_in_zip_read_info->pos_local_extrafield=0;
1113 pfile_in_zip_read_info->raw=raw;
1115 if (pfile_in_zip_read_info->read_buffer==NULL)
1117 TRYFREE(pfile_in_zip_read_info);
1118 return UNZ_INTERNALERROR;
1121 pfile_in_zip_read_info->stream_initialised=0;
1124 *method = (int)s->cur_file_info.compression_method;
1129 switch (s->cur_file_info.flag & 0x06)
1131 case 6 : *level = 1; break;
1132 case 4 : *level = 2; break;
1133 case 2 : *level = 9; break;
1137 if ((s->cur_file_info.compression_method!=0) &&
1138 (s->cur_file_info.compression_method!=Z_DEFLATED))
1141 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1142 pfile_in_zip_read_info->crc32=0;
1143 pfile_in_zip_read_info->compression_method =
1144 s->cur_file_info.compression_method;
1145 pfile_in_zip_read_info->filestream=s->filestream;
1146 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1147 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1149 pfile_in_zip_read_info->stream.total_out = 0;
1151 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1154 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1155 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1156 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1157 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1158 pfile_in_zip_read_info->stream.avail_in = 0;
1160 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1162 pfile_in_zip_read_info->stream_initialised=1;
1165 TRYFREE(pfile_in_zip_read_info);
1168 /* windowBits is passed < 0 to tell that there is no zlib header.
1169 * Note that in this case inflate *requires* an extra "dummy" byte
1170 * after the compressed stream in order to complete decompression and
1171 * return Z_STREAM_END.
1172 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1173 * size of both compressed and uncompressed data
1176 pfile_in_zip_read_info->rest_read_compressed =
1177 s->cur_file_info.compressed_size ;
1178 pfile_in_zip_read_info->rest_read_uncompressed =
1179 s->cur_file_info.uncompressed_size ;
1182 pfile_in_zip_read_info->pos_in_zipfile =
1183 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1186 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1188 s->pfile_in_zip_read = pfile_in_zip_read_info;
1193 extern int ZEXPORT unzOpenCurrentFile (file)
1196 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1199 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1201 const char* password;
1203 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1206 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1212 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1216 Read bytes from the current file.
1217 buf contain buffer where data must be copied
1218 len the size of buf.
1220 return the number of byte copied if somes bytes are copied
1221 return 0 if the end of file was reached
1222 return <0 with error code if there is an error
1223 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1225 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1233 file_in_zip_read_info_s* pfile_in_zip_read_info;
1235 return UNZ_PARAMERROR;
1237 pfile_in_zip_read_info=s->pfile_in_zip_read;
1239 if (pfile_in_zip_read_info==NULL)
1240 return UNZ_PARAMERROR;
1243 if ((pfile_in_zip_read_info->read_buffer == NULL))
1244 return UNZ_END_OF_LIST_OF_FILE;
1248 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1250 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1252 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1253 (!(pfile_in_zip_read_info->raw)))
1254 pfile_in_zip_read_info->stream.avail_out =
1255 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1257 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1258 pfile_in_zip_read_info->stream.avail_in) &&
1259 (pfile_in_zip_read_info->raw))
1260 pfile_in_zip_read_info->stream.avail_out =
1261 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1262 pfile_in_zip_read_info->stream.avail_in;
1264 while (pfile_in_zip_read_info->stream.avail_out>0)
1266 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1267 (pfile_in_zip_read_info->rest_read_compressed>0))
1269 uInt uReadThis = UNZ_BUFSIZE;
1270 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1271 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1274 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1275 pfile_in_zip_read_info->filestream,
1276 pfile_in_zip_read_info->pos_in_zipfile +
1277 pfile_in_zip_read_info->byte_before_the_zipfile,
1278 ZLIB_FILEFUNC_SEEK_SET)!=0)
1280 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1281 pfile_in_zip_read_info->filestream,
1282 pfile_in_zip_read_info->read_buffer,
1283 uReadThis)!=uReadThis)
1289 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1291 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1293 pfile_in_zip_read_info->stream.next_in =
1294 (Bytef*)pfile_in_zip_read_info->read_buffer;
1295 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1298 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1302 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1303 (pfile_in_zip_read_info->rest_read_compressed == 0))
1304 return (iRead==0) ? UNZ_EOF : iRead;
1306 if (pfile_in_zip_read_info->stream.avail_out <
1307 pfile_in_zip_read_info->stream.avail_in)
1308 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1310 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1312 for (i=0;i<uDoCopy;i++)
1313 *(pfile_in_zip_read_info->stream.next_out+i) =
1314 *(pfile_in_zip_read_info->stream.next_in+i);
1316 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1317 pfile_in_zip_read_info->stream.next_out,
1319 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1320 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1321 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1322 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1323 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1324 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1329 uLong uTotalOutBefore,uTotalOutAfter;
1330 const Bytef *bufBefore;
1332 int flush=Z_SYNC_FLUSH;
1334 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1335 bufBefore = pfile_in_zip_read_info->stream.next_out;
1338 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1339 pfile_in_zip_read_info->stream.avail_out) &&
1340 (pfile_in_zip_read_info->rest_read_compressed == 0))
1343 err=inflate(&pfile_in_zip_read_info->stream,flush);
1345 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1348 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1349 uOutThis = uTotalOutAfter-uTotalOutBefore;
1351 pfile_in_zip_read_info->crc32 =
1352 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1355 pfile_in_zip_read_info->rest_read_uncompressed -=
1358 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1360 if (err==Z_STREAM_END)
1361 return (iRead==0) ? UNZ_EOF : iRead;
1374 Give the current position in uncompressed data
1376 extern z_off_t ZEXPORT unztell (file)
1380 file_in_zip_read_info_s* pfile_in_zip_read_info;
1382 return UNZ_PARAMERROR;
1384 pfile_in_zip_read_info=s->pfile_in_zip_read;
1386 if (pfile_in_zip_read_info==NULL)
1387 return UNZ_PARAMERROR;
1389 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1394 return 1 if the end of file was reached, 0 elsewhere
1396 extern int ZEXPORT unzeof (file)
1400 file_in_zip_read_info_s* pfile_in_zip_read_info;
1402 return UNZ_PARAMERROR;
1404 pfile_in_zip_read_info=s->pfile_in_zip_read;
1406 if (pfile_in_zip_read_info==NULL)
1407 return UNZ_PARAMERROR;
1409 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1418 Read extra field from the current file (opened by unzOpenCurrentFile)
1419 This is the local-header version of the extra field (sometimes, there is
1420 more info in the local-header version than in the central-header)
1422 if buf==NULL, it return the size of the local extra field that can be read
1424 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1426 the return value is the number of bytes copied in buf, or (if <0)
1429 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1435 file_in_zip_read_info_s* pfile_in_zip_read_info;
1440 return UNZ_PARAMERROR;
1442 pfile_in_zip_read_info=s->pfile_in_zip_read;
1444 if (pfile_in_zip_read_info==NULL)
1445 return UNZ_PARAMERROR;
1447 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1448 pfile_in_zip_read_info->pos_local_extrafield);
1451 return (int)size_to_read;
1453 if (len>size_to_read)
1454 read_now = (uInt)size_to_read;
1456 read_now = (uInt)len ;
1461 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1462 pfile_in_zip_read_info->filestream,
1463 pfile_in_zip_read_info->offset_local_extrafield +
1464 pfile_in_zip_read_info->pos_local_extrafield,
1465 ZLIB_FILEFUNC_SEEK_SET)!=0)
1468 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1469 pfile_in_zip_read_info->filestream,
1470 buf,read_now)!=read_now)
1473 return (int)read_now;
1477 Close the file in zip opened with unzipOpenCurrentFile
1478 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1480 extern int ZEXPORT unzCloseCurrentFile (file)
1486 file_in_zip_read_info_s* pfile_in_zip_read_info;
1488 return UNZ_PARAMERROR;
1490 pfile_in_zip_read_info=s->pfile_in_zip_read;
1492 if (pfile_in_zip_read_info==NULL)
1493 return UNZ_PARAMERROR;
1496 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1497 (!pfile_in_zip_read_info->raw))
1499 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1504 TRYFREE(pfile_in_zip_read_info->read_buffer);
1505 pfile_in_zip_read_info->read_buffer = NULL;
1506 if (pfile_in_zip_read_info->stream_initialised)
1507 inflateEnd(&pfile_in_zip_read_info->stream);
1509 pfile_in_zip_read_info->stream_initialised = 0;
1510 TRYFREE(pfile_in_zip_read_info);
1512 s->pfile_in_zip_read=NULL;
1519 Get the global comment string of the ZipFile, in the szComment buffer.
1520 uSizeBuf is the size of the szComment buffer.
1521 return the number of byte copied or an error code <0
1523 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1532 return UNZ_PARAMERROR;
1535 uReadThis = uSizeBuf;
1536 if (uReadThis>s->gi.size_comment)
1537 uReadThis = s->gi.size_comment;
1539 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1545 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1549 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1550 *(szComment+s->gi.size_comment)='\0';
1551 return (int)uReadThis;
1554 /* Additions by RX '2004 */
1555 extern uLong ZEXPORT unzGetOffset (file)
1561 return UNZ_PARAMERROR;
1563 if (!s->current_file_ok)
1565 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1566 if (s->num_file==s->gi.number_entry)
1568 return s->pos_in_central_dir;
1571 extern int ZEXPORT unzSetOffset (file, pos)
1579 return UNZ_PARAMERROR;
1582 s->pos_in_central_dir = pos;
1583 s->num_file = s->gi.number_entry; /* hack */
1584 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1585 &s->cur_file_info_internal,
1586 NULL,0,NULL,0,NULL,0);
1587 s->current_file_ok = (err == UNZ_OK);