home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / api.c next >
C/C++ Source or Header  |  1998-11-22  |  15KB  |  602 lines

  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 */
  602.