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 "ZStrings.h"
4
#include "ZipOp.h"
5
#include "dz_errs.h"
6
 
7
#undef _DZ_FILE_
8
#define _DZ_FILE_ DZ_ZIPREAD_CPP
9
 
10
/* ZipFile.c Copyright (C) 1990-1996
11
   Mark Adler, Richard B. Wales, Jean-loup Gailly, Kai Uwe Rommel,
12
   Onno van der Linden and Igor Mandrichenko.
13
   This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
14
   * distributed under LGPL license ** see license.txt for details
15
 
16
  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
17
 
18
  See the accompanying file LICENSE, version 2007-Mar-4 or later
19
  (the contents of which are also included in zip.h) for terms of use.
20
  If, for some reason, all these files are missing, the Info-ZIP license
21
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
22
 
23
  parts Copyright (C) 1997 Mike White, Eric W. Engler
24
************************************************************************
25
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
26
 
27
   This file is part of TZipMaster Version 1.9.
28
 
29
    TZipMaster is free software: you can redistribute it and/or modify
30
    it under the terms of the GNU Lesser General Public License as published by
31
    the Free Software Foundation, either version 3 of the License, or
32
    (at your option) any later version.
33
 
34
    TZipMaster is distributed in the hope that it will be useful,
35
    but WITHOUT ANY WARRANTY; without even the implied warranty of
36
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
    GNU Lesser General Public License for more details.
38
 
39
    You should have received a copy of the GNU Lesser General Public License
40
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
41
 
42
    contact: problems@delphizip.org (include ZipMaster in the subject).
43
    updates: http://www.delphizip.org
44
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
45
************************************************************************/
46
 
47
// -- Structure of a ZIP file --
48
// Signatures for zip file information headers
49
#define LOCSIG    0x04034b50L
50
#define CENSIG    0x02014b50L
51
#define ENDSIG    0x06054b50L
52
#define EXTLOCSIG 0x08074b50L
53
 
54
// Make first pass through zip file, reading information from local file
55
// headers and then verifying that information with the central file headers.
56
// Any deviation from the expected zip file format returns an error. At the
57
// end, a sorted list of file names in the zip file is made to facilitate
58
// searching by name. The name of the zip file is pointed to by the global
59
// "zipfile". The globals zfiles, zcount, zcomlen, zcomment, and zsort are
60
// filled in. Return an error code in the ZEN_xxx class.
61
// static int readzipfile1(ZGlobals *pG, HANDLE hInz);
62
int ZipOp::readzipfile(void)
63
{
64
        HANDLE hInz;
65
        ZipItem *z; /* current zip entry structure */
66
        int r = 0; // Initialize zip file info
67
        fzipbeg = 0;
68
        fcenbeg = 0;
69
        fzfiles = NULL; // Points to first header
70
        fzcount = 0; // number of files
71
 
72
        // If zip file exists, read headers and check structure
73
        if (fzipfile.IsEmpty())
74
                return DZ_ERR_GOOD;
75
 
76
        if (Verbose)
77
                Notify(IVERBOSE, _T("ready to open: %s for read only"), fzipfile.c_str()
78
                        );
79
 
80
        if ((hInz = CreateFile(fzipfile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
81
                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL))
82
                != INVALID_HANDLE_VALUE)
83
        {
84
                diag(_T("zip archive is now open"));
85
                r = readzipfile1(hInz);
86
                Close_Handle(&hInz);
87
 
88
                if (r < 0)
89
                        r = (GetLastError() ? DZ_ERM_ERROR_READ : DZ_ERM_ZIP_EOF);
90
        }
91
 
92
        if (r != 0)
93
                return r;
94
 
95
        // If one or more files, sort by name
96
        if (fzcount)
97
        {
98
                fndlist = new HashListInt(fzcount);
99
 
100
                for (z = fzfiles; z != NULL; z = z->nxt)
101
                        fndlist->AddNode(z);
102
        }
103
 
104
        return DZ_ERR_GOOD;
105
}
106
 
