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(
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 (
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 (
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 (
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 (
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(
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 (
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 (
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 (
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 (
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 (
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 (
579 unz_file_info *pfile_info,
580 unz_file_info_internal *pfile_info_internal,
582 uLong fileNameBufferSize,
584 uLong extraFieldBufferSize,
586 uLong commentBufferSize)
589 unz_file_info file_info;
590 unz_file_info_internal file_info_internal;
596 return UNZ_PARAMERROR;
598 if (ZSEEK(s->z_filefunc, s->filestream,
599 s->pos_in_central_dir+s->byte_before_the_zipfile,
600 ZLIB_FILEFUNC_SEEK_SET)!=0)
604 /* we check the magic */
606 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
608 else if (uMagic!=0x02014b50)
612 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
615 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
618 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
621 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
624 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
627 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
629 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
632 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
635 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
638 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
641 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
644 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
647 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
650 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
653 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
656 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
659 lSeek+=file_info.size_filename;
660 if ((err==UNZ_OK) && (szFileName!=NULL))
663 if (file_info.size_filename<fileNameBufferSize)
665 *(szFileName+file_info.size_filename)='\0';
666 uSizeRead = file_info.size_filename;
669 uSizeRead = fileNameBufferSize;
671 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
672 if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
678 if ((err==UNZ_OK) && (extraField!=NULL))
681 if (file_info.size_file_extra<extraFieldBufferSize)
682 uSizeRead = file_info.size_file_extra;
684 uSizeRead = extraFieldBufferSize;
688 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
693 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
694 if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
696 lSeek += file_info.size_file_extra - uSizeRead;
699 lSeek+=file_info.size_file_extra;
702 if ((err==UNZ_OK) && (szComment!=NULL))
705 if (file_info.size_file_comment<commentBufferSize)
707 *(szComment+file_info.size_file_comment)='\0';
708 uSizeRead = file_info.size_file_comment;
711 uSizeRead = commentBufferSize;
714 if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
718 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
719 if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
721 lSeek+=file_info.size_file_comment - uSizeRead;
724 lSeek+=file_info.size_file_comment;
726 if ((err==UNZ_OK) && (pfile_info!=NULL))
727 *pfile_info=file_info;
729 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
730 *pfile_info_internal=file_info_internal;
738 Write info about the ZipFile in the *pglobal_info structure.
739 No preparation of the structure is needed
740 return UNZ_OK if there is no problem.
742 extern int ZEXPORT unzGetCurrentFileInfo (
744 unz_file_info *pfile_info,
746 uLong fileNameBufferSize,
748 uLong extraFieldBufferSize,
750 uLong commentBufferSize)
752 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
753 szFileName,fileNameBufferSize,
754 extraField,extraFieldBufferSize,
755 szComment,commentBufferSize);
759 Set the current file of the zipfile to the first file.
760 return UNZ_OK if there is no problem
762 extern int ZEXPORT unzGoToFirstFile (
768 return UNZ_PARAMERROR;
770 s->pos_in_central_dir=s->offset_central_dir;
772 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
773 &s->cur_file_info_internal,
774 NULL,0,NULL,0,NULL,0);
775 s->current_file_ok = (err == UNZ_OK);
780 Set the current file of the zipfile to the next file.
781 return UNZ_OK if there is no problem
782 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
784 extern int ZEXPORT unzGoToNextFile (
791 return UNZ_PARAMERROR;
793 if (!s->current_file_ok)
794 return UNZ_END_OF_LIST_OF_FILE;
795 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
796 if (s->num_file+1==s->gi.number_entry)
797 return UNZ_END_OF_LIST_OF_FILE;
799 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
800 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
802 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
803 &s->cur_file_info_internal,
804 NULL,0,NULL,0,NULL,0);
805 s->current_file_ok = (err == UNZ_OK);
811 Try locate the file szFileName in the zipfile.
812 For the iCaseSensitivity signification, see unzipStringFileNameCompare
815 UNZ_OK if the file is found. It becomes the current file.
816 UNZ_END_OF_LIST_OF_FILE if the file is not found
818 extern int ZEXPORT unzLocateFile (
820 const char *szFileName,
821 int iCaseSensitivity)
826 /* We remember the 'current' position in the file so that we can jump
827 * back there if we fail.
829 unz_file_info cur_file_infoSaved;
830 unz_file_info_internal cur_file_info_internalSaved;
832 uLong pos_in_central_dirSaved;
836 return UNZ_PARAMERROR;
838 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
839 return UNZ_PARAMERROR;
842 if (!s->current_file_ok)
843 return UNZ_END_OF_LIST_OF_FILE;
845 /* Save the current state */
846 num_fileSaved = s->num_file;
847 pos_in_central_dirSaved = s->pos_in_central_dir;
848 cur_file_infoSaved = s->cur_file_info;
849 cur_file_info_internalSaved = s->cur_file_info_internal;
851 err = unzGoToFirstFile(file);
853 while (err == UNZ_OK)
855 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
856 err = unzGetCurrentFileInfo(file,NULL,
857 szCurrentFileName,sizeof(szCurrentFileName)-1,
861 if (unzStringFileNameCompare(szCurrentFileName,
862 szFileName,iCaseSensitivity)==0)
864 err = unzGoToNextFile(file);
868 /* We failed, so restore the state of the 'current file' to where we
871 s->num_file = num_fileSaved ;
872 s->pos_in_central_dir = pos_in_central_dirSaved ;
873 s->cur_file_info = cur_file_infoSaved;
874 s->cur_file_info_internal = cur_file_info_internalSaved;
880 ///////////////////////////////////////////
881 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
882 // I need random access
884 // Further optimization could be realized by adding an ability
885 // to cache the directory in memory. The goal being a single
886 // comprehensive file read to put the file I need in a memory.
890 typedef struct unz_file_pos_s
892 uLong pos_in_zip_directory; // offset in file
893 uLong num_of_file; // # of file
897 extern int ZEXPORT unzGetFilePos(
899 unz_file_pos* file_pos)
903 if (file==NULL || file_pos==NULL)
904 return UNZ_PARAMERROR;
906 if (!s->current_file_ok)
907 return UNZ_END_OF_LIST_OF_FILE;
909 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
910 file_pos->num_of_file = s->num_file;
915 extern int ZEXPORT unzGoToFilePos(
917 unz_file_pos* file_pos)
922 if (file==NULL || file_pos==NULL)
923 return UNZ_PARAMERROR;
926 /* jump to the right spot */
927 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
928 s->num_file = file_pos->num_of_file;
930 /* set the current file */
931 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
932 &s->cur_file_info_internal,
933 NULL,0,NULL,0,NULL,0);
935 s->current_file_ok = (err == UNZ_OK);
940 // Unzip Helper Functions - should be here?
941 ///////////////////////////////////////////
945 Read the local header of the current zipfile
946 Check the coherency of the local header and info in the end of central
947 directory about this file
948 store in *piSizeVar the size of extra info in local header
949 (filename and size of extra field data)
951 local int unzlocal_CheckCurrentFileCoherencyHeader (
954 uLong *poffset_local_extrafield,
955 uInt *psize_local_extrafield)
957 uLong uMagic,uData,uFlags;
959 uLong size_extra_field;
963 *poffset_local_extrafield = 0;
964 *psize_local_extrafield = 0;
966 if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
967 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
972 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
974 else if (uMagic!=0x04034b50)
977 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
980 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
983 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
986 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
988 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
991 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
992 (s->cur_file_info.compression_method!=Z_DEFLATED))
995 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
998 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1000 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1004 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1006 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1010 if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1012 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1017 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1019 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1022 *piSizeVar += (uInt)size_filename;
1024 if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1026 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1027 SIZEZIPLOCALHEADER + size_filename;
1028 *psize_local_extrafield = (uInt)size_extra_field;
1030 *piSizeVar += (uInt)size_extra_field;
1036 Open for reading data the current file in the zipfile.
1037 If there is no error and the file is opened, the return value is UNZ_OK.
1039 extern int ZEXPORT unzOpenCurrentFile3 (
1044 const char* password)
1049 file_in_zip_read_info_s* pfile_in_zip_read_info;
1050 uLong offset_local_extrafield; /* offset of the local extra field */
1051 uInt size_local_extrafield; /* size of the local extra field */
1055 if (password != NULL)
1056 return UNZ_PARAMERROR;
1060 return UNZ_PARAMERROR;
1062 if (!s->current_file_ok)
1063 return UNZ_PARAMERROR;
1065 if (s->pfile_in_zip_read != NULL)
1066 unzCloseCurrentFile(file);
1068 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1069 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1070 return UNZ_BADZIPFILE;
1072 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1073 ALLOC(sizeof(file_in_zip_read_info_s));
1074 if (pfile_in_zip_read_info==NULL)
1075 return UNZ_INTERNALERROR;
1077 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1078 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1079 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1080 pfile_in_zip_read_info->pos_local_extrafield=0;
1081 pfile_in_zip_read_info->raw=raw;
1083 if (pfile_in_zip_read_info->read_buffer==NULL)
1085 TRYFREE(pfile_in_zip_read_info);
1086 return UNZ_INTERNALERROR;
1089 pfile_in_zip_read_info->stream_initialised=0;
1092 *method = (int)s->cur_file_info.compression_method;
1097 switch (s->cur_file_info.flag & 0x06)
1099 case 6 : *level = 1; break;
1100 case 4 : *level = 2; break;
1101 case 2 : *level = 9; break;
1105 if ((s->cur_file_info.compression_method!=0) &&
1106 (s->cur_file_info.compression_method!=Z_DEFLATED))
1109 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1110 pfile_in_zip_read_info->crc32=0;
1111 pfile_in_zip_read_info->compression_method =
1112 s->cur_file_info.compression_method;
1113 pfile_in_zip_read_info->filestream=s->filestream;
1114 pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1115 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1117 pfile_in_zip_read_info->stream.total_out = 0;
1119 if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1122 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1123 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1124 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1125 pfile_in_zip_read_info->stream.next_in = (Bytef*)0;
1126 pfile_in_zip_read_info->stream.avail_in = 0;
1128 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1130 pfile_in_zip_read_info->stream_initialised=1;
1133 TRYFREE(pfile_in_zip_read_info);
1136 /* windowBits is passed < 0 to tell that there is no zlib header.
1137 * Note that in this case inflate *requires* an extra "dummy" byte
1138 * after the compressed stream in order to complete decompression and
1139 * return Z_STREAM_END.
1140 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1141 * size of both compressed and uncompressed data
1144 pfile_in_zip_read_info->rest_read_compressed =
1145 s->cur_file_info.compressed_size ;
1146 pfile_in_zip_read_info->rest_read_uncompressed =
1147 s->cur_file_info.uncompressed_size ;
1150 pfile_in_zip_read_info->pos_in_zipfile =
1151 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1154 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1156 s->pfile_in_zip_read = pfile_in_zip_read_info;
1159 if (password != NULL)
1162 s->pcrc_32_tab = get_crc_table();
1163 init_keys(password,s->keys,s->pcrc_32_tab);
1164 if (ZSEEK(s->z_filefunc, s->filestream,
1165 s->pfile_in_zip_read->pos_in_zipfile +
1166 s->pfile_in_zip_read->byte_before_the_zipfile,
1168 return UNZ_INTERNALERROR;
1169 if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1170 return UNZ_INTERNALERROR;
1172 for (i = 0; i<12; i++)
1173 zdecode(s->keys,s->pcrc_32_tab,source[i]);
1175 s->pfile_in_zip_read->pos_in_zipfile+=12;
1184 extern int ZEXPORT unzOpenCurrentFile (
1187 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1190 extern int ZEXPORT unzOpenCurrentFilePassword (
1192 const char* password)
1194 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1197 extern int ZEXPORT unzOpenCurrentFile2 (
1203 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1207 Read bytes from the current file.
1208 buf contain buffer where data must be copied
1209 len the size of buf.
1211 return the number of byte copied if somes bytes are copied
1212 return 0 if the end of file was reached
1213 return <0 with error code if there is an error
1214 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1216 extern int ZEXPORT unzReadCurrentFile (
1224 file_in_zip_read_info_s* pfile_in_zip_read_info;
1226 return UNZ_PARAMERROR;
1228 pfile_in_zip_read_info=s->pfile_in_zip_read;
1230 if (pfile_in_zip_read_info==NULL)
1231 return UNZ_PARAMERROR;
1234 if ((pfile_in_zip_read_info->read_buffer == NULL))
1235 return UNZ_END_OF_LIST_OF_FILE;
1239 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1241 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1243 if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1244 (!(pfile_in_zip_read_info->raw)))
1245 pfile_in_zip_read_info->stream.avail_out =
1246 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1248 if ((len>pfile_in_zip_read_info->rest_read_compressed+
1249 pfile_in_zip_read_info->stream.avail_in) &&
1250 (pfile_in_zip_read_info->raw))
1251 pfile_in_zip_read_info->stream.avail_out =
1252 (uInt)pfile_in_zip_read_info->rest_read_compressed+
1253 pfile_in_zip_read_info->stream.avail_in;
1255 while (pfile_in_zip_read_info->stream.avail_out>0)
1257 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1258 (pfile_in_zip_read_info->rest_read_compressed>0))
1260 uInt uReadThis = UNZ_BUFSIZE;
1261 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1262 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1265 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1266 pfile_in_zip_read_info->filestream,
1267 pfile_in_zip_read_info->pos_in_zipfile +
1268 pfile_in_zip_read_info->byte_before_the_zipfile,
1269 ZLIB_FILEFUNC_SEEK_SET)!=0)
1271 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1272 pfile_in_zip_read_info->filestream,
1273 pfile_in_zip_read_info->read_buffer,
1274 uReadThis)!=uReadThis)
1282 for(i=0;i<uReadThis;i++)
1283 pfile_in_zip_read_info->read_buffer[i] =
1284 zdecode(s->keys,s->pcrc_32_tab,
1285 pfile_in_zip_read_info->read_buffer[i]);
1290 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1292 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1294 pfile_in_zip_read_info->stream.next_in =
1295 (Bytef*)pfile_in_zip_read_info->read_buffer;
1296 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1299 if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1303 if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1304 (pfile_in_zip_read_info->rest_read_compressed == 0))
1305 return (iRead==0) ? UNZ_EOF : iRead;
1307 if (pfile_in_zip_read_info->stream.avail_out <
1308 pfile_in_zip_read_info->stream.avail_in)
1309 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1311 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1313 for (i=0;i<uDoCopy;i++)
1314 *(pfile_in_zip_read_info->stream.next_out+i) =
1315 *(pfile_in_zip_read_info->stream.next_in+i);
1317 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1318 pfile_in_zip_read_info->stream.next_out,
1320 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1321 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1322 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1323 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1324 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1325 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1330 uLong uTotalOutBefore,uTotalOutAfter;
1331 const Bytef *bufBefore;
1333 int flush=Z_SYNC_FLUSH;
1335 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1336 bufBefore = pfile_in_zip_read_info->stream.next_out;
1339 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1340 pfile_in_zip_read_info->stream.avail_out) &&
1341 (pfile_in_zip_read_info->rest_read_compressed == 0))
1344 err=inflate(&pfile_in_zip_read_info->stream,flush);
1346 if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1349 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1350 uOutThis = uTotalOutAfter-uTotalOutBefore;
1352 pfile_in_zip_read_info->crc32 =
1353 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1356 pfile_in_zip_read_info->rest_read_uncompressed -=
1359 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1361 if (err==Z_STREAM_END)
1362 return (iRead==0) ? UNZ_EOF : iRead;
1375 Give the current position in uncompressed data
1377 extern z_off_t ZEXPORT unztell (
1381 file_in_zip_read_info_s* pfile_in_zip_read_info;
1383 return UNZ_PARAMERROR;
1385 pfile_in_zip_read_info=s->pfile_in_zip_read;
1387 if (pfile_in_zip_read_info==NULL)
1388 return UNZ_PARAMERROR;
1390 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1395 return 1 if the end of file was reached, 0 elsewhere
1397 extern int ZEXPORT unzeof (
1401 file_in_zip_read_info_s* pfile_in_zip_read_info;
1403 return UNZ_PARAMERROR;
1405 pfile_in_zip_read_info=s->pfile_in_zip_read;
1407 if (pfile_in_zip_read_info==NULL)
1408 return UNZ_PARAMERROR;
1410 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1419 Read extra field from the current file (opened by unzOpenCurrentFile)
1420 This is the local-header version of the extra field (sometimes, there is
1421 more info in the local-header version than in the central-header)
1423 if buf==NULL, it return the size of the local extra field that can be read
1425 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1427 the return value is the number of bytes copied in buf, or (if <0)
1430 extern int ZEXPORT unzGetLocalExtrafield (
1436 file_in_zip_read_info_s* pfile_in_zip_read_info;
1441 return UNZ_PARAMERROR;
1443 pfile_in_zip_read_info=s->pfile_in_zip_read;
1445 if (pfile_in_zip_read_info==NULL)
1446 return UNZ_PARAMERROR;
1448 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1449 pfile_in_zip_read_info->pos_local_extrafield);
1452 return (int)size_to_read;
1454 if (len>size_to_read)
1455 read_now = (uInt)size_to_read;
1457 read_now = (uInt)len ;
1462 if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1463 pfile_in_zip_read_info->filestream,
1464 pfile_in_zip_read_info->offset_local_extrafield +
1465 pfile_in_zip_read_info->pos_local_extrafield,
1466 ZLIB_FILEFUNC_SEEK_SET)!=0)
1469 if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1470 pfile_in_zip_read_info->filestream,
1471 buf,read_now)!=read_now)
1474 return (int)read_now;
1478 Close the file in zip opened with unzipOpenCurrentFile
1479 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1481 extern int ZEXPORT unzCloseCurrentFile (
1487 file_in_zip_read_info_s* pfile_in_zip_read_info;
1489 return UNZ_PARAMERROR;
1491 pfile_in_zip_read_info=s->pfile_in_zip_read;
1493 if (pfile_in_zip_read_info==NULL)
1494 return UNZ_PARAMERROR;
1497 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1498 (!pfile_in_zip_read_info->raw))
1500 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1505 TRYFREE(pfile_in_zip_read_info->read_buffer);
1506 pfile_in_zip_read_info->read_buffer = NULL;
1507 if (pfile_in_zip_read_info->stream_initialised)
1508 inflateEnd(&pfile_in_zip_read_info->stream);
1510 pfile_in_zip_read_info->stream_initialised = 0;
1511 TRYFREE(pfile_in_zip_read_info);
1513 s->pfile_in_zip_read=NULL;
1520 Get the global comment string of the ZipFile, in the szComment buffer.
1521 uSizeBuf is the size of the szComment buffer.
1522 return the number of byte copied or an error code <0
1524 extern int ZEXPORT unzGetGlobalComment (
1533 return UNZ_PARAMERROR;
1536 uReadThis = uSizeBuf;
1537 if (uReadThis>s->gi.size_comment)
1538 uReadThis = s->gi.size_comment;
1540 if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1546 if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1550 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1551 *(szComment+s->gi.size_comment)='\0';
1552 return (int)uReadThis;
1555 /* Additions by RX '2004 */
1556 extern uLong ZEXPORT unzGetOffset (
1562 return (uLong)UNZ_PARAMERROR;
1564 if (!s->current_file_ok)
1566 if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1567 if (s->num_file==s->gi.number_entry)
1569 return s->pos_in_central_dir;
1572 extern int ZEXPORT unzSetOffset (
1580 return UNZ_PARAMERROR;
1583 s->pos_in_central_dir = pos;
1584 s->num_file = s->gi.number_entry; /* hack */
1585 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1586 &s->cur_file_info_internal,
1587 NULL,0,NULL,0,NULL,0);
1588 s->current_file_ok = (err == UNZ_OK);