Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
unit ZMCenDir19;
2
 
3
(*
4
  ZMCenDir19.pas - handles external interface to directory entries
5
  TZipMaster19 VCL by Chris Vleghert and Eric W. Engler
6
  v1.9
7
  Copyright (C) 2009  Russell Peters
8
 
9
 
10
  This library is free software; you can redistribute it and/or
11
  modify it under the terms of the GNU Lesser General Public
12
  License as published by the Free Software Foundation; either
13
  version 2.1 of the License, or (at your option) any later version.
14
 
15
  This library is distributed in the hope that it will be useful,
16
  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
  Lesser General Public License (licence.txt) for more details.
19
 
20
  You should have received a copy of the GNU Lesser General Public
21
  License along with this library; if not, write to the Free Software
22
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23
 
24
  contact: problems AT delphizip DOT org
25
  updates: http://www.delphizip.org
26
 
27
  modified 2010-06-20
28
---------------------------------------------------------------------------*)
29
 
30
interface
31
 
32
uses
33
  Classes, ZipMstr19, ZMStructs19, ZMCompat19,
34
  ZMZipFile19, ZMIRec19, ZMCore19;
35
 
36
type
37
  TZCentralValues = (zcvDirty, zcvEmpty, zcvError, zcvBadStruct, zcvBusy);
38
  TZCentralStatus = set of TZCentralValues;
39
 
40
type
41
  TZMCenDir = class;
42
 
43
  // class to handle external directory access requests
44
  TZMCentralEntry = class(TZMDirEntry)
45
  private
46
    fCheck: Cardinal;
47
    fDir:   TZMCenDir;
48
    fIdx:   Cardinal;
49
  protected
50
    function Fetch(var rec: TZMIRec): Boolean;
51
    function GetCompressedSize: Int64; override;
52
    function GetCompressionMethod: Word; override;
53
    function GetCRC32: Cardinal; override;
54
    function GetDateTime: Cardinal; override;
55
    function GetEncoded: TZMEncodingOpts; override;
56
    function GetEncrypted: Boolean; override;
57
    function GetExtFileAttrib: Longword; override;
58
    function GetExtraData(Tag: Word): TZMRawBytes; override;
59
    function GetExtraField: TZMRawBytes; override;
60
    function GetExtraFieldLength: Word; override;
61
    function GetFileComment: TZMString; override;
62
    function GetFileCommentLen: Word; override;
63
    function GetFileName: TZMString; override;
64
    function GetFileNameLength: Word; override;
65
    function GetFlag: Word; override;
66
    function GetHeaderName: TZMRawBytes; override;
67
    function GetIntFileAttrib: Word; override;
68
    function GetRelOffLocalHdr: Int64; override;
69
    function GetStartOnDisk: Word; override;
70
    function GetStatusBits: Cardinal; override;
71
    function GetUncompressedSize: Int64; override;
72
    function GetVersionMadeBy: Word; override;
73
    function GetVersionNeeded: Word; override;
74
    property Check: Cardinal Read fCheck Write fCheck;
75
    property Idx: Cardinal Read fIdx Write fIdx;
76
  public
77
    constructor Create(Dir: TZMCenDir; idx: Integer; Check: Cardinal);
78
  end;
79
 
80
  TZMCenDir = class
81
  private
82
    fCount:         Integer;
83
    fCurrent:       TZMZipFile;
84
    fDirOnlyCount:  Integer;
85
    fEntries:       TList;
86
    fIgnoreDirOnly: Boolean;
87
    fLoadNo:        Integer;
88
    fStatus:        TZCentralStatus;
89
    fVerbose:       Boolean;
90
    fWorker:        TZMCore;
91
    procedure ClearEntries; //virtual;
92
    function GetCurrent: TZMZipFile;
93
    function GetEOCOffset: Int64;
94
    function GetMultiDisk: Boolean;
95
    function GetSFXOffset: Cardinal;
96
    function GetSOCOffset: Int64;
97
    function GetTotalDisks: Integer;
98
    function GetZipComment: Ansistring;
99
    function GetZipFileSize: Int64;
100
    procedure SetCurrent(const Value: TZMZipFile);
101
    procedure SetIgnoreDirOnly(Value: Boolean);
102
    procedure SetStatus(const Value: TZCentralStatus);
103
    procedure SetZipComment(const Value: Ansistring);
104
  protected
105
    function AddRecord(idx: Integer): Boolean;
106
    function GetDirEntry(Idx: Integer): TZMCentralEntry;
107
    procedure Invalidate;
108
    function Map: Integer;
