1 /*
2 Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
3
4 See the accompanying file LICENSE, version 2009-Jan-02 or later
5 (the contents of which are also included in unzip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
8 */
9 /*---------------------------------------------------------------------------
10
11 api.c
12
13 This module supplies an UnZip engine for use directly from C/C++
14 programs. The functions are:
15
16 ZCONST UzpVer *UzpVersion(void);
17 unsigned UzpVersion2(UzpVer2 *version)
18 int UzpMain(int argc, char *argv[]);
19 int UzpAltMain(int argc, char *argv[], UzpInit *init);
20 int UzpValidate(char *archive, int AllCodes);
21 void UzpFreeMemBuffer(UzpBuffer *retstr);
22 int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
23 UzpCB *UsrFuncts, UzpBuffer *retstr);
24
25 non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
26 int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
27 UzpCB *UsrFuncts);
28
29 OS/2 only (for now):
30 int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
31 char *cpExclude[]);
32
33 You must define `DLL' in order to include the API extensions.
34
35 ---------------------------------------------------------------------------*/
36
37
38 #ifdef OS2
39 # define INCL_DOSMEMMGR
40 # include <os2.h>
41 #endif
42
43 #define UNZIP_INTERNAL
44 #include "unzip.h"
45 #ifdef WINDLL
46 # ifdef POCKET_UNZIP
47 # include "wince/intrface.h"
48 # else
49 # include "windll/windll.h"
50 # endif
51 #endif
52 #include "unzvers.h"
53 #include <setjmp.h>
54
55 #ifdef DLL /* This source file supplies DLL-only interface code. */
56
57 #ifndef POCKET_UNZIP /* WinCE pUnZip defines this elsewhere. */
58 jmp_buf dll_error_return;
59 #endif
60
61 /*---------------------------------------------------------------------------
62 Documented API entry points
63 ---------------------------------------------------------------------------*/
64
65
UzpVersion()66 ZCONST UzpVer * UZ_EXP UzpVersion() /* returns pointer to const struct */
67 {
68 static ZCONST UzpVer version = { /* doesn't change between calls */
69 /* structure size */
70 UZPVER_LEN,
71 /* version flags */
72 #ifdef BETA
73 # ifdef ZLIB_VERSION
74 3,
75 # else
76 1,
77 # endif
78 #else
79 # ifdef ZLIB_VERSION
80 2,
81 # else
82 0,
83 # endif
84 #endif
85 /* betalevel and date strings */
86 UZ_BETALEVEL, UZ_VERSION_DATE,
87 /* zlib_version string */
88 #ifdef ZLIB_VERSION
89 ZLIB_VERSION,
90 #else
91 NULL,
92 #endif
93 /*== someday each of these may have a separate patchlevel: ==*/
94 /* unzip version */
95 {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
96 /* zipinfo version */
97 {ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, 0},
98 /* os2dll version (retained for backward compatibility) */
99 {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
100 /* windll version (retained for backward compatibility)*/
101 {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
102 #ifdef OS2DLL
103 /* os2dll API minimum compatible version*/
104 {UZ_OS2API_COMP_MAJOR, UZ_OS2API_COMP_MINOR, UZ_OS2API_COMP_REVIS, 0}
105 #else /* !OS2DLL */
106 #ifdef WINDLL
107 /* windll API minimum compatible version*/
108 {UZ_WINAPI_COMP_MAJOR, UZ_WINAPI_COMP_MINOR, UZ_WINAPI_COMP_REVIS, 0}
109 #else /* !WINDLL */
110 /* generic DLL API minimum compatible version*/
111 {UZ_GENAPI_COMP_MAJOR, UZ_GENAPI_COMP_MINOR, UZ_GENAPI_COMP_REVIS, 0}
112 #endif /* ?WINDLL */
113 #endif /* ?OS2DLL */
114 };
115
116 return &version;
117 }
118
UzpVersion2(UzpVer2 * version)119 unsigned UZ_EXP UzpVersion2(UzpVer2 *version)
120 {
121
122 if (version->structlen != sizeof(UzpVer2))
123 return sizeof(UzpVer2);
124
125 #ifdef BETA
126 version->flag = 1;
127 #else
128 version->flag = 0;
129 #endif
130 strcpy(version->betalevel, UZ_BETALEVEL);
131 strcpy(version->date, UZ_VERSION_DATE);
132
133 #ifdef ZLIB_VERSION
134 /* Although ZLIB_VERSION is a compile-time constant, we implement an
135 "overrun-safe" copy because its actual value is not under our control.
136 */
137 strncpy(version->zlib_version, ZLIB_VERSION,
138 sizeof(version->zlib_version) - 1);
139 version->zlib_version[sizeof(version->zlib_version) - 1] = '\0';
140 version->flag |= 2;
141 #else
142 version->zlib_version[0] = '\0';
143 #endif
144
145 /* someday each of these may have a separate patchlevel: */
146 version->unzip.major = UZ_MAJORVER;
147 version->unzip.minor = UZ_MINORVER;
148 version->unzip.patchlevel = UZ_PATCHLEVEL;
149
150 version->zipinfo.major = ZI_MAJORVER;
151 version->zipinfo.minor = ZI_MINORVER;
152 version->zipinfo.patchlevel = UZ_PATCHLEVEL;
153
154 /* these are retained for backward compatibility only: */
155 version->os2dll.major = UZ_MAJORVER;
156 version->os2dll.minor = UZ_MINORVER;
157 version->os2dll.patchlevel = UZ_PATCHLEVEL;
158
159 version->windll.major = UZ_MAJORVER;
160 version->windll.minor = UZ_MINORVER;
161 version->windll.patchlevel = UZ_PATCHLEVEL;
162
163 #ifdef OS2DLL
164 /* os2dll API minimum compatible version*/
165 version->dllapimin.major = UZ_OS2API_COMP_MAJOR;
166 version->dllapimin.minor = UZ_OS2API_COMP_MINOR;
167 version->dllapimin.patchlevel = UZ_OS2API_COMP_REVIS;
168 #else /* !OS2DLL */
169 #ifdef WINDLL
170 /* windll API minimum compatible version*/
171 version->dllapimin.major = UZ_WINAPI_COMP_MAJOR;
172 version->dllapimin.minor = UZ_WINAPI_COMP_MINOR;
173 version->dllapimin.patchlevel = UZ_WINAPI_COMP_REVIS;
174 #else /* !WINDLL */
175 /* generic DLL API minimum compatible version*/
176 version->dllapimin.major = UZ_GENAPI_COMP_MAJOR;
177 version->dllapimin.minor = UZ_GENAPI_COMP_MINOR;
178 version->dllapimin.patchlevel = UZ_GENAPI_COMP_REVIS;
179 #endif /* ?WINDLL */
180 #endif /* ?OS2DLL */
181 return 0;
182 }
183
184
185
186
187
188 #ifndef SFX
189 #ifndef WINDLL
190
UzpAltMain(int argc,char * argv[],UzpInit * init)191 int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
192 {
193 int r, (*dummyfn)();
194
195
196 CONSTRUCTGLOBALS();
197
198 if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
199 G.message = init->msgfn;
200
201 if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
202 G.input = init->inputfn;
203
204 if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
205 G.mpause = init->pausefn;
206
207 if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
208 (*init->userfn)(); /* allow void* arg? */
209
210 r = unzip(__G__ argc, argv);
211 DESTROYGLOBALS();
212 RETURN(r);
213 }
214
215 #endif /* !WINDLL */
216
217
218
219
220 #ifndef __16BIT__
221
UzpFreeMemBuffer(UzpBuffer * retstr)222 void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
223 {
224 if (retstr != NULL && retstr->strptr != NULL) {
225 free(retstr->strptr);
226 retstr->strptr = NULL;
227 retstr->strlength = 0;
228 }
229 }
230
231
232
233
234 #ifndef WINDLL
235
236 static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
237
UzpDLL_Init(pG,UsrFuncts)238 static int UzpDLL_Init(pG, UsrFuncts)
239 zvoid *pG;
240 UzpCB *UsrFuncts;
241 {
242 int (*dummyfn)();
243
244 if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
245 UsrFuncts->msgfn)
246 ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
247 else
248 return FALSE;
249
250 if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
251 UsrFuncts->inputfn)
252 ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
253
254 if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
255 UsrFuncts->pausefn)
256 ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
257
258 if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
259 UsrFuncts->passwdfn)
260 ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
261
262 if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
263 UsrFuncts->statrepfn)
264 ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
265
266 return TRUE;
267 }
268
269
UzpUnzipToMemory(char * zip,char * file,UzpOpts * optflgs,UzpCB * UsrFuncts,UzpBuffer * retstr)270 int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
271 UzpCB *UsrFuncts, UzpBuffer *retstr)
272 {
273 int r;
274 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
275 char *intern_zip, *intern_file;
276 #endif
277
278 CONSTRUCTGLOBALS();
279 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
280 intern_zip = (char *)malloc(strlen(zip)+1);
281 if (intern_zip == NULL) {
282 DESTROYGLOBALS();
283 return PK_MEM;
284 }
285 intern_file = (char *)malloc(strlen(file)+1);
286 if (intern_file == NULL) {
287 DESTROYGLOBALS();
288 free(intern_zip);
289 return PK_MEM;
290 }
291 ISO_TO_INTERN(zip, intern_zip);
292 ISO_TO_INTERN(file, intern_file);
293 # define zip intern_zip
294 # define file intern_file
295 #endif
296 /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
297 * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
298 */
299 uO.pwdarg = optflgs->pwdarg;
300 uO.aflag = optflgs->aflag;
301 uO.C_flag = optflgs->C_flag;
302 uO.qflag = optflgs->qflag; /* currently, overridden in unzipToMemory */
303
304 if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
305 DESTROYGLOBALS();
306 return PK_BADERR;
307 }
308 G.redirect_data = 1;
309
310 r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
311
312 DESTROYGLOBALS();
313 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
314 # undef file
315 # undef zip
316 free(intern_file);
317 free(intern_zip);
318 #endif
319 if (!r && retstr->strlength) {
320 free(retstr->strptr);
321 retstr->strptr = NULL;
322 }
323 return r;
324 }
325 #endif /* !WINDLL */
326 #endif /* !__16BIT__ */
327
328
329
330
331
332 #ifdef OS2DLL
333
UzpFileTree(char * name,cbList (callBack),char * cpInclude[],char * cpExclude[])334 int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
335 char *cpExclude[])
336 {
337 int r;
338
339 CONSTRUCTGLOBALS();
340 uO.qflag = 2;
341 uO.vflag = 1;
342 uO.C_flag = 1;
343 G.wildzipfn = name;
344 G.process_all_files = TRUE;
345 if (cpInclude) {
346 char **ptr = cpInclude;
347
348 while (*ptr != NULL) ptr++;
349 G.filespecs = ptr - cpInclude;
350 G.pfnames = cpInclude, G.process_all_files = FALSE;
351 }
352 if (cpExclude) {
353 char **ptr = cpExclude;
354
355 while (*ptr != NULL) ptr++;
356 G.xfilespecs = ptr - cpExclude;
357 G.pxnames = cpExclude, G.process_all_files = FALSE;
358 }
359
360 G.processExternally = callBack;
361 r = process_zipfiles(__G)==0;
362 DESTROYGLOBALS();
363 return r;
364 }
365
366 #endif /* OS2DLL */
367 #endif /* !SFX */
368
369
370
371
372 /*---------------------------------------------------------------------------
373 Helper functions
374 ---------------------------------------------------------------------------*/
375
376
setFileNotFound(__G)377 void setFileNotFound(__G)
378 __GDEF
379 {
380 G.filenotfound++;
381 }
382
383
384 #ifndef SFX
385
unzipToMemory(__GPRO__ char * zip,char * file,UzpBuffer * retstr)386 int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
387 {
388 int r;
389 char *incname[2];
390
391 if ((zip == NULL) || (strlen(zip) > ((WSIZE>>2) - 160)))
392 return PK_PARAM;
393 if ((file == NULL) || (strlen(file) > ((WSIZE>>2) - 160)))
394 return PK_PARAM;
395
396 G.process_all_files = FALSE;
397 G.extract_flag = TRUE;
398 uO.qflag = 2;
399 G.wildzipfn = zip;
400
401 G.pfnames = incname;
402 incname[0] = file;
403 incname[1] = NULL;
404 G.filespecs = 1;
405
406 r = process_zipfiles(__G);
407 if (retstr) {
408 retstr->strptr = (char *)G.redirect_buffer;
409 retstr->strlength = G.redirect_size;
410 }
411 return r; /* returns `PK_???' error values */
412 }
413
414 #endif /* !SFX */
415
416 /*
417 With the advent of 64 bit support, for now I am assuming that
418 if the size of the file is greater than an unsigned long, there
419 will simply not be enough memory to handle it, and am returning
420 FALSE.
421 */
redirect_outfile(__G)422 int redirect_outfile(__G)
423 __GDEF
424 {
425 #ifdef ZIP64_SUPPORT
426 __int64 check_conversion;
427 #endif
428
429 if (G.redirect_size != 0 || G.redirect_buffer != NULL)
430 return FALSE;
431
432 #ifndef NO_SLIDE_REDIR
433 G.redirect_slide = !G.pInfo->textmode;
434 #endif
435 #if (lenEOL != 1)
436 if (G.pInfo->textmode) {
437 G.redirect_size = (ulg)(G.lrec.ucsize * lenEOL);
438 if (G.redirect_size < G.lrec.ucsize)
439 G.redirect_size = (ulg)((G.lrec.ucsize > (ulg)-2L) ?
440 G.lrec.ucsize : -2L);
441 #ifdef ZIP64_SUPPORT
442 check_conversion = G.lrec.ucsize * lenEOL;
443 #endif
444 } else
445 #endif
446 {
447 G.redirect_size = (ulg)G.lrec.ucsize;
448 #ifdef ZIP64_SUPPORT
449 check_conversion = (__int64)G.lrec.ucsize;
450 #endif
451 }
452
453 #ifdef ZIP64_SUPPORT
454 if ((__int64)G.redirect_size != check_conversion)
455 return FALSE;
456 #endif
457
458 #ifdef __16BIT__
459 if ((ulg)((extent)G.redirect_size) != G.redirect_size)
460 return FALSE;
461 #endif
462 #ifdef OS2
463 DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
464 PAG_READ|PAG_WRITE|PAG_COMMIT);
465 G.redirect_pointer = G.redirect_buffer;
466 #else
467 G.redirect_pointer =
468 G.redirect_buffer = malloc((extent)(G.redirect_size+1));
469 #endif
470 if (!G.redirect_buffer)
471 return FALSE;
472 G.redirect_pointer[G.redirect_size] = '\0';
473 return TRUE;
474 }
475
476
477
writeToMemory(__GPRO__ ZCONST uch * rawbuf,extent size)478 int writeToMemory(__GPRO__ ZCONST uch *rawbuf, extent size)
479 {
480 int errflg = FALSE;
481
482 if ((uch *)rawbuf != G.redirect_pointer) {
483 extent redir_avail = (G.redirect_buffer + G.redirect_size) -
484 G.redirect_pointer;
485
486 /* Check for output buffer overflow */
487 if (size > redir_avail) {
488 /* limit transfer data to available space, set error return flag */
489 size = redir_avail;
490 errflg = TRUE;
491 }
492 memcpy(G.redirect_pointer, rawbuf, size);
493 }
494 G.redirect_pointer += size;
495 return errflg;
496 }
497
498
499
500
close_redirect(__G)501 int close_redirect(__G)
502 __GDEF
503 {
504 if (G.pInfo->textmode) {
505 *G.redirect_pointer = '\0';
506 G.redirect_size = (ulg)(G.redirect_pointer - G.redirect_buffer);
507 if ((G.redirect_buffer =
508 realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
509 G.redirect_size = 0;
510 return EOF;
511 }
512 }
513 return 0;
514 }
515
516
517
518
519 #ifndef SFX
520 #ifndef __16BIT__
521 #ifndef WINDLL
522
523 /* Purpose: Determine if file in archive contains the string szSearch
524
525 Parameters: archive = archive name
526 file = file contained in the archive. This cannot be
527 a wildcard to be meaningful
528 pattern = string to search for
529 cmd = 0 - case-insensitive search
530 1 - case-sensitve search
531 2 - case-insensitive, whole words only
532 3 - case-sensitive, whole words only
533 SkipBin = if true, skip any files that have control
534 characters other than CR, LF, or tab in the first
535 100 characters.
536
537 Returns: TRUE if a match is found
538 FALSE if no match is found
539 -1 on error
540
541 Comments: This does not pretend to be as useful as the standard
542 Unix grep, which returns the strings associated with a
543 particular pattern, nor does it search past the first
544 matching occurrence of the pattern.
545 */
546
UzpGrep(char * archive,char * file,char * pattern,int cmd,int SkipBin,UzpCB * UsrFuncts)547 int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
548 int SkipBin, UzpCB *UsrFuncts)
549 {
550 int retcode = FALSE, compare;
551 ulg i, j, patternLen, buflen;
552 char * sz, *p;
553 UzpOpts flgopts;
554 UzpBuffer retstr;
555
556 memzero(&flgopts, sizeof(UzpOpts)); /* no special options */
557
558 if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
559 return -1; /* not enough memory, file not found, or other error */
560 }
561
562 if (SkipBin) {
563 if (retstr.strlength < 100)
564 buflen = retstr.strlength;
565 else
566 buflen = 100;
567 for (i = 0; i < buflen; i++) {
568 if (iscntrl(retstr.strptr[i])) {
569 if ((retstr.strptr[i] != 0x0A) &&
570 (retstr.strptr[i] != 0x0D) &&
571 (retstr.strptr[i] != 0x09))
572 {
573 /* OK, we now think we have a binary file of some sort */
574 free(retstr.strptr);
575 return FALSE;
576 }
577 }
578 }
579 }
580
581 patternLen = strlen(pattern);
582
583 if (retstr.strlength < patternLen) {
584 free(retstr.strptr);
585 return FALSE;
586 }
587
588 sz = malloc(patternLen + 3); /* add two in case doing whole words only */
589 if (cmd > 1) {
590 strcpy(sz, " ");
591 strcat(sz, pattern);
592 strcat(sz, " ");
593 } else
594 strcpy(sz, pattern);
595
596 if ((cmd == 0) || (cmd == 2)) {
597 for (i = 0; i < strlen(sz); i++)
598 sz[i] = toupper(sz[i]);
599 for (i = 0; i < retstr.strlength; i++)
600 retstr.strptr[i] = toupper(retstr.strptr[i]);
601 }
602
603 for (i = 0; i < (retstr.strlength - patternLen); i++) {
604 p = &retstr.strptr[i];
605 compare = TRUE;
606 for (j = 0; j < patternLen; j++) {
607 /* We cannot do strncmp here, as we may be dealing with a
608 * "binary" file, such as a word processing file, or perhaps
609 * even a true executable of some sort. */
610 if (p[j] != sz[j]) {
611 compare = FALSE;
612 break;
613 }
614 }
615 if (compare == TRUE) {
616 retcode = TRUE;
617 break;
618 }
619 }
620
621 free(sz);
622 free(retstr.strptr);
623
624 return retcode;
625 }
626 #endif /* !WINDLL */
627 #endif /* !__16BIT__ */
628
629
630
UzpValidate(char * archive,int AllCodes)631 int UZ_EXP UzpValidate(char *archive, int AllCodes)
632 {
633 int retcode;
634 CONSTRUCTGLOBALS();
635
636 uO.jflag = 1;
637 uO.tflag = 1;
638 uO.overwrite_none = 0;
639 G.extract_flag = (!uO.zipinfo_mode &&
640 !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
641 #ifdef TIMESTAMP
642 && !uO.T_flag
643 #endif
644 );
645
646 uO.qflag = 2; /* turn off all messages */
647 G.fValidate = TRUE;
648 G.pfnames = (char **)&fnames[0]; /* assign default filename vector */
649
650 if (archive == NULL) { /* something is screwed up: no filename */
651 DESTROYGLOBALS();
652 retcode = PK_NOZIP;
653 goto exit_retcode;
654 }
655
656 if (strlen(archive) >= FILNAMSIZ) {
657 /* length of supplied archive name exceed the system's filename limit */
658 DESTROYGLOBALS();
659 retcode = PK_PARAM;
660 goto exit_retcode;
661 }
662
663 G.wildzipfn = (char *)malloc(FILNAMSIZ);
664 strcpy(G.wildzipfn, archive);
665 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
666 _ISO_INTERN(G.wildzipfn);
667 #endif
668
669 #ifdef WINDLL
670 Wiz_NoPrinting(TRUE);
671 #endif
672
673 G.process_all_files = TRUE; /* for speed */
674
675 if (setjmp(dll_error_return) != 0) {
676 #ifdef WINDLL
677 Wiz_NoPrinting(FALSE);
678 #endif
679 free(G.wildzipfn);
680 DESTROYGLOBALS();
681 retcode = PK_BADERR;
682 goto exit_retcode;
683 }
684
685 retcode = process_zipfiles(__G);
686
687 free(G.wildzipfn);
688 #ifdef WINDLL
689 Wiz_NoPrinting(FALSE);
690 #endif
691 DESTROYGLOBALS();
692
693 /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
694 archive, we should still be able to see the files inside it,
695 even if we can't decode them for some reason.
696
697 We also still want to be able to get at files even if there is
698 something odd about the zip archive, hence allow PK_WARN,
699 PK_FIND, IZ_UNSUP as well as PK_ERR
700 */
701
702 exit_retcode:
703 if (AllCodes)
704 return retcode;
705
706 if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
707 (retcode == IZ_UNSUP) || (retcode == PK_FIND))
708 return TRUE;
709 else
710 return FALSE;
711 }
712
713 #endif /* !SFX */
714 #endif /* DLL */
715