unit PrecompSearch; interface uses InitCode, Utils, SynCommons, SynCrypto, PrecompUtils, WinAPI.Windows, System.SysUtils, System.Classes, System.StrUtils, System.Types, System.Math, System.IOUtils; const XTOOL_DB = $31445458; var Codec: TPrecompressor; implementation const MinSize = 65536; type PEntryStruct = ^TEntryStruct; TEntryStruct = packed record Position: Int64; OldSize, NewSize, DepthSize: Integer; end; PSearchStruct = ^TSearchStruct; PHashStruct = ^THashStruct; THashStruct = record Size: Integer; Hash: Cardinal; end; TSearchStruct = record Name: String; SearchInt1, SearchInt2: Integer; Hash: Cardinal; HashList: TArray; Codec: String; Resource: Integer; EntryList: TArray; end; var SearchList: TStringDynArray; SearchInfo: TArray>>; SearchCount: TArray>; CodecSearch: TArray>; CodecAvailable, CodecEnabled: TArray; function CheckHashList(Instance: Integer; Position, SizeEx: NativeInt; HashList: TArray; Funcs: PPrecompFuncs): Boolean; const BufferSize = 65536; var Buffer: array [0 .. BufferSize - 1] of Byte; LPos: NativeInt; I: Integer; X, Y: Integer; CRC: Cardinal; begin Result := False; LPos := Position; for I := Low(HashList) to High(HashList) do begin X := HashList[I].Size; CRC := 0; Y := Funcs^.ReadFuture(Instance, LPos, @Buffer[0], Min(X, BufferSize)); while Y > 0 do begin Inc(LPos, Y); CRC := Utils.CRC32(CRC, @Buffer[0], Y); Dec(X, Y); Y := Funcs^.ReadFuture(Instance, LPos, @Buffer[0], Min(X, BufferSize)); end; if (X > 0) or (CRC <> HashList[I].Hash) then break; if (I = High(HashList)) or ((FULLSCAN = False) and (LPos > SizeEx)) then exit(True) end; end; function SearchInit(Command: PChar; Count: Integer; Funcs: PPrecompFuncs): Boolean; var I: Integer; W, X, Y, Z: Integer; S: String; List: System.Types.TStringDynArray; begin Result := True; for X := Low(CodecAvailable) to High(CodecAvailable) do begin CodecAvailable[X] := True; CodecEnabled[X] := False; end; for X := Low(CodecSearch) to High(CodecSearch) do for Y := Low(CodecSearch[X]) to High(CodecSearch[X]) do CodecSearch[X, Y].Resource := RegisterResources(CodecSearch[X, Y].Codec); X := 0; while Funcs^.GetCodec(Command, X, False) <> '' do begin S := Funcs^.GetCodec(Command, X, False); for Y := Low(Codec.Names) to High(Codec.Names) do if CompareText(S, Codec.Names[Y]) = 0 then begin CodecEnabled[Y] := True; break; end; Inc(X); end; I := 0; for X := Low(CodecEnabled) to High(CodecEnabled) do if CodecEnabled[X] then begin for Y := Low(CodecSearch[X]) to High(CodecSearch[X]) do begin List := DecodeStr(CodecSearch[X, Y].Codec, SPrecompSep4); for W := Low(List) to High(List) do AddMethod(PrecompGetCodec(PChar(List[W]), 0, False)); end; SetLength(SearchInfo[X], $10000); SetLength(SearchCount[X], $10000); for Z := Low(SearchInfo[X]) to High(SearchInfo[X]) do begin SearchCount[X, Z] := 0; for Y := Low(CodecSearch[X]) to High(CodecSearch[X]) do begin LongRec(I).Words[0] := LongRec(CodecSearch[X, Y].SearchInt1).Words[0]; if Z = I then begin Inc(SearchCount[X, Z]); Insert(Y, SearchInfo[X, Z], Length(SearchInfo[X, Z])); end; end; end; end; end; procedure SearchFree(Funcs: PPrecompFuncs); var X, Y, Z: Integer; begin for X := Low(CodecEnabled) to High(CodecEnabled) do if CodecEnabled[X] then begin for Y := Low(SearchInfo[X]) to High(SearchInfo[X]) do SetLength(SearchInfo[X, Y], 0); SetLength(SearchInfo[X], 0); SetLength(SearchCount[X], 0); end; end; function SearchParse(Command: PChar; Option: PInteger; Funcs: PPrecompFuncs): Boolean; begin Result := False; end; procedure SearchScan1(Instance, Depth: Integer; Input: PByte; Size, SizeEx: NativeInt; Output: _PrecompOutput; Add: _PrecompAdd; Funcs: PPrecompFuncs); var I: Integer; J: Word; X, Y: Integer; Pos, LSize: NativeInt; SI: _StrInfo1; DS: TPrecompStr; SS: PSearchStruct; CRC: Cardinal; Checked: Boolean; begin if Depth > 0 then exit; for I := Low(CodecSearch) to High(CodecSearch) do if CodecEnabled[I] then begin Pos := 0; LSize := Size - Pred(Integer.Size); while Pos < LSize do begin J := PWord(Input + Pos)^; if (SearchCount[I, J] > 0) and (MinSize <= (SizeEx - Pos)) then begin Checked := False; for X := 0 to SearchCount[I, J] - 1 do begin if (PInteger(Input + Pos)^ = CodecSearch[I, SearchInfo[I, J, X]] .SearchInt1) and (PInteger(Input + Pos + MinSize - Integer.Size) ^ = CodecSearch[I, SearchInfo[I, J, X]].SearchInt2) then begin if not Checked then begin CRC := Utils.CRC32(0, Input + Pos, MinSize); Checked := True; end; if (CodecSearch[I, SearchInfo[I, J, X]].Hash = CRC) and CheckHashList(Instance, Pos, SizeEx, CodecSearch[I, SearchInfo[I, J, X]].HashList, Funcs) then begin SS := @CodecSearch[I, SearchInfo[I, J, X]]; Output(Instance, nil, 0); for Y := Low(SS^.EntryList) to High(SS^.EntryList) do begin SI.Position := Pos + SS^.EntryList[Y].Position; SI.OldSize := SS^.EntryList[Y].OldSize; SI.NewSize := SS^.EntryList[Y].NewSize; SI.Option := 0; SI.Resource := SS^.Resource; if System.Pos(SPrecompSep2 + 'l', SS^.Codec) > 0 then SI.Status := TStreamStatus.Predicted else SI.Status := TStreamStatus.None; Add(Instance, @SI, PChar(SS^.Codec), nil); DS := Funcs^.GetDepthCodec(PChar(SS^.Codec)); if DS <> '' then Funcs^.AddDepthStream(Instance, 0, SS^.EntryList[Y].NewSize, SS^.EntryList[Y].DepthSize, DS, 0, 0); end; end; end; end; end; Inc(Pos); end; end; end; function SearchScan2(Instance, Depth: Integer; Input: Pointer; Size: NativeInt; StreamInfo: PStrInfo2; Offset: PInteger; Output: _PrecompOutput; Funcs: PPrecompFuncs): Boolean; begin Result := False; end; function SearchProcess(Instance, Depth: Integer; OldInput, NewInput: Pointer; StreamInfo: PStrInfo2; Output: _PrecompOutput; Funcs: PPrecompFuncs): Boolean; begin Result := False; end; function SearchRestore(Instance, Depth: Integer; Input, InputExt: Pointer; StreamInfo: _StrInfo3; Output: _PrecompOutput; Funcs: PPrecompFuncs): Boolean; begin Result := False; end; var I, J, K: Integer; S: String; Bytes: TBytes; FStream: TFileStream; I32: Integer; SearchStruct: PSearchStruct; HList: TArray; initialization SearchList := TDirectory.GetFiles(ExpandPath(PluginsPath, True), '*.xtl', TSearchOption.soTopDirectoryOnly); for I := Low(SearchList) to High(SearchList) do begin FStream := TFileStream.Create(SearchList[I], fmShareDenyNone); try if FStream.Size >= 8 then begin FStream.ReadBuffer(I32, I32.Size); if (I32 = XTOOL_DB) then begin if FStream.Position < FStream.Size then begin if SameText(ChangeFileExt(ExtractFileName(SearchList[I]), ''), ChangeFileExt(ExtractFileName(Utils.GetModuleName), '')) then FORCEDMETHOD := True; J := Length(CodecSearch); SetLength(CodecSearch, Succ(J)); S := ChangeFileExt(ExtractFileName(SearchList[I]), ''); Insert(S, Codec.Names, Length(Codec.Names)); if not SameText(ChangeFileExt(ExtractFileName(SearchList[I]), ''), ChangeFileExt(ExtractFileName(Utils.GetModuleName), '')) then if InitCode.UIDLLLoaded then XTLAddplugin(S, PLUGIN_DATABASE); end; while FStream.Position < FStream.Size do begin New(SearchStruct); SearchStruct^.Name := S; FStream.ReadBuffer(SearchStruct^.SearchInt1, SearchStruct^.SearchInt1.Size); FStream.ReadBuffer(SearchStruct^.SearchInt2, SearchStruct^.SearchInt2.Size); FStream.ReadBuffer(SearchStruct^.Hash, SearchStruct^.Hash.Size); FStream.ReadBuffer(I32, I32.Size); SetLength(HList, I32); FStream.ReadBuffer(HList[0], I32 * SizeOf(THashStruct)); FStream.ReadBuffer(I32, I32.Size); SetLength(Bytes, I32); FStream.ReadBuffer(Bytes[0], I32); SearchStruct^.Codec := StringOf(Bytes); Insert(SearchStruct^, CodecSearch[J], Length(CodecSearch[J])); FStream.ReadBuffer(I32, I32.Size); K := Pred(Length(CodecSearch[J])); SetLength(CodecSearch[J, K].HashList, Length(HList)); Move(HList[0], CodecSearch[J, K].HashList[0], Length(HList) * SizeOf(THashStruct)); SetLength(CodecSearch[J, K].EntryList, I32); FStream.ReadBuffer(CodecSearch[J, K].EntryList[0], I32 * SizeOf(TEntryStruct)); end; end; end; finally FStream.Free; end; end; Codec.Initialised := False; Codec.Init := @SearchInit; Codec.Free := @SearchFree; Codec.Parse := @SearchParse; Codec.Scan1 := @SearchScan1; Codec.Scan2 := @SearchScan2; Codec.Process := @SearchProcess; Codec.Restore := @SearchRestore; SetLength(SearchInfo, Length(CodecSearch)); SetLength(SearchCount, Length(CodecSearch)); SetLength(CodecAvailable, Length(CodecSearch)); SetLength(CodecEnabled, Length(CodecSearch)); end.