109
    procedure SetCapacity(MaxEntries: Integer);
110
    property Worker: TZMCore Read fWorker;
111
  public
112
    constructor Create(Core: TZMCore);
113
    destructor Destroy; override;
114
    procedure Clear;
115
    // returns pointer to internal record
116
    function Entry(chk, idx: Cardinal): TZMIRec;
117
    function Find(const fspec: TZMString; var idx: Integer): TZMCentralEntry;
118
    function IndexOf(const FName: TZMString): Integer;
119
    function ReleaseZip: TZMZipFile;
120
    procedure ZipChange(Sender: TObject; idx: Integer; chng: TZCChanges);
121
    property Count: Integer Read fCount Write fCount;
122
    property Current: TZMZipFile Read GetCurrent Write SetCurrent;
123
    // DirEntry uses 'external' filtered index
124
    property DirEntry[Idx: Integer]: TZMCentralEntry read GetDirEntry; default;
125
    property DirOnlyCount: Integer Read fDirOnlyCount Write fDirOnlyCount;
126
    property EOCOffset: Int64 Read GetEOCOffset;
127
    property IgnoreDirOnly: Boolean Read fIgnoreDirOnly Write SetIgnoreDirOnly;
128
    property LoadNo: Integer Read fLoadNo Write fLoadNo;
129
    property MultiDisk: Boolean Read GetMultiDisk;
130
    property SFXOffset: Cardinal Read GetSFXOffset;
131
    property SOCOffset: Int64 Read GetSOCOffset;
132
    property Status: TZCentralStatus Read fStatus Write SetStatus;
133
    property TotalDisks: Integer Read GetTotalDisks;
134
    property Verbose: Boolean Read fVerbose Write fVerbose;
135
    property ZipComment: Ansistring Read GetZipComment Write SetZipComment;
136
    property ZipFileSize: Int64 Read GetZipFileSize;
137
  end;
138
 
139
implementation
140
 
141
uses SysUtils, ZMMatch19;
142
 
143
 {
144
type
145
  TZCChanges = (zccNone, zccBegin, zccCount, zccAdd, zccEdit, zccDelete, zccEnd);
146
  TZCChangeEvent = procedure(Sender: TObject; idx: integer; change: TZCChanges) of object;
147
  }
148
{TZMCenDir}
149
constructor TZMCenDir.Create(Core: TZMCore);
150
begin
151
  inherited Create;
152
  fWorker := Core;
153
  fEntries := TList.Create;
154
  fCount  := 0;
155
  fLoadNo := 0;
156
  fDirOnlyCount := 0;
157
end;
158
 
159
destructor TZMCenDir.Destroy;
160
begin
161
  ClearEntries;
162
  FreeAndNil(fEntries);
163
  FreeAndNil(fCurrent);
164
  inherited Destroy;
165
end;
166
 
167
function TZMCenDir.AddRecord(idx: Integer): Boolean;
168
var
169
  rec: TZMIRec;
170
  x: TZMCentralEntry;
171
begin
172
  Result := False;
173
  rec := fCurrent.Items[idx];
174
  if IgnoreDirOnly and rec.TestStatusBit(zsbDirOnly) then
175
    Inc(fDirOnlyCount)
176
  else
177
  begin
178
    x := fEntries.Items[fCount];
179
    x.Idx := idx;
180
    x.Check := fCurrent.CheckNo;
181
    Inc(fCount);
182
    Result := True;
183
  end;
184
end;
185
 
186
procedure TZMCenDir.Clear;
187
begin
188
  ClearEntries;
189
  FreeAndNil(fCurrent);
190
end;
191
 
192
procedure TZMCenDir.ClearEntries;
193
var
194
  i: Integer;
195
  tmp: TObject;
196
begin
197
  fCount := 0;
198
  fDirOnlyCount := 0;
199
  for i := 0 to pred(fEntries.Count) do
200
  begin
201
    tmp := fEntries.Items[i];
202
    if tmp <> nil then
203
    begin
204
      fEntries.Items[i] := nil;
205
      tmp.Free;
206
    end;
207
  end;
208
  fEntries.Clear;
209
end;
210
 
211
// return a pointer to an internal Entry
212
function TZMCenDir.Entry(chk, idx: Cardinal): TZMIRec;
213
begin
214
  if assigned(Current) then
215
    Result := fCurrent.Entry(chk, idx)
216
  else
217
    Result := nil;
218
end;
219
 
