1 /*---------------------------------------------------------------------------
5 This module supplies an UnZip engine for use directly from C/C++
6 programs. The functions are:
8 UzpVer *UzpVersion(void);
9 void UzpVersion2(UzpVer2 *version)
10 int UzpMain(int argc, char *argv[]);
11 int UzpAltMain(int argc, char *argv[], UzpInit *init);
12 int UzpValidate(char *archive, int AllCodes);
13 void UzpFreeMemBuffer(UzpBuffer *retstr);
14 int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
15 UzpCB *UsrFuncts, UzpBuffer *retstr);
17 non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
18 int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
22 int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
25 You must define `DLL' in order to include the API extensions.
27 ---------------------------------------------------------------------------*/
31 # define INCL_DOSMEMMGR
36 #define UNZIP_INTERNAL
40 # include "windll/windll.h"
43 #ifdef DLL /* This source file supplies DLL-only interface code. */
45 jmp_buf dll_error_return
;
47 /*---------------------------------------------------------------------------
48 Documented API entry points
49 ---------------------------------------------------------------------------*/
52 UzpVer
* UZ_EXP
UzpVersion() /* should be pointer to const struct */
54 static UzpVer version
; /* doesn't change between calls */
57 version
.structlen
= UZPVER_LEN
;
64 version
.betalevel
= BETALEVEL
;
65 version
.date
= VERSION_DATE
;
68 version
.zlib_version
= ZLIB_VERSION
;
71 version
.zlib_version
= NULL
;
74 /* someday each of these may have a separate patchlevel: */
75 version
.unzip
.major
= UZ_MAJORVER
;
76 version
.unzip
.minor
= UZ_MINORVER
;
77 version
.unzip
.patchlevel
= PATCHLEVEL
;
79 version
.zipinfo
.major
= ZI_MAJORVER
;
80 version
.zipinfo
.minor
= ZI_MINORVER
;
81 version
.zipinfo
.patchlevel
= PATCHLEVEL
;
83 /* these are retained for backward compatibility only: */
84 version
.os2dll
.major
= UZ_MAJORVER
;
85 version
.os2dll
.minor
= UZ_MINORVER
;
86 version
.os2dll
.patchlevel
= PATCHLEVEL
;
88 version
.windll
.major
= UZ_MAJORVER
;
89 version
.windll
.minor
= UZ_MINORVER
;
90 version
.windll
.patchlevel
= PATCHLEVEL
;
95 void UZ_EXP
UzpVersion2(UzpVer2
*version
)
98 version
->structlen
= UZPVER_LEN
;
105 strcpy(version
->betalevel
, BETALEVEL
);
106 strcpy(version
->date
, VERSION_DATE
);
109 strcpy(version
->zlib_version
, ZLIB_VERSION
);
112 version
->zlib_version
[0] = '\0';
115 /* someday each of these may have a separate patchlevel: */
116 version
->unzip
.major
= UZ_MAJORVER
;
117 version
->unzip
.minor
= UZ_MINORVER
;
118 version
->unzip
.patchlevel
= PATCHLEVEL
;
120 version
->zipinfo
.major
= ZI_MAJORVER
;
121 version
->zipinfo
.minor
= ZI_MINORVER
;
122 version
->zipinfo
.patchlevel
= PATCHLEVEL
;
124 /* these are retained for backward compatibility only: */
125 version
->os2dll
.major
= UZ_MAJORVER
;
126 version
->os2dll
.minor
= UZ_MINORVER
;
127 version
->os2dll
.patchlevel
= PATCHLEVEL
;
129 version
->windll
.major
= UZ_MAJORVER
;
130 version
->windll
.minor
= UZ_MINORVER
;
131 version
->windll
.patchlevel
= PATCHLEVEL
;
140 int UZ_EXP
UzpAltMain(int argc
, char *argv
[], UzpInit
*init
)
147 if (init
->structlen
>= (sizeof(ulg
) + sizeof(dummyfn
)) && init
->msgfn
)
148 G
.message
= init
->msgfn
;
150 if (init
->structlen
>= (sizeof(ulg
) + 2*sizeof(dummyfn
)) && init
->inputfn
)
151 G
.input
= init
->inputfn
;
153 if (init
->structlen
>= (sizeof(ulg
) + 3*sizeof(dummyfn
)) && init
->pausefn
)
154 G
.mpause
= init
->pausefn
;
156 if (init
->structlen
>= (sizeof(ulg
) + 4*sizeof(dummyfn
)) && init
->userfn
)
157 (*init
->userfn
)(); /* allow void* arg? */
159 r
= unzip(__G__ argc
, argv
);
171 void UZ_EXP
UzpFreeMemBuffer(UzpBuffer
*retstr
)
173 if (retstr
->strptr
!= NULL
) {
174 free(retstr
->strptr
);
175 retstr
->strptr
= NULL
;
184 static int UzpDLL_Init
OF((zvoid
*pG
, UzpCB
*UsrFuncts
));
186 static int UzpDLL_Init(pG
, UsrFuncts
)
192 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + sizeof(dummyfn
)) &&
194 ((Uz_Globs
*)pG
)->message
= UsrFuncts
->msgfn
;
198 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 2*sizeof(dummyfn
)) &&
200 ((Uz_Globs
*)pG
)->input
= UsrFuncts
->inputfn
;
202 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 3*sizeof(dummyfn
)) &&
204 ((Uz_Globs
*)pG
)->mpause
= UsrFuncts
->pausefn
;
206 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 4*sizeof(dummyfn
)) &&
208 ((Uz_Globs
*)pG
)->decr_passwd
= UsrFuncts
->passwdfn
;
210 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 5*sizeof(dummyfn
)) &&
211 UsrFuncts
->statrepfn
)
212 ((Uz_Globs
*)pG
)->statreportcb
= UsrFuncts
->statrepfn
;
218 int UZ_EXP
UzpUnzipToMemory(char *zip
, char *file
, UzpOpts
*optflgs
,
219 UzpCB
*UsrFuncts
, UzpBuffer
*retstr
)
222 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
223 char *intern_zip
, *intern_file
;
227 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
228 intern_zip
= (char *)malloc(strlen(zip
)+1);
229 if (intern_zip
== NULL
) {
233 intern_file
= (char *)malloc(strlen(file
)+1);
234 if (intern_file
== NULL
) {
239 ISO_TO_INTERN(zip
, intern_zip
);
240 ISO_TO_INTERN(file
, intern_file
);
241 # define zip intern_zip
242 # define file intern_file
244 /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
245 * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
247 uO
.pwdarg
= optflgs
->pwdarg
;
248 uO
.aflag
= optflgs
->aflag
;
249 uO
.C_flag
= optflgs
->C_flag
;
250 uO
.qflag
= optflgs
->qflag
; /* currently, overridden in unzipToMemory */
252 if (!UzpDLL_Init((zvoid
*)&G
, UsrFuncts
)) {
258 r
= (unzipToMemory(__G__ zip
, file
, retstr
) <= PK_WARN
);
261 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
267 if (!r
&& retstr
->strlength
) {
268 free(retstr
->strptr
);
269 retstr
->strptr
= NULL
;
274 #endif /* !__16BIT__ */
282 int UZ_EXP
UzpFileTree(char *name
, cbList(callBack
), char *cpInclude
[],
292 G
.process_all_files
= TRUE
;
294 char **ptr
= cpInclude
;
296 while (*ptr
!= NULL
) ptr
++;
297 G
.filespecs
= ptr
- cpInclude
;
298 G
.pfnames
= cpInclude
, G
.process_all_files
= FALSE
;
301 char **ptr
= cpExclude
;
303 while (*ptr
!= NULL
) ptr
++;
304 G
.xfilespecs
= ptr
- cpExclude
;
305 G
.pxnames
= cpExclude
, G
.process_all_files
= FALSE
;
308 G
.processExternally
= callBack
;
309 r
= process_zipfiles(__G
)==0;
319 /*---------------------------------------------------------------------------
321 ---------------------------------------------------------------------------*/
324 void setFileNotFound(__G
)
332 int unzipToMemory(__GPRO__
char *zip
, char *file
, UzpBuffer
*retstr
)
337 G
.process_all_files
= FALSE
;
338 G
.extract_flag
= TRUE
;
347 r
= process_zipfiles(__G
);
349 retstr
->strptr
= (char *)G
.redirect_buffer
;
350 retstr
->strlength
= G
.redirect_size
;
352 return r
; /* returns `PK_???' error values */
357 int redirect_outfile(__G
)
360 if (G
.redirect_size
!= 0 || G
.redirect_buffer
!= NULL
)
363 #ifndef NO_SLIDE_REDIR
364 G
.redirect_slide
= !G
.pInfo
->textmode
;
366 G
.redirect_size
= (G
.pInfo
->textmode
?
367 G
.lrec
.ucsize
* lenEOL
: G
.lrec
.ucsize
);
369 DosAllocMem((void **)&G
.redirect_buffer
, G
.redirect_size
+1,
370 PAG_READ
|PAG_WRITE
|PAG_COMMIT
);
371 G
.redirect_pointer
= G
.redirect_buffer
;
374 if ((ulg
)((extent
)G
.redirect_size
) != G
.redirect_size
)
377 G
.redirect_pointer
= G
.redirect_buffer
= malloc(G
.redirect_size
+1);
379 if (!G
.redirect_buffer
)
381 G
.redirect_pointer
[G
.redirect_size
] = '\0';
387 int writeToMemory(__GPRO__ uch
*rawbuf
, ulg size
)
389 if (rawbuf
!= G
.redirect_pointer
)
390 memcpy(G
.redirect_pointer
,rawbuf
,size
);
391 G
.redirect_pointer
+= size
;
398 int close_redirect(__G
)
401 if (G
.pInfo
->textmode
) {
402 *G
.redirect_pointer
= '\0';
403 G
.redirect_size
= G
.redirect_pointer
- G
.redirect_buffer
;
404 if ((G
.redirect_buffer
=
405 realloc(G
.redirect_buffer
, G
.redirect_size
+ 1)) == NULL
) {
419 /* Purpose: Determine if file in archive contains the string szSearch
421 Parameters: archive = archive name
422 file = file contained in the archive. This cannot be
423 a wild card to be meaningful
424 pattern = string to search for
425 cmd = 0 - case-insensitive search
426 1 - case-sensitve search
427 2 - case-insensitive, whole words only
428 3 - case-sensitive, whole words only
429 SkipBin = if true, skip any files that have control
430 characters other than CR, LF, or tab in the first
433 Returns: TRUE if a match is found
434 FALSE if no match is found
437 Comments: This does not pretend to be as useful as the standard
438 Unix grep, which returns the strings associated with a
439 particular pattern, nor does it search past the first
440 matching occurrence of the pattern.
443 int UZ_EXP
UzpGrep(char *archive
, char *file
, char *pattern
, int cmd
,
444 int SkipBin
, UzpCB
*UsrFuncts
)
446 int retcode
= FALSE
, compare
;
447 ulg i
, j
, patternLen
, buflen
;
452 memzero(&flgopts
, sizeof(UzpOpts
)); /* no special options */
454 if (!UzpUnzipToMemory(archive
, file
, &flgopts
, UsrFuncts
, &retstr
)) {
455 return -1; /* not enough memory, file not found, or other error */
459 if (retstr
.strlength
< 100)
460 buflen
= retstr
.strlength
;
463 for (i
= 0; i
< buflen
; i
++) {
464 if (iscntrl(retstr
.strptr
[i
])) {
465 if ((retstr
.strptr
[i
] != 0x0A) &&
466 (retstr
.strptr
[i
] != 0x0D) &&
467 (retstr
.strptr
[i
] != 0x09))
469 /* OK, we now think we have a binary file of some sort */
477 patternLen
= strlen(pattern
);
479 if (retstr
.strlength
< patternLen
) {
484 sz
= malloc(patternLen
+ 3); /* add two in case doing whole words only */
492 if ((cmd
== 0) || (cmd
== 2)) {
493 for (i
= 0; i
< strlen(sz
); i
++)
494 sz
[i
] = toupper(sz
[i
]);
495 for (i
= 0; i
< retstr
.strlength
; i
++)
496 retstr
.strptr
[i
] = toupper(retstr
.strptr
[i
]);
499 for (i
= 0; i
< (retstr
.strlength
- patternLen
); i
++) {
500 p
= &retstr
.strptr
[i
];
502 for (j
= 0; j
< patternLen
; j
++) {
503 /* We cannot do strncmp here, as we may be dealing with a
504 * "binary" file, such as a word processing file, or perhaps
505 * even a true executable of some sort. */
511 if (compare
== TRUE
) {
523 #endif /* !__16BIT__ */
528 int UZ_EXP
UzpValidate(char *archive
, int AllCodes
)
535 uO
.overwrite_none
= 0;
536 G
.extract_flag
= (!uO
.zipinfo_mode
&&
537 !uO
.cflag
&& !uO
.tflag
&& !uO
.vflag
&& !uO
.zflag
543 uO
.qflag
= 2; /* turn off all messages */
545 G
.pfnames
= (char **)&fnames
[0]; /* assign default filename vector */
547 Wiz_NoPrinting(TRUE
);
550 if (archive
== NULL
) { /* something is screwed up: no filename */
555 G
.wildzipfn
= (char *)malloc(FILNAMSIZ
+ 1);
556 strcpy(G
.wildzipfn
, archive
);
557 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
558 _ISO_INTERN(G
.wildzipfn
);
561 G
.process_all_files
= TRUE
; /* for speed */
563 retcode
= setjmp(dll_error_return
);
567 Wiz_NoPrinting(FALSE
);
574 retcode
= process_zipfiles(__G
);
578 Wiz_NoPrinting(FALSE
);
582 /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
583 archive, we should still be able to see the files inside it,
584 even if we can't decode them for some reason.
586 We also still want to be able to get at files even if there is
587 something odd about the zip archive, hence allow PK_WARN,
588 PK_FIND, IZ_UNSUP as well as PK_ERR
594 if ((retcode
== PK_OK
) || (retcode
== PK_WARN
) || (retcode
== PK_ERR
) ||
595 (retcode
== IZ_UNSUP
) || (retcode
== PK_FIND
))