吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 370|回复: 5
上一主题 下一主题
收起左侧

[其他原创] 编个TotalCommander的*.jar、*.class搜索插件配合组织行动!

[复制链接]
跳转到指定楼层
楼主
冥界3大法王 发表于 2026-7-23 19:10 回帖奖励
本帖最后由 冥界3大法王 于 2026-7-23 19:14 编辑

编个TotalCommander的*.jar、*.class搜索插件配合组织行动!

故事情节是这样的:

我要汉化这个Ghidra 12.1.2
可是没个像样的汉化工具来汉化Java程序(*.jar特殊的ZIP文件,解包后会得到*.class文件)

用这个老得掉渣的工具是过时的,落伍的。。没有效率的体现!
既然电脑里安装了VS2022、Delphi、Rust。。等强力后援就得自己开发像样的工具,体现穷人翻身做主DIY没枪没炮自己造的精神!





是不是开发了工具感觉高大上了许多? 我还能调用AI快速汉化呢,但是这样极易引起Java程序报错,因此开发了纠错和状态列、撤销、备份与恢复功能。{:301_997:}

突然发现我的TotalCommander竟然只能搜索到未汉化前的英文
汉化之后无论是*.class 还是*.html内的词条都无法找到,这是不能忍受的!{:301_1006:}

[Delphi] 纯文本查看 复制代码
library JavaSearch;

uses
  SysUtils,
  Classes,
  Windows,
  System.Zip,
  AnsiStrings;

const
  // TC WDX 插件返回值常量
  FT_NOMOREFIELDS = 0;
  FT_NUMERIC_32   = 1;
  FT_STRING       = 8;
  FT_FULLTEXT     = 9;

  FT_FILEERROR    = -1;
  FT_FIELD_EMPTY  = -2;

// ------------------------------------------------------------------
// 辅助函数 1:将 Java .properties 中的 \uXXXX 转义字符还原为真实中文字符
// ------------------------------------------------------------------
function UnescapeJavaUnicode(const Input: string): string;
var
  I, Len: Integer;
  HexCode: string;
  ChVal: Integer;