107
// -------------------------------------------------------------------------
108
 
109
/* searches the cextra member of zlist for a zip64 extra field. if it finds one it */
110
/* updates the len, siz and off members of zlist with the corresponding values of */
111
/* the zip64 extra field, that is if either the len, siz or off member of zlist is */
112
/* set to its max value we have to use the corresponding value from the zip64 extra */
113
/* field. as of now the dsk member of zlist is not much of interest since we should */
114
/* not modify multi volume archives at all. */
115
static void adjust_zip_central_entry(ZipItem *z)
116
{
117
        const uch* pTemp;
118
        /* assume not using zip64 fields */
119
 
120
        /* check if we have a "large file" Zip64 extra field ... */
121
        pTemp = z->cextra.Find(ZIP64_XDATA_TAG);
122
 
123
        if (pTemp == NULL)
124
                return;
125
 
126
        /* using zip64 field */
127
        pTemp += sizeof(XDataHead);
128
 
129
        /* ... if so, update corresponding entries in struct zlist */
130
        if (z->len == MAX_UNSIGNED)
131
        {
132
                z->len = *(ZInt64*)pTemp;
133
                pTemp += 8;
134
        }
135
 
136
        if (z->siz == MAX_UNSIGNED)
137
        {
138
                z->siz = *(ZInt64*)pTemp;
139
                pTemp += 8;
140
        }
141
 
142
        if (z->off == MAX_UNSIGNED)
143
                z->off = *(ZInt64*)pTemp;
144
}
145
 
146
# define ZIP64_EOCD_SIG                  0x06064b50
147
 
148
bool NeedEOC64(ZipEndOfCentral *eoc)
149
{
150
        if (eoc->CentralOffset == MAX_UNSIGNED || eoc->TotalEntries == MAX_WORD ||
151
                eoc->CentralSize == MAX_UNSIGNED || eoc->CentralEntries == MAX_WORD ||
152
                eoc->ThisDiskNo == MAX_WORD || eoc->CentralDiskNo == MAX_WORD)
153
                return true;
154
 
155
        return false;
156
}
157
 
