12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349 |
- /*****************************************************************************
- * name: unzip.c
- *
- * desc: IO on .zip files using portions of zlib
- *
- * $Archive: /StarTrek/Code-Single/qcommon/unzip.cpp $
- * $Author: osman $
- * $Revision: 1.19 $
- * $Modtime: 4/10/01 6:47p $
- * $Date: 2003/07/27 20:28:47 $
- *
- *****************************************************************************/
- #include "../client/client.h"
- #define ZIP_fopen fopen
- #define ZIP_fclose fclose
- #define ZIP_fseek fseek
- #define ZIP_fread fread
- #define ZIP_ftell ftell
- #include "../zlib32/zip.h"
- #include "unzip.h"
- /* unzip.h -- IO for uncompress .zip files using zlib
- Version 0.15 beta, Mar 19th, 1998,
- Copyright (C) 1998 Gilles Vollant
- This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
- WinZip, InfoZip tools and compatible.
- Encryption and multi volume ZipFile (span) are not supported.
- Old compressions used by old PKZip 1.x are not supported
- THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
- CAN CHANGE IN FUTURE VERSION !!
- I WAIT FEEDBACK at mail info@winimage.com
- Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
- Condition of use and distribution are the same than zlib :
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- /* Type declarations */
- #ifndef OF /* function prototypes */
- #define OF(args) args
- #endif
- typedef unsigned char Byte; /* 8 bits */
- typedef unsigned int uInt; /* 16 bits or more */
- typedef unsigned long uLong; /* 32 bits or more */
- typedef Byte *voidp;
- #ifndef SEEK_SET
- # define SEEK_SET 0 /* Seek from beginning of file. */
- # define SEEK_CUR 1 /* Seek from current position. */
- # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
- #endif
- typedef voidp gzFile;
- gzFile gzopen OF((const char *path, const char *mode));
- /*
- Opens a gzip (.gz) file for reading or writing. The mode parameter
- is as in fopen ("rb" or "wb") but can also include a compression level
- ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
- Huffman only compression as in "wb1h". (See the description
- of deflateInit2 for more information about the strategy parameter.)
- gzopen can be used to read a file which is not in gzip format; in this
- case gzread will directly read from the file without decompression.
- gzopen returns NULL if the file could not be opened or if there was
- insufficient memory to allocate the (de)compression state; errno
- can be checked to distinguish the two cases (if errno is zero, the
- zlib error is Z_MEM_ERROR). */
- gzFile gzdopen OF((int fd, const char *mode));
- /*
- gzdopen() associates a gzFile with the file descriptor fd. File
- descriptors are obtained from calls like open, dup, creat, pipe or
- fileno (in the file has been previously opened with fopen).
- The mode parameter is as in gzopen.
- The next call of gzclose on the returned gzFile will also close the
- file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
- descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
- gzdopen returns NULL if there was insufficient memory to allocate
- the (de)compression state.
- */
- int gzsetparams OF((gzFile file, int level, int strategy));
- /*
- Dynamically update the compression level or strategy. See the description
- of deflateInit2 for the meaning of these parameters.
- gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
- opened for writing.
- */
- int gzread OF((gzFile file, voidp buf, unsigned len));
- /*
- Reads the given number of uncompressed bytes from the compressed file.
- If the input file was not in gzip format, gzread copies the given number
- of bytes into the buffer.
- gzread returns the number of uncompressed bytes actually read (0 for
- end of file, -1 for error). */
- int gzwrite OF((gzFile file,
- const voidp buf, unsigned len));
- /*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes actually written
- (0 in case of error).
- */
- int QDECL gzprintf OF((gzFile file, const char *format, ...));
- /*
- Converts, formats, and writes the args to the compressed file under
- control of the format string, as in fprintf. gzprintf returns the number of
- uncompressed bytes actually written (0 in case of error).
- */
- int gzputs OF((gzFile file, const char *s));
- /*
- Writes the given null-terminated string to the compressed file, excluding
- the terminating null character.
- gzputs returns the number of characters written, or -1 in case of error.
- */
- char * gzgets OF((gzFile file, char *buf, int len));
- /*
- Reads bytes from the compressed file until len-1 characters are read, or
- a newline character is read and transferred to buf, or an end-of-file
- condition is encountered. The string is then terminated with a null
- character.
- gzgets returns buf, or Z_NULL in case of error.
- */
- int gzputc OF((gzFile file, int c));
- /*
- Writes c, converted to an unsigned char, into the compressed file.
- gzputc returns the value that was written, or -1 in case of error.
- */
- int gzgetc OF((gzFile file));
- /*
- Reads one byte from the compressed file. gzgetc returns this byte
- or -1 in case of end of file or error.
- */
- int gzflush OF((gzFile file, int flush));
- /*
- Flushes all pending output into the compressed file. The parameter
- flush is as in the deflate() function. The return value is the zlib
- error number (see function gzerror below). gzflush returns Z_OK if
- the flush parameter is Z_FINISH and all output could be flushed.
- gzflush should be called only when strictly necessary because it can
- degrade compression.
- */
- long gzseek OF((gzFile file,
- long offset, int whence));
- /*
- Sets the starting position for the next gzread or gzwrite on the
- given compressed file. The offset represents a number of bytes in the
- uncompressed data stream. The whence parameter is defined as in lseek(2);
- the value SEEK_END is not supported.
- If the file is opened for reading, this function is emulated but can be
- extremely slow. If the file is opened for writing, only forward seeks are
- supported; gzseek then compresses a sequence of zeroes up to the new
- starting position.
- gzseek returns the resulting offset location as measured in bytes from
- the beginning of the uncompressed stream, or -1 in case of error, in
- particular if the file is opened for writing and the new starting position
- would be before the current position.
- */
- int gzrewind OF((gzFile file));
- /*
- Rewinds the given file. This function is supported only for reading.
- gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
- */
- long gztell OF((gzFile file));
- /*
- Returns the starting position for the next gzread or gzwrite on the
- given compressed file. This position represents a number of bytes in the
- uncompressed data stream.
- gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
- */
- int gzeof OF((gzFile file));
- /*
- Returns 1 when EOF has previously been detected reading the given
- input stream, otherwise zero.
- */
- int gzclose OF((gzFile file));
- /*
- Flushes all pending output if necessary, closes the compressed file
- and deallocates all the (de)compression state. The return value is the zlib
- error number (see function gzerror below).
- */
- const char * gzerror OF((gzFile file, int *errnum));
- /*
- Returns the error message for the last error which occurred on the
- given compressed file. errnum is set to zlib error number. If an
- error occurred in the file system and not in the compression library,
- errnum is set to Z_ERRNO and the application may consult errno
- to get the exact error code.
- */
- #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
- !defined(CASESENSITIVITYDEFAULT_NO)
- #define CASESENSITIVITYDEFAULT_NO
- #endif
- #ifndef UNZ_BUFSIZE
- #define UNZ_BUFSIZE (65536)
- #endif
- #ifndef UNZ_MAXFILENAMEINZIP
- #define UNZ_MAXFILENAMEINZIP (256)
- #endif
- #ifndef ALLOC
- # define ALLOC(size) (UNZ_Malloc (size)) //Quake hookups
- #endif
- #ifndef TRYFREE
- # define TRYFREE(p) {if (p) Z_Free(p);}//Quake hookups
- #endif
- #define SIZECENTRALDIRITEM (0x2e)
- #define SIZEZIPLOCALHEADER (0x1e)
- static void *UNZ_Malloc( int size ) {
- void *buf;
-
- buf = Z_Malloc( size, TAG_FILESYS, qfalse);
- return buf;
- }
- /* ===========================================================================
- Reads a long in LSB order from the given gz_stream. Sets
- */
- static int unzlocal_getShort (ZIP_FILE* fin, uLong *pX)
- {
- short v;
- ZIP_fread( &v, sizeof(v), 1, fin );
- *pX = LittleShort( v);
- return UNZ_OK;
- }
- static int unzlocal_getLong (ZIP_FILE *fin, uLong *pX)
- {
- int v;
- ZIP_fread( &v, sizeof(v), 1, fin );
- *pX = LittleLong( v);
- return UNZ_OK;
- }
- /* My own strcmpi / strcasecmp */
- static int strcmpcasenosensitive_internal (const char* fileName1,const char* fileName2)
- {
- for (;;)
- {
- char c1=*(fileName1++);
- char c2=*(fileName2++);
- if ((c1>='a') && (c1<='z'))
- c1 -= 0x20;
- if ((c2>='a') && (c2<='z'))
- c2 -= 0x20;
- if (c1=='\0')
- return ((c2=='\0') ? 0 : -1);
- if (c2=='\0')
- return 1;
- if (c1<c2)
- return -1;
- if (c1>c2)
- return 1;
- }
- }
- #ifdef CASESENSITIVITYDEFAULT_NO
- #define CASESENSITIVITYDEFAULTVALUE 2
- #else
- #define CASESENSITIVITYDEFAULTVALUE 1
- #endif
- #ifndef STRCMPCASENOSENTIVEFUNCTION
- #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
- #endif
- /*
- Compare two filename (fileName1,fileName2).
- If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
- If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
- or strcasecmp)
- If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
- (like 1 on Unix, 2 on Windows)
- */
- extern int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity)
- {
- if (iCaseSensitivity==0)
- iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
- if (iCaseSensitivity==1)
- return strcmp(fileName1,fileName2);
- return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
- }
- #define BUFREADCOMMENT (0x400)
- /*
- Locate the Central directory of a zipfile (at the end, just before
- the global comment)
- */
- static uLong unzlocal_SearchCentralDir(ZIP_FILE *fin)
- {
- unsigned char* buf;
- uLong uSizeFile;
- uLong uBackRead;
- uLong uMaxBack=0xffff; /* maximum size of global comment */
- uLong uPosFound=0;
-
- if (ZIP_fseek(fin,0,SEEK_END) != 0)
- return 0;
- uSizeFile = ZIP_ftell( fin );
-
- if (uMaxBack>uSizeFile)
- uMaxBack = uSizeFile;
- buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
- uBackRead = 4;
- while (uBackRead<uMaxBack)
- {
- uLong uReadSize,uReadPos ;
- int i;
- if (uBackRead+BUFREADCOMMENT>uMaxBack)
- uBackRead = uMaxBack;
- else
- uBackRead+=BUFREADCOMMENT;
- uReadPos = uSizeFile-uBackRead ;
-
- uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
- (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
- if (ZIP_fseek(fin,uReadPos,SEEK_SET)!=0)
- break;
- if (ZIP_fread(buf,(uInt)uReadSize,1,fin)!=1)
- break;
- for (i=(int)uReadSize-3; (i--)>0;)
- if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
- ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
- {
- uPosFound = uReadPos+i;
- break;
- }
- if (uPosFound!=0)
- break;
- }
- TRYFREE(buf);
- return uPosFound;
- }
- extern unzFile unzReOpen (const char* path, unzFile file)
- {
- unz_s *s;
- ZIP_FILE * fin;
- fin=ZIP_fopen(path,"rb");
- if (fin==NULL)
- return NULL;
- s=(unz_s*)ALLOC(sizeof(unz_s));
- memcpy(s, (unz_s*)file, sizeof(unz_s));
- s->file = fin;
- return (unzFile)s;
- }
- /*
- Open a Zip file. path contain the full pathname (by example,
- on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
- "zlib/zlib109.zip".
- If the zipfile cannot be opened (file don't exist or in not valid), the
- return value is NULL.
- Else, the return value is a unzFile Handle, usable with other function
- of this unzip package.
- */
- extern unzFile unzOpen (const char* path)
- {
- unz_s us;
- unz_s *s;
- uLong central_pos,uL;
- ZIP_FILE * fin ;
- uLong number_disk; /* number of the current dist, used for
- spaning ZIP, unsupported, always 0*/
- uLong number_disk_with_CD; /* number the the disk with central dir, used
- for spaning ZIP, unsupported, always 0*/
- uLong number_entry_CD; /* total number of entries in
- the central dir
- (same than number_entry on nospan) */
- int err=UNZ_OK;
- fin=ZIP_fopen(path,"rb");
- if (fin==NULL)
- return NULL;
- central_pos = unzlocal_SearchCentralDir(fin);
- if (central_pos==0)
- err=UNZ_ERRNO;
- if (ZIP_fseek(fin,central_pos,SEEK_SET)!=0)
- err=UNZ_ERRNO;
- /* the signature, already checked */
- if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* number of this disk */
- if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* number of the disk with the start of the central directory */
- if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* total number of entries in the central dir on this disk */
- if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* total number of entries in the central dir */
- if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
- err=UNZ_ERRNO;
- if ((number_entry_CD!=us.gi.number_entry) ||
- (number_disk_with_CD!=0) ||
- (number_disk!=0))
- err=UNZ_BADZIPFILE;
- /* size of the central directory */
- if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* offset of start of central directory with respect to the
- starting disk number */
- if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
- err=UNZ_ERRNO;
- /* zipfile comment length */
- if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
- err=UNZ_ERRNO;
- if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
- (err==UNZ_OK))
- err=UNZ_BADZIPFILE;
- if (err!=UNZ_OK)
- {
- ZIP_fclose(fin);
- return NULL;
- }
- us.file=fin;
- us.byte_before_the_zipfile = central_pos -
- (us.offset_central_dir+us.size_central_dir);
- us.central_pos = central_pos;
- us.pfile_in_zip_read = NULL;
-
- s=(unz_s*)ALLOC(sizeof(unz_s));
- *s=us;
- // unzGoToFirstFile((unzFile)s);
- return (unzFile)s;
- }
- /*
- Close a ZipFile opened with unzipOpen.
- If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
- these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
- return UNZ_OK if there is no problem. */
- extern int unzClose (unzFile file)
- {
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (s->pfile_in_zip_read!=NULL)
- unzCloseCurrentFile(file);
- ZIP_fclose(s->file);
- TRYFREE(s);
- return UNZ_OK;
- }
- /*
- Write info about the ZipFile in the *pglobal_info structure.
- No preparation of the structure is needed
- return UNZ_OK if there is no problem. */
- extern int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
- {
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- *pglobal_info=s->gi;
- return UNZ_OK;
- }
- /*
- Translate date/time from Dos format to tm_unz (readable more easilty)
- */
- static void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
- {
- uLong uDate;
- uDate = (uLong)(ulDosDate>>16);
- ptm->tm_mday = (uInt)(uDate&0x1f) ;
- ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
- ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
- ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
- ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
- ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
- }
- /*
- Get Info about the current file in the zipfile, with internal only info
- */
- static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
- unz_file_info *pfile_info,
- unz_file_info_internal
- *pfile_info_internal,
- char *szFileName,
- uLong fileNameBufferSize,
- void *extraField,
- uLong extraFieldBufferSize,
- char *szComment,
- uLong commentBufferSize)
- {
- unz_s* s;
- unz_file_info file_info;
- unz_file_info_internal file_info_internal;
- int err=UNZ_OK;
- uLong uMagic;
- long lSeek=0;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (ZIP_fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
- err=UNZ_ERRNO;
- /* we check the magic */
- if (err==UNZ_OK)
- if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
- err=UNZ_ERRNO;
- else if (uMagic!=0x02014b50)
- err=UNZ_BADZIPFILE;
- if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
- err=UNZ_ERRNO;
- unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
- if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
- err=UNZ_ERRNO;
- lSeek+=file_info.size_filename;
- if ((err==UNZ_OK) && (szFileName!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_filename<fileNameBufferSize)
- {
- *(szFileName+file_info.size_filename)='\0';
- uSizeRead = file_info.size_filename;
- }
- else
- uSizeRead = fileNameBufferSize;
- if ((file_info.size_filename>0) && (fileNameBufferSize>0))
- if (ZIP_fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
- err=UNZ_ERRNO;
- lSeek -= uSizeRead;
- }
-
- if ((err==UNZ_OK) && (extraField!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_file_extra<extraFieldBufferSize)
- uSizeRead = file_info.size_file_extra;
- else
- uSizeRead = extraFieldBufferSize;
- if (lSeek!=0)
- if (ZIP_fseek(s->file,lSeek,SEEK_CUR)==0)
- lSeek=0;
- else
- err=UNZ_ERRNO;
- if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
- if (ZIP_fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
- err=UNZ_ERRNO;
- lSeek += file_info.size_file_extra - uSizeRead;
- }
- else
- lSeek+=file_info.size_file_extra;
-
- if ((err==UNZ_OK) && (szComment!=NULL))
- {
- uLong uSizeRead ;
- if (file_info.size_file_comment<commentBufferSize)
- {
- *(szComment+file_info.size_file_comment)='\0';
- uSizeRead = file_info.size_file_comment;
- }
- else
- uSizeRead = commentBufferSize;
- if (lSeek!=0)
- if (ZIP_fseek(s->file,lSeek,SEEK_CUR)==0)
- lSeek=0;
- else
- err=UNZ_ERRNO;
- if ((file_info.size_file_comment>0) && (commentBufferSize>0))
- if (ZIP_fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
- err=UNZ_ERRNO;
- lSeek+=file_info.size_file_comment - uSizeRead;
- }
- else
- lSeek+=file_info.size_file_comment;
- if ((err==UNZ_OK) && (pfile_info!=NULL))
- *pfile_info=file_info;
- if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
- *pfile_info_internal=file_info_internal;
- return err;
- }
- /*
- Write info about the ZipFile in the *pglobal_info structure.
- No preparation of the structure is needed
- return UNZ_OK if there is no problem.
- */
- extern int unzGetCurrentFileInfo ( unzFile file, unz_file_info *pfile_info,
- char *szFileName, uLong fileNameBufferSize,
- void *extraField, uLong extraFieldBufferSize,
- char *szComment, uLong commentBufferSize)
- {
- return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
- szFileName,fileNameBufferSize,
- extraField,extraFieldBufferSize,
- szComment,commentBufferSize);
- }
- /*
- Set the current file of the zipfile to the first file.
- return UNZ_OK if there is no problem
- */
- extern int unzGoToFirstFile (unzFile file)
- {
- int err=UNZ_OK;
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- s->pos_in_central_dir=s->offset_central_dir;
- s->num_file=0;
- err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
- &s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
- s->current_file_ok = (err == UNZ_OK);
- return err;
- }
- /*
- Set the current file of the zipfile to the next file.
- return UNZ_OK if there is no problem
- return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
- */
- extern int unzGoToNextFile (unzFile file)
- {
- unz_s* s;
- int err;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (!s->current_file_ok)
- return UNZ_END_OF_LIST_OF_FILE;
- if (s->num_file+1==s->gi.number_entry)
- return UNZ_END_OF_LIST_OF_FILE;
- s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
- s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
- s->num_file++;
- err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
- &s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
- s->current_file_ok = (err == UNZ_OK);
- return err;
- }
- /*
- Get the position of the info of the current file in the zip.
- return UNZ_OK if there is no problem
- */
- extern int unzGetCurrentFileInfoPosition (unzFile file, unsigned long *pos )
- {
- unz_s* s;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- *pos = s->pos_in_central_dir;
- return UNZ_OK;
- }
- /*
- Set the position of the info of the current file in the zip.
- return UNZ_OK if there is no problem
- */
- extern int unzSetCurrentFileInfoPosition (unzFile file, unsigned long pos )
- {
- unz_s* s;
- int err;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- s->pos_in_central_dir = pos;
- err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
- &s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
- s->current_file_ok = (err == UNZ_OK);
- return UNZ_OK;
- }
- /*
- Try locate the file szFileName in the zipfile.
- For the iCaseSensitivity signification, see unzipStringFileNameCompare
- return value :
- UNZ_OK if the file is found. It becomes the current file.
- UNZ_END_OF_LIST_OF_FILE if the file is not found
- */
- extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
- {
- unz_s* s;
- int err;
-
- uLong num_fileSaved;
- uLong pos_in_central_dirSaved;
- if (file==NULL)
- return UNZ_PARAMERROR;
- if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (!s->current_file_ok)
- return UNZ_END_OF_LIST_OF_FILE;
- num_fileSaved = s->num_file;
- pos_in_central_dirSaved = s->pos_in_central_dir;
- err = unzGoToFirstFile(file);
- while (err == UNZ_OK)
- {
- char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
- unzGetCurrentFileInfo(file,NULL,
- szCurrentFileName,sizeof(szCurrentFileName)-1,
- NULL,0,NULL,0);
- if (unzStringFileNameCompare(szCurrentFileName,
- szFileName,iCaseSensitivity)==0)
- return UNZ_OK;
- err = unzGoToNextFile(file);
- }
- s->num_file = num_fileSaved ;
- s->pos_in_central_dir = pos_in_central_dirSaved ;
- return err;
- }
- /*
- Read the static header of the current zipfile
- Check the coherency of the static header and info in the end of central
- directory about this file
- store in *piSizeVar the size of extra info in static header
- (filename and size of extra field data)
- */
- static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
- uLong *poffset_local_extrafield,
- uInt *psize_local_extrafield)
- {
- uLong uMagic,uData,uFlags;
- uLong size_filename;
- uLong size_extra_field;
- int err=UNZ_OK;
- *piSizeVar = 0;
- *poffset_local_extrafield = 0;
- *psize_local_extrafield = 0;
- if (ZIP_fseek(s->file,s->cur_file_info_internal.offset_curfile +
- s->byte_before_the_zipfile,SEEK_SET)!=0)
- return UNZ_ERRNO;
- if (err==UNZ_OK)
- if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
- err=UNZ_ERRNO;
- else if (uMagic!=0x04034b50)
- err=UNZ_BADZIPFILE;
- if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
- err=UNZ_ERRNO;
- /*
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
- err=UNZ_BADZIPFILE;
- */
- if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
- err=UNZ_ERRNO;
- if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
- err=UNZ_BADZIPFILE;
- if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
- (s->cur_file_info.compression_method!=ZF_DEFLATED))
- err=UNZ_BADZIPFILE;
- if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
- err=UNZ_ERRNO;
- if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
- if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
- if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
- ((uFlags & 8)==0))
- err=UNZ_BADZIPFILE;
- if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
- err=UNZ_ERRNO;
- else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
- err=UNZ_BADZIPFILE;
- *piSizeVar += (uInt)size_filename;
- if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
- err=UNZ_ERRNO;
- *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
- SIZEZIPLOCALHEADER + size_filename;
- *psize_local_extrafield = (uInt)size_extra_field;
- *piSizeVar += (uInt)size_extra_field;
- return err;
- }
-
- /*
- Open for reading data the current file in the zipfile.
- If there is no error and the file is opened, the return value is UNZ_OK.
- */
- extern int unzOpenCurrentFile (unzFile file)
- {
- int err=UNZ_OK;
- int Store;
- uInt iSizeVar;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- uLong offset_local_extrafield; /* offset of the static extra field */
- uInt size_local_extrafield; /* size of the static extra field */
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- if (!s->current_file_ok)
- return UNZ_PARAMERROR;
- if (s->pfile_in_zip_read != NULL)
- unzCloseCurrentFile(file);
- if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
- &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
- return UNZ_BADZIPFILE;
- pfile_in_zip_read_info = (file_in_zip_read_info_s*) ALLOC(sizeof(file_in_zip_read_info_s));
- pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
- pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
- pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
- pfile_in_zip_read_info->pos_local_extrafield=0;
- pfile_in_zip_read_info->stream_initialised=0;
-
- if ((s->cur_file_info.compression_method!=0) &&
- (s->cur_file_info.compression_method!=ZF_DEFLATED))
- err=UNZ_BADZIPFILE;
- Store = s->cur_file_info.compression_method==0;
- pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
- pfile_in_zip_read_info->crc32=0;
- pfile_in_zip_read_info->compression_method =
- s->cur_file_info.compression_method;
- pfile_in_zip_read_info->file=s->file;
- pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
- pfile_in_zip_read_info->stream.total_out = 0;
- if (!Store)
- {
- err=inflateInit(&pfile_in_zip_read_info->stream, Z_SYNC_FLUSH, 1);
- if (err == Z_OK)
- pfile_in_zip_read_info->stream_initialised=1;
- /* windowBits is passed < 0 to tell that there is no zlib header.
- * Note that in this case inflate *requires* an extra "dummy" byte
- * after the compressed stream in order to complete decompression and
- * return Z_STREAM_END.
- * In unzip, i don't wait absolutely Z_STREAM_END because I known the
- * size of both compressed and uncompressed data
- */
- }
- pfile_in_zip_read_info->rest_read_compressed =
- s->cur_file_info.compressed_size ;
- pfile_in_zip_read_info->rest_read_uncompressed =
- s->cur_file_info.uncompressed_size ;
-
- pfile_in_zip_read_info->pos_in_zipfile =
- s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
- iSizeVar;
-
- pfile_in_zip_read_info->stream.avail_in = (uInt)0;
- s->pfile_in_zip_read = pfile_in_zip_read_info;
- return UNZ_OK;
- }
- /*
- Read bytes from the current file.
- buf contain buffer where data must be copied
- len the size of buf.
- return the number of byte copied if somes bytes are copied
- return 0 if the end of file was reached
- return <0 with error code if there is an error
- (UNZ_ERRNO for IO error, or zLib error for uncompress error)
- */
- extern int unzReadCurrentFile (unzFile file, void *buf, unsigned len)
- {
- int err=UNZ_OK;
- uInt iRead = 0;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
- if ((pfile_in_zip_read_info->read_buffer == NULL))
- return UNZ_END_OF_LIST_OF_FILE;
- if (len==0)
- return 0;
- pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
- pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-
- if (len>pfile_in_zip_read_info->rest_read_uncompressed)
- pfile_in_zip_read_info->stream.avail_out =
- (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
- while (pfile_in_zip_read_info->stream.avail_out>0)
- {
- if ((pfile_in_zip_read_info->stream.avail_in==0) &&
- (pfile_in_zip_read_info->rest_read_compressed>0))
- {
- uInt uReadThis = UNZ_BUFSIZE;
- if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
- uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
- if (uReadThis == 0)
- return UNZ_EOF;
- if (s->cur_file_info.compressed_size == pfile_in_zip_read_info->rest_read_compressed)
- if (ZIP_fseek(pfile_in_zip_read_info->file,
- pfile_in_zip_read_info->pos_in_zipfile +
- pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
- return UNZ_ERRNO;
- if (ZIP_fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
- pfile_in_zip_read_info->file)!=1)
- return UNZ_ERRNO;
- pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
- pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-
- pfile_in_zip_read_info->stream.next_in =
- (Byte*)pfile_in_zip_read_info->read_buffer;
- pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
- }
- if (pfile_in_zip_read_info->compression_method==0)
- {
- uInt uDoCopy,i ;
- if (pfile_in_zip_read_info->stream.avail_out <
- pfile_in_zip_read_info->stream.avail_in)
- uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
- else
- uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
-
- for (i=0;i<uDoCopy;i++)
- *(pfile_in_zip_read_info->stream.next_out+i) =
- *(pfile_in_zip_read_info->stream.next_in+i);
-
- pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
- pfile_in_zip_read_info->stream.next_out,
- uDoCopy);
- pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
- pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
- pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
- pfile_in_zip_read_info->stream.next_out += uDoCopy;
- pfile_in_zip_read_info->stream.next_in += uDoCopy;
- pfile_in_zip_read_info->stream.total_out += uDoCopy;
- iRead += uDoCopy;
- }
- else
- {
- uLong uTotalOutBefore,uTotalOutAfter;
- const Byte *bufBefore;
- uLong uOutThis;
- uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
- bufBefore = pfile_in_zip_read_info->stream.next_out;
- /*
- if ((pfile_in_zip_read_info->rest_read_uncompressed ==
- pfile_in_zip_read_info->stream.avail_out) &&
- (pfile_in_zip_read_info->rest_read_compressed == 0))
- flush = Z_FINISH;
- */
- err=inflate(&pfile_in_zip_read_info->stream);
- uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
- uOutThis = uTotalOutAfter-uTotalOutBefore;
-
- pfile_in_zip_read_info->crc32 =
- crc32(pfile_in_zip_read_info->crc32,bufBefore,
- (uInt)(uOutThis));
- pfile_in_zip_read_info->rest_read_uncompressed -=
- uOutThis;
- iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-
- if (err==Z_STREAM_END)
- return (iRead==0) ? UNZ_EOF : iRead;
- if (err!=Z_OK)
- break;
- }
- }
- if (err==Z_OK)
- return iRead;
- return err;
- }
- /*
- Give the current position in uncompressed data
- */
- extern long unztell (unzFile file)
- {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
- return (long)pfile_in_zip_read_info->stream.total_out;
- }
- /*
- return 1 if the end of file was reached, 0 elsewhere
- */
- extern int unzeof (unzFile file)
- {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
-
- if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
- return 1;
- else
- return 0;
- }
- /*
- Read extra field from the current file (opened by unzOpenCurrentFile)
- This is the static-header version of the extra field (sometimes, there is
- more info in the static-header version than in the central-header)
- if buf==NULL, it return the size of the static extra field that can be read
- if buf!=NULL, len is the size of the buffer, the extra header is copied in
- buf.
- the return value is the number of bytes copied in buf, or (if <0)
- the error code
- */
- extern int unzGetLocalExtrafield (unzFile file,void *buf,unsigned len)
- {
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- uInt read_now;
- uLong size_to_read;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
- size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
- pfile_in_zip_read_info->pos_local_extrafield);
- if (buf==NULL)
- return (int)size_to_read;
-
- if (len>size_to_read)
- read_now = (uInt)size_to_read;
- else
- read_now = (uInt)len ;
- if (read_now==0)
- return 0;
-
- if (ZIP_fseek(pfile_in_zip_read_info->file,
- pfile_in_zip_read_info->offset_local_extrafield +
- pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
- return UNZ_ERRNO;
- if (ZIP_fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
- return UNZ_ERRNO;
- return (int)read_now;
- }
- /*
- Close the file in zip opened with unzipOpenCurrentFile
- Return UNZ_CRCERROR if all the file was read but the CRC is not good
- */
- extern int unzCloseCurrentFile (unzFile file)
- {
- int err=UNZ_OK;
- unz_s* s;
- file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
- return UNZ_PARAMERROR;
- if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
- {
- if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
- err=UNZ_CRCERROR;
- }
- TRYFREE(pfile_in_zip_read_info->read_buffer);
- pfile_in_zip_read_info->read_buffer = NULL;
- if (pfile_in_zip_read_info->stream_initialised)
- inflateEnd(&pfile_in_zip_read_info->stream);
- pfile_in_zip_read_info->stream_initialised = 0;
- TRYFREE(pfile_in_zip_read_info);
- s->pfile_in_zip_read=NULL;
- return err;
- }
- /*
- Get the global comment string of the ZipFile, in the szComment buffer.
- uSizeBuf is the size of the szComment buffer.
- return the number of byte copied or an error code <0
- */
- extern int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
- {
- unz_s* s;
- uLong uReadThis ;
- if (file==NULL)
- return UNZ_PARAMERROR;
- s=(unz_s*)file;
- uReadThis = uSizeBuf;
- if (uReadThis>s->gi.size_comment)
- uReadThis = s->gi.size_comment;
- if (ZIP_fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
- return UNZ_ERRNO;
- if (uReadThis>0)
- {
- *szComment='\0';
- if (ZIP_fread(szComment,(uInt)uReadThis,1,s->file)!=1)
- return UNZ_ERRNO;
- }
- if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
- *(szComment+s->gi.size_comment)='\0';
- return (int)uReadThis;
- }
- // end
|