]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/api.c
don't allow expanding/collapsing hidden root node
[wxWidgets.git] / utils / Install / sfxzip / api.c
1 /*---------------------------------------------------------------------------
2
3 api.c
4
5 This module supplies an UnZip engine for use directly from C/C++
6 programs. The functions are:
7
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);
16
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,
19 UzpCB *UsrFuncts);
20
21 OS/2 only (for now):
22 int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
23 char *cpExclude[]);
24
25 You must define `DLL' in order to include the API extensions.
26
27 ---------------------------------------------------------------------------*/
28
29
30 #ifdef OS2
31 # define INCL_DOSMEMMGR
32 # include <os2.h>
33 #endif
34 #include <setjmp.h>
35
36 #define UNZIP_INTERNAL
37 #include "unzip.h"
38 #include "version.h"
39 #ifdef WINDLL
40 # include "windll/windll.h"
41 #endif
42
43 #ifdef DLL /* This source file supplies DLL-only interface code. */
44
45 jmp_buf dll_error_return;
46
47 /*---------------------------------------------------------------------------
48 Documented API entry points
49 ---------------------------------------------------------------------------*/
50
51
52 UzpVer * UZ_EXP UzpVersion() /* should be pointer to const struct */
53 {
54 static UzpVer version; /* doesn't change between calls */
55
56
57 version.structlen = UZPVER_LEN;
58
59 #ifdef BETA
60 version.flag = 1;
61 #else
62 version.flag = 0;
63 #endif
64 version.betalevel = BETALEVEL;
65 version.date = VERSION_DATE;
66
67 #ifdef ZLIB_VERSION
68 version.zlib_version = ZLIB_VERSION;
69 version.flag |= 2;
70 #else
71 version.zlib_version = NULL;
72 #endif
73
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;
78
79 version.zipinfo.major = ZI_MAJORVER;
80 version.zipinfo.minor = ZI_MINORVER;
81 version.zipinfo.patchlevel = PATCHLEVEL;
82
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;
87
88 version.windll.major = UZ_MAJORVER;
89 version.windll.minor = UZ_MINORVER;
90 version.windll.patchlevel = PATCHLEVEL;
91
92 return &version;
93 }
94
95 void UZ_EXP UzpVersion2(UzpVer2 *version)
96 {
97
98 version->structlen = UZPVER_LEN;
99
100 #ifdef BETA
101 version->flag = 1;
102 #else
103 version->flag = 0;
104 #endif
105 strcpy(version->betalevel, BETALEVEL);
106 strcpy(version->date, VERSION_DATE);
107
108 #ifdef ZLIB_VERSION
109 strcpy(version->zlib_version, ZLIB_VERSION);
110 version->flag |= 2;
111 #else
112 version->zlib_version[0] = '\0';
113 #endif
114
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;
119
120 version->zipinfo.major = ZI_MAJORVER;
121 version->zipinfo.minor = ZI_MINORVER;
122 version->zipinfo.patchlevel = PATCHLEVEL;
123
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;
128
129 version->windll.major = UZ_MAJORVER;
130 version->windll.minor = UZ_MINORVER;
131 version->windll.patchlevel = PATCHLEVEL;
132 }
133
134
135
136
137
138 #ifndef WINDLL
139
140 int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
141 {
142 int r, (*dummyfn)();
143
144
145 CONSTRUCTGLOBALS();
146
147 if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
148 G.message = init->msgfn;
149
150 if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
151 G.input = init->inputfn;
152
153 if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
154 G.mpause = init->pausefn;
155
156 if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
157 (*init->userfn)(); /* allow void* arg? */
158
159 r = unzip(__G__ argc, argv);
160 DESTROYGLOBALS()
161 RETURN(r);
162 }
163
164 #endif /* !WINDLL */
165
166
167
168
169 #ifndef __16BIT__
170
171 void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
172 {
173 if (retstr->strptr != NULL) {
174 free(retstr->strptr);
175 retstr->strptr = NULL;
176 }
177 }
178
179
180
181
182 #ifndef WINDLL
183
184 static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
185
186 static int UzpDLL_Init(pG, UsrFuncts)
187 zvoid *pG;
188 UzpCB *UsrFuncts;
189 {
190 int (*dummyfn)();
191
192 if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
193 UsrFuncts->msgfn)
194 ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
195 else
196 return FALSE;
197
198 if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
199 UsrFuncts->inputfn)
200 ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
201
202 if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
203 UsrFuncts->pausefn)
204 ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
205
206 if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
207 UsrFuncts->passwdfn)
208 ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
209
210 if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
211 UsrFuncts->statrepfn)
212 ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
213
214 return TRUE;
215 }
216
217
218 int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
219 UzpCB *UsrFuncts, UzpBuffer *retstr)
220 {
221 int r;
222 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
223 char *intern_zip, *intern_file;
224 #endif
225
226 CONSTRUCTGLOBALS();
227 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
228 intern_zip = (char *)malloc(strlen(zip)+1);
229 if (intern_zip == NULL) {
230 DESTROYGLOBALS()
231 return PK_MEM;
232 }
233 intern_file = (char *)malloc(strlen(file)+1);
234 if (intern_file == NULL) {
235 DESTROYGLOBALS()
236 free(intern_zip);
237 return PK_MEM;
238 }
239 ISO_TO_INTERN(zip, intern_zip);
240 ISO_TO_INTERN(file, intern_file);
241 # define zip intern_zip
242 # define file intern_file
243 #endif
244 /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
245 * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
246 */
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 */
251
252 if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
253 DESTROYGLOBALS();
254 return PK_BADERR;
255 }
256 G.redirect_data = 1;
257
258 r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
259
260 DESTROYGLOBALS()
261 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
262 # undef file
263 # undef zip
264 free(intern_file);
265 free(intern_zip);
266 #endif
267 if (!r && retstr->strlength) {
268 free(retstr->strptr);
269 retstr->strptr = NULL;
270 }
271 return r;
272 }
273 #endif /* !WINDLL */
274 #endif /* !__16BIT__ */
275
276
277
278
279
280 #ifdef OS2DLL
281
282 int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
283 char *cpExclude[])
284 {
285 int r;
286
287 CONSTRUCTGLOBALS();
288 uO.qflag = 2;
289 uO.vflag = 1;
290 uO.C_flag = 1;
291 G.wildzipfn = name;
292 G.process_all_files = TRUE;
293 if (cpInclude) {
294 char **ptr = cpInclude;
295
296 while (*ptr != NULL) ptr++;
297 G.filespecs = ptr - cpInclude;
298 G.pfnames = cpInclude, G.process_all_files = FALSE;
299 }
300 if (cpExclude) {
301 char **ptr = cpExclude;
302
303 while (*ptr != NULL) ptr++;
304 G.xfilespecs = ptr - cpExclude;
305 G.pxnames = cpExclude, G.process_all_files = FALSE;
306 }
307
308 G.processExternally = callBack;
309 r = process_zipfiles(__G)==0;
310 DESTROYGLOBALS()
311 return r;
312 }
313
314 #endif /* OS2DLL */
315
316
317
318
319 /*---------------------------------------------------------------------------
320 Helper functions
321 ---------------------------------------------------------------------------*/
322
323
324 void setFileNotFound(__G)
325 __GDEF
326 {
327 G.filenotfound++;
328 }
329
330
331
332 int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
333 {
334 int r;
335 char *incname[2];
336
337 G.process_all_files = FALSE;
338 G.extract_flag = TRUE;
339 uO.qflag = 2;
340 G.wildzipfn = zip;
341
342 G.pfnames = incname;
343 incname[0] = file;
344 incname[1] = NULL;
345 G.filespecs = 1;
346
347 r = process_zipfiles(__G);
348 if (retstr) {
349 retstr->strptr = (char *)G.redirect_buffer;
350 retstr->strlength = G.redirect_size;
351 }
352 return r; /* returns `PK_???' error values */
353 }
354
355
356
357 int redirect_outfile(__G)
358 __GDEF
359 {
360 if (G.redirect_size != 0 || G.redirect_buffer != NULL)
361 return FALSE;
362
363 #ifndef NO_SLIDE_REDIR
364 G.redirect_slide = !G.pInfo->textmode;
365 #endif
366 G.redirect_size = (G.pInfo->textmode ?
367 G.lrec.ucsize * lenEOL : G.lrec.ucsize);
368 #ifdef OS2
369 DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
370 PAG_READ|PAG_WRITE|PAG_COMMIT);
371 G.redirect_pointer = G.redirect_buffer;
372 #else
373 #ifdef __16BIT__
374 if ((ulg)((extent)G.redirect_size) != G.redirect_size)
375 return FALSE;
376 #endif
377 G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1);
378 #endif
379 if (!G.redirect_buffer)
380 return FALSE;
381 G.redirect_pointer[G.redirect_size] = '\0';
382 return TRUE;
383 }
384
385
386
387 int writeToMemory(__GPRO__ uch *rawbuf, ulg size)
388 {
389 if (rawbuf != G.redirect_pointer)
390 memcpy(G.redirect_pointer,rawbuf,size);
391 G.redirect_pointer += size;
392 return 0;
393 }
394
395
396
397
398 int close_redirect(__G)
399 __GDEF
400 {
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) {
406 G.redirect_size = 0;
407 return EOF;
408 }
409 }
410 return 0;
411 }
412
413
414
415
416 #ifndef __16BIT__
417 #ifndef WINDLL
418
419 /* Purpose: Determine if file in archive contains the string szSearch
420
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
431 100 characters.
432
433 Returns: TRUE if a match is found
434 FALSE if no match is found
435 -1 on error
436
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.
441 */
442
443 int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
444 int SkipBin, UzpCB *UsrFuncts)
445 {
446 int retcode = FALSE, compare;
447 ulg i, j, patternLen, buflen;
448 char * sz, *p;
449 UzpOpts flgopts;
450 UzpBuffer retstr;
451
452 memzero(&flgopts, sizeof(UzpOpts)); /* no special options */
453
454 if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
455 return -1; /* not enough memory, file not found, or other error */
456 }
457
458 if (SkipBin) {
459 if (retstr.strlength < 100)
460 buflen = retstr.strlength;
461 else
462 buflen = 100;
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))
468 {
469 /* OK, we now think we have a binary file of some sort */
470 free(retstr.strptr);
471 return FALSE;
472 }
473 }
474 }
475 }
476
477 patternLen = strlen(pattern);
478
479 if (retstr.strlength < patternLen) {
480 free(retstr.strptr);
481 return FALSE;
482 }
483
484 sz = malloc(patternLen + 3); /* add two in case doing whole words only */
485 if (cmd > 1) {
486 strcpy(sz, " ");
487 strcat(sz, pattern);
488 strcat(sz, " ");
489 } else
490 strcpy(sz, pattern);
491
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]);
497 }
498
499 for (i = 0; i < (retstr.strlength - patternLen); i++) {
500 p = &retstr.strptr[i];
501 compare = TRUE;
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. */
506 if (p[j] != sz[j]) {
507 compare = FALSE;
508 break;
509 }
510 }
511 if (compare == TRUE) {
512 retcode = TRUE;
513 break;
514 }
515 }
516
517 free(sz);
518 free(retstr.strptr);
519
520 return retcode;
521 }
522 #endif /* !WINDLL */
523 #endif /* !__16BIT__ */
524
525
526
527
528 int UZ_EXP UzpValidate(char *archive, int AllCodes)
529 {
530 int retcode;
531 CONSTRUCTGLOBALS();
532
533 uO.jflag = 1;
534 uO.tflag = 1;
535 uO.overwrite_none = 0;
536 G.extract_flag = (!uO.zipinfo_mode &&
537 !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
538 #ifdef TIMESTAMP
539 && !uO.T_flag
540 #endif
541 );
542
543 uO.qflag = 2; /* turn off all messages */
544 G.fValidate = TRUE;
545 G.pfnames = (char **)&fnames[0]; /* assign default filename vector */
546 #ifdef WINDLL
547 Wiz_NoPrinting(TRUE);
548 #endif
549
550 if (archive == NULL) { /* something is screwed up: no filename */
551 DESTROYGLOBALS();
552 return PK_NOZIP;
553 }
554
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);
559 #endif
560
561 G.process_all_files = TRUE; /* for speed */
562
563 retcode = setjmp(dll_error_return);
564
565 if (retcode) {
566 #ifdef WINDLL
567 Wiz_NoPrinting(FALSE);
568 #endif
569 free(G.wildzipfn);
570 DESTROYGLOBALS();
571 return PK_BADERR;
572 }
573
574 retcode = process_zipfiles(__G);
575
576 free(G.wildzipfn);
577 #ifdef WINDLL
578 Wiz_NoPrinting(FALSE);
579 #endif
580 DESTROYGLOBALS();
581
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.
585
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
589 */
590
591 if (AllCodes)
592 return retcode;
593
594 if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
595 (retcode == IZ_UNSUP) || (retcode == PK_FIND))
596 return TRUE;
597 else
598 return FALSE;
599 }
600
601 #endif /* DLL */