158
int ZipOp::readzipfile1(HANDLE hInz)
159
{
160
        ZipEndOfCentral* zeoc;
161
        Zip64EOCLocator* zloc;
162
        ZipEOC64* zeoc64;
163
        ZipCentralHeader *zcen;
164
        ZipLocalHeader *zlcl;
165
        ::extent n; /* length of name */
166
        ZipItem **x; /* pointer last entry's link */
167
        ZipItem *z; /* current zip entry structure */
168
        char *t; /* temporary pointer */
169
        int found;
170
        char *buf; /* temp buffer for reading zipfile */
171
        DWORD k; // count of bytes read
172
        int idx;
173
        int cnt, CenEntries;
174
        ZInt64 u8; /* unsigned 8 byte variable */
175
        ZInt64 censiz; /* size of central directory */
176
        ZInt64 z64eocd; /* Zip64 End Of Central Directory record byte offset */
177
        ZInt64 deltaoff = 0;
178
        bool need64; // = false;
179
        DZStrA tmp;
180
 
181
        buf = (char*)fwindow;
182
 
183
        found = 0;
184
        t = &buf[4096];
185
        t[1] = '\0';
186
        t[2] = '\0';
187
        t[3] = '\0';
188
        fzipbeg = SetFilePointer64(hInz, -(ZInt64)sizeof(ZipEndOfCentral),
189
                SEEK_END);
190
 
191
        if (fzipbeg < 0)
192
        {
193
                Notify(IWARNING, _T("not a zip file"));
194
                return DZ_ERM_INVAL_ZIP;
195
        }
196
 
197
        if (ReadFile(hInz, buf, sizeof(ZipEndOfCentral), &k, NULL) && k == sizeof
198
                (ZipEndOfCentral) && *(ulg*)buf == ENDSIG)
199
                found = 2;
200
        else
201
        {
202
                fzipbeg += sizeof(ZipEndOfCentral); // size of file
203
 
204
                idx = 16; // max 16 * 4k = 64k
205
 
206
                while (!found && idx-- >= 0 && fzipbeg >= 0)
207
                {
208
                        size_t sz;
209
                        fzipbeg -= 4096;
210
 
211
                        if (fzipbeg < 0)
212
                                fzipbeg = 0;
213
 
214
                        if (SetFilePointer64(hInz, fzipbeg, SEEK_SET) < 0)
215
                                break;
216
 
217
                        if (!ReadFile(hInz, buf, 4096 /* (size_t) fzipbeg */ , &k, NULL))
218
                                break;
219
 
220
                        sz = (size_t)k;
221
                        buf[sz] = t[1];
222
                        buf[sz + 1] = t[2];
223
                        buf[sz + 2] = t[3];
224
                        t = &buf[sz - 1];
225
                        while (t >= buf)
226
                        {
227
                                /* Check for ENDSIG ("PK\5\6" in ASCII) */
228
                                if (*(ulg*)t == ENDSIG)
229
                                {
230
                                        found = 1;
231
                                        fzipbeg += (ZInt64)(t - buf); // at the eoc
232
                                        break;
233
                                }
234
 
235
                                --t;
236
                        }
237
                }
238
        }
239
 
240
        if (!found)
241
        {
242
                Notify(IWARNING, _T("missing end signature--probably not a zip file"));
243
                return DZ_ERM_INVAL_ZIP;
244
        }
245
 
246
        // fzipbeg at eoc offset
247
 
248
        /* Read end header */
249
        zeoc = (ZipEndOfCentral*)fwindow;
250
        SetFilePointer64(hInz, (ZInt64)fzipbeg, SEEK_SET);
251
 
252
        if (!ReadFile(hInz, zeoc, sizeof(ZipEndOfCentral), &k, NULL) || k != sizeof
253
                (ZipEndOfCentral))
254
                return-1;
255
 
256
        if (zeoc->ThisDiskNo || zeoc->CentralDiskNo || zeoc->CentralEntries !=
257
                zeoc->TotalEntries)
258
                Notify(IWARNING, _T("multiple disk information ignored"));
259
 
260
        CenEntries = zeoc->CentralEntries;
261
 
262
        if (!fzcomlen) // ignore if have new
263
        {
264
                fzcomlen = zeoc->ZipCommentLen;
265
 
266
                if (fzcomlen)
267
                {
268
                        if (!ReadFile(hInz, fzcomment.GetBuffer(fzcomlen), fzcomlen, &k,
269
                                        NULL) || k != (DWORD)fzcomlen)
270
                        {
271
                                fzcomment.Empty();
272
                                return-1;
273
                        }
274
                }
275
        }
276
 
277
        need64 = NeedEOC64(zeoc);
278
        if (need64)
279
        {
280
                /* account for Zip64 EOCD Record and Zip64 EOCD Locator */
281
                /* Z64 EOCDL must be just before EOCD if it exists */
282
                fcenbeg = fzipbeg-sizeof(Zip64EOCLocator);
283
 
284
                /* check for empty archive */
285
                if (fcenbeg >= 0)
286
                {
287
                        /* look for signature */
288
                        if (SetFilePointer64(hInz, fcenbeg, SEEK_SET) == -1)
289
                        {
290
                                Notify(IWARNING, _T("end of file seeking Z64EOCLocator"));
291
                                return DZ_ERM_INVAL_ZIP;
292
                        }
293
 
294
                        zloc = (Zip64EOCLocator*)(fwindow + 128);
295
                        if (!ReadFile(hInz, zloc, sizeof(Zip64EOCLocator), &k, NULL)
296
                                || k != sizeof(Zip64EOCLocator))
297
                        {
298
                                throw DZException(DZ_ERM_INVAL_ZIP);
299
                        }
300
 
301
                        if (zloc->HeaderSig == EOC64LocatorSig)
302
                        {
303
                                /* found Zip64 EOCD Locator */
304
                                /* check for disk information */
305
                                if (zloc->NumberDisks != 1)
306
                                {
307
                                        Notify(IWARNING, _T("multiple disk archives not supported")
308
                                                );
309
                                        throw DZException(DZ_ERM_ZIP_MULTI);
310
                                }
311
 
312
                                /* look for Zip64 EOCD Record */
313
                                z64eocd = zloc->EOC64RelOfs;
314
                                if (SetFilePointer64(hInz, z64eocd, SEEK_SET) == -1)
315
                                {
316
                                        throw DZException(DZ_ERM_INVAL_ZIP);
317
                                }
318
 
319
                                zeoc64 = (ZipEOC64*)(fwindow + 256);
320
                                if (!ReadFile(hInz, zeoc64, sizeof(ZipEOC64), &k, NULL)
321
                                        || k != sizeof(ZipEOC64))
322
                                {
323
                                        throw DZException(DZ_ERM_INVAL_ZIP);
324
                                }
325
 
326
                                if (zeoc64->HeaderSig != EndCentral64Sig)
327
                                {
328
                                        Notify(IWARNING, _T(
329
                                                        "Z64 EOCD not found but Z64 EOCD Locator exists"));
330
                                        throw DZException(DZ_ERM_INVAL_ZIP);
331
                                }
332
 
333
                                /* get size of CD */
334
                                /* get start of CD */
335
                                CenEntries = zeoc->CentralEntries;
336
                                fcenbeg = zeoc64->CentralOffSet;
337
                                deltaoff = 0; // Zip64 offsets must be correct or could not locate EOC64
338
                                fadjust = 0; // no adjust needed
339
                        }
340
                        else
341
                        {
342
                                /* assume no Locator and no Zip64 EOCD Record */
343
                                need64 = false;
344
                                censiz = zeoc->CentralSize;
345
                                fcenbeg = censiz ? zeoc->CentralOffset : fzipbeg;
346
                                u8 = (fzipbeg - censiz) - fcenbeg;
347
 
348
                                if (u8)
349
                                {
350
                                        if (Verbose)
351
                                                Notify(IWARNING, _T("wrong central directory offset"));
352
                                }
353
                                else
354
                                        fadjust = 0; // no adjust needed
355
 
356
                                deltaoff = fadjust ? u8 : 0L;
357
                        }
358
                }
359
        }
360
        else
361
        {
362
                /* assume no Locator and no Zip64 EOCD Record */
363
                censiz = zeoc->CentralSize;
364
                fcenbeg = censiz ? zeoc->CentralOffset : fzipbeg;
365
                u8 = (fzipbeg - censiz) - fcenbeg;
366
 
367
                if (u8)
368
                {
369
                        if (Verbose)
370
                                Notify(IWARNING, _T("wrong central directory offset"));
371
                }
372
                else
373
                        fadjust = 0; // no adjust needed
374
 
375
                deltaoff = fadjust ? u8 : 0L;
376
        }
377
 
378
        if (!CenEntries || (need64 && fzipbeg < sizeof(Zip64EOCLocator)))
379
        {
380
                /* zip file seems empty */
381
                return DZ_ERR_GOOD;
382
        }
383
 
384
        if (SetFilePointer64(hInz, fcenbeg + deltaoff, SEEK_SET) == -1)
385
        {
386
                Notify(IWARNING, _T("error seeking central directory"));
387
                return DZ_ERM_INVAL_ZIP;
388
        }
389
 
390
        CB->UserXItem(CenEntries + CenEntries, 9, _T("*Loading central"));
391
 
392
        cnt = 0;
393
 
394
        x = &fzfiles; /* first link */
395
        zcen = (ZipCentralHeader*)fwindow + 512;
396
 
397
        if (!ReadFile(hInz, zcen, 4, &k, NULL) || k != 4)
398
                return-1;
399
 
400
        while (zcen->HeaderSig == CENSIG)
401
        {
402
                /* Read central header. The portion of the central header that should
403
                be in common with local header is read raw, for later comparison.
404
                (this requires that the offset of ext in the zlist structure
405
                be greater than or equal to LOCHEAD) */
406
                if (!ReadFile(hInz, &zcen->MadeBy, CENHEAD, &k, NULL) || k != CENHEAD)
407
                        return-1;
408
 
409
                z = new ZipItem;
410
                /* Link into list */
411
                z->nxt = NULL;
412
                *x = z; // link it now so it can't get lost
413
                x = &z->nxt;
414
                z->vem = zcen->MadeBy; // MadeByVersion;
415
                z->ver = zcen->VersionNeed;
416
                z->flg = zcen->Flag;
417
                z->how = zcen->ComprMethod;
418
                z->tim = zcen->ModifStamp;
419
                z->crc = zcen->CRC32;
420
                z->siz = zcen->ComprSize;
421
                z->len = zcen->UnComprSize;
422
                z->nam = zcen->FileNameLen;
423
                z->ext = 0;
424
                z->com = zcen->FileComLen;
425
                z->dsk = zcen->DiskStart;
426
                z->att = zcen->IntFileAtt;
427
                z->atx = zcen->ExtFileAtt;
428
                z->off = zcen->RelOffLocal + deltaoff;
429
                z->options.dosflag = ((z->vem & 0xff00) == 0) ? 1 : 0;
430
                z->options.level = flevel;
431
                z->options.noext = 0;
432
 
433
                if (!z->nam || z->nam > MAX_PATH)
434
                {
435
                        const TCHAR*erm = z->nam ? _T("name too long") : _T
436
                                ("zero-length name");
437
                        Notify(IWARNING, _T("%s for entry #%lu"), erm, (ulg)fzcount + 1);
438
#ifndef DEBUG
439
                        return DZ_ERM_INVAL_ZIP;
440
#endif
441
                }
442
 
443
                /* Read file name, extra field and comment field */
444
                if (!ReadFile(hInz, tmp.GetBuffer(z->nam), z->nam, &k, NULL)
445
                        || k != z->nam)
446
                        return-1;
447
 
448
                tmp.ReleaseBuffer(z->nam);
449
 
450
                z->HName = tmp;
451
 
452
                if (zcen->ExtraLen)
453
                {
454
                        DZRawData xdata;
455
                        if (!ReadFile(hInz, xdata.GetBuffer(zcen->ExtraLen),
456
                                        zcen->ExtraLen, &k, NULL) || k != (unsigned)zcen->ExtraLen)
457
                                return-1;
458
 
459
                        z->cext = zcen->ExtraLen;
460
                        z->cextra = xdata;
461
                }
462
 
463
                DZStrA zcom; // file comment
464
                if (z->com)
465
                {
466
                        if (!ReadFile(hInz, zcom.GetBuffer(z->com), z->com, &k, NULL)
467
                                || k != z->com)
468
                                return-1;
469
 
470
                        zcom.ReleaseBuffer(z->com);
471
                }
472
 
473
                // decode header name
474
                z->Enc = IsEncoded(z->vem, z->flg & FLAG_UTF8_BIT) & 3;
475
 
476
                if (z->Enc == zeoAuto && ValidUTF8(z->hname) > 0)
477
                        z->Enc = zeoUTF8;
478
                DZStrW wn;
479
                if (z->cext && (fEncodedAs == zeoAuto || fEncodedAs == zeoUPATH))
480
                {
481
                        const UPhead *up = (const UPhead*)z->cextra.Find(UPATH_XDATA_TAG);
482
                        if (up && up->ver == 1 && up->hed.vsize > sizeof(UPhead))
483
                        {
484
                                ulg ocrc = crc32(0, (uch*)z->hname, z->nam);
485
                                if (ocrc == up->crc)
486
                                {
487
                                        const char *bf = ((char*)up)+sizeof(UPhead);
488
                                        int ulen = up->hed.vsize - 5;
489
                                        wn = DZStrW(CP_UTF8, bf, ulen);
490
                                }
491
                        }
492
 
493
                }
494
                if (wn.IsEmpty())
495
                {
496
                        int UseCP = CP_THREAD_ACP;
497
                        switch((Encodings)z->Enc)
498
                        {
499
                        case zeoAuto:
500
                        case zeoNone:
501
                                UseCP = fFromPage;
502
                                break;
503
 
504
                        case zeoUTF8:
505
                                UseCP = CP_UTF8;
506
                                break;
507
 
508
                        case zeoOEM:
509
                                UseCP = CP_OEM;
510
                                break;
511
                        }
512
                        wn = DZStrW(UseCP, z->hname, z->nam);
513
                }
514
 
515
                DZStrW wx, wt = StrExtSep(wn);
516
                int nerr = CleanPath(wt, wx);
517
                if (nerr)
518
                {
519
                        if (Verbose)
520
                                Notify(IVERBOSE, _T("read file - invalid filename %s [%d]"),
521
                                z->hname, nerr);
522
                        return DZ_ERM_INVAL_NAME;
523
                }
524
 
525
                z->IName = wx;
526
                z->XName = wx;
527
                if (!zcom.IsEmpty())
528
                {
529
                        wn.Empty();
530
                        if (z->Enc == zeoAuto || z->Enc == zeoUPATH)
531
                        {
532
                                const UPhead *up = (const UPhead*)z->cextra.Find
533
                                        (UCMNT_XDATA_TAG);
534
 
535
                                if (up && up->ver == 1 && up->hed.vsize > sizeof(UPhead))
536
                                {
537
                                        ulg ocrc = crc32(0, (uch*)zcom.c_str(), z->com);
538
                                        if (ocrc == up->crc)
539
                                        {
540
                                                int len = up->hed.vsize-sizeof(UPhead);
541
                                                const char *bf = ((char*)up)+sizeof(UPhead);
542
                                                wn = DZStrW(CP_UTF8, bf, len);
543
                                        }
544
                                }
545
 
546
                        }
547
                        int UseCP = CP_THREAD_ACP;
548
                        switch((Encodings)z->Enc)
549
                        {
550
                        case zeoAuto:
551
                        case zeoNone:
552
                                UseCP = fFromPage;
553
                                break;
554
 
555
                        case zeoUTF8:
556
                                UseCP = CP_UTF8;
557
                                break;
558
 
559
                        case zeoOEM:
560
                                UseCP = CP_OEM;
561
                                break;
562
                        }
563
                        if (wn.IsEmpty())
564
                                wn = DZStrW(UseCP, zcom.c_str(), z->com);
565
                        z->Comment = wn;
566
                }
567
 
568
                /* zip64 support 08/31/2003 R.Nausedat */
569
                /* here, we have to read the len, siz etc values from the CD */
570
                /* entry as we might have to adjust them regarding their */
571
                /* correspronding zip64 extra fields. */
572
                /* also, we cannot compare the values from the CD entries with */
573
                /* the values from the LH as they might be different. */
574
                /* adjust/update siz,len and off (to come: dsk) entries */
575
                /* PKZIP does not care of the version set in a CDH: if */
576
                /* there is a zip64 extra field assigned to a CDH PKZIP */
577
                /* uses it, we should do so, too. */
578
                adjust_zip_central_entry(z);
579
#ifdef _ZDEBUG
580
                Notify(ITRACE, _T("readzipfile1: %s dosflag %i"), z->iname,
581
                        z->options.dosflag);
582
#endif
583
 
584
                /* Update zipbeg offset, prepare for next header */
585
                if (z->off < fzipbeg)
586
                        fzipbeg = z->off;
587
 
588
                fzcount++;
589
 
590
                if (Verbose < 0)
591
                        Notify(ITRACE, _T("read file [%d] %s"), fzcount, z->xname);
592
 
593
                /* Read next signature */
594
                zcen = (ZipCentralHeader*)fwindow + 512;
595
 
596
                if (!ReadFile(hInz, zcen, 4, &k, NULL) || k != 4)
597
                        return-1;
598
 
599
                if (++cnt >= 10)
600
                {
601
                        CB->UserXProgress(cnt, 9);
602
                        cnt = 0;
603
 
604
                        if (Abort_Flag)
605
                                Fatal(DZ_ERM_ABORT, 0);
606
                }
607
        }
608
 
609
        /* Point to start of header list and read local headers */
610
        idx = 0;
611
 
612
        z = fzfiles;
613
 
614
        while (z != NULL)
615
        {
616
                if (Verbose < 0)
617
                        Notify(ITRACE, _T("checking file [%d] %s"), ++idx, z->iname);
618
 
619
                /* Read next signature */
620
                zlcl = (ZipLocalHeader*)fwindow + 640;
621
 
622
                if (SetFilePointer64(hInz, z->off, SEEK_SET) < 0 || !ReadFile
623
                        (hInz, zlcl, sizeof(ZipLocalHeader), &k, NULL) || k != sizeof(ZipLocalHeader))
624
                        return-1;
625
 
626
                if (zlcl->HeaderSig != LOCSIG)
627
                {
628
                        Notify(IWARNING, _T("local header not found for %s"), z->iname);
629
                        return DZ_ERM_INVAL_ZIP;
630
                }
631
 
632
                z->lflg = zlcl->Flag;
633
 
634
                n = zlcl->FileNameLen;
635
                z->ext = zlcl->ExtraLen;
636
                bool IsProblematic = false;
637
 
638
                if ((z->atx & 0xFFFF0000u) != 0 && z->vem == FS_FAT &&
639
                        (z->ver == 25 || z->ver == 26 || z->ver == 40))
640
                        IsProblematic = true;
641
 
642
                /* Compare name and extra fields */
643
                if (n != z->nam)
644
                {
645
                        Notify(IWARNING, _T("name lengths in local and central differ for %s"),
646
                                z->iname);
647
 
648
                        if (!IsProblematic) // unreliable in PKZIP
649
                                return DZ_ERM_INVAL_ZIP;
650
                }
651
 
652
                if (!ReadFile(hInz, tmp.GetBuffer(z->nam + 1), z->nam, &k, NULL)
653
                        || k != z->nam)
654
                {
655
                        return-1;
656
                }
657
 
658
                tmp.ReleaseBuffer();
659
 
660
                if (memcmp(tmp.c_str(), z->hname, z->nam) &&
661
                        (!IsProblematic || !ZMatch(tmp, z->iname)))
662
                {
663
                        Notify(IWARNING, _T("names in local and central differ for %s"),
664
                                z->iname);
665
                        if (!IsProblematic) // unreliable in PKZIP
666
                        {
667
                                return DZ_ERM_INVAL_ZIP;
668
                        }
669
                }
670
 
671
                if (z->ext)
672
                {
673
                        DZRawData tmp;
674
 
675
                        if (!ReadFile(hInz, tmp.GetBuffer(z->ext), z->ext, &k, NULL)
676
                                || k != (DWORD)z->ext)
677
                        {
678
                                z->extra = NULL;
679
                                return-1;
680
                        }
681
                        tmp.SetLength(z->ext);
682
                        z->extra = tmp;
683
                }
684
 
685
                /* Clear actions */
686
                z->mark = 0;
687
                z->trash = 0;
688
                z = z->nxt;
689
                if (++cnt >= 5)
690
                {
691
                        CB->UserXProgress(cnt, 9);
692
                        cnt = 0;
693
 
694
                        if (Abort_Flag)
695
                                break;
696
                }
697
        }
698
 
699
        if (cnt)
700
                CB->UserXProgress(cnt, 9); // last few
701
 
702
        return DZ_ERR_GOOD;
703
}