Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  695.