2 Copyright (c) 1990-2001 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2000-Apr-09 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
9 /*---------------------------------------------------------------------------
13 This module supplies an UnZip engine for use directly from C/C++
14 programs. The functions are:
16 UzpVer *UzpVersion(void);
17 void 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);
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,
30 int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
33 You must define `DLL' in order to include the API extensions.
35 ---------------------------------------------------------------------------*/
39 # define INCL_DOSMEMMGR
44 #define UNZIP_INTERNAL
47 # include "windll/windll.h"
51 #ifdef DLL /* This source file supplies DLL-only interface code. */
53 jmp_buf dll_error_return
;
55 /*---------------------------------------------------------------------------
56 Documented API entry points
57 ---------------------------------------------------------------------------*/
60 UzpVer
* UZ_EXP
UzpVersion() /* should be pointer to const struct */
62 static UzpVer version
; /* doesn't change between calls */
65 version
.structlen
= UZPVER_LEN
;
72 version
.betalevel
= UZ_BETALEVEL
;
73 version
.date
= UZ_VERSION_DATE
;
76 version
.zlib_version
= ZLIB_VERSION
;
79 version
.zlib_version
= NULL
;
82 /* someday each of these may have a separate patchlevel: */
83 version
.unzip
.major
= UZ_MAJORVER
;
84 version
.unzip
.minor
= UZ_MINORVER
;
85 version
.unzip
.patchlevel
= UZ_PATCHLEVEL
;
87 version
.zipinfo
.major
= ZI_MAJORVER
;
88 version
.zipinfo
.minor
= ZI_MINORVER
;
89 version
.zipinfo
.patchlevel
= UZ_PATCHLEVEL
;
91 /* these are retained for backward compatibility only: */
92 version
.os2dll
.major
= UZ_MAJORVER
;
93 version
.os2dll
.minor
= UZ_MINORVER
;
94 version
.os2dll
.patchlevel
= UZ_PATCHLEVEL
;
96 version
.windll
.major
= UZ_MAJORVER
;
97 version
.windll
.minor
= UZ_MINORVER
;
98 version
.windll
.patchlevel
= UZ_PATCHLEVEL
;
103 void UZ_EXP
UzpVersion2(UzpVer2
*version
)
106 version
->structlen
= UZPVER_LEN
;
113 strcpy(version
->betalevel
, UZ_BETALEVEL
);
114 strcpy(version
->date
, UZ_VERSION_DATE
);
117 strcpy(version
->zlib_version
, ZLIB_VERSION
);
120 version
->zlib_version
[0] = '\0';
123 /* someday each of these may have a separate patchlevel: */
124 version
->unzip
.major
= UZ_MAJORVER
;
125 version
->unzip
.minor
= UZ_MINORVER
;
126 version
->unzip
.patchlevel
= UZ_PATCHLEVEL
;
128 version
->zipinfo
.major
= ZI_MAJORVER
;
129 version
->zipinfo
.minor
= ZI_MINORVER
;
130 version
->zipinfo
.patchlevel
= UZ_PATCHLEVEL
;
132 /* these are retained for backward compatibility only: */
133 version
->os2dll
.major
= UZ_MAJORVER
;
134 version
->os2dll
.minor
= UZ_MINORVER
;
135 version
->os2dll
.patchlevel
= UZ_PATCHLEVEL
;
137 version
->windll
.major
= UZ_MAJORVER
;
138 version
->windll
.minor
= UZ_MINORVER
;
139 version
->windll
.patchlevel
= UZ_PATCHLEVEL
;
148 int UZ_EXP
UzpAltMain(int argc
, char *argv
[], UzpInit
*init
)
155 if (init
->structlen
>= (sizeof(ulg
) + sizeof(dummyfn
)) && init
->msgfn
)
156 G
.message
= init
->msgfn
;
158 if (init
->structlen
>= (sizeof(ulg
) + 2*sizeof(dummyfn
)) && init
->inputfn
)
159 G
.input
= init
->inputfn
;
161 if (init
->structlen
>= (sizeof(ulg
) + 3*sizeof(dummyfn
)) && init
->pausefn
)
162 G
.mpause
= init
->pausefn
;
164 if (init
->structlen
>= (sizeof(ulg
) + 4*sizeof(dummyfn
)) && init
->userfn
)
165 (*init
->userfn
)(); /* allow void* arg? */
167 r
= unzip(__G__ argc
, argv
);
179 void UZ_EXP
UzpFreeMemBuffer(UzpBuffer
*retstr
)
181 if (retstr
->strptr
!= NULL
) {
182 free(retstr
->strptr
);
183 retstr
->strptr
= NULL
;
192 static int UzpDLL_Init
OF((zvoid
*pG
, UzpCB
*UsrFuncts
));
194 static int UzpDLL_Init(pG
, UsrFuncts
)
200 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + sizeof(dummyfn
)) &&
202 ((Uz_Globs
*)pG
)->message
= UsrFuncts
->msgfn
;
206 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 2*sizeof(dummyfn
)) &&
208 ((Uz_Globs
*)pG
)->input
= UsrFuncts
->inputfn
;
210 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 3*sizeof(dummyfn
)) &&
212 ((Uz_Globs
*)pG
)->mpause
= UsrFuncts
->pausefn
;
214 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 4*sizeof(dummyfn
)) &&
216 ((Uz_Globs
*)pG
)->decr_passwd
= UsrFuncts
->passwdfn
;
218 if (UsrFuncts
->structlen
>= (sizeof(ulg
) + 5*sizeof(dummyfn
)) &&
219 UsrFuncts
->statrepfn
)
220 ((Uz_Globs
*)pG
)->statreportcb
= UsrFuncts
->statrepfn
;
226 int UZ_EXP
UzpUnzipToMemory(char *zip
, char *file
, UzpOpts
*optflgs
,
227 UzpCB
*UsrFuncts
, UzpBuffer
*retstr
)
230 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
231 char *intern_zip
, *intern_file
;
235 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
236 intern_zip
= (char *)malloc(strlen(zip
)+1);
237 if (intern_zip
== NULL
) {
241 intern_file
= (char *)malloc(strlen(file
)+1);
242 if (intern_file
== NULL
) {
247 ISO_TO_INTERN(zip
, intern_zip
);
248 ISO_TO_INTERN(file
, intern_file
);
249 # define zip intern_zip
250 # define file intern_file
252 /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
253 * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
255 uO
.pwdarg
= optflgs
->pwdarg
;
256 uO
.aflag
= optflgs
->aflag
;
257 uO
.C_flag
= optflgs
->C_flag
;
258 uO
.qflag
= optflgs
->qflag
; /* currently, overridden in unzipToMemory */
260 if (!UzpDLL_Init((zvoid
*)&G
, UsrFuncts
)) {
266 r
= (unzipToMemory(__G__ zip
, file
, retstr
) <= PK_WARN
);
269 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
275 if (!r
&& retstr
->strlength
) {
276 free(retstr
->strptr
);
277 retstr
->strptr
= NULL
;
282 #endif /* !__16BIT__ */
290 int UZ_EXP
UzpFileTree(char *name
, cbList(callBack
), char *cpInclude
[],
300 G
.process_all_files
= TRUE
;
302 char **ptr
= cpInclude
;
304 while (*ptr
!= NULL
) ptr
++;
305 G
.filespecs
= ptr
- cpInclude
;
306 G
.pfnames
= cpInclude
, G
.process_all_files
= FALSE
;
309 char **ptr
= cpExclude
;
311 while (*ptr
!= NULL
) ptr
++;
312 G
.xfilespecs
= ptr
- cpExclude
;
313 G
.pxnames
= cpExclude
, G
.process_all_files
= FALSE
;
316 G
.processExternally
= callBack
;
317 r
= process_zipfiles(__G
)==0;
327 /*---------------------------------------------------------------------------
329 ---------------------------------------------------------------------------*/
332 void setFileNotFound(__G
)
340 int unzipToMemory(__GPRO__
char *zip
, char *file
, UzpBuffer
*retstr
)
345 G
.process_all_files
= FALSE
;
346 G
.extract_flag
= TRUE
;
355 r
= process_zipfiles(__G
);
357 retstr
->strptr
= (char *)G
.redirect_buffer
;
358 retstr
->strlength
= G
.redirect_size
;
360 return r
; /* returns `PK_???' error values */
365 int redirect_outfile(__G
)
368 if (G
.redirect_size
!= 0 || G
.redirect_buffer
!= NULL
)
371 #ifndef NO_SLIDE_REDIR
372 G
.redirect_slide
= !G
.pInfo
->textmode
;
374 G
.redirect_size
= (G
.pInfo
->textmode
?
375 G
.lrec
.ucsize
* lenEOL
: G
.lrec
.ucsize
);
377 DosAllocMem((void **)&G
.redirect_buffer
, G
.redirect_size
+1,
378 PAG_READ
|PAG_WRITE
|PAG_COMMIT
);
379 G
.redirect_pointer
= G
.redirect_buffer
;
382 if ((ulg
)((extent
)G
.redirect_size
) != G
.redirect_size
)
386 G
.redirect_buffer
= malloc((extent
)(G
.redirect_size
+1));
388 if (!G
.redirect_buffer
)
390 G
.redirect_pointer
[G
.redirect_size
] = '\0';
396 int writeToMemory(__GPRO__ ZCONST uch
*rawbuf
, extent size
)
398 if ((uch
*)rawbuf
!= G
.redirect_pointer
)
399 memcpy(G
.redirect_pointer
, rawbuf
, size
);
400 G
.redirect_pointer
+= size
;
407 int close_redirect(__G
)
410 if (G
.pInfo
->textmode
) {
411 *G
.redirect_pointer
= '\0';
412 G
.redirect_size
= (ulg
)(G
.redirect_pointer
- G
.redirect_buffer
);
413 if ((G
.redirect_buffer
=
414 realloc(G
.redirect_buffer
, G
.redirect_size
+ 1)) == NULL
) {
428 /* Purpose: Determine if file in archive contains the string szSearch
430 Parameters: archive = archive name
431 file = file contained in the archive. This cannot be
432 a wild card to be meaningful
433 pattern = string to search for
434 cmd = 0 - case-insensitive search
435 1 - case-sensitve search
436 2 - case-insensitive, whole words only
437 3 - case-sensitive, whole words only
438 SkipBin = if true, skip any files that have control
439 characters other than CR, LF, or tab in the first
442 Returns: TRUE if a match is found
443 FALSE if no match is found
446 Comments: This does not pretend to be as useful as the standard
447 Unix grep, which returns the strings associated with a
448 particular pattern, nor does it search past the first
449 matching occurrence of the pattern.
452 int UZ_EXP
UzpGrep(char *archive
, char *file
, char *pattern
, int cmd
,
453 int SkipBin
, UzpCB
*UsrFuncts
)
455 int retcode
= FALSE
, compare
;
456 ulg i
, j
, patternLen
, buflen
;
461 memzero(&flgopts
, sizeof(UzpOpts
)); /* no special options */
463 if (!UzpUnzipToMemory(archive
, file
, &flgopts
, UsrFuncts
, &retstr
)) {
464 return -1; /* not enough memory, file not found, or other error */
468 if (retstr
.strlength
< 100)
469 buflen
= retstr
.strlength
;
472 for (i
= 0; i
< buflen
; i
++) {
473 if (iscntrl(retstr
.strptr
[i
])) {
474 if ((retstr
.strptr
[i
] != 0x0A) &&
475 (retstr
.strptr
[i
] != 0x0D) &&
476 (retstr
.strptr
[i
] != 0x09))
478 /* OK, we now think we have a binary file of some sort */
486 patternLen
= strlen(pattern
);
488 if (retstr
.strlength
< patternLen
) {
493 sz
= malloc(patternLen
+ 3); /* add two in case doing whole words only */
501 if ((cmd
== 0) || (cmd
== 2)) {
502 for (i
= 0; i
< strlen(sz
); i
++)
503 sz
[i
] = toupper(sz
[i
]);
504 for (i
= 0; i
< retstr
.strlength
; i
++)
505 retstr
.strptr
[i
] = toupper(retstr
.strptr
[i
]);
508 for (i
= 0; i
< (retstr
.strlength
- patternLen
); i
++) {
509 p
= &retstr
.strptr
[i
];
511 for (j
= 0; j
< patternLen
; j
++) {
512 /* We cannot do strncmp here, as we may be dealing with a
513 * "binary" file, such as a word processing file, or perhaps
514 * even a true executable of some sort. */
520 if (compare
== TRUE
) {
532 #endif /* !__16BIT__ */
537 int UZ_EXP
UzpValidate(char *archive
, int AllCodes
)
544 uO
.overwrite_none
= 0;
545 G
.extract_flag
= (!uO
.zipinfo_mode
&&
546 !uO
.cflag
&& !uO
.tflag
&& !uO
.vflag
&& !uO
.zflag
552 uO
.qflag
= 2; /* turn off all messages */
554 G
.pfnames
= (char **)&fnames
[0]; /* assign default filename vector */
556 Wiz_NoPrinting(TRUE
);
559 if (archive
== NULL
) { /* something is screwed up: no filename */
564 G
.wildzipfn
= (char *)malloc(FILNAMSIZ
+ 1);
565 strcpy(G
.wildzipfn
, archive
);
566 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
567 _ISO_INTERN(G
.wildzipfn
);
570 G
.process_all_files
= TRUE
; /* for speed */
572 retcode
= setjmp(dll_error_return
);
576 Wiz_NoPrinting(FALSE
);
583 retcode
= process_zipfiles(__G
);
587 Wiz_NoPrinting(FALSE
);
591 /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
592 archive, we should still be able to see the files inside it,
593 even if we can't decode them for some reason.
595 We also still want to be able to get at files even if there is
596 something odd about the zip archive, hence allow PK_WARN,
597 PK_FIND, IZ_UNSUP as well as PK_ERR
603 if ((retcode
== PK_OK
) || (retcode
== PK_WARN
) || (retcode
== PK_ERR
) ||
604 (retcode
== IZ_UNSUP
) || (retcode
== PK_FIND
))