1 /* unzip.c -- IO for uncompress .zip files using zlib
2 Version 1.01e, February 12th, 2005
4 Copyright (C) 1998-2005 Gilles Vollant
6 Read unzip.h for more info
9 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
10 compatibility with older software. The following is from the original crypt.c. Code
11 woven in by Terry Thorsen 1/2003.
14 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
16 See the accompanying file LICENSE, version 2000-Apr-09 or later
17 (the contents of which are also included in zip.h) for terms of use.
18 If, for some reason, all these files are missing, the Info-ZIP license
19 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
22 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
24 The encryption/decryption parts of this source code (as opposed to the
25 non-echoing password parts) were originally written in Europe. The
26 whole source package can be freely distributed, including from the USA.
27 (Prior to January 2000, re-export from the US was a violation of US law.)
31 This encryption code is a direct transcription of the algorithm from
32 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
33 file (appnote.txt) is distributed with the PKZIP program (even in the
34 version without encryption capabilities).
56 /* compile with -Dlocal if your debugger can't find static symbols */
59 #ifndef CASESENSITIVITYDEFAULT_NO
60 # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
61 # define CASESENSITIVITYDEFAULT_NO
67 #define UNZ_BUFSIZE (16384)
70 #ifndef UNZ_MAXFILENAMEINZIP
71 #define UNZ_MAXFILENAMEINZIP (256)
75 # define ALLOC(size) (malloc(size))
78 # define TRYFREE(p) {free(p);}
81 #define SIZECENTRALDIRITEM (0x2e)
82 #define SIZEZIPLOCALHEADER (0x1e)
87 const char unz_copyright[] =
88 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
90 /* unz_file_info_interntal contain internal info about a file in zipfile*/
91 typedef struct unz_file_info_internal_s
93 uLong offset_curfile;/* relative offset of local header 4 bytes */
94 } unz_file_info_internal;
97 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
98 when reading and decompress it */
101 char *read_buffer; /* internal buffer for compressed data */
102 z_stream stream; /* zLib stream structure for inflate */
104 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
105 uLong stream_initialised; /* flag set if stream structure is initialised*/
107 uLong offset_local_extrafield;/* offset of the local extra field */
108 uInt size_local_extrafield;/* size of the local extra field */
109 uLong pos_local_extrafield; /* position in the local extra field in read*/
111 uLong crc32; /* crc32 of all data uncompressed */
112 uLong crc32_wait; /* crc32 we must obtain after decompress all */
113 uLong rest_read_compressed; /* number of byte to be decompressed */
114 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
115 zlib_filefunc_def z_filefunc;
116 voidpf filestream; /* io structore of the zipfile */
117 uLong compression_method; /* compression method (0==store) */
118 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
120 } file_in_zip_read_info_s;
123 /* unz_s contain internal information about the zipfile
127 zlib_filefunc_def z_filefunc;
128 voidpf filestream; /* io structore of the zipfile */
129 unz_global_info gi; /* public global information */
130 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
131 uLong num_file; /* number of the current file in the zipfile*/
132 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
133 uLong current_file_ok; /* flag about the usability of the current file*/
134 uLong central_pos; /* position of the beginning of the central dir*/
136 uLong size_central_dir; /* size of the central directory */
137 uLong offset_central_dir; /* offset of start of central directory with
138 respect to the starting disk number */
140 unz_file_info cur_file_info; /* public info about the current file in zip*/
141 unz_file_info_internal cur_file_info_internal; /* private info about it*/
142 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
143 file if we are decompressing it */
146 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
147 const unsigned long* pcrc_32_tab;
156 /* ===========================================================================
157 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
159 IN assertion: the stream s has been sucessfully opened for reading.
163 local int unzlocal_getByte OF((
164 const zlib_filefunc_def* pzlib_filefunc_def,
168 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
169 const zlib_filefunc_def* pzlib_filefunc_def;
174 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
182 if (ZERROR(*pzlib_filefunc_def,filestream))
190 /* ===========================================================================
191 Reads a long in LSB order from the given gz_stream. Sets
193 local int unzlocal_getShort OF((
194 const zlib_filefunc_def* pzlib_filefunc_def,
198 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
199 const zlib_filefunc_def* pzlib_filefunc_def;
207 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
211 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
221 local int unzlocal_getLong OF((
222 const zlib_filefunc_def* pzlib_filefunc_def,
226 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
227 const zlib_filefunc_def* pzlib_filefunc_def;
235 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
239 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
243 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
247 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
258 /* My own strcmpi / strcasecmp */
259 local int strcmpcasenosensitive_internal (fileName1,fileName2)
260 const char* fileName1;
261 const char* fileName2;
265 char c1=*(fileName1++);
266 char c2=*(fileName2++);
267 if ((c1>='a') && (c1<='z'))
269 if ((c2>='a') && (c2<='z'))
272 return ((c2=='\0') ? 0 : -1);
283 #ifdef CASESENSITIVITYDEFAULT_NO
284 #define CASESENSITIVITYDEFAULTVALUE 2
286 #define CASESENSITIVITYDEFAULTVALUE 1
289 #ifndef STRCMPCASENOSENTIVEFUNCTION
290 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
294 Compare two filename (fileName1,fileName2).
295 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
296 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
298 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
299 (like 1 on Unix, 2 on Windows)
302 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
303 const char* fileName1;
304 const char* fileName2;
305 int iCaseSensitivity;
307 if (iCaseSensitivity==0)
308 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
310 if (iCaseSensitivity==1)
311 return strcmp(fileName1,fileName2);
313 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
316 #ifndef BUFREADCOMMENT
317 #define BUFREADCOMMENT (0x400)
321 Locate the Central directory of a zipfile (at the end, just before
324 local uLong unzlocal_SearchCentralDir OF((
325 const zlib_filefunc_def* pzlib_filefunc_def,
328 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
329 const zlib_filefunc_def* pzlib_filefunc_def;
335 uLong uMaxBack=0xffff; /* maximum size of global comment */
338 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
342 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
344 if (uMaxBack>uSizeFile)
345 uMaxBack = uSizeFile;
347 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
352 while (uBackRead<uMaxBack)
354 uLong uReadSize,uReadPos ;
356 if (uBackRead+BUFREADCOMMENT>uMaxBack)
357 uBackRead = uMaxBack;
359 uBackRead+=BUFREADCOMMENT;
360 uReadPos = uSizeFile-uBackRead ;
362 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
363 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
364 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
367 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
370 for (i=(int)uReadSize-3; (i--)>0;)
371 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
372 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
374 uPosFound = uReadPos+i;
386 Open a Zip file. path contain the full pathname (by example,
387 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
389 If the zipfile cannot be opened (file doesn't exist or in not valid), the
390 return value is NULL.
391 Else, the return value is a unzFile Handle, usable with other function
392 of this unzip package.
394 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
396 zlib_filefunc_def* pzlib_filefunc_def;
400 uLong central_pos,uL;
402 uLong number_disk; /* number of the current dist, used for
403 spaning ZIP, unsupported, always 0*/
404 uLong number_disk_with_CD; /* number the the disk with central dir, used
405 for spaning ZIP, unsupported, always 0*/
406 uLong number_entry_CD; /* total number of entries in
408 (same than number_entry on nospan) */
412 if (unz_copyright[0]!=' ')
415 if (pzlib_filefunc_def==NULL)
416 fill_fopen_filefunc(&us.z_filefunc);
418 us.z_filefunc = *pzlib_filefunc_def;
420 us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
422 ZLIB_FILEFUNC_MODE_READ |
423 ZLIB_FILEFUNC_MODE_EXISTING);
424 if (us.filestream==NULL)
427 central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
431 if (ZSEEK(us.z_filefunc, us.filestream,
432 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
435 /* the signature, already checked */
436 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
439 /* number of this disk */
440 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
443 /* number of the disk with the start of the central directory */
444 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
447 /* total number of entries in the central dir on this disk */
448 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
451 /* total number of entries in the central dir */
452 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
455 if ((number_entry_CD!=us.gi.number_entry) ||
456 (number_disk_with_CD!=0) ||
460 /* size of the central directory */
461 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
464 /* offset of start of central directory with respect to the
465 starting disk number */
466 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
469 /* zipfile comment length */
470 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
473 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
479 ZCLOSE(us.z_filefunc, us.filestream);
483 us.byte_before_the_zipfile = central_pos -
484 (us.offset_central_dir+us.size_central_dir);
485 us.central_pos = central_pos;
486 us.pfile_in_zip_read = NULL;
490 s=(unz_s*)ALLOC(sizeof(unz_s));
492 unzGoToFirstFile((unzFile)s);
497 extern unzFile ZEXPORT unzOpen (path)
500 return unzOpen2(path, NULL);
504 Close a ZipFile opened with unzipOpen.
505 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
506 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
507 return UNZ_OK if there is no problem. */
508 extern int ZEXPORT unzClose (file)
513 return UNZ_PARAMERROR;
516 if (s->pfile_in_zip_read!=NULL)
517 unzCloseCurrentFile(file);
519 ZCLOSE(s->z_filefunc, s->filestream);
526 Write info about the ZipFile in the *pglobal_info structure.
527 No preparation of the structure is needed
528 return UNZ_OK if there is no problem. */
529 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
531 unz_global_info *pglobal_info;
535 return UNZ_PARAMERROR;
543 Translate date/time from Dos format to tm_unz (readable more easilty)
545 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
550 uDate = (uLong)(ulDosDate>>16);
551 ptm->tm_mday = (uInt)(uDate&0x1f) ;
552 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
553 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
555 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
556 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
557 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
561 Get Info about the current file in the zipfile, with internal only info
563 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
564 unz_file_info *pfile_info,
565 unz_file_info_internal
566 *pfile_info_internal,
568 uLong fileNameBufferSize,
570 uLong extraFieldBufferSize,
572 uLong commentBufferSize));
574 local int unzlocal_GetCurrentFileInfoInternal (file,
577 szFileName, fileNameBufferSize,
578 extraField, extraFieldBufferSize,
579 szComment, commentBufferSize)
581 unz_file_info *pfile_info;
582 unz_file_info_internal *pfile_info_internal;
584 uLong fileNameBufferSize;
586 uLong extraFieldBufferSize;
588 uLong commentBufferSize;
591 unz_file_info file_info;
592 unz_file_info_internal file_info_internal;
598 return UNZ_PARAMERROR;
600 if (ZSEEK(s->z_filefunc, s->filestream,
601 s->pos_in_central_dir+s->byte_before_the_zipfile,
602 ZLIB_FILEFUNC_SEEK_SET)!=0)
606 /* we check the magic */
609 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
611 else if (uMagic!=0x02014b50)
615 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
618 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
621 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
624 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
627 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
630 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
632 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
635 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
638 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
641 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
644 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
647 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
650 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
653 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
656 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
659 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
662 lSeek+=file_info.size_filename;
663 if ((err==UNZ_OK) && (szFileName!=NULL))
666 if (file_info.size_filename<fileNameBufferSize)
668 *(szFileName+file_info.size_filename)='\0';
669 uSizeRead = file_info.size_filename;
672 uSizeRead = fileNameBufferSize;
674 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
675 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
681 if ((err==UNZ_OK) && (extraField!=NULL))
684 if (file_info.size_file_extra<extraFieldBufferSize)
685 uSizeRead = file_info.size_file_extra;
687 uSizeRead = extraFieldBufferSize;
691 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
696 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
697 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
699 lSeek += file_info.size_file_extra - uSizeRead;
702 lSeek+=file_info.size_file_extra;
705 if ((err==UNZ_OK) && (szComment!=NULL))
708 if (file_info.size_file_comment<commentBufferSize)
710 *(szComment+file_info.size_file_comment)='\0';
711 uSizeRead = file_info.size_file_comment;
714 uSizeRead = commentBufferSize;
718 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
723 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
724 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
726 lSeek+=file_info.size_file_comment - uSizeRead;
729 lSeek+=file_info.size_file_comment;
731 if ((err==UNZ_OK) && (pfile_info!=NULL))
732 *pfile_info=file_info;
734 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
735 *pfile_info_internal=file_info_internal;
743 Write info about the ZipFile in the *pglobal_info structure.
744 No preparation of the structure is needed
745 return UNZ_OK if there is no problem.
747 extern int ZEXPORT unzGetCurrentFileInfo (file,
749 szFileName, fileNameBufferSize,
750 extraField, extraFieldBufferSize,
751 szComment, commentBufferSize)
753 unz_file_info *pfile_info;
755 uLong fileNameBufferSize;
757 uLong extraFieldBufferSize;
759 uLong commentBufferSize;
761 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
762 szFileName,fileNameBufferSize,
763 extraField,extraFieldBufferSize,
764 szComment,commentBufferSize);
768 Set the current file of the zipfile to the first file.
769 return UNZ_OK if there is no problem
771 extern int ZEXPORT unzGoToFirstFile (file)
777 return UNZ_PARAMERROR;
779 s->pos_in_central_dir=s->offset_central_dir;
781 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
782 &s->cur_file_info_internal,
783 NULL,0,NULL,0,NULL,0);
784 s->current_file_ok = (err == UNZ_OK);
789 Set the current file of the zipfile to the next file.
790 return UNZ_OK if there is no problem
791 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
793 extern int ZEXPORT unzGoToNextFile (file)
800 return UNZ_PARAMERROR;
802 if (!s->current_file_ok)
803 return UNZ_END_OF_LIST_OF_FILE;
804 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
805 if (s->num_file+1==s->gi.number_entry)
806 return UNZ_END_OF_LIST_OF_FILE;
808 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
809 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
811 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
812 &s->cur_file_info_internal,
813 NULL,0,NULL,0,NULL,0);
814 s->current_file_ok = (err == UNZ_OK);
820 Try locate the file szFileName in the zipfile.
821 For the iCaseSensitivity signification, see unzipStringFileNameCompare
824 UNZ_OK if the file is found. It becomes the current file.
825 UNZ_END_OF_LIST_OF_FILE if the file is not found
827 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
829 const char *szFileName;
830 int iCaseSensitivity;
835 /* We remember the 'current' position in the file so that we can jump
836 * back there if we fail.
838 unz_file_info cur_file_infoSaved;
839 unz_file_info_internal cur_file_info_internalSaved;
841 uLong pos_in_central_dirSaved;
845 return UNZ_PARAMERROR;
847 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
848 return UNZ_PARAMERROR;
851 if (!s->current_file_ok)
852 return UNZ_END_OF_LIST_OF_FILE;
854 /* Save the current state */
855 num_fileSaved = s->num_file;
856 pos_in_central_dirSaved = s->pos_in_central_dir;
857 cur_file_infoSaved = s->cur_file_info;
858 cur_file_info_internalSaved = s->cur_file_info_internal;
860 err = unzGoToFirstFile(file);
862 while (err == UNZ_OK)
864 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
865 err = unzGetCurrentFileInfo(file,NULL,
866 szCurrentFileName,sizeof(szCurrentFileName)-1,
870 if (unzStringFileNameCompare(szCurrentFileName,
871 szFileName,iCaseSensitivity)==0)
873 err = unzGoToNextFile(file);
877 /* We failed, so restore the state of the 'current file' to where we
880 s->num_file = num_fileSaved ;
881 s->pos_in_central_dir = pos_in_central_dirSaved ;
882 s->cur_file_info = cur_file_infoSaved;
883 s->cur_file_info_internal = cur_file_info_internalSaved;
889 ///////////////////////////////////////////
890 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
891 // I need random access
893 // Further optimization could be realized by adding an ability
894 // to cache the directory in memory. The goal being a single
895 // comprehensive file read to put the file I need in a memory.
899 typedef struct unz_file_pos_s
901 uLong pos_in_zip_directory; // offset in file
902 uLong num_of_file; // # of file
906 extern int ZEXPORT unzGetFilePos(file, file_pos)
908 unz_file_pos* file_pos;
912 if (file==NULL || file_pos==NULL)
913 return UNZ_PARAMERROR;
915 if (!s->current_file_ok)
916 return UNZ_END_OF_LIST_OF_FILE;
918 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
919 file_pos->num_of_file = s->num_file;
924 extern int ZEXPORT unzGoToFilePos(file, file_pos)
926 unz_file_pos* file_pos;
931 if (file==NULL || file_pos==NULL)
932 return UNZ_PARAMERROR;
935 /* jump to the right spot */
936 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
937 s->num_file = file_pos->num_of_file;
939 /* set the current file */
940 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
941 &s->cur_file_info_internal,
942 NULL,0,NULL,0,NULL,0);
944 s->current_file_ok = (err == UNZ_OK);
949 // Unzip Helper Functions - should be here?
950 ///////////////////////////////////////////
954 Read the local header of the current zipfile
955 Check the coherency of the local header and info in the end of central
956 directory about this file
957 store in *piSizeVar the size of extra info in local header
958 (filename and size of extra field data)
960 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
961 poffset_local_extrafield,
962 psize_local_extrafield)
965 uLong *poffset_local_extrafield;
966 uInt *psize_local_extrafield;
968 uLong uMagic,uData,uFlags;
970 uLong size_extra_field;
974 *poffset_local_extrafield = 0;
975 *psize_local_extrafield = 0;
977 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
978 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
984 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
986 else if (uMagic!=0x04034b50)
989 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
992 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
995 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
998 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1000 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1003 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1004 (s->cur_file_info.compression_method!=Z_DEFLATED))
1007 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1010 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1012 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1016 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1018 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1022 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1024 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1029 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1031 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1034 *piSizeVar += (uInt)size_filename;
1036 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1038 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1039 SIZEZIPLOCALHEADER + size_filename;
1040 *psize_local_extrafield = (uInt)size_extra_field;
1042 *piSizeVar += (uInt)size_extra_field;
1048 Open for reading data the current file in the zipfile.
1049 If there is no error and the file is opened, the return value is UNZ_OK.
1051 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1056 const char* password;
1061 file_in_zip_read_info_s* pfile_in_zip_read_info;
1062 uLong offset_local_extrafield; /* offset of the local extra field */
1063 uInt size_local_extrafield; /* size of the local extra field */
1067 if (password != NULL)
1068 return UNZ_PARAMERROR;
1072 return UNZ_PARAMERROR;
1074 if (!s->current_file_ok)
1075 return UNZ_PARAMERROR;
1077 if (s->pfile_in_zip_read != NULL)
1078 unzCloseCurrentFile(file);
1080 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1081 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1082 return UNZ_BADZIPFILE;
1084 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1085 ALLOC(sizeof(file_in_zip_read_info_s));
1086 if (pfile_in_zip_read_info==NULL)
1087 return UNZ_INTERNALERROR;
1089 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1090 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1091 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1092 pfile_in_zip_read_info->pos_local_extrafield=0;
1093 pfile_in_zip_read_info->raw=raw;
1095 if (pfile_in_zip_read_info->read_buffer==NULL)
1097 TRYFREE(pfile_in_zip_read_info);
1098 return UNZ_INTERNALERROR;
1101 pfile_in_zip_read_info->stream_initialised=0;
1104 *method = (int)s->cur_file_info.compression_method;
1109 switch (s->cur_file_info.flag & 0x06)
1111 case 6 : *level = 1; break;
1112 case 4 : *level = 2; break;
1113 case 2 : *level = 9; break;
1117 if ((s->cur_file_info.compression_method!=0) &&
1118 (s->cur_file_info.compression_method!=Z_DEFLATED))
1121 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1122 pfile_in_zip_read_info->crc32=0;
1123 pfile_in_zip_read_info->compression_method =
1124 s->cur_file_info.compression_method;
1125 pfile_in_zip_read_info->filestream=s->filestream;
1126 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1127 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1129 pfile_in_zip_read_info->stream.total_out = 0;
1131 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1134 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1135 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1136 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1137 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1138 pfile_in_zip_read_info->stream.avail_in = 0;
1140 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1142 pfile_in_zip_read_info->stream_initialised=1;
1145 TRYFREE(pfile_in_zip_read_info);
1148 /* windowBits is passed < 0 to tell that there is no zlib header.
1149 * Note that in this case inflate *requires* an extra "dummy" byte
1150 * after the compressed stream in order to complete decompression and
1151 * return Z_STREAM_END.
1152 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1153 * size of both compressed and uncompressed data
1156 pfile_in_zip_read_info->rest_read_compressed =
1157 s->cur_file_info.compressed_size ;
1158 pfile_in_zip_read_info->rest_read_uncompressed =
1159 s->cur_file_info.uncompressed_size ;
1162 pfile_in_zip_read_info->pos_in_zipfile =
1163 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1166 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1168 s->pfile_in_zip_read = pfile_in_zip_read_info;
1171 if (password != NULL)
1174 s->pcrc_32_tab = get_crc_table();
1175 init_keys(password,s->keys,s->pcrc_32_tab);
1176 if (ZSEEK(s->z_filefunc, s->filestream,
1177 s->pfile_in_zip_read->pos_in_zipfile +
1178 s->pfile_in_zip_read->byte_before_the_zipfile,
1180 return UNZ_INTERNALERROR;
1181 if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1182 return UNZ_INTERNALERROR;
1184 for (i = 0; i<12; i++)
1185 zdecode(s->keys,s->pcrc_32_tab,source[i]);
1187 s->pfile_in_zip_read->pos_in_zipfile+=12;
1196 extern int ZEXPORT unzOpenCurrentFile (file)
1199 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1202 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1204 const char* password;
1206 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1209 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1215 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1219 Read bytes from the current file.
1220 buf contain buffer where data must be copied
1221 len the size of buf.
1223 return the number of byte copied if somes bytes are copied
1224 return 0 if the end of file was reached
1225 return <0 with error code if there is an error
1226 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1228 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1236 file_in_zip_read_info_s* pfile_in_zip_read_info;
1238 return UNZ_PARAMERROR;
1240 pfile_in_zip_read_info=s->pfile_in_zip_read;
1242 if (pfile_in_zip_read_info==NULL)
1243 return UNZ_PARAMERROR;
1246 if ((pfile_in_zip_read_info->read_buffer == NULL))
1247 return UNZ_END_OF_LIST_OF_FILE;
1251 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1253 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1255 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
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_uncompressed;
1260 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1261 pfile_in_zip_read_info->stream.avail_in) &&
1262 (pfile_in_zip_read_info->raw))
1263 pfile_in_zip_read_info->stream.avail_out =
1264 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1265 pfile_in_zip_read_info->stream.avail_in;
1267 while (pfile_in_zip_read_info->stream.avail_out>0)
1269 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1270 (pfile_in_zip_read_info->rest_read_compressed>0))
1272 uInt uReadThis = UNZ_BUFSIZE;
1273 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1274 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1277 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1278 pfile_in_zip_read_info->filestream,
1279 pfile_in_zip_read_info->pos_in_zipfile +
1280 pfile_in_zip_read_info->byte_before_the_zipfile,
1281 ZLIB_FILEFUNC_SEEK_SET)!=0)
1283 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1284 pfile_in_zip_read_info->filestream,
1285 pfile_in_zip_read_info->read_buffer,
1286 uReadThis)!=uReadThis)
1294 for(i=0;i<uReadThis;i++)
1295 pfile_in_zip_read_info->read_buffer[i] =
1296 zdecode(s->keys,s->pcrc_32_tab,
1297 pfile_in_zip_read_info->read_buffer[i]);
1302 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1304 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1306 pfile_in_zip_read_info->stream.next_in =
1307 (Bytef*)pfile_in_zip_read_info->read_buffer;
1308 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1311 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1315 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1316 (pfile_in_zip_read_info->rest_read_compressed == 0))
1317 return (iRead==0) ? UNZ_EOF : iRead;
1319 if (pfile_in_zip_read_info->stream.avail_out <
1320 pfile_in_zip_read_info->stream.avail_in)
1321 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1323 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1325 for (i=0;i<uDoCopy;i++)
1326 *(pfile_in_zip_read_info->stream.next_out+i) =
1327 *(pfile_in_zip_read_info->stream.next_in+i);
1329 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1330 pfile_in_zip_read_info->stream.next_out,
1332 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1333 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1334 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1335 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1336 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1337 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1342 uLong uTotalOutBefore,uTotalOutAfter;
1343 const Bytef *bufBefore;
1345 int flush=Z_SYNC_FLUSH;
1347 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1348 bufBefore = pfile_in_zip_read_info->stream.next_out;
1351 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1352 pfile_in_zip_read_info->stream.avail_out) &&
1353 (pfile_in_zip_read_info->rest_read_compressed == 0))
1356 err=inflate(&pfile_in_zip_read_info->stream,flush);
1358 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1361 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1362 uOutThis = uTotalOutAfter-uTotalOutBefore;
1364 pfile_in_zip_read_info->crc32 =
1365 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1368 pfile_in_zip_read_info->rest_read_uncompressed -=
1371 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1373 if (err==Z_STREAM_END)
1374 return (iRead==0) ? UNZ_EOF : iRead;
1387 Give the current position in uncompressed data
1389 extern z_off_t ZEXPORT unztell (file)
1393 file_in_zip_read_info_s* pfile_in_zip_read_info;
1395 return UNZ_PARAMERROR;
1397 pfile_in_zip_read_info=s->pfile_in_zip_read;
1399 if (pfile_in_zip_read_info==NULL)
1400 return UNZ_PARAMERROR;
1402 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1407 return 1 if the end of file was reached, 0 elsewhere
1409 extern int ZEXPORT unzeof (file)
1413 file_in_zip_read_info_s* pfile_in_zip_read_info;
1415 return UNZ_PARAMERROR;
1417 pfile_in_zip_read_info=s->pfile_in_zip_read;
1419 if (pfile_in_zip_read_info==NULL)
1420 return UNZ_PARAMERROR;
1422 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1431 Read extra field from the current file (opened by unzOpenCurrentFile)
1432 This is the local-header version of the extra field (sometimes, there is
1433 more info in the local-header version than in the central-header)
1435 if buf==NULL, it return the size of the local extra field that can be read
1437 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1439 the return value is the number of bytes copied in buf, or (if <0)
1442 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1448 file_in_zip_read_info_s* pfile_in_zip_read_info;
1453 return UNZ_PARAMERROR;
1455 pfile_in_zip_read_info=s->pfile_in_zip_read;
1457 if (pfile_in_zip_read_info==NULL)
1458 return UNZ_PARAMERROR;
1460 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1461 pfile_in_zip_read_info->pos_local_extrafield);
1464 return (int)size_to_read;
1466 if (len>size_to_read)
1467 read_now = (uInt)size_to_read;
1469 read_now = (uInt)len ;
1474 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1475 pfile_in_zip_read_info->filestream,
1476 pfile_in_zip_read_info->offset_local_extrafield +
1477 pfile_in_zip_read_info->pos_local_extrafield,
1478 ZLIB_FILEFUNC_SEEK_SET)!=0)
1481 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1482 pfile_in_zip_read_info->filestream,
1483 buf,read_now)!=read_now)
1486 return (int)read_now;
1490 Close the file in zip opened with unzipOpenCurrentFile
1491 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1493 extern int ZEXPORT unzCloseCurrentFile (file)
1499 file_in_zip_read_info_s* pfile_in_zip_read_info;
1501 return UNZ_PARAMERROR;
1503 pfile_in_zip_read_info=s->pfile_in_zip_read;
1505 if (pfile_in_zip_read_info==NULL)
1506 return UNZ_PARAMERROR;
1509 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1510 (!pfile_in_zip_read_info->raw))
1512 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1517 TRYFREE(pfile_in_zip_read_info->read_buffer);
1518 pfile_in_zip_read_info->read_buffer = NULL;
1519 if (pfile_in_zip_read_info->stream_initialised)
1520 inflateEnd(&pfile_in_zip_read_info->stream);
1522 pfile_in_zip_read_info->stream_initialised = 0;
1523 TRYFREE(pfile_in_zip_read_info);
1525 s->pfile_in_zip_read=NULL;
1532 Get the global comment string of the ZipFile, in the szComment buffer.
1533 uSizeBuf is the size of the szComment buffer.
1534 return the number of byte copied or an error code <0
1536 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1544 return UNZ_PARAMERROR;
1547 uReadThis = uSizeBuf;
1548 if (uReadThis>s->gi.size_comment)
1549 uReadThis = s->gi.size_comment;
1551 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1557 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1561 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1562 *(szComment+s->gi.size_comment)='\0';
1563 return (int)uReadThis;
1566 /* Additions by RX '2004 */
1567 extern uLong ZEXPORT unzGetOffset (file)
1573 return UNZ_PARAMERROR;
1575 if (!s->current_file_ok)
1577 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1578 if (s->num_file==s->gi.number_entry)
1580 return s->pos_in_central_dir;
1583 extern int ZEXPORT unzSetOffset (file, pos)
1591 return UNZ_PARAMERROR;
1594 s->pos_in_central_dir = pos;
1595 s->num_file = s->gi.number_entry; /* hack */
1596 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1597 &s->cur_file_info_internal,
1598 NULL,0,NULL,0,NULL,0);
1599 s->current_file_ok = (err == UNZ_OK);