]> git.sesse.net Git - vlc/blob - modules/gui/skins2/unzip/unzip.c
2a55e2bb5cca5408b4f1f31a7195e43478949481
[vlc] / modules / gui / skins2 / unzip / unzip.c
1 /* unzip.c -- IO for uncompress .zip files using zlib\r
2    Version 1.01e, February 12th, 2005\r
3 \r
4    Copyright (C) 1998-2005 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 #ifndef CASESENSITIVITYDEFAULT_NO\r
63 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)\r
64 #    define CASESENSITIVITYDEFAULT_NO\r
65 #  endif\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 1.01 Copyright 1998-2004 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 = 0;\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 = 0;\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     {\r
612         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
613             err=UNZ_ERRNO;\r
614         else if (uMagic!=0x02014b50)\r
615             err=UNZ_BADZIPFILE;\r
616     }\r
617 \r
618     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)\r
619         err=UNZ_ERRNO;\r
620 \r
621     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)\r
622         err=UNZ_ERRNO;\r
623 \r
624     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)\r
625         err=UNZ_ERRNO;\r
626 \r
627     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)\r
628         err=UNZ_ERRNO;\r
629 \r
630     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)\r
631         err=UNZ_ERRNO;\r
632 \r
633     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);\r
634 \r
635     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)\r
636         err=UNZ_ERRNO;\r
637 \r
638     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)\r
639         err=UNZ_ERRNO;\r
640 \r
641     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)\r
642         err=UNZ_ERRNO;\r
643 \r
644     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)\r
645         err=UNZ_ERRNO;\r
646 \r
647     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)\r
648         err=UNZ_ERRNO;\r
649 \r
650     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)\r
651         err=UNZ_ERRNO;\r
652 \r
653     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)\r
654         err=UNZ_ERRNO;\r
655 \r
656     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)\r
657         err=UNZ_ERRNO;\r
658 \r
659     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)\r
660         err=UNZ_ERRNO;\r
661 \r
662     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)\r
663         err=UNZ_ERRNO;\r
664 \r
665     lSeek+=file_info.size_filename;\r
666     if ((err==UNZ_OK) && (szFileName!=NULL))\r
667     {\r
668         uLong uSizeRead ;\r
669         if (file_info.size_filename<fileNameBufferSize)\r
670         {\r
671             *(szFileName+file_info.size_filename)='\0';\r
672             uSizeRead = file_info.size_filename;\r
673         }\r
674         else\r
675             uSizeRead = fileNameBufferSize;\r
676 \r
677         if ((file_info.size_filename>0) && (fileNameBufferSize>0))\r
678             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)\r
679                 err=UNZ_ERRNO;\r
680         lSeek -= uSizeRead;\r
681     }\r
682 \r
683 \r
684     if ((err==UNZ_OK) && (extraField!=NULL))\r
685     {\r
686         uLong uSizeRead ;\r
687         if (file_info.size_file_extra<extraFieldBufferSize)\r
688             uSizeRead = file_info.size_file_extra;\r
689         else\r
690             uSizeRead = extraFieldBufferSize;\r
691 \r
692         if (lSeek!=0)\r
693         {\r
694             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
695                 lSeek=0;\r
696             else\r
697                 err=UNZ_ERRNO;\r
698         }\r
699         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))\r
700             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)\r
701                 err=UNZ_ERRNO;\r
702         lSeek += file_info.size_file_extra - uSizeRead;\r
703     }\r
704     else\r
705         lSeek+=file_info.size_file_extra;\r
706 \r
707 \r
708     if ((err==UNZ_OK) && (szComment!=NULL))\r
709     {\r
710         uLong uSizeRead ;\r
711         if (file_info.size_file_comment<commentBufferSize)\r
712         {\r
713             *(szComment+file_info.size_file_comment)='\0';\r
714             uSizeRead = file_info.size_file_comment;\r
715         }\r
716         else\r
717             uSizeRead = commentBufferSize;\r
718 \r
719         if (lSeek!=0)\r
720         {\r
721             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\r
722                 lSeek=0;\r
723             else\r
724                 err=UNZ_ERRNO;\r
725         }\r
726         if ((file_info.size_file_comment>0) && (commentBufferSize>0))\r
727             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)\r
728                 err=UNZ_ERRNO;\r
729         lSeek+=file_info.size_file_comment - uSizeRead;\r
730     }\r
731     else\r
732         lSeek+=file_info.size_file_comment;\r
733 \r
734     if ((err==UNZ_OK) && (pfile_info!=NULL))\r
735         *pfile_info=file_info;\r
736 \r
737     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))\r
738         *pfile_info_internal=file_info_internal;\r
739 \r
740     return err;\r
741 }\r
742 \r
743 \r
744 \r
745 /*\r
746   Write info about the ZipFile in the *pglobal_info structure.\r
747   No preparation of the structure is needed\r
748   return UNZ_OK if there is no problem.\r
749 */\r
750 extern int ZEXPORT unzGetCurrentFileInfo (file,\r
751                                           pfile_info,\r
752                                           szFileName, fileNameBufferSize,\r
753                                           extraField, extraFieldBufferSize,\r
754                                           szComment,  commentBufferSize)\r
755     unzFile file;\r
756     unz_file_info *pfile_info;\r
757     char *szFileName;\r
758     uLong fileNameBufferSize;\r
759     void *extraField;\r
760     uLong extraFieldBufferSize;\r
761     char *szComment;\r
762     uLong commentBufferSize;\r
763 {\r
764     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,\r
765                                                 szFileName,fileNameBufferSize,\r
766                                                 extraField,extraFieldBufferSize,\r
767                                                 szComment,commentBufferSize);\r
768 }\r
769 \r
770 /*\r
771   Set the current file of the zipfile to the first file.\r
772   return UNZ_OK if there is no problem\r
773 */\r
774 extern int ZEXPORT unzGoToFirstFile (file)\r
775     unzFile file;\r
776 {\r
777     int err=UNZ_OK;\r
778     unz_s* s;\r
779     if (file==NULL)\r
780         return UNZ_PARAMERROR;\r
781     s=(unz_s*)file;\r
782     s->pos_in_central_dir=s->offset_central_dir;\r
783     s->num_file=0;\r
784     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
785                                              &s->cur_file_info_internal,\r
786                                              NULL,0,NULL,0,NULL,0);\r
787     s->current_file_ok = (err == UNZ_OK);\r
788     return err;\r
789 }\r
790 \r
791 /*\r
792   Set the current file of the zipfile to the next file.\r
793   return UNZ_OK if there is no problem\r
794   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\r
795 */\r
796 extern int ZEXPORT unzGoToNextFile (file)\r
797     unzFile file;\r
798 {\r
799     unz_s* s;\r
800     int err;\r
801 \r
802     if (file==NULL)\r
803         return UNZ_PARAMERROR;\r
804     s=(unz_s*)file;\r
805     if (!s->current_file_ok)\r
806         return UNZ_END_OF_LIST_OF_FILE;\r
807     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */\r
808       if (s->num_file+1==s->gi.number_entry)\r
809         return UNZ_END_OF_LIST_OF_FILE;\r
810 \r
811     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +\r
812             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;\r
813     s->num_file++;\r
814     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
815                                                &s->cur_file_info_internal,\r
816                                                NULL,0,NULL,0,NULL,0);\r
817     s->current_file_ok = (err == UNZ_OK);\r
818     return err;\r
819 }\r
820 \r
821 \r
822 /*\r
823   Try locate the file szFileName in the zipfile.\r
824   For the iCaseSensitivity signification, see unzipStringFileNameCompare\r
825 \r
826   return value :\r
827   UNZ_OK if the file is found. It becomes the current file.\r
828   UNZ_END_OF_LIST_OF_FILE if the file is not found\r
829 */\r
830 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)\r
831     unzFile file;\r
832     const char *szFileName;\r
833     int iCaseSensitivity;\r
834 {\r
835     unz_s* s;\r
836     int err;\r
837 \r
838     /* We remember the 'current' position in the file so that we can jump\r
839      * back there if we fail.\r
840      */\r
841     unz_file_info cur_file_infoSaved;\r
842     unz_file_info_internal cur_file_info_internalSaved;\r
843     uLong num_fileSaved;\r
844     uLong pos_in_central_dirSaved;\r
845 \r
846 \r
847     if (file==NULL)\r
848         return UNZ_PARAMERROR;\r
849 \r
850     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)\r
851         return UNZ_PARAMERROR;\r
852 \r
853     s=(unz_s*)file;\r
854     if (!s->current_file_ok)\r
855         return UNZ_END_OF_LIST_OF_FILE;\r
856 \r
857     /* Save the current state */\r
858     num_fileSaved = s->num_file;\r
859     pos_in_central_dirSaved = s->pos_in_central_dir;\r
860     cur_file_infoSaved = s->cur_file_info;\r
861     cur_file_info_internalSaved = s->cur_file_info_internal;\r
862 \r
863     err = unzGoToFirstFile(file);\r
864 \r
865     while (err == UNZ_OK)\r
866     {\r
867         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];\r
868         err = unzGetCurrentFileInfo(file,NULL,\r
869                                     szCurrentFileName,sizeof(szCurrentFileName)-1,\r
870                                     NULL,0,NULL,0);\r
871         if (err == UNZ_OK)\r
872         {\r
873             if (unzStringFileNameCompare(szCurrentFileName,\r
874                                             szFileName,iCaseSensitivity)==0)\r
875                 return UNZ_OK;\r
876             err = unzGoToNextFile(file);\r
877         }\r
878     }\r
879 \r
880     /* We failed, so restore the state of the 'current file' to where we\r
881      * were.\r
882      */\r
883     s->num_file = num_fileSaved ;\r
884     s->pos_in_central_dir = pos_in_central_dirSaved ;\r
885     s->cur_file_info = cur_file_infoSaved;\r
886     s->cur_file_info_internal = cur_file_info_internalSaved;\r
887     return err;\r
888 }\r
889 \r
890 \r
891 /*\r
892 ///////////////////////////////////////////\r
893 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)\r
894 // I need random access\r
895 //\r
896 // Further optimization could be realized by adding an ability\r
897 // to cache the directory in memory. The goal being a single\r
898 // comprehensive file read to put the file I need in a memory.\r
899 */\r
900 \r
901 /*\r
902 typedef struct unz_file_pos_s\r
903 {\r
904     uLong pos_in_zip_directory;   // offset in file\r
905     uLong num_of_file;            // # of file\r
906 } unz_file_pos;\r
907 */\r
908 \r
909 extern int ZEXPORT unzGetFilePos(file, file_pos)\r
910     unzFile file;\r
911     unz_file_pos* file_pos;\r
912 {\r
913     unz_s* s;\r
914 \r
915     if (file==NULL || file_pos==NULL)\r
916         return UNZ_PARAMERROR;\r
917     s=(unz_s*)file;\r
918     if (!s->current_file_ok)\r
919         return UNZ_END_OF_LIST_OF_FILE;\r
920 \r
921     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;\r
922     file_pos->num_of_file           = s->num_file;\r
923 \r
924     return UNZ_OK;\r
925 }\r
926 \r
927 extern int ZEXPORT unzGoToFilePos(file, file_pos)\r
928     unzFile file;\r
929     unz_file_pos* file_pos;\r
930 {\r
931     unz_s* s;\r
932     int err;\r
933 \r
934     if (file==NULL || file_pos==NULL)\r
935         return UNZ_PARAMERROR;\r
936     s=(unz_s*)file;\r
937 \r
938     /* jump to the right spot */\r
939     s->pos_in_central_dir = file_pos->pos_in_zip_directory;\r
940     s->num_file           = file_pos->num_of_file;\r
941 \r
942     /* set the current file */\r
943     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
944                                                &s->cur_file_info_internal,\r
945                                                NULL,0,NULL,0,NULL,0);\r
946     /* return results */\r
947     s->current_file_ok = (err == UNZ_OK);\r
948     return err;\r
949 }\r
950 \r
951 /*\r
952 // Unzip Helper Functions - should be here?\r
953 ///////////////////////////////////////////\r
954 */\r
955 \r
956 /*\r
957   Read the local header of the current zipfile\r
958   Check the coherency of the local header and info in the end of central\r
959         directory about this file\r
960   store in *piSizeVar the size of extra info in local header\r
961         (filename and size of extra field data)\r
962 */\r
963 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,\r
964                                                     poffset_local_extrafield,\r
965                                                     psize_local_extrafield)\r
966     unz_s* s;\r
967     uInt* piSizeVar;\r
968     uLong *poffset_local_extrafield;\r
969     uInt  *psize_local_extrafield;\r
970 {\r
971     uLong uMagic,uData,uFlags;\r
972     uLong size_filename;\r
973     uLong size_extra_field;\r
974     int err=UNZ_OK;\r
975 \r
976     *piSizeVar = 0;\r
977     *poffset_local_extrafield = 0;\r
978     *psize_local_extrafield = 0;\r
979 \r
980     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +\r
981                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
982         return UNZ_ERRNO;\r
983 \r
984 \r
985     if (err==UNZ_OK)\r
986     {\r
987         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\r
988             err=UNZ_ERRNO;\r
989         else if (uMagic!=0x04034b50)\r
990             err=UNZ_BADZIPFILE;\r
991     }\r
992     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
993         err=UNZ_ERRNO;\r
994 /*\r
995     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))\r
996         err=UNZ_BADZIPFILE;\r
997 */\r
998     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)\r
999         err=UNZ_ERRNO;\r
1000 \r
1001     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\r
1002         err=UNZ_ERRNO;\r
1003     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))\r
1004         err=UNZ_BADZIPFILE;\r
1005 \r
1006     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&\r
1007                          (s->cur_file_info.compression_method!=Z_DEFLATED))\r
1008         err=UNZ_BADZIPFILE;\r
1009 \r
1010     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */\r
1011         err=UNZ_ERRNO;\r
1012 \r
1013     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */\r
1014         err=UNZ_ERRNO;\r
1015     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&\r
1016                               ((uFlags & 8)==0))\r
1017         err=UNZ_BADZIPFILE;\r
1018 \r
1019     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */\r
1020         err=UNZ_ERRNO;\r
1021     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&\r
1022                               ((uFlags & 8)==0))\r
1023         err=UNZ_BADZIPFILE;\r
1024 \r
1025     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */\r
1026         err=UNZ_ERRNO;\r
1027     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&\r
1028                               ((uFlags & 8)==0))\r
1029         err=UNZ_BADZIPFILE;\r
1030 \r
1031 \r
1032     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)\r
1033         err=UNZ_ERRNO;\r
1034     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))\r
1035         err=UNZ_BADZIPFILE;\r
1036 \r
1037     *piSizeVar += (uInt)size_filename;\r
1038 \r
1039     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)\r
1040         err=UNZ_ERRNO;\r
1041     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +\r
1042                                     SIZEZIPLOCALHEADER + size_filename;\r
1043     *psize_local_extrafield = (uInt)size_extra_field;\r
1044 \r
1045     *piSizeVar += (uInt)size_extra_field;\r
1046 \r
1047     return err;\r
1048 }\r
1049 \r
1050 /*\r
1051   Open for reading data the current file in the zipfile.\r
1052   If there is no error and the file is opened, the return value is UNZ_OK.\r
1053 */\r
1054 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)\r
1055     unzFile file;\r
1056     int* method;\r
1057     int* level;\r
1058     int raw;\r
1059     const char* password;\r
1060 {\r
1061     int err=UNZ_OK;\r
1062     uInt iSizeVar;\r
1063     unz_s* s;\r
1064     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1065     uLong offset_local_extrafield;  /* offset of the local extra field */\r
1066     uInt  size_local_extrafield;    /* size of the local extra field */\r
1067 #    ifndef NOUNCRYPT\r
1068     char source[12];\r
1069 #    else\r
1070     if (password != NULL)\r
1071         return UNZ_PARAMERROR;\r
1072 #    endif\r
1073 \r
1074     if (file==NULL)\r
1075         return UNZ_PARAMERROR;\r
1076     s=(unz_s*)file;\r
1077     if (!s->current_file_ok)\r
1078         return UNZ_PARAMERROR;\r
1079 \r
1080     if (s->pfile_in_zip_read != NULL)\r
1081         unzCloseCurrentFile(file);\r
1082 \r
1083     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,\r
1084                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)\r
1085         return UNZ_BADZIPFILE;\r
1086 \r
1087     pfile_in_zip_read_info = (file_in_zip_read_info_s*)\r
1088                                         ALLOC(sizeof(file_in_zip_read_info_s));\r
1089     if (pfile_in_zip_read_info==NULL)\r
1090         return UNZ_INTERNALERROR;\r
1091 \r
1092     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);\r
1093     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;\r
1094     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;\r
1095     pfile_in_zip_read_info->pos_local_extrafield=0;\r
1096     pfile_in_zip_read_info->raw=raw;\r
1097 \r
1098     if (pfile_in_zip_read_info->read_buffer==NULL)\r
1099     {\r
1100         TRYFREE(pfile_in_zip_read_info);\r
1101         return UNZ_INTERNALERROR;\r
1102     }\r
1103 \r
1104     pfile_in_zip_read_info->stream_initialised=0;\r
1105 \r
1106     if (method!=NULL)\r
1107         *method = (int)s->cur_file_info.compression_method;\r
1108 \r
1109     if (level!=NULL)\r
1110     {\r
1111         *level = 6;\r
1112         switch (s->cur_file_info.flag & 0x06)\r
1113         {\r
1114           case 6 : *level = 1; break;\r
1115           case 4 : *level = 2; break;\r
1116           case 2 : *level = 9; break;\r
1117         }\r
1118     }\r
1119 \r
1120     if ((s->cur_file_info.compression_method!=0) &&\r
1121         (s->cur_file_info.compression_method!=Z_DEFLATED))\r
1122         err=UNZ_BADZIPFILE;\r
1123 \r
1124     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;\r
1125     pfile_in_zip_read_info->crc32=0;\r
1126     pfile_in_zip_read_info->compression_method =\r
1127             s->cur_file_info.compression_method;\r
1128     pfile_in_zip_read_info->filestream=s->filestream;\r
1129     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;\r
1130     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;\r
1131 \r
1132     pfile_in_zip_read_info->stream.total_out = 0;\r
1133 \r
1134     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&\r
1135         (!raw))\r
1136     {\r
1137       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\r
1138       pfile_in_zip_read_info->stream.zfree = (free_func)0;\r
1139       pfile_in_zip_read_info->stream.opaque = (voidpf)0;\r
1140       pfile_in_zip_read_info->stream.next_in = (voidpf)0;\r
1141       pfile_in_zip_read_info->stream.avail_in = 0;\r
1142 \r
1143       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);\r
1144       if (err == Z_OK)\r
1145         pfile_in_zip_read_info->stream_initialised=1;\r
1146       else\r
1147       {\r
1148         TRYFREE(pfile_in_zip_read_info);\r
1149         return err;\r
1150       }\r
1151         /* windowBits is passed < 0 to tell that there is no zlib header.\r
1152          * Note that in this case inflate *requires* an extra "dummy" byte\r
1153          * after the compressed stream in order to complete decompression and\r
1154          * return Z_STREAM_END.\r
1155          * In unzip, i don't wait absolutely Z_STREAM_END because I known the\r
1156          * size of both compressed and uncompressed data\r
1157          */\r
1158     }\r
1159     pfile_in_zip_read_info->rest_read_compressed =\r
1160             s->cur_file_info.compressed_size ;\r
1161     pfile_in_zip_read_info->rest_read_uncompressed =\r
1162             s->cur_file_info.uncompressed_size ;\r
1163 \r
1164 \r
1165     pfile_in_zip_read_info->pos_in_zipfile =\r
1166             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +\r
1167               iSizeVar;\r
1168 \r
1169     pfile_in_zip_read_info->stream.avail_in = (uInt)0;\r
1170 \r
1171     s->pfile_in_zip_read = pfile_in_zip_read_info;\r
1172 \r
1173 #    ifndef NOUNCRYPT\r
1174     if (password != NULL)\r
1175     {\r
1176         int i;\r
1177         s->pcrc_32_tab = get_crc_table();\r
1178         init_keys(password,s->keys,s->pcrc_32_tab);\r
1179         if (ZSEEK(s->z_filefunc, s->filestream,\r
1180                   s->pfile_in_zip_read->pos_in_zipfile +\r
1181                      s->pfile_in_zip_read->byte_before_the_zipfile,\r
1182                   SEEK_SET)!=0)\r
1183             return UNZ_INTERNALERROR;\r
1184         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)\r
1185             return UNZ_INTERNALERROR;\r
1186 \r
1187         for (i = 0; i<12; i++)\r
1188             zdecode(s->keys,s->pcrc_32_tab,source[i]);\r
1189 \r
1190         s->pfile_in_zip_read->pos_in_zipfile+=12;\r
1191         s->encrypted=1;\r
1192     }\r
1193 #    endif\r
1194 \r
1195 \r
1196     return UNZ_OK;\r
1197 }\r
1198 \r
1199 extern int ZEXPORT unzOpenCurrentFile (file)\r
1200     unzFile file;\r
1201 {\r
1202     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);\r
1203 }\r
1204 \r
1205 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)\r
1206     unzFile file;\r
1207     const char* password;\r
1208 {\r
1209     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);\r
1210 }\r
1211 \r
1212 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)\r
1213     unzFile file;\r
1214     int* method;\r
1215     int* level;\r
1216     int raw;\r
1217 {\r
1218     return unzOpenCurrentFile3(file, method, level, raw, NULL);\r
1219 }\r
1220 \r
1221 /*\r
1222   Read bytes from the current file.\r
1223   buf contain buffer where data must be copied\r
1224   len the size of buf.\r
1225 \r
1226   return the number of byte copied if somes bytes are copied\r
1227   return 0 if the end of file was reached\r
1228   return <0 with error code if there is an error\r
1229     (UNZ_ERRNO for IO error, or zLib error for uncompress error)\r
1230 */\r
1231 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)\r
1232     unzFile file;\r
1233     voidp buf;\r
1234     unsigned len;\r
1235 {\r
1236     int err=UNZ_OK;\r
1237     uInt iRead = 0;\r
1238     unz_s* s;\r
1239     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1240     if (file==NULL)\r
1241         return UNZ_PARAMERROR;\r
1242     s=(unz_s*)file;\r
1243     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1244 \r
1245     if (pfile_in_zip_read_info==NULL)\r
1246         return UNZ_PARAMERROR;\r
1247 \r
1248 \r
1249     if ((pfile_in_zip_read_info->read_buffer == NULL))\r
1250         return UNZ_END_OF_LIST_OF_FILE;\r
1251     if (len==0)\r
1252         return 0;\r
1253 \r
1254     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;\r
1255 \r
1256     pfile_in_zip_read_info->stream.avail_out = (uInt)len;\r
1257 \r
1258     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&\r
1259         (!(pfile_in_zip_read_info->raw)))\r
1260         pfile_in_zip_read_info->stream.avail_out =\r
1261             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;\r
1262 \r
1263     if ((len>pfile_in_zip_read_info->rest_read_compressed+\r
1264            pfile_in_zip_read_info->stream.avail_in) &&\r
1265          (pfile_in_zip_read_info->raw))\r
1266         pfile_in_zip_read_info->stream.avail_out =\r
1267             (uInt)pfile_in_zip_read_info->rest_read_compressed+\r
1268             pfile_in_zip_read_info->stream.avail_in;\r
1269 \r
1270     while (pfile_in_zip_read_info->stream.avail_out>0)\r
1271     {\r
1272         if ((pfile_in_zip_read_info->stream.avail_in==0) &&\r
1273             (pfile_in_zip_read_info->rest_read_compressed>0))\r
1274         {\r
1275             uInt uReadThis = UNZ_BUFSIZE;\r
1276             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)\r
1277                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;\r
1278             if (uReadThis == 0)\r
1279                 return UNZ_EOF;\r
1280             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
1281                       pfile_in_zip_read_info->filestream,\r
1282                       pfile_in_zip_read_info->pos_in_zipfile +\r
1283                          pfile_in_zip_read_info->byte_before_the_zipfile,\r
1284                          ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1285                 return UNZ_ERRNO;\r
1286             if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
1287                       pfile_in_zip_read_info->filestream,\r
1288                       pfile_in_zip_read_info->read_buffer,\r
1289                       uReadThis)!=uReadThis)\r
1290                 return UNZ_ERRNO;\r
1291 \r
1292 \r
1293 #            ifndef NOUNCRYPT\r
1294             if(s->encrypted)\r
1295             {\r
1296                 uInt i;\r
1297                 for(i=0;i<uReadThis;i++)\r
1298                   pfile_in_zip_read_info->read_buffer[i] =\r
1299                       zdecode(s->keys,s->pcrc_32_tab,\r
1300                               pfile_in_zip_read_info->read_buffer[i]);\r
1301             }\r
1302 #            endif\r
1303 \r
1304 \r
1305             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;\r
1306 \r
1307             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;\r
1308 \r
1309             pfile_in_zip_read_info->stream.next_in =\r
1310                 (Bytef*)pfile_in_zip_read_info->read_buffer;\r
1311             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;\r
1312         }\r
1313 \r
1314         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))\r
1315         {\r
1316             uInt uDoCopy,i ;\r
1317 \r
1318             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&\r
1319                 (pfile_in_zip_read_info->rest_read_compressed == 0))\r
1320                 return (iRead==0) ? UNZ_EOF : iRead;\r
1321 \r
1322             if (pfile_in_zip_read_info->stream.avail_out <\r
1323                             pfile_in_zip_read_info->stream.avail_in)\r
1324                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;\r
1325             else\r
1326                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;\r
1327 \r
1328             for (i=0;i<uDoCopy;i++)\r
1329                 *(pfile_in_zip_read_info->stream.next_out+i) =\r
1330                         *(pfile_in_zip_read_info->stream.next_in+i);\r
1331 \r
1332             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,\r
1333                                 pfile_in_zip_read_info->stream.next_out,\r
1334                                 uDoCopy);\r
1335             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;\r
1336             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;\r
1337             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;\r
1338             pfile_in_zip_read_info->stream.next_out += uDoCopy;\r
1339             pfile_in_zip_read_info->stream.next_in += uDoCopy;\r
1340             pfile_in_zip_read_info->stream.total_out += uDoCopy;\r
1341             iRead += uDoCopy;\r
1342         }\r
1343         else\r
1344         {\r
1345             uLong uTotalOutBefore,uTotalOutAfter;\r
1346             const Bytef *bufBefore;\r
1347             uLong uOutThis;\r
1348             int flush=Z_SYNC_FLUSH;\r
1349 \r
1350             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;\r
1351             bufBefore = pfile_in_zip_read_info->stream.next_out;\r
1352 \r
1353             /*\r
1354             if ((pfile_in_zip_read_info->rest_read_uncompressed ==\r
1355                      pfile_in_zip_read_info->stream.avail_out) &&\r
1356                 (pfile_in_zip_read_info->rest_read_compressed == 0))\r
1357                 flush = Z_FINISH;\r
1358             */\r
1359             err=inflate(&pfile_in_zip_read_info->stream,flush);\r
1360 \r
1361             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))\r
1362               err = Z_DATA_ERROR;\r
1363 \r
1364             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;\r
1365             uOutThis = uTotalOutAfter-uTotalOutBefore;\r
1366 \r
1367             pfile_in_zip_read_info->crc32 =\r
1368                 crc32(pfile_in_zip_read_info->crc32,bufBefore,\r
1369                         (uInt)(uOutThis));\r
1370 \r
1371             pfile_in_zip_read_info->rest_read_uncompressed -=\r
1372                 uOutThis;\r
1373 \r
1374             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\r
1375 \r
1376             if (err==Z_STREAM_END)\r
1377                 return (iRead==0) ? UNZ_EOF : iRead;\r
1378             if (err!=Z_OK)\r
1379                 break;\r
1380         }\r
1381     }\r
1382 \r
1383     if (err==Z_OK)\r
1384         return iRead;\r
1385     return err;\r
1386 }\r
1387 \r
1388 \r
1389 /*\r
1390   Give the current position in uncompressed data\r
1391 */\r
1392 extern z_off_t ZEXPORT unztell (file)\r
1393     unzFile file;\r
1394 {\r
1395     unz_s* s;\r
1396     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1397     if (file==NULL)\r
1398         return UNZ_PARAMERROR;\r
1399     s=(unz_s*)file;\r
1400     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1401 \r
1402     if (pfile_in_zip_read_info==NULL)\r
1403         return UNZ_PARAMERROR;\r
1404 \r
1405     return (z_off_t)pfile_in_zip_read_info->stream.total_out;\r
1406 }\r
1407 \r
1408 \r
1409 /*\r
1410   return 1 if the end of file was reached, 0 elsewhere\r
1411 */\r
1412 extern int ZEXPORT unzeof (file)\r
1413     unzFile file;\r
1414 {\r
1415     unz_s* s;\r
1416     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1417     if (file==NULL)\r
1418         return UNZ_PARAMERROR;\r
1419     s=(unz_s*)file;\r
1420     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1421 \r
1422     if (pfile_in_zip_read_info==NULL)\r
1423         return UNZ_PARAMERROR;\r
1424 \r
1425     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\r
1426         return 1;\r
1427     else\r
1428         return 0;\r
1429 }\r
1430 \r
1431 \r
1432 \r
1433 /*\r
1434   Read extra field from the current file (opened by unzOpenCurrentFile)\r
1435   This is the local-header version of the extra field (sometimes, there is\r
1436     more info in the local-header version than in the central-header)\r
1437 \r
1438   if buf==NULL, it return the size of the local extra field that can be read\r
1439 \r
1440   if buf!=NULL, len is the size of the buffer, the extra header is copied in\r
1441     buf.\r
1442   the return value is the number of bytes copied in buf, or (if <0)\r
1443     the error code\r
1444 */\r
1445 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)\r
1446     unzFile file;\r
1447     voidp buf;\r
1448     unsigned len;\r
1449 {\r
1450     unz_s* s;\r
1451     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1452     uInt read_now;\r
1453     uLong size_to_read;\r
1454 \r
1455     if (file==NULL)\r
1456         return UNZ_PARAMERROR;\r
1457     s=(unz_s*)file;\r
1458     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1459 \r
1460     if (pfile_in_zip_read_info==NULL)\r
1461         return UNZ_PARAMERROR;\r
1462 \r
1463     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -\r
1464                 pfile_in_zip_read_info->pos_local_extrafield);\r
1465 \r
1466     if (buf==NULL)\r
1467         return (int)size_to_read;\r
1468 \r
1469     if (len>size_to_read)\r
1470         read_now = (uInt)size_to_read;\r
1471     else\r
1472         read_now = (uInt)len ;\r
1473 \r
1474     if (read_now==0)\r
1475         return 0;\r
1476 \r
1477     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,\r
1478               pfile_in_zip_read_info->filestream,\r
1479               pfile_in_zip_read_info->offset_local_extrafield +\r
1480               pfile_in_zip_read_info->pos_local_extrafield,\r
1481               ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1482         return UNZ_ERRNO;\r
1483 \r
1484     if (ZREAD(pfile_in_zip_read_info->z_filefunc,\r
1485               pfile_in_zip_read_info->filestream,\r
1486               buf,read_now)!=read_now)\r
1487         return UNZ_ERRNO;\r
1488 \r
1489     return (int)read_now;\r
1490 }\r
1491 \r
1492 /*\r
1493   Close the file in zip opened with unzipOpenCurrentFile\r
1494   Return UNZ_CRCERROR if all the file was read but the CRC is not good\r
1495 */\r
1496 extern int ZEXPORT unzCloseCurrentFile (file)\r
1497     unzFile file;\r
1498 {\r
1499     int err=UNZ_OK;\r
1500 \r
1501     unz_s* s;\r
1502     file_in_zip_read_info_s* pfile_in_zip_read_info;\r
1503     if (file==NULL)\r
1504         return UNZ_PARAMERROR;\r
1505     s=(unz_s*)file;\r
1506     pfile_in_zip_read_info=s->pfile_in_zip_read;\r
1507 \r
1508     if (pfile_in_zip_read_info==NULL)\r
1509         return UNZ_PARAMERROR;\r
1510 \r
1511 \r
1512     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&\r
1513         (!pfile_in_zip_read_info->raw))\r
1514     {\r
1515         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)\r
1516             err=UNZ_CRCERROR;\r
1517     }\r
1518 \r
1519 \r
1520     TRYFREE(pfile_in_zip_read_info->read_buffer);\r
1521     pfile_in_zip_read_info->read_buffer = NULL;\r
1522     if (pfile_in_zip_read_info->stream_initialised)\r
1523         inflateEnd(&pfile_in_zip_read_info->stream);\r
1524 \r
1525     pfile_in_zip_read_info->stream_initialised = 0;\r
1526     TRYFREE(pfile_in_zip_read_info);\r
1527 \r
1528     s->pfile_in_zip_read=NULL;\r
1529 \r
1530     return err;\r
1531 }\r
1532 \r
1533 \r
1534 /*\r
1535   Get the global comment string of the ZipFile, in the szComment buffer.\r
1536   uSizeBuf is the size of the szComment buffer.\r
1537   return the number of byte copied or an error code <0\r
1538 */\r
1539 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)\r
1540     unzFile file;\r
1541     char *szComment;\r
1542     uLong uSizeBuf;\r
1543 {\r
1544     unz_s* s;\r
1545     uLong uReadThis ;\r
1546     if (file==NULL)\r
1547         return UNZ_PARAMERROR;\r
1548     s=(unz_s*)file;\r
1549 \r
1550     uReadThis = uSizeBuf;\r
1551     if (uReadThis>s->gi.size_comment)\r
1552         uReadThis = s->gi.size_comment;\r
1553 \r
1554     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)\r
1555         return UNZ_ERRNO;\r
1556 \r
1557     if (uReadThis>0)\r
1558     {\r
1559       *szComment='\0';\r
1560       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)\r
1561         return UNZ_ERRNO;\r
1562     }\r
1563 \r
1564     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))\r
1565         *(szComment+s->gi.size_comment)='\0';\r
1566     return (int)uReadThis;\r
1567 }\r
1568 \r
1569 /* Additions by RX '2004 */\r
1570 extern uLong ZEXPORT unzGetOffset (file)\r
1571     unzFile file;\r
1572 {\r
1573     unz_s* s;\r
1574 \r
1575     if (file==NULL)\r
1576           return UNZ_PARAMERROR;\r
1577     s=(unz_s*)file;\r
1578     if (!s->current_file_ok)\r
1579       return 0;\r
1580     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)\r
1581       if (s->num_file==s->gi.number_entry)\r
1582          return 0;\r
1583     return s->pos_in_central_dir;\r
1584 }\r
1585 \r
1586 extern int ZEXPORT unzSetOffset (file, pos)\r
1587         unzFile file;\r
1588         uLong pos;\r
1589 {\r
1590     unz_s* s;\r
1591     int err;\r
1592 \r
1593     if (file==NULL)\r
1594         return UNZ_PARAMERROR;\r
1595     s=(unz_s*)file;\r
1596 \r
1597     s->pos_in_central_dir = pos;\r
1598     s->num_file = s->gi.number_entry;      /* hack */\r
1599     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,\r
1600                                               &s->cur_file_info_internal,\r
1601                                               NULL,0,NULL,0,NULL,0);\r
1602     s->current_file_ok = (err == UNZ_OK);\r
1603     return err;\r
1604 }\r