220
(*? TZMCentralDir.Find
221
 Find specified external filespec after idx (<0 - from beginning)
222
 returns pointer to Directory entry (nil - not found)
223
 sets idx to index of found entry (-1 not found)
224
*)
225
function TZMCenDir.Find(const fspec: TZMString; var idx: Integer): TZMCentralEntry;
226
var
227
  c: Integer;
228
begin
229
  if idx < 0 then
230
    idx := -1;
231
  c := pred(Count);
232
  while idx < c do
233
  begin
234
    Inc(idx);
235
    Result := DirEntry[idx];
236
    if Worker.FNMatch(fspec, Result.FileName) then
237
      exit;
238
  end;
239
  idx := -1;
240
  Result := nil;
241
end;
242
 
243
function TZMCenDir.GetCurrent: TZMZipFile;
244
begin
245
  if assigned(fCurrent) then
246
  begin
247
    if (fCurrent.info and zfi_Invalid) <> 0 then
248
      Current := TZMZipFile.Create(Worker); // force reload
249
  end
250
  else
251
    Current := TZMZipFile.Create(Worker);
252
  Result := fCurrent;
253
end;
254
 
255
function TZMCenDir.GetDirEntry(Idx: Integer): TZMCentralEntry;
256
begin
257
  if (Idx >= 0) and (Idx < Count) then
258
    Result := TZMCentralEntry(fEntries.Items[Idx])
259
  else
260
    Result := nil;
261
end;
262
 
263
function TZMCenDir.GetEOCOffset: Int64;
264
begin
265
  if assigned(Current) then
266
    Result := fCurrent.EOCOffset
267
  else
268
    Result := 0;
269
end;
270
 
271
function TZMCenDir.GetMultiDisk: Boolean;
272
begin
273
  if assigned(Current) then
274
    Result := fCurrent.MultiDisk
275
  else
276
    Result := False;
277
end;
278
 
279
function TZMCenDir.GetSFXOffset: Cardinal;
280
begin
281
  if assigned(Current) then
282
    Result := fCurrent.SFXOfs
283
  else
284
    Result := 0;
285
end;
286
 
287
function TZMCenDir.GetSOCOffset: Int64;
288
begin
289
  if assigned(Current) then
290
    Result := fCurrent.CentralOffset
291
  else
292
    Result := 0;
293
end;
294
 
295
function TZMCenDir.GetTotalDisks: Integer;
296
begin
297
  Result := 0;
298
  if assigned(Current) then
299
    Result := Current.TotalDisks;
300
end;
301
 
302
function TZMCenDir.GetZipComment: Ansistring;
303
begin
304
  if assigned(Current) then
305
    Result := fCurrent.ZipComment
306
  else
307
    Result := '';
308
end;
309
 
310
function TZMCenDir.GetZipFileSize: Int64;
311
begin
312
  Result := 0;
313
  if assigned(Current) then
314
    Result := Current.File_Size;
315
end;
316
 
317
(*? TZMCentralDir.IndexOf
318
 Find specified external filespec
319
  returns index of Directory entry (-1 - not found)
320
 Only checks unfiltered entries
321
*)
322
function TZMCenDir.IndexOf(const FName: TZMString): Integer;
323
begin
324
  for Result := 0 to pred(Count) do
325
    if Worker.FNMatch(FName, DirEntry[Result].FileName) then
326
      exit;
327
  Result := -1;
328
end;
329
 
330
procedure TZMCenDir.Invalidate;
331
var
332
  i: Integer;
333
  x: TZMCentralEntry;
334
begin
335
  fLoadNo := Worker.NextCheckNo;
336
  for i := 0 to fEntries.Count - 1 do
337
  begin
338
    x := fEntries.Items[i];
339
    x.Idx := i;
340
    x.Check := fLoadNo;
341
  end;
342
  fCount := 0;
343
end;
344
 
345
function TZMCenDir.Map: Integer;
346
var
347
  i:  Integer;
348
  x:  TZMCentralEntry;
349
  zc: Integer;
350
begin
351
  fDirOnlyCount := 0;
352
  if assigned(fCurrent) then
353
    zc := Current.Count
354
  else
355
    zc := 0;
356
  SetCapacity(zc);
357
  fCount := 0;
358
  if IgnoreDirOnly then
359
  begin
360
    for i := 0 to pred(zc) do
361
      AddRecord(i);
362
  end
363
  else
364
  begin
365
    for i := 0 to pred(zc) do
366
    begin
367
      x := fEntries.Items[i];
368
      x.Idx := i;
369
      x.Check := fLoadNo;
370
    end;
371
    fCount := zc;
372
  end;
373
  Result := 0;
374
end;
375
 
