350 lines
13 KiB
Plaintext
350 lines
13 KiB
Plaintext
|
|
unit JclZLib;
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
JclZLibStreamDefaultBufferSize = 32 * 1024;
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
{$IFDEF MSWINDOWS}
|
|||
|
|
JclZLibDefaultLineSeparator = #$0D#$0A;
|
|||
|
|
{$ENDIF MSWINDOWS}
|
|||
|
|
{$IFDEF UNIX}
|
|||
|
|
JclZLibDefaultLineSeparator = #$0A;
|
|||
|
|
{$ENDIF UNIX}
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
WindowsPathDelimiter = '\';
|
|||
|
|
UnixPathDelimiter = '/';
|
|||
|
|
{$IFNDEF RTL140_UP}
|
|||
|
|
{$IFDEF MSWINDOWS}
|
|||
|
|
PathDelim = WindowsPathDelimiter;
|
|||
|
|
{$ENDIF MSWINDOWS}
|
|||
|
|
{$IFDEF UNIX}
|
|||
|
|
PathDelim = UnixPathDelimiter;
|
|||
|
|
{$ENDIF UNIX}
|
|||
|
|
{$ENDIF ~RTL140_UP}
|
|||
|
|
|
|||
|
|
//--------------------------------------------------------------------------------------------------
|
|||
|
|
// zlib format support
|
|||
|
|
//--------------------------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TJclZLibStream = class(TStream)
|
|||
|
|
protected
|
|||
|
|
FStream: TStream;
|
|||
|
|
FBufferSize: Integer;
|
|||
|
|
FBuffer: Pointer;
|
|||
|
|
FZLibStream: TZStreamRec;
|
|||
|
|
procedure SetSize(NewSize: Longint); override;
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream; const BufferSize: Integer);
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TJclZLibReader = class(TJclZLibStream)
|
|||
|
|
protected
|
|||
|
|
FEndOfStream: Boolean;
|
|||
|
|
procedure ReadNextBlock;
|
|||
|
|
procedure FinishZLibStream;
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream;
|
|||
|
|
const BufferSize: Integer = JclZLibStreamDefaultBufferSize;
|
|||
|
|
const WindowBits: Integer = DEF_WBITS);
|
|||
|
|
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
|
|||
|
|
function Read(var Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Write(const Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
|||
|
|
|
|||
|
|
procedure Reset;
|
|||
|
|
procedure SyncZLibStream;
|
|||
|
|
|
|||
|
|
property EndOfStream: Boolean read FEndOfStream;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TJclZLibWriter = class(TJclZLibStream)
|
|||
|
|
protected
|
|||
|
|
procedure WriteNextBlock;
|
|||
|
|
procedure FlushZLibStream(const Flush: Integer);
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream;
|
|||
|
|
const BufferSize: Integer = JclZLibStreamDefaultBufferSize;
|
|||
|
|
const Level: Integer = Z_DEFAULT_COMPRESSION;
|
|||
|
|
const Strategy: Integer = Z_DEFAULT_STRATEGY;
|
|||
|
|
const WindowBits: Integer = DEF_WBITS);
|
|||
|
|
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
|
|||
|
|
function Read(var Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Write(const Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
|||
|
|
|
|||
|
|
procedure Reset;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
EJclZLibError = class(EJclError);
|
|||
|
|
|
|||
|
|
// zlib error texts
|
|||
|
|
function GetZLibErrorText(const ErrorCode: Integer): PResStringRec;
|
|||
|
|
|
|||
|
|
function ZLibCompressMem(const Src: Pointer; SrcLen: Integer;
|
|||
|
|
out Dst: Pointer; out DstLen: Integer; out DstCapacity: Integer;
|
|||
|
|
const Level: Integer = Z_DEFAULT_COMPRESSION): Boolean;
|
|||
|
|
|
|||
|
|
// Flush:
|
|||
|
|
// Z_SYNC_FLUSH: DstCapacity can be 0
|
|||
|
|
// Z_FINISH: decompress with faster routine in a single step
|
|||
|
|
// DstCapacity must be >= uncompressed size
|
|||
|
|
function ZLibDecompressMem(const Src: Pointer; SrcLen: Integer;
|
|||
|
|
out Dst: Pointer; out DstLen: Integer; var DstCapacity: Integer;
|
|||
|
|
const Flush: Integer = Z_SYNC_FLUSH): Boolean;
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TJclGZipStream = class(TStream)
|
|||
|
|
protected
|
|||
|
|
FStream: TStream;
|
|||
|
|
FCRC32: LongWord;
|
|||
|
|
FUncompressedSize: LongWord;
|
|||
|
|
procedure SetSize(NewSize: Longint); override;
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream);
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TJclGZipReader = class(TJclGZipStream)
|
|||
|
|
private
|
|||
|
|
FZLibReader: TJclZLibReader;
|
|||
|
|
FTextMode: Boolean;
|
|||
|
|
FFilename: string;
|
|||
|
|
FComment: string;
|
|||
|
|
FTimeStamp: TJclUnixTime32;
|
|||
|
|
FLevel: Integer;
|
|||
|
|
FOperatingSystem: Byte;
|
|||
|
|
FMultipartNumber: Word;
|
|||
|
|
FExtraField: Pointer;
|
|||
|
|
FExtraFieldSize: Integer;
|
|||
|
|
FEndOfStream: Boolean;
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream;
|
|||
|
|
const BufferSize: Integer = JclZLibStreamDefaultBufferSize;
|
|||
|
|
const LineSeparator: string = JclZLibDefaultLineSeparator);
|
|||
|
|
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
|
|||
|
|
function Read(var Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Write(const Buffer; Count: Longint): Longint; override;
|
|||
|
|
|
|||
|
|
property TextMode: Boolean read FTextMode;
|
|||
|
|
property Filename: string read FFilename;
|
|||
|
|
property Comment: string read FComment;
|
|||
|
|
property TimeStamp: TJclUnixTime32 read FTimeStamp;
|
|||
|
|
property Level: Integer read FLevel;
|
|||
|
|
property OperatingSystem: Byte read FOperatingSystem;
|
|||
|
|
property MultipartNumber: Word read FMultipartNumber; // 0 = first part
|
|||
|
|
property ExtraField: Pointer read FExtraField;
|
|||
|
|
property ExtraFieldSize: Integer read FExtraFieldSize;
|
|||
|
|
|
|||
|
|
property EndOfStream: Boolean read FEndOfStream;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TJclGZipWriter = class(TJclGZipStream)
|
|||
|
|
private
|
|||
|
|
FTextMode: Boolean;
|
|||
|
|
FZLibWriter: TJclZLibWriter;
|
|||
|
|
public
|
|||
|
|
constructor Create(const Stream: TStream;
|
|||
|
|
const BufferSize: Integer = JclZLibStreamDefaultBufferSize;
|
|||
|
|
const Level: Integer = Z_DEFAULT_COMPRESSION;
|
|||
|
|
const Strategie: Integer = Z_DEFAULT_STRATEGY;
|
|||
|
|
const Filename: string = '';
|
|||
|
|
const TimeStamp: TJclUnixTime32 = 0;
|
|||
|
|
const Comment: string = '';
|
|||
|
|
const TextMode: Boolean = False;
|
|||
|
|
const ExtraField: Pointer = nil;
|
|||
|
|
const ExtraFieldSize: Integer = 0);
|
|||
|
|
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
|
|||
|
|
function Read(var Buffer; Count: Longint): Longint; override;
|
|||
|
|
function Write(const Buffer; Count: Longint): Longint; override;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
EJclGZipError = class(EJclError);
|
|||
|
|
|
|||
|
|
// gzip file extension
|
|||
|
|
const
|
|||
|
|
JclGZipDefaultFileExtension = '.gz';
|
|||
|
|
|
|||
|
|
// if DstFilename = '' -> DstFilename := SrcFilename + JclGZipDefaultFileExtension
|
|||
|
|
procedure GZipCompressFile(const SrcFilename: string; DstFilename: string;
|
|||
|
|
const Level: Integer = Z_DEFAULT_COMPRESSION);
|
|||
|
|
procedure GZipDecompressFile(const SrcFilename: string; DstFilename: string);
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
TarBlockSize = 512;
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TTarArchiveFormat = (
|
|||
|
|
tafDefaultFormat, // format to be decided later
|
|||
|
|
tafV7Format, // old V7 tar format
|
|||
|
|
tafOldGnuFormat, // GNU format as per before tar 1.12
|
|||
|
|
tafPosixFormat, // restricted, pure POSIX format
|
|||
|
|
tafGnuFormat); // POSIX format with GNU extensions
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
PSparse = ^TSparse;
|
|||
|
|
TSparse = packed record // offset
|
|||
|
|
Offset: array [0..11] of AnsiChar; // $00
|
|||
|
|
NumBytes: array [0..11] of AnsiChar; // $0C
|
|||
|
|
end; // $18
|
|||
|
|
|
|||
|
|
PTarHeader = ^TTarHeader;
|
|||
|
|
TTarHeader = packed record // offset
|
|||
|
|
case Integer of
|
|||
|
|
0: (Buffer: array [0..TarBlockSize - 1] of Byte);
|
|||
|
|
1: (
|
|||
|
|
// Old UNIX TAR format
|
|||
|
|
Name: array [0..99] of AnsiChar; // $000 Char + #0 / mit 0 gef<65>llt
|
|||
|
|
Mode: array [0..7] of AnsiChar; // $064 Octal + ' '#0 9 + 3 bits 20 34 30 37 35 35 20 00
|
|||
|
|
UID: array [0..7] of AnsiChar; // $06C Octal + ' '#0 ignore on DOS 20 20 31 37 35 36 20 00
|
|||
|
|
GID: array [0..7] of AnsiChar; // $074 Octal + ' '#0 ignore on DOS 20 20 20 31 34 34 20 00
|
|||
|
|
Size: array [0..11] of AnsiChar; // $07C Octal + ' ' size in bytes 20 20 20 20 20 20 20 20 20 20 30 20
|
|||
|
|
MTime: array [0..11] of AnsiChar; // $088 Octal + ' ' last modify Unix 20 36 37 32 32 34 34 36 31 30 37 20
|
|||
|
|
Chksum: array [0..7] of AnsiChar; // $094 Octal + ' '#0 >= 17 bit, init 0, add 20 20 37 35 37 32 00 20
|
|||
|
|
TypeFlag: AnsiChar; // $09C Octal + ' '#0 ?? 35
|
|||
|
|
Linkname: array [0..99] of AnsiChar; // $09D Char + #0
|
|||
|
|
// Extension of POSIX P1003.1
|
|||
|
|
Magic: array [0..5] of AnsiChar; // $101 Char + #0 75 73 74 61 72 20
|
|||
|
|
Version: array [0..1] of AnsiChar; // $107 Octal + ' ' 20 00
|
|||
|
|
UName: array [0..31] of AnsiChar; // $109 Char + #0 72 63 64 00 ...
|
|||
|
|
GName: array [0..31] of AnsiChar; // $129 Char + #0 75 73 65 72 73 00 ...
|
|||
|
|
DevMajor: array [0..7] of AnsiChar; // $149 Octal + ' '#0
|
|||
|
|
DevMinor: array [0..7] of AnsiChar; // $151 Octal + ' '#0
|
|||
|
|
case TTarArchiveFormat of
|
|||
|
|
tafV7Format: (
|
|||
|
|
FillV7: array [0..166] of AnsiChar); // $159
|
|||
|
|
tafPosixFormat: (
|
|||
|
|
Prefix: array [0..154] of AnsiChar; // $159 Prefix for name
|
|||
|
|
FillPosix: array [0..11] of AnsiChar); // $1F4
|
|||
|
|
tafOldGnuFormat: (
|
|||
|
|
ATime: array [0..11] of AnsiChar; // $159
|
|||
|
|
CTime: array [0..11] of AnsiChar; // $165
|
|||
|
|
Offset: array [0..11] of AnsiChar; // $171
|
|||
|
|
Longnames: array [0..3] of AnsiChar; // $17D
|
|||
|
|
Pad: AnsiChar; // $181
|
|||
|
|
Sparses: array [0..3] of TSparse; // $182
|
|||
|
|
IsExtended: AnsiChar; // $1E2
|
|||
|
|
RealSize: array [0..11] of AnsiChar; // $1E3
|
|||
|
|
FillGnu: array [0..16] of AnsiChar)); // $1EF
|
|||
|
|
end; // $200
|
|||
|
|
|
|||
|
|
// ModeFlag Flags
|
|||
|
|
type
|
|||
|
|
TTarMode = (
|
|||
|
|
tmOtherExec, // execute/search by other
|
|||
|
|
tmOtherWrite, // write by other
|
|||
|
|
tmOtherRead, // read by other
|
|||
|
|
tmGroupExec, // execute/search by group
|
|||
|
|
tmGroupWrite, // write by group
|
|||
|
|
tmGroupRead, // read by group
|
|||
|
|
tmOwnerExec, // execute/search by owner
|
|||
|
|
tmOwnerWrite, // write by owner
|
|||
|
|
tmOwnerRead, // read by owner
|
|||
|
|
tmSaveText, // reserved
|
|||
|
|
tmSetGID, // set GID on execution
|
|||
|
|
tmSetUID); // set UID on execution
|
|||
|
|
TTarModes = set of TTarMode;
|
|||
|
|
|
|||
|
|
// TypeFlag
|
|||
|
|
type
|
|||
|
|
TTarTypeFlag = AnsiChar;
|
|||
|
|
|
|||
|
|
const // V7 Posix
|
|||
|
|
ttfRegFile = '0'; // regular file x x
|
|||
|
|
ttfARegFile = #0; // regular file x x
|
|||
|
|
ttfLink = '1'; // link x x
|
|||
|
|
ttfSymbolicLink = '2'; // symbolic link x
|
|||
|
|
ttfCharacter = '3'; // character special x
|
|||
|
|
ttfBlock = '4'; // block special x
|
|||
|
|
ttfDirectory = '5'; // directory x
|
|||
|
|
ttfFIFO = '6'; // FIFO special x
|
|||
|
|
ttfContiguous = '7'; // contiguous file
|
|||
|
|
|
|||
|
|
// GNU extensions
|
|||
|
|
ttfGnuDumpDir = 'D';
|
|||
|
|
ttfGnuLongLink = 'K'; // next file have a long link name
|
|||
|
|
ttfGnuLongName = 'L'; // next file have a long name
|
|||
|
|
ttfGnuMultiVol = 'M'; // file began on another volume
|
|||
|
|
ttfGnuNames = 'N'; // long filename
|
|||
|
|
ttfGnuSparse = 'S'; // sparse files
|
|||
|
|
ttfGnuVolHeader = 'V'; // Volume label (must be the first file)
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
TarOldGnuMagic = 'ustar '#0; // old GNU Magic + Version
|
|||
|
|
TarPosixMagic = 'ustar'#0; // Posix or GNU
|
|||
|
|
TarGnuVersion = '00';
|
|||
|
|
|
|||
|
|
// other version for GNU-Magic: 'GNUtar '#0
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TJclTarFileType = (tftUnknown, tftEof, tftFile, tftDirectory);
|
|||
|
|
|
|||
|
|
TJclTarFileSize = Int64;
|
|||
|
|
|
|||
|
|
|
|||
|
|
TJclTarReader = class(TObject)
|
|||
|
|
private
|
|||
|
|
function GetFileDateTime: TDateTime;
|
|||
|
|
protected
|
|||
|
|
FTarStream: TStream;
|
|||
|
|
FHeader: TTarHeader;
|
|||
|
|
FArchiveFormat: TTarArchiveFormat;
|
|||
|
|
FFileType: TJclTarFileType;
|
|||
|
|
FFilename: string;
|
|||
|
|
FFileSize: TJclTarFileSize;
|
|||
|
|
FFileTime: TJclUnixTime32;
|
|||
|
|
function ReadHeader: Boolean; // False if Eof
|
|||
|
|
procedure ScanHeader;
|
|||
|
|
public
|
|||
|
|
constructor Create(const TarStream: TStream);
|
|||
|
|
procedure CopyToStream(const FileStream: TStream; CanSeek: Boolean = False);
|
|||
|
|
procedure CopyToFile(const FilePath: string);
|
|||
|
|
procedure SkipFile;
|
|||
|
|
procedure SkipFileSeek;
|
|||
|
|
property FileType: TJclTarFileType read FFileType;
|
|||
|
|
property Filename: string read FFilename;
|
|||
|
|
property FileSize: TJclTarFileSize read FFileSize;
|
|||
|
|
property FileTime: TJclUnixTime32 read FFileTime;
|
|||
|
|
property FileDateTime: TDateTime read GetFileDateTime;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
TJclTarWriter = class(TObject)
|
|||
|
|
protected
|
|||
|
|
FTarStream: TStream;
|
|||
|
|
procedure AddEof;
|
|||
|
|
public
|
|||
|
|
constructor Create(const TarStream: TStream);
|
|||
|
|
destructor Destroy; override;
|
|||
|
|
procedure AddFile(FileRoot, Filename: string);
|
|||
|
|
procedure AddStream(const Stream: TStream; Filename: string;
|
|||
|
|
FileSize: TJclTarFileSize; FileTime: TJclUnixTime32);
|
|||
|
|
procedure AddDirectory(DirName: string);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
EJclTarError = class(EJclError);
|
|||
|
|
|
|||
|
|
procedure TarAllFiles(const TarFilename, FileRoot: string);
|
|||
|
|
procedure TarFileList(const TarFilename, FileRoot: string; List: TStrings);
|
|||
|
|
procedure TarFileArray(const TarFilename, FileRoot: string; const Filenames: array of string);
|
|||
|
|
procedure TarGZipAllFiles(const TgzFilename, FileRoot: string);
|
|||
|
|
procedure TarGZipFileList(const TgzFilename, FileRoot: string; List: TStrings);
|
|||
|
|
procedure TarGZipFileArray(const TgzFilename, FileRoot: string; const Filenames: array of string);
|
|||
|
|
|
|||
|
|
procedure UnTarAllFiles(const TarFilename: string; DstDir: string);
|
|||
|
|
procedure UnGZipTarAllFiles(const TgzFilename: string; DstDir: string);
|
|||
|
|
|
|||
|
|
procedure GetFileList(RootDir: string; List: TStrings);
|
|||
|
|
|