352 lines
11 KiB
ObjectPascal
352 lines
11 KiB
ObjectPascal
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ****************************************************************************
|
|
// * Project : FWZip - ZipAnalizer
|
|
// * Unit Name : uZipAnalizer
|
|
// * Purpose : Âûâîä ïàðàìåòðîâ àðõèâà èñïîëüçóÿ âîçìîæíîñòè FWZipReader
|
|
// * Author : Àëåêñàíäð (Rouse_) Áàãåëü
|
|
// * Copyright : © Fangorn Wizards Lab 1998 - 2013.
|
|
// * Version : 1.0.10
|
|
// * 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
|
|
// http://zlib.net/zlib-1.2.5.tar.gz
|
|
// http://www.base2ti.com/
|
|
//
|
|
|
|
unit uZipAnalizer;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Controls, Forms,
|
|
Dialogs, StdCtrls, ComCtrls, ExtCtrls, Menus,
|
|
FWZipReader, FWZipConsts;
|
|
|
|
type
|
|
TFWZipReaderFriendly = class(TFWZipReader);
|
|
TFWZipReaderItemFriendly = class(TFWZipReaderItem);
|
|
TExDataRecord = record
|
|
Index: Integer;
|
|
Tag: Word;
|
|
Stream: TMemoryStream;
|
|
end;
|
|
TExDataRecords = array of TExDataRecord;
|
|
|
|
TdlgZipAnalizer = class(TForm)
|
|
edPath: TLabeledEdit;
|
|
btnBrowse: TButton;
|
|
btnAnalize: TButton;
|
|
GroupBox: TGroupBox;
|
|
edReport: TRichEdit;
|
|
OpenDialog: TOpenDialog;
|
|
PopupMenu: TPopupMenu;
|
|
mnuSave: TMenuItem;
|
|
SaveDialog: TSaveDialog;
|
|
procedure btnBrowseClick(Sender: TObject);
|
|
procedure edPathChange(Sender: TObject);
|
|
procedure btnAnalizeClick(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure mnuSaveClick(Sender: TObject);
|
|
procedure PopupMenuPopup(Sender: TObject);
|
|
private
|
|
ExDataRecords: TExDataRecords;
|
|
Zip: TFWZipReaderFriendly;
|
|
procedure OnLoadExData(Sender: TObject; ItemIndex: Integer;
|
|
Tag: Word; Data: TStream);
|
|
private
|
|
procedure ClearExData;
|
|
procedure Log(const Value: string);
|
|
procedure ShowEndOfCentralDir;
|
|
procedure ShowZip64EOFCentralDirectoryLocator;
|
|
procedure ShowZip64EOFCentralDirectoryRecord;
|
|
procedure ShowItemData(Index: Integer);
|
|
end;
|
|
|
|
var
|
|
dlgZipAnalizer: TdlgZipAnalizer;
|
|
|
|
implementation
|
|
|
|
const
|
|
Delim = '===================================================================';
|
|
|
|
{$R *.dfm}
|
|
|
|
procedure TdlgZipAnalizer.btnAnalizeClick(Sender: TObject);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
edReport.Lines.BeginUpdate;
|
|
try
|
|
edReport.Clear;
|
|
Log(edPath.Text);
|
|
Log(Delim);
|
|
ClearExData;
|
|
Zip.Clear;
|
|
Zip.LoadFromFile(edPath.Text);
|
|
ShowEndOfCentralDir;
|
|
ShowZip64EOFCentralDirectoryLocator;
|
|
ShowZip64EOFCentralDirectoryRecord;
|
|
for I := 0 to Zip.Count - 1 do
|
|
ShowItemData(I);
|
|
Log('DONE');
|
|
finally
|
|
edReport.Lines.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.btnBrowseClick(Sender: TObject);
|
|
begin
|
|
if OpenDialog.Execute then
|
|
begin
|
|
edPath.Text := OpenDialog.FileName;
|
|
edReport.Clear;
|
|
end;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.ClearExData;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Length(ExDataRecords) - 1 do
|
|
ExDataRecords[I].Stream.Free;
|
|
SetLength(ExDataRecords, 0);;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.edPathChange(Sender: TObject);
|
|
begin
|
|
btnAnalize.Enabled := FileExists(edPath.Text);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.FormCreate(Sender: TObject);
|
|
begin
|
|
Zip := TFWZipReaderFriendly.Create;
|
|
Zip.OnLoadExData := OnLoadExData;
|
|
edReport.PlainText := True;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.FormDestroy(Sender: TObject);
|
|
begin
|
|
ClearExData;
|
|
Zip.Free;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.Log(const Value: string);
|
|
begin
|
|
edReport.Lines.Add(Value);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.mnuSaveClick(Sender: TObject);
|
|
begin
|
|
if SaveDialog.Execute then
|
|
edReport.Lines.SaveToFile(SaveDialog.FileName);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.OnLoadExData(Sender: TObject; ItemIndex: Integer;
|
|
Tag: Word; Data: TStream);
|
|
var
|
|
Count: Integer;
|
|
begin
|
|
Count := Length(ExDataRecords);
|
|
SetLength(ExDataRecords, Count + 1);
|
|
ExDataRecords[Count].Index := ItemIndex;
|
|
ExDataRecords[Count].Tag := Tag;
|
|
ExDataRecords[Count].Stream := TMemoryStream.Create;
|
|
ExDataRecords[Count].Stream.CopyFrom(Data, 0);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.PopupMenuPopup(Sender: TObject);
|
|
begin
|
|
mnuSave.Enabled := edReport.Lines.Count > 1;
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.ShowEndOfCentralDir;
|
|
begin
|
|
Log('END_OF_CENTRAL_DIR_SIGNATURE found');
|
|
with Zip.EndOfCentralDir do
|
|
begin
|
|
Log(Format('NumberOfThisDisk: %d', [NumberOfThisDisk]));
|
|
Log(Format('NumberOfTheDiskWithTheStart: %d', [NumberOfTheDiskWithTheStart]));
|
|
Log(Format('TotalNumberOfEntriesOnThisDisk: %d', [TotalNumberOfEntriesOnThisDisk]));
|
|
Log(Format('TotalNumberOfEntries: %d', [TotalNumberOfEntries]));
|
|
Log(Format('SizeOfTheCentralDirectory: %d', [SizeOfTheCentralDirectory]));
|
|
Log(Format('OffsetOfStartOfCentralDirectory: %d', [OffsetOfStartOfCentralDirectory]));
|
|
Log(Format('ZipfileCommentLength: %d', [ZipfileCommentLength]));
|
|
if ZipfileCommentLength > 0 then
|
|
Log(Format('Comment: %s', [Zip.Comment]));
|
|
end;
|
|
Log(Delim);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.ShowItemData(Index: Integer);
|
|
|
|
function ByteToStr(Bytes: PByte; Size: Integer): string;
|
|
const
|
|
BytesHex: array[0..15] of char =
|
|
('0', '1', '2', '3', '4', '5', '6', '7',
|
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
|
|
var
|
|
I: integer;
|
|
begin
|
|
SetLength(Result, Size shl 1);
|
|
for I := 0 to Size - 1 do
|
|
begin
|
|
Result[I * 2 + 1] := BytesHex[Bytes^ shr 4];
|
|
Result[I * 2 + 2] := BytesHex[Bytes^ and $0F];
|
|
Inc(Bytes);
|
|
end;
|
|
end;
|
|
|
|
function GPBFToStr(Value: Word): string;
|
|
|
|
procedure AddValue(const S: string);
|
|
begin
|
|
if Result = '' then
|
|
Result := S
|
|
else
|
|
Result := Result + ', ' + S;
|
|
end;
|
|
|
|
begin
|
|
if Value = 0 then
|
|
begin
|
|
Result := 'EMPTY';
|
|
Exit;
|
|
end;
|
|
if PBF_CRYPTED and Value <> 0 then
|
|
AddValue('PBF_CRYPTED');
|
|
|
|
if PBF_DESCRIPTOR and Value <> 0 then
|
|
AddValue('PBF_DESCRIPTOR');
|
|
|
|
if PBF_UTF8 and Value <> 0 then
|
|
AddValue('PBF_UTF8');
|
|
|
|
if PBF_STRONG_CRYPT and Value <> 0 then
|
|
AddValue('PBF_STRONG_CRYPT');
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
Item: TFWZipReaderItemFriendly;
|
|
begin
|
|
Log('CENTRAL_FILE_HEADER_SIGNATURE found');
|
|
Item := TFWZipReaderItemFriendly(Zip.Item[Index]);
|
|
with Item.CentralDirFileHeader do
|
|
begin
|
|
Log(Format('VersionMadeBy: %d', [VersionMadeBy]));
|
|
Log(Format('VersionNeededToExtract: %d', [VersionNeededToExtract]));
|
|
Log(Format('GeneralPurposeBitFlag: %d (%s)', [GeneralPurposeBitFlag,
|
|
GPBFToStr(GeneralPurposeBitFlag)]));
|
|
Log(Format('CompressionMethod: %d', [CompressionMethod]));
|
|
Log(Format('LastModFileTimeTime: %d', [LastModFileTimeTime]));
|
|
Log(Format('LastModFileTimeDate: %d', [LastModFileTimeDate]));
|
|
Log(Format('Crc32: %d', [Crc32]));
|
|
Log(Format('CompressedSize: %d', [CompressedSize]));
|
|
Log(Format('UncompressedSize: %d', [UncompressedSize]));
|
|
Log(Format('FilenameLength: %d', [FilenameLength]));
|
|
if FilenameLength > 0 then
|
|
Log('>>> FileName: ' + Item.FileName);
|
|
Log(Format('ExtraFieldLength: %d', [ExtraFieldLength]));
|
|
Log(Format('FileCommentLength: %d', [FileCommentLength]));
|
|
if FileCommentLength > 0 then
|
|
Log('>>> FileComment: ' + Item.Comment);
|
|
Log(Format('DiskNumberStart: %d', [DiskNumberStart]));
|
|
Log(Format('InternalFileAttributes: %d', [InternalFileAttributes]));
|
|
Log(Format('ExternalFileAttributes: %d', [ExternalFileAttributes]));
|
|
Log(Format('RelativeOffsetOfLocalHeader: %d', [RelativeOffsetOfLocalHeader]));
|
|
end;
|
|
|
|
Log('');
|
|
|
|
Item.LoadLocalFileHeader;
|
|
Log('LOCAL_FILE_HEADER_SIGNATURE found');
|
|
with Item.LocalFileHeader do
|
|
begin
|
|
Log(Format('VersionNeededToExtract: %d', [VersionNeededToExtract]));
|
|
Log(Format('GeneralPurposeBitFlag: %d (%s)', [GeneralPurposeBitFlag,
|
|
GPBFToStr(GeneralPurposeBitFlag)]));
|
|
Log(Format('CompressionMethod: %d', [CompressionMethod]));
|
|
Log(Format('LastModFileTimeTime: %d', [LastModFileTimeTime]));
|
|
Log(Format('LastModFileTimeDate: %d', [LastModFileTimeDate]));
|
|
Log(Format('Crc32: %d', [Crc32]));
|
|
Log(Format('CompressedSize: %d', [CompressedSize]));
|
|
Log(Format('UncompressedSize: %d', [UncompressedSize]));
|
|
Log(Format('FilenameLength: %d', [FilenameLength]));
|
|
Log(Format('ExtraFieldLength: %d', [ExtraFieldLength]));
|
|
end;
|
|
|
|
if ssZIP64 in Item.PresentStreams then
|
|
begin
|
|
Log('');
|
|
Log('SUPPORTED_EXDATA_ZIP64 found');
|
|
with Item do
|
|
begin
|
|
Log(Format('UncompressedSize: %d', [UncompressedSize]));
|
|
Log(Format('CompressedSize: %d', [CompressedSize]));
|
|
Log(Format('RelativeOffsetOfLocalHeader: %d', [RelativeOffsetOfLocalHeader]));
|
|
Log(Format('DiskNumberStart: %d', [DiskNumberStart]));
|
|
end;
|
|
end;
|
|
|
|
if ssNTFS in Item.PresentStreams then
|
|
begin
|
|
Log('');
|
|
Log('SUPPORTED_EXDATA_NTFSTIME found');
|
|
end;
|
|
|
|
for I := 0 to Length(ExDataRecords) - 1 do
|
|
if ExDataRecords[I].Index = Index then
|
|
begin
|
|
Log('');
|
|
Log(Format('UNKNOWN TAG (%d) found', [ExDataRecords[I].Tag]));
|
|
Log(Format('ExData size %d', [ExDataRecords[I].Stream.Size]));
|
|
Log('ExData dump:');
|
|
Log(ByteToStr(ExDataRecords[I].Stream.Memory, ExDataRecords[I].Stream.Size));
|
|
end;
|
|
|
|
Log(Delim);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.ShowZip64EOFCentralDirectoryLocator;
|
|
begin
|
|
with Zip.Zip64EOFCentralDirectoryLocator do
|
|
begin
|
|
if Signature <> ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE then Exit;
|
|
Log('ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE found');
|
|
Log(Format('NumberOfTheDisk: %d', [NumberOfTheDisk]));
|
|
Log(Format('RelativeOffset: %d', [RelativeOffset]));
|
|
Log(Format('TotalNumberOfDisks: %d', [TotalNumberOfDisks]));
|
|
end;
|
|
Log(Delim);
|
|
end;
|
|
|
|
procedure TdlgZipAnalizer.ShowZip64EOFCentralDirectoryRecord;
|
|
begin
|
|
with Zip.Zip64EOFCentralDirectoryRecord do
|
|
begin
|
|
if Zip64EndOfCentralDirSignature <> ZIP64_END_OF_CENTRAL_DIR_SIGNATURE then Exit;
|
|
Log('ZIP64_END_OF_CENTRAL_DIR_SIGNATURE found');
|
|
Log(Format('SizeOfZip64EOFCentralDirectoryRecord: %d', [SizeOfZip64EOFCentralDirectoryRecord]));
|
|
Log(Format('VersionMadeBy: %d', [VersionMadeBy]));
|
|
Log(Format('VersionNeededToExtract: %d', [VersionNeededToExtract]));
|
|
Log(Format('number of this disk: %d', [Number1]));
|
|
Log(Format('number of the disk with the start of the central directory: %d', [Number2]));
|
|
Log(Format('total number of entries in the central directory on this disk: %d', [TotalNumber1]));
|
|
Log(Format('total number of entries in the central directory: %d', [TotalNumber2]));
|
|
Log(Format('size of the central directory: %d', [Size]));
|
|
Log(Format('offset of start of central directory with respect to the starting disk number: %d', [Offset]));
|
|
end;
|
|
Log(Delim);
|
|
end;
|
|
|
|
end.
|