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