376
function TZMCenDir.ReleaseZip: TZMZipFile;
377
begin
378
  Result := fCurrent;
379
  fCurrent := nil;
380
  Worker.OnDirUpdate;
381
end;
382
 
383
procedure TZMCenDir.SetCapacity(MaxEntries: Integer);
384
var
385
  i: Integer;
386
begin
387
  if MaxEntries > fEntries.Count then
388
  begin
389
    fEntries.Capacity := MaxEntries;
390
    // populate the list
391
    for i := fEntries.Count to MaxEntries - 1 do
392
      fEntries.Add(TZMCentralEntry.Create(self, i, fLoadNo));
393
  end;
394
  Invalidate;
395
end;
396
 
397
procedure TZMCenDir.SetCurrent(const Value: TZMZipFile);
398
var
399
  cnt: Integer;
400
  i: Integer;
401
begin
402
  if fCurrent <> Value then
403
  begin
404
    Invalidate;       // don't free old - just mark useless
405
    FreeAndNil(fCurrent);
406
    fCurrent := Value;
407
    if assigned(Value) then
408
    begin
409
      fCurrent.OnChange := ZipChange;
410
      fLoadNo := fCurrent.CheckNo;
411
      cnt := fCurrent.Count;
412
      if cnt > 0 then
413
      begin
414
        // load entries
415
        SetCapacity(cnt);  // will set remap
416
        fCount := 0;
417
        for i := 0 to cnt - 1 do
418
          if AddRecord(i) then
419
            Worker.OnNewName(pred(fCount));
420
      end;
421
    end;
422
    Worker.OnDirUpdate;
423
  end;
424
end;
425
 
426
procedure TZMCenDir.SetIgnoreDirOnly(Value: Boolean);
427
begin
428
  if Value <> IgnoreDirOnly then
429
  begin
430
    fIgnoreDirOnly := Value;
431
    Map;
432
  end;
433
end;
434
 
435
procedure TZMCenDir.SetStatus(const Value: TZCentralStatus);
436
begin
437
  fStatus := Value;
438
end;
439
 
440
procedure TZMCenDir.SetZipComment(const Value: Ansistring);
441
begin
442
  //
443
end;
444
 
445
procedure TZMCenDir.ZipChange(Sender: TObject; idx: Integer; chng: TZCChanges);
446
begin
447
  case chng of
448
    //    zccNone: ;
449
    zccBegin:
450
      ClearEntries;
451
    zccCount:
452
      SetCapacity(idx);
453
    zccAdd:
454
      if AddRecord(idx) then
455
        Worker.OnNewName(pred(fCount));
456
//    zccEdit: ;
457
//    zccDelete: ;
458
    zccEnd:
459
      Worker.OnDirUpdate;
460
    zccCheckNo: // CheckNo changed because entries changed
461
      Invalidate;
462
  end;
463
end;
464
 
465
{ TZMCentralEntry }
466
 
467
constructor TZMCentralEntry.Create(Dir: TZMCenDir; idx: Integer; Check: Cardinal);
468
begin
469
  inherited Create;
470
  fDir := Dir;
471
  fIdx := idx;
472
  fCheck := Check;
473
end;
474
 
475
// return pointer to internal data
476
function TZMCentralEntry.Fetch(var rec: TZMIRec): Boolean;
477
begin
478
  Result := False;
479
  if assigned(fDir) then
480
  begin
481
    rec := fDir.Entry(Check, Idx);
482
    Result := assigned(rec);
483
  end;
484
end;
485
 
486
function TZMCentralEntry.GetCompressedSize: Int64;
487
var
488
  r: TZMIRec;
489
begin
490
  Result := 0;
491
  if Fetch(r) then
492
    Result := r.CompressedSize;
493
end;
494
 
495
function TZMCentralEntry.GetCompressionMethod: Word;
496
var
497
  r: TZMIRec;
498
begin
499
  Result := 0;
500
  if Fetch(r) then
501
    Result := r.ComprMethod;
502
end;
503
 
504
function TZMCentralEntry.GetCRC32: Cardinal;
505
var
506
  r: TZMIRec;
507
begin
508
  Result := 0;
509
  if Fetch(r) then
510
    Result := r.CRC32;
511
end;
512
 
513
function TZMCentralEntry.GetDateTime: Cardinal;
514
var
515
  r: TZMIRec;
516
begin
517
  Result := 0;
518
  if Fetch(r) then
519
    Result := r.ModifDateTime;
520
end;
521
 
522
function TZMCentralEntry.GetEncoded: TZMEncodingOpts;
523
var
524
  r: TZMIRec;
525
begin
526
  Result := zeoOEM;
