Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
262 lines (236 sloc) 7.38 KB
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Project : FWZip
// * Unit Name : FWZipStream
// * Purpose : Âñïîìîãàòåëüíûå ñòðèìû äëÿ ïîääåðæêè øèôðîâàíèÿ íà ëåòó,
// * : è óñå÷åííîãî çàãîëîâêà ZLib
// * Author : Àëåêñàíäð (Rouse_) Áàãåëü
// * Copyright : © Fangorn Wizards Lab 1998 - 2015.
// * Version : 1.0.11
// * 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/
//
//
// Îïèñàíèå èäåè ìîäóëÿ:
// Ïðè ïîìåùåíèè â àðõèâ ñæàòîãî áëîêà äàííûõ ìåòîäîì Deflate ó íåãî
// îòðåçàåòñÿ äâóõáàéòíûé çàãîëîâîê â êîòîðîì óêàçàíû ïàðàìåòðû ñæàòèÿ.
// Ò.å. â àðõèâ ïîìåùàþòñÿ ñàìè äàííûå â ÷èñòîì âèäå.
// Äëÿ ðàñïàêîâêè íåîáõîäèìî äàííûé çàãîëîâîê âîññòàíîâèòü.
// Äàííûé êëàññ ïîçâîëÿåò äîáàâèòü äàííûé çàãîëîâîê "íà ëåòó"
// àáñîëþòíî ïðîçðà÷íî äëÿ âíåøíåãî êîäà.
// Ñàì çàãîëîâîê ãåíåðèðóåòñÿ â êîíñòðóêòîðå è ïîäñòàâëÿåòñÿ â ìåòîäå Read.
// Òàê-æå êëàññ, âûñòóïàÿ ïîñðåäíèêîì ìåæäó äâóìÿ ñòðèìàìè,
// ïîçâîëÿåò ïðîèçâîäèòü øèôðîâàíèå è äåøèôðîâêó ïåðåäàâàåìûõ äàííûõ.
// Øèôðîâàíèå ïðîèçâîäèòñÿ â ìåòîäå Write, â ýòîò ìîìåíò êëàññ ÿâëÿåòñÿ
// ïîñðåäíèêîì ìåæäó TCompressionStream è ðåçóëüòèðóþùèì ñòðèìîì.
// Äåøèôðîâàíèå îñóùåñòâëÿåòñÿ â ìåòîäå Read, â ýòîò ìîìåíò êëàññ ÿâëÿåòñÿ
// ïîñðåäíèêîì ìåæäó ñòðèìîì ñî ñæàòûìè è
// ïîøèôðîâàííûìè äàííûìè è TDecompressionStream.
//
unit FWZipStream;
interface
{$I fwzip.inc}
uses
Classes,
FWZipConsts,
FWZipCrypt,
FWZipCrc32,
FWZipZLib;
type
TFWZipItemStream = class(TStream)
private
FOwner: TStream;
FCryptor: TFWZipCryptor;
FDecryptor: TFWZipDecryptor;
FSize, FStart, FPosition: Int64;
{$IFDEF USE_AUTOGENERATED_ZLIB_HEADER}
FHeader: Word;
{$ENDIF}
protected
function GetSize: Int64; override;
public
constructor Create(AOwner: TStream; Cryptor: TFWZipCryptor;
Decryptor: TFWZipDecryptor; CompressLevel: Byte; ASize: Int64);
function Seek(Offset: Longint; Origin: Word): Longint; overload; override;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
end;
implementation
{ TFWZipItemStream }
constructor TFWZipItemStream.Create(AOwner: TStream; Cryptor: TFWZipCryptor;
Decryptor: TFWZipDecryptor; CompressLevel: Byte; ASize: Int64);
begin
inherited Create;
FOwner := AOwner;
FCryptor := Cryptor;
FDecryptor := Decryptor;
FSize := ASize;
FStart := AOwner.Position;
FPosition := 0;
// Rouse_ 30.10.2013
// Óñòàðåâøèé êîä
{$IFDEF USE_AUTOGENERATED_ZLIB_HEADER}
// Rouse_ 17.03.2011
// Ðàçìåð÷èê âñå-æå íóæíî ïðàâèòü óâåëè÷èêàÿ íà ðàçìåð çàãîëîâêà
Inc(FSize, 2);
// Âîññòàíàâëèâàåì ïðîïóùåííûé çàãîëîâîê ZLib ñòðèìà
// ñì. deflate.c - int ZEXPORT deflate (strm, flush)
// uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
FHeader := (Z_DEFLATED + (7 {32k Window size} shl 4)) shl 8;
// if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
// level_flags = 0;
// else if (s->level < 6)
// level_flags = 1;
// else if (s->level == 6)
// level_flags = 2;
// else
// level_flags = 3;
//
// ñàì CompressLevel (level_flags)
// áåðåòñÿ èç óæå çàïîëíåííîãî GeneralPurposeBitFlag
// çäåñü ìû èç áèòîâîé ìàñêè âîññòàíàâëèâàåì îðèãèíàëüíûå çíà÷åíèÿ
case CompressLevel of
PBF_COMPRESS_SUPERFAST:
CompressLevel := 0;
PBF_COMPRESS_FAST:
CompressLevel := 1;
PBF_COMPRESS_NORMAL:
CompressLevel := 2;
PBF_COMPRESS_MAXIMUM:
CompressLevel := 3;
end;
// header |= (level_flags << 6);
FHeader := FHeader or (CompressLevel shl 6);
// if (s->strstart != 0) header |= PRESET_DICT;
// ñëîâàðü íå èñïîëüçóåòñÿ - îñòàâëÿåì áåç èçìåíåíèé
// header += 31 - (header % 31);
Inc(FHeader, 31 - (FHeader mod 31));
// putShortMSB(s, header);
FHeader := (FHeader shr 8) + (FHeader and $FF) shl 8;
{$ENDIF}
end;
function TFWZipItemStream.GetSize: Int64;
begin
Result := FSize;
end;
function TFWZipItemStream.Read(var Buffer; Count: Integer): Longint;
var
P: PByte;
DecryptBuff: Pointer;
begin
// Rouse_ 30.10.2013
// Óñòàðåâøèé êîä
{$IFDEF USE_AUTOGENERATED_ZLIB_HEADER}
if FPosition = 0 then
begin
// åñëè çà÷èòûâàþòñÿ äàííûå ñ ñàìîãî íà÷àëà
// íåîáõîäèìî ïåðåä íèìè ðàçìåñòèòü çàãîëîâîê ZLib
P := @FHeader;
Move(P^, Buffer, 2);
FOwner.Position := FStart;
P := @Buffer;
Inc(P, 2);
if Count > Size then
Count := Size;
FOwner.Position := FStart;
if FDecryptor <> nil then
begin
// â ñëó÷àå åñëè ôàéë çàøèôðîâàí, ïðîèçâîäèì ðàñøèôðîâêó áëîêà
GetMem(DecryptBuff, Count - 2);
try
Result := FOwner.Read(DecryptBuff^, Count - 2);
FDecryptor.DecryptBuffer(DecryptBuff, Result);
Move(DecryptBuff^, P^, Result);
finally
FreeMem(DecryptBuff);
end;
end
else
Result := FOwner.Read(P^, Count - 2);
Inc(Result, 2);
Inc(FPosition, Result);
end
else
begin
FOwner.Position := FStart + Position - 2;
{$ELSE}
begin
FOwner.Position := FStart + Position;
{$ENDIF}
if Count > Size - Position then
Count := Size - Position;
if FDecryptor <> nil then
begin
// â ñëó÷àå åñëè ôàéë çàøèôðîâàí, ïðîèçâîäèì ðàñøèôðîâêó áëîêà
GetMem(DecryptBuff, Count);
try
Result := FOwner.Read(DecryptBuff^, Count);
FDecryptor.DecryptBuffer(DecryptBuff, Result);
P := @Buffer;
Move(DecryptBuff^, P^, Result);
finally
FreeMem(DecryptBuff);
end;
end
else
Result := FOwner.Read(Buffer, Count);
Inc(FPosition, Result);
end;
end;
function TFWZipItemStream.Seek(Offset: Integer; Origin: Word): Longint;
begin
Result := Seek(Int64(Offset), TSeekOrigin(Origin));
end;
function TFWZipItemStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
case Origin of
soBeginning: FPosition := Offset;
soCurrent: Inc(FPosition, Offset);
soEnd: FPosition := Size + Offset;
end;
Result := FPosition;
end;
function TFWZipItemStream.Write(const Buffer; Count: Integer): Longint;
var
EncryptBuffer: PByte;
begin
if FCryptor = nil then
Result := FOwner.Write(Buffer, Count)
else
begin
// êðèïòóåì áóôåð
GetMem(EncryptBuffer, Count);
try
Move(Buffer, EncryptBuffer^, Count);
// Rouse_ 31.10.2013
// Óñòàðåâøèé êîä
{$IFDEF USE_AUTOGENERATED_ZLIB_HEADER}
// Øèôðîâàòü áëîê íóæíî ïðîïóñòèâ äâóáàéòíûé çàãîëîâîê ZLib
if FPosition = 0 then
begin
Inc(EncryptBuffer, 2);
FCryptor.EncryptBuffer(EncryptBuffer, Count - 2);
Dec(EncryptBuffer, 2);
end
else
{$ENDIF}
FCryptor.EncryptBuffer(EncryptBuffer, Count);
Result := FOwner.Write(EncryptBuffer^, Count);
finally
FreeMem(EncryptBuffer);
end;
end;
Inc(FPosition, Result);
end;
end.