api.c
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:15k
源码类别:

压缩解压

开发平台:

MultiPlatform

  1. /*---------------------------------------------------------------------------
  2.   api.c
  3.   This module supplies an UnZip engine for use directly from C/C++
  4.   programs.  The functions are:
  5.     UzpVer *UzpVersion(void);
  6.     void UzpVersion2(UzpVer2 *version)
  7.     int UzpMain(int argc, char *argv[]);
  8.     int UzpAltMain(int argc, char *argv[], UzpInit *init);
  9.     int UzpValidate(char *archive, int AllCodes);
  10.     void UzpFreeMemBuffer(UzpBuffer *retstr);
  11.     int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
  12.                          UzpCB *UsrFuncts, UzpBuffer *retstr);
  13.   non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
  14.     int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
  15.                 UzpCB *UsrFuncts);
  16.   OS/2 only (for now):
  17.     int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
  18.           char *cpExclude[]);
  19.   You must define `DLL' in order to include the API extensions.
  20.   ---------------------------------------------------------------------------*/
  21. #ifdef OS2
  22. #  define  INCL_DOSMEMMGR
  23. #  include <os2.h>
  24. #endif
  25. #include <setjmp.h>
  26. #define UNZIP_INTERNAL
  27. #include "unzip.h"
  28. #include "version.h"
  29. #ifdef WINDLL
  30. #  include "windll/windll.h"
  31. #endif
  32. #ifdef DLL      /* This source file supplies DLL-only interface code. */
  33. jmp_buf dll_error_return;
  34. /*---------------------------------------------------------------------------
  35.     Documented API entry points
  36.   ---------------------------------------------------------------------------*/
  37. UzpVer * UZ_EXP UzpVersion()   /* should be pointer to const struct */
  38. {
  39.     static UzpVer version;     /* doesn't change between calls */
  40.     version.structlen = UZPVER_LEN;
  41. #ifdef BETA
  42.     version.flag = 1;
  43. #else
  44.     version.flag = 0;
  45. #endif
  46.     version.betalevel = BETALEVEL;
  47.     version.date = VERSION_DATE;
  48. #ifdef ZLIB_VERSION
  49.     version.zlib_version = ZLIB_VERSION;
  50.     version.flag |= 2;
  51. #else
  52.     version.zlib_version = NULL;
  53. #endif
  54.     /* someday each of these may have a separate patchlevel: */
  55.     version.unzip.major = UZ_MAJORVER;
  56.     version.unzip.minor = UZ_MINORVER;
  57.     version.unzip.patchlevel = PATCHLEVEL;
  58.     version.zipinfo.major = ZI_MAJORVER;
  59.     version.zipinfo.minor = ZI_MINORVER;
  60.     version.zipinfo.patchlevel = PATCHLEVEL;
  61.     /* these are retained for backward compatibility only: */
  62.     version.os2dll.major = UZ_MAJORVER;
  63.     version.os2dll.minor = UZ_MINORVER;
  64.     version.os2dll.patchlevel = PATCHLEVEL;
  65.     version.windll.major = UZ_MAJORVER;
  66.     version.windll.minor = UZ_MINORVER;
  67.     version.windll.patchlevel = PATCHLEVEL;
  68.     return &version;
  69. }
  70. void UZ_EXP UzpVersion2(UzpVer2 *version)
  71. {
  72.     version->structlen = UZPVER_LEN;
  73. #ifdef BETA
  74.     version->flag = 1;
  75. #else
  76.     version->flag = 0;
  77. #endif
  78.     strcpy(version->betalevel, BETALEVEL);
  79.     strcpy(version->date, VERSION_DATE);
  80. #ifdef ZLIB_VERSION
  81.     strcpy(version->zlib_version, ZLIB_VERSION);
  82.     version->flag |= 2;
  83. #else
  84.     version->zlib_version[0] = '';
  85. #endif
  86.     /* someday each of these may have a separate patchlevel: */
  87.     version->unzip.major = UZ_MAJORVER;
  88.     version->unzip.minor = UZ_MINORVER;
  89.     version->unzip.patchlevel = PATCHLEVEL;
  90.     version->zipinfo.major = ZI_MAJORVER;
  91.     version->zipinfo.minor = ZI_MINORVER;
  92.     version->zipinfo.patchlevel = PATCHLEVEL;
  93.     /* these are retained for backward compatibility only: */
  94.     version->os2dll.major = UZ_MAJORVER;
  95.     version->os2dll.minor = UZ_MINORVER;
  96.     version->os2dll.patchlevel = PATCHLEVEL;
  97.     version->windll.major = UZ_MAJORVER;
  98.     version->windll.minor = UZ_MINORVER;
  99.     version->windll.patchlevel = PATCHLEVEL;
  100. }
  101. #ifndef WINDLL
  102. int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
  103. {
  104.     int r, (*dummyfn)();
  105.     CONSTRUCTGLOBALS();
  106.     if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
  107.         G.message = init->msgfn;
  108.     if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
  109.         G.input = init->inputfn;
  110.     if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
  111.         G.mpause = init->pausefn;
  112.     if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
  113.         (*init->userfn)();    /* allow void* arg? */
  114.     r = unzip(__G__ argc, argv);
  115.     DESTROYGLOBALS()
  116.     RETURN(r);
  117. }
  118. #endif /* !WINDLL */
  119. #ifndef __16BIT__
  120. void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
  121. {
  122.     if (retstr->strptr != NULL) {
  123.         free(retstr->strptr);
  124.         retstr->strptr = NULL;
  125.     }
  126. }
  127. #ifndef WINDLL
  128. static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
  129. static int UzpDLL_Init(pG, UsrFuncts)
  130. zvoid *pG;
  131. UzpCB *UsrFuncts;
  132. {
  133.     int (*dummyfn)();
  134.     if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
  135.         UsrFuncts->msgfn)
  136.         ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
  137.     else
  138.         return FALSE;
  139.     if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
  140.         UsrFuncts->inputfn)
  141.         ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
  142.     if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
  143.         UsrFuncts->pausefn)
  144.         ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
  145.     if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
  146.         UsrFuncts->passwdfn)
  147.         ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
  148.     if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
  149.         UsrFuncts->statrepfn)
  150.         ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
  151.     return TRUE;
  152. }
  153. int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
  154.     UzpCB *UsrFuncts, UzpBuffer *retstr)
  155. {
  156.     int r;
  157. #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
  158.     char *intern_zip, *intern_file;
  159. #endif
  160.     CONSTRUCTGLOBALS();
  161. #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
  162.     intern_zip = (char *)malloc(strlen(zip)+1);
  163.     if (intern_zip == NULL) {
  164.        DESTROYGLOBALS()
  165.        return PK_MEM;
  166.     }
  167.     intern_file = (char *)malloc(strlen(file)+1);
  168.     if (intern_file == NULL) {
  169.        DESTROYGLOBALS()
  170.        free(intern_zip);
  171.        return PK_MEM;
  172.     }
  173.     ISO_TO_INTERN(zip, intern_zip);
  174.     ISO_TO_INTERN(file, intern_file);
  175. #   define zip intern_zip
  176. #   define file intern_file
  177. #endif
  178.     /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
  179.      * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
  180.      */
  181.     uO.pwdarg = optflgs->pwdarg;
  182.     uO.aflag = optflgs->aflag;
  183.     uO.C_flag = optflgs->C_flag;
  184.     uO.qflag = optflgs->qflag;  /* currently,  overridden in unzipToMemory */
  185.     if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
  186.        DESTROYGLOBALS();
  187.        return PK_BADERR;
  188.     }
  189.     G.redirect_data = 1;
  190.     r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
  191.     DESTROYGLOBALS()
  192. #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
  193. #  undef file
  194. #  undef zip
  195.     free(intern_file);
  196.     free(intern_zip);
  197. #endif
  198.     if (!r && retstr->strlength) {
  199.        free(retstr->strptr);
  200.        retstr->strptr = NULL;
  201.     }
  202.     return r;
  203. }
  204. #endif /* !WINDLL */
  205. #endif /* !__16BIT__ */
  206. #ifdef OS2DLL
  207. int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
  208.                 char *cpExclude[])
  209. {
  210.     int r;
  211.     CONSTRUCTGLOBALS();
  212.     uO.qflag = 2;
  213.     uO.vflag = 1;
  214.     uO.C_flag = 1;
  215.     G.wildzipfn = name;
  216.     G.process_all_files = TRUE;
  217.     if (cpInclude) {
  218.         char **ptr = cpInclude;
  219.         while (*ptr != NULL) ptr++;
  220.         G.filespecs = ptr - cpInclude;
  221.         G.pfnames = cpInclude, G.process_all_files = FALSE;
  222.     }
  223.     if (cpExclude) {
  224.         char **ptr = cpExclude;
  225.         while (*ptr != NULL) ptr++;
  226.         G.xfilespecs = ptr - cpExclude;
  227.         G.pxnames = cpExclude, G.process_all_files = FALSE;
  228.     }
  229.     G.processExternally = callBack;
  230.     r = process_zipfiles(__G)==0;
  231.     DESTROYGLOBALS()
  232.     return r;
  233. }
  234. #endif /* OS2DLL */
  235. /*---------------------------------------------------------------------------
  236.     Helper functions
  237.   ---------------------------------------------------------------------------*/
  238. void setFileNotFound(__G)
  239.     __GDEF
  240. {
  241.     G.filenotfound++;
  242. }
  243. int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
  244. {
  245.     int r;
  246.     char *incname[2];
  247.     G.process_all_files = FALSE;
  248.     G.extract_flag = TRUE;
  249.     uO.qflag = 2;
  250.     G.wildzipfn = zip;
  251.     G.pfnames = incname;
  252.     incname[0] = file;
  253.     incname[1] = NULL;
  254.     G.filespecs = 1;
  255.     r = process_zipfiles(__G);
  256.     if (retstr) {
  257.         retstr->strptr = (char *)G.redirect_buffer;
  258.         retstr->strlength = G.redirect_size;
  259.     }
  260.     return r;                   /* returns `PK_???' error values */
  261. }
  262. int redirect_outfile(__G)
  263.      __GDEF
  264. {
  265.     if (G.redirect_size != 0 || G.redirect_buffer != NULL)
  266.         return FALSE;
  267. #ifndef NO_SLIDE_REDIR
  268.     G.redirect_slide = !G.pInfo->textmode;
  269. #endif
  270.     G.redirect_size = (G.pInfo->textmode ?
  271.                        G.lrec.ucsize * lenEOL : G.lrec.ucsize);
  272. #ifdef OS2
  273.     DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
  274.       PAG_READ|PAG_WRITE|PAG_COMMIT);
  275.     G.redirect_pointer = G.redirect_buffer;
  276. #else
  277. #ifdef __16BIT__
  278.     if ((ulg)((extent)G.redirect_size) != G.redirect_size)
  279.         return FALSE;
  280. #endif
  281.     G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1);
  282. #endif
  283.     if (!G.redirect_buffer)
  284.         return FALSE;
  285.     G.redirect_pointer[G.redirect_size] = '';
  286.     return TRUE;
  287. }
  288. int writeToMemory(__GPRO__ uch *rawbuf, ulg size)
  289. {
  290.     if (rawbuf != G.redirect_pointer)
  291.         memcpy(G.redirect_pointer,rawbuf,size);
  292.     G.redirect_pointer += size;
  293.     return 0;
  294. }
  295. int close_redirect(__G)
  296.      __GDEF
  297. {
  298.     if (G.pInfo->textmode) {
  299.         *G.redirect_pointer = '';
  300.         G.redirect_size = G.redirect_pointer - G.redirect_buffer;
  301.         if ((G.redirect_buffer =
  302.              realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
  303.             G.redirect_size = 0;
  304.             return EOF;
  305.         }
  306.     }
  307.     return 0;
  308. }
  309. #ifndef __16BIT__
  310. #ifndef WINDLL
  311. /* Purpose: Determine if file in archive contains the string szSearch
  312.    Parameters: archive  = archive name
  313.                file     = file contained in the archive. This cannot be
  314.                           a wild card to be meaningful
  315.                pattern  = string to search for
  316.                cmd      = 0 - case-insensitive search
  317.                           1 - case-sensitve search
  318.                           2 - case-insensitive, whole words only
  319.                           3 - case-sensitive, whole words only
  320.                SkipBin  = if true, skip any files that have control
  321.                           characters other than CR, LF, or tab in the first
  322.                           100 characters.
  323.    Returns:    TRUE if a match is found
  324.                FALSE if no match is found
  325.                -1 on error
  326.    Comments: This does not pretend to be as useful as the standard
  327.              Unix grep, which returns the strings associated with a
  328.              particular pattern, nor does it search past the first
  329.              matching occurrence of the pattern.
  330.  */
  331. int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
  332.                    int SkipBin, UzpCB *UsrFuncts)
  333. {
  334.     int retcode = FALSE, compare;
  335.     ulg i, j, patternLen, buflen;
  336.     char * sz, *p;
  337.     UzpOpts flgopts;
  338.     UzpBuffer retstr;
  339.     memzero(&flgopts, sizeof(UzpOpts));         /* no special options */
  340.     if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
  341.        return -1;   /* not enough memory, file not found, or other error */
  342.     }
  343.     if (SkipBin) {
  344.         if (retstr.strlength < 100)
  345.             buflen = retstr.strlength;
  346.         else
  347.             buflen = 100;
  348.         for (i = 0; i < buflen; i++) {
  349.             if (iscntrl(retstr.strptr[i])) {
  350.                 if ((retstr.strptr[i] != 0x0A) &&
  351.                     (retstr.strptr[i] != 0x0D) &&
  352.                     (retstr.strptr[i] != 0x09))
  353.                 {
  354.                     /* OK, we now think we have a binary file of some sort */
  355.                     free(retstr.strptr);
  356.                     return FALSE;
  357.                 }
  358.             }
  359.         }
  360.     }
  361.     patternLen = strlen(pattern);
  362.     if (retstr.strlength < patternLen) {
  363.         free(retstr.strptr);
  364.         return FALSE;
  365.     }
  366.     sz = malloc(patternLen + 3); /* add two in case doing whole words only */
  367.     if (cmd > 1) {
  368.         strcpy(sz, " ");
  369.         strcat(sz, pattern);
  370.         strcat(sz, " ");
  371.     } else
  372.         strcpy(sz, pattern);
  373.     if ((cmd == 0) || (cmd == 2)) {
  374.         for (i = 0; i < strlen(sz); i++)
  375.             sz[i] = toupper(sz[i]);
  376.         for (i = 0; i < retstr.strlength; i++)
  377.             retstr.strptr[i] = toupper(retstr.strptr[i]);
  378.     }
  379.     for (i = 0; i < (retstr.strlength - patternLen); i++) {
  380.         p = &retstr.strptr[i];
  381.         compare = TRUE;
  382.         for (j = 0; j < patternLen; j++) {
  383.             /* We cannot do strncmp here, as we may be dealing with a
  384.              * "binary" file, such as a word processing file, or perhaps
  385.              * even a true executable of some sort. */
  386.             if (p[j] != sz[j]) {
  387.                 compare = FALSE;
  388.                 break;
  389.             }
  390.         }
  391.         if (compare == TRUE) {
  392.             retcode = TRUE;
  393.             break;
  394.         }
  395.     }
  396.     free(sz);
  397.     free(retstr.strptr);
  398.     return retcode;
  399. }
  400. #endif /* !WINDLL */
  401. #endif /* !__16BIT__ */
  402. int UZ_EXP UzpValidate(char *archive, int AllCodes)
  403. {
  404.     int retcode;
  405.     CONSTRUCTGLOBALS();
  406.     uO.jflag = 1;
  407.     uO.tflag = 1;
  408.     uO.overwrite_none = 0;
  409.     G.extract_flag = (!uO.zipinfo_mode &&
  410.                       !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
  411. #ifdef TIMESTAMP
  412.                       && !uO.T_flag
  413. #endif
  414.                      );
  415.     uO.qflag = 2;                        /* turn off all messages */
  416.     G.fValidate = TRUE;
  417.     G.pfnames = (char **)&fnames[0];    /* assign default filename vector */
  418. #ifdef WINDLL
  419.     Wiz_NoPrinting(TRUE);
  420. #endif
  421.     if (archive == NULL) {      /* something is screwed up:  no filename */
  422.         DESTROYGLOBALS();
  423.         return PK_NOZIP;
  424.     }
  425.     G.wildzipfn = (char *)malloc(FILNAMSIZ + 1);
  426.     strcpy(G.wildzipfn, archive);
  427. #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
  428.     _ISO_INTERN(G.wildzipfn);
  429. #endif
  430.     G.process_all_files = TRUE;         /* for speed */
  431.     retcode = setjmp(dll_error_return);
  432.     if (retcode) {
  433. #ifdef WINDLL
  434.         Wiz_NoPrinting(FALSE);
  435. #endif
  436.         free(G.wildzipfn);
  437.         DESTROYGLOBALS();
  438.         return PK_BADERR;
  439.     }
  440.     retcode = process_zipfiles(__G);
  441.     free(G.wildzipfn);
  442. #ifdef WINDLL
  443.     Wiz_NoPrinting(FALSE);
  444. #endif
  445.     DESTROYGLOBALS();
  446.     /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
  447.        archive, we should still be able to see the files inside it,
  448.        even if we can't decode them for some reason.
  449.        We also still want to be able to get at files even if there is
  450.        something odd about the zip archive, hence allow PK_WARN,
  451.        PK_FIND, IZ_UNSUP as well as PK_ERR
  452.      */
  453.     if (AllCodes)
  454.         return retcode;
  455.     if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
  456.         (retcode == IZ_UNSUP) || (retcode == PK_FIND))
  457.         return TRUE;
  458.     else
  459.         return FALSE;
  460. }
  461. #endif /* DLL */