⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sui2skinreader.pas

📁 SUIPack是一款为Delphi和C++Builder开发的所见即所得的界面增强VCL组件
💻 PAS
📖 第 1 页 / 共 4 页
字号:
                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 + -