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).
59 /* compile with -Dlocal if your debugger can't find static symbols */
62 #ifndef CASESENSITIVITYDEFAULT_NO
63 # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
64 # define CASESENSITIVITYDEFAULT_NO
70 #define UNZ_BUFSIZE (16384)
73 #ifndef UNZ_MAXFILENAMEINZIP
74 #define UNZ_MAXFILENAMEINZIP (256)
78 # define ALLOC(size) (malloc(size))
81 # define TRYFREE(p) {if (p) free(p);}
84 #define SIZECENTRALDIRITEM (0x2e)
85 #define SIZEZIPLOCALHEADER (0x1e)
90 const char unz_copyright[] =
91 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
93 /* unz_file_info_interntal contain internal info about a file in zipfile*/
94 typedef struct unz_file_info_internal_s
96 uLong offset_curfile;/* relative offset of local header 4 bytes */
97 } unz_file_info_internal;
100 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
101 when reading and decompress it */
104 char *read_buffer; /* internal buffer for compressed data */
105 z_stream stream; /* zLib stream structure for inflate */
107 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
108 uLong stream_initialised; /* flag set if stream structure is initialised*/
110 uLong offset_local_extrafield;/* offset of the local extra field */
111 uInt size_local_extrafield;/* size of the local extra field */
112 uLong pos_local_extrafield; /* position in the local extra field in read*/
114 uLong crc32; /* crc32 of all data uncompressed */
115 uLong crc32_wait; /* crc32 we must obtain after decompress all */
116 uLong rest_read_compressed; /* number of byte to be decompressed */
117 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
118 zlib_filefunc_def z_filefunc;
119 voidpf filestream; /* io structore of the zipfile */
120 uLong compression_method; /* compression method (0==store) */
121 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
123 } file_in_zip_read_info_s;
126 /* unz_s contain internal information about the zipfile
130 zlib_filefunc_def z_filefunc;
131 voidpf filestream; /* io structore of the zipfile */
132 unz_global_info gi; /* public global information */
133 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
134 uLong num_file; /* number of the current file in the zipfile*/
135 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
136 uLong current_file_ok; /* flag about the usability of the current file*/
137 uLong central_pos; /* position of the beginning of the central dir*/
139 uLong size_central_dir; /* size of the central directory */
140 uLong offset_central_dir; /* offset of start of central directory with
141 respect to the starting disk number */
143 unz_file_info cur_file_info; /* public info about the current file in zip*/
144 unz_file_info_internal cur_file_info_internal; /* private info about it*/
145 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
146 file if we are decompressing it */
149 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
150 const unsigned long* pcrc_32_tab;
159 /* ===========================================================================
160 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
162 IN assertion: the stream s has been sucessfully opened for reading.
166 local int unzlocal_getByte OF((
167 const zlib_filefunc_def* pzlib_filefunc_def,
171 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
172 const zlib_filefunc_def* pzlib_filefunc_def;
177 int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
185 if (ZERROR(*pzlib_filefunc_def,filestream))
193 /* ===========================================================================
194 Reads a long in LSB order from the given gz_stream. Sets
196 local int unzlocal_getShort OF((
197 const zlib_filefunc_def* pzlib_filefunc_def,
201 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
202 const zlib_filefunc_def* pzlib_filefunc_def;
210 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
214 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
224 local int unzlocal_getLong OF((
225 const zlib_filefunc_def* pzlib_filefunc_def,
229 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
230 const zlib_filefunc_def* pzlib_filefunc_def;
238 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
242 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
246 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
250 err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
261 /* My own strcmpi / strcasecmp */
262 local int strcmpcasenosensitive_internal (fileName1,fileName2)
263 const char* fileName1;
264 const char* fileName2;
268 char c1=*(fileName1++);
269 char c2=*(fileName2++);
270 if ((c1>='a') && (c1<='z'))
272 if ((c2>='a') && (c2<='z'))
275 return ((c2=='\0') ? 0 : -1);
286 #ifdef CASESENSITIVITYDEFAULT_NO
287 #define CASESENSITIVITYDEFAULTVALUE 2
289 #define CASESENSITIVITYDEFAULTVALUE 1
292 #ifndef STRCMPCASENOSENTIVEFUNCTION
293 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
297 Compare two filename (fileName1,fileName2).
298 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
299 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
301 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
302 (like 1 on Unix, 2 on Windows)
305 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
306 const char* fileName1;
307 const char* fileName2;
308 int iCaseSensitivity;
310 if (iCaseSensitivity==0)
311 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
313 if (iCaseSensitivity==1)
314 return strcmp(fileName1,fileName2);
316 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
319 #ifndef BUFREADCOMMENT
320 #define BUFREADCOMMENT (0x400)
324 Locate the Central directory of a zipfile (at the end, just before
327 local uLong unzlocal_SearchCentralDir OF((
328 const zlib_filefunc_def* pzlib_filefunc_def,
331 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
332 const zlib_filefunc_def* pzlib_filefunc_def;
338 uLong uMaxBack=0xffff; /* maximum size of global comment */
341 if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
345 uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
347 if (uMaxBack>uSizeFile)
348 uMaxBack = uSizeFile;
350 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
355 while (uBackRead<uMaxBack)
357 uLong uReadSize,uReadPos ;
359 if (uBackRead+BUFREADCOMMENT>uMaxBack)
360 uBackRead = uMaxBack;
362 uBackRead+=BUFREADCOMMENT;
363 uReadPos = uSizeFile-uBackRead ;
365 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
366 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
367 if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
370 if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
373 for (i=(int)uReadSize-3; (i--)>0;)
374 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
375 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
377 uPosFound = uReadPos+i;
389 Open a Zip file. path contain the full pathname (by example,
390 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
392 If the zipfile cannot be opened (file doesn't exist or in not valid), the
393 return value is NULL.
394 Else, the return value is a unzFile Handle, usable with other function
395 of this unzip package.
397 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
399 zlib_filefunc_def* pzlib_filefunc_def;
403 uLong central_pos,uL;
405 uLong number_disk; /* number of the current dist, used for
406 spaning ZIP, unsupported, always 0*/
407 uLong number_disk_with_CD; /* number the the disk with central dir, used
408 for spaning ZIP, unsupported, always 0*/
409 uLong number_entry_CD; /* total number of entries in
411 (same than number_entry on nospan) */
415 if (unz_copyright[0]!=' ')
418 if (pzlib_filefunc_def==NULL)
419 fill_fopen_filefunc(&us.z_filefunc);
421 us.z_filefunc = *pzlib_filefunc_def;
423 us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
425 ZLIB_FILEFUNC_MODE_READ |
426 ZLIB_FILEFUNC_MODE_EXISTING);
427 if (us.filestream==NULL)
430 central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
434 if (ZSEEK(us.z_filefunc, us.filestream,
435 central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
438 /* the signature, already checked */
439 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
442 /* number of this disk */
443 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
446 /* number of the disk with the start of the central directory */
447 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
450 /* total number of entries in the central dir on this disk */
451 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
454 /* total number of entries in the central dir */
455 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
458 if ((number_entry_CD!=us.gi.number_entry) ||
459 (number_disk_with_CD!=0) ||
463 /* size of the central directory */
464 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
467 /* offset of start of central directory with respect to the
468 starting disk number */
469 if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
472 /* zipfile comment length */
473 if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
476 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
482 ZCLOSE(us.z_filefunc, us.filestream);
486 us.byte_before_the_zipfile = central_pos -
487 (us.offset_central_dir+us.size_central_dir);
488 us.central_pos = central_pos;
489 us.pfile_in_zip_read = NULL;
493 s=(unz_s*)ALLOC(sizeof(unz_s));
495 unzGoToFirstFile((unzFile)s);
500 extern unzFile ZEXPORT unzOpen (path)
503 return unzOpen2(path, NULL);
507 Close a ZipFile opened with unzipOpen.
508 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
509 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
510 return UNZ_OK if there is no problem. */
511 extern int ZEXPORT unzClose (file)
516 return UNZ_PARAMERROR;
519 if (s->pfile_in_zip_read!=NULL)
520 unzCloseCurrentFile(file);
522 ZCLOSE(s->z_filefunc, s->filestream);
529 Write info about the ZipFile in the *pglobal_info structure.
530 No preparation of the structure is needed
531 return UNZ_OK if there is no problem. */
532 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
534 unz_global_info *pglobal_info;
538 return UNZ_PARAMERROR;
546 Translate date/time from Dos format to tm_unz (readable more easilty)
548 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
553 uDate = (uLong)(ulDosDate>>16);
554 ptm->tm_mday = (uInt)(uDate&0x1f) ;
555 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
556 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
558 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
559 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
560 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
564 Get Info about the current file in the zipfile, with internal only info
566 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
567 unz_file_info *pfile_info,
568 unz_file_info_internal
569 *pfile_info_internal,
571 uLong fileNameBufferSize,
573 uLong extraFieldBufferSize,
575 uLong commentBufferSize));
577 local int unzlocal_GetCurrentFileInfoInternal (file,
580 szFileName, fileNameBufferSize,
581 extraField, extraFieldBufferSize,
582 szComment, commentBufferSize)
584 unz_file_info *pfile_info;
585 unz_file_info_internal *pfile_info_internal;
587 uLong fileNameBufferSize;
589 uLong extraFieldBufferSize;
591 uLong commentBufferSize;
594 unz_file_info file_info;
595 unz_file_info_internal file_info_internal;
601 return UNZ_PARAMERROR;
603 if (ZSEEK(s->z_filefunc, s->filestream,
604 s->pos_in_central_dir+s->byte_before_the_zipfile,
605 ZLIB_FILEFUNC_SEEK_SET)!=0)
609 /* we check the magic */
611 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
613 else if (uMagic!=0x02014b50)
617 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
620 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
623 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
626 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
629 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
632 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
634 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
637 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
640 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
643 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
646 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
649 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
652 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
655 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
658 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
661 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
664 lSeek+=file_info.size_filename;
665 if ((err==UNZ_OK) && (szFileName!=NULL))
668 if (file_info.size_filename<fileNameBufferSize)
670 *(szFileName+file_info.size_filename)='\0';
671 uSizeRead = file_info.size_filename;
674 uSizeRead = fileNameBufferSize;
676 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
677 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
683 if ((err==UNZ_OK) && (extraField!=NULL))
686 if (file_info.size_file_extra<extraFieldBufferSize)
687 uSizeRead = file_info.size_file_extra;
689 uSizeRead = extraFieldBufferSize;
692 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
698 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
699 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
701 lSeek += file_info.size_file_extra - uSizeRead;
704 lSeek+=file_info.size_file_extra;
707 if ((err==UNZ_OK) && (szComment!=NULL))
710 if (file_info.size_file_comment<commentBufferSize)
712 *(szComment+file_info.size_file_comment)='\0';
713 uSizeRead = file_info.size_file_comment;
716 uSizeRead = commentBufferSize;
719 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
725 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
726 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
728 lSeek+=file_info.size_file_comment - uSizeRead;
731 lSeek+=file_info.size_file_comment;
733 if ((err==UNZ_OK) && (pfile_info!=NULL))
734 *pfile_info=file_info;
736 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
737 *pfile_info_internal=file_info_internal;
745 Write info about the ZipFile in the *pglobal_info structure.
746 No preparation of the structure is needed
747 return UNZ_OK if there is no problem.
749 extern int ZEXPORT unzGetCurrentFileInfo (file,
751 szFileName, fileNameBufferSize,
752 extraField, extraFieldBufferSize,
753 szComment, commentBufferSize)
755 unz_file_info *pfile_info;
757 uLong fileNameBufferSize;
759 uLong extraFieldBufferSize;
761 uLong commentBufferSize;
763 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
764 szFileName,fileNameBufferSize,
765 extraField,extraFieldBufferSize,
766 szComment,commentBufferSize);
770 Set the current file of the zipfile to the first file.
771 return UNZ_OK if there is no problem
773 extern int ZEXPORT unzGoToFirstFile (file)
779 return UNZ_PARAMERROR;
781 s->pos_in_central_dir=s->offset_central_dir;
783 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
784 &s->cur_file_info_internal,
785 NULL,0,NULL,0,NULL,0);
786 s->current_file_ok = (err == UNZ_OK);
791 Set the current file of the zipfile to the next file.
792 return UNZ_OK if there is no problem
793 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
795 extern int ZEXPORT unzGoToNextFile (file)
802 return UNZ_PARAMERROR;
804 if (!s->current_file_ok)
805 return UNZ_END_OF_LIST_OF_FILE;
806 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
807 if (s->num_file+1==s->gi.number_entry)
808 return UNZ_END_OF_LIST_OF_FILE;
810 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
811 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
813 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
814 &s->cur_file_info_internal,
815 NULL,0,NULL,0,NULL,0);
816 s->current_file_ok = (err == UNZ_OK);
822 Try locate the file szFileName in the zipfile.
823 For the iCaseSensitivity signification, see unzipStringFileNameCompare
826 UNZ_OK if the file is found. It becomes the current file.
827 UNZ_END_OF_LIST_OF_FILE if the file is not found
829 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
831 const char *szFileName;
832 int iCaseSensitivity;
837 /* We remember the 'current' position in the file so that we can jump
838 * back there if we fail.
840 unz_file_info cur_file_infoSaved;
841 unz_file_info_internal cur_file_info_internalSaved;
843 uLong pos_in_central_dirSaved;
847 return UNZ_PARAMERROR;
849 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
850 return UNZ_PARAMERROR;
853 if (!s->current_file_ok)
854 return UNZ_END_OF_LIST_OF_FILE;
856 /* Save the current state */
857 num_fileSaved = s->num_file;
858 pos_in_central_dirSaved = s->pos_in_central_dir;
859 cur_file_infoSaved = s->cur_file_info;
860 cur_file_info_internalSaved = s->cur_file_info_internal;
862 err = unzGoToFirstFile(file);
864 while (err == UNZ_OK)
866 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
867 err = unzGetCurrentFileInfo(file,NULL,
868 szCurrentFileName,sizeof(szCurrentFileName)-1,
872 if (unzStringFileNameCompare(szCurrentFileName,
873 szFileName,iCaseSensitivity)==0)
875 err = unzGoToNextFile(file);
879 /* We failed, so restore the state of the 'current file' to where we
882 s->num_file = num_fileSaved ;
883 s->pos_in_central_dir = pos_in_central_dirSaved ;
884 s->cur_file_info = cur_file_infoSaved;
885 s->cur_file_info_internal = cur_file_info_internalSaved;
891 ///////////////////////////////////////////
892 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
893 // I need random access
895 // Further optimization could be realized by adding an ability
896 // to cache the directory in memory. The goal being a single
897 // comprehensive file read to put the file I need in a memory.
901 typedef struct unz_file_pos_s
903 uLong pos_in_zip_directory; // offset in file
904 uLong num_of_file; // # of file
908 extern int ZEXPORT unzGetFilePos(file, file_pos)
910 unz_file_pos* file_pos;
914 if (file==NULL || file_pos==NULL)
915 return UNZ_PARAMERROR;
917 if (!s->current_file_ok)
918 return UNZ_END_OF_LIST_OF_FILE;
920 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
921 file_pos->num_of_file = s->num_file;
926 extern int ZEXPORT unzGoToFilePos(file, file_pos)
928 unz_file_pos* file_pos;
933 if (file==NULL || file_pos==NULL)
934 return UNZ_PARAMERROR;
937 /* jump to the right spot */
938 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
939 s->num_file = file_pos->num_of_file;
941 /* set the current file */
942 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
943 &s->cur_file_info_internal,
944 NULL,0,NULL,0,NULL,0);
946 s->current_file_ok = (err == UNZ_OK);
951 // Unzip Helper Functions - should be here?
952 ///////////////////////////////////////////
956 Read the local header of the current zipfile
957 Check the coherency of the local header and info in the end of central
958 directory about this file
959 store in *piSizeVar the size of extra info in local header
960 (filename and size of extra field data)
962 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
963 poffset_local_extrafield,
964 psize_local_extrafield)
967 uLong *poffset_local_extrafield;
968 uInt *psize_local_extrafield;
970 uLong uMagic,uData,uFlags;
972 uLong size_extra_field;
976 *poffset_local_extrafield = 0;
977 *psize_local_extrafield = 0;
979 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
980 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
985 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
987 else if (uMagic!=0x04034b50)
991 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
994 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
997 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1000 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1002 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1005 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1006 (s->cur_file_info.compression_method!=Z_DEFLATED))
1009 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1012 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1014 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1018 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1020 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1024 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1026 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1031 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1033 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1036 *piSizeVar += (uInt)size_filename;
1038 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1040 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1041 SIZEZIPLOCALHEADER + size_filename;
1042 *psize_local_extrafield = (uInt)size_extra_field;
1044 *piSizeVar += (uInt)size_extra_field;
1050 Open for reading data the current file in the zipfile.
1051 If there is no error and the file is opened, the return value is UNZ_OK.
1053 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1058 const char* password;
1063 file_in_zip_read_info_s* pfile_in_zip_read_info;
1064 uLong offset_local_extrafield; /* offset of the local extra field */
1065 uInt size_local_extrafield; /* size of the local extra field */
1069 if (password != NULL)
1070 return UNZ_PARAMERROR;
1074 return UNZ_PARAMERROR;
1076 if (!s->current_file_ok)
1077 return UNZ_PARAMERROR;
1079 if (s->pfile_in_zip_read != NULL)
1080 unzCloseCurrentFile(file);
1082 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1083 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1084 return UNZ_BADZIPFILE;
1086 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1087 ALLOC(sizeof(file_in_zip_read_info_s));
1088 if (pfile_in_zip_read_info==NULL)
1089 return UNZ_INTERNALERROR;
1091 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1092 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1093 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1094 pfile_in_zip_read_info->pos_local_extrafield=0;
1095 pfile_in_zip_read_info->raw=raw;
1097 if (pfile_in_zip_read_info->read_buffer==NULL)
1099 TRYFREE(pfile_in_zip_read_info);
1100 return UNZ_INTERNALERROR;
1103 pfile_in_zip_read_info->stream_initialised=0;
1106 *method = (int)s->cur_file_info.compression_method;
1111 switch (s->cur_file_info.flag & 0x06)
1113 case 6 : *level = 1; break;
1114 case 4 : *level = 2; break;
1115 case 2 : *level = 9; break;
1119 if ((s->cur_file_info.compression_method!=0) &&
1120 (s->cur_file_info.compression_method!=Z_DEFLATED))
1123 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1124 pfile_in_zip_read_info->crc32=0;
1125 pfile_in_zip_read_info->compression_method =
1126 s->cur_file_info.compression_method;
1127 pfile_in_zip_read_info->filestream=s->filestream;
1128 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1129 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1131 pfile_in_zip_read_info->stream.total_out = 0;
1133 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1136 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1137 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1138 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1139 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1140 pfile_in_zip_read_info->stream.avail_in = 0;
1142 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1144 pfile_in_zip_read_info->stream_initialised=1;
1147 TRYFREE(pfile_in_zip_read_info);
1150 /* windowBits is passed < 0 to tell that there is no zlib header.
1151 * Note that in this case inflate *requires* an extra "dummy" byte
1152 * after the compressed stream in order to complete decompression and
1153 * return Z_STREAM_END.
1154 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1155 * size of both compressed and uncompressed data
1158 pfile_in_zip_read_info->rest_read_compressed =
1159 s->cur_file_info.compressed_size ;
1160 pfile_in_zip_read_info->rest_read_uncompressed =
1161 s->cur_file_info.uncompressed_size ;
1164 pfile_in_zip_read_info->pos_in_zipfile =
1165 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1168 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1170 s->pfile_in_zip_read = pfile_in_zip_read_info;
1173 if (password != NULL)
1176 s->pcrc_32_tab = get_crc_table();
1177 init_keys(password,s->keys,s->pcrc_32_tab);
1178 if (ZSEEK(s->z_filefunc, s->filestream,
1179 s->pfile_in_zip_read->pos_in_zipfile +
1180 s->pfile_in_zip_read->byte_before_the_zipfile,
1182 return UNZ_INTERNALERROR;
1183 if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1184 return UNZ_INTERNALERROR;
1186 for (i = 0; i<12; i++)
1187 zdecode(s->keys,s->pcrc_32_tab,source[i]);
1189 s->pfile_in_zip_read->pos_in_zipfile+=12;
1198 extern int ZEXPORT unzOpenCurrentFile (file)
1201 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1204 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1206 const char* password;
1208 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1211 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1217 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1221 Read bytes from the current file.
1222 buf contain buffer where data must be copied
1223 len the size of buf.
1225 return the number of byte copied if somes bytes are copied
1226 return 0 if the end of file was reached
1227 return <0 with error code if there is an error
1228 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1230 extern int ZEXPORT unzReadCurrentFile (file, buf, len)
1238 file_in_zip_read_info_s* pfile_in_zip_read_info;
1240 return UNZ_PARAMERROR;
1242 pfile_in_zip_read_info=s->pfile_in_zip_read;
1244 if (pfile_in_zip_read_info==NULL)
1245 return UNZ_PARAMERROR;
1248 if ((pfile_in_zip_read_info->read_buffer == NULL))
1249 return UNZ_END_OF_LIST_OF_FILE;
1253 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1255 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1257 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1258 (!(pfile_in_zip_read_info->raw)))
1259 pfile_in_zip_read_info->stream.avail_out =
1260 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1262 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1263 pfile_in_zip_read_info->stream.avail_in) &&
1264 (pfile_in_zip_read_info->raw))
1265 pfile_in_zip_read_info->stream.avail_out =
1266 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1267 pfile_in_zip_read_info->stream.avail_in;
1269 while (pfile_in_zip_read_info->stream.avail_out>0)
1271 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1272 (pfile_in_zip_read_info->rest_read_compressed>0))
1274 uInt uReadThis = UNZ_BUFSIZE;
1275 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1276 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1279 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1280 pfile_in_zip_read_info->filestream,
1281 pfile_in_zip_read_info->pos_in_zipfile +
1282 pfile_in_zip_read_info->byte_before_the_zipfile,
1283 ZLIB_FILEFUNC_SEEK_SET)!=0)
1285 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1286 pfile_in_zip_read_info->filestream,
1287 pfile_in_zip_read_info->read_buffer,
1288 uReadThis)!=uReadThis)
1296 for(i=0;i<uReadThis;i++)
1297 pfile_in_zip_read_info->read_buffer[i] =
1298 zdecode(s->keys,s->pcrc_32_tab,
1299 pfile_in_zip_read_info->read_buffer[i]);
1304 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1306 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1308 pfile_in_zip_read_info->stream.next_in =
1309 (Bytef*)pfile_in_zip_read_info->read_buffer;
1310 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1313 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1317 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1318 (pfile_in_zip_read_info->rest_read_compressed == 0))
1319 return (iRead==0) ? UNZ_EOF : iRead;
1321 if (pfile_in_zip_read_info->stream.avail_out <
1322 pfile_in_zip_read_info->stream.avail_in)
1323 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1325 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1327 for (i=0;i<uDoCopy;i++)
1328 *(pfile_in_zip_read_info->stream.next_out+i) =
1329 *(pfile_in_zip_read_info->stream.next_in+i);
1331 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1332 pfile_in_zip_read_info->stream.next_out,
1334 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1335 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1336 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1337 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1338 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1339 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1344 uLong uTotalOutBefore,uTotalOutAfter;
1345 const Bytef *bufBefore;
1347 int flush=Z_SYNC_FLUSH;
1349 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1350 bufBefore = pfile_in_zip_read_info->stream.next_out;
1353 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1354 pfile_in_zip_read_info->stream.avail_out) &&
1355 (pfile_in_zip_read_info->rest_read_compressed == 0))
1358 err=inflate(&pfile_in_zip_read_info->stream,flush);
1360 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1363 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1364 uOutThis = uTotalOutAfter-uTotalOutBefore;
1366 pfile_in_zip_read_info->crc32 =
1367 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1370 pfile_in_zip_read_info->rest_read_uncompressed -=
1373 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1375 if (err==Z_STREAM_END)
1376 return (iRead==0) ? UNZ_EOF : iRead;
1389 Give the current position in uncompressed data
1391 extern z_off_t ZEXPORT unztell (file)
1395 file_in_zip_read_info_s* pfile_in_zip_read_info;
1397 return UNZ_PARAMERROR;
1399 pfile_in_zip_read_info=s->pfile_in_zip_read;
1401 if (pfile_in_zip_read_info==NULL)
1402 return UNZ_PARAMERROR;
1404 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1409 return 1 if the end of file was reached, 0 elsewhere
1411 extern int ZEXPORT unzeof (file)
1415 file_in_zip_read_info_s* pfile_in_zip_read_info;
1417 return UNZ_PARAMERROR;
1419 pfile_in_zip_read_info=s->pfile_in_zip_read;
1421 if (pfile_in_zip_read_info==NULL)
1422 return UNZ_PARAMERROR;
1424 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1433 Read extra field from the current file (opened by unzOpenCurrentFile)
1434 This is the local-header version of the extra field (sometimes, there is
1435 more info in the local-header version than in the central-header)
1437 if buf==NULL, it return the size of the local extra field that can be read
1439 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1441 the return value is the number of bytes copied in buf, or (if <0)
1444 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1450 file_in_zip_read_info_s* pfile_in_zip_read_info;
1455 return UNZ_PARAMERROR;
1457 pfile_in_zip_read_info=s->pfile_in_zip_read;
1459 if (pfile_in_zip_read_info==NULL)
1460 return UNZ_PARAMERROR;
1462 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1463 pfile_in_zip_read_info->pos_local_extrafield);
1466 return (int)size_to_read;
1468 if (len>size_to_read)
1469 read_now = (uInt)size_to_read;
1471 read_now = (uInt)len ;
1476 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1477 pfile_in_zip_read_info->filestream,
1478 pfile_in_zip_read_info->offset_local_extrafield +
1479 pfile_in_zip_read_info->pos_local_extrafield,
1480 ZLIB_FILEFUNC_SEEK_SET)!=0)
1483 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1484 pfile_in_zip_read_info->filestream,
1485 buf,read_now)!=read_now)
1488 return (int)read_now;
1492 Close the file in zip opened with unzipOpenCurrentFile
1493 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1495 extern int ZEXPORT unzCloseCurrentFile (file)
1501 file_in_zip_read_info_s* pfile_in_zip_read_info;
1503 return UNZ_PARAMERROR;
1505 pfile_in_zip_read_info=s->pfile_in_zip_read;
1507 if (pfile_in_zip_read_info==NULL)
1508 return UNZ_PARAMERROR;
1511 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1512 (!pfile_in_zip_read_info->raw))
1514 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1519 TRYFREE(pfile_in_zip_read_info->read_buffer);
1520 pfile_in_zip_read_info->read_buffer = NULL;
1521 if (pfile_in_zip_read_info->stream_initialised)
1522 inflateEnd(&pfile_in_zip_read_info->stream);
1524 pfile_in_zip_read_info->stream_initialised = 0;
1525 TRYFREE(pfile_in_zip_read_info);
1527 s->pfile_in_zip_read=NULL;
1534 Get the global comment string of the ZipFile, in the szComment buffer.
1535 uSizeBuf is the size of the szComment buffer.
1536 return the number of byte copied or an error code <0
1538 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1546 return UNZ_PARAMERROR;
1549 uReadThis = uSizeBuf;
1550 if (uReadThis>s->gi.size_comment)
1551 uReadThis = s->gi.size_comment;
1553 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1559 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1563 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1564 *(szComment+s->gi.size_comment)='\0';
1565 return (int)uReadThis;
1568 /* Additions by RX '2004 */
1569 extern uLong ZEXPORT unzGetOffset (file)
1575 return UNZ_PARAMERROR;
1577 if (!s->current_file_ok)
1579 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1580 if (s->num_file==s->gi.number_entry)
1582 return s->pos_in_central_dir;
1585 extern int ZEXPORT unzSetOffset (file, pos)
1593 return UNZ_PARAMERROR;
1596 s->pos_in_central_dir = pos;
1597 s->num_file = s->gi.number_entry; /* hack */
1598 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1599 &s->cur_file_info_internal,
1600 NULL,0,NULL,0,NULL,0);
1601 s->current_file_ok = (err == UNZ_OK);