Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 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