527
  if Fetch(r) then
528
    Result := r.IsEncoded;
529
end;
530
 
531
function TZMCentralEntry.GetEncrypted: Boolean;
532
var
533
  r: TZMIRec;
534
begin
535
  Result := False;
536
  if Fetch(r) then
537
    Result := r.Encrypted;
538
end;
539
 
540
function TZMCentralEntry.GetExtFileAttrib: Longword;
541
var
542
  r: TZMIRec;
543
begin
544
  Result := 0;
545
  if Fetch(r) then
546
    Result := r.ExtFileAttrib;
547
end;
548
 
549
function TZMCentralEntry.GetExtraData(Tag: Word): TZMRawBytes;
550
var
551
  r: TZMIRec;
552
begin
553
  Result := '';
554
  if Fetch(r) then
555
    Result := r.ExtraData[Tag];
556
end;
557
 
558
function TZMCentralEntry.GetExtraField: TZMRawBytes;
559
var
560
  r: TZMIRec;
561
begin
562
  Result := '';
563
  if Fetch(r) then
564
    Result := r.ExtraField;
565
end;
566
 
567
function TZMCentralEntry.GetExtraFieldLength: Word;
568
var
569
  r: TZMIRec;
570
begin
571
  Result := 0;
572
  if Fetch(r) then
573
    Result := r.ExtraFieldLength;
574
end;
575
 
576
function TZMCentralEntry.GetFileComment: TZMString;
577
var
578
  r: TZMIRec;
579
begin
580
  Result := '';
581
  if Fetch(r) then
582
    Result := r.FileComment;
583
end;
584
 
585
function TZMCentralEntry.GetFileCommentLen: Word;
586
var
587
  r: TZMIRec;
588
begin
589
  Result := 0;
590
  if Fetch(r) then
591
    Result := r.FileCommentLen;
592
end;
593
 
594
function TZMCentralEntry.GetFileName: TZMString;
595
var
596
  r: TZMIRec;
597
begin
598
  Result := '';
599
  if Fetch(r) then
600
    Result := r.FileName;
601
end;
602
 
603
function TZMCentralEntry.GetFileNameLength: Word;
604
var
605
  r: TZMIRec;
606
begin
607
  Result := 0;
608
  if Fetch(r) then
609
    Result := r.FileNameLength;
610
end;
611
 
612
function TZMCentralEntry.GetFlag: Word;
613
var
614
  r: TZMIRec;
615
begin
616
  Result := 0;
617
  if Fetch(r) then
618
    Result := r.Flag;
619
end;
620
 
621
function TZMCentralEntry.GetHeaderName: TZMRawBytes;
622
var
623
  r: TZMIRec;
624
begin
625
  Result := '';
626
  if Fetch(r) then
627
    Result := r.HeaderName;
628
end;
629
 
630
function TZMCentralEntry.GetIntFileAttrib: Word;
631
var
632
  r: TZMIRec;
633
begin
634
  Result := 0;
635
  if Fetch(r) then
636
    Result := r.IntFileAttrib;
637
end;
638
 
639
function TZMCentralEntry.GetRelOffLocalHdr: Int64;
640
var
641
  r: TZMIRec;
642
begin
643
  Result := 0;
644
  if Fetch(r) then
645
    Result := r.RelOffLocal;
646
end;
647
 
648
function TZMCentralEntry.GetStartOnDisk: Word;
649
var
650
  r: TZMIRec;
651
begin
652
  Result := 0;
653
  if Fetch(r) then
654
    Result := r.DiskStart;
655
end;
656
 
657
function TZMCentralEntry.GetStatusBits: Cardinal;
658
var
659
  r: TZMIRec;
660
begin
661
  Result := 0;
662
  if Fetch(r) then
663
    Result := r.StatusBits;
664
end;
665
 
666
function TZMCentralEntry.GetUncompressedSize: Int64;
667
var
668
  r: TZMIRec;
669
begin
670
  Result := 0;
671
  if Fetch(r) then
672
    Result := r.UncompressedSize;
673
end;
674
 
675
function TZMCentralEntry.GetVersionMadeBy: Word;
676
var
677
  r: TZMIRec;
678
begin
679
  Result := 0;
680
  if Fetch(r) then
681
    Result := r.VersionMadeBy;
682
end;
683
 
684
function TZMCentralEntry.GetVersionNeeded: Word;
685
var
686
  r: TZMIRec;
687
begin
688
  Result := 0;
689
  if Fetch(r) then
690
    Result := r.VersionNeeded;
691
end;
692
 
693
end.
694