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