begin
  Result := '';
  Len := Length(Input);
  I := 1;
  while I <= Len do
  begin
    if (Input[I] = '\') and (I + 5 <= Len) and (LowerCase(Input[I + 1]) = 'u') then
    begin
      HexCode := Copy(Input, I + 2, 4);
      ChVal := StrToIntDef('$' + HexCode, -1);
      if ChVal <> -1 then
      begin
        Result := Result + Char(ChVal);
        Inc(I, 6);
        Continue;
      end;
    end;
    Result := Result + Input[I];
    Inc(I);
  end;
end;

// ------------------------------------------------------------------
// 辅助函数 2:把中文/字符串转换为 \uXXXX 格式(用于备选匹配)
// ------------------------------------------------------------------
function StringToUnicodeEscape(const S: string): string;
var
  I: Integer;
begin
  Result := '';
  for I := 1 to Length(S) do
  begin
    if Ord(S[I]) > 127 then
      Result := Result + '\u' + Format('%.4x', [Ord(S[I])])
    else
      Result := Result + S[I];
  end;
end;

// ------------------------------------------------------------------
// TC 导出函数 1:定义插件支持的字段
// ------------------------------------------------------------------
function ContentGetSupportedField(FieldIndex: Integer; FieldName: PAnsiChar;
  Units: PAnsiChar; MaxLen: Integer): Integer; stdcall;
begin
  if FieldIndex = 0 then
  begin
    AnsiStrings.StrLCopy(FieldName, 'ContainsText', MaxLen);
    Result := FT_STRING; // 声明为字符串字段
  end
  else
    Result := FT_NOMOREFIELDS;
end;

// ------------------------------------------------------------------
// TC 导出函数 2:获取文件对应字段的值(核心搜索逻辑)
// ------------------------------------------------------------------
function ContentGetValue(FileName: PAnsiChar; FieldIndex: Integer;
  UnitIndex: Integer; FieldValue: PByte; MaxLen: Integer; Flags: Integer): Integer; stdcall;
var
  FilePath: string;
  SearchQuery: string;
  EscapedQueryLower: string;
  EscapedQueryUpper: string;
  JarFile: TZipFile;
  I: Integer;
  ZipHeader: TZipHeader;
  Stream: TStream;
  StringList: TStringList;
  Ext: string;
  FileContent: string;
  Bytes: TBytes;
  Matched: Boolean;
begin
  if FieldIndex <> 0 then
  begin
    Result := FT_FIELD_EMPTY;
    Exit;
  end;

  FilePath := string(FileName);

  // 仅处理 .jar 压缩包
  if not (SameText(ExtractFileExt(FilePath), '.jar') and TZipFile.IsValid(FilePath)) then
  begin
    Result := FT_FIELD_EMPTY;
    Exit;
  end;

  // 获取 TC 在【插件】选项卡搜索框传入的搜索关键字(如果有)
  SearchQuery := '';
  if Assigned(FieldValue) and (PAnsiChar(FieldValue)^ <> #0) then
  begin
    try
      SearchQuery := string(PAnsiChar(FieldValue));
    except
      SearchQuery := '';
    end;
  end;

  // 生成 \uXXXX 格式的转义词供对比
  if SearchQuery <> '' then
  begin
    EscapedQueryLower := LowerCase(StringToUnicodeEscape(SearchQuery));
    EscapedQueryUpper := UpperCase(StringToUnicodeEscape(SearchQuery));
  end;

  Matched := False;
  JarFile := TZipFile.Create;
  try
    try
      JarFile.Open(FilePath, zmRead);
      for I := 0 to JarFile.FileCount - 1 do
      begin
        Ext := ExtractFileExt(JarFile.FileName[I]);

        // 1. 处理 .properties 属性文件
        if SameText(Ext, '.properties') then
        begin
          JarFile.Read(I, Stream, ZipHeader);
          if Assigned(Stream) then
          begin
            StringList := TStringList.Create;
            try
              StringList.LoadFromStream(Stream, TEncoding.UTF8);
              FileContent := StringList.Text;

              // 对内容进行 \uXXXX 解码,还原中文文本
              FileContent := UnescapeJavaUnicode(FileContent);

              // 如果 TC 传入了搜索词,内部直接判断
              if SearchQuery <> '' then
              begin
                if (Pos(SearchQuery, FileContent) > 0) or
                   (Pos(EscapedQueryLower, LowerCase(StringList.Text)) > 0) or
                   (Pos(EscapedQueryUpper, UpperCase(StringList.Text)) > 0) then
                begin
                  Matched := True;
                  Break;
                end;
              end
              else
              begin
                // 未传入搜索词时,默认返回解密后的部分文本给 TC 匹配
                if Length(FileContent) > MaxLen - 1 then
                  FileContent := Copy(FileContent, 1, MaxLen - 1);
                AnsiStrings.StrLCopy(PAnsiChar(FieldValue), PAnsiChar(AnsiString(FileContent)), MaxLen);
                Result := FT_STRING;
                Exit;
              end;
            finally
              StringList.Free;
              Stream.Free;
            end;
          end;
        end

        // 2. 处理 .class 二进制文件(按 UTF-8 匹配关键字)
        else if SameText(Ext, '.class') then
        begin
          if SearchQuery <> '' then
          begin
            JarFile.Read(I, Stream, ZipHeader);
            if Assigned(Stream) and (Stream.Size > 0) then
            begin
              try
                SetLength(Bytes, Stream.Size);
                Stream.Position := 0;
                Stream.Read(Bytes[0], Stream.Size);

                // 直接将 .class 中的字节转换为 UTF-8 文本搜索
                FileContent := TEncoding.UTF8.GetString(Bytes);
                if Pos(SearchQuery, FileContent) > 0 then
                begin
                  Matched := True;
                  Break;
                end;
              finally
                Stream.Free;
              end;
            end;
          end;
        end;
      end;
    except
      Matched := False;
    end;
  finally
    JarFile.Free;
  end;

  // 返回匹配结果
  if Matched then
  begin
    AnsiStrings.StrLCopy(PAnsiChar(FieldValue), PAnsiChar(AnsiString(SearchQuery)), MaxLen);
    Result := FT_STRING;
  end
  else
    Result := FT_FIELD_EMPTY;
end;

exports
  ContentGetSupportedField,
  ContentGetValue;

begin
end.

将编译好的DLL改名,复制到TC插件目录下

添加进来


这样就能开心的搜索到无论是*.jar内的*.class还是修改后的*.html {:301_987:}

image.png (176.26 KB, 下载次数: 0)

image.png

image.png (221.57 KB, 下载次数: 0)

image.png

免费评分

参与人数 2吾爱币 +1 热心值 +2 收起 理由
52pojieplayer + 1 谢谢@Thanks!
Mint_Grass + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
 楼主| 冥界3大法王 发表于 2026-7-23 19:19 |楼主
自古楼主坐沙发。
https://wwaso.lanzouu.com/i0bz23y7meri
包括32位 和 64位的插件
3#
dunniu 发表于 2026-7-23 20:39
4#
clg603 发表于 2026-7-23 20:47
这个看上去还挺复杂的,虽然不会弄还是要谢谢你
5#
playplay2121 发表于 2026-7-24 08:51
感谢分享,按照这个思路,应该是可以衍生,添加支持其他文件类型的插件。
6#
goldharp 发表于 2026-7-24 09:41
相当会玩
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-24 23:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表