Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "dz_errs.h"
  4.  
  5. #undef _DZ_FILE_
  6. #define _DZ_FILE_ DZ_UNZXTRCT_CPP
  7. /*
  8.   extract.c -
  9.  
  10.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  11.  
  12.   See the accompanying file LICENSE, version 2007-Mar-4 or later
  13.   (the contents of which are also included in zip.h) for terms of use.
  14.   If, for some reason, all these files are missing, the Info-ZIP license
  15.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  16.  
  17.   parts Copyright (C) 1997 Mike White, Eric W. Engler
  18. ************************************************************************
  19.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
  20.  
  21.    This file is part of TZipMaster Version 1.9.
  22.  
  23.     TZipMaster is free software: you can redistribute it and/or modify
  24.     it under the terms of the GNU Lesser General Public License as published by
  25.     the Free Software Foundation, either version 3 of the License, or
  26.     (at your option) any later version.
  27.  
  28.     TZipMaster is distributed in the hope that it will be useful,
  29.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  30.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31.     GNU Lesser General Public License for more details.
  32.  
  33.     You should have received a copy of the GNU Lesser General Public License
  34.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  35.  
  36.     contact: problems@delphizip.org (include ZipMaster in the subject).
  37.     updates: http://www.delphizip.org
  38.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  39. ************************************************************************/
  40.  
  41.  
  42. /* This version modified by Chris Vleghert and Eric W. Engler * for BCB/Delphi Zip, Sep 22, 2000.
  43. */
  44.  
  45. /*--------------------------------------------------------
  46. * extract.c
  47. * This file contains the high-level routines ("driver routines") for extrac-
  48. * ting and testing zipfile members.  It calls the low-level routines in files
  49. * explode.c, inflate.c, unreduce.c and unshrink.c.
  50. * Contains:  extract_or_test_files()
  51. *            store_info()   -> StoreInfo()
  52. *            extract_or_test_member()
  53. *            TestExtraField()   RCV Removed
  54. *            MemExtract()
  55. *            MemFlush()
  56. *            fnfilter()
  57. *-------------------------------------------------------------------------*/
  58. #include "DZOper.h"
  59. #include "UnzOp.h"
  60. #include <stdio.h>
  61.  
  62. /* ==================
  63. *    Function extract_or_test_files()
  64. */
  65. int UnzOpr::SelectMembers(void)
  66. {
  67.         /* return PK-type error code */
  68.         uch * cd_inptr;
  69.         int i, j = 0, cd_incnt;
  70.         int error, error_in_archive = PK_COOL;
  71.         unsigned members;
  72.         int why_skipped = 0;
  73.         ZInt64 cd_bufstart;
  74.         ulg sig;
  75.     ZInt64 TotSize;
  76.     unsigned fspecs;
  77.         UnzFileSpec *pfn;
  78.  
  79.     int cnt;
  80.         bool notEOC = false;
  81.         DZStrW g_excludes = MakeExclFilters();   // Process arguments
  82.     if (Verbose < 0)
  83.                 Notify(IVERBOSE, _T("Exclude: \"%s\""), g_excludes.c_str());
  84.  
  85.     ffilespecs = 0;
  86.     // get first spec and count
  87.     DZStrW fspec = CB->UserArg(zcbFSpecArgs, 0, &ffilespecs);
  88.         DZStrW spec;
  89.         DZStrW tmp;
  90.         unsigned index = 0;
  91.  
  92.     if (fspec.IsEmpty())
  93.     {
  94.                 ffilespecs = 1;
  95.                 spec = _T("*.*");
  96.                 fprocess_all_files = true;
  97.         }
  98.     else
  99.     if (ffilespecs < 2)
  100.         {
  101.                 // if is *.* just do all - quicker
  102.                 spec = GetArg(fspec, index, true);
  103.                 if (spec.IsEmpty() || !spec.Compare(_T("*.*")) || !spec.Compare(_T("*")))
  104.                 {
  105.                         fprocess_all_files = true;
  106.                         ffilespecs = 1;
  107.                 }
  108.         }
  109.         if (fprocess_all_files)
  110.                 fprocess_all_files = g_excludes.IsEmpty();
  111.  
  112.     if (Verbose < 0)
  113.         Notify(ITRACE, _T("search specs = %d, all = %d"), ffilespecs, fprocess_all_files ? 1 : 0);
  114.  
  115.     SrchSpecs = new UnzFileSpec[ffilespecs];
  116.     pfn = &SrchSpecs[0];
  117.  
  118.         bool ExcChanged = false;
  119.         pfn->Excludes = g_excludes;
  120.         for (i = 0; i < ffilespecs; i++)
  121.         {
  122.                 if (ExcChanged)
  123.                 {
  124.                         pfn->Excludes = g_excludes;
  125.             if (Verbose < 0)
  126.                                 Notify(IVERBOSE, _T("Exclude now: \"%s\""), pfn->Excludes.c_str());
  127.             ExcChanged = false;
  128.                 }
  129.                 // initial set Match -1= wild, 1=check
  130.                 if (i)
  131.                 {
  132.                         // get next
  133.                         fspec = CB->UserArg(zcbFSpecArgs, i, 0);
  134.                         if (!fspec)
  135.                         {
  136.                                 if (Verbose < 0)
  137.                                         Notify(ITRACE, _T("fewer specs than expected = %d [%d]"), i, ffilespecs);
  138.                                 ffilespecs = i;
  139.                                 break;
  140.                         }
  141.                 }
  142.                 index = 0;//1;
  143.                 tmp = GetArg(fspec, index, true);
  144.                 int nerr = CleanPath(tmp, spec);
  145.                 if (nerr < 0)
  146.                 {
  147.                         int bad = DZ_ERM_BAD_OPTIONS;
  148.                         if (Verbose)
  149.                                 Notify(bad, _T("invalid filespec %s"), fspec.c_str());
  150.                         return bad;
  151.                 }
  152.  
  153.                 if (spec.IsEmpty())
  154.                         spec = _T("*.*");   // presume they mean all
  155.  
  156.                 while (fspec[index] == '/')
  157.                 {
  158.                         // process switches
  159.                         tmp = GetArg(fspec, ++index, true);
  160.                         if (tmp.length() < 1)
  161.                                 continue;
  162.                         TCHAR ch = tmp[0]; // the switch
  163.                         if (tmp.length() >= 2 && tmp[1] == _T(':'))
  164.                         {
  165.                                 DZStrW tmp2;
  166.                                 switch (ch)
  167.                                 {
  168.                                         case _T('e'):
  169.                                         case _T('E'):
  170.                                                 tmp2 = ConvExclFilters(tmp.Mid(2));
  171.                                                 if (!tmp2.IsEmpty() && tmp[0] == _T('|'))
  172.                                                         tmp2 = g_excludes + tmp2; // append the new ones
  173. //                                                      fNoExtChk = 1;
  174. //                                              else
  175. //                                              if (tmp[0] == _T('|'))
  176. //                                                      tmp2 = g_excludes + tmp2; // append the new ones
  177.                                                 pfn->Excludes = tmp2;
  178.                                                 ExcChanged = true;
  179.  
  180.                                                 if (Verbose < 0)
  181.                                                         Notify(IVERBOSE, _T("Exclude now: \"%s\""), pfn->Excludes.c_str());
  182.                                                 break;
  183.                                         case _T('f'):
  184.                                         case _T('F'):
  185.                                                 if (tmp.length() == 2)
  186.                                                 {
  187.                                                         // use current dir
  188.                                                         if (!GetFullPathName(_T(".\\"), MAX_PATH, tmp.GetBuffer(MAX_PATH), NULL))
  189.                                                                 throw DZFatalException(DZ_ERM_MEMORY);
  190.                                                         tmp.ReleaseBuffer();
  191.                                                 }
  192.                                                 if (tmp.LastChar() != BSLASH)
  193.                                                         tmp += BSLASH;
  194.                                                 // new base folder
  195.                                                 if (CleanPath(tmp.Mid(2), tmp) == 0)//, checkA))
  196.                                                 {
  197.                                                         pfn->Base = AddBase(tmp, true);   // add to list, bring to front
  198.                                                 }
  199.                                                 break;
  200.                                         default:
  201.                                                 if (Verbose)
  202.                                                         Notify(IVERBOSE, _T("invalid switch %s ignored"), tmp.c_str());
  203.                                 }
  204.                                 continue;
  205.                         }
  206.           /*            if (tmp.length() >= 2 && tmp[1] == _T(':') &&
  207.                                 (ch == _T('f') || ch == _T('F')))
  208.                         {
  209.                                 if (tmp.length() == 2)
  210.                                 {
  211.                                         // use current dir
  212.                                         if (!GetFullPathName(_T(".\\"), MAX_PATH, tmp.GetBuffer(MAX_PATH), NULL))
  213.                                                 throw DZFatalException(DZ_ERM_MEMORY);
  214.                                         tmp.ReleaseBuffer();
  215.                                 }
  216.                                 if (tmp.LastChar() != BSLASH)
  217.                                         tmp += BSLASH;
  218.                                 // new base folder
  219.                                 if (CleanPath(tmp.Mid(2), tmp) == 0)//, checkA))
  220.                                 {
  221.                                         pfn->Base = AddBase(tmp, true);   // add to list, bring to front
  222.                                 }
  223.                                 continue;
  224.                         }
  225.                         if (Verbose)
  226.                                 Notify(IVERBOSE, _T("invalid switch %s ignored"), tmp.c_str());  */
  227.                 }
  228.                 if (fspec[index] == ZPasswordFollows)
  229.                 {
  230.                         tmp = tmp.Mid(++index);
  231.                         pfn->Password = AddPW(tmp, true);
  232.                 }
  233.                 if (!pfn->Base)
  234.                         pfn->Base = CurBase;  // default
  235.                 if (fprocess_all_files)
  236.                 {
  237.                         pfn->Match = -1;
  238.                         break;
  239.                 }
  240.  
  241.                 pfn->Spec = spec;
  242.                 pfn->Match = IsWild(spec) ? -1 : 1;
  243.                 pfn++;
  244.         }
  245.  
  246.     /*---------------------------------------------------------------------------
  247.     * Since the central directory lies at the end of the zipfile, and the
  248.     * member files lie at the beginning or middle or wherever, it is not very
  249.     * efficient to read a central directory entry, jump to the member file
  250.     * and extract it, and then jump back to the central directory.
  251.     *
  252.     * Instead, we read from the central directory the pertinent information
  253.     * for all files, then go extract/test the whole block.  Thus, this
  254.     * routine contains two loops:
  255.     * the first loop reads all files from the central directory storing
  256.     * information for the required files
  257.     * the second extracts or tests each file
  258.     *
  259.     * Because of this jumping around, we can afford to be lenient if an
  260.     * error occurs in one of the member files:  we should still be able to
  261.     * go find the other members, since we know the offset of each from the
  262.     * beginning of the zipfile.
  263.     *---------------------------------------------------------------------------*/
  264.     TotSize = 0;
  265.     chdrCount = 0;
  266.     fpInfo = NULL;
  267.  
  268.     // We're going to check each member file inside the archive
  269.     members = (ulg)fecrec.total_entries_central_dir;
  270.  
  271.     if (Verbose < 0)
  272.     {
  273.         Notify(ITRACE, _T("Searching for files to extract or test"));
  274.         Notify(ITRACE, _T("Central entries = %d, filespecs = %d"), members, ffilespecs);
  275.     }
  276.  
  277.         fnewzip = true;
  278.         freported_backslash = false;
  279.     CB->UserXItem(members, 9, _T("*Loading central"));
  280.  
  281.     cnt = 0;
  282.     cd_bufstart = fcur_zipfile_bufstart;
  283.     cd_inptr = finptr;
  284.     cd_incnt = fincnt;
  285.     fspecs = ffilespecs;
  286.     CHdrInfo *chdrEnd = NULL;
  287.     int chdrseq = 0;
  288.  
  289.     while (members && !Abort_Flag)
  290.     {
  291.         int DoThisFile = false;
  292.  
  293.         if (!fpInfo)
  294.         {
  295.             fpInfo = new CHdrInfo;
  296.         }
  297.         else
  298.             fpInfo->Clear();
  299.         fpInfo->chdrseq = chdrseq++;
  300.  
  301.         members--;
  302.  
  303.         if (readbuf((char*)&sig, 4) == 0)
  304.             break;
  305.  
  306.         if (sig != CentralFileHeaderSig)
  307.             break;
  308.  
  309.         if ((error = process_cdir_file_hdr()) != PK_COOL)
  310.             break;
  311.         if ((error = do_string(fcrec.filename_length, DS_FN)) != PK_COOL)
  312.         {
  313.             if (error > error_in_archive)
  314.                 error_in_archive = error;
  315.  
  316.         if (PK_ERR_NOWARN(error))
  317.                 break;   /* fatal */
  318.         }
  319.  
  320.         if ((error = do_string(fcrec.extra_field_length, EXTRA_FIELD)) != PK_COOL)
  321.         {
  322.             if (PK_Rank(error) > PK_Rank(error_in_archive))
  323.                 error_in_archive = error;
  324.  
  325.             if (PK_ERR_NOWARN(error))
  326.                     break;  /* fatal */
  327.         }
  328.  
  329.         do_string(fcrec.file_comment_length, SKIP);
  330.  
  331.                 int flen = fcrec.filename_length;
  332.                 fpInfo->HName = file_name;
  333.  
  334.                 DZStrW wn;
  335.                 if (fcrec.extra_field_length && (fEncodedAs == zeoAuto || fEncodedAs == zeoUPATH))
  336.                 {
  337.                         const UPhead *up = (const UPhead*)extra_field.Find(UPATH_XDATA_TAG);
  338.                         if (up && up->ver == 1 && up->hed.vsize > sizeof(UPhead))
  339.                         {
  340.                                 ulg ocrc = crc32(0, (uch*)file_name.c_str(), flen);
  341.                                 if (ocrc == up->crc)
  342.                                 {
  343.                                         int len = up->hed.vsize - 5;
  344.                                         const char *bf = ((char*)up) + sizeof(UPhead);
  345.                                         wn = DZStrW(CP_UTF8, bf, len);
  346.                                 }
  347.                         }
  348.  
  349.                 }
  350.                 // use UPATH if was available
  351.                 if (wn.IsEmpty())
  352.                 {
  353.                         int Enc = IsEncoded((ush)fpInfo->host, fpInfo->UTF8flag);
  354.                         if (Enc == zeoAuto && ValidUTF8(file_name) > 0)
  355.                                 Enc = zeoUTF8;
  356.                         int UseCP;
  357.                         switch ((Encodings)Enc)
  358.                         {
  359.                                 case zeoAuto:
  360.                                 case zeoNone: UseCP = fFromPage;
  361.                                         break;
  362.  
  363.                                 case zeoUTF8: UseCP = CP_UTF8;
  364.                                         break;
  365.  
  366.                                 case zeoOEM: UseCP = CP_OEM;
  367.                                         break;
  368.                         }
  369.                         wn = DZStrW(UseCP, file_name.c_str(), flen);
  370.                 }
  371.  /*  defer test until extract
  372.                 DZStrW wt = StrExtSep(wn);
  373.                 int nerr = CleanPath(wt, ffilename);
  374.                 if (nerr)
  375.                 {
  376.                         if (Verbose)
  377.                                 Notify(IVERBOSE, _T("read file - invalid filename %s [%d]"),
  378.                                                                 fpInfo->hname, nerr);
  379.                         error_in_archive = DZ_ERR_INVAL_NAME;
  380.                         break;  // fatal
  381.                 }     */
  382.                 ffilename = StrExtSep(wn);
  383.                 fpInfo->XName = ffilename;
  384.  
  385.         pfn = (UnzFileSpec *) SrchSpecs;
  386.  
  387.                 if (fprocess_all_files)
  388.             DoThisFile = true;
  389.         else
  390.                 {
  391.                         unsigned hash = HashFunc(ffilename);
  392.             int k = 0;
  393.             for (; k < ffilespecs; k++, ++pfn)
  394.                         {
  395.                                 DoThisFile = false;
  396.                 if (pfn->Match)
  397.                                 {
  398.  
  399.                                         if (pfn->Match == 1)
  400.                                         {
  401.                                                 if (pfn->Hash != hash)
  402.                                                         continue;   // not wild and will not match
  403.                                         }
  404.  
  405.                                         const TCHAR *fs = pfn->FileSpec;
  406.                                         if (Is_Drv(pfn->FileSpec) < 0)
  407.                                                 fs += DriveLen(pfn->FileSpec); // get filename for stream
  408.  
  409.                                         if (ZMatch(fs, ffilename))
  410.                                         {
  411.                                                 DZStrW exc = pfn->Excludes;
  412.                                                 DoThisFile = exc.IsEmpty() ? true : !ZMatch(exc, ffilename);
  413. //                                              DoThisFile = true;
  414.  
  415.                                                 pfn->Match = pfn->Match & -2;   // reset bit 0 for match
  416.                                                 if ((!pfn->Match) &&
  417.                                                                 (! --fspecs)) // removed non-wild from search
  418.                         {
  419.                             members = 0; // none left to match
  420.                             notEOC = true;
  421.                         }
  422.  
  423.                                                 if (Verbose < 0)
  424.                                                         Notify(ITRACE, _T("Matched %s"), ffilename.c_str());
  425.  
  426.                         break;  // found match, so stop looping
  427.                     }
  428.                 }
  429.             }
  430.         }
  431.  
  432.         if (DoThisFile)
  433.         {
  434.             int r;
  435.  
  436.             if ((r = StoreInfo()) == 0)
  437.             {
  438.                 if (Verbose < 0) //** less noisy
  439.                     Notify(ITRACE, _T("selected: %s"), ffilename.c_str());
  440.  
  441.                 fpInfo->spec = pfn;
  442.                 j++;
  443.                 TotSize += fcrec.ucsize;
  444.  
  445.                 if (chdrList)
  446.                     chdrEnd->next = fpInfo;   // append to list
  447.                 else
  448.                     chdrList = fpInfo;       // first in list
  449.  
  450.                 chdrEnd = fpInfo;
  451.                 fpInfo = NULL;              // been used
  452.                 chdrCount++;
  453.             }
  454.             else
  455.                         {
  456.                                 bool usr = Skipping(ffilename, 0, r);
  457.  
  458.                 if (!why_skipped)
  459.                     why_skipped = r;
  460.                 else
  461.                     if (why_skipped != r)
  462.                         why_skipped = -1;
  463.                                 if (usr)
  464.                                 {
  465.                                         error_in_archive = DZ_ERR_SKIPPED;
  466.                     break;
  467.                 }
  468.             }
  469.         }
  470.  
  471.         if (++cnt >= 50)
  472.         {
  473.             CB->UserXProgress(cnt, 9);
  474.             cnt = 0;
  475.         }
  476.     }
  477.  
  478.         if (cnt)
  479.                 CB->UserXProgress(cnt, 9);
  480.  
  481.     // delete if unused
  482.     if (fpInfo)
  483.     {
  484.  
  485.         CHdrInfo* tmp = fpInfo;
  486.  
  487.         fpInfo = NULL;
  488.  
  489.         delete tmp;
  490.     }
  491.  
  492.     if (PK_ERR_NOWARN(error_in_archive))
  493.         return error_in_archive;  /* fatal */
  494.  
  495.     CB->Arg1 = j;
  496.     CB->UserCB(zacCount);
  497.     CB->FileSize = TotSize;
  498.     CB->UserCB(zacSize);
  499.  
  500.     /*---------------------------------------------------------------------------
  501.     * Double-check that we're back at the end-of-central-directory record, and
  502.     * print quick summary of results, if we were just testing the archive.
  503.     *---------------------------------------------------------------------------*/
  504.  
  505.     if (readbuf((char*)&sig, 4) == 0)
  506.     {
  507.         if (Verbose)
  508.             Notify(ITRACE, _T("bad signature at end of archive, or premature EOF"));
  509.  
  510.         error_in_archive = PK_EOF;
  511.     }
  512.  
  513.     if (sig != EndCentralDirSig && sig != EndCentral64Sig &&
  514.             (notEOC && sig != CentralFileHeaderSig))
  515.     {
  516.         /* just to make sure */
  517.         Notify(IWARNING,  _T("Bad Ending Signature for Central dir"));
  518.  
  519.         if (!error_in_archive) /* don't overwrite stronger error */
  520.             error_in_archive = PK_WARN;
  521.     }
  522.  
  523.  
  524.     // RCV Changed 29-1-99 USE_STREAM_INPUT
  525.         fcur_zipfile_bufstart = fUnzInfile->SetPosition(cd_bufstart, SEEK_SET);
  526.     vclRead((char *) finbuf, INBUFSIZ);
  527.  
  528.     finptr = cd_inptr;
  529.     fincnt = cd_incnt;
  530.  
  531.     return error_in_archive;
  532. }
  533.  
  534. // true = overwrite
  535. int UnzOpr::AskOverwrite(const DZStrW& filename, int cond)
  536. {
  537.         int ucb;
  538.         int ret = 1;   // default overwrite
  539.     switch (cond)
  540.     {
  541.  
  542.         case DOES_NOT_EXIST:
  543.             // NOVELL_BUG_FAILSAFE:
  544.             //            fdne = true;
  545.             /* stat() says file DOES NOT EXIST */
  546.             /* if freshening, don't skip if just renamed */
  547.  
  548.             if (ffflag)
  549.                         {
  550.                                 ret = Skipping(filename, 0, SKIPPED_ON_FRESHEN /*fpInfo->chdrseq */) ? -1 : 0;
  551.                 /* freshen (no new files):  skip */
  552.             }
  553.  
  554.             break;
  555.  
  556.         case EXISTS_AND_OLDER:
  557.             // Ask the user what to do, take overwrite_all as default. RCV: 1.6010
  558.             CB->Arg3 = 1;
  559.             CB->Arg2 = fpInfo->chdrseq;
  560.             CB->Arg1 = foverwrite_all;
  561.             CB->Msg = filename;
  562.             ucb = CB->UserCB(zacOverwrite);
  563.  
  564.             if (ucb <= 0)           // no response - use default
  565.                 ucb = foverwrite_all ? CALLBACK_TRUE : CALLBACK_2;
  566.  
  567.             if (ucb != CALLBACK_TRUE)          // responded 'no'
  568.                         {
  569.                                 ret = Skipping(filename, 0, SKIPPED_NO_OVERWRITE) ? -1 : 0;
  570.                 if (Verbose)
  571.                     Notify(ITRACE, _T("File exists: %s, overwrite false"),
  572.                                                         filename.c_str());
  573.                                  /* never overwrite:  skip file */
  574.             }
  575.             break;
  576.  
  577.         case EXISTS_AND_NEWER:
  578.             /* or equal */
  579.             // Ask the user what to do, take overwrite_all as default. RCV: 1.6010
  580.             // If no event handler present w'll keep the default.
  581.             CB->Arg3 = 2;
  582.             CB->Arg2 = fpInfo->chdrseq;
  583.             CB->Arg1 = foverwrite_all && !(fuflag || ffflag);
  584.             CB->Msg = filename;
  585.             ucb = CB->UserCB(zacOverwrite);
  586.  
  587.             if (ucb <= 0)           // no response - use default
  588.                 ucb = CB->Arg1 ? CALLBACK_TRUE : CALLBACK_2;
  589.  
  590.                         if (ucb != CALLBACK_TRUE)          // responded 'skip'
  591.                         {
  592.                                 if (Verbose)
  593.                                         Notify(ITRACE, _T("File exists: %s, skipped"), filename.c_str());
  594.                                 ret = Skipping(filename, 0, SKIPPED_FILE_EXISTS) ? -1 : 0;
  595.                 /* skip if update/freshen & orig name */
  596.                         }
  597.     }     /* end switch */
  598.     return ret;
  599. }
  600.  
  601. int UnzOpr::extract_or_test_files(void)
  602. {
  603.     /* return PK-type error code */
  604.     int i, filnum = (-1);
  605.     int error, error_in_archive;// = PK_COOL;
  606.     unsigned num_skipped = 0, num_bad_pwd = 0;
  607.     int why_skipped = 0;
  608.     int did_skip = 0;       // skipped previous file
  609.     ZInt64 bufstart, inbuf_offset, request;
  610.     ZInt64 old_extra_bytes = 0;
  611.     ZInt64 fsize;
  612.     ulg sig;
  613.  
  614.     int changed;
  615.         int ucb;          // result of user_cb
  616.  
  617.         error_in_archive = SelectMembers();
  618. //  if (Verbose < 0)
  619. //    Notify(ITRACE, "starting main loop");
  620.  
  621.     InProgress = false;
  622.     fBytesWritten = 0;
  623.     /*---------------------------------------------------------------------------
  624.     *    Begin main loop over member files.
  625.     *---------------------------------------------------------------------------*/
  626.     const TCHAR *OpMsg = ftflag ? _T("test") : _T("extract");
  627.  
  628.     if (Verbose)
  629.         Notify(IVERBOSE,  _T("Expects to %s %d files"), OpMsg, chdrCount);
  630.  
  631.     /*-----------------------------------------------------------------------
  632.     *  Second loop:  process files in current block, extracting or testing
  633.     *  each one.
  634.     *-----------------------------------------------------------------------*/
  635.     if (Verbose < 0)
  636.         Notify(ITRACE, _T("starting second loop - THIS TIME we take action."));
  637.  
  638.     CHdrInfo* Info = chdrList;
  639.  
  640.     DZStrW CurrentName;
  641.  
  642.         while (Info)
  643.     {
  644.         if (did_skip)
  645.                 {
  646. //                      did_skip = 0;
  647.                         if (Skipping(ffilename, 0, did_skip))
  648.                         {
  649.                                 Fatal(DZ_ERM_SKIPPED, 2, false);
  650.                                 break;
  651.                         }
  652.                         did_skip = 0;
  653.         }
  654.                 if (Abort_Flag)
  655.                 {
  656.                         Fatal(DZ_ERM_CANCELLED, 2, false);
  657.                         break;
  658.                 }
  659.         fpInfo = Info;
  660.         Encrypted = fpInfo->encrypted != 0;
  661.         Info = Info->next;
  662.         filnum++;
  663.         CurrentName = fpInfo->XName;
  664.  
  665.                 if (Verbose < 0)   //** less noisy
  666.             Notify(ITRACE, _T("%sing %s"), OpMsg, CurrentName.c_str());
  667.  
  668.         /* if the target position is not within the current input buffer
  669.         * (either haven't yet read far enough, or (maybe) skipping back-
  670.         * ward), skip to the target position and reset readbuf(). */
  671.         request = fpInfo->offset + fextra_bytes;
  672.         inbuf_offset = request % INBUFSIZ;
  673.         bufstart = request - inbuf_offset;
  674.  
  675.         if (Verbose < 0)
  676.             Notify(ITRACE, _T("loc A: request = %Ld, inbuf_offset = %Ld"),
  677.                 request, inbuf_offset);
  678.  
  679.         if (request < fpInfo->offset)
  680.         {
  681.                         DZError(DZ_ERM_INVAL_ZIP);
  682.             error_in_archive = PK_ERR;
  683.  
  684.             if (filnum == 0 && fextra_bytes != 0L)
  685.             {
  686.                 if (Verbose < 0)
  687.                     Notify(ITRACE,  _T("attempting to recompensate"));
  688.  
  689.                 old_extra_bytes = fextra_bytes;
  690.                 fextra_bytes = 0L;
  691.                 request = fpInfo->offset;
  692.  
  693.                 /* could also check if this != 0 */
  694.                 inbuf_offset = request % INBUFSIZ;
  695.                 bufstart = request - inbuf_offset;
  696.  
  697.                 if (Verbose < 0)
  698.                     Notify(ITRACE, _T("loc B: request = %Ld, inbuf_offset = %Ld"),
  699.                         request, inbuf_offset);
  700.             }
  701.             else
  702.             {
  703.                 error_in_archive = PK_BADERR;
  704.                                 if (Verbose)
  705.                     Notify(ITRACE, _T("loc A: hosed - try next file"));
  706.  
  707.                 continue;    /* this one hosed; try next */
  708.             }
  709.         }
  710.  
  711.         /* try again */
  712.         if (request < 0)
  713.         {
  714.             if (Verbose < 0)
  715.                 Notify(0, _T("the recompensated request is still < 0"));
  716.  
  717.                         DZError(DZ_ERM_INVAL_ZIP);
  718.             did_skip = SKIPPED_FILEFORMAT_WRONG;
  719.             error_in_archive = PK_BADERR;
  720.             continue;
  721.         }
  722.         else
  723.             if (bufstart != fcur_zipfile_bufstart)
  724.             {
  725.                 if (Verbose < 0)
  726.                     Notify(ITRACE, _T("bufstart != cur_zipfile_bufstart"));
  727.  
  728.                 // RCV Changed 29-1-99 USE_STRM_INPUT
  729.                 fcur_zipfile_bufstart = fUnzInfile->SetPosition(bufstart, SEEK_SET);
  730.  
  731.                 fincnt = vclRead((char *) finbuf, INBUFSIZ);
  732.  
  733.                 if (fincnt <= 0)
  734.                 {
  735.                                         DZError(DZ_ERM_INVAL_ZIP);
  736.                     error_in_archive = PK_BADERR;
  737.  
  738.                                         if (Verbose)
  739.                         Notify(ITRACE, _T("B. hosed - try next file"));
  740.  
  741.                     continue;    /* can still do next file */
  742.                 }
  743.  
  744.                 finptr = finbuf + (int)inbuf_offset;
  745.                 fincnt -= (int)inbuf_offset;
  746.             }
  747.             else
  748.             {
  749.                 fincnt += (int)(finptr - finbuf) - (int)inbuf_offset;
  750.                 finptr = finbuf + (int)inbuf_offset;
  751.             }
  752.  
  753.         /* should be in proper position now, so check for sig */
  754.         if (readbuf((char*)&sig, 4) == 0)
  755.         {
  756.             /* bad offset */
  757.                         DZError(DZ_ERM_INVAL_ZIP);
  758.             did_skip = SKIPPED_FILEFORMAT_WRONG;
  759.             error_in_archive = PK_BADERR;
  760.             continue;      /* but can still try next one */
  761.  
  762.         }
  763.  
  764.         if (sig != LocalFileHeaderSig)
  765.         {
  766.                         DZError(DZ_ERM_INVAL_ZIP);
  767.             error_in_archive = PK_ERR;
  768.  
  769.             if ((filnum == 0 && fextra_bytes != 0L)
  770.                     || (fextra_bytes == 0L && old_extra_bytes != 0L))
  771.             {
  772.                 if (Verbose < 0)
  773.                     Notify(ITRACE,  _T("Attempting to Recompensate"));
  774.  
  775.                 if (fextra_bytes)
  776.                 {
  777.                     old_extra_bytes = fextra_bytes;
  778.                     fextra_bytes = 0L;
  779.                 }
  780.                 else
  781.                     fextra_bytes = old_extra_bytes;
  782.  
  783.                 /* third attempt */
  784.                 zlseek(fpInfo->offset);
  785.  
  786.                 if (readbuf((char*)&sig, 4) == 0)
  787.                 {
  788.                     /* bad offset */
  789.                                         DZError(DZ_ERM_INVAL_ZIP);
  790.                     did_skip = SKIPPED_FILEFORMAT_WRONG;
  791.                     error_in_archive = PK_BADERR;
  792.                     continue;         /* but can still try next one */
  793.  
  794.                 }
  795.  
  796.                 if (sig != LocalFileHeaderSig)
  797.                 {
  798.                                         DZError(DZ_ERM_INVAL_ZIP);
  799.                     error_in_archive = PK_BADERR;
  800.                     continue;
  801.                 }
  802.             }
  803.             else
  804.             {
  805.                 if (Verbose)
  806.                     Notify(ITRACE, _T("C: hosed - try next file"));
  807.  
  808.                 continue;          /* this one hosed; try next */
  809.             }
  810.         }
  811.  
  812.         if (Verbose < 0)
  813.             Notify(ITRACE, _T("about to process local file hdr"));
  814.  
  815.                 if ((error = process_local_file_hdr()) != PK_COOL)
  816.         {
  817.                         DZError(DZ_ERM_INVAL_ZIP);
  818.             did_skip = SKIPPED_FILEFORMAT_WRONG;
  819.             error_in_archive = error;  /* only PK_EOF defined */
  820.  
  821.             if (Verbose)
  822.                 Notify(ITRACE, _T("D. hosed - try next file"));
  823.  
  824.             continue;         /* can still try next one */
  825.         }
  826.  
  827.         if ((error = do_string(flrec.filename_length, DS_FN)) != PK_COOL)
  828.         {
  829.             if (PK_Rank(error) > PK_Rank(error_in_archive))
  830.                 error_in_archive = error;
  831.  
  832.         if (PK_ERR_NOWARN(error))
  833.             {
  834.                 did_skip = SKIPPED_FILEFORMAT_WRONG;
  835.                                 DZError(DZ_ERM_INVAL_ZIP);
  836.  
  837.                 if (Verbose)
  838.                     Notify(ITRACE, _T("E. hosed - try next file"));
  839.  
  840.                 continue;       /* go on to next one */
  841.             }
  842.         }
  843.  
  844.         extra_field.Empty();
  845.  
  846.         if ((error = do_string(flrec.extra_field_length, EXTRA_FIELD)) != 0)
  847.         {
  848.             if (PK_Rank(error) > PK_Rank(error_in_archive))
  849.                 error_in_archive = error;
  850.  
  851.             if (PK_ERR_NOWARN(error))
  852.             {
  853.                 did_skip = SKIPPED_FILEFORMAT_WRONG;
  854.                                 DZError(DZ_ERM_INVAL_ZIP);
  855.                 if (Verbose)
  856.                     Notify(ITRACE, _T("F. hosed - try next file"));
  857.                 continue;    /* go on */                  
  858.             }
  859.         }
  860.  
  861.         /* Just about to extract file:  if extracting to disk, check if
  862.         * already exists, and if so, take appropriate action according to
  863.         * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  864.         * loop because we don't store the possibly renamed filename[] in
  865.         * info[]) */
  866.         // use central name
  867.         if (file_name.CompareNoCase(fpInfo->HName))
  868.         {
  869.             error = PK_WARN;
  870.             Notify(IWARNING, _T("Names do not match - using '%s' [local:%s]"),
  871.                    CurrentName.c_str(), file_name.c_str());
  872.  
  873.             if (error > error_in_archive)
  874.                 error_in_archive = error;
  875.         }
  876.  
  877.         if (Is_Drv(fpInfo->spec->Spec) < 0)
  878.             ffilename = fpInfo->spec->Spec;
  879.         else
  880.         {
  881.             ffilename = CurrentName;
  882.  
  883.                         if (!ftflag)
  884.             {
  885.                 /* for files from DOS FAT, check for use of backslash instead
  886.                 * of slash as directory separator (bug in some zipper(s); so
  887.                                 * far, not a problem in HPFS, NTFS or VFAT systems) */
  888.                                 if (((fpInfo->host & 0xff00) == (FS_FAT_ * 256)) &&
  889.                                         ffilename.ReverseFind(_T('/')) >= 0)
  890.                                 {
  891.                                         ffilename = StrExtSep(ffilename);
  892.  
  893.                     if (Verbose < 0)
  894.                         Notify(ITRACE, _T("parsing a FAT file"));
  895.                 }
  896.  
  897.                 ucb = CB->UserCB(zacExtName, ffilename, fpInfo->spec->Base->BaseDir);
  898.                 if (Abort_Flag)
  899.                 {
  900.                     Fatal(DZ_ERM_CANCELLED, 2, false);
  901.                     break;
  902.                 }
  903.                 changed = 0;
  904.                 if (ucb == CALLBACK_TRUE)      // changed
  905.                                 {
  906.                                         unsigned index = 0;
  907.                                         DZStrW nname = StrExtSep(CB->Msg);
  908.                                         DZStrW tmp = GetArg(nname, index, false);
  909.                                         int ss = CleanPath(tmp, nname);
  910.                                         if (ss < 0 || ss == Z_WILD)
  911.                                         {
  912.                                                 if (Verbose)//< 0)
  913.                                                         Notify(ITRACE, _T("invalid new name %s"), nname.c_str());
  914.                                                 error_in_archive = PK_ERR;
  915.                                                 did_skip = SKIPPED_BAD_NAME;
  916.                                                 continue; // try next
  917.                                         }
  918.                     if (!nname)
  919.                     {
  920.                         if (Verbose)//< 0)
  921.                             Notify(ITRACE, _T("file ignored - try next file"));
  922.                         error_in_archive = PK_ERR;
  923.                         did_skip = SKIPPED_USER;
  924.                         continue; // try next
  925.                     }
  926.  
  927.                     bool wasDir = ffilename.LastChar() == BSLASH;
  928.                     if ((nname.LastChar() == BSLASH) != wasDir)
  929.                     {
  930.                         if (Verbose)
  931.                             Notify(IVERBOSE, _T("Must not change %s to %s"),
  932.                                 ffilename.c_str(), nname.c_str());
  933.                                                 error_in_archive = PK_ERR;
  934.                                                 did_skip = SKIPPED_BAD_NAME;
  935.                         continue; // try next
  936.                     }
  937.  
  938.                     if (Verbose)
  939.                         Notify(IVERBOSE,  _T("filename changed from %s to %s"),
  940.                             ffilename.c_str(), nname.c_str());
  941.                                         if (fpInfo->ntfs_data && (ffilename.CompareNoCase(nname.Right(ffilename.length()))))
  942.                     {
  943.                         delete fpInfo->ntfs_data;   // new file - times invalid
  944.                         fpInfo->ntfs_data = NULL;
  945.                         if (Verbose)
  946.                             Notify(IVERBOSE,  _T("filename changed - times invalid"));
  947.                     }
  948.                     ffilename = nname;
  949.                     changed++;
  950.                 }
  951.                                 // verify an acceptable filename
  952.                                 DZStrW wt = ffilename;//StrExtSep(wn);
  953.                                 int nerr = CleanPath(wt, ffilename);
  954.                                 if (nerr)
  955.                                 {
  956.                                         if (Verbose)
  957.                                                 Notify(IVERBOSE, _T("extract file - invalid filename %s [%d]"),
  958.                                                                                 /*fpInfo->hname*/wt.c_str(), nerr);
  959.                                         error_in_archive = DZ_ERR_INVAL_NAME;
  960.                                         did_skip = SKIPPED_BAD_NAME;
  961.                                         continue; // skip file
  962.                                 }
  963.  
  964.                                 // filename contains the name as stored in the archive if the user want
  965.                                 // to extract directories too then this part of the path is also present.
  966.                                 // So we only need to complement it with the currentdir or the extractbasedir.
  967.                                 /* Mapname can create dirs if not freshening or if renamed(now always false) */
  968.                                 error = mapname(changed);
  969.                                 if (error < 0)
  970.                                 {
  971.                                         if (error == IZ_CREATED_DIR || error == IZ_SKIP_DIR)
  972.                                         {
  973.                                                 /* GRR:  add code to set times/attribs on dirs--
  974.                                                 * save to list, sort when done (a la zip), set
  975.                                                 * times/attributes on deepest dirs first */
  976.                                                 int doset = 0;
  977.                                                 if (error == IZ_CREATED_DIR)
  978.                                                 {
  979.                                                         Notify(0,  _T("   created: %s"), ffilename.c_str());
  980.                                                         doset = 1;//true; // didn't exist
  981.                                                 }
  982.                                                 if (!changed && fpInfo->ntfs_data)
  983.                                                 {
  984.                                                         doset = AskOverwrite(ffilename, doset ? -1 :
  985.                                                                                 check_for_newer(ffilename));
  986.                                                         if (doset < 0)
  987.                                                                 Fatal(DZ_ERM_ABORT, 2);
  988.                                                         if (doset > 0)
  989.                                                         {
  990.                                                                 bool notset = true;
  991.                                                                 // set folder stamp
  992.                                                                 HANDLE hFolder = CreateFile(ffilename, GENERIC_WRITE,
  993.                                                                                 FILE_SHARE_READ, NULL, OPEN_EXISTING,
  994.                                                                                 FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS, NULL);
  995.                                                                 if(hFolder != INVALID_HANDLE_VALUE)
  996.                                                                 {
  997.                                                                         notset = !SetFileTime(hFolder, &fpInfo->ntfs_data->CTime,
  998.                                                                         &fpInfo->ntfs_data->ATime, &fpInfo->ntfs_data->MTime);
  999.                                                                         CloseHandle(hFolder);
  1000.                                                                 }
  1001.                                                                 if (notset && Verbose < 0)
  1002.                                                                         Notify(IWARNING, _T("Could not set times for %s"),
  1003.                                                                                 ffilename.c_str());
  1004.                                                         }
  1005.                                                 }
  1006.                                         }
  1007.                                         //-----------------------------------------------------------
  1008.                                         // BUG FIX since v1.4: bump up the file count when we extract
  1009.                                         // a dirname (whether or not it already existed).
  1010.                                         // This keeps SuccessCnt in line with TZipContents.Count
  1011.                                         ffiles_acted_on++;
  1012.                                         //-----------------------------------------------------------
  1013.                                         continue;  // don't try to 'extract' it
  1014.                                 }
  1015.                                 if (PK_Rank(error) > PK_Rank(PK_WARN))
  1016.                                 {
  1017.                                         if (error == IZ_VOL_LABEL)
  1018.                                         {
  1019.                                                 if (Verbose)// < 0)
  1020.                                                         Notify(ITRACE, _T("file is a vol label"));
  1021.  
  1022.                                                 DZError(DZ_ERM_INVAL_ZIP);
  1023.                                         }
  1024.                                         else
  1025.                                         if (PK_Rank(error) > PK_Rank(PK_ERR) &&
  1026.                                                         PK_Rank(error_in_archive) < PK_Rank(PK_ERR))
  1027.                                         {
  1028.                                                 if (Verbose)// < 0)
  1029.                                                         Notify(IVERBOSE, _T("f hosed - try next file"));
  1030.                                                 error_in_archive = PK_ERR;
  1031.                                         }
  1032.  
  1033.                     if (Verbose < 0)
  1034.                         Notify(ITRACE, _T("mapname(%s) returns error = %d"),
  1035.                             ffilename.c_str(), error);
  1036.                     continue;     /* go on to next file */
  1037.                 }
  1038.  
  1039.                 // v1.6024
  1040.                 flrec.filename_length = (WORD)ffilename.length();
  1041.  
  1042.                 if (Abort_Flag)
  1043.                                         Fatal(DZ_ERM_ABORT, 0);
  1044.  
  1045.                 if (Verbose < 0)
  1046.                     Notify(ITRACE, _T("starting switch near Novell failsafe in extract.c"));
  1047.                 int ucb = AskOverwrite(ffilename, check_for_newer(ffilename));
  1048.                 if (ucb < 0)
  1049.                                         Fatal(DZ_ERM_ABORT, 2);
  1050.                                 if (!ucb)
  1051.                     continue;
  1052.             }   /* end if (extracting to disk) */
  1053.         }
  1054.  
  1055.                 if (Verbose < 0)
  1056.             Notify(ITRACE, _T("in extract.c, about to call decrypt"));
  1057.  
  1058.         ulg crc = fpInfo->ExtLocHdr ? flrec.last_mod_file_time >> 8 : (ush)(flrec.crc32 >> 24);
  1059.  
  1060.         if (Encrypted)
  1061.         {
  1062.             if (fpInfo->spec->Password)                                                  
  1063.                 fkey = fpInfo->spec->Password;   // use copy of specified
  1064.             else
  1065.                 fkey = AddPW(fpwdarg, false);     // use global
  1066.  
  1067.             if ((error = decrypt(crc)) != PK_COOL)
  1068.                         {
  1069.                                 ++num_bad_pwd;
  1070.  
  1071.                                 if (Verbose < 0)
  1072.                                         Notify(ITRACE, _T("Skipping encrypted file %s, bad password"),
  1073.                                                 ffilename.c_str());
  1074.                                 if (Skipping(ffilename, 0, SKIPPED_BAD_PASSWORD))
  1075.                                         Fatal(DZ_ERM_SKIPPED, 2);
  1076.  
  1077.                 if (Abort_Flag)
  1078.                 {
  1079.                     Fatal(DZ_ERM_CANCELLED, 2, false);
  1080.                                         break;
  1081.                 }
  1082.                 continue;  // go on to next file
  1083.             }
  1084.                 }
  1085.                 fdisk_full = 0;
  1086.  
  1087.         if (Abort_Flag)
  1088.                         Fatal(DZ_ERM_ABORT, 0);
  1089.  
  1090.         fsize = flrec.ucsize;
  1091.                 CB->UserItem(fsize, ffilename);
  1092.  
  1093.         // ====================================================
  1094.         // Function:  extract_or_test_member() does the unzip
  1095.         // ====================================================
  1096.  
  1097.                 if ((error = extract_or_test_member()) != PK_COOL)
  1098.         {
  1099.             int zerr = DZ_ERR(error);
  1100.             if (zerr <= DZ_ERR_CALLBACK)
  1101.             {
  1102.                 Fatal(DZ_ERM_CANCELLED, 2, false);
  1103.                 break;
  1104.             }
  1105.             if (zerr != DZ_ERR(PK_WARN) &&
  1106.                 (zerr == DZ_ERR(PK_BADERR) || zerr == DZ_ERR(PK_NOZIP) ||
  1107.                 zerr == DZ_ERR(PK_FIND) || zerr == DZ_ERR(PK_EOF)))
  1108.             {
  1109.                 /* abort check v1.6026 */
  1110.                                 DZError(error);
  1111.                 break;
  1112.             }
  1113.  
  1114.                         if (Skipping(ffilename, error, SKIPPED_EXTRACT_ERROR))
  1115.                                 return DZ_ERR_SKIPPED;
  1116.  
  1117.             if (Verbose)// < 0)
  1118.                 Notify(ITRACE, _T("error occured while extracting or testing"));
  1119.  
  1120.             if (error > error_in_archive)
  1121.                 error_in_archive = error;
  1122.  
  1123.             /* ...and keep going */
  1124.             if (fdisk_full > 1)
  1125.             {
  1126.                 return error_in_archive;
  1127.             }
  1128.         }
  1129.         else
  1130.         {
  1131.             Notify(IMSG,  _T("%s file %s of size %Lu"), ftflag ?
  1132.                 _T("Tested  ") : _T("Unzipped"), ffilename.c_str(), fsize);
  1133.             ffiles_acted_on++;
  1134.                 }
  1135.                 /* TODO 1 -oRP -cenhancement : Finished Item */
  1136.     }
  1137.  
  1138.     /* end for-loop (i:  files in current block) */
  1139. //  if (Verbose < 0)
  1140. //    Notify(ITRACE, "done with big outer block");
  1141.     CB->UserCB(zacEndOfBatch); // done with a batch of files
  1142.  
  1143.     /*---------------------------------------------------------------------------
  1144.     *  Check for unmatched filespecs on command line and print warning if any *  found.  Free allocated memory.
  1145.     *---------------------------------------------------------------------------*/
  1146.     if (Abort_Flag)
  1147.                 return Fatal(DZ_ERM_ABORT, 0, false);
  1148.  
  1149.     // R. Peters - changed reporting fn_matched not used
  1150.     if (!fprocess_all_files && ffilespecs > 0 && SrchSpecs)
  1151.     {
  1152.         UnzFileSpec *pfn = SrchSpecs;
  1153.  
  1154.         for (i = 0; i < ffilespecs; i++)
  1155.         {
  1156.             // initial bit 0 set if not found
  1157.             if (pfn->Match & 1)
  1158.             {
  1159.                 UnzMsg.Format(_T("Filespec Not Matched: %s"), pfn->FileSpec);
  1160.                                 DZError(DZ_ERM_MISS);
  1161.  
  1162.                 if (!DZ_ERR(error_in_archive) || DZ_ERR(error_in_archive) == PK_WARN)
  1163.                     error_in_archive = PK_FIND; // some files not found
  1164.             }
  1165.  
  1166.             pfn++;
  1167.         }
  1168.     }
  1169.  
  1170.     ++filnum;
  1171.  
  1172.     /* initialized to -1, so now zero if no files found */
  1173.     if (Verbose < 0)
  1174.         Notify(ITRACE, _T("filnum = %d"), filnum);
  1175.  
  1176.     if (ftflag)
  1177.     {
  1178.         // testing archive
  1179.         int num = filnum - num_bad_pwd;
  1180.  
  1181.         if (fqflag < 2)
  1182.         {
  1183.             /* GRR 930710:  was (fqflag == 1) */
  1184.             if (error_in_archive)
  1185.             {    
  1186.                 UnzMsg.Format(_T("Error In Archive %s %s"),
  1187.                     (error_in_archive == 1) ? _T("warning-") : _T(" "), fzipfn.c_str());
  1188.                                 DZError(DZM_MessageBit | DZ_ERM_GENERAL, UnzMsg);
  1189.             }
  1190.             else
  1191.                 if (num == 0)
  1192.                 {
  1193.                     UnzMsg.Format(_T("No Files Tested %s"), fzipfn.c_str());
  1194.                     Notify(0, UnzMsg);
  1195.                 }
  1196.                 else
  1197.                     if (fprocess_all_files && (num_skipped + num_bad_pwd == 0))
  1198.                     {
  1199.                         UnzMsg.Format(_T("no error in %s"), fzipfn.c_str());
  1200.                         Notify(0, UnzMsg);
  1201.                     }
  1202.                     else
  1203.                     {
  1204.                         if (num > 1)
  1205.                                                         UnzMsg.Format(_T("No Errors Found In %d Tested Files of %s"),
  1206.                                                                         num, fzipfn.c_str());
  1207.                         else
  1208.                                                         UnzMsg.Format(_T("No Error Found In %d Tested File of %s"),
  1209.                                                                         num, fzipfn.c_str());
  1210.  
  1211.                         Notify(0, UnzMsg);
  1212.                     }
  1213.         }
  1214.  
  1215.         if (num_skipped > 0)
  1216.         {
  1217.             if (why_skipped > 0)
  1218.                 why_skipped = (why_skipped & 63) - 1;
  1219.  
  1220.             UnzMsg.Format(_T("Skipped %d Files: %d"), num_skipped, why_skipped);
  1221.                         DZError(DZM_MessageBit | DZ_ERM_SKIPPING, UnzMsg);
  1222.         }
  1223.  
  1224.                 if (num_bad_pwd > 0)
  1225.                 {
  1226.                         UnzMsg.Format(_T("Files with bad pwd: %d"), num_bad_pwd);
  1227.                         DZError(DZ_ERM_GENERAL, UnzMsg);
  1228.                 }
  1229.         else
  1230.             if ((fqflag == 0) && !error_in_archive && (num == 0))
  1231.             {
  1232.                 UnzMsg.Format(_T("Zero Files Tested %s"), fzipfn.c_str());
  1233.                 Notify(0, UnzMsg);
  1234.             }
  1235.     }
  1236.  
  1237.     /* give warning if files not tested or extracted (first condition can still
  1238.     * happen if zipfile is empty and no files specified on command line) */
  1239.     if ((filnum == 0) && error_in_archive <= PK_WARN)
  1240.     {
  1241.                 DZError(DZ_ERM_NOTHING_TO_DO, _T("no files found"));
  1242.         error_in_archive = PK_FIND;
  1243.         /* no files found at all */
  1244.     }
  1245.     else
  1246.         if ((num_skipped > 0) && !error_in_archive)
  1247.         {
  1248.             UnzMsg.Format(_T("some files skipped"));
  1249.             Notify(0, UnzMsg);
  1250.             error_in_archive = PK_WARN;
  1251.         }    
  1252. //#ifdef CRYPT
  1253.                 else
  1254.                         if ((num_bad_pwd > 0) && !error_in_archive)
  1255.                                 error_in_archive = PK_WARN;
  1256. //#endif
  1257.         return error_in_archive;
  1258. }
  1259.  
  1260. /* end function extract_or_test_files() */
  1261.  
  1262.  
  1263. #ifdef COPYRIGHT_CLEAN          /* no reduced or tokenized files */
  1264. #  define UNKN_COMPR  (fcrec.compression_method >= SHRUNK && \
  1265.                        fcrec.compression_method != IMPLODED \
  1266.                        && fcrec.compression_method != DEFLATED \
  1267.                        && fcrec.compression_method != ENHDEFLATED)
  1268. #else /* !COPYRIGHT_CLEAN */
  1269. #  define UNKN_COMPR \
  1270.     (fcrec.compression_method > IMPLODED && fcrec.compression_method != DEFLATED)
  1271. #endif /* ?COPYRIGHT_CLEAN */
  1272.  
  1273. /* ===========================================================================
  1274. *   Check central directory info for version/compatibility requirements.
  1275. *      Function store_info()
  1276. *  changed to StoreInfo - returns reason for skipping */
  1277. int UnzOpr::StoreInfo(void)
  1278. {
  1279.     fpInfo->ntfs_data = NULL;
  1280.     /* return err if skipping, 0 if OK */
  1281.     fpInfo->encrypted = fcrec.general_purpose_bit_flag & FLAG_ENCRYPT_BIT;
  1282.  
  1283.     /* bit field */
  1284.     fpInfo->ExtLocHdr = (fcrec.general_purpose_bit_flag & FLAG_EXTEND_BIT) == FLAG_EXTEND_BIT;
  1285.  
  1286.     /* bit field */
  1287.     fpInfo->textfile = fcrec.internal_file_attributes & 1;
  1288.  
  1289.     fpInfo->crc = fcrec.crc32;
  1290.     fpInfo->compr_size = fcrec.csize;
  1291.     fpInfo->uncomp_size = fcrec.ucsize;
  1292.     fpInfo->offset = fcrec.relative_offset_local_header;
  1293.  
  1294.     fpInfo->textmode = false;
  1295.  
  1296.     // EWE note: all platforms define VMS_UNZIP_VERSION (currently 42)
  1297.     if (fcrec.version_needed_to_extract[1] == VMS_)
  1298.     {
  1299.         if (fcrec.version_needed_to_extract[0] > VMS_UNZIP_VERSION)
  1300.         {
  1301.             if (Verbose)// < 0)
  1302.                 Notify(ITRACE, _T("Skipping Unsupported zip version or hosttype: %s"),
  1303.                     ffilename.c_str());
  1304.  
  1305.             return SKIPPED_UNKNOWN_ZIPHOST;
  1306.         }
  1307.  
  1308. #ifndef VMS /* won't be able to use extra field, but still have data */
  1309.         else
  1310.             if (!ftflag && !foverwrite_all)
  1311.             {
  1312.                 /* if -o, extract regardless */
  1313.                 if (Verbose)// < 0)
  1314.                     Notify(ITRACE, _T("Warning - file's format may be incorrect: %s"),
  1315.                         ffilename.c_str());
  1316.  
  1317.                 return SKIPPED_FILEFORMAT_WRONG;
  1318.             }
  1319.  
  1320. #endif
  1321.         /* usual file type:  don't need VMS to extract */
  1322.     }
  1323.     else
  1324.         if (fcrec.version_needed_to_extract[0] > UNZIP_VERSION)
  1325.         {
  1326.                 if (Verbose)// < 0)
  1327.                         Notify(ITRACE, _T("Skipping Unsupported zip version or hosttype: %s"),
  1328.                                 ffilename.c_str());
  1329.  
  1330.                 return SKIPPED_UNKNOWN_ZIPHOST;
  1331.         }
  1332.  
  1333.     if UNKN_COMPR
  1334.         {
  1335.                 // RCV: 1.610
  1336.                 if (Verbose)// < 0)
  1337.                                 Notify(ITRACE, _T("Skipping Unsupported compression type: %s"),
  1338.                                         ffilename.c_str());
  1339.  
  1340.         return SKIPPED_COMPRESSION_UNKNOWN;
  1341.         }
  1342.  
  1343.     /* map whatever file attributes we have into the local format */
  1344.     mapattr();
  1345.  
  1346.     if (!extra_field.IsEmpty() && IsNTorAbove && fNTFSStamps)
  1347.         {
  1348.                 const X_NTFSHeader* data = (const X_NTFSHeader*)extra_field.Find(NTFS_STAMP_TAG);
  1349.                 if (data && data->hed.vsize >= 32)
  1350.                 {
  1351.                         unsigned siz = data->hed.vsize;
  1352.                         const XNTFSData *hdata = (const XNTFSData *)FindTag(1, (const unsigned char*)++data, siz);
  1353.                         if (hdata && siz == 24)
  1354.                         {
  1355.                                 fpInfo->ntfs_data = new XNTFSData;
  1356.                                 memcpy((void*)(fpInfo->ntfs_data), (void*)hdata, sizeof(XNTFSData));
  1357.                         }
  1358.                 }
  1359.         }
  1360.  
  1361.     /* GRR:  worry about return value later */
  1362.     return 0;
  1363. }
  1364. /* end function store_info() */
  1365.  
  1366.  
  1367. /* ===========================================================================
  1368. *    Function extract_or_test_member() *
  1369. * return PK-type error code or PK_COOL.
  1370. * direct: PK_DISK (open error or full), PK_ERR, PK_WARN, PK_MEM3
  1371. * indirect caused by unshrink:
  1372. * */
  1373. int UnzOpr::extract_or_test_member(void)
  1374. {
  1375.     register int b;
  1376.     int ucb;      // user_cb result
  1377.         int r, error = PK_COOL;
  1378.  
  1379.     if (Verbose < 0)
  1380.         Notify(ITRACE, _T("Start extract_or_test_member: %s"), ffilename.c_str());
  1381.  
  1382.     /*---------------------------------------------------------------------------
  1383.     *    Initialize variables, buffers, etc.
  1384.     *---------------------------------------------------------------------------*/
  1385.     fbits_left = 0;
  1386.  
  1387.     fbitbuf = 0L;
  1388.  
  1389.     /* unreduce and unshrink only */
  1390.     fzipeof = 0;
  1391.  
  1392.     fnewfile = true;
  1393.     fcrc32val = CRCVAL_INITIAL;
  1394.  
  1395.  
  1396.         if (ftflag)
  1397.         {
  1398.                 // if test desired
  1399.                 if (Verbose)
  1400.                         Notify(0, _T("Testing %s"), ffilename.c_str());
  1401.         }
  1402.         else
  1403.                 if ((r = open_outfile()) != 0)
  1404.                         return r;
  1405.         /*---------------------------------------------------------------------------
  1406.         *    Unpack the file.
  1407.         *---------------------------------------------------------------------------*/
  1408.         if (Verbose < 0)
  1409.                 Notify(ITRACE, _T("unpack the file"));
  1410.  
  1411.         defer_leftover_input(); /* so NEXTBYTE bounds check will work */
  1412.  
  1413.         fMax_Write = flrec.ucsize;      // restrict extraction length
  1414.         if (fMax_Write)
  1415.         {
  1416.                 switch (flrec.compression_method)
  1417.                 {
  1418.  
  1419.                         case STORED:
  1420.                                 foutptr = Slide;
  1421.                                 foutcnt = 0L;
  1422.  
  1423.                                 while ((b = NEXTBYTE) != EOF && !fdisk_full)
  1424.                                 {
  1425.                                         * foutptr++ = (uch)b;
  1426.  
  1427.                                         if (++foutcnt == wsize)
  1428.                                         {
  1429.                                                 // EWE: wsize = 32K
  1430.                                                 flush(Slide, foutcnt, 0);
  1431.                                                 foutptr = Slide;
  1432.                                                 foutcnt = 0L;
  1433.  
  1434.                                                 if (Abort_Flag)
  1435.                                                 {
  1436.                                                         /* v1.6026 */
  1437.                                                         CloseOut();
  1438.                                                         undefer_input();
  1439.                                                         Fatal(DZ_ERM_ABORT, 0);
  1440.                                                 }
  1441.                                         }
  1442.                                 }
  1443.  
  1444.                                 if (foutcnt) /* flush final (partial) buffer */
  1445.                                         flush(Slide, foutcnt, 0);
  1446.                                 break;
  1447.  
  1448.                         case IMPLODED:
  1449.                                 if (((r = explode()) != 0) && r != 5)
  1450.                                 {
  1451.                                         /* treat 5 specially */
  1452.                                         Notify(0, _T("Error unzipping files"));
  1453.                                         error = PK_ERR;
  1454.                                 }
  1455.  
  1456.                                 if (r == 5)
  1457.                                 {
  1458.                                         int warning = ((ulg)fused_csize <= flrec.csize);
  1459.                                         Notify(0, _T("Error unzipping files"));
  1460.                                         error = warning ? PK_WARN : PK_ERR;
  1461.                                 }
  1462.  
  1463.                                 break;
  1464.  
  1465.                         case DEFLATED:
  1466.                         case ENHDEFLATED:
  1467.                                 if ((r = inflate(flrec.compression_method == ENHDEFLATED)) != 0)
  1468.                                 {
  1469.                                         int zerr = DZ_ERR(r);
  1470.                                         if (zerr != DZ_ERR(PK_WARN) &&
  1471.                                                 (zerr == DZ_ERR(PK_BADERR) || zerr == DZ_ERR(PK_NOZIP) ||
  1472.                                                 zerr == DZ_ERR(PK_FIND) || zerr == DZ_ERR(PK_EOF)))
  1473.                                                 if (r != 1 && r & 0x09) // RP 1.7
  1474.                                         {
  1475.                                                 /* user want to cancel operation v 1.6026 */
  1476.                                                 CloseOut();
  1477.                                                 undefer_input();
  1478.                                                 return r;
  1479.                                         }
  1480.  
  1481.                                         Notify(0, _T("Error unzipping files"));
  1482.  
  1483.                                         error = PK_ERR;
  1484.                                 }
  1485.                                 break;
  1486.  
  1487.                         default:
  1488.                                 /* should never get to this point */
  1489.                                 if (Verbose)// < 0)
  1490.                                         Notify(ITRACE, _T("should NEVER get here"));
  1491.  
  1492.                                 Notify(0, _T("Error unzipping files - unknown method"));
  1493.  
  1494.                                 /* close and delete file before return? */
  1495.                                 undefer_input();
  1496.                                 CloseOut();  // finished the file
  1497.  
  1498.                                 return PK_WARN;
  1499.                 }
  1500.  
  1501.                 /* end switch (compression method) */
  1502.                 if (fdisk_full)
  1503.                 {
  1504.                         /* set by flush() */
  1505.                         if (fdisk_full > 1)
  1506.                         {
  1507.                                 undefer_input();
  1508.                                 return PK_DISKFULL;
  1509.                         }
  1510.  
  1511.                         error = PK_WARN;
  1512.                 }
  1513.  
  1514.                 if (error != PK_COOL && Verbose)
  1515.                         Notify(ITRACE, _T("had an error of %d before closing file"), error);
  1516.  
  1517.                 CloseOut();  // finished the file
  1518.         }
  1519.  
  1520.         if (PK_ERR_NOWARN(error))
  1521.         {
  1522.                 /* don't print redundant CRC error if error already */
  1523.                 undefer_input();
  1524.                 return error;
  1525.         }
  1526.  
  1527.         if (Verbose < 0)
  1528.         {
  1529.                 Notify(ITRACE, _T("After extraction, fcrc32val = %08X"), fcrc32val);
  1530.                 Notify(ITRACE, _T("File's CRC in local hdr = %08X"), flrec.crc32);
  1531.         }
  1532.  
  1533.         if (fcrc32val != flrec.crc32)
  1534.         {
  1535.         // Call the component with a request for what do with with this CRC error.
  1536.                 CB->Arg1 = fcrc32val;
  1537.                 CB->Arg2 = flrec.crc32;
  1538.                 CB->Msg = ffilename;
  1539.                 ucb = CB->UserCB(zacCRCError);
  1540.  
  1541.                 if (ucb == CALLBACK_UNHANDLED)
  1542.                         ucb = CALLBACK_2;     // warn
  1543.  
  1544.         if (ucb == CALLBACK_3)          // responded 'delete'
  1545.         {
  1546.             DeleteFile(ffilename);
  1547.             error = PK_ERR;
  1548.         }
  1549.  
  1550.         if (ucb == CALLBACK_2)          // responded 'warn'
  1551.         {
  1552.             /* if quiet enough, we haven't output the filename yet:  do it */
  1553.                         Notify(0, _T("After extraction, file %s had a CRC error"), ffilename.c_str());
  1554.                         if (Encrypted)
  1555.                                 Notify(0, _T("May be Bad Password for file: %s"), ffilename.c_str());
  1556.                         error = PK_WARN;
  1557.         }
  1558.     }
  1559.  
  1560.     undefer_input();
  1561.  
  1562.     if (error != PK_COOL && Verbose < 0)
  1563.         Notify(ITRACE, _T("extract_or_test_member returning error: %d"), error);
  1564.  
  1565.     return error;
  1566. }
  1567. /* end function extract_or_test_member() */
  1568.  
  1569.  
  1570. /*---------------------------------------------------------------------------
  1571. * Close the file and set its date and time (not necessarily in that order),
  1572. * and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
  1573. * machines (redundant on 32-bit machines).
  1574. *---------------------------------------------------------------------------*/
  1575. void UnzOpr::CloseOut(void)
  1576. {
  1577.     if (!ftflag) /* don't close NULL file or stdout */
  1578.                 close_outfile();
  1579. }
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.