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

压缩解压

开发平台:

MultiPlatform

  1. /*---------------------------------------------------------------------------
  2.   extract.c
  3.   This file contains the high-level routines ("driver routines") for extrac-
  4.   ting and testing zipfile members.  It calls the low-level routines in files
  5.   explode.c, inflate.c, unreduce.c and unshrink.c.
  6.   Contains:  extract_or_test_files()
  7.              store_info()
  8.              extract_or_test_member()
  9.              TestExtraField()
  10.              test_compr_eb()
  11.              memextract()
  12.              memflush()
  13.              fnfilter()
  14.   ---------------------------------------------------------------------------*/
  15. #define EXTRACT_C
  16. #define UNZIP_INTERNAL
  17. #include "unzip.h"
  18. #include "crypt.h"
  19. #ifdef WINDLL
  20. #  ifdef POCKET_UNZIP
  21. #    include "wince/intrface.h"
  22. #  else
  23. #    include "windll/windll.h"
  24. #  endif
  25. #endif
  26. #define GRRDUMP(buf,len) { 
  27.     int i, j; 
  28.  
  29.     for (j = 0;  j < (len)/16;  ++j) { 
  30.         printf("        "); 
  31.         for (i = 0;  i < 16;  ++i) 
  32.             printf("%02x ", (uch)(buf)[i+(j<<4)]); 
  33.         printf("n        "); 
  34.         for (i = 0;  i < 16;  ++i) { 
  35.             char c = (char)(buf)[i+(j<<4)]; 
  36.  
  37.             if (c == 'n') 
  38.                 printf("\n "); 
  39.             else if (c == 'r') 
  40.                 printf("\r "); 
  41.             else 
  42.                 printf(" %c ", c); 
  43.         } 
  44.         printf("n"); 
  45.     } 
  46.     if ((len) % 16) { 
  47.         printf("        "); 
  48.         for (i = j<<4;  i < (len);  ++i) 
  49.             printf("%02x ", (uch)(buf)[i]); 
  50.         printf("n        "); 
  51.         for (i = j<<4;  i < (len);  ++i) { 
  52.             char c = (char)(buf)[i]; 
  53.  
  54.             if (c == 'n') 
  55.                 printf("\n "); 
  56.             else if (c == 'r') 
  57.                 printf("\r "); 
  58.             else 
  59.                 printf(" %c ", c); 
  60.         } 
  61.         printf("n"); 
  62.     } 
  63. }
  64. static int store_info OF((__GPRO));
  65. static int extract_or_test_member OF((__GPRO));
  66. #ifndef SFX
  67.    static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
  68.    static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
  69.         unsigned compr_offset,
  70.         int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
  71.                               uch *eb_ucptr, ulg eb_ucsize)));
  72. #endif
  73. #ifdef SET_DIR_ATTRIB
  74.    static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
  75. #endif
  76. /*******************************/
  77. /*  Strings used in extract.c  */
  78. /*******************************/
  79. static ZCONST char Far VersionMsg[] =
  80.   "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)n";
  81. static ZCONST char Far ComprMsgNum[] =
  82.   "   skipping: %-22s  unsupported compression method %un";
  83. #ifndef SFX
  84.    static ZCONST char Far ComprMsgName[] =
  85.      "   skipping: %-22s  `%s' method not supportedn";
  86.    static ZCONST char Far CmprNone[]       = "store";
  87.    static ZCONST char Far CmprShrink[]     = "shrink";
  88.    static ZCONST char Far CmprReduce[]     = "reduce";
  89.    static ZCONST char Far CmprImplode[]    = "implode";
  90.    static ZCONST char Far CmprTokenize[]   = "tokenize";
  91.    static ZCONST char Far CmprDeflate[]    = "deflate";
  92.    static ZCONST char Far CmprEnDeflate[]  = "enhanced deflate";
  93.    static ZCONST char Far CmprDCLImplode[] = "DCL implode";
  94.    static ZCONST char Far *ComprNames[NUM_METHODS] = {
  95.      CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
  96.      CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
  97.    };
  98. #endif /* !SFX */
  99. static ZCONST char Far FilNamMsg[] =
  100.   "%s:  bad filename length (%s)n";
  101. static ZCONST char Far ExtFieldMsg[] =
  102.   "%s:  bad extra field length (%s)n";
  103. static ZCONST char Far OffsetMsg[] =
  104.   "file #%u:  bad zipfile offset (%s):  %ldn";
  105. static ZCONST char Far ExtractMsg[] =
  106.   "%8sing: %-22s  %s%s";
  107. #ifndef SFX
  108.    static ZCONST char Far LengthMsg[] =
  109.      "%s  %s:  %ld bytes required to uncompress to %lu bytes;n    %s
  110.       supposed to require %lu bytes%s%s%sn";
  111. #endif
  112. static ZCONST char Far BadFileCommLength[] = "%s:  bad file comment lengthn";
  113. static ZCONST char Far LocalHdrSig[] = "local header sig";
  114. static ZCONST char Far BadLocalHdr[] = "file #%u:  bad local headern";
  115. static ZCONST char Far AttemptRecompensate[] =
  116.   "  (attempting to re-compensate)n";
  117. #ifndef SFX
  118.    static ZCONST char Far BackslashPathSep[] =
  119.      "warning:  %s appears to use backslashes as path separatorsn";
  120. #endif
  121. static ZCONST char Far SkipVolumeLabel[] =
  122.   "   skipping: %-22s  %svolume labeln";
  123. #ifdef SET_DIR_ATTRIB  /* messages of code for setting directory attributes */
  124.    static ZCONST char Far DirlistEntryNoMem[] =
  125.      "warning:  cannot alloc memory for dir times/permissions/UID/GIDn";
  126.    static ZCONST char Far DirlistSortNoMem[] =
  127.      "warning:  cannot alloc memory to sort dir times/perms/etc.n";
  128.    static ZCONST char Far DirlistSetAttrFailed[] =
  129.      "warning:  set times/attribs failed for %sn";
  130. #endif
  131. #ifndef WINDLL
  132.    static ZCONST char Far ReplaceQuery[] =
  133.      "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  134.    static ZCONST char Far AssumeNone[] = " NULLn(assuming [N]one)n";
  135.    static ZCONST char Far NewNameQuery[] = "new name: ";
  136.    static ZCONST char Far InvalidResponse[] = "error:  invalid response [%c]n";
  137. #endif /* !WINDLL */
  138. static ZCONST char Far ErrorInArchive[] =
  139.   "At least one %serror was detected in %s.n";
  140. static ZCONST char Far ZeroFilesTested[] =
  141.   "Caution:  zero files tested in %s.n";
  142. #ifndef VMS
  143.    static ZCONST char Far VMSFormatQuery[] =
  144.      "n%s:  stored in VMS format.  Extract anyway? (y/n) ";
  145. #endif
  146. #if CRYPT
  147.    static ZCONST char Far SkipCannotGetPasswd[] =
  148.      "   skipping: %-22s  unable to get passwordn";
  149.    static ZCONST char Far SkipIncorrectPasswd[] =
  150.      "   skipping: %-22s  incorrect passwordn";
  151.    static ZCONST char Far FilesSkipBadPasswd[] =
  152.      "%u file%s skipped because of incorrect password.n";
  153.    static ZCONST char Far MaybeBadPasswd[] =
  154.      "    (may instead be incorrect password)n";
  155. #else
  156.    static ZCONST char Far SkipEncrypted[] =
  157.      "   skipping: %-22s  encrypted (not supported)n";
  158. #endif
  159. static ZCONST char Far NoErrInCompData[] =
  160.   "No errors detected in compressed data of %s.n";
  161. static ZCONST char Far NoErrInTestedFiles[] =
  162.   "No errors detected in %s for the %u file%s tested.n";
  163. static ZCONST char Far FilesSkipped[] =
  164.   "%u file%s skipped because of unsupported compression or encoding.n";
  165. static ZCONST char Far ErrUnzipFile[] = "  error:  %s%s %sn";
  166. static ZCONST char Far ErrUnzipNoFile[] = "n  error:  %s%sn";
  167. static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
  168. static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
  169. static ZCONST char Far Inflate[] = "inflate";
  170. #ifndef SFX
  171.    static ZCONST char Far Explode[] = "explode";
  172. #ifndef LZW_CLEAN
  173.    static ZCONST char Far Unshrink[] = "unshrink";
  174. #endif
  175. #endif
  176. #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
  177.    static ZCONST char Far FileTruncated[] =
  178.      "warning:  %s is probably truncatedn";
  179. #endif
  180. static ZCONST char Far FileUnknownCompMethod[] =
  181.   "%s:  unknown compression methodn";
  182. static ZCONST char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)n";
  183.       /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
  184. char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
  185. char ZCONST Far TruncNTSD[] =
  186.   " compressed WinNT security data missing (%d bytes)%s";
  187. #ifndef SFX
  188.    static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:n 
  189.      EF block length (%u bytes) exceeds remaining EF data (%u bytes)n";
  190.    static ZCONST char Far InvalidComprDataEAs[] =
  191.      " invalid compressed data for EAsn";
  192. #  if (defined(WIN32) && defined(NTSD_EAS))
  193.      static ZCONST char Far InvalidSecurityEAs[] =
  194.        " EAs fail security checkn";
  195. #  endif
  196.    static ZCONST char Far UnsuppNTSDVersEAs[] =
  197.      " unsupported NTSD EAs version %dn";
  198.    static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributesn";
  199.    static ZCONST char Far UnknComprMethodEAs[] =
  200.      " unknown compression method for EAs (%u)n";
  201.    static ZCONST char Far NotEnoughMemEAs[] =
  202.      " out of memory while inflating EAsn";
  203.    static ZCONST char Far UnknErrorEAs[] =
  204.      " unknown error on extended attributesn";
  205. #endif /* !SFX */
  206. static ZCONST char Far UnsupportedExtraField[] =
  207.   "nerror:  unsupported extra-field compression type (%u)--skippingn";
  208. static ZCONST char Far BadExtraFieldCRC[] =
  209.   "error [%s]:  bad extra-field CRC %08lx (should be %08lx)n";
  210. /**************************************/
  211. /*  Function extract_or_test_files()  */
  212. /**************************************/
  213. int extract_or_test_files(__G)    /* return PK-type error code */
  214.      __GDEF
  215. {
  216.     uch *cd_inptr;
  217.     unsigned i, j, filnum=0, blknum=0;
  218.     int cd_incnt, renamed, query;
  219.     int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
  220. #ifdef WINDLL
  221.     int done_once = 0;
  222. #else
  223.     extent len;
  224. #endif
  225.     unsigned members_remaining, num_skipped=0, num_bad_pwd=0;
  226.     long cd_bufstart, bufstart, inbuf_offset, request;
  227.     LONGINT old_extra_bytes = 0L;
  228. #ifdef SET_DIR_ATTRIB
  229.     unsigned num_dirs=0;
  230.     dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
  231. #endif
  232. /*---------------------------------------------------------------------------
  233.     The basic idea of this function is as follows.  Since the central di-
  234.     rectory lies at the end of the zipfile and the member files lie at the
  235.     beginning or middle or wherever, it is not very desirable to simply
  236.     read a central directory entry, jump to the member and extract it, and
  237.     then jump back to the central directory.  In the case of a large zipfile
  238.     this would lead to a whole lot of disk-grinding, especially if each mem-
  239.     ber file is small.  Instead, we read from the central directory the per-
  240.     tinent information for a block of files, then go extract/test the whole
  241.     block.  Thus this routine contains two small(er) loops within a very
  242.     large outer loop:  the first of the small ones reads a block of files
  243.     from the central directory; the second extracts or tests each file; and
  244.     the outer one loops over blocks.  There's some file-pointer positioning
  245.     stuff in between, but that's about it.  Btw, it's because of this jump-
  246.     ing around that we can afford to be lenient if an error occurs in one of
  247.     the member files:  we should still be able to go find the other members,
  248.     since we know the offset of each from the beginning of the zipfile.
  249.   ---------------------------------------------------------------------------*/
  250.     G.pInfo = G.info;
  251.     members_remaining = (unsigned)G.ecrec.total_entries_central_dir;
  252. #if CRYPT
  253.     G.newzip = TRUE;
  254. #endif
  255. #ifndef SFX
  256.     G.reported_backslash = FALSE;
  257. #endif
  258.     /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
  259.     if (G.filespecs > 0  &&
  260.         (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
  261.         for (i = 0;  i < G.filespecs;  ++i)
  262.             fn_matched[i] = FALSE;
  263.     if (G.xfilespecs > 0  &&
  264.         (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
  265.         for (i = 0;  i < G.xfilespecs;  ++i)
  266.             xn_matched[i] = FALSE;
  267. /*---------------------------------------------------------------------------
  268.     Begin main loop over blocks of member files.  We know the entire central
  269.     directory is on this disk:  we would not have any of this information un-
  270.     less the end-of-central-directory record was on this disk, and we would
  271.     not have gotten to this routine unless this is also the disk on which
  272.     the central directory starts.  In practice, this had better be the ONLY
  273.     disk in the archive, but we'll add multi-disk support soon.
  274.   ---------------------------------------------------------------------------*/
  275.     while (members_remaining) {
  276.         j = 0;
  277. #ifdef AMIGA
  278.         memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
  279. #endif
  280.         /*
  281.          * Loop through files in central directory, storing offsets, file
  282.          * attributes, case-conversion and text-conversion flags until block
  283.          * size is reached.
  284.          */
  285.         while (members_remaining && (j < DIR_BLKSIZ)) {
  286.             --members_remaining;
  287.             G.pInfo = &G.info[j];
  288.             if (readbuf(__G__ G.sig, 4) == 0) {
  289.                 error_in_archive = PK_EOF;
  290.                 members_remaining = 0;  /* ...so no more left to do */
  291.                 break;
  292.             }
  293.             if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
  294.                 Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
  295.                   j + blknum*DIR_BLKSIZ + 1));
  296.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  297.                 error_in_archive = PK_BADERR;
  298.                 members_remaining = 0;  /* ...so no more left to do */
  299.                 break;
  300.             }
  301.             /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  302.             if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
  303.                 error_in_archive = error;   /* only PK_EOF defined */
  304.                 members_remaining = 0;  /* ...so no more left to do */
  305.                 break;
  306.             }
  307.             if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
  308.                  PK_COOL)
  309.             {
  310.                 if (error > error_in_archive)
  311.                     error_in_archive = error;
  312.                 if (error > PK_WARN) {  /* fatal:  no more left to do */
  313.                     Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  314.                       FnFilter1(G.filename), "central"));
  315.                     members_remaining = 0;
  316.                     break;
  317.                 }
  318.             }
  319.             if ((error = do_string(__G__ G.crec.extra_field_length,
  320.                 EXTRA_FIELD)) != 0)
  321.             {
  322.                 if (error > error_in_archive)
  323.                     error_in_archive = error;
  324.                 if (error > PK_WARN) {  /* fatal */
  325.                     Info(slide, 0x401, ((char *)slide,
  326.                       LoadFarString(ExtFieldMsg),
  327.                       FnFilter1(G.filename), "central"));
  328.                     members_remaining = 0;
  329.                     break;
  330.                 }
  331.             }
  332. #ifdef AMIGA
  333.             G.filenote_slot = j;
  334.             if ((error = do_string(__G__ G.crec.file_comment_length,
  335.                                    uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
  336. #else
  337.             if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
  338.                 != PK_COOL)
  339. #endif
  340.             {
  341.                 if (error > error_in_archive)
  342.                     error_in_archive = error;
  343.                 if (error > PK_WARN) {  /* fatal */
  344.                     Info(slide, 0x421, ((char *)slide,
  345.                       LoadFarString(BadFileCommLength),
  346.                       FnFilter1(G.filename)));
  347.                     members_remaining = 0;
  348.                     break;
  349.                 }
  350.             }
  351.             if (G.process_all_files) {
  352.                 if (store_info(__G))
  353.                     ++j;  /* file is OK; info[] stored; continue with next */
  354.                 else
  355.                     ++num_skipped;
  356.             } else {
  357.                 int   do_this_file;
  358.                 if (G.filespecs == 0)
  359.                     do_this_file = TRUE;
  360.                 else {  /* check if this entry matches an `include' argument */
  361.                     do_this_file = FALSE;
  362.                     for (i = 0; i < G.filespecs; i++)
  363.                         if (match(G.filename, G.pfnames[i], uO.C_flag)) {
  364.                             do_this_file = TRUE;  /* ^-- ignore case or not? */
  365.                             if (fn_matched)
  366.                                 fn_matched[i] = TRUE;
  367.                             break;       /* found match, so stop looping */
  368.                         }
  369.                 }
  370.                 if (do_this_file) {  /* check if this is an excluded file */
  371.                     for (i = 0; i < G.xfilespecs; i++)
  372.                         if (match(G.filename, G.pxnames[i], uO.C_flag)) {
  373.                             do_this_file = FALSE; /* ^-- ignore case or not? */
  374.                             if (xn_matched)
  375.                                 xn_matched[i] = TRUE;
  376.                             break;
  377.                         }
  378.                 }
  379.                 if (do_this_file) {
  380.                     if (store_info(__G))
  381.                         ++j;            /* file is OK */
  382.                     else
  383.                         ++num_skipped;  /* unsupp. compression or encryption */
  384.                 }
  385.             } /* end if (process_all_files) */
  386.         } /* end while-loop (adding files to current block) */
  387.         /* save position in central directory so can come back later */
  388.         cd_bufstart = G.cur_zipfile_bufstart;
  389.         cd_inptr = G.inptr;
  390.         cd_incnt = G.incnt;
  391.     /*-----------------------------------------------------------------------
  392.         Second loop:  process files in current block, extracting or testing
  393.         each one.
  394.       -----------------------------------------------------------------------*/
  395.         for (i = 0; i < j; ++i) {
  396.             filnum++;   /* filnum = i + blknum*DIR_BLKSIZ + 1; */
  397.             G.pInfo = &G.info[i];
  398. #ifdef NOVELL_BUG_FAILSAFE
  399.             G.dne = FALSE;  /* assume file exists until stat() says otherwise */
  400. #endif
  401.             /* if the target position is not within the current input buffer
  402.              * (either haven't yet read far enough, or (maybe) skipping back-
  403.              * ward), skip to the target position and reset readbuf(). */
  404.             /* ZLSEEK(pInfo->offset):  */
  405.             request = G.pInfo->offset + G.extra_bytes;
  406.             inbuf_offset = request % INBUFSIZ;
  407.             bufstart = request - inbuf_offset;
  408.             Trace((stderr, "ndebug: request = %ld, inbuf_offset = %ldn",
  409.               request, inbuf_offset));
  410.             Trace((stderr,
  411.               "debug: bufstart = %ld, cur_zipfile_bufstart = %ldn",
  412.               bufstart, G.cur_zipfile_bufstart));
  413.             if (request < 0) {
  414.                 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  415.                   G.zipfn, LoadFarString(ReportMsg)));
  416.                 error_in_archive = PK_ERR;
  417.                 if (filnum == 1 && G.extra_bytes != 0L) {
  418.                     Info(slide, 0x401, ((char *)slide,
  419.                       LoadFarString(AttemptRecompensate)));
  420.                     old_extra_bytes = G.extra_bytes;
  421.                     G.extra_bytes = 0L;
  422.                     request = G.pInfo->offset;  /* could also check if != 0 */
  423.                     inbuf_offset = request % INBUFSIZ;
  424.                     bufstart = request - inbuf_offset;
  425.                     Trace((stderr, "debug: request = %ld, inbuf_offset = %ldn",
  426.                       request, inbuf_offset));
  427.                     Trace((stderr,
  428.                       "debug: bufstart = %ld, cur_zipfile_bufstart = %ldn",
  429.                       bufstart, G.cur_zipfile_bufstart));
  430.                 } else {
  431.                     error_in_archive = PK_BADERR;
  432.                     continue;  /* this one hosed; try next */
  433.                 }
  434.             }
  435.             /* try again */
  436.             if (request < 0) {
  437.                 Trace((stderr, "debug: recompensated request still < 0n"));
  438.                 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  439.                   G.zipfn, LoadFarString(ReportMsg)));
  440.                 error_in_archive = PK_BADERR;
  441.                 continue;
  442.             } else if (bufstart != G.cur_zipfile_bufstart) {
  443.                 Trace((stderr, "debug: bufstart != cur_zipfile_bufstartn"));
  444. #ifdef USE_STRM_INPUT
  445.                 fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
  446.                 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
  447. #else /* !USE_STRM_INPUT */
  448.                 G.cur_zipfile_bufstart =
  449.                   lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);
  450. #endif /* ?USE_STRM_INPUT */
  451.                 if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)
  452.                 {
  453.                     Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  454.                       filnum, "lseek", bufstart));
  455.                     error_in_archive = PK_BADERR;
  456.                     continue;   /* can still do next file */
  457.                 }
  458.                 G.inptr = G.inbuf + (int)inbuf_offset;
  459.                 G.incnt -= (int)inbuf_offset;
  460.             } else {
  461.                 G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
  462.                 G.inptr = G.inbuf + (int)inbuf_offset;
  463.             }
  464.             /* should be in proper position now, so check for sig */
  465.             if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
  466.                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  467.                   filnum, "EOF", request));
  468.                 error_in_archive = PK_BADERR;
  469.                 continue;   /* but can still try next one */
  470.             }
  471.             if (strncmp(G.sig, local_hdr_sig, 4)) {
  472.                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  473.                   filnum, LoadFarStringSmall(LocalHdrSig), request));
  474.                 /*
  475.                     GRRDUMP(G.sig, 4)
  476.                     GRRDUMP(local_hdr_sig, 4)
  477.                  */
  478.                 error_in_archive = PK_ERR;
  479.                 if ((filnum == 1 && G.extra_bytes != 0L) ||
  480.                     (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
  481.                     Info(slide, 0x401, ((char *)slide,
  482.                       LoadFarString(AttemptRecompensate)));
  483.                     if (G.extra_bytes) {
  484.                         old_extra_bytes = G.extra_bytes;
  485.                         G.extra_bytes = 0L;
  486.                     } else
  487.                         G.extra_bytes = old_extra_bytes;  /* third attempt */
  488.                     ZLSEEK(G.pInfo->offset)
  489.                     if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
  490.                         Info(slide, 0x401, ((char *)slide,
  491.                           LoadFarString(OffsetMsg), filnum, "EOF", request));
  492.                         error_in_archive = PK_BADERR;
  493.                         continue;   /* but can still try next one */
  494.                     }
  495.                     if (strncmp(G.sig, local_hdr_sig, 4)) {
  496.                         Info(slide, 0x401, ((char *)slide,
  497.                           LoadFarString(OffsetMsg), filnum,
  498.                           LoadFarStringSmall(LocalHdrSig), request));
  499.                         error_in_archive = PK_BADERR;
  500.                         continue;
  501.                     }
  502.                 } else
  503.                     continue;  /* this one hosed; try next */
  504.             }
  505.             if ((error = process_local_file_hdr(__G)) != PK_COOL) {
  506.                 Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
  507.                   filnum));
  508.                 error_in_archive = error;   /* only PK_EOF defined */
  509.                 continue;   /* can still try next one */
  510.             }
  511.             if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
  512.                  PK_COOL)
  513.             {
  514.                 if (error > error_in_archive)
  515.                     error_in_archive = error;
  516.                 if (error > PK_WARN) {
  517.                     Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  518.                       FnFilter1(G.filename), "local"));
  519.                     continue;   /* go on to next one */
  520.                 }
  521.             }
  522.             if (G.extra_field != (uch *)NULL) {
  523.                 free(G.extra_field);
  524.                 G.extra_field = (uch *)NULL;
  525.             }
  526.             if ((error =
  527.                  do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
  528.             {
  529.                 if (error > error_in_archive)
  530.                     error_in_archive = error;
  531.                 if (error > PK_WARN) {
  532.                     Info(slide, 0x401, ((char *)slide,
  533.                       LoadFarString(ExtFieldMsg),
  534.                       FnFilter1(G.filename), "local"));
  535.                     continue;   /* go on */
  536.                 }
  537.             }
  538. #if CRYPT
  539.             if (G.pInfo->encrypted &&
  540.                 (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
  541.                 if (error == PK_WARN) {
  542.                     if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  543.                         Info(slide, 0x401, ((char *)slide,
  544.                           LoadFarString(SkipIncorrectPasswd),
  545.                           FnFilter1(G.filename)));
  546.                     ++num_bad_pwd;
  547.                 } else {  /* (error > PK_WARN) */
  548.                     if (error > error_in_archive)
  549.                         error_in_archive = error;
  550.                     Info(slide, 0x401, ((char *)slide,
  551.                       LoadFarString(SkipCannotGetPasswd),
  552.                       FnFilter1(G.filename)));
  553.                 }
  554.                 continue;   /* go on to next file */
  555.             }
  556. #endif /* CRYPT */
  557.             /*
  558.              * just about to extract file:  if extracting to disk, check if
  559.              * already exists, and if so, take appropriate action according to
  560.              * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  561.              * loop because we don't store the possibly renamed filename[] in
  562.              * info[])
  563.              */
  564. #ifdef DLL
  565.             if (!uO.tflag && !uO.cflag && !G.redirect_data)
  566. #else
  567.             if (!uO.tflag && !uO.cflag)
  568. #endif
  569.             {
  570.                 renamed = FALSE;   /* user hasn't renamed output file yet */
  571. startover:
  572.                 query = FALSE;
  573.                 /* for files from DOS FAT, check for use of backslash instead
  574.                  *  of slash as directory separator (bug in some zipper(s); so
  575.                  *  far, not a problem in HPFS, NTFS or VFAT systems)
  576.                  */
  577. #ifndef SFX
  578.                 if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
  579.                     char *p=G.filename-1;
  580.                     while (*++p) {
  581.                         if (*p == '\') {
  582.                             if (!G.reported_backslash) {
  583.                                 Info(slide, 0x21, ((char *)slide,
  584.                                   LoadFarString(BackslashPathSep), G.zipfn));
  585.                                 G.reported_backslash = TRUE;
  586.                                 if (!error_in_archive)
  587.                                     error_in_archive = PK_WARN;
  588.                             }
  589.                             *p = '/';
  590.                         }
  591.                     }
  592.                 }
  593. #endif /* !SFX */
  594.                 /* mapname can create dirs if not freshening or if renamed */
  595.                 if ((error = mapname(__G__ renamed)) > PK_WARN) {
  596.                     if (error == IZ_CREATED_DIR) {
  597. #ifdef SET_DIR_ATTRIB
  598.                         dirtime *d_entry;
  599.                         d_entry = (dirtime *)malloc(sizeof(dirtime));
  600.                         if (d_entry == (dirtime *)NULL) {
  601.                             Info(slide, 0x401, ((char *)slide,
  602.                                  LoadFarString(DirlistEntryNoMem)));
  603.                         } else {
  604.                             unsigned eb_izux_flg;
  605.                             d_entry->next = dirlist;
  606.                             dirlist = d_entry;
  607.                             dirlist->fn =
  608.                               (char *)malloc(strlen(G.filename) + 1);
  609.                             if (dirlist->fn == (char *)NULL) {
  610.                                 Info(slide, 0x401, ((char *)slide,
  611.                                   LoadFarString(DirlistEntryNoMem)));
  612.                                 dirlist = d_entry->next;
  613.                                 free(d_entry);
  614.                                 if (!error_in_archive)
  615.                                     error_in_archive = PK_WARN;
  616.                                 continue;
  617.                             }
  618.                             strcpy(dirlist->fn, G.filename);
  619.                             dirlist->perms = G.pInfo->file_attr;
  620. #ifdef USE_EF_UT_TIME
  621.                             eb_izux_flg = G.extra_field? ef_scan_for_izux(
  622.                               G.extra_field, G.lrec.extra_field_length, 0,
  623.                               G.lrec.last_mod_dos_datetime,
  624. #ifdef IZ_CHECK_TZ
  625.                               (G.tz_is_valid ? &(dirlist->u.t3) : NULL),
  626. #else
  627.                               &(dirlist->u.t3),
  628. #endif
  629.                               dirlist->uidgid)
  630.                               : 0;
  631. #else /* !USE_EF_UT_TIME */
  632.                             eb_izux_flg = 0;
  633. #endif /* ?USE_EF_UT_TIME */
  634.                             if (eb_izux_flg & EB_UT_FL_MTIME) {
  635.                                 TTrace((stderr,
  636.                                   "nextract:  Unix dir e.f. modtime = %ldn",
  637.                                   dirlist->u.t3.mtime));
  638.                             } else {
  639.                                 dirlist->u.t3.mtime = dos_to_unix_time(
  640.                                   G.lrec.last_mod_dos_datetime);
  641.                             }
  642.                             if (eb_izux_flg & EB_UT_FL_ATIME) {
  643.                                 TTrace((stderr,
  644.                                   "nextract:  Unix dir e.f. actime = %ldn",
  645.                                   dirlist->u.t3.atime));
  646.                             } else {
  647.                                 dirlist->u.t3.atime =
  648.                                   dirlist->u.t3.mtime;
  649.                             }
  650.                             dirlist->have_uidgid =
  651.                                 (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
  652.                             ++num_dirs;
  653.                         }
  654. #endif /* SET_DIR_ATTRIB */
  655.                     } else if (error == IZ_VOL_LABEL) {
  656. #ifdef DOS_OS2_W32
  657.                         Info(slide, 0x401, ((char *)slide,
  658.                           LoadFarString(SkipVolumeLabel),
  659.                           FnFilter1(G.filename),
  660.                           uO.volflag? "hard disk " : ""));
  661. #else
  662.                         Info(slide, 1, ((char *)slide,
  663.                           LoadFarString(SkipVolumeLabel),
  664.                           FnFilter1(G.filename), ""));
  665. #endif
  666.                     /*  if (!error_in_archive)
  667.                             error_in_archive = PK_WARN;  */
  668.                     } else if (error > PK_ERR  &&  error_in_archive < PK_ERR)
  669.                         error_in_archive = PK_ERR;
  670.                     Trace((stderr, "mapname(%s) returns error = %dn",
  671.                       FnFilter1(G.filename), error));
  672.                     continue;   /* go on to next file */
  673.                 }
  674. #ifdef QDOS
  675.                 QFilename(__G__ G.filename);
  676. #endif
  677.                 switch (check_for_newer(__G__ G.filename)) {
  678.                     case DOES_NOT_EXIST:
  679. #ifdef NOVELL_BUG_FAILSAFE
  680.                         G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
  681. #endif
  682.                         /* if freshening, don't skip if just renamed */
  683.                         if (uO.fflag && !renamed)
  684.                             continue;   /* freshen (no new files):  skip */
  685.                         break;
  686.                     case EXISTS_AND_OLDER:
  687.                         if (uO.overwrite_none) {
  688. #ifdef WINDLL
  689.                             char szStr[FILNAMSIZ+40]; /* add. space for text */
  690.                             if ((!G.prompt_always) || (done_once)) {
  691.                                 sprintf(szStr,
  692.                                   "Target file exists.nSkipping %sn",
  693.                                   FnFilter1(G.filename));
  694.                                 win_fprintf((zvoid *)&G, stdout,
  695.                                   strlen(szStr), szStr);
  696.                             } else {
  697.                                 query = TRUE;
  698.                                 break;
  699.                             }
  700. #endif /* WINDLL */
  701.                             continue;   /* never overwrite:  skip file */
  702.                         }
  703. #ifdef UNIXBACKUP
  704.                         if (!uO.overwrite_all && !uO.B_flag)
  705. #else
  706.                         if (!uO.overwrite_all)
  707. #endif
  708.                             query = TRUE;
  709.                         break;
  710.                     case EXISTS_AND_NEWER:             /* (or equal) */
  711.                         if (uO.overwrite_none || (uO.uflag && !renamed)) {
  712. #ifdef WINDLL
  713.                             char szStr[FILNAMSIZ+40]; /* add. space for text */
  714.                             if ((!G.prompt_always) || (done_once)) {
  715.                                 sprintf(szStr,
  716.                                   "Target file newer.nSkipping %sn",
  717.                                   FnFilter1(G.filename));
  718.                                 win_fprintf((zvoid *)&G, stdout,
  719.                                   strlen(szStr), szStr);
  720.                             } else {
  721.                                 query = TRUE;
  722.                                 break;
  723.                             }
  724. #endif /* WINDLL */
  725.                             continue;  /* skip if update/freshen & orig name */
  726.                         }
  727. #ifdef UNIXBACKUP
  728.                         if (!uO.overwrite_all && !uO.B_flag)
  729. #else
  730.                         if (!uO.overwrite_all)
  731. #endif
  732.                             query = TRUE;
  733.                         break;
  734.                 }
  735.                 if (query) {
  736. #ifdef WINDLL
  737.                     switch (G.lpUserFunctions->replace != NULL ?
  738.                             (*G.lpUserFunctions->replace)(G.filename) :
  739.                             IDM_REPLACE_NONE) {
  740.                         case IDM_REPLACE_RENAME:
  741.                             _ISO_INTERN(G.filename);
  742.                             renamed = TRUE;
  743.                             goto startover;
  744.                         case IDM_REPLACE_YES:
  745.                             break;
  746.                         case IDM_REPLACE_ALL:
  747.                             uO.overwrite_all = TRUE;
  748.                             uO.overwrite_none = FALSE;  /* just to make sure */
  749.                             break;
  750.                         case IDM_REPLACE_NONE:
  751.                             uO.overwrite_none = TRUE;
  752.                             uO.overwrite_all = FALSE;   /* make sure */
  753.                             done_once = TRUE;
  754.                             /* FALL THROUGH, skip */
  755.                         case IDM_REPLACE_NO:
  756.                             {
  757.                                 char szStr[FILNAMSIZ+40];
  758.                                 sprintf(szStr,
  759.                                   "Target file newer.nSkipping %sn",
  760.                                   FnFilter1(G.filename));
  761.                                 win_fprintf((zvoid *)&G, stdout,
  762.                                   strlen(szStr), szStr);
  763.                             }
  764.                             continue;
  765.                     }
  766. #else /* !WINDLL */
  767. reprompt:
  768.                     Info(slide, 0x81, ((char *)slide,
  769.                       LoadFarString(ReplaceQuery),
  770.                       FnFilter1(G.filename)));
  771.                     if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
  772.                         Info(slide, 1, ((char *)slide,
  773.                           LoadFarString(AssumeNone)));
  774.                         *G.answerbuf = 'N';
  775.                         if (!error_in_archive)
  776.                             error_in_archive = 1;  /* not extracted:  warning */
  777.                     }
  778.                     switch (*G.answerbuf) {
  779.                         case 'A':   /* dangerous option:  force caps */
  780.                             uO.overwrite_all = TRUE;
  781.                             uO.overwrite_none = FALSE;  /* just to make sure */
  782.                             break;
  783.                         case 'r':
  784.                         case 'R':
  785.                             do {
  786.                                 Info(slide, 0x81, ((char *)slide,
  787.                                   LoadFarString(NewNameQuery)));
  788.                                 fgets(G.filename, FILNAMSIZ, stdin);
  789.                                 /* usually get n here:  better check for it */
  790.                                 len = strlen(G.filename);
  791.                                 if (G.filename[len-1] == 'n')
  792.                                     G.filename[--len] = '';
  793.                             } while (len == 0);
  794. #ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
  795.                             _OEM_INTERN(G.filename);
  796. #endif
  797.                             renamed = TRUE;
  798.                             goto startover;   /* sorry for a goto */
  799.                         case 'y':
  800.                         case 'Y':
  801.                             break;
  802.                         case 'N':
  803.                             uO.overwrite_none = TRUE;
  804.                             uO.overwrite_all = FALSE;   /* make sure */
  805.                             /* FALL THROUGH, skip */
  806.                         case 'n':
  807.                             continue;   /* skip file */
  808.                         default:
  809.                             Info(slide, 1, ((char *)slide,
  810.                               LoadFarString(InvalidResponse), *G.answerbuf));
  811.                             goto reprompt;   /* yet another goto? */
  812.                     } /* end switch (*answerbuf) */
  813. #endif /* ?WINDLL */
  814.                 } /* end if (query) */
  815.             } /* end if (extracting to disk) */
  816. #ifdef DLL
  817.             if ((G.statreportcb != NULL) &&
  818.                 (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
  819.                                   G.filename, NULL)) {
  820.                 if (fn_matched)
  821.                     free((zvoid *)fn_matched);
  822.                 if (xn_matched)
  823.                     free((zvoid *)xn_matched);
  824.                 return IZ_CTRLC;        /* cancel operation by user request */
  825.             }
  826. #endif
  827. #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
  828.             UserStop();
  829. #endif
  830. #ifdef AMIGA
  831.             G.filenote_slot = i;
  832. #endif
  833.             G.disk_full = 0;
  834.             if ((error = extract_or_test_member(__G)) != PK_COOL) {
  835.                 if (error > error_in_archive)
  836.                     error_in_archive = error;       /* ...and keep going */
  837. #ifdef DLL
  838.                 if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
  839. #else
  840.                 if (G.disk_full > 1) {
  841. #endif
  842.                     if (fn_matched)
  843.                         free((zvoid *)fn_matched);
  844.                     if (xn_matched)
  845.                         free((zvoid *)xn_matched);
  846.                     return error_in_archive;        /* (unless disk full) */
  847.                 }
  848.             }
  849. #ifdef DLL
  850.             if ((G.statreportcb != NULL) &&
  851.                 (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
  852.                                   G.filename, (zvoid *)&G.lrec.ucsize)) {
  853.                 if (fn_matched)
  854.                     free((zvoid *)fn_matched);
  855.                 if (xn_matched)
  856.                     free((zvoid *)xn_matched);
  857.                 return IZ_CTRLC;        /* cancel operation by user request */
  858.             }
  859. #endif
  860. #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
  861.             UserStop();
  862. #endif
  863.         } /* end for-loop (i:  files in current block) */
  864.         /*
  865.          * Jump back to where we were in the central directory, then go and do
  866.          * the next batch of files.
  867.          */
  868. #ifdef USE_STRM_INPUT
  869.         fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
  870.         G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
  871. #else /* !USE_STRM_INPUT */
  872.         G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET);
  873. #endif /* ?USE_STRM_INPUT */
  874.         read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
  875.         G.inptr = cd_inptr;
  876.         G.incnt = cd_incnt;
  877.         ++blknum;
  878. #ifdef TEST
  879.         printf("ncd_bufstart = %ld (%.8lXh)n", cd_bufstart, cd_bufstart);
  880.         printf("cur_zipfile_bufstart = %ld (%.8lXh)n", cur_zipfile_bufstart,
  881.           cur_zipfile_bufstart);
  882.         printf("inptr-inbuf = %dn", G.inptr-G.inbuf);
  883.         printf("incnt = %dnn", G.incnt);
  884. #endif
  885.     } /* end while-loop (blocks of files in central directory) */
  886. /*---------------------------------------------------------------------------
  887.     Go back through saved list of directories, sort and set times/perms/UIDs
  888.     and GIDs from the deepest level on up.
  889.   ---------------------------------------------------------------------------*/
  890. #ifdef SET_DIR_ATTRIB
  891.     if (num_dirs > 0) {
  892.         sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
  893.         if (sorted_dirlist == (dirtime **)NULL) {
  894.             Info(slide, 0x401, ((char *)slide,
  895.               LoadFarString(DirlistSortNoMem)));
  896.             while (dirlist != (dirtime *)NULL) {
  897.                 dirtime *d = dirlist;
  898.                 dirlist = dirlist->next;
  899.                 free(d);
  900.             }
  901.         } else {
  902.             if (num_dirs == 1)
  903.                 sorted_dirlist[0] = dirlist;
  904.             else {
  905.                 for (i = 0;  i < num_dirs;  ++i) {
  906.                     sorted_dirlist[i] = dirlist;
  907.                     dirlist = dirlist->next;
  908.                 }
  909.                 qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
  910.                   dircomp);
  911.             }
  912.             Trace((stderr, "setting directory times/perms/attributesn"));
  913.             for (i = 0;  i < num_dirs;  ++i) {
  914.                 dirtime *d = sorted_dirlist[i];
  915.                 Trace((stderr, "dir = %sn", d->fn));
  916.                 if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
  917.                     Info(slide, 0x201, ((char *)slide,
  918.                       LoadFarString(DirlistSetAttrFailed), d->fn));
  919.                     if (!error_in_archive)
  920.                         error_in_archive = error;
  921.                 }
  922.                 free(d->fn);
  923.                 free(d);
  924.             }
  925.             free(sorted_dirlist);
  926.         }
  927.     }
  928. #endif /* SET_DIR_ATTRIB */
  929. #if (defined(WIN32) && defined(NTSD_EAS))
  930.     process_defer_NT(__G);  /* process any deferred items for this .zip file */
  931. #endif
  932. /*---------------------------------------------------------------------------
  933.     Check for unmatched filespecs on command line and print warning if any
  934.     found.  Free allocated memory.
  935.   ---------------------------------------------------------------------------*/
  936.     if (fn_matched) {
  937.         for (i = 0;  i < G.filespecs;  ++i)
  938.             if (!fn_matched[i]) {
  939. #ifdef DLL
  940.                 if (!G.redirect_data && !G.redirect_text)
  941.                     Info(slide, 0x401, ((char *)slide,
  942.                       LoadFarString(FilenameNotMatched), G.pfnames[i]));
  943.                 else
  944.                     setFileNotFound(__G);
  945. #else
  946.                 Info(slide, 1, ((char *)slide,
  947.                   LoadFarString(FilenameNotMatched), G.pfnames[i]));
  948. #endif
  949.                 if (error_in_archive <= PK_WARN)
  950.                     error_in_archive = PK_FIND;   /* some files not found */
  951.             }
  952.         free((zvoid *)fn_matched);
  953.     }
  954.     if (xn_matched) {
  955.         for (i = 0;  i < G.xfilespecs;  ++i)
  956.             if (!xn_matched[i])
  957.                 Info(slide, 0x401, ((char *)slide,
  958.                   LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
  959.         free((zvoid *)xn_matched);
  960.     }
  961. /*---------------------------------------------------------------------------
  962.     Double-check that we're back at the end-of-central-directory record, and
  963.     print quick summary of results, if we were just testing the archive.  We
  964.     send the summary to stdout so that people doing the testing in the back-
  965.     ground and redirecting to a file can just do a "tail" on the output file.
  966.   ---------------------------------------------------------------------------*/
  967. #ifndef SFX
  968.     if (readbuf(__G__ G.sig, 4) == 0)
  969.         error_in_archive = PK_EOF;
  970.     if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure */
  971.         Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  972.         Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  973.         if (!error_in_archive)       /* don't overwrite stronger error */
  974.             error_in_archive = PK_WARN;
  975.     }
  976. #endif /* !SFX */
  977.     if (uO.tflag) {
  978.         unsigned num = filnum - num_bad_pwd;
  979.         if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */
  980.             if (error_in_archive)
  981.                 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
  982.                   (error_in_archive == 1)? "warning-" : "", G.zipfn));
  983.             else if (num == 0)
  984.                 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
  985.                   G.zipfn));
  986.             else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
  987.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
  988.                   G.zipfn));
  989.             else
  990.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
  991.                   , G.zipfn, num, (num==1)? "":"s"));
  992.             if (num_skipped > 0)
  993.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
  994.                   num_skipped, (num_skipped==1)? "":"s"));
  995. #if CRYPT
  996.             if (num_bad_pwd > 0)
  997.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
  998.                   , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
  999. #endif /* CRYPT */
  1000.         } else if ((uO.qflag == 0) && !error_in_archive && (num == 0))
  1001.             Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
  1002.               G.zipfn));
  1003.     }
  1004.     /* give warning if files not tested or extracted (first condition can still
  1005.      * happen if zipfile is empty and no files specified on command line) */
  1006.     if ((filnum == 0) && error_in_archive <= PK_WARN) {
  1007.         if (num_skipped > 0)
  1008.             error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
  1009.         else
  1010.             error_in_archive = PK_FIND;  /* no files found at all */
  1011.     }
  1012. #if CRYPT
  1013.     else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
  1014.         error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
  1015. #endif
  1016.     else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
  1017.         error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
  1018. #if CRYPT
  1019.     else if ((num_bad_pwd > 0) && !error_in_archive)
  1020.         error_in_archive = PK_WARN;
  1021. #endif
  1022.     return error_in_archive;
  1023. } /* end function extract_or_test_files() */
  1024. /***************************/
  1025. /*  Function store_info()  */
  1026. /***************************/
  1027. static int store_info(__G)   /* return 0 if skipping, 1 if OK */
  1028.     __GDEF
  1029. {
  1030. #ifdef SFX
  1031. #  define UNKN_COMPR 
  1032.    (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
  1033. #else
  1034. #  ifdef COPYRIGHT_CLEAN  /* no reduced files */
  1035. #    define UNKN_RED (G.crec.compression_method >= REDUCED1 && 
  1036.                       G.crec.compression_method <= REDUCED4)
  1037. #  else
  1038. #    define UNKN_RED  FALSE  /* reducing not unknown */
  1039. #  endif
  1040. #  ifdef LZW_CLEAN  /* no shrunk files */
  1041. #    define UNKN_SHR (G.crec.compression_method == SHRUNK)
  1042. #  else
  1043. #    define UNKN_SHR  FALSE  /* unshrinking not unknown */
  1044. #  endif
  1045. #  define UNKN_COMPR (UNKN_RED || UNKN_SHR || 
  1046.    G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
  1047. #endif
  1048. /*---------------------------------------------------------------------------
  1049.     Check central directory info for version/compatibility requirements.
  1050.   ---------------------------------------------------------------------------*/
  1051.     G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
  1052.     G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  1053.     G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
  1054.     G.pInfo->crc = G.crec.crc32;
  1055.     G.pInfo->compr_size = G.crec.csize;
  1056.     G.pInfo->uncompr_size = G.crec.ucsize;
  1057.     switch (uO.aflag) {
  1058.         case 0:
  1059.             G.pInfo->textmode = FALSE;   /* bit field */
  1060.             break;
  1061.         case 1:
  1062.             G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
  1063.             break;
  1064.         default:  /* case 2: */
  1065.             G.pInfo->textmode = TRUE;
  1066.             break;
  1067.     }
  1068.     if (G.crec.version_needed_to_extract[1] == VMS_) {
  1069.         if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  1070.             if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  1071.                 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  1072.                   FnFilter1(G.filename), "VMS",
  1073.                   G.crec.version_needed_to_extract[0] / 10,
  1074.                   G.crec.version_needed_to_extract[0] % 10,
  1075.                   VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
  1076.             return 0;
  1077.         }
  1078. #ifndef VMS   /* won't be able to use extra field, but still have data */
  1079.         else if (!uO.tflag && !uO.overwrite_all) { /* if -o, extract anyway */
  1080.             Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
  1081.               FnFilter1(G.filename)));
  1082.             fgets(G.answerbuf, 9, stdin);
  1083.             if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
  1084.                 return 0;
  1085.         }
  1086. #endif /* !VMS */
  1087.     /* usual file type:  don't need VMS to extract */
  1088.     } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
  1089.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  1090.             Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  1091.               FnFilter1(G.filename), "PK",
  1092.               G.crec.version_needed_to_extract[0] / 10,
  1093.               G.crec.version_needed_to_extract[0] % 10,
  1094.               UNZIP_VERSION / 10, UNZIP_VERSION % 10));
  1095.         return 0;
  1096.     }
  1097.     if UNKN_COMPR {
  1098.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
  1099. #ifndef SFX
  1100.             if (G.crec.compression_method < NUM_METHODS)
  1101.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
  1102.                   FnFilter1(G.filename),
  1103.                   LoadFarStringSmall(ComprNames[G.crec.compression_method])));
  1104.             else
  1105. #endif
  1106.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
  1107.                   FnFilter1(G.filename),
  1108.                   G.crec.compression_method));
  1109.         }
  1110.         return 0;
  1111.     }
  1112. #if (!CRYPT)
  1113.     if (G.pInfo->encrypted) {
  1114.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  1115.             Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
  1116.               FnFilter1(G.filename)));
  1117.         return 0;
  1118.     }
  1119. #endif /* !CRYPT */
  1120.     /* map whatever file attributes we have into the local format */
  1121.     mapattr(__G);   /* GRR:  worry about return value later */
  1122.     G.pInfo->offset = (long)G.crec.relative_offset_local_header;
  1123.     return 1;
  1124. } /* end function store_info() */
  1125. /***************************************/
  1126. /*  Function extract_or_test_member()  */
  1127. /***************************************/
  1128. static int extract_or_test_member(__G)    /* return PK-type error code */
  1129.      __GDEF
  1130. {
  1131.     char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
  1132. #ifdef CMS_MVS
  1133.     char *ebc="[ebcdic]";
  1134. #endif
  1135.     register int b;
  1136.     int r, error=PK_COOL;
  1137. #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  1138.     ulg wsize;
  1139. #else
  1140. #   define wsize WSIZE
  1141. #endif
  1142. /*---------------------------------------------------------------------------
  1143.     Initialize variables, buffers, etc.
  1144.   ---------------------------------------------------------------------------*/
  1145.     G.bits_left = 0;
  1146.     G.bitbuf = 0L;       /* unreduce and unshrink only */
  1147.     G.zipeof = 0;
  1148.     G.newfile = TRUE;
  1149.     G.crc32val = CRCVAL_INITIAL;
  1150. #ifdef SYMLINKS
  1151.     /* if file came from Unix and is a symbolic link and we are extracting
  1152.      * to disk, prepare to restore the link */
  1153.     if (S_ISLNK(G.pInfo->file_attr) &&
  1154.         (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
  1155.          G.pInfo->hostnum == BEOS_) &&
  1156.         !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0))
  1157.         G.symlnk = TRUE;
  1158.     else
  1159.         G.symlnk = FALSE;
  1160. #endif /* SYMLINKS */
  1161.     if (uO.tflag) {
  1162.         if (!uO.qflag)
  1163.             Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
  1164.               FnFilter1(G.filename), "", ""));
  1165.     } else {
  1166. #ifdef DLL
  1167.         if (uO.cflag && !G.redirect_data)
  1168. #else
  1169.         if (uO.cflag)
  1170. #endif
  1171.         {
  1172. #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
  1173.             G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
  1174. #else
  1175.             G.outfile = stdout;
  1176. #endif
  1177. #ifdef DOS_FLX_H68_OS2_W32
  1178. #if (defined(__HIGHC__) && !defined(FLEXOS))
  1179.             setmode(G.outfile, _BINARY);
  1180. #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
  1181.             setmode(fileno(G.outfile), O_BINARY);
  1182. #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
  1183. #           define NEWLINE "rn"
  1184. #else /* !DOS_FLX_H68_OS2_W32 */
  1185. #           define NEWLINE "n"
  1186. #endif /* ?DOS_FLX_H68_OS2_W32 */
  1187. #ifdef VMS
  1188.             if (open_outfile(__G))   /* VMS:  required even for stdout! */
  1189.                 return PK_DISK;
  1190. #endif
  1191.         } else if (open_outfile(__G))
  1192.             return PK_DISK;
  1193.     }
  1194. /*---------------------------------------------------------------------------
  1195.     Unpack the file.
  1196.   ---------------------------------------------------------------------------*/
  1197.     defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
  1198.     switch (G.lrec.compression_method) {
  1199.         case STORED:
  1200.             if (!uO.tflag && QCOND2) {
  1201. #ifdef SYMLINKS
  1202.                 if (G.symlnk)   /* can also be deflated, but rarer... */
  1203.                     Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1204.                       "link", FnFilter1(G.filename), "", ""));
  1205.                 else
  1206. #endif /* SYMLINKS */
  1207.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1208.                   "extract", FnFilter1(G.filename),
  1209.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1210.                   "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
  1211.                   bin)), uO.cflag? NEWLINE : ""));
  1212.             }
  1213. #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  1214.             if (G.redirect_slide) {
  1215.                 wsize = G.redirect_size; redirSlide = G.redirect_buffer;
  1216.             } else {
  1217.                 wsize = WSIZE; redirSlide = slide;
  1218.             }
  1219. #endif
  1220.             G.outptr = redirSlide;
  1221.             G.outcnt = 0L;
  1222.             while ((b = NEXTBYTE) != EOF && !G.disk_full) {
  1223.                 *G.outptr++ = (uch)b;
  1224.                 if (++G.outcnt == wsize) {
  1225.                     flush(__G__ redirSlide, G.outcnt, 0);
  1226.                     G.outptr = redirSlide;
  1227.                     G.outcnt = 0L;
  1228.                 }
  1229.             }
  1230.             if (G.outcnt)          /* flush final (partial) buffer */
  1231.                 flush(__G__ redirSlide, G.outcnt, 0);
  1232.             break;
  1233. #ifndef SFX
  1234. #ifndef LZW_CLEAN
  1235.         case SHRUNK:
  1236.             if (!uO.tflag && QCOND2) {
  1237.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1238.                   LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
  1239.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1240.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1241.             }
  1242.             if ((r = unshrink(__G)) != PK_COOL) {
  1243.                 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1244.                     Info(slide, 0x401, ((char *)slide,
  1245.                       LoadFarStringSmall(ErrUnzipFile),
  1246.                       LoadFarString(NotEnoughMem),
  1247.                       LoadFarStringSmall2(Unshrink),
  1248.                       FnFilter1(G.filename)));
  1249.                 else
  1250.                     Info(slide, 0x401, ((char *)slide,
  1251.                       LoadFarStringSmall(ErrUnzipNoFile),
  1252.                       LoadFarString(NotEnoughMem),
  1253.                       LoadFarStringSmall2(Unshrink)));
  1254.                 error = r;
  1255.             }
  1256.             break;
  1257. #endif /* !LZW_CLEAN */
  1258. #ifndef COPYRIGHT_CLEAN
  1259.         case REDUCED1:
  1260.         case REDUCED2:
  1261.         case REDUCED3:
  1262.         case REDUCED4:
  1263.             if (!uO.tflag && QCOND2) {
  1264.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1265.                   "unreduc", FnFilter1(G.filename),
  1266.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1267.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1268.             }
  1269.             unreduce(__G);
  1270.             break;
  1271. #endif /* !COPYRIGHT_CLEAN */
  1272.         case IMPLODED:
  1273.             if (!uO.tflag && QCOND2) {
  1274.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1275.                   "explod", FnFilter1(G.filename),
  1276.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1277.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1278.             }
  1279.             if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
  1280.                 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1281.                     Info(slide, 0x401, ((char *)slide,
  1282.                       LoadFarStringSmall(ErrUnzipFile), r == 3?
  1283.                       LoadFarString(NotEnoughMem) :
  1284.                       LoadFarString(InvalidComprData),
  1285.                       LoadFarStringSmall2(Explode),
  1286.                       FnFilter1(G.filename)));
  1287.                 else
  1288.                     Info(slide, 0x401, ((char *)slide,
  1289.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1290.                       LoadFarString(NotEnoughMem) :
  1291.                       LoadFarString(InvalidComprData),
  1292.                       LoadFarStringSmall2(Explode)));
  1293.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1294.             }
  1295.             if (r == 5) {
  1296.                 int warning = ((ulg)G.used_csize <= G.lrec.csize);
  1297.                 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1298.                     Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
  1299.                       "", warning?  "warning" : "error", G.used_csize,
  1300.                       G.lrec.ucsize, warning?  "  " : "", G.lrec.csize,
  1301.                       " [", FnFilter1(G.filename), "]"));
  1302.                 else
  1303.                     Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
  1304.                       "n", warning? "warning" : "error", G.used_csize,
  1305.                       G.lrec.ucsize, warning? "  ":"", G.lrec.csize,
  1306.                       "", "", "."));
  1307.                 error = warning? PK_WARN : PK_ERR;
  1308.             }
  1309.             break;
  1310. #endif /* !SFX */
  1311.         case DEFLATED:
  1312.             if (!uO.tflag && QCOND2) {
  1313.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1314.                   "inflat", FnFilter1(G.filename),
  1315.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1316.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1317.             }
  1318. #ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
  1319. #  define UZinflate inflate
  1320. #endif
  1321.             if ((r = UZinflate(__G)) != 0) {
  1322.                 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1323.                     Info(slide, 0x401, ((char *)slide,
  1324.                       LoadFarStringSmall(ErrUnzipFile), r == 3?
  1325.                       LoadFarString(NotEnoughMem) :
  1326.                       LoadFarString(InvalidComprData),
  1327.                       LoadFarStringSmall2(Inflate),
  1328.                       FnFilter1(G.filename)));
  1329.                 else
  1330.                     Info(slide, 0x401, ((char *)slide,
  1331.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1332.                       LoadFarString(NotEnoughMem) :
  1333.                       LoadFarString(InvalidComprData),
  1334.                       LoadFarStringSmall2(Inflate)));
  1335.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1336.             }
  1337.             break;
  1338.         default:   /* should never get to this point */
  1339.             Info(slide, 0x401, ((char *)slide,
  1340.               LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
  1341.             /* close and delete file before return? */
  1342.             undefer_input(__G);
  1343.             return PK_WARN;
  1344.     } /* end switch (compression method) */
  1345. /*---------------------------------------------------------------------------
  1346.     Close the file and set its date and time (not necessarily in that order),
  1347.     and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
  1348.     machines (redundant on 32-bit machines).
  1349.   ---------------------------------------------------------------------------*/
  1350. #ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
  1351.     if (!uO.tflag)           /* don't close NULL file */
  1352.         close_outfile(__G);
  1353. #else
  1354. #ifdef DLL
  1355.     if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
  1356.         if (G.redirect_data)
  1357.             FINISH_REDIRECT();
  1358.         else
  1359.             close_outfile(__G);
  1360.     }
  1361. #else
  1362.     if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
  1363.         close_outfile(__G);
  1364. #endif
  1365. #endif /* VMS */
  1366.             /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
  1367.     if (G.disk_full) {            /* set by flush() */
  1368.         if (G.disk_full > 1) {
  1369. #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
  1370.             /* delete the incomplete file if we can */
  1371.             if (unlink(G.filename) != 0)
  1372.                 Trace((stderr, "extract.c:  could not delete %sn",
  1373.                   FnFilter1(G.filename)));
  1374. #else
  1375.             /* warn user about the incomplete file */
  1376.             Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
  1377.               FnFilter1(G.filename)));
  1378. #endif
  1379.             error = PK_DISK;
  1380.         } else {
  1381.             error = PK_WARN;
  1382.         }
  1383.     }
  1384.     if (error > PK_WARN) {/* don't print redundant CRC error if error already */
  1385.         undefer_input(__G);
  1386.         return error;
  1387.     }
  1388.     if (G.crc32val != G.lrec.crc32) {
  1389.         /* if quiet enough, we haven't output the filename yet:  do it */
  1390.         if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1391.             Info(slide, 0x401, ((char *)slide, "%-22s ",
  1392.               FnFilter1(G.filename)));
  1393.         Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
  1394.           G.lrec.crc32));
  1395. #if CRYPT
  1396.         if (G.pInfo->encrypted)
  1397.             Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
  1398. #endif
  1399.         error = PK_ERR;
  1400.     } else if (uO.tflag) {
  1401. #ifndef SFX
  1402.         if (G.extra_field) {
  1403.             if ((r = TestExtraField(__G__ G.extra_field,
  1404.                                     G.lrec.extra_field_length)) > error)
  1405.                 error = r;
  1406.         } else
  1407. #endif /* !SFX */
  1408.         if (!uO.qflag)
  1409.             Info(slide, 0, ((char *)slide, " OKn"));
  1410.     } else {
  1411.         if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
  1412.             Info(slide, 0, ((char *)slide, "n"));
  1413.     }
  1414.     undefer_input(__G);
  1415.     return error;
  1416. } /* end function extract_or_test_member() */
  1417. #ifndef SFX
  1418. /*******************************/
  1419. /*  Function TestExtraField()  */
  1420. /*******************************/
  1421. static int TestExtraField(__G__ ef, ef_len)
  1422.     __GDEF
  1423.     uch *ef;
  1424.     unsigned ef_len;
  1425. {
  1426.     ush ebID;
  1427.     unsigned ebLen;
  1428.     unsigned eb_cmpr_offs = 0;
  1429.     int r;
  1430.     /* we know the regular compressed file data tested out OK, or else we
  1431.      * wouldn't be here ==> print filename if any extra-field errors found
  1432.      */
  1433.     while (ef_len >= EB_HEADSIZE) {
  1434.         ebID = makeword(ef);
  1435.         ebLen = (unsigned)makeword(ef+EB_LEN);
  1436.         if (ebLen > (ef_len - EB_HEADSIZE)) {
  1437.            /* Discovered some extra field inconsistency! */
  1438.             if (uO.qflag)
  1439.                 Info(slide, 1, ((char *)slide, "%-22s ",
  1440.                   FnFilter1(G.filename)));
  1441.             Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
  1442.               ebLen, (ef_len - EB_HEADSIZE)));
  1443.             return PK_ERR;
  1444.         }
  1445.         switch (ebID) {
  1446.             case EF_OS2:
  1447.             case EF_ACL:
  1448.             case EF_MAC3:
  1449.             case EF_BEOS:
  1450.                 switch (ebID) {
  1451.                   case EF_OS2:
  1452.                   case EF_ACL:
  1453.                     eb_cmpr_offs = EB_OS2_HLEN;
  1454.                     break;
  1455.                   case EF_MAC3:
  1456.                     if (ebLen >= EB_MAC3_HLEN &&
  1457.                         (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
  1458.                          & EB_M3_FL_UNCMPR) &&
  1459.                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
  1460.                         eb_cmpr_offs = 0;
  1461.                     else
  1462.                         eb_cmpr_offs = EB_MAC3_HLEN;
  1463.                     break;
  1464.                   case EF_BEOS:
  1465.                     if (ebLen >= EB_BEOS_HLEN &&
  1466.                         (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
  1467.                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
  1468.                         eb_cmpr_offs = 0;
  1469.                     else
  1470.                         eb_cmpr_offs = EB_BEOS_HLEN;
  1471.                     break;
  1472.                 }
  1473.                 if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
  1474.                     != PK_OK) {
  1475.                     if (uO.qflag)
  1476.                         Info(slide, 1, ((char *)slide, "%-22s ",
  1477.                           FnFilter1(G.filename)));
  1478.                     switch (r) {
  1479.                         case IZ_EF_TRUNC:
  1480.                             Info(slide, 1, ((char *)slide,
  1481.                               LoadFarString(TruncEAs),
  1482.                               ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "n"));
  1483.                             break;
  1484.                         case PK_ERR:
  1485.                             Info(slide, 1, ((char *)slide,
  1486.                               LoadFarString(InvalidComprDataEAs)));
  1487.                             break;
  1488.                         case PK_MEM3:
  1489.                         case PK_MEM4:
  1490.                             Info(slide, 1, ((char *)slide,
  1491.                               LoadFarString(NotEnoughMemEAs)));
  1492.                             break;
  1493.                         default:
  1494.                             if ((r & 0xff) != PK_ERR)
  1495.                                 Info(slide, 1, ((char *)slide,
  1496.                                   LoadFarString(UnknErrorEAs)));
  1497.                             else {
  1498.                                 ush m = (ush)(r >> 8);
  1499.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  1500.                                     Info(slide, 1, ((char *)slide,
  1501.                                       LoadFarString(BadCRC_EAs)));
  1502.                                 else
  1503.                                     Info(slide, 1, ((char *)slide,
  1504.                                       LoadFarString(UnknComprMethodEAs), m));
  1505.                             }
  1506.                             break;
  1507.                     }
  1508.                     return r;
  1509.                 }
  1510.                 break;
  1511.             case EF_NTSD:
  1512.                 Trace((stderr, "ebID: %i / ebLen: %un", ebID, ebLen));
  1513.                 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
  1514.                     ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
  1515.                      (PK_WARN | 0x4000) :
  1516.                      test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
  1517.                 if (r != PK_OK) {
  1518.                     if (uO.qflag)
  1519.                         Info(slide, 1, ((char *)slide, "%-22s ",
  1520.                           FnFilter1(G.filename)));
  1521.                     switch (r) {
  1522.                         case IZ_EF_TRUNC:
  1523.                             Info(slide, 1, ((char *)slide,
  1524.                               LoadFarString(TruncNTSD),
  1525.                               ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "n"));
  1526.                             break;
  1527. #if (defined(WIN32) && defined(NTSD_EAS))
  1528.                         case PK_WARN:
  1529.                             Info(slide, 1, ((char *)slide,
  1530.                               LoadFarString(InvalidSecurityEAs)));
  1531.                             break;
  1532. #endif
  1533.                         case PK_ERR:
  1534.                             Info(slide, 1, ((char *)slide,
  1535.                               LoadFarString(InvalidComprDataEAs)));
  1536.                             break;
  1537.                         case PK_MEM3:
  1538.                         case PK_MEM4:
  1539.                             Info(slide, 1, ((char *)slide,
  1540.                               LoadFarString(NotEnoughMemEAs)));
  1541.                             break;
  1542.                         case (PK_WARN | 0x4000):
  1543.                             Info(slide, 1, ((char *)slide,
  1544.                               LoadFarString(UnsuppNTSDVersEAs),
  1545.                               (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
  1546.                             r = PK_WARN;
  1547.                             break;
  1548.                         default:
  1549.                             if ((r & 0xff) != PK_ERR)
  1550.                                 Info(slide, 1, ((char *)slide,
  1551.                                   LoadFarString(UnknErrorEAs)));
  1552.                             else {
  1553.                                 ush m = (ush)(r >> 8);
  1554.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  1555.                                     Info(slide, 1, ((char *)slide,
  1556.                                       LoadFarString(BadCRC_EAs)));
  1557.                                 else
  1558.                                     Info(slide, 1, ((char *)slide,
  1559.                                       LoadFarString(UnknComprMethodEAs), m));
  1560.                             }
  1561.                             break;
  1562.                     }
  1563.                     return r;
  1564.                 }
  1565.                 break;
  1566.             case EF_PKVMS:
  1567.             case EF_PKW32:
  1568.             case EF_PKUNIX:
  1569.             case EF_ASIUNIX:
  1570.             case EF_IZVMS:
  1571.             case EF_IZUNIX:
  1572.             case EF_VMCMS:
  1573.             case EF_MVS:
  1574.             case EF_SPARK:
  1575.             case EF_AV:
  1576.             default:
  1577.                 break;
  1578.         }
  1579.         ef_len -= (ebLen + EB_HEADSIZE);
  1580.         ef += (ebLen + EB_HEADSIZE);
  1581.     }
  1582.     if (!uO.qflag)
  1583.         Info(slide, 0, ((char *)slide, " OKn"));
  1584.     return PK_COOL;
  1585. } /* end function TestExtraField() */
  1586. /******************************/
  1587. /*  Function test_compr_eb()  */
  1588. /******************************/
  1589. #ifdef PROTO
  1590. static int test_compr_eb(
  1591.     __GPRO__
  1592.     uch *eb,
  1593.     unsigned eb_size,
  1594.     unsigned compr_offset,
  1595.     int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
  1596.                           uch *eb_ucptr, ulg eb_ucsize))
  1597. #else /* !PROTO */
  1598. static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  1599.     __GDEF
  1600.     uch *eb;
  1601.     unsigned eb_size;
  1602.     unsigned compr_offset;
  1603.     int (*test_uc_ebdata)();
  1604. #endif /* ?PROTO */
  1605. {
  1606.     ulg eb_ucsize;
  1607.     uch *eb_ucptr;
  1608.     int r;
  1609.     if (compr_offset < 4)                /* field is not compressed: */
  1610.         return PK_OK;                    /* do nothing and signal OK */
  1611.     if ((eb_size < (EB_UCSIZE_P + 4)) ||
  1612.         ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
  1613.          eb_size <= (compr_offset + EB_CMPRHEADLEN)))
  1614.         return IZ_EF_TRUNC;               /* no compressed data! */
  1615.     if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
  1616.         return PK_MEM4;
  1617.     r = memextract(__G__ eb_ucptr, eb_ucsize,
  1618.                    eb + (EB_HEADSIZE + compr_offset),
  1619.                    (ulg)(eb_size - compr_offset));
  1620.     if (r == PK_OK && test_uc_ebdata != NULL)
  1621.         r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
  1622.     free(eb_ucptr);
  1623.     return r;
  1624. } /* end function test_compr_eb() */
  1625. #endif /* !SFX */
  1626. /***************************/
  1627. /*  Function memextract()  */
  1628. /***************************/
  1629. int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
  1630.     __GDEF                                        /*  extra field block; */
  1631.     uch *tgt, *src;                               /*  return PK-type error */
  1632.     ulg tgtsize, srcsize;                         /*  level */
  1633. {
  1634.     long old_csize=G.csize;
  1635.     uch *old_inptr=G.inptr;
  1636.     int  old_incnt=G.incnt;
  1637.     int  r, error=PK_OK;
  1638.     ush  method;
  1639.     ulg  extra_field_crc;
  1640.     method = makeword(src);
  1641.     extra_field_crc = makelong(src+2);
  1642.     /* compressed extra field exists completely in memory at this location: */
  1643.     G.inptr = src + 2 + 4;      /* method and extra_field_crc */
  1644.     G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
  1645.     G.mem_mode = TRUE;
  1646.     G.outbufptr = tgt;
  1647.     G.outsize = tgtsize;
  1648.     switch (method) {
  1649.         case STORED:
  1650.             memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
  1651.             G.outcnt = G.csize;   /* for CRC calculation */
  1652.             break;
  1653.         case DEFLATED:
  1654.             G.outcnt = 0L;
  1655.             if ((r = UZinflate(__G)) != 0) {
  1656.                 if (!uO.tflag)
  1657.                     Info(slide, 0x401, ((char *)slide,
  1658.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1659.                       LoadFarString(NotEnoughMem) :
  1660.                       LoadFarString(InvalidComprData),
  1661.                       LoadFarStringSmall2(Inflate)));
  1662.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1663.             }
  1664.             if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
  1665.                 break;
  1666.             break;
  1667.         default:
  1668.             if (uO.tflag)
  1669.                 error = PK_ERR | ((int)method << 8);
  1670.             else {
  1671.                 Info(slide, 0x401, ((char *)slide,
  1672.                   LoadFarString(UnsupportedExtraField), method));
  1673.                 error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
  1674.             }
  1675.             break;
  1676.     }
  1677.     G.inptr = old_inptr;
  1678.     G.incnt = old_incnt;
  1679.     G.csize = old_csize;
  1680.     G.mem_mode = FALSE;
  1681.     if (!error) {
  1682.         register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
  1683.         if (crcval != extra_field_crc) {
  1684.             if (uO.tflag)
  1685.                 error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
  1686.             else {
  1687.                 Info(slide, 0x401, ((char *)slide,
  1688.                   LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
  1689.                   extra_field_crc));
  1690.                 error = PK_ERR;
  1691.             }
  1692.         }
  1693.     }
  1694.     return error;
  1695. } /* end function memextract() */
  1696. /*************************/
  1697. /*  Function memflush()  */
  1698. /*************************/
  1699. int memflush(__G__ rawbuf, size)
  1700.     __GDEF
  1701.     uch *rawbuf;
  1702.     ulg size;
  1703. {
  1704.     if (size > G.outsize)
  1705.         return 50;   /* more data than output buffer can hold */
  1706.     memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
  1707.     G.outbufptr += (unsigned int)size;
  1708.     G.outsize -= size;
  1709.     G.outcnt += size;
  1710.     return 0;
  1711. } /* end function memflush() */
  1712. /*************************/
  1713. /*  Function fnfilter()  */        /* here instead of in list.c for SFX */
  1714. /*************************/
  1715. char *fnfilter(raw, space)         /* convert name to safely printable form */
  1716.     ZCONST char *raw;
  1717.     uch *space;
  1718. {
  1719. #ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
  1720.     uch *r=(uch *)raw, *s=space;
  1721.     while (*r) {
  1722. #ifdef QDOS
  1723.         if (qlflag & 2) {
  1724.             if (*r == '/' || *r == '.') {
  1725.                 ++r;
  1726.                 *s++ = '_';
  1727.                 continue;
  1728.             }
  1729.         } else
  1730. #endif
  1731.         if (*r < 32)
  1732.             *s++ = '^', *s++ = (uch)(64 + *r++);
  1733.         else
  1734.             *s++ = *r++;
  1735.     }
  1736.     *s = 0;
  1737. #ifdef WINDLL
  1738.     INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
  1739. #else
  1740. #ifdef WIN32
  1741.     /* Win9x console always uses OEM character coding, and
  1742.        WinNT console is set to OEM charset by default, too */
  1743.     INTERN_TO_OEM((char *)space, (char *)space);
  1744. #endif /* WIN32 */
  1745. #endif /* ?WINDLL */
  1746.     return (char *)space;
  1747. #else /* NATIVE:  EBCDIC or whatever */
  1748.     return (char *)raw;
  1749. #endif
  1750. } /* end function fnfilter() */
  1751. #ifdef SET_DIR_ATTRIB
  1752. /* must sort saved directories so can set perms from bottom up */
  1753. /************************/
  1754. /*  Function dircomp()  */
  1755. /************************/
  1756. static int dircomp(a, b)   /* used by qsort(); swiped from Zip */
  1757.     ZCONST zvoid *a, *b;
  1758. {
  1759.     /* order is significant:  this sorts in reverse order (deepest first) */
  1760.     return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
  1761.  /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
  1762. }
  1763. #if 0   /* not used in Unix, but maybe for future OSes? */
  1764. /************************/
  1765. /*  Function namecmp()  */
  1766. /************************/
  1767. static int namecmp(s1, s2)   /* [not] used by dircomp(); swiped from Zip */
  1768.     ZCONST char *s1, *s2;
  1769. {
  1770.     int d;
  1771.     for (;;) {
  1772.         d = (int)(uch)case_map(*s1)
  1773.           - (int)(uch)case_map(*s2);
  1774.         if (d || *s1 == 0 || *s2 == 0)
  1775.             return d;
  1776.         s1++;
  1777.         s2++;
  1778.     }
  1779. }
  1780. #endif /* 0 */
  1781. #endif /* SET_DIR_ATTRIB */