capacitor-dex-editor 0.0.70 → 0.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -307,6 +307,31 @@ public class DexEditorPluginPlugin extends Plugin {
307
307
  ));
308
308
  break;
309
309
 
310
+ // ============ 交叉引用分析(C++ 实现)============
311
+ case "findMethodXrefs":
312
+ result.put("data", dexManager.findMethodXrefs(
313
+ params.getString("sessionId"),
314
+ params.getString("className"),
315
+ params.getString("methodName")
316
+ ));
317
+ break;
318
+
319
+ case "findFieldXrefs":
320
+ result.put("data", dexManager.findFieldXrefs(
321
+ params.getString("sessionId"),
322
+ params.getString("className"),
323
+ params.getString("fieldName")
324
+ ));
325
+ break;
326
+
327
+ // ============ Smali 转 Java(C++ 实现)============
328
+ case "smaliToJava":
329
+ result.put("data", dexManager.smaliToJava(
330
+ params.getString("sessionId"),
331
+ params.getString("className")
332
+ ));
333
+ break;
334
+
310
335
  // ============ 工具操作 ============
311
336
  case "fixDex":
312
337
  dexManager.fixDex(
@@ -130,14 +130,16 @@ public class DexManager {
130
130
  String sessionId;
131
131
  String filePath;
132
132
  DexBackedDexFile originalDexFile;
133
+ byte[] dexBytes; // DEX 字节数据,用于 C++ 解析
133
134
  List<ClassDef> modifiedClasses;
134
135
  Set<String> removedClasses;
135
136
  boolean modified = false;
136
137
 
137
- DexSession(String sessionId, String filePath, DexBackedDexFile dexFile) {
138
+ DexSession(String sessionId, String filePath, DexBackedDexFile dexFile, byte[] bytes) {
138
139
  this.sessionId = sessionId;
139
140
  this.filePath = filePath;
140
141
  this.originalDexFile = dexFile;
142
+ this.dexBytes = bytes;
141
143
  this.modifiedClasses = new ArrayList<>();
142
144
  this.removedClasses = new HashSet<>();
143
145
  }
@@ -188,6 +190,9 @@ public class DexManager {
188
190
  // 生成或使用提供的 sessionId
189
191
  String sid = (sessionId != null && !sessionId.isEmpty()) ? sessionId : UUID.randomUUID().toString();
190
192
 
193
+ // 读取 DEX 字节数据(用于 C++ 解析)
194
+ byte[] dexBytes = readFileBytes(file);
195
+
191
196
  // 加载 DEX 文件 (使用官方推荐的 DexFileFactory)
192
197
  DexBackedDexFile dexFile = (DexBackedDexFile) DexFileFactory.loadDexFile(
193
198
  file,
@@ -195,7 +200,7 @@ public class DexManager {
195
200
  );
196
201
 
197
202
  // 创建会话
198
- DexSession session = new DexSession(sid, path, dexFile);
203
+ DexSession session = new DexSession(sid, path, dexFile, dexBytes);
199
204
  sessions.put(sid, session);
200
205
 
201
206
  Log.d(TAG, "Loaded DEX: " + path + " with session: " + sid);
@@ -262,18 +267,41 @@ public class DexManager {
262
267
  }
263
268
 
264
269
  /**
265
- * 获取 DEX 文件信息
270
+ * 获取 DEX 文件信息(优先使用 C++ 实现)
266
271
  */
267
272
  public JSObject getDexInfo(String sessionId) throws Exception {
268
273
  DexSession session = getSession(sessionId);
274
+
275
+ // 优先使用 C++ 实现
276
+ if (CppDex.isAvailable() && session.dexBytes != null) {
277
+ try {
278
+ String jsonResult = CppDex.getDexInfo(session.dexBytes);
279
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
280
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
281
+ JSObject info = new JSObject();
282
+ info.put("sessionId", sessionId);
283
+ info.put("filePath", session.filePath);
284
+ info.put("classCount", cppResult.optInt("classCount", 0));
285
+ info.put("methodCount", cppResult.optInt("methodCount", 0));
286
+ info.put("fieldCount", cppResult.optInt("fieldCount", 0));
287
+ info.put("stringCount", cppResult.optInt("stringCount", 0));
288
+ info.put("dexVersion", cppResult.optInt("version", 35));
289
+ info.put("modified", session.modified);
290
+ info.put("engine", "cpp");
291
+ return info;
292
+ }
293
+ } catch (Exception e) {
294
+ Log.w(TAG, "C++ getDexInfo failed, fallback to Java", e);
295
+ }
296
+ }
297
+
298
+ // Java 回退实现
269
299
  DexBackedDexFile dexFile = session.originalDexFile;
270
-
271
300
  JSObject info = new JSObject();
272
301
  info.put("sessionId", sessionId);
273
302
  info.put("filePath", session.filePath);
274
303
  info.put("classCount", dexFile.getClasses().size());
275
304
 
276
- // 统计方法和字段数量
277
305
  int methodCount = 0;
278
306
  int fieldCount = 0;
279
307
  for (ClassDef classDef : dexFile.getClasses()) {
@@ -284,18 +312,45 @@ public class DexManager {
284
312
  info.put("fieldCount", fieldCount);
285
313
  info.put("dexVersion", dexFile.getOpcodes().api);
286
314
  info.put("modified", session.modified);
315
+ info.put("engine", "java");
287
316
  return info;
288
317
  }
289
318
 
290
319
  // ==================== 类操作 ====================
291
320
 
292
321
  /**
293
- * 获取所有类列表
322
+ * 获取所有类列表(优先使用 C++ 实现)
294
323
  */
295
324
  public JSArray getClasses(String sessionId) throws Exception {
296
325
  DexSession session = getSession(sessionId);
326
+
327
+ // 优先使用 C++ 实现
328
+ if (CppDex.isAvailable() && session.dexBytes != null) {
329
+ try {
330
+ String jsonResult = CppDex.listClasses(session.dexBytes, "", 0, 100000);
331
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
332
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
333
+ org.json.JSONArray cppClasses = cppResult.optJSONArray("classes");
334
+ if (cppClasses != null) {
335
+ JSArray classes = new JSArray();
336
+ for (int i = 0; i < cppClasses.length(); i++) {
337
+ String className = cppClasses.getString(i);
338
+ if (!session.removedClasses.contains(className)) {
339
+ JSObject classInfo = new JSObject();
340
+ classInfo.put("type", className);
341
+ classes.put(classInfo);
342
+ }
343
+ }
344
+ return classes;
345
+ }
346
+ }
347
+ } catch (Exception e) {
348
+ Log.w(TAG, "C++ getClasses failed, fallback to Java", e);
349
+ }
350
+ }
351
+
352
+ // Java 回退实现
297
353
  JSArray classes = new JSArray();
298
-
299
354
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
300
355
  if (!session.removedClasses.contains(classDef.getType())) {
301
356
  JSObject classInfo = new JSObject();
@@ -305,7 +360,6 @@ public class DexManager {
305
360
  classes.put(classInfo);
306
361
  }
307
362
  }
308
-
309
363
  return classes;
310
364
  }
311
365
 
@@ -407,12 +461,38 @@ public class DexManager {
407
461
  // ==================== 方法操作 ====================
408
462
 
409
463
  /**
410
- * 获取类的所有方法
464
+ * 获取类的所有方法(优先使用 C++ 实现)
411
465
  */
412
466
  public JSArray getMethods(String sessionId, String className) throws Exception {
413
467
  DexSession session = getSession(sessionId);
468
+
469
+ // 优先使用 C++ 实现
470
+ if (CppDex.isAvailable() && session.dexBytes != null) {
471
+ try {
472
+ String jsonResult = CppDex.listMethods(session.dexBytes, className);
473
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
474
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
475
+ org.json.JSONArray cppMethods = cppResult.optJSONArray("methods");
476
+ if (cppMethods != null) {
477
+ JSArray methods = new JSArray();
478
+ for (int i = 0; i < cppMethods.length(); i++) {
479
+ org.json.JSONObject m = cppMethods.getJSONObject(i);
480
+ JSObject methodInfo = new JSObject();
481
+ methodInfo.put("name", m.optString("name"));
482
+ methodInfo.put("signature", m.optString("prototype"));
483
+ methodInfo.put("accessFlags", m.optInt("accessFlags"));
484
+ methods.put(methodInfo);
485
+ }
486
+ return methods;
487
+ }
488
+ }
489
+ } catch (Exception e) {
490
+ Log.w(TAG, "C++ getMethods failed, fallback to Java", e);
491
+ }
492
+ }
493
+
494
+ // Java 回退实现
414
495
  ClassDef classDef = findClass(session, className);
415
-
416
496
  if (classDef == null) {
417
497
  throw new IllegalArgumentException("Class not found: " + className);
418
498
  }
@@ -424,14 +504,12 @@ public class DexManager {
424
504
  methodInfo.put("returnType", method.getReturnType());
425
505
  methodInfo.put("accessFlags", method.getAccessFlags());
426
506
 
427
- // 参数类型
428
507
  JSArray params = new JSArray();
429
508
  for (CharSequence param : method.getParameterTypes()) {
430
509
  params.put(param.toString());
431
510
  }
432
511
  methodInfo.put("parameters", params);
433
512
 
434
- // 方法签名
435
513
  StringBuilder sig = new StringBuilder("(");
436
514
  for (CharSequence param : method.getParameterTypes()) {
437
515
  sig.append(param);
@@ -441,7 +519,6 @@ public class DexManager {
441
519
 
442
520
  methods.put(methodInfo);
443
521
  }
444
-
445
522
  return methods;
446
523
  }
447
524
 
@@ -485,21 +562,42 @@ public class DexManager {
485
562
  }
486
563
 
487
564
  /**
488
- * 获取方法的 Smali 代码
565
+ * 获取方法的 Smali 代码(优先使用 C++ 实现)
489
566
  */
490
567
  public JSObject getMethodSmali(String sessionId, String className,
491
568
  String methodName, String methodSignature) throws Exception {
492
569
  DexSession session = getSession(sessionId);
493
570
 
494
- // 获取类的完整 Smali,然后提取方法部分
495
- String classSmali = classToSmali(sessionId, className).getString("smali");
571
+ // 优先使用 C++ 实现
572
+ if (CppDex.isAvailable() && session.dexBytes != null) {
573
+ try {
574
+ String jsonResult = CppDex.getMethodSmali(session.dexBytes, className, methodName, methodSignature);
575
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
576
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
577
+ String smali = cppResult.optString("smali", "");
578
+ if (!smali.isEmpty()) {
579
+ JSObject result = new JSObject();
580
+ result.put("className", className);
581
+ result.put("methodName", methodName);
582
+ result.put("methodSignature", methodSignature);
583
+ result.put("smali", smali);
584
+ result.put("engine", "cpp");
585
+ return result;
586
+ }
587
+ }
588
+ } catch (Exception e) {
589
+ Log.w(TAG, "C++ getMethodSmali failed, fallback to Java", e);
590
+ }
591
+ }
496
592
 
497
- // 简化处理:返回整个类的 Smali(实际应该解析提取特定方法)
593
+ // Java 回退实现
594
+ String classSmali = classToSmali(sessionId, className).getString("smali");
498
595
  JSObject result = new JSObject();
499
596
  result.put("className", className);
500
597
  result.put("methodName", methodName);
501
598
  result.put("methodSignature", methodSignature);
502
599
  result.put("smali", extractMethodSmali(classSmali, methodName, methodSignature));
600
+ result.put("engine", "java");
503
601
  return result;
504
602
  }
505
603
 
@@ -583,12 +681,38 @@ public class DexManager {
583
681
  // ==================== 字段操作 ====================
584
682
 
585
683
  /**
586
- * 获取类的所有字段
684
+ * 获取类的所有字段(优先使用 C++ 实现)
587
685
  */
588
686
  public JSArray getFields(String sessionId, String className) throws Exception {
589
687
  DexSession session = getSession(sessionId);
688
+
689
+ // 优先使用 C++ 实现
690
+ if (CppDex.isAvailable() && session.dexBytes != null) {
691
+ try {
692
+ String jsonResult = CppDex.listFields(session.dexBytes, className);
693
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
694
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
695
+ org.json.JSONArray cppFields = cppResult.optJSONArray("fields");
696
+ if (cppFields != null) {
697
+ JSArray fields = new JSArray();
698
+ for (int i = 0; i < cppFields.length(); i++) {
699
+ org.json.JSONObject f = cppFields.getJSONObject(i);
700
+ JSObject fieldInfo = new JSObject();
701
+ fieldInfo.put("name", f.optString("name"));
702
+ fieldInfo.put("type", f.optString("type"));
703
+ fieldInfo.put("accessFlags", f.optInt("accessFlags"));
704
+ fields.put(fieldInfo);
705
+ }
706
+ return fields;
707
+ }
708
+ }
709
+ } catch (Exception e) {
710
+ Log.w(TAG, "C++ getFields failed, fallback to Java", e);
711
+ }
712
+ }
713
+
714
+ // Java 回退实现
590
715
  ClassDef classDef = findClass(session, className);
591
-
592
716
  if (classDef == null) {
593
717
  throw new IllegalArgumentException("Class not found: " + className);
594
718
  }
@@ -679,21 +803,40 @@ public class DexManager {
679
803
  // ==================== Smali 操作 ====================
680
804
 
681
805
  /**
682
- * 将类转换为 Smali 代码
806
+ * 将类转换为 Smali 代码(优先使用 C++ 实现)
683
807
  */
684
808
  public JSObject classToSmali(String sessionId, String className) throws Exception {
685
809
  DexSession session = getSession(sessionId);
810
+
811
+ // 优先使用 C++ 实现
812
+ if (CppDex.isAvailable() && session.dexBytes != null) {
813
+ try {
814
+ String jsonResult = CppDex.getClassSmali(session.dexBytes, className);
815
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
816
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
817
+ String smali = cppResult.optString("smali", "");
818
+ if (!smali.isEmpty()) {
819
+ JSObject result = new JSObject();
820
+ result.put("className", className);
821
+ result.put("smali", smali);
822
+ result.put("engine", "cpp");
823
+ return result;
824
+ }
825
+ }
826
+ } catch (Exception e) {
827
+ Log.w(TAG, "C++ classToSmali failed, fallback to Java", e);
828
+ }
829
+ }
830
+
831
+ // Java 回退实现
686
832
  ClassDef classDef = findClass(session, className);
687
-
688
833
  if (classDef == null) {
689
834
  throw new IllegalArgumentException("Class not found: " + className);
690
835
  }
691
836
 
692
- // 使用 baksmali 转换
693
837
  StringWriter writer = new StringWriter();
694
838
  BaksmaliOptions options = new BaksmaliOptions();
695
839
 
696
- // 创建临时 DEX 只包含该类
697
840
  List<ClassDef> singleClass = new ArrayList<>();
698
841
  singleClass.add(classDef);
699
842
  ImmutableDexFile singleDex = new ImmutableDexFile(
@@ -701,7 +844,6 @@ public class DexManager {
701
844
  singleClass
702
845
  );
703
846
 
704
- // 使用临时目录输出
705
847
  File tempDir = File.createTempFile("smali_", "_temp");
706
848
  tempDir.delete();
707
849
  tempDir.mkdirs();
@@ -709,7 +851,6 @@ public class DexManager {
709
851
  try {
710
852
  Baksmali.disassembleDexFile(singleDex, tempDir, 1, options);
711
853
 
712
- // 读取生成的 smali 文件
713
854
  String smaliPath = className.substring(1, className.length() - 1) + ".smali";
714
855
  File smaliFile = new File(tempDir, smaliPath);
715
856
 
@@ -718,6 +859,7 @@ public class DexManager {
718
859
  JSObject result = new JSObject();
719
860
  result.put("className", className);
720
861
  result.put("smali", smali);
862
+ result.put("engine", "java");
721
863
  return result;
722
864
  } else {
723
865
  throw new IOException("Failed to generate smali for: " + className);
@@ -784,30 +926,51 @@ public class DexManager {
784
926
  // ==================== 搜索操作 ====================
785
927
 
786
928
  /**
787
- * 搜索字符串
929
+ * 搜索字符串(优先使用 C++ 实现)
788
930
  */
789
931
  public JSArray searchString(String sessionId, String query,
790
932
  boolean regex, boolean caseSensitive) throws Exception {
791
933
  DexSession session = getSession(sessionId);
934
+
935
+ // 优先使用 C++ 实现
936
+ if (CppDex.isAvailable() && session.dexBytes != null && !regex) {
937
+ try {
938
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "string", caseSensitive, 1000);
939
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
940
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
941
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
942
+ if (cppResults != null) {
943
+ JSArray results = new JSArray();
944
+ for (int i = 0; i < cppResults.length(); i++) {
945
+ org.json.JSONObject r = cppResults.getJSONObject(i);
946
+ JSObject item = new JSObject();
947
+ item.put("value", r.optString("value"));
948
+ item.put("index", r.optInt("index"));
949
+ results.put(item);
950
+ }
951
+ return results;
952
+ }
953
+ }
954
+ } catch (Exception e) {
955
+ Log.w(TAG, "C++ searchString failed, fallback to Java", e);
956
+ }
957
+ }
958
+
959
+ // Java 回退实现
792
960
  JSArray results = new JSArray();
793
-
794
961
  Pattern pattern = null;
795
962
  if (regex) {
796
963
  int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
797
964
  pattern = Pattern.compile(query, flags);
798
965
  }
799
966
 
800
- // 遍历所有类中的字符串引用进行搜索
801
967
  Set<String> searchedStrings = new HashSet<>();
802
968
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
803
- // 类名
804
969
  checkAndAddString(classDef.getType(), query, regex, caseSensitive, pattern, searchedStrings, results);
805
- // 父类
806
970
  if (classDef.getSuperclass() != null) {
807
971
  checkAndAddString(classDef.getSuperclass(), query, regex, caseSensitive, pattern, searchedStrings, results);
808
972
  }
809
973
  }
810
-
811
974
  return results;
812
975
  }
813
976
 
@@ -842,16 +1005,41 @@ public class DexManager {
842
1005
  }
843
1006
 
844
1007
  /**
845
- * 搜索方法
1008
+ * 搜索方法(优先使用 C++ 实现)
846
1009
  */
847
1010
  public JSArray searchMethod(String sessionId, String query) throws Exception {
848
1011
  DexSession session = getSession(sessionId);
1012
+
1013
+ // 优先使用 C++ 实现
1014
+ if (CppDex.isAvailable() && session.dexBytes != null) {
1015
+ try {
1016
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "method", false, 1000);
1017
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
1018
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1019
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
1020
+ if (cppResults != null) {
1021
+ JSArray results = new JSArray();
1022
+ for (int i = 0; i < cppResults.length(); i++) {
1023
+ org.json.JSONObject r = cppResults.getJSONObject(i);
1024
+ JSObject item = new JSObject();
1025
+ item.put("className", r.optString("className"));
1026
+ item.put("methodName", r.optString("name"));
1027
+ item.put("returnType", r.optString("returnType", ""));
1028
+ results.put(item);
1029
+ }
1030
+ return results;
1031
+ }
1032
+ }
1033
+ } catch (Exception e) {
1034
+ Log.w(TAG, "C++ searchMethod failed, fallback to Java", e);
1035
+ }
1036
+ }
1037
+
1038
+ // Java 回退实现
849
1039
  JSArray results = new JSArray();
850
1040
  String queryLower = query.toLowerCase();
851
-
852
1041
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
853
1042
  if (session.removedClasses.contains(classDef.getType())) continue;
854
-
855
1043
  for (Method method : classDef.getMethods()) {
856
1044
  if (method.getName().toLowerCase().contains(queryLower)) {
857
1045
  JSObject item = new JSObject();
@@ -862,21 +1050,45 @@ public class DexManager {
862
1050
  }
863
1051
  }
864
1052
  }
865
-
866
1053
  return results;
867
1054
  }
868
1055
 
869
1056
  /**
870
- * 搜索字段
1057
+ * 搜索字段(优先使用 C++ 实现)
871
1058
  */
872
1059
  public JSArray searchField(String sessionId, String query) throws Exception {
873
1060
  DexSession session = getSession(sessionId);
1061
+
1062
+ // 优先使用 C++ 实现
1063
+ if (CppDex.isAvailable() && session.dexBytes != null) {
1064
+ try {
1065
+ String jsonResult = CppDex.searchInDex(session.dexBytes, query, "field", false, 1000);
1066
+ if (jsonResult != null && !jsonResult.contains("\"error\"")) {
1067
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1068
+ org.json.JSONArray cppResults = cppResult.optJSONArray("results");
1069
+ if (cppResults != null) {
1070
+ JSArray results = new JSArray();
1071
+ for (int i = 0; i < cppResults.length(); i++) {
1072
+ org.json.JSONObject r = cppResults.getJSONObject(i);
1073
+ JSObject item = new JSObject();
1074
+ item.put("className", r.optString("className"));
1075
+ item.put("fieldName", r.optString("name"));
1076
+ item.put("fieldType", r.optString("type", ""));
1077
+ results.put(item);
1078
+ }
1079
+ return results;
1080
+ }
1081
+ }
1082
+ } catch (Exception e) {
1083
+ Log.w(TAG, "C++ searchField failed, fallback to Java", e);
1084
+ }
1085
+ }
1086
+
1087
+ // Java 回退实现
874
1088
  JSArray results = new JSArray();
875
1089
  String queryLower = query.toLowerCase();
876
-
877
1090
  for (ClassDef classDef : session.originalDexFile.getClasses()) {
878
1091
  if (session.removedClasses.contains(classDef.getType())) continue;
879
-
880
1092
  for (Field field : classDef.getFields()) {
881
1093
  if (field.getName().toLowerCase().contains(queryLower)) {
882
1094
  JSObject item = new JSObject();
@@ -887,10 +1099,109 @@ public class DexManager {
887
1099
  }
888
1100
  }
889
1101
  }
890
-
891
1102
  return results;
892
1103
  }
893
1104
 
1105
+ // ==================== 交叉引用分析(C++ 实现)====================
1106
+
1107
+ /**
1108
+ * 查找方法的交叉引用
1109
+ */
1110
+ public JSObject findMethodXrefs(String sessionId, String className, String methodName) throws Exception {
1111
+ DexSession session = getSession(sessionId);
1112
+
1113
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1114
+ throw new UnsupportedOperationException("C++ library not available for xref analysis");
1115
+ }
1116
+
1117
+ String jsonResult = CppDex.findMethodXrefs(session.dexBytes, className, methodName);
1118
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1119
+ throw new Exception("Failed to find method xrefs");
1120
+ }
1121
+
1122
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1123
+ JSObject result = new JSObject();
1124
+ result.put("className", className);
1125
+ result.put("methodName", methodName);
1126
+
1127
+ org.json.JSONArray xrefs = cppResult.optJSONArray("xrefs");
1128
+ JSArray xrefArray = new JSArray();
1129
+ if (xrefs != null) {
1130
+ for (int i = 0; i < xrefs.length(); i++) {
1131
+ org.json.JSONObject x = xrefs.getJSONObject(i);
1132
+ JSObject xref = new JSObject();
1133
+ xref.put("callerClass", x.optString("callerClass"));
1134
+ xref.put("callerMethod", x.optString("callerMethod"));
1135
+ xref.put("offset", x.optInt("offset"));
1136
+ xrefArray.put(xref);
1137
+ }
1138
+ }
1139
+ result.put("xrefs", xrefArray);
1140
+ result.put("count", xrefArray.length());
1141
+ return result;
1142
+ }
1143
+
1144
+ /**
1145
+ * 查找字段的交叉引用
1146
+ */
1147
+ public JSObject findFieldXrefs(String sessionId, String className, String fieldName) throws Exception {
1148
+ DexSession session = getSession(sessionId);
1149
+
1150
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1151
+ throw new UnsupportedOperationException("C++ library not available for xref analysis");
1152
+ }
1153
+
1154
+ String jsonResult = CppDex.findFieldXrefs(session.dexBytes, className, fieldName);
1155
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1156
+ throw new Exception("Failed to find field xrefs");
1157
+ }
1158
+
1159
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1160
+ JSObject result = new JSObject();
1161
+ result.put("className", className);
1162
+ result.put("fieldName", fieldName);
1163
+
1164
+ org.json.JSONArray xrefs = cppResult.optJSONArray("xrefs");
1165
+ JSArray xrefArray = new JSArray();
1166
+ if (xrefs != null) {
1167
+ for (int i = 0; i < xrefs.length(); i++) {
1168
+ org.json.JSONObject x = xrefs.getJSONObject(i);
1169
+ JSObject xref = new JSObject();
1170
+ xref.put("accessorClass", x.optString("accessorClass"));
1171
+ xref.put("accessorMethod", x.optString("accessorMethod"));
1172
+ xref.put("accessType", x.optString("accessType"));
1173
+ xrefArray.put(xref);
1174
+ }
1175
+ }
1176
+ result.put("xrefs", xrefArray);
1177
+ result.put("count", xrefArray.length());
1178
+ return result;
1179
+ }
1180
+
1181
+ // ==================== Smali 转 Java(C++ 实现)====================
1182
+
1183
+ /**
1184
+ * 将 Smali 代码转换为 Java 伪代码
1185
+ */
1186
+ public JSObject smaliToJava(String sessionId, String className) throws Exception {
1187
+ DexSession session = getSession(sessionId);
1188
+
1189
+ if (!CppDex.isAvailable() || session.dexBytes == null) {
1190
+ throw new UnsupportedOperationException("C++ library not available for smali to java conversion");
1191
+ }
1192
+
1193
+ String jsonResult = CppDex.smaliToJava(session.dexBytes, className);
1194
+ if (jsonResult == null || jsonResult.contains("\"error\"")) {
1195
+ throw new Exception("Failed to convert smali to java");
1196
+ }
1197
+
1198
+ org.json.JSONObject cppResult = new org.json.JSONObject(jsonResult);
1199
+ JSObject result = new JSObject();
1200
+ result.put("className", className);
1201
+ result.put("java", cppResult.optString("java", ""));
1202
+ return result;
1203
+ }
1204
+
894
1205
  // ==================== 工具操作 ====================
895
1206
 
896
1207
  /**
@@ -1254,6 +1565,14 @@ public class DexManager {
1254
1565
  return content.toString();
1255
1566
  }
1256
1567
 
1568
+ private byte[] readFileBytes(File file) throws IOException {
1569
+ byte[] bytes = new byte[(int) file.length()];
1570
+ try (FileInputStream fis = new FileInputStream(file)) {
1571
+ fis.read(bytes);
1572
+ }
1573
+ return bytes;
1574
+ }
1575
+
1257
1576
  private void deleteRecursive(File file) {
1258
1577
  if (file.isDirectory()) {
1259
1578
  File[] children = file.listFiles();
@@ -2903,21 +3222,6 @@ public class DexManager {
2903
3222
  return result;
2904
3223
  }
2905
3224
 
2906
- /**
2907
- * 读取文件为字节数组
2908
- */
2909
- private byte[] readFileBytes(java.io.File file) throws java.io.IOException {
2910
- java.io.FileInputStream fis = new java.io.FileInputStream(file);
2911
- java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
2912
- byte[] buffer = new byte[8192];
2913
- int len;
2914
- while ((len = fis.read(buffer)) != -1) {
2915
- baos.write(buffer, 0, len);
2916
- }
2917
- fis.close();
2918
- return baos.toByteArray();
2919
- }
2920
-
2921
3225
  /**
2922
3226
  * 计算 CRC32
2923
3227
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-dex-editor",
3
- "version": "0.0.70",
3
+ "version": "0.0.72",
4
4
  "description": "Capacitor-plugin-for-editing-DEX-files-in-APK",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",