]> git.lizzy.rs Git - zlib.git/blob - contrib/minizip/unzip.c
zlib 1.2.0.3
[zlib.git] / contrib / minizip / unzip.c
1 /* unzip.c -- IO for uncompress .zip files using zlib\r
2    Version 0.22, May 19th, 2003\r
3 \r
4    Copyright (C) 1998-2003 Gilles Vollant\r
5 \r
6    Read unzip.h for more info\r
7 */\r
8 \r
9 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of\r
10 compatibility with older software. The following is from the original crypt.c. Code\r
11 woven in by Terry Thorsen 1/2003.\r
12 */\r
13 /*\r
14   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\r
15 \r
16   See the accompanying file LICENSE, version 2000-Apr-09 or later\r
17   (the contents of which are also included in zip.h) for terms of use.\r
18   If, for some reason, all these files are missing, the Info-ZIP license\r
19   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\r
20 */\r
21 /*\r
22   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]\r
23 \r
24   The encryption/decryption parts of this source code (as opposed to the\r
25   non-echoing password parts) were originally written in Europe.  The\r
26   whole source package can be freely distributed, including from the USA.\r
27   (Prior to January 2000, re-export from the US was a violation of US law.)\r
28  */\r
29 \r
30 /*\r
31   This encryption code is a direct transcription of the algorithm from\r
32   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\r
33   file (appnote.txt) is distributed with the PKZIP program (even in the\r
34   version without encryption capabilities).\r
35  */\r
36 \r
37 \r
38 #include <stdio.h>\r
39 #include <stdlib.h>\r
40 #include <string.h>\r
41 #include "zlib.h"\r
42 #include "unzip.h"\r
43 \r
44 #ifdef STDC\r
45 #  include <stddef.h>\r
46 #  include <string.h>\r
47 #  include <stdlib.h>\r
48 #endif\r
49 #ifdef NO_ERRNO_H\r
50     extern int errno;\r
51 #else\r
52 #   include <errno.h>\r
53 #endif\r
54 \r
55 \r
56 #ifndef local\r
57 #  define local static\r
58 #endif\r
59 /* compile with -Dlocal if your debugger can't find static symbols */\r
60 \r
61 \r
62 \r
63 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \\r
64                       !defined(CASESENSITIVITYDEFAULT_NO)\r
65 #define CASESENSITIVITYDEFAULT_NO\r
66 #endif\r
67 \r
68 \r
69 #ifndef UNZ_BUFSIZE\r
70 #define UNZ_BUFSIZE (16384)\r
71 #endif\r
72 \r
73 #ifndef UNZ_MAXFILENAMEINZIP\r
74 #define UNZ_MAXFILENAMEINZIP (256)\r
75 #endif\r
76 \r
77 #ifndef ALLOC\r
78 # define ALLOC(size) (malloc(size))\r
79 #endif\r
80 #ifndef TRYFREE\r
81 # define TRYFREE(p) {if (p) free(p);}\r
82 #endif\r
83 \r
84 #define SIZECENTRALDIRITEM (0x2e)\r
85 #define SIZEZIPLOCALHEADER (0x1e)\r
86 \r
87 \r
88 \r
89 \r
90 const char unz_copyright[] =\r
91    " unzip 0.22 Copyright 1998-2003 Gilles Vollant - http://www.winimage.com/zLibDll";\r
92 \r
93 /* unz_file_info_interntal contain internal info about a file in zipfile*/\r
94 typedef struct unz_file_info_internal_s\r
95 {\r
96     uLong offset_curfile;/* relative offset of local header 4 bytes */\r
97 } unz_file_info_internal;\r
98 \r
99 \r
100 /* file_in_zip_read_info_s contain internal information about a file in zipfile,\r
101     when reading and decompress it */\r
102 typedef struct\r
103 {\r
104     char  *read_buffer;         /* internal buffer for compressed data */\r
105     z_stream stream;            /* zLib stream structure for inflate */\r
106 \r
107     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/\r
108     uLong stream_initialised;   /* flag set if stream structure is initialised*/\r
109 \r
110     uLong offset_local_extrafield;/* offset of the local extra field */\r
111     uInt  size_local_extrafield;/* size of the local extra field */\r
112     uLong pos_local_extrafield;   /* position in the local extra field in read*/\r
113 \r
114     uLong crc32;                /* crc32 of all data uncompressed */\r
115     uLong crc32_wait;           /* crc32 we must obtain after decompress all */\r
116     uLong rest_read_compressed; /* number of byte to be decompressed */\r
117     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/\r
118     zlib_filefunc_def z_filefunc;\r
119     voidpf filestream;        /* io structore of the zipfile */\r
120     uLong compression_method;   /* compression method (0==store) */\r
121     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r
122     int   raw;\r
123 } file_in_zip_read_info_s;\r
124 \r
125 \r
126 /* unz_s contain internal information about the zipfile\r
127 */\r
128 typedef struct\r
129 {\r
130     zlib_filefunc_def z_filefunc;\r
131     voidpf filestream;        /* io structore of the zipfile */\r
132     unz_global_info gi;       /* public global information */\r
133     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\r
134     uLong num_file;             /* number of the current file in the zipfile*/\r
135     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/\r
136     uLong current_file_ok;      /* flag about the usability of the current file*/\r
137     uLong central_pos;          /* position of the beginning of the central dir*/\r
138 \r
139     uLong size_central_dir;     /* size of the central directory  */\r
140     uLong offset_central_dir;   /* offset of start of central directory with\r
141                                    respect to the starting disk number */\r
142 \r
143     unz_file_info cur_file_info; /* public info about the current file in zip*/\r
144     unz_file_info_internal cur_file_info_internal; /* private info about it*/\r
145     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current\r
146                                         file if we are decompressing it */\r
147     int encrypted;\r
148     #ifndef NOUNCRYPT\r
149     unsigned long keys[3];     /* keys defining the pseudo-random sequence */\r
150     const unsigned long* pcrc_32_tab;\r
151     #endif\r
152 } unz_s;\r
153 \r
154 \r
155 #ifndef NOUNCRYPT\r
156 #include "crypt.h"\r
157 #endif\r
158 \r
159 /* ===========================================================================\r
160      Read a byte from a gz_stream; update next_in and avail_in. Return EOF\r
161    for end of file.\r
162    IN assertion: the stream s has been sucessfully opened for reading.\r
163 */\r
164 \r
165 \r
166 local int unzlocal_getByte OF((\r
167     const zlib_filefunc_def* pzlib_filefunc_def,\r
168     voidpf filestream,\r
169     int *pi));\r
170 \r
171 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)\r
172     const zlib_filefunc_def* pzlib_filefunc_def;\r
173     voidpf filestream;\r
174     int *pi;\r
175 {\r
176     unsigned char c;\r
177     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);\r
178     if (err==1)\r
179     {\r
180         *pi = (int)c;\r
181         return UNZ_OK;\r
182     }\r
183     else\r
184     {\r
185         if (ZERROR(*pzlib_filefunc_def,filestream))\r
186             return UNZ_ERRNO;\r
187         else\r
188             return UNZ_EOF;\r
189     }\r
190 }\r
191 \r
192 \r
193 /* ===========================================================================\r
194    Reads a long in LSB order from the given gz_stream. Sets\r
195 */\r
196 local int unzlocal_getShort OF((\r
197     const zlib_filefunc_def* pzlib_filefunc_def,\r
198     voidpf filestream,\r
199     uLong *pX));\r
200 \r
201 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)\r
202     const zlib_filefunc_def* pzlib_filefunc_def;\r
203     voidpf filestream;\r
204     uLong *pX;\r
205 {\r
206     uLong x ;\r
207     int i;\r
208     int err;\r
209 \r
210     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
211     x = (uLong)i;\r
212 \r
213     if (err==UNZ_OK)\r
214         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
215     x += ((uLong)i)<<8;\r
216 \r
217     if (err==UNZ_OK)\r
218         *pX = x;\r
219     else\r
220         *pX = 0;\r
221     return err;\r
222 }\r
223 \r
224 local int unzlocal_getLong OF((\r
225     const zlib_filefunc_def* pzlib_filefunc_def,\r
226     voidpf filestream,\r
227     uLong *pX));\r
228 \r
229 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)\r
230     const zlib_filefunc_def* pzlib_filefunc_def;\r
231     voidpf filestream;\r
232     uLong *pX;\r
233 {\r
234     uLong x ;\r
235     int i;\r
236     int err;\r
237 \r
238     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
239     x = (uLong)i;\r
240 \r
241     if (err==UNZ_OK)\r
242         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
243     x += ((uLong)i)<<8;\r
244 \r
245     if (err==UNZ_OK)\r
246         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
247     x += ((uLong)i)<<16;\r
248 \r
249     if (err==UNZ_OK)\r
250         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);\r
251     x += ((uLong)i)<<24;\r
252 \r
253     if (err==UNZ_OK)\r
254         *pX = x;\r
255     else\r
256         *pX = 0;\r
257     return err;\r
258 }\r
259 \r
260 \r
261 /* My own strcmpi / strcasecmp */\r
262 local int strcmpcasenosensitive_internal (fileName1,fileName2)\r
263     const char* fileName1;\r
264     const char* fileName2;\r
265 {\r
266     for (;;)\r
267     {\r
268         char c1=*(fileName1++);\r
269         char c2=*(fileName2++);\r
270         if ((c1>='a') && (c1<='z'))\r
271             c1 -= 0x20;\r
272         if ((c2>='a') && (c2<='z'))\r
273             c2 -= 0x20;\r
274         if (c1=='\0')\r
275             return ((c2=='\0') ? 0 : -1);\r
276         if (c2=='\0')\r
277             return 1;\r
278         if (c1<c2)\r
279             return -1;\r
280         if (c1>c2)\r
281             return 1;\r
282     }\r
283 }\r
284 \r
285 \r
286 #ifdef  CASESENSITIVITYDEFAULT_NO\r
287 #define CASESENSITIVITYDEFAULTVALUE 2\r
288 #else\r
289 #define CASESENSITIVITYDEFAULTVALUE 1\r
290 #endif\r
291 \r
292 #ifndef STRCMPCASENOSENTIVEFUNCTION\r
293 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal\r
294 #endif\r
295 \r
296 /*\r
297    Compare two filename (fileName1,fileName2).\r
298    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\r
299    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\r
300                                                                 or strcasecmp)\r
301    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\r
302         (like 1 on Unix, 2 on Windows)\r
303 \r
304 */\r
305 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)\r
306     const char* fileName1;\r
307     const char* fileName2;\r
308     int iCaseSensitivity;\r
309 {\r
310     if (iCaseSensitivity==0)\r
311         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;\r
312 \r
313     if (iCaseSensitivity==1)\r
314         return strcmp(fileName1,fileName2);\r
315 \r
316     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);\r
317 }\r
318 \r
319 #ifndef BUFREADCOMMENT\r
320 #define BUFREADCOMMENT (0x400)\r
321 #endif\r
322 \r
323 /*\r
324   Locate the Central directory of a zipfile (at the end, just before\r
325     the global comment)\r
326 */\r
327 local uLong unzlocal_SearchCentralDir OF((\r
328     const zlib_filefunc_def* pzlib_filefunc_def,\r
329     voidpf filestream));\r
330 \r
331 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)\r
332     const zlib_filefunc_def* pzlib_filefunc_def;\r
333     voidpf filestream;\r
334 {\r
335     unsigned char* buf;\r
336     uLong uSizeFile;\r
337     uLong uBackRead;\r
338     uLong uMaxBack=0xffff; /* maximum size of global comment */\r
339     uLong uPosFound=0;\r
340 \r
341     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\r
342         return 0;\r
343 \r
344 \r
345     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);\r
346 \r
347     if (uMaxBack>uSizeFile)\r
348         uMaxBack = uSizeFile;\r
349 \r
350     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\r
351     if (buf==NULL)\r
352         return 0;\r
353 \r
354     uBackRead = 4;\r
355     while (uBackRead<uMaxBack)\r
356     {\r
357         uLong uReadSize,uReadPos ;\r
358         int i;\r
359         if (uBackRead+BUFREADCOMMENT>uMaxBack)\r
360             uBackRead = uMaxBack;\r
361         else\r
362             uBackRead+=BUFREADCOMMENT;\r
363         uReadPos = uSizeFile-uBackRead ;\r
364 \r
365         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\r
366                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);\r
367         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
368             break;\r
369 \r
370         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\r
371             break;\r
372 \r
373         for (i=(int)uReadSize-3; (i--)>0;)\r
374             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\r
375                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\r
376             {\r
377                 uPosFound = uReadPos+i;\r
378                 break;\r
379             }\r
380 \r
381         if (uPosFound!=0)\r
382             break;\r
383     }\r
384     TRYFREE(buf);\r
385     return uPosFound;\r
386 }\r
387 \r
388 /*\r
389   Open a Zip file. path contain the full pathname (by example,\r
390      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer\r
391      "zlib/zlib114.zip".\r
392      If the zipfile cannot be opened (file doesn't exist or in not valid), the\r
393        return value is NULL.\r
394      Else, the return value is a unzFile Handle, usable with other function\r
395        of this unzip package.\r
396 */\r
397 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)\r
398     const char *path;\r
399     zlib_filefunc_def* pzlib_filefunc_def;\r
400 {\r
401     unz_s us;\r
402     unz_s *s;\r
403     uLong central_pos,uL;\r
404 \r
405     uLong number_disk;          /* number of the current dist, used for\r
406                                    spaning ZIP, unsupported, always 0*/\r
407     uLong number_disk_with_CD;  /* number the the disk with central dir, used\r
408                                    for spaning ZIP, unsupported, always 0*/\r
409     uLong number_entry_CD;      /* total number of entries in\r
410                                    the central dir\r
411                                    (same than number_entry on nospan) */\r
412 \r
413     int err=UNZ_OK;\r
414 \r
415     if (unz_copyright[0]!=' ')\r
416         return NULL;\r
417 \r
418     if (pzlib_filefunc_def==NULL)\r
419         fill_fopen_filefunc(&us.z_filefunc);\r
420     else\r
421         us.z_filefunc = *pzlib_filefunc_def;\r
422 \r
423     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,\r
424                                                  path,\r
425                                                  ZLIB_FILEFUNC_MODE_READ |\r
426                                                  ZLIB_FILEFUNC_MODE_EXISTING);\r
427     if (us.filestream==NULL)\r
428         return NULL;\r
429 \r
430     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);\r
431     if (central_pos==0)\r
432         err=UNZ_ERRNO;\r
433 \r
434     if (ZSEEK(us.z_filefunc, us.filestream,\r
435                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
436         err=UNZ_ERRNO;\r
437 \r
438     /* the signature, already checked */\r
439     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\r
440         err=UNZ_ERRNO;\r
441 \r
442     /* number of this disk */\r
443     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)\r
444         err=UNZ_ERRNO;\r
445 \r
446     /* number of the disk with the start of the central directory */\r
447     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)\r
448         err=UNZ_ERRNO;\r
449 \r
450     /* total number of entries in the central dir on this disk */\r
451     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)\r
452         err=UNZ_ERRNO;\r
453 \r
454     /* total number of entries in the central dir */\r
455     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)\r
456         err=UNZ_ERRNO;\r
457 \r
458     if ((number_entry_CD!=us.gi.number_entry) ||\r
459         (number_disk_with_CD!=0) ||\r
460         (number_disk!=0))\r
461         err=UNZ_BADZIPFILE;\r
462 \r
463     /* size of the central directory */\r
464     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)\r
465         err=UNZ_ERRNO;\r
466 \r
467     /* offset of start of central directory with respect to the\r
468           starting disk number */\r
469     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)\r
470         err=UNZ_ERRNO;\r
471 \r
472     /* zipfile comment length */\r
473     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)\r
474         err=UNZ_ERRNO;\r
475 \r
476     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&\r
477         (err==UNZ_OK))\r
478         err=UNZ_BADZIPFILE;\r
479 \r
480     if (err!=UNZ_OK)\r
481     {\r
482         ZCLOSE(us.z_filefunc, us.filestream);\r
483         return NULL;\r
484     }\r
485 \r
486     us.byte_before_the_zipfile = central_pos -\r
487                             (us.offset_central_dir+us.size_central_dir);\r
488     us.central_pos = central_pos;\r
489     us.pfile_in_zip_read = NULL;\r
490     us.encrypted = 0;\r
491 \r
492 \r
493     s=(unz_s*)ALLOC(sizeof(unz_s));\r
494     *s=us;\r
495     unzGoToFirstFile((unzFile)s);\r
496     return (unzFile)s;\r
497 }\r
498 \r
499 \r
500 extern unzFile ZEXPORT unzOpen (path)\r
501     const char *path;\r
502 {\r
503     return unzOpen2(path, NULL);\r
504 }\r
505 \r
506 /*\r
507   Close a ZipFile opened with unzipOpen.\r
508   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),\r
509     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\r
510   return UNZ_OK if there is no problem. */\r
511 extern int ZEXPORT unzClose (file)\r
512     unzFile file;\r
513 {\r
514     unz_s* s;\r
515     if (file==NULL)\r
516         return UNZ_PARAMERROR;\r
517     s=(unz_s*)file;\r
518 \r
519     if (s->pfile_in_zip_read!=NULL)\r
520         unzCloseCurrentFile(file);\r
521 \r
522     ZCLOSE(s->z_filefunc, s->filestream);\r
523     TRYFREE(s);\r
524     return UNZ_OK;\r
525 }\r
526 \r
527 \r
528 /*\r
529   Write info about the ZipFile in the *pglobal_info structure.\r
530   No preparation of the structure is needed\r
531   return UNZ_OK if there is no problem. */\r
532 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)\r
533     unzFile file;\r
534     unz_global_info *pglobal_info;\r
535 {\r
536     unz_s* s;\r
537     if (file==NULL)\r
538         return UNZ_PARAMERROR;\r
539     s=(unz_s*)file;\r
540     *pglobal_info=s->gi;\r
541     return UNZ_OK;\r
542 }\r
543 \r
544 \r
545 /*\r
546    Translate date/time from Dos format to tm_unz (readable more easilty)\r
547 */\r
548 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)\r
549     uLong ulDosDate;\r
550     tm_unz* ptm;\r
551 {\r
552     uLong uDate;\r
553     uDate = (uLong)(ulDosDate>>16);\r
554     ptm->tm_mday = (uInt)(uDate&0x1f) ;\r
555     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;\r
556     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;\r
557 \r
558     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);\r
559     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;\r
560     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;\r
561 }\r
562 \r
563 /*\r
564   Get Info about the current file in the zipfile, with internal only info\r
565 */\r
566 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,\r
567                                                   unz_file_info *pfile_info,\r
568                                                   unz_file_info_internal\r
569                                                   *pfile_info_internal,\r
570                                                   char *szFileName,\r
571                                                   uLong fileNameBufferSize,\r
572                                                   void *extraField,\r
573                                                   uLong extraFieldBufferSize,\r
574                                                   char *szComment,\r
575                                                   uLong commentBufferSize));\r
576 \r
577 local int unzlocal_GetCurrentFileInfoInternal (file,\r
578                                               pfile_info,\r
579                                               pfile_info_internal,\r
580                                               szFileName, fileNameBufferSize,\r
581                                               extraField, extraFieldBufferSize,\r
582                                               szComment,  commentBufferSize)\r
583     unzFile file;\r
584     unz_file_info *pfile_info;\r
585     unz_file_info_internal *pfile_info_internal;\r
586     char *szFileName;\r
587     uLong fileNameBufferSize;\r
588     void *extraField;\r
589     uLong extraFieldBufferSize;\r
590     char *szComment;\r
591     uLong commentBufferSize;\r
592 {\r
593     unz_s* s;\r
594     unz_file_info file_info;\r
595     unz_file_info_internal file_info_internal;\r
596     int err=UNZ_OK;\r
597     uLong uMagic;\r
598     long lSeek=0;\r
599 \r
600     if (file==NULL)\r
601         return UNZ_PARAMERROR;\r
602     s=(unz_s*)file;\r
603     if (ZSEEK(s->z_filefunc, s->filestream,\r
604               s->pos_in_central_dir+s->byte_before_the_zipfile,\r
605               ZLIB_FILEFUNC_SEEK_SET)!=0)\r
606         err=UNZ_ERRNO;\r
607 \r
608 \r
609     /* we check the magic */\r
610     if (err==UNZ_OK)\r
611         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
612             err=UNZ_ERRNO;\r
613         else if (uMagic!=0x02014b50)\r
614             err=UNZ_BADZIPFILE;\r
615 \r
616     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)\r
617         err=UNZ_ERRNO;\r
618 \r
619     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)\r
620         err=UNZ_ERRNO;\r
621 \r
622     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)\r
623         err=UNZ_ERRNO;\r
624 \r
625     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)\r
626         err=UNZ_ERRNO;\r
627 \r
628     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)\r
629         err=UNZ_ERRNO;\r
630 \r
631     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);\r
632 \r
633     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)\r
634         err=UNZ_ERRNO;\r
635 \r
636     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)\r
637         err=UNZ_ERRNO;\r
638 \r
639     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)\r
640         err=UNZ_ERRNO;\r
641 \r
642     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)\r
643         err=UNZ_ERRNO;\r
644 \r
645     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)\r
646         err=UNZ_ERRNO;\r
647 \r
648     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)\r
649         err=UNZ_ERRNO;\r
650 \r
651     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)\r
652         err=UNZ_ERRNO;\r
653 \r
654     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)\r
655         err=UNZ_ERRNO;\r
656 \r
657     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)\r
658         err=UNZ_ERRNO;\r
659 \r
660     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)\r
661         err=UNZ_ERRNO;\r
662 \r
663     lSeek+=file_info.size_filename;\r
664     if ((err==UNZ_OK) && (szFileName!=NULL))\r
665     {\r
666         uLong uSizeRead ;\r
667         if (file_info.size_filename<fileNameBufferSize)\r
668         {\r
669             *(szFileName+file_info.size_filename)='\0';\r
670             uSizeRead = file_info.size_filename;\r
671         }\r
672         else\r
673             uSizeRead = fileNameBufferSize;\r
674 \r
675         if ((file_info.size_filename>0) && (fileNameBufferSize>0))\r
676             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)\r
677                 err=UNZ_ERRNO;\r
678         lSeek -= uSizeRead;\r
679     }\r
680 \r
681 \r
682     if ((err==UNZ_OK) && (extraField!=NULL))\r
683     {\r
684         uLong uSizeRead ;\r
685         if (file_info.size_file_extra<extraFieldBufferSize)\r
686             uSizeRead = file_info.size_file_extra;\r
687         else\r
688             uSizeRead = extraFieldBufferSize;\r
689 \r
690         if (lSeek!=0)\r
691             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
692                 lSeek=0;\r
693             else\r
694                 err=UNZ_ERRNO;\r
695         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))\r
696             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)\r
697                 err=UNZ_ERRNO;\r
698         lSeek += file_info.size_file_extra - uSizeRead;\r
699     }\r
700     else\r
701         lSeek+=file_info.size_file_extra;\r
702 \r
703 \r
704     if ((err==UNZ_OK) && (szComment!=NULL))\r
705     {\r
706         uLong uSizeRead ;\r
707         if (file_info.size_file_comment<commentBufferSize)\r
708         {\r
709             *(szComment+file_info.size_file_comment)='\0';\r
710             uSizeRead = file_info.size_file_comment;\r
711         }\r
712         else\r
713             uSizeRead = commentBufferSize;\r
714 \r
715         if (lSeek!=0)\r
716             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
717                 lSeek=0;\r
718             else\r
719                 err=UNZ_ERRNO;\r
720         if ((file_info.size_file_comment>0) && (commentBufferSize>0))\r
721             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)\r
722                 err=UNZ_ERRNO;\r
723         lSeek+=file_info.size_file_comment - uSizeRead;\r
724     }\r
725     else\r
726         lSeek+=file_info.size_file_comment;\r
727 \r
728     if ((err==UNZ_OK) && (pfile_info!=NULL))\r
729         *pfile_info=file_info;\r
730 \r
731     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))\r
732         *pfile_info_internal=file_info_internal;\r
733 \r
734     return err;\r
735 }\r
736 \r
737 \r
738 \r
739 /*\r
740   Write info about the ZipFile in the *pglobal_info structure.\r
741   No preparation of the structure is needed\r
742   return UNZ_OK if there is no problem.\r
743 */\r
744 extern int ZEXPORT unzGetCurrentFileInfo (file,\r
745                                           pfile_info,\r
746                                           szFileName, fileNameBufferSize,\r
747                                           extraField, extraFieldBufferSize,\r
748                                           szComment,  commentBufferSize)\r
749     unzFile file;\r
750     unz_file_info *pfile_info;\r
751     char *szFileName;\r
752     uLong fileNameBufferSize;\r
753     void *extraField;\r
754     uLong extraFieldBufferSize;\r
755     char *szComment;\r
756     uLong commentBufferSize;\r
757 {\r
758     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,\r
759                                                 szFileName,fileNameBufferSize,\r
760                                                 extraField,extraFieldBufferSize,\r
761                                                 szComment,commentBufferSize);\r
762 }\r
763 \r
764 /*\r
765   Set the current file of the zipfile to the first file.\r
766   return UNZ_OK if there is no problem\r
767 */\r
768 extern int ZEXPORT unzGoToFirstFile (file)\r
769     unzFile file;\r
770 {\r
771     int err=UNZ_OK;\r
772     unz_s* s;\r
773     if (file==NULL)\r
774         return UNZ_PARAMERROR;\r
775     s=(unz_s*)file;\r
776     s->pos_in_central_dir=s->offset_central_dir;\r
777     s->num_file=0;\r
778     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
779                                              &s->cur_file_info_internal,\r
780                                              NULL,0,NULL,0,NULL,0);\r
781     s->current_file_ok = (err == UNZ_OK);\r
782     return err;\r
783 }\r
784 \r
785 /*\r
786   Set the current file of the zipfile to the next file.\r
787   return UNZ_OK if there is no problem\r
788   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\r
789 */\r
790 extern int ZEXPORT unzGoToNextFile (file)\r
791     unzFile file;\r
792 {\r
793     unz_s* s;\r
794     int err;\r
795 \r
796     if (file==NULL)\r
797         return UNZ_PARAMERROR;\r
798     s=(unz_s*)file;\r
799     if (!s->current_file_ok)\r
800         return UNZ_END_OF_LIST_OF_FILE;\r
801     if (s->num_file+1==s->gi.number_entry)\r
802         return UNZ_END_OF_LIST_OF_FILE;\r
803 \r
804     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +\r
805             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;\r
806     s->num_file++;\r
807     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
808                                                &s->cur_file_info_internal,\r
809                                                NULL,0,NULL,0,NULL,0);\r
810     s->current_file_ok = (err == UNZ_OK);\r
811     return err;\r
812 }\r
813 \r
814 \r
815 /*\r
816   Try locate the file szFileName in the zipfile.\r
817   For the iCaseSensitivity signification, see unzipStringFileNameCompare\r
818 \r
819   return value :\r
820   UNZ_OK if the file is found. It becomes the current file.\r
821   UNZ_END_OF_LIST_OF_FILE if the file is not found\r
822 */\r
823 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)\r
824     unzFile file;\r
825     const char *szFileName;\r
826     int iCaseSensitivity;\r
827 {\r
828     unz_s* s;\r
829     int err;\r
830 \r
831     /* We remember the 'current' position in the file so that we can jump\r
832      * back there if we fail.\r
833      */\r
834     unz_file_info cur_file_infoSaved;\r
835     unz_file_info_internal cur_file_info_internalSaved;\r
836     uLong num_fileSaved;\r
837     uLong pos_in_central_dirSaved;\r
838 \r
839 \r
840     if (file==NULL)\r
841         return UNZ_PARAMERROR;\r
842 \r
843     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)\r
844         return UNZ_PARAMERROR;\r
845 \r
846     s=(unz_s*)file;\r
847     if (!s->current_file_ok)\r
848         return UNZ_END_OF_LIST_OF_FILE;\r
849 \r
850     /* Save the current state */\r
851     num_fileSaved = s->num_file;\r
852     pos_in_central_dirSaved = s->pos_in_central_dir;\r
853     cur_file_infoSaved = s->cur_file_info;\r
854     cur_file_info_internalSaved = s->cur_file_info_internal;\r
855 \r
856     err = unzGoToFirstFile(file);\r
857 \r
858     while (err == UNZ_OK)\r
859     {\r
860         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];\r
861         err = unzGetCurrentFileInfo(file,NULL,\r
862                                     szCurrentFileName,sizeof(szCurrentFileName)-1,\r
863                                     NULL,0,NULL,0);\r
864         if (err == UNZ_OK)\r
865         {\r
866             if (unzStringFileNameCompare(szCurrentFileName,\r
867                                             szFileName,iCaseSensitivity)==0)\r
868                 return UNZ_OK;\r
869             err = unzGoToNextFile(file);\r
870         }\r
871     }\r
872 \r
873     /* We failed, so restore the state of the 'current file' to where we\r
874      * were.\r
875      */\r
876     s->num_file = num_fileSaved ;\r
877     s->pos_in_central_dir = pos_in_central_dirSaved ;\r
878     s->cur_file_info = cur_file_infoSaved;\r
879     s->cur_file_info_internal = cur_file_info_internalSaved;\r
880     return err;\r
881 }\r
882 \r
883 \r
884 /*\r
885 ///////////////////////////////////////////\r
886 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)\r
887 // I need random access\r
888 //\r
889 // Further optimization could be realized by adding an ability\r
890 // to cache the directory in memory. The goal being a single\r
891 // comprehensive file read to put the file I need in a memory.\r
892 */\r
893 \r
894 /*\r
895 typedef struct unz_file_pos_s\r
896 {\r
897     uLong pos_in_zip_directory;   // offset in file\r
898     uLong num_of_file;            // # of file\r
899 } unz_file_pos;\r
900 */\r
901 \r
902 extern int ZEXPORT unzGetFilePos(file, file_pos)\r
903     unzFile file;\r
904     unz_file_pos* file_pos;\r
905 {\r
906     unz_s* s;\r
907 \r
908     if (file==NULL || file_pos==NULL)\r
909         return UNZ_PARAMERROR;\r
910     s=(unz_s*)file;\r
911     if (!s->current_file_ok)\r
912         return UNZ_END_OF_LIST_OF_FILE;\r
913 \r
914     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;\r
915     file_pos->num_of_file           = s->num_file;\r
916 \r
917     return UNZ_OK;\r
918 }\r
919 \r
920 extern int ZEXPORT unzGoToFilePos(file, file_pos)\r
921     unzFile file;\r
922     unz_file_pos* file_pos;\r
923 {\r
924     unz_s* s;\r
925     int err;\r
926 \r
927     if (file==NULL || file_pos==NULL)\r
928         return UNZ_PARAMERROR;\r
929     s=(unz_s*)file;\r
930 \r
931     /* jump to the right spot */\r
932     s->pos_in_central_dir = file_pos->pos_in_zip_directory;\r
933     s->num_file           = file_pos->num_of_file;\r
934 \r
935     /* set the current file */\r
936     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
937                                                &s->cur_file_info_internal,\r
938                                                NULL,0,NULL,0,NULL,0);\r
939     /* return results */\r
940     s->current_file_ok = (err == UNZ_OK);\r
941     return err;\r
942 }\r
943 \r
944 /*\r
945 // Unzip Helper Functions - should be here?\r
946 ///////////////////////////////////////////\r
947 */\r
948 \r
949 /*\r
950   Read the local header of the current zipfile\r
951   Check the coherency of the local header and info in the end of central\r
952         directory about this file\r
953   store in *piSizeVar the size of extra info in local header\r
954         (filename and size of extra field data)\r
955 */\r
956 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,\r
957                                                     poffset_local_extrafield,\r
958                                                     psize_local_extrafield)\r
959     unz_s* s;\r
960     uInt* piSizeVar;\r
961     uLong *poffset_local_extrafield;\r
962     uInt  *psize_local_extrafield;\r
963 {\r
964     uLong uMagic,uData,uFlags;\r
965     uLong size_filename;\r
966     uLong size_extra_field;\r
967     int err=UNZ_OK;\r
968 \r
969     *piSizeVar = 0;\r
970     *poffset_local_extrafield = 0;\r
971     *psize_local_extrafield = 0;\r
972 \r
973     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +\r
974                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
975         return UNZ_ERRNO;\r
976 \r
977 \r
978     if (err==UNZ_OK)\r
979         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
980             err=UNZ_ERRNO;\r
981         else if (uMagic!=0x04034b50)\r
982             err=UNZ_BADZIPFILE;\r
983 \r
984     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
985         err=UNZ_ERRNO;\r
986 /*\r
987     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))\r
988         err=UNZ_BADZIPFILE;\r
989 */\r
990     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)\r
991         err=UNZ_ERRNO;\r
992 \r
993     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
994         err=UNZ_ERRNO;\r
995     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))\r
996         err=UNZ_BADZIPFILE;\r
997 \r
998     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&\r
999                          (s->cur_file_info.compression_method!=Z_DEFLATED))\r
1000         err=UNZ_BADZIPFILE;\r
1001 \r
1002     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */\r
1003         err=UNZ_ERRNO;\r
1004 \r
1005     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */\r
1006         err=UNZ_ERRNO;\r
1007     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&\r
1008                               ((uFlags & 8)==0))\r
1009         err=UNZ_BADZIPFILE;\r
1010 \r
1011     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */\r
1012         err=UNZ_ERRNO;\r
1013     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&\r
1014                               ((uFlags & 8)==0))\r
1015         err=UNZ_BADZIPFILE;\r
1016 \r
1017     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */\r
1018         err=UNZ_ERRNO;\r
1019     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&\r
1020                               ((uFlags & 8)==0))\r
1021         err=UNZ_BADZIPFILE;\r
1022 \r
1023 \r
1024     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)\r
1025         err=UNZ_ERRNO;\r
1026     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))\r
1027         err=UNZ_BADZIPFILE;\r
1028 \r
1029     *piSizeVar += (uInt)size_filename;\r
1030 \r
1031     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)\r
1032         err=UNZ_ERRNO;\r
1033     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +\r
1034                                     SIZEZIPLOCALHEADER + size_filename;\r
1035     *psize_local_extrafield = (uInt)size_extra_field;\r
1036 \r
1037     *piSizeVar += (uInt)size_extra_field;\r
1038 \r
1039     return err;\r
1040 }\r
1041 \r
1042 /*\r
1043   Open for reading data the current file in the zipfile.\r
1044   If there is no error and the file is opened, the return value is UNZ_OK.\r
1045 */\r
1046 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)\r
1047     unzFile file;\r
1048     int* method;\r
1049     int* level;\r
1050     int raw;\r
1051     const char* password;\r
1052 {\r
1053     int err=UNZ_OK;\r
1054     uInt iSizeVar;\r
1055     unz_s* s;\r
1056     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1057     uLong offset_local_extrafield;  /* offset of the local extra field */\r
1058     uInt  size_local_extrafield;    /* size of the local extra field */\r
1059     #ifndef NOUNCRYPT\r
1060     char source[12];\r
1061     #else\r
1062     if (password != NULL)\r
1063         return UNZ_PARAMERROR;\r
1064     #endif\r
1065 \r
1066     if (file==NULL)\r
1067         return UNZ_PARAMERROR;\r
1068     s=(unz_s*)file;\r
1069     if (!s->current_file_ok)\r
1070         return UNZ_PARAMERROR;\r
1071 \r
1072     if (s->pfile_in_zip_read != NULL)\r
1073         unzCloseCurrentFile(file);\r
1074 \r
1075     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,\r
1076                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)\r
1077         return UNZ_BADZIPFILE;\r
1078 \r
1079     pfile_in_zip_read_info = (file_in_zip_read_info_s*)\r
1080                                         ALLOC(sizeof(file_in_zip_read_info_s));\r
1081     if (pfile_in_zip_read_info==NULL)\r
1082         return UNZ_INTERNALERROR;\r
1083 \r
1084     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);\r
1085     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;\r
1086     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;\r
1087     pfile_in_zip_read_info->pos_local_extrafield=0;\r
1088     pfile_in_zip_read_info->raw=raw;\r
1089 \r
1090     if (pfile_in_zip_read_info->read_buffer==NULL)\r
1091     {\r
1092         TRYFREE(pfile_in_zip_read_info);\r
1093         return UNZ_INTERNALERROR;\r
1094     }\r
1095 \r
1096     pfile_in_zip_read_info->stream_initialised=0;\r
1097 \r
1098     if (method!=NULL)\r
1099         *method = (int)s->cur_file_info.compression_method;\r
1100 \r
1101     if (level!=NULL)\r
1102     {\r
1103         *level = 6;\r
1104         switch (s->cur_file_info.flag & 0x06)\r
1105         {\r
1106           case 6 : *level = 1; break;\r
1107           case 4 : *level = 2; break;\r
1108           case 2 : *level = 9; break;\r
1109         }\r
1110     }\r
1111 \r
1112     if ((s->cur_file_info.compression_method!=0) &&\r
1113         (s->cur_file_info.compression_method!=Z_DEFLATED))\r
1114         err=UNZ_BADZIPFILE;\r
1115 \r
1116     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;\r
1117     pfile_in_zip_read_info->crc32=0;\r
1118     pfile_in_zip_read_info->compression_method =\r
1119             s->cur_file_info.compression_method;\r
1120     pfile_in_zip_read_info->filestream=s->filestream;\r
1121     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;\r
1122     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;\r
1123 \r
1124     pfile_in_zip_read_info->stream.total_out = 0;\r
1125 \r
1126     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&\r
1127         (!raw))\r
1128     {\r
1129       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\r
1130       pfile_in_zip_read_info->stream.zfree = (free_func)0;\r
1131       pfile_in_zip_read_info->stream.opaque = (voidpf)0;\r
1132       pfile_in_zip_read_info->stream.next_in = (voidpf)0;\r
1133       pfile_in_zip_read_info->stream.avail_in = 0;\r
1134 \r
1135       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);\r
1136       if (err == Z_OK)\r
1137         pfile_in_zip_read_info->stream_initialised=1;\r
1138       else\r
1139         return err;\r
1140         /* windowBits is passed < 0 to tell that there is no zlib header.\r
1141          * Note that in this case inflate *requires* an extra "dummy" byte\r
1142          * after the compressed stream in order to complete decompression and\r
1143          * return Z_STREAM_END.\r
1144          * In unzip, i don't wait absolutely Z_STREAM_END because I known the\r
1145          * size of both compressed and uncompressed data\r
1146          */\r
1147     }\r
1148     pfile_in_zip_read_info->rest_read_compressed =\r
1149             s->cur_file_info.compressed_size ;\r
1150     pfile_in_zip_read_info->rest_read_uncompressed =\r
1151             s->cur_file_info.uncompressed_size ;\r
1152 \r
1153 \r
1154     pfile_in_zip_read_info->pos_in_zipfile =\r
1155             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +\r
1156               iSizeVar;\r
1157 \r
1158     pfile_in_zip_read_info->stream.avail_in = (uInt)0;\r
1159 \r
1160     s->pfile_in_zip_read = pfile_in_zip_read_info;\r
1161 \r
1162     #ifndef NOUNCRYPT\r
1163     if (password != NULL)\r
1164     {\r
1165         int i;\r
1166         s->pcrc_32_tab = get_crc_table();\r
1167         init_keys(password,s->keys,s->pcrc_32_tab);\r
1168         if (ZSEEK(s->z_filefunc, s->filestream,\r
1169                   s->pfile_in_zip_read->pos_in_zipfile +\r
1170                      s->pfile_in_zip_read->byte_before_the_zipfile,\r
1171                   SEEK_SET)!=0)\r
1172             return UNZ_INTERNALERROR;\r
1173         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)\r
1174             return UNZ_INTERNALERROR;\r
1175 \r
1176         for (i = 0; i<12; i++)\r
1177             zdecode(s->keys,s->pcrc_32_tab,source[i]);\r
1178 \r
1179         s->pfile_in_zip_read->pos_in_zipfile+=12;\r
1180         s->encrypted=1;\r
1181     }\r
1182     #endif\r
1183 \r
1184 \r
1185     return UNZ_OK;\r
1186 }\r
1187 \r
1188 extern int ZEXPORT unzOpenCurrentFile (file)\r
1189     unzFile file;\r
1190 {\r
1191     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);\r
1192 }\r
1193 \r
1194 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)\r
1195     unzFile file;\r
1196     const char* password;\r
1197 {\r
1198     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);\r
1199 }\r
1200 \r
1201 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)\r
1202     unzFile file;\r
1203     int* method;\r
1204     int* level;\r
1205     int raw;\r
1206 {\r
1207     return unzOpenCurrentFile3(file, method, level, raw, NULL);\r
1208 }\r
1209 \r
1210 /*\r
1211   Read bytes from the current file.\r
1212   buf contain buffer where data must be copied\r
1213   len the size of buf.\r
1214 \r
1215   return the number of byte copied if somes bytes are copied\r
1216   return 0 if the end of file was reached\r
1217   return <0 with error code if there is an error\r
1218     (UNZ_ERRNO for IO error, or zLib error for uncompress error)\r
1219 */\r
1220 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)\r
1221     unzFile file;\r
1222     voidp buf;\r
1223     unsigned len;\r
1224 {\r
1225     int err=UNZ_OK;\r
1226     uInt iRead = 0;\r
1227     unz_s* s;\r
1228     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1229     if (file==NULL)\r
1230         return UNZ_PARAMERROR;\r
1231     s=(unz_s*)file;\r
1232     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1233 \r
1234     if (pfile_in_zip_read_info==NULL)\r
1235         return UNZ_PARAMERROR;\r
1236 \r
1237 \r
1238     if ((pfile_in_zip_read_info->read_buffer == NULL))\r
1239         return UNZ_END_OF_LIST_OF_FILE;\r
1240     if (len==0)\r
1241         return 0;\r
1242 \r
1243     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;\r
1244 \r
1245     pfile_in_zip_read_info->stream.avail_out = (uInt)len;\r
1246 \r
1247     if (len>pfile_in_zip_read_info->rest_read_uncompressed)\r
1248         pfile_in_zip_read_info->stream.avail_out =\r
1249           (uInt)pfile_in_zip_read_info->rest_read_uncompressed;\r
1250 \r
1251     while (pfile_in_zip_read_info->stream.avail_out>0)\r
1252     {\r
1253         if ((pfile_in_zip_read_info->stream.avail_in==0) &&\r
1254             (pfile_in_zip_read_info->rest_read_compressed>0))\r
1255         {\r
1256             uInt uReadThis = UNZ_BUFSIZE;\r
1257             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)\r
1258                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;\r
1259             if (uReadThis == 0)\r
1260                 return UNZ_EOF;\r
1261             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
1262                       pfile_in_zip_read_info->filestream,\r
1263                       pfile_in_zip_read_info->pos_in_zipfile +\r
1264                          pfile_in_zip_read_info->byte_before_the_zipfile,\r
1265                          ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1266                 return UNZ_ERRNO;\r
1267             if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
1268                       pfile_in_zip_read_info->filestream,\r
1269                       pfile_in_zip_read_info->read_buffer,\r
1270                       uReadThis)!=uReadThis)\r
1271                 return UNZ_ERRNO;\r
1272 \r
1273 \r
1274             #ifndef NOUNCRYPT\r
1275             if(s->encrypted)\r
1276             {\r
1277                 uInt i;\r
1278                 for(i=0;i<uReadThis;i++)\r
1279                   pfile_in_zip_read_info->read_buffer[i] =\r
1280                       zdecode(s->keys,s->pcrc_32_tab,\r
1281                               pfile_in_zip_read_info->read_buffer[i]);\r
1282             }\r
1283             #endif\r
1284 \r
1285 \r
1286             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;\r
1287 \r
1288             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;\r
1289 \r
1290             pfile_in_zip_read_info->stream.next_in =\r
1291                 (Bytef*)pfile_in_zip_read_info->read_buffer;\r
1292             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;\r
1293         }\r
1294 \r
1295         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))\r
1296         {\r
1297             uInt uDoCopy,i ;\r
1298 \r
1299             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&\r
1300                 (pfile_in_zip_read_info->rest_read_compressed == 0))\r
1301                 return (iRead==0) ? UNZ_EOF : iRead;\r
1302 \r
1303             if (pfile_in_zip_read_info->stream.avail_out <\r
1304                             pfile_in_zip_read_info->stream.avail_in)\r
1305                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;\r
1306             else\r
1307                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;\r
1308 \r
1309             for (i=0;i<uDoCopy;i++)\r
1310                 *(pfile_in_zip_read_info->stream.next_out+i) =\r
1311                         *(pfile_in_zip_read_info->stream.next_in+i);\r
1312 \r
1313             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,\r
1314                                 pfile_in_zip_read_info->stream.next_out,\r
1315                                 uDoCopy);\r
1316             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;\r
1317             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;\r
1318             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;\r
1319             pfile_in_zip_read_info->stream.next_out += uDoCopy;\r
1320             pfile_in_zip_read_info->stream.next_in += uDoCopy;\r
1321             pfile_in_zip_read_info->stream.total_out += uDoCopy;\r
1322             iRead += uDoCopy;\r
1323         }\r
1324         else\r
1325         {\r
1326             uLong uTotalOutBefore,uTotalOutAfter;\r
1327             const Bytef *bufBefore;\r
1328             uLong uOutThis;\r
1329             int flush=Z_SYNC_FLUSH;\r
1330 \r
1331             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;\r
1332             bufBefore = pfile_in_zip_read_info->stream.next_out;\r
1333 \r
1334             /*\r
1335             if ((pfile_in_zip_read_info->rest_read_uncompressed ==\r
1336                      pfile_in_zip_read_info->stream.avail_out) &&\r
1337                 (pfile_in_zip_read_info->rest_read_compressed == 0))\r
1338                 flush = Z_FINISH;\r
1339             */\r
1340             err=inflate(&pfile_in_zip_read_info->stream,flush);\r
1341 \r
1342             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;\r
1343             uOutThis = uTotalOutAfter-uTotalOutBefore;\r
1344 \r
1345             pfile_in_zip_read_info->crc32 =\r
1346                 crc32(pfile_in_zip_read_info->crc32,bufBefore,\r
1347                         (uInt)(uOutThis));\r
1348 \r
1349             pfile_in_zip_read_info->rest_read_uncompressed -=\r
1350                 uOutThis;\r
1351 \r
1352             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\r
1353 \r
1354             if (err==Z_STREAM_END)\r
1355                 return (iRead==0) ? UNZ_EOF : iRead;\r
1356             if (err!=Z_OK)\r
1357                 break;\r
1358         }\r
1359     }\r
1360 \r
1361     if (err==Z_OK)\r
1362         return iRead;\r
1363     return err;\r
1364 }\r
1365 \r
1366 \r
1367 /*\r
1368   Give the current position in uncompressed data\r
1369 */\r
1370 extern z_off_t ZEXPORT unztell (file)\r
1371     unzFile file;\r
1372 {\r
1373     unz_s* s;\r
1374     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1375     if (file==NULL)\r
1376         return UNZ_PARAMERROR;\r
1377     s=(unz_s*)file;\r
1378     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1379 \r
1380     if (pfile_in_zip_read_info==NULL)\r
1381         return UNZ_PARAMERROR;\r
1382 \r
1383     return (z_off_t)pfile_in_zip_read_info->stream.total_out;\r
1384 }\r
1385 \r
1386 \r
1387 /*\r
1388   return 1 if the end of file was reached, 0 elsewhere\r
1389 */\r
1390 extern int ZEXPORT unzeof (file)\r
1391     unzFile file;\r
1392 {\r
1393     unz_s* s;\r
1394     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1395     if (file==NULL)\r
1396         return UNZ_PARAMERROR;\r
1397     s=(unz_s*)file;\r
1398     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1399 \r
1400     if (pfile_in_zip_read_info==NULL)\r
1401         return UNZ_PARAMERROR;\r
1402 \r
1403     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\r
1404         return 1;\r
1405     else\r
1406         return 0;\r
1407 }\r
1408 \r
1409 \r
1410 \r
1411 /*\r
1412   Read extra field from the current file (opened by unzOpenCurrentFile)\r
1413   This is the local-header version of the extra field (sometimes, there is\r
1414     more info in the local-header version than in the central-header)\r
1415 \r
1416   if buf==NULL, it return the size of the local extra field that can be read\r
1417 \r
1418   if buf!=NULL, len is the size of the buffer, the extra header is copied in\r
1419     buf.\r
1420   the return value is the number of bytes copied in buf, or (if <0)\r
1421     the error code\r
1422 */\r
1423 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)\r
1424     unzFile file;\r
1425     voidp buf;\r
1426     unsigned len;\r
1427 {\r
1428     unz_s* s;\r
1429     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1430     uInt read_now;\r
1431     uLong size_to_read;\r
1432 \r
1433     if (file==NULL)\r
1434         return UNZ_PARAMERROR;\r
1435     s=(unz_s*)file;\r
1436     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1437 \r
1438     if (pfile_in_zip_read_info==NULL)\r
1439         return UNZ_PARAMERROR;\r
1440 \r
1441     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -\r
1442                 pfile_in_zip_read_info->pos_local_extrafield);\r
1443 \r
1444     if (buf==NULL)\r
1445         return (int)size_to_read;\r
1446 \r
1447     if (len>size_to_read)\r
1448         read_now = (uInt)size_to_read;\r
1449     else\r
1450         read_now = (uInt)len ;\r
1451 \r
1452     if (read_now==0)\r
1453         return 0;\r
1454 \r
1455     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
1456               pfile_in_zip_read_info->filestream,\r
1457               pfile_in_zip_read_info->offset_local_extrafield +\r
1458               pfile_in_zip_read_info->pos_local_extrafield,\r
1459               ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1460         return UNZ_ERRNO;\r
1461 \r
1462     if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
1463               pfile_in_zip_read_info->filestream,\r
1464               buf,size_to_read)!=size_to_read)\r
1465         return UNZ_ERRNO;\r
1466 \r
1467     return (int)read_now;\r
1468 }\r
1469 \r
1470 /*\r
1471   Close the file in zip opened with unzipOpenCurrentFile\r
1472   Return UNZ_CRCERROR if all the file was read but the CRC is not good\r
1473 */\r
1474 extern int ZEXPORT unzCloseCurrentFile (file)\r
1475     unzFile file;\r
1476 {\r
1477     int err=UNZ_OK;\r
1478 \r
1479     unz_s* s;\r
1480     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1481     if (file==NULL)\r
1482         return UNZ_PARAMERROR;\r
1483     s=(unz_s*)file;\r
1484     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1485 \r
1486     if (pfile_in_zip_read_info==NULL)\r
1487         return UNZ_PARAMERROR;\r
1488 \r
1489 \r
1490     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&\r
1491         (!pfile_in_zip_read_info->raw))\r
1492     {\r
1493         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)\r
1494             err=UNZ_CRCERROR;\r
1495     }\r
1496 \r
1497 \r
1498     TRYFREE(pfile_in_zip_read_info->read_buffer);\r
1499     pfile_in_zip_read_info->read_buffer = NULL;\r
1500     if (pfile_in_zip_read_info->stream_initialised)\r
1501         inflateEnd(&pfile_in_zip_read_info->stream);\r
1502 \r
1503     pfile_in_zip_read_info->stream_initialised = 0;\r
1504     TRYFREE(pfile_in_zip_read_info);\r
1505 \r
1506     s->pfile_in_zip_read=NULL;\r
1507 \r
1508     return err;\r
1509 }\r
1510 \r
1511 \r
1512 /*\r
1513   Get the global comment string of the ZipFile, in the szComment buffer.\r
1514   uSizeBuf is the size of the szComment buffer.\r
1515   return the number of byte copied or an error code <0\r
1516 */\r
1517 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)\r
1518     unzFile file;\r
1519     char *szComment;\r
1520     uLong uSizeBuf;\r
1521 {\r
1522     int err=UNZ_OK;\r
1523     unz_s* s;\r
1524     uLong uReadThis ;\r
1525     if (file==NULL)\r
1526         return UNZ_PARAMERROR;\r
1527     s=(unz_s*)file;\r
1528 \r
1529     uReadThis = uSizeBuf;\r
1530     if (uReadThis>s->gi.size_comment)\r
1531         uReadThis = s->gi.size_comment;\r
1532 \r
1533     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1534         return UNZ_ERRNO;\r
1535 \r
1536     if (uReadThis>0)\r
1537     {\r
1538       *szComment='\0';\r
1539       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)\r
1540         return UNZ_ERRNO;\r
1541     }\r
1542 \r
1543     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))\r
1544         *(szComment+s->gi.size_comment)='\0';\r
1545     return (int)uReadThis;\r
1546 }\r