📄 sui2skinreader.pas
字号:
ZipStream.Read(DirHeader.InternalFileAttributes, sizeof(DirHeader.InternalFileAttributes));
ZipStream.Read(DirHeader.ExternalFileAttributes, sizeof(DirHeader.ExternalFileAttributes));
ZipStream.Read(DirHeader.RelativeOffset, sizeof(DirHeader.RelativeOffset));
ZipStream.Read(InternalFile, DirHeader.FileNameLength);
InternalFile[DirHeader.FileNameLength] := #0;
if UpperCase(StrPas(InternalFile)) = UpperCase(ExtractFile) then
begin
Found := true;
break;
end;
end;
if not Found then
Exit; // can't find the extract file
OutStream := TFileStream.Create(OutputFile, fmCreate or fmShareDenyWrite);
ZipStream.Seek(DirHeader.RelativeOffset, soFromBeginning);
ZipStream.Read(LocalHeader.Signature, sizeof(LocalHeader.Signature));
ZipStream.Read(LocalHeader.VersionNeededToExtract, sizeof(LocalHeader.VersionNeededToExtract));
ZipStream.Read(LocalHeader.GeneralPurposeBitFlag, sizeof(LocalHeader.GeneralPurposeBitFlag));
ZipStream.Read(LocalHeader.CompressionMethod, sizeof(LocalHeader.CompressionMethod));
ZipStream.Read(LocalHeader.LastModFileTime, sizeof(LocalHeader.LastModFileTime));
ZipStream.Read(LocalHeader.LastModFileDate, sizeof(LocalHeader.LastModFileDate));
ZipStream.Read(LocalHeader.CRC32, sizeof(LocalHeader.CRC32));
ZipStream.Read(LocalHeader.CompressedSize, sizeof(LocalHeader.CompressedSize));
ZipStream.Read(LocalHeader.UncompressedSize, sizeof(LocalHeader.UncompressedSize));
ZipStream.Read(LocalHeader.FileNameLength, sizeof(LocalHeader.FileNameLength));
ZipStream.Read(LocalHeader.ExtraFieldLength, sizeof(LocalHeader.ExtraFieldLength));
ZipStream.Seek(LocalHeader.FileNameLength, soFromCurrent);
if LocalHeader.ExtraFieldLength > 0 then
ZipStream.Seek(LocalHeader.ExtraFieldLength, soFromCurrent);
if DirHeader.GeneralPurposeBitFlag and $0001 <> 0 then
begin
if Password = '' then
begin
Result := suiURWrongPassword;
Exit;
end;
M1 := 305419896;
M2 := 591751049;
M3 := 878082192;
M := 134775813;
ZipStream.ReadBuffer(H, sizeof(H));
for i := 1 to Length(Password) do
begin
M1 := DWORD(CRC32Table[BYTE(M1 xor Integer(Password[i]))] xor ((M1 shr 8) and DWORD($00FFFFFF)));
M2 := M2 + (M1 and $FF);
M2 := M2 * M + 1;
M3 := DWORD(CRC32Table[BYTE(M3 xor Integer(M2 shr 24))] xor ((M3 shr 8) and DWORD($00FFFFFF)));
end;
for i := 0 to 11 do
begin
BlockType := (M3 and $FFFF) or 2;
EncryptedHead[i] := H[i] xor ((BlockType * (BlockType xor 1)) shr 8);
M1 := DWORD(CRC32Table[BYTE(M1 xor Integer(EncryptedHead[i]))] xor ((M1 shr 8) and DWORD($00FFFFFF)));
M2 := M2 + (M1 and $FF);
M2 := M2 * M + 1;
M3 := DWORD(CRC32Table[BYTE(M3 xor Integer(M2 shr 24))] xor ((M3 shr 8) and DWORD($00FFFFFF)));
end;
if (DirHeader.GeneralPurposeBitFlag and $0008) = $0008 then
C := DirHeader.LastModFileTime shl $10
else
C := DirHeader.CRC32;
if TLongAsBytes(C).L4 <> EncryptedHead[11] then
begin
Result := suiURWrongPassword;
Exit;
end;
DecrypedStream := TMemoryStream.Create();
FillChar(Buf, 1024, #0);
BytesToGo := ZipStream.Read(Buf[0], 1024);
while BytesToGo = 1024 do
begin
DecodeBuffer(Buf[0], 1024, M1, M2, M3, M);
DecrypedStream.WriteBuffer(Buf[0], 1024);
BytesToGo := ZipStream.Read(Buf[0], 1024);
end;
DecodeBuffer(Buf[0], BytesToGo, M1, M2, M3, M);
DecrypedStream.Write(Buf[0], BytesToGo);
DecrypedStream.Position := 0;
InStream := DecrypedStream;
end
else
InStream := ZipStream;
GetMem(InBuf, 1024 * 16);
GetMem(OutBuf, 1024 * 64 + 258);
OutCurrent := OutBuf;
OutWritePoint := OutBuf + 64 * 1024;
InBufPos := nil;
InBufEnd := nil;
InBitsLeft := 0;
InBitBuf := 0;
repeat
if InBitsLeft = 0 then
begin
if (InBufEnd - InBufPos) < sizeof(Integer) then
FillBuffer(InStream, InBuf, InBufPos, InBufEnd);
InBitBuf := PInteger(InBufPos)^;
Inc(InBufPos, sizeof(Integer));
InBitsLeft := 32;
end;
LastBit := Odd(InBitBuf);
InBitBuf := InBitBuf shr 1;
Dec(InBitsLeft);
BlockType := ReadBits(2, InBitsLeft, InBitBuf, InBufPos);
if BlockType = 0 then
begin
InBitBuf := InBitBuf shr (InBitsLeft mod 8);
Dec(InBitsLeft, InBitsLeft mod 8);
ReadBuffer(InStream, LenNotLen, sizeof(LenNotLen), InBitsLeft, InBitBuf, InBufPos, InBufEnd, InBuf);
BytesToGo := LenNotLen.Len;
GetMem(Buffer, 16384);
while BytesToGo <> 0 do
begin
if BytesToGo > 16384 then
BytesToWrite := 16384
else
BytesToWrite := BytesToGo;
ReadBuffer(InStream, Buffer^, BytesToWrite, InBitsLeft, InBitBuf, InBufPos, InBufEnd, InBuf);
Count := BytesToWrite;
if OutCurrent >= OutWritePoint then
begin
OutStream.WriteBuffer(OutBuf^, 32768);
FromPtr := OutBuf + 32768;
Move(FromPtr^, OutBuf^, OutCurrent - FromPtr);
OutCurrent := OutCurrent - 32768;
end;
Buffer2 := Buffer;
BytesToWrite2 := OutWritePoint - OutCurrent;
if BytesToWrite2 > Count then
BytesToWrite2 := Count;
Move(Buffer2^, OutCurrent^, BytesToWrite2);
Inc(OutCurrent, BytesToWrite2);
Dec(Count, BytesToWrite2);
while Count > 0 do
begin
Inc(Buffer2, BytesToWrite2);
OutStream.WriteBuffer(OutBuf^, 32768);
FromPtr := OutBuf + 32768;
Move(FromPtr^, OutBuf^, OutCurrent - FromPtr);
OutCurrent := OutCurrent - 32768;
BytesToWrite2 := OutWritePoint - OutCurrent;
if BytesToWrite2 > Count then
BytesToWrite2 := Count;
Move(Buffer2^, OutCurrent^, BytesToWrite2);
Inc(OutCurrent, BytesToWrite2);
Dec(Count, BytesToWrite2);
end;
Dec(BytesToGo, BytesToWrite);
end;
FreeMem(Buffer);
end
else if BlockType = 2 then
begin
LitCount := ReadBits(5, InBitsLeft, InBitBuf, InBufPos) + 257;
DistCount := ReadBits(5, InBitsLeft, InBitBuf, InBufPos) + 1;
CodeLenCount := ReadBits(4, InBitsLeft, InBitBuf, InBufPos) + 4;
if (LitCount > 286) or (DistCount > 30) then
Exit;
FillChar(CodeLens, 19 * sizeof(Integer), 0);
for i := 0 to CodeLenCount - 1 do
CodeLens[CodeLengthIndex[i]] := ReadBits(3, InBitsLeft, InBitBuf, InBufPos);
CodeLenTree := THuffmanTree.Create(7);
CodeLenTree.Build(CodeLens, 0, 19, [0], $FFFF);
FillChar(CodeLens, sizeof(CodeLens), 0);
SymbolCount := 0;
while SymbolCount < LitCount + DistCount do
begin
BitCount := CodeLenTree.MaxCodeLen + 7;
BitBuffer := PeekBits(InStream, BitCount, InBitsLeft, InBitBuf, InBufPos, InBufEnd, InBuf);
LookupValue := BitBuffer and ExtractMaskArray[CodeLenTree.MaxCodeLen];
EncodedSymbol := CodeLenTree.Decode(LookupValue);
Symbol := EncodedSymbol and $FFFF;
SymbolCodeLen := (EncodedSymbol shr 16) and $FF;
if Symbol <= 15 then
begin
CodeLens[SymbolCount] := Symbol;
Inc(SymbolCount);
DiscardBits(SymbolCodeLen, InBitsLeft, InBitBuf, InBufPos);
end
else if Symbol = 16 then
begin
RepeatCount := 3 + ((BitBuffer shr SymbolCodeLen) and $3);
Symbol := CodeLens[SymbolCount - 1];
for i := 0 to RepeatCount - 1 do
CodeLens[SymbolCount+i] := Symbol;
Inc(SymbolCount, RepeatCount);
BitCount := SymbolCodeLen + 2;
DiscardBits(BitCount, InBitsLeft, InBitBuf, InBufPos);
end
else if Symbol = 17 then
begin
RepeatCount := 3 + ((BitBuffer shr SymbolCodeLen) and $7);
Inc(SymbolCount, RepeatCount);
BitCount := SymbolCodeLen + 3;
DiscardBits(BitCount, InBitsLeft, InBitBuf, InBufPos);
end
else if Symbol = 18 then
begin
RepeatCount := 11 + ((BitBuffer shr SymbolCodeLen) and $7F);
Inc(SymbolCount, RepeatCount);
BitCount := SymbolCodeLen + 7;
DiscardBits(BitCount, InBitsLeft, InBitBuf, InBufPos);
end;
end;
LiteralTree := THuffmanTree.Create(15);
LiteralTree.Build(CodeLens, 0, LitCount, LitExtraBits, 257);
DistanceTree := THuffmanTree.Create(15);
DistanceTree.Build(CodeLens, LitCount, DistCount, DistExtraBits, 0);
Decode(
LiteralTree, DistanceTree, InStream, OutStream, BitCount,
InBitsLeft, InBitBuf, BitBuffer, LookupValue, EncodedSymbol,
Symbol, SymbolCodeLen, Len, ExtraBitCount, Distance, InBufPos,
InBufEnd, InBuf, OutCurrent, OutWritePoint, OutBuf, FromPtr,
FromChar, ToChar
);
CodeLenTree.Free();
LiteralTree.Free();
DistanceTree.Free();
end // block type = 2
else if BlockType = 1 then
begin
Decode(
StaticLiteralTree, StaticDistanceTree, InStream, OutStream, BitCount,
InBitsLeft, InBitBuf, BitBuffer, LookupValue, EncodedSymbol,
Symbol, SymbolCodeLen, Len, ExtraBitCount, Distance, InBufPos,
InBufEnd, InBuf, OutCurrent, OutWritePoint, OutBuf, FromPtr,
FromChar, ToChar
);
end;
until LastBit;
if OutBuf <> OutCurrent then
OutStream.WriteBuffer(OutBuf^, OutCurrent - OutBuf);
Result := suiURSucc;
except
Result := suiURFailed;
end;
finally
if DecrypedStream <> nil then
DecrypedStream.Free();
if OutStream <> nil then
begin
if (OutStream.Size = 0) and (Result = suiURSucc) then
Result := suiURFailed
else if OutStream.Size <> DirHeader.UncompressedSize then
Result := suiURWrongPassword;
OutStream.Free();
end;
if ZipStream <> nil then
ZipStream.Free();
if Assigned(InBuf) then
FreeMem(InBuf);
if Assigned(OutBuf) then
FreeMem(OutBuf);
if (Result <> suiURSucc) and FileExists(OutputFile) then
DeleteFile(OutputFile);
end;
end;
{ THuffmanTree }
procedure THuffmanTree.Build(const CodeLengths: array of Integer; StartInx,
Count: Integer; const ExtraBits: array of BYTE; ExtraOffset: Integer);
const
ByteRevTable : array [0..255] of BYTE = (
$00, $80, $40, $C0, $20, $A0, $60, $E0, $10, $90, $50, $D0,
$30, $B0, $70, $F0, $08, $88, $48, $C8, $28, $A8, $68, $E8,
$18, $98, $58, $D8, $38, $B8, $78, $F8, $04, $84, $44, $C4,
$24, $A4, $64, $E4, $14, $94, $54, $D4, $34, $B4, $74, $F4,
$0C, $8C, $4C, $CC, $2C, $AC, $6C, $EC, $1C, $9C, $5C, $DC,
$3C, $BC, $7C, $FC, $02, $82, $42, $C2, $22, $A2, $62, $E2,
$12, $92, $52, $D2, $32, $B2, $72, $F2, $0A, $8A, $4A, $CA,
$2A, $AA, $6A, $EA, $1A, $9A, $5A, $DA, $3A, $BA, $7A, $FA,
$06, $86, $46, $C6, $26, $A6, $66, $E6, $16, $96, $56, $D6,
$36, $B6, $76, $F6, $0E, $8E, $4E, $CE, $2E, $AE, $6E, $EE,
$1E, $9E, $5E, $DE, $3E, $BE, $7E, $FE, $01, $81, $41, $C1,
$21, $A1, $61, $E1, $11, $91, $51, $D1, $31, $B1, $71, $F1,
$09, $89, $49, $C9, $29, $A9, $69, $E9, $19, $99, $59, $D9,
$39, $B9, $79, $F9, $05, $85, $45, $C5, $25, $A5, $65, $E5,
$15, $95, $55, $D5, $35, $B5, $75, $F5, $0D, $8D, $4D, $CD,
$2D, $AD, $6D, $ED, $1D, $9D, $5D, $DD, $3D, $BD, $7D, $FD,
$03, $83, $43, $C3, $23, $A3, $63, $E3, $13, $93, $53, $D3,
$33, $B3, $73, $F3, $0B, $8B, $4B, $CB, $2B, $AB, $6B, $EB,
$1B, $9B, $5B, $DB, $3B, $BB, $7B, $FB, $07, $87, $47, $C7,
$27, $A7, $67, $E7, $17, $97, $57, $D7, $37, $B7, $77, $F7,
$0F, $8F, $4F, $CF, $2F, $AF, $6F, $EF, $1F, $9F, $5F, $DF,
$3F, $BF, $7F, $FF
);
var
i : Integer;
Symbol : Integer;
LengthCount : array [0..15] of Integer;
NextCode : array [0..15] of Integer;
Code : Integer;
CodeLen : Integer;
CodeData : Integer;
DecoderLen : Integer;
CodeIncr : Integer;
Decodes : PTIntegerList;
DecodesEnd : Pointer;
TablePtr : Pointer;
begin
FillChar(LengthCount, sizeof(LengthCount), 0);
m_MaxCodeLen := 0;
for i := 0 to Count - 1 do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -