511 lines
18 KiB
ObjectPascal
511 lines
18 KiB
ObjectPascal
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ****************************************************************************
|
|
// * Project : FWZip
|
|
// * Unit Name : FWZipModifier
|
|
// * Purpose : Êëàññ äëÿ ìîäèôèêàöèè ñîçäàííîãî ðàíåå ZIP àðõèâà
|
|
// * Author : Àëåêñàíäð (Rouse_) Áàãåëü
|
|
// * Copyright : © Fangorn Wizards Lab 1998 - 2023.
|
|
// * Version : 2.0.2
|
|
// * Home Page : http://rouse.drkb.ru
|
|
// * Home Blog : http://alexander-bagel.blogspot.ru
|
|
// ****************************************************************************
|
|
// * Stable Release : http://rouse.drkb.ru/components.php#fwzip
|
|
// * Latest Source : https://github.com/AlexanderBagel/FWZip
|
|
// ****************************************************************************
|
|
//
|
|
// Èñïîëüçóåìûå èñòî÷íèêè:
|
|
// ftp://ftp.info-zip.org/pub/infozip/doc/appnote-iz-latest.zip
|
|
// https://zlib.net/zlib-1.2.13.tar.gz
|
|
// http://www.base2ti.com/
|
|
//
|
|
|
|
unit FWZipModifier;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE Delphi}
|
|
{$H+}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes,
|
|
SysUtils,
|
|
FWZipConsts,
|
|
FWZipReader,
|
|
FWZipWriter,
|
|
FWZipStream,
|
|
FWZipZLib,
|
|
FWZipUtils;
|
|
|
|
type
|
|
TReaderIndex = Integer;
|
|
|
|
TFWZipModifierItem = class(TFWZipWriterItem)
|
|
private
|
|
FReaderIndex: TReaderIndex; // èíäåêñ TFWZipReader â ìàññèâå TFWZipModifier.FReaderList
|
|
FOriginalItemIndex: Integer; // îðèãèíàëüíûé èíäåêñ ýëåìåíòà â èçíà÷àëüíîì àðõèâå
|
|
FOverloadItemPath: string; // çàäàâàåìûé èçâíå ïóòü ýëåìåíòà â àðõèâå
|
|
protected
|
|
property ReaderIndex: TReaderIndex read FReaderIndex write FReaderIndex;
|
|
property OriginalItemIndex: Integer read FOriginalItemIndex write FOriginalItemIndex;
|
|
property OverloadItemPath: string read FOverloadItemPath write FOverloadItemPath;
|
|
public
|
|
constructor Create(Owner: TFWZipWriter;
|
|
const InitFilePath: string;
|
|
InitAttributes: TFileAttributeData;
|
|
const InitFileName: string = ''); override;
|
|
end;
|
|
|
|
EFWZipModifier = class(Exception);
|
|
|
|
// Äàííàÿ ñòðóêòóðà õðàíèò âñå áëîêè ExData èç ïîäêëþ÷àåìûõ àðõèâîâ
|
|
TExDataRecord = record
|
|
Index: Integer;
|
|
Tag: Word;
|
|
Stream: TMemoryStream;
|
|
end;
|
|
TExDataRecords = array of TExDataRecord;
|
|
|
|
// ñòðóêòóðà äëÿ õðàíåíèÿ ïîäêëþ÷åííîãî àðõèâà è åãî áëîêîâ ExData
|
|
TReaderOwnership = (roReference, roOwned);
|
|
TReaderData = record
|
|
Reader: TFWZipReader;
|
|
ExDataRecords: TExDataRecords;
|
|
Ownership: TReaderOwnership;
|
|
end;
|
|
|
|
TReaderList = array of TReaderData;
|
|
|
|
TFWZipModifier = class(TFWZipWriter)
|
|
private
|
|
FReaderList: TReaderList;
|
|
function CheckZipFileIndex(Value: TReaderIndex): TReaderIndex;
|
|
function AddItemFromZip(AReader: TFWZipReader;
|
|
ReaderIndex: TReaderIndex; ItemIndex: Integer;
|
|
OverloadItemPath: string): Integer;
|
|
function GetReader(Index: Integer): TFWZipReader;
|
|
protected
|
|
function GetItemClass: TFWZipWriterItemClass; override;
|
|
procedure FillItemCDFHeader(CurrentItem: TFWZipWriterItem;
|
|
var Value: TCentralDirectoryFileHeaderEx); override;
|
|
procedure CompressItem(CurrentItem: TFWZipWriterItem;
|
|
Index: Integer; StreamSizeBeforeCompress: Int64; Stream: TStream); override;
|
|
procedure FillExData(Stream: TStream; Index: Integer); override;
|
|
procedure OnLoadExData(Sender: TObject; ItemIndex: Integer;
|
|
Tag: Word; Data: TStream);
|
|
public
|
|
destructor Destroy; override;
|
|
function AddZipFile(const AReader: TFWZipReader;
|
|
AOwnership: TReaderOwnership = roReference): TReaderIndex; overload;
|
|
function AddZipFile(const FilePath: string; SFXOffset: Integer = -1;
|
|
ZipEndOffset: Integer = -1): TReaderIndex; overload;
|
|
function AddZipFile(FileStream: TStream; SFXOffset: Integer = -1;
|
|
ZipEndOffset: Integer = -1): TReaderIndex; overload;
|
|
function AddFromZip(ReaderIndex: TReaderIndex): Integer; overload;
|
|
function AddFromZip(ReaderIndex: TReaderIndex; const ItemPath: string): Integer; overload;
|
|
function AddFromZip(ReaderIndex: TReaderIndex; const ItemPath, NewItemPath: string): Integer; overload;
|
|
function AddFromZip(ReaderIndex: TReaderIndex; ItemsList: TStringList): Integer; overload;
|
|
function ReadersCount: Integer;
|
|
property Reader[Index: Integer]: TFWZipReader read GetReader;
|
|
end;
|
|
|
|
implementation
|
|
|
|
type
|
|
TFWZipReaderFriendly = class(TFWZipReader);
|
|
TFWZipReaderItemFriendly = class(TFWZipReaderItem);
|
|
|
|
{ TFWZipModifierItem }
|
|
|
|
//
|
|
//  êîíñòðóêòîðå ïðîèçâîäèì ïåðâè÷íóþ èíèöèàëèçàöèþ ïîëåé
|
|
// Ñàìè ïîëÿ ReaderIndex è OriginalItemIndex áóäóò èíèöèàëèçèðîâàòüñÿ òîëüêî
|
|
// ïðè äîáàâëåíèè èõ ïîñðåäñòâîì êëàññà TFWZipModifier
|
|
// =============================================================================
|
|
constructor TFWZipModifierItem.Create(Owner: TFWZipWriter;
|
|
const InitFilePath: string; InitAttributes: TFileAttributeData;
|
|
const InitFileName: string);
|
|
begin
|
|
inherited Create(Owner, InitFilePath, InitAttributes, InitFileName);
|
|
FReaderIndex := -1;
|
|
FOriginalItemIndex := -1;
|
|
end;
|
|
|
|
{ TFWZipModifier }
|
|
|
|
//
|
|
// Ôóíêöèÿ ïåðåíîñèò ýëåìåíò â ôèíàëüíûé àðõèâ èç ðàíåå äîáàâëåííîãî àðõèâà.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò èíäåêñ ýëåìåíòà â ñïèñêå.
|
|
// Ïàðàìåòðû:
|
|
// ReaderIndex - èíäåêñ ðàíåå äîáàâëåííî ôóíêöèåé AddZipFile àðõèâà
|
|
// ItemPath - èìÿ ýëåìåíòà, êîòîðîå òðåáóåòñÿ äîáàâèòü
|
|
// =============================================================================
|
|
function TFWZipModifier.AddFromZip(ReaderIndex: TReaderIndex;
|
|
const ItemPath: string): Integer;
|
|
begin
|
|
Result := AddFromZip(ReaderIndex, ItemPath, EmptyStr);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ ïåðåíîñèò âñå ýëåìåíòû èç ðàíåå äîáàâëåííîãî àðõèâà â ôèíàëüíûé àðõèâ.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò êîëè÷åñòâî óñïåøíî äîáàâëåííûõ ýëåìåíòîâ.
|
|
// Ïàðàìåòðû:
|
|
// ReaderIndex - èíäåêñ ðàíåå äîáàâëåííî ôóíêöèåé AddZipFile àðõèâà
|
|
// =============================================================================
|
|
function TFWZipModifier.AddFromZip(ReaderIndex: TReaderIndex): Integer;
|
|
var
|
|
I: Integer;
|
|
Reader: TFWZipReader;
|
|
begin
|
|
CheckZipFileIndex(ReaderIndex);
|
|
Result := 0;
|
|
Reader := FReaderList[ReaderIndex].Reader;
|
|
for I := 0 to Reader.Count - 1 do
|
|
if AddItemFromZip(Reader, ReaderIndex, I, EmptyStr) >= 0 then
|
|
Inc(Result);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ ïåðåíîñèò âñå ýëåìåíòû èç ðàíåå äîáàâëåííîãî àðõèâà
|
|
// ïî ñïèñêó â ôèíàëüíûé àðõèâ.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò êîëè÷åñòâî óñïåøíî äîáàâëåííûõ ýëåìåíòîâ.
|
|
// Ïàðàìåòðû:
|
|
// ReaderIndex - èíäåêñ ðàíåå äîáàâëåííî ôóíêöèåé AddZipFile àðõèâà
|
|
// ItemsList - ñïèñîê ýëåìåíòîâ ê äîáàâëåíèþ
|
|
// =============================================================================
|
|
function TFWZipModifier.AddFromZip(ReaderIndex: TReaderIndex;
|
|
ItemsList: TStringList): Integer;
|
|
var
|
|
I: Integer;
|
|
Reader: TFWZipReader;
|
|
begin
|
|
CheckZipFileIndex(ReaderIndex);
|
|
Result := 0;
|
|
Reader := FReaderList[ReaderIndex].Reader;
|
|
for I := 0 to ItemsList.Count - 1 do
|
|
if AddItemFromZip(Reader, ReaderIndex,
|
|
Reader.GetElementIndex(ItemsList[I]), EmptyStr) >= 0 then
|
|
Inc(Result);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ ïåðåíîñèò ýëåìåíò â ôèíàëüíûé àðõèâ èç ðàíåå äîáàâëåííîãî àðõèâà.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò èíäåêñ ýëåìåíòà â ñïèñêå.
|
|
// Ïàðàìåòðû:
|
|
// ReaderIndex - èíäåêñ ðàíåå äîáàâëåííî ôóíêöèåé AddZipFile àðõèâà
|
|
// ItemPath - èìÿ ýëåìåíòà, êîòîðîå òðåáóåòñÿ äîáàâèòü
|
|
// NewItemPath - íîâîå èìÿ ýëåìåíòà â àðõèâå
|
|
// =============================================================================
|
|
function TFWZipModifier.AddFromZip(ReaderIndex: TReaderIndex; const ItemPath,
|
|
NewItemPath: string): Integer;
|
|
var
|
|
Reader: TFWZipReader;
|
|
begin
|
|
CheckZipFileIndex(ReaderIndex);
|
|
Reader := FReaderList[ReaderIndex].Reader;
|
|
Result :=
|
|
AddItemFromZip(Reader, ReaderIndex, Reader.GetElementIndex(ItemPath),
|
|
CheckFileNameSlashes( NewItemPath));
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ ïåðåíîñèò ýëåìåíò â ôèíàëüíûé àðõèâ èç ðàíåå äîáàâëåííîãî àðõèâà.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò èíäåêñ ýëåìåíòà â ñïèñêå.
|
|
// =============================================================================
|
|
function TFWZipModifier.AddItemFromZip(AReader: TFWZipReader;
|
|
ReaderIndex: TReaderIndex; ItemIndex: Integer;
|
|
OverloadItemPath: string): Integer;
|
|
const
|
|
OldItemType: array [Boolean] of string = ('file', 'folder');
|
|
var
|
|
OldItem: TFWZipReaderItemFriendly;
|
|
NewItem: TFWZipModifierItem;
|
|
begin
|
|
Result := -1;
|
|
if ItemIndex < 0 then Exit;
|
|
// Ïîëó÷àåì óêàçàòåëü íà ýëåìåíò èç óæå ñóùåñòâóþùåãî àðõèâà
|
|
OldItem := TFWZipReaderItemFriendly(AReader.Item[ItemIndex]);
|
|
// Ïðîâåðêà ñîîòâåòñòâèÿ íîâîãî èìåíè òèïó ñòàðîãî ýëåìåíòà
|
|
if OverloadItemPath <> '' then
|
|
begin
|
|
if OverloadItemPath <> OldItem.FileName then
|
|
begin
|
|
if OldItem.IsFolder <>
|
|
(OverloadItemPath[Length(OverloadItemPath)] = ZIP_SLASH) then
|
|
raise EFWZipModifier.CreateFmt(
|
|
'"%s" does not match the %s path.',
|
|
[OverloadItemPath, OldItemType[OldItem.IsFolder]]);
|
|
end
|
|
else
|
|
OverloadItemPath := EmptyStr;
|
|
end;
|
|
// ñîçäàåì íîâûé ýëåìåíò, êîòîðûé áóäåì äîáàâëÿòü ê íîâîìó àðõèâó
|
|
NewItem := TFWZipModifierItem(
|
|
GetItemClass.Create(Self, '', OldItem.Attributes, OldItem.FileName));
|
|
// ïåðåêëþ÷àåì åãî â ðåæèì ïîëó÷åíèÿ äàííûõ âðó÷íóþ
|
|
NewItem.UseExternalData := True;
|
|
// èíèöèàëèçèðóåì åìó èíäåêñû, äàáû ïîòîì ïîíÿòü, îòêóäà áðàòü î íåì äàííûå
|
|
NewItem.ReaderIndex := ReaderIndex;
|
|
NewItem.OriginalItemIndex := ItemIndex;
|
|
NewItem.OverloadItemPath := OverloadItemPath;
|
|
// èíèöèàëèçèðóåì âíåøíèå è ðàññ÷èòûâàåìûå ïîëÿ
|
|
NewItem.Comment := OldItem.Comment;
|
|
NewItem.NeedDescriptor :=
|
|
OldItem.CentralDirFileHeader.GeneralPurposeBitFlag and PBF_DESCRIPTOR <> 0;
|
|
NewItem.UseUTF8String :=
|
|
OldItem.CentralDirFileHeader.GeneralPurposeBitFlag and PBF_UTF8 <> 0;
|
|
// äîáàâëÿåì
|
|
Result := AddNewItem(NewItem);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ äîáàâëÿåò íîâûé àðõèâ èç êîòîðîãî ìîæíî áðàòü ãîòîâûå äàííûå.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò èíäåêñ àðõèâà â ñïèñêå äîáàâëåííûõ.
|
|
// Ïàðàìåòðû:
|
|
// FileStream - ïîòîê ñ äàííûìè àðõèâà
|
|
// SFXOffset è ZipEndOffset - åãî ãðàíèöû
|
|
// =============================================================================
|
|
function TFWZipModifier.AddZipFile(FileStream: TStream; SFXOffset,
|
|
ZipEndOffset: Integer): TReaderIndex;
|
|
var
|
|
AReader: TFWZipReader;
|
|
begin
|
|
AReader := TFWZipReader.Create;
|
|
Result := AddZipFile(AReader, roOwned);
|
|
AReader.OnLoadExData := OnLoadExData;
|
|
AReader.LoadFromStream(FileStream, SFXOffset, ZipEndOffset);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ äîáàâëÿåò íîâíûé ðèäåð â ñïèñîê äîñòóïíûõ
|
|
// Çàãðóçêà äàííûõ íå ïðîèçâîäèòñÿ, ïîýòîìó äàííûé âàðèàíò äîáàâëåíèÿ
|
|
// ðèäåðà íå ïîçâîëèò ðàáîòàòü ñ áëîêîì ExData åñëè òàêîâîé ïðèñóòñòâóåò.
|
|
// =============================================================================
|
|
function TFWZipModifier.AddZipFile(const AReader: TFWZipReader;
|
|
AOwnership: TReaderOwnership): TReaderIndex;
|
|
begin
|
|
Result := Length(FReaderList);
|
|
SetLength(FReaderList, Result + 1);
|
|
FReaderList[Result].Reader := AReader;
|
|
FReaderList[Result].Ownership := AOwnership;
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ äîáàâëÿåò íîâûé àðõèâ èç êîòîðîãî ìîæíî áðàòü ãîòîâûå äàííûå.
|
|
//  êà÷åñòâå ðåçóëüòàòà âîçâðàùàåò èíäåêñ àðõèâà â ñïèñêå äîáàâëåííûõ.
|
|
// Ïàðàìåòðû:
|
|
// FilePath - ïóòü ê äîáàâëÿåìîìó àðõèâó
|
|
// SFXOffset è ZipEndOffset - åãî ãðàíèöû
|
|
// =============================================================================
|
|
function TFWZipModifier.AddZipFile(const FilePath: string;
|
|
SFXOffset, ZipEndOffset: Integer): TReaderIndex;
|
|
var
|
|
AReader: TFWZipReader;
|
|
begin
|
|
AReader := TFWZipReader.Create;
|
|
Result := AddZipFile(AReader, roOwned);
|
|
AReader.OnLoadExData := OnLoadExData;
|
|
AReader.LoadFromFile(FilePath, SFXOffset, ZipEndOffset);
|
|
end;
|
|
|
|
//
|
|
// Ôóíêöèÿ ïðîâåðÿåò ïðàâèëüíîñòü ïåðåäàííîãî èíäåêñà àðõèâà â ñïèñêå
|
|
// =============================================================================
|
|
function TFWZipModifier.CheckZipFileIndex(Value: TReaderIndex): TReaderIndex;
|
|
begin
|
|
Result := Value;
|
|
if (Value < 0) or (Value >= Length(FReaderList)) then
|
|
raise EFWZipModifier.CreateFmt('Invalid index value (%d).', [Value]);
|
|
end;
|
|
|
|
//
|
|
// Ïðîöåäóðà ïåðåêðûâàåò ñæàòèå äàííûõ ýåëåìåíòà
|
|
// è áåðåò ýòè äàííûå èç ðàíåå ñôîðìèðîâàííîãî àðõèâà.
|
|
// =============================================================================
|
|
procedure TFWZipModifier.CompressItem(CurrentItem: TFWZipWriterItem;
|
|
Index: Integer; StreamSizeBeforeCompress: Int64; Stream: TStream);
|
|
var
|
|
OldItem: TFWZipReaderItemFriendly;
|
|
NewItem: TFWZipModifierItem;
|
|
Reader: TFWZipReaderFriendly;
|
|
Offset: Int64;
|
|
begin
|
|
NewItem := TFWZipModifierItem(CurrentItem);
|
|
// ïðîâåðêà, ðàáîòàåì ëè ìû ñ ýëåìåíòîì, äàííûå êîòîðîãî çàïîëíÿþòñÿ âðó÷íóþ?
|
|
if not NewItem.UseExternalData then
|
|
begin
|
|
inherited;
|
|
Exit;
|
|
end;
|
|
// ïîëó÷àåì óêàçàòåëü íà êëàññ, êîòîðûé äåðæèò äîáàâëåííûé ðàíåå àðõèâ
|
|
Reader := TFWZipReaderFriendly(FReaderList[NewItem.ReaderIndex].Reader);
|
|
// ïîëó÷àåì óêàçàòåëü íà îðèãèíàëüíûé ýëåìåíò àðõèâà
|
|
OldItem := TFWZipReaderItemFriendly(Reader.Item[NewItem.OriginalItemIndex]);
|
|
// ðàññ÷èòûâàåì åãî ïîçèöèþ â àðõèâå
|
|
if IsMultiPartZip(Reader.ZIPStream) then
|
|
begin
|
|
TFWAbstractMultiStream(Reader.ZIPStream).Seek(
|
|
OldItem.CentralDirFileHeader.DiskNumberStart,
|
|
OldItem.CentralDirFileHeader.RelativeOffsetOfLocalHeader);
|
|
Offset := Reader.ZIPStream.Position;
|
|
end
|
|
else
|
|
Offset := OldItem.CentralDirFileHeader.RelativeOffsetOfLocalHeader;
|
|
Inc(Offset, SizeOf(TLocalFileHeader));
|
|
Inc(Offset, OldItem.CentralDirFileHeader.FilenameLength);
|
|
if OldItem.CentralDirFileHeaderEx.UncompressedSize >= MAXDWORD then
|
|
Inc(Offset, SizeOf(TExDataInfo64));
|
|
Reader.ZIPStream.Position := Offset;
|
|
// êîïèðóåì äàííûå êàê åñòü, áåç ïåðåïàêîâêè
|
|
Stream.CopyFrom(Reader.ZIPStream, OldItem.CentralDirFileHeaderEx.CompressedSize);
|
|
end;
|
|
|
|
//
|
|
// Modifier ñëåãêà íå îïòèìàëüíî ðàñõîäóåò ïàìÿòü, ïîýòîìó ïîä÷èùàåì.
|
|
// =============================================================================
|
|
destructor TFWZipModifier.Destroy;
|
|
var
|
|
I, A: Integer;
|
|
begin
|
|
for I := 0 to Length(FReaderList) - 1 do
|
|
begin
|
|
if FReaderList[I].Ownership = roOwned then
|
|
FReaderList[I].Reader.Free;
|
|
for A := 0 to Length(FReaderList[I].ExDataRecords) - 1 do
|
|
FReaderList[I].ExDataRecords[A].Stream.Free;
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
//
|
|
// Ïðîöåäóðà ïåðåêðûâàåò çàïîëíåíèå áëîêîâ ExData
|
|
// è áåðåò ýòè äàííûå èç ðàíåå ñôîðìèðîâàííîãî àðõèâà.
|
|
// =============================================================================
|
|
procedure TFWZipModifier.FillExData(Stream: TStream; Index: Integer);
|
|
var
|
|
NewItem: TFWZipModifierItem;
|
|
ReaderIndex: TReaderIndex;
|
|
I: Integer;
|
|
{%H-}ExDataSize: Word;
|
|
ExDataRecord: TExDataRecord;
|
|
begin
|
|
NewItem := TFWZipModifierItem(Item[Index]);
|
|
// ïðîâåðêà, ðàáîòàåì ëè ìû ñ ýëåìåíòîì, äàííûå êîòîðîãî çàïîëíÿþòñÿ âðó÷íóþ?
|
|
if not NewItem.UseExternalData then
|
|
begin
|
|
inherited;
|
|
Exit;
|
|
end;
|
|
// ïðîâåðÿåì ïðèâÿçêó ê àðõèâó, ñ åëåìåíòîâ êîòîðîãî ìû áóäåì äîáàâëÿòü áëîêè ExData
|
|
ReaderIndex := CheckZipFileIndex(NewItem.ReaderIndex);
|
|
for I := 0 to Length(FReaderList[ReaderIndex].ExDataRecords) - 1 do
|
|
if FReaderList[ReaderIndex].ExDataRecords[I].Index = NewItem.OriginalItemIndex then
|
|
begin
|
|
// áëîêîâ ìîæåò áûòü íåñêîëüêî, ïîýòîìó äîáàâëÿåì èõ âñå
|
|
ExDataRecord := FReaderList[ReaderIndex].ExDataRecords[I];
|
|
Stream.WriteBuffer(ExDataRecord.Tag, 2);
|
|
ExDataSize := ExDataRecord.Stream.Size;
|
|
Stream.WriteBuffer(ExDataSize, 2);
|
|
Stream.CopyFrom(ExDataRecord.Stream, 0);
|
|
end;
|
|
end;
|
|
|
|
//
|
|
// Ïðîöåäóðà ïåðåêðûâàåò çàïîëíåíèå ñòðóêòóðû TCentralDirectoryFileHeaderEx
|
|
// è áåðåò ýòè äàííûå èç ðàíåå ñôîðìèðîâàííîãî àðõèâà.
|
|
// =============================================================================
|
|
procedure TFWZipModifier.FillItemCDFHeader(CurrentItem: TFWZipWriterItem;
|
|
var Value: TCentralDirectoryFileHeaderEx);
|
|
var
|
|
OldItem: TFWZipReaderItemFriendly;
|
|
NewItem: TFWZipModifierItem;
|
|
Reader: TFWZipReader;
|
|
FileDate: Cardinal;
|
|
begin
|
|
NewItem := TFWZipModifierItem(CurrentItem);
|
|
|
|
// ïðîâåðêà, ðàáîòàåì ëè ìû ñ ýëåìåíòîì, äàííûå êîòîðîãî çàïîëíÿþòñÿ âðó÷íóþ?
|
|
if not NewItem.UseExternalData then
|
|
begin
|
|
inherited;
|
|
Exit;
|
|
end;
|
|
|
|
Reader := FReaderList[NewItem.ReaderIndex].Reader;
|
|
OldItem := TFWZipReaderItemFriendly(Reader.Item[NewItem.OriginalItemIndex]);
|
|
|
|
// ïîëíîñòüþ ïåðåçàïèñûâàåì âñå äàííûå ñòðóêòóðû
|
|
// èñêëþ÷åíèåì ÿâëÿåòñÿ ïîëå RelativeOffsetOfLocalHeader
|
|
// íî îíî ðåèíèöèàëèçèðóåòñÿ ïîñëå âûçîâà äàííîãî ìåòîäà
|
|
Value := OldItem.CentralDirFileHeaderEx;
|
|
|
|
// Rouse_ 11.11.2023
|
|
// åñëè èìÿ â àðõèâå áûëî ïåðåíàçíà÷åíî,
|
|
// òî ìåíÿåì åãî ñ ïðàâêîé âðåìåíè ïîñëåäíåãî èçìåíåíèÿ
|
|
if NewItem.OverloadItemPath <> '' then
|
|
begin
|
|
Value.Filename := NewItem.OverloadItemPath;
|
|
Value.Header.FilenameLength :=
|
|
StringLength(NewItem.OverloadItemPath, CurrentItem.UseUTF8String);
|
|
|
|
Value.Attributes.ftLastWriteTime := GetCurrentFileTime;
|
|
FileDate := FileTimeToLocalFileDate(Value.Attributes.ftLastWriteTime);
|
|
|
|
Value.Header.LastModFileTimeTime := FileDate and $FFFF;
|
|
Value.Header.LastModFileTimeDate := FileDate shr 16;
|
|
end;
|
|
end;
|
|
|
|
//
|
|
// Ðàñøèðÿåì êîëëåêöèþ
|
|
// =============================================================================
|
|
function TFWZipModifier.GetItemClass: TFWZipWriterItemClass;
|
|
begin
|
|
Result := TFWZipModifierItem;
|
|
end;
|
|
|
|
//
|
|
// Âîçâðàùàåì ñûëêó íà âíóòðåííèé ðèäåð
|
|
// =============================================================================
|
|
function TFWZipModifier.GetReader(Index: Integer): TFWZipReader;
|
|
begin
|
|
if (Index < 0) or (Index >= ReadersCount) then
|
|
raise EFWZipModifier.CreateFmt('Invalid reader index value (%d).', [Index]);
|
|
Result := FReaderList[Index].Reader;
|
|
end;
|
|
|
|
//
|
|
// Çàäà÷à ïðîöåäóðû ñîáðàòü âñå ExData â ëîêàëüíîå õðàíèëèùå,
|
|
// ÷òîáû èõ ìîæíî áûëî ïðèñîåäèíèòü ê ñòðóêòóðå àðõèâà íà ýòàïå ðåáèëäà
|
|
// =============================================================================
|
|
procedure TFWZipModifier.OnLoadExData(Sender: TObject; ItemIndex: Integer;
|
|
Tag: Word; Data: TStream);
|
|
var
|
|
Index, ExDataCount: Integer;
|
|
ExData: TExDataRecord;
|
|
begin
|
|
Index := ReadersCount - 1;
|
|
if Index >= 0 then
|
|
begin
|
|
ExData.Index := ItemIndex;
|
|
ExData.Tag := Tag;
|
|
ExData.Stream := TMemoryStream.Create;
|
|
ExData.Stream.CopyFrom(Data, 0);
|
|
ExDataCount := Length(FReaderList[Index].ExDataRecords);
|
|
SetLength(FReaderList[Index].ExDataRecords, ExDataCount + 1);
|
|
FReaderList[Index].ExDataRecords[ExDataCount] := ExData;
|
|
end;
|
|
end;
|
|
|
|
//
|
|
// Âîçâðàùàåì êîëè÷åñòâî äîñòóïíûõ ðèäåðîâ
|
|
// =============================================================================
|
|
function TFWZipModifier.ReadersCount: Integer;
|
|
begin
|
|
Result := Length(FReaderList);
|
|
end;
|
|
|
|
end.
|