capacitor-dex-editor 0.0.68 → 0.0.70

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.
Files changed (40) hide show
  1. package/android/build.gradle +22 -0
  2. package/android/src/main/cpp/CMakeLists.txt +57 -0
  3. package/android/src/main/cpp/apk/apk_handler.cpp +121 -0
  4. package/android/src/main/cpp/apk/zip_utils.cpp +425 -0
  5. package/android/src/main/cpp/arsc/arsc_parser.cpp +390 -0
  6. package/android/src/main/cpp/dex/dex_builder.cpp +752 -0
  7. package/android/src/main/cpp/dex/dex_parser.cpp +620 -0
  8. package/android/src/main/cpp/dex/smali_disasm.cpp +1223 -0
  9. package/android/src/main/cpp/dex/smali_to_java.cpp +576 -0
  10. package/android/src/main/cpp/include/apk/apk_handler.h +41 -0
  11. package/android/src/main/cpp/include/apk/zip_utils.h +57 -0
  12. package/android/src/main/cpp/include/arsc/arsc_parser.h +98 -0
  13. package/android/src/main/cpp/include/dex/dex_builder.h +189 -0
  14. package/android/src/main/cpp/include/dex/dex_parser.h +137 -0
  15. package/android/src/main/cpp/include/dex/smali_disasm.h +127 -0
  16. package/android/src/main/cpp/include/dex/smali_to_java.h +50 -0
  17. package/android/src/main/cpp/include/xml/android_resources.h +495 -0
  18. package/android/src/main/cpp/include/xml/axml_parser.h +147 -0
  19. package/android/src/main/cpp/jni_bridge.cpp +872 -0
  20. package/android/src/main/cpp/third_party/miniz.c +646 -0
  21. package/android/src/main/cpp/third_party/miniz.h +605 -0
  22. package/android/src/main/cpp/third_party/miniz_common.h +97 -0
  23. package/android/src/main/cpp/third_party/miniz_export.h +6 -0
  24. package/android/src/main/cpp/third_party/miniz_tdef.c +1597 -0
  25. package/android/src/main/cpp/third_party/miniz_tdef.h +199 -0
  26. package/android/src/main/cpp/third_party/miniz_tinfl.c +770 -0
  27. package/android/src/main/cpp/third_party/miniz_tinfl.h +150 -0
  28. package/android/src/main/cpp/third_party/miniz_zip.c +4895 -0
  29. package/android/src/main/cpp/third_party/miniz_zip.h +454 -0
  30. package/android/src/main/cpp/third_party/nlohmann_json/CMakeLists.txt +0 -0
  31. package/android/src/main/cpp/third_party/nlohmann_json/single_include/nlohmann/json.hpp +24765 -0
  32. package/android/src/main/cpp/xml/axml_parser.cpp +1701 -0
  33. package/android/src/main/java/com/aetherlink/dexeditor/CppDex.java +295 -0
  34. package/android/src/main/java/com/aetherlink/dexeditor/DexManager.java +20 -20
  35. package/package.json +1 -1
  36. package/android/src/main/java/com/aetherlink/dexeditor/RustDex.java +0 -108
  37. package/android/src/main/jniLibs/arm64-v8a/libdex_rust.so +0 -0
  38. package/android/src/main/jniLibs/armeabi-v7a/libdex_rust.so +0 -0
  39. package/android/src/main/jniLibs/x86/libdex_rust.so +0 -0
  40. package/android/src/main/jniLibs/x86_64/libdex_rust.so +0 -0
@@ -0,0 +1,1701 @@
1
+ #include "xml/axml_parser.h"
2
+ #include <sstream>
3
+ #include <cstring>
4
+ #include <functional>
5
+
6
+ namespace axml {
7
+
8
+ static const uint16_t RES_NULL_TYPE = 0x0000;
9
+ static const uint16_t RES_STRING_POOL_TYPE = 0x0001;
10
+ static const uint16_t RES_TABLE_TYPE = 0x0002;
11
+ static const uint16_t RES_XML_TYPE = 0x0003;
12
+ static const uint16_t RES_XML_START_NAMESPACE_TYPE = 0x0100;
13
+ static const uint16_t RES_XML_END_NAMESPACE_TYPE = 0x0101;
14
+ static const uint16_t RES_XML_START_ELEMENT_TYPE = 0x0102;
15
+ static const uint16_t RES_XML_END_ELEMENT_TYPE = 0x0103;
16
+ static const uint16_t RES_XML_CDATA_TYPE = 0x0104;
17
+ static const uint16_t RES_XML_RESOURCE_MAP_TYPE = 0x0180;
18
+
19
+ // 类型常量直接使用 android_resources.h 中定义的 ResourceValueType 枚举
20
+
21
+ template<typename T>
22
+ static T read_le(const uint8_t* p) {
23
+ T val = 0;
24
+ for (size_t i = 0; i < sizeof(T); i++) {
25
+ val |= static_cast<T>(p[i]) << (i * 8);
26
+ }
27
+ return val;
28
+ }
29
+
30
+ template<typename T>
31
+ static void write_le(uint8_t* p, T val) {
32
+ for (size_t i = 0; i < sizeof(T); i++) {
33
+ p[i] = static_cast<uint8_t>(val >> (i * 8));
34
+ }
35
+ }
36
+
37
+ bool AxmlParser::parse(const std::vector<uint8_t>& data) {
38
+ data_ = data;
39
+
40
+ if (data_.size() < 8) return false;
41
+
42
+ uint16_t type = read_le<uint16_t>(&data_[0]);
43
+ uint16_t header_size = read_le<uint16_t>(&data_[2]);
44
+ uint32_t file_size = read_le<uint32_t>(&data_[4]);
45
+
46
+ if (type != RES_XML_TYPE) return false;
47
+ if (file_size > data_.size()) return false;
48
+
49
+ size_t offset = header_size;
50
+
51
+ while (offset < data_.size()) {
52
+ if (offset + 8 > data_.size()) break;
53
+
54
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
55
+ uint16_t chunk_header_size = read_le<uint16_t>(&data_[offset + 2]);
56
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
57
+
58
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
59
+
60
+ switch (chunk_type) {
61
+ case RES_STRING_POOL_TYPE:
62
+ parse_string_pool(offset);
63
+ break;
64
+ case RES_XML_RESOURCE_MAP_TYPE:
65
+ parse_resource_map(offset);
66
+ break;
67
+ case RES_XML_START_ELEMENT_TYPE:
68
+ case RES_XML_END_ELEMENT_TYPE:
69
+ case RES_XML_START_NAMESPACE_TYPE:
70
+ case RES_XML_END_NAMESPACE_TYPE:
71
+ case RES_XML_CDATA_TYPE:
72
+ break;
73
+ }
74
+
75
+ offset += chunk_size;
76
+ }
77
+
78
+ parse_elements(offset);
79
+
80
+ return true;
81
+ }
82
+
83
+ bool AxmlParser::parse_string_pool(size_t& offset) {
84
+ if (offset + 28 > data_.size()) return false;
85
+
86
+ uint32_t string_count = read_le<uint32_t>(&data_[offset + 8]);
87
+ uint32_t style_count = read_le<uint32_t>(&data_[offset + 12]);
88
+ uint32_t flags = read_le<uint32_t>(&data_[offset + 16]);
89
+ uint32_t strings_start = read_le<uint32_t>(&data_[offset + 20]);
90
+ uint32_t styles_start = read_le<uint32_t>(&data_[offset + 24]);
91
+
92
+ bool is_utf8 = (flags & (1 << 8)) != 0;
93
+
94
+ string_pool_.clear();
95
+ string_pool_.reserve(string_count);
96
+
97
+ size_t offsets_start = offset + 28;
98
+
99
+ for (uint32_t i = 0; i < string_count; i++) {
100
+ uint32_t string_offset = read_le<uint32_t>(&data_[offsets_start + i * 4]);
101
+ size_t str_pos = offset + strings_start + string_offset;
102
+
103
+ if (str_pos >= data_.size()) {
104
+ string_pool_.push_back("");
105
+ continue;
106
+ }
107
+
108
+ std::string str;
109
+ if (is_utf8) {
110
+ uint8_t len1 = data_[str_pos];
111
+ str_pos++;
112
+ if (len1 & 0x80) str_pos++;
113
+
114
+ uint8_t len2 = data_[str_pos];
115
+ str_pos++;
116
+ if (len2 & 0x80) {
117
+ len2 = ((len2 & 0x7F) << 8) | data_[str_pos];
118
+ str_pos++;
119
+ }
120
+
121
+ if (str_pos + len2 <= data_.size()) {
122
+ str = std::string(reinterpret_cast<const char*>(&data_[str_pos]), len2);
123
+ }
124
+ } else {
125
+ uint16_t len = read_le<uint16_t>(&data_[str_pos]);
126
+ str_pos += 2;
127
+ if (len & 0x8000) {
128
+ len = ((len & 0x7FFF) << 16) | read_le<uint16_t>(&data_[str_pos]);
129
+ str_pos += 2;
130
+ }
131
+
132
+ for (uint16_t j = 0; j < len && str_pos + 2 <= data_.size(); j++) {
133
+ uint16_t ch = read_le<uint16_t>(&data_[str_pos]);
134
+ str_pos += 2;
135
+ if (ch < 0x80) {
136
+ str += static_cast<char>(ch);
137
+ } else if (ch < 0x800) {
138
+ str += static_cast<char>(0xC0 | (ch >> 6));
139
+ str += static_cast<char>(0x80 | (ch & 0x3F));
140
+ } else {
141
+ str += static_cast<char>(0xE0 | (ch >> 12));
142
+ str += static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
143
+ str += static_cast<char>(0x80 | (ch & 0x3F));
144
+ }
145
+ }
146
+ }
147
+
148
+ string_pool_.push_back(str);
149
+ }
150
+
151
+ return true;
152
+ }
153
+
154
+ bool AxmlParser::parse_resource_map(size_t& offset) {
155
+ return true;
156
+ }
157
+
158
+ bool AxmlParser::parse_elements(size_t& offset) {
159
+ std::vector<Element*> element_stack;
160
+
161
+ size_t pos = 8;
162
+
163
+ while (pos < data_.size()) {
164
+ if (pos + 8 > data_.size()) break;
165
+
166
+ uint16_t chunk_type = read_le<uint16_t>(&data_[pos]);
167
+ uint16_t chunk_header_size = read_le<uint16_t>(&data_[pos + 2]);
168
+ uint32_t chunk_size = read_le<uint32_t>(&data_[pos + 4]);
169
+
170
+ if (chunk_size == 0 || pos + chunk_size > data_.size()) break;
171
+
172
+ if (chunk_type == RES_XML_START_ELEMENT_TYPE) {
173
+ if (pos + 28 > data_.size()) break;
174
+
175
+ uint32_t ns_idx = read_le<uint32_t>(&data_[pos + 16]);
176
+ uint32_t name_idx = read_le<uint32_t>(&data_[pos + 20]);
177
+ uint16_t attr_start = read_le<uint16_t>(&data_[pos + 24]);
178
+ uint16_t attr_size = read_le<uint16_t>(&data_[pos + 26]);
179
+ uint16_t attr_count = read_le<uint16_t>(&data_[pos + 28]);
180
+
181
+ Element elem;
182
+ if (ns_idx != 0xFFFFFFFF && ns_idx < string_pool_.size()) {
183
+ elem.namespace_uri = string_pool_[ns_idx];
184
+ }
185
+ if (name_idx < string_pool_.size()) {
186
+ elem.name = string_pool_[name_idx];
187
+ }
188
+
189
+ // Attributes start after: chunk header (16) + attr_start offset
190
+ size_t attr_pos = pos + 16 + attr_start;
191
+ for (uint16_t i = 0; i < attr_count && attr_pos + 20 <= data_.size(); i++) {
192
+ Attribute attr;
193
+
194
+ uint32_t attr_ns = read_le<uint32_t>(&data_[attr_pos]);
195
+ uint32_t attr_name = read_le<uint32_t>(&data_[attr_pos + 4]);
196
+ uint32_t attr_raw = read_le<uint32_t>(&data_[attr_pos + 8]);
197
+ uint16_t attr_type = read_le<uint16_t>(&data_[attr_pos + 14]);
198
+ uint32_t attr_data = read_le<uint32_t>(&data_[attr_pos + 16]);
199
+
200
+ if (attr_ns != 0xFFFFFFFF && attr_ns < string_pool_.size()) {
201
+ attr.namespace_uri = string_pool_[attr_ns];
202
+ }
203
+ if (attr_name < string_pool_.size()) {
204
+ attr.name = string_pool_[attr_name];
205
+ }
206
+
207
+ attr.type = attr_type >> 8;
208
+ attr.data = attr_data;
209
+
210
+ if (attr_raw != 0xFFFFFFFF && attr_raw < string_pool_.size()) {
211
+ attr.value = string_pool_[attr_raw];
212
+ } else {
213
+ switch (attr.type) {
214
+ case ResourceValueType::TYPE_STRING:
215
+ if (attr_data < string_pool_.size()) {
216
+ attr.value = string_pool_[attr_data];
217
+ }
218
+ break;
219
+ case ResourceValueType::TYPE_INT_DEC:
220
+ attr.value = std::to_string(static_cast<int32_t>(attr_data));
221
+ break;
222
+ case ResourceValueType::TYPE_INT_HEX: {
223
+ std::ostringstream ss;
224
+ ss << "0x" << std::hex << attr_data;
225
+ attr.value = ss.str();
226
+ break;
227
+ }
228
+ case ResourceValueType::TYPE_INT_BOOLEAN:
229
+ attr.value = attr_data ? "true" : "false";
230
+ break;
231
+ case ResourceValueType::TYPE_REFERENCE: {
232
+ std::ostringstream ss;
233
+ ss << "@0x" << std::hex << attr_data;
234
+ attr.value = ss.str();
235
+ break;
236
+ }
237
+ case ResourceValueType::TYPE_ATTRIBUTE: {
238
+ std::ostringstream ss;
239
+ ss << "?0x" << std::hex << attr_data;
240
+ attr.value = ss.str();
241
+ break;
242
+ }
243
+ case ResourceValueType::TYPE_DIMENSION:
244
+ attr.value = parse_complex_value(attr_data, false);
245
+ break;
246
+ case ResourceValueType::TYPE_FRACTION:
247
+ attr.value = parse_complex_value(attr_data, true);
248
+ break;
249
+ case ResourceValueType::TYPE_FLOAT: {
250
+ float f;
251
+ std::memcpy(&f, &attr_data, sizeof(f));
252
+ attr.value = std::to_string(f);
253
+ break;
254
+ }
255
+ case ResourceValueType::TYPE_INT_COLOR_ARGB8:
256
+ case ResourceValueType::TYPE_INT_COLOR_RGB8:
257
+ case ResourceValueType::TYPE_INT_COLOR_ARGB4:
258
+ case ResourceValueType::TYPE_INT_COLOR_RGB4:
259
+ attr.value = format_color(attr_data, attr.type);
260
+ break;
261
+ default:
262
+ attr.value = std::to_string(attr_data);
263
+ break;
264
+ }
265
+ }
266
+
267
+ elem.attributes.push_back(attr);
268
+ attr_pos += attr_size > 0 ? attr_size : 20;
269
+ }
270
+
271
+ if (element_stack.empty()) {
272
+ root_ = elem;
273
+ element_stack.push_back(&root_);
274
+ } else {
275
+ element_stack.back()->children.push_back(elem);
276
+ element_stack.push_back(&element_stack.back()->children.back());
277
+ }
278
+ } else if (chunk_type == RES_XML_END_ELEMENT_TYPE) {
279
+ if (!element_stack.empty()) {
280
+ element_stack.pop_back();
281
+ }
282
+ }
283
+
284
+ pos += chunk_size;
285
+ }
286
+
287
+ return true;
288
+ }
289
+
290
+ std::string AxmlParser::to_xml(int indent) const {
291
+ return element_to_xml(root_, indent);
292
+ }
293
+
294
+ std::string AxmlParser::element_to_xml(const Element& elem, int indent) const {
295
+ std::stringstream ss;
296
+ std::string ind(indent * 2, ' ');
297
+
298
+ ss << ind << "<" << elem.name;
299
+
300
+ for (const auto& attr : elem.attributes) {
301
+ ss << " ";
302
+ if (!attr.namespace_uri.empty()) {
303
+ size_t pos = attr.namespace_uri.rfind('/');
304
+ if (pos != std::string::npos) {
305
+ ss << attr.namespace_uri.substr(pos + 1) << ":";
306
+ }
307
+ }
308
+ ss << attr.name << "=\"" << attr.value << "\"";
309
+ }
310
+
311
+ if (elem.children.empty() && elem.text.empty()) {
312
+ ss << "/>\n";
313
+ } else {
314
+ ss << ">\n";
315
+
316
+ for (const auto& child : elem.children) {
317
+ ss << element_to_xml(child, indent + 1);
318
+ }
319
+
320
+ if (!elem.text.empty()) {
321
+ ss << ind << " " << elem.text << "\n";
322
+ }
323
+
324
+ ss << ind << "</" << elem.name << ">\n";
325
+ }
326
+
327
+ return ss.str();
328
+ }
329
+
330
+ std::string AxmlParser::get_attribute_value(const Element& elem, const std::string& name) const {
331
+ for (const auto& attr : elem.attributes) {
332
+ if (attr.name == name) {
333
+ return attr.value;
334
+ }
335
+ }
336
+ return "";
337
+ }
338
+
339
+ std::string AxmlParser::get_package_name() const {
340
+ return get_attribute_value(root_, "package");
341
+ }
342
+
343
+ std::string AxmlParser::get_version_name() const {
344
+ return get_attribute_value(root_, "versionName");
345
+ }
346
+
347
+ int AxmlParser::get_version_code() const {
348
+ std::string val = get_attribute_value(root_, "versionCode");
349
+ return val.empty() ? 0 : std::stoi(val);
350
+ }
351
+
352
+ std::string AxmlParser::get_min_sdk() const {
353
+ for (const auto& child : root_.children) {
354
+ if (child.name == "uses-sdk") {
355
+ return get_attribute_value(child, "minSdkVersion");
356
+ }
357
+ }
358
+ return "";
359
+ }
360
+
361
+ std::string AxmlParser::get_target_sdk() const {
362
+ for (const auto& child : root_.children) {
363
+ if (child.name == "uses-sdk") {
364
+ return get_attribute_value(child, "targetSdkVersion");
365
+ }
366
+ }
367
+ return "";
368
+ }
369
+
370
+ std::vector<std::string> AxmlParser::get_permissions() const {
371
+ std::vector<std::string> perms;
372
+ for (const auto& child : root_.children) {
373
+ if (child.name == "uses-permission") {
374
+ std::string name = get_attribute_value(child, "name");
375
+ if (!name.empty()) {
376
+ perms.push_back(name);
377
+ }
378
+ }
379
+ }
380
+ return perms;
381
+ }
382
+
383
+ std::vector<std::string> AxmlParser::get_activities() const {
384
+ std::vector<std::string> activities;
385
+ for (const auto& child : root_.children) {
386
+ if (child.name == "application") {
387
+ for (const auto& app_child : child.children) {
388
+ if (app_child.name == "activity") {
389
+ std::string name = get_attribute_value(app_child, "name");
390
+ if (!name.empty()) {
391
+ activities.push_back(name);
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
397
+ return activities;
398
+ }
399
+
400
+ std::vector<std::string> AxmlParser::get_services() const {
401
+ std::vector<std::string> services;
402
+ for (const auto& child : root_.children) {
403
+ if (child.name == "application") {
404
+ for (const auto& app_child : child.children) {
405
+ if (app_child.name == "service") {
406
+ std::string name = get_attribute_value(app_child, "name");
407
+ if (!name.empty()) {
408
+ services.push_back(name);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ return services;
415
+ }
416
+
417
+ std::vector<std::string> AxmlParser::get_receivers() const {
418
+ std::vector<std::string> receivers;
419
+ for (const auto& child : root_.children) {
420
+ if (child.name == "application") {
421
+ for (const auto& app_child : child.children) {
422
+ if (app_child.name == "receiver") {
423
+ std::string name = get_attribute_value(app_child, "name");
424
+ if (!name.empty()) {
425
+ receivers.push_back(name);
426
+ }
427
+ }
428
+ }
429
+ }
430
+ }
431
+ return receivers;
432
+ }
433
+
434
+ std::string AxmlParser::get_info() const {
435
+ std::stringstream ss;
436
+
437
+ ss << "AndroidManifest Info:\n";
438
+ ss << " Package: " << get_package_name() << "\n";
439
+ ss << " Version Name: " << get_version_name() << "\n";
440
+ ss << " Version Code: " << get_version_code() << "\n";
441
+ ss << " Min SDK: " << get_min_sdk() << "\n";
442
+ ss << " Target SDK: " << get_target_sdk() << "\n";
443
+
444
+ auto perms = get_permissions();
445
+ ss << " Permissions: " << perms.size() << "\n";
446
+ for (const auto& p : perms) {
447
+ ss << " - " << p << "\n";
448
+ }
449
+
450
+ auto activities = get_activities();
451
+ ss << " Activities: " << activities.size() << "\n";
452
+
453
+ auto services = get_services();
454
+ ss << " Services: " << services.size() << "\n";
455
+
456
+ auto receivers = get_receivers();
457
+ ss << " Receivers: " << receivers.size() << "\n";
458
+
459
+ return ss.str();
460
+ }
461
+
462
+ bool AxmlEditor::load(const std::vector<uint8_t>& data) {
463
+ data_ = data;
464
+ return parse_internal();
465
+ }
466
+
467
+ bool AxmlEditor::parse_internal() {
468
+ if (data_.size() < 8) return false;
469
+
470
+ uint16_t type = read_le<uint16_t>(&data_[0]);
471
+ if (type != 0x0003) return false;
472
+
473
+ size_t offset = 8;
474
+ string_pool_.clear();
475
+
476
+ while (offset < data_.size()) {
477
+ if (offset + 8 > data_.size()) break;
478
+
479
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
480
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
481
+
482
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
483
+
484
+ if (chunk_type == 0x0001) {
485
+ chunk_info_.string_pool_offset = offset;
486
+ chunk_info_.string_pool_size = chunk_size;
487
+
488
+ uint32_t string_count = read_le<uint32_t>(&data_[offset + 8]);
489
+ uint32_t flags = read_le<uint32_t>(&data_[offset + 16]);
490
+ uint32_t strings_start = read_le<uint32_t>(&data_[offset + 20]);
491
+ bool is_utf8 = (flags & (1 << 8)) != 0;
492
+
493
+ size_t offsets_start = offset + 28;
494
+
495
+ for (uint32_t i = 0; i < string_count; i++) {
496
+ uint32_t str_offset = read_le<uint32_t>(&data_[offsets_start + i * 4]);
497
+ size_t str_pos = offset + strings_start + str_offset;
498
+
499
+ std::string str;
500
+ if (str_pos < data_.size()) {
501
+ if (is_utf8) {
502
+ str_pos++;
503
+ if (str_pos < data_.size() && (data_[str_pos - 1] & 0x80)) str_pos++;
504
+ uint8_t len = data_[str_pos++];
505
+ if (len & 0x80) {
506
+ len = ((len & 0x7F) << 8) | data_[str_pos++];
507
+ }
508
+ if (str_pos + len <= data_.size()) {
509
+ str = std::string(reinterpret_cast<const char*>(&data_[str_pos]), len);
510
+ }
511
+ } else {
512
+ uint16_t len = read_le<uint16_t>(&data_[str_pos]);
513
+ str_pos += 2;
514
+ for (uint16_t j = 0; j < len && str_pos + 2 <= data_.size(); j++) {
515
+ uint16_t ch = read_le<uint16_t>(&data_[str_pos]);
516
+ str_pos += 2;
517
+ if (ch < 0x80) str += static_cast<char>(ch);
518
+ else if (ch < 0x800) {
519
+ str += static_cast<char>(0xC0 | (ch >> 6));
520
+ str += static_cast<char>(0x80 | (ch & 0x3F));
521
+ } else {
522
+ str += static_cast<char>(0xE0 | (ch >> 12));
523
+ str += static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
524
+ str += static_cast<char>(0x80 | (ch & 0x3F));
525
+ }
526
+ }
527
+ }
528
+ }
529
+ string_pool_.push_back(str);
530
+ }
531
+ } else if (chunk_type == 0x0180) {
532
+ chunk_info_.resource_map_offset = offset;
533
+ chunk_info_.resource_map_size = chunk_size;
534
+ // 解析资源ID映射表
535
+ resource_ids_.clear();
536
+ size_t res_count = (chunk_size - 8) / 4;
537
+ for (size_t i = 0; i < res_count && offset + 8 + i * 4 + 4 <= data_.size(); i++) {
538
+ uint32_t res_id = read_le<uint32_t>(&data_[offset + 8 + i * 4]);
539
+ resource_ids_.push_back(res_id);
540
+ }
541
+ } else if (chunk_type == 0x0102) {
542
+ chunk_info_.xml_content_offset = offset;
543
+ break;
544
+ }
545
+
546
+ offset += chunk_size;
547
+ }
548
+
549
+ AxmlParser parser;
550
+ if (parser.parse(data_)) {
551
+ root_ = parser.root();
552
+ return true;
553
+ }
554
+ return false;
555
+ }
556
+
557
+ std::vector<uint8_t> AxmlEditor::save() {
558
+ rebuild_binary();
559
+ return data_;
560
+ }
561
+
562
+ void AxmlEditor::search_element(const Element& elem, const std::string& path, int& index,
563
+ const std::string& attr_name, const std::string& value_pattern,
564
+ std::vector<SearchResult>& results) const {
565
+ std::string current_path = path.empty() ? elem.name : path + "/" + elem.name;
566
+
567
+ for (const auto& attr : elem.attributes) {
568
+ bool match = false;
569
+ if (!attr_name.empty() && !value_pattern.empty()) {
570
+ match = (attr.name.find(attr_name) != std::string::npos) &&
571
+ (attr.value.find(value_pattern) != std::string::npos);
572
+ } else if (!attr_name.empty()) {
573
+ match = attr.name.find(attr_name) != std::string::npos;
574
+ } else if (!value_pattern.empty()) {
575
+ match = attr.value.find(value_pattern) != std::string::npos;
576
+ }
577
+
578
+ if (match) {
579
+ SearchResult r;
580
+ r.element_path = current_path;
581
+ r.element_name = elem.name;
582
+ r.attribute_name = attr.name;
583
+ r.attribute_value = attr.value;
584
+ r.element_index = index;
585
+ results.push_back(r);
586
+ }
587
+ }
588
+
589
+ index++;
590
+
591
+ for (const auto& child : elem.children) {
592
+ search_element(child, current_path, index, attr_name, value_pattern, results);
593
+ }
594
+ }
595
+
596
+ std::vector<SearchResult> AxmlEditor::search_by_attribute(const std::string& attr_name, const std::string& value_pattern) const {
597
+ std::vector<SearchResult> results;
598
+ int index = 0;
599
+ search_element(root_, "", index, attr_name, value_pattern, results);
600
+ return results;
601
+ }
602
+
603
+ std::vector<SearchResult> AxmlEditor::search_by_element(const std::string& element_name) const {
604
+ std::vector<SearchResult> results;
605
+
606
+ std::function<void(const Element&, const std::string&, int&)> search_fn;
607
+ search_fn = [&](const Element& elem, const std::string& path, int& index) {
608
+ std::string current_path = path.empty() ? elem.name : path + "/" + elem.name;
609
+
610
+ if (elem.name.find(element_name) != std::string::npos) {
611
+ for (const auto& attr : elem.attributes) {
612
+ SearchResult r;
613
+ r.element_path = current_path;
614
+ r.element_name = elem.name;
615
+ r.attribute_name = attr.name;
616
+ r.attribute_value = attr.value;
617
+ r.element_index = index;
618
+ results.push_back(r);
619
+ }
620
+ }
621
+
622
+ index++;
623
+ for (const auto& child : elem.children) {
624
+ search_fn(child, current_path, index);
625
+ }
626
+ };
627
+
628
+ int index = 0;
629
+ search_fn(root_, "", index);
630
+ return results;
631
+ }
632
+
633
+ std::vector<SearchResult> AxmlEditor::search_by_value(const std::string& value_pattern) const {
634
+ return search_by_attribute("", value_pattern);
635
+ }
636
+
637
+ bool AxmlEditor::set_attribute(const std::string& element_path, const std::string& attr_name, const std::string& new_value) {
638
+ // 智能解析 new_value 的类型
639
+ bool is_int = false;
640
+ int32_t int_value = 0;
641
+ bool is_bool = false;
642
+ bool bool_value = false;
643
+ bool is_color = false;
644
+ uint32_t color_data = 0;
645
+ uint8_t color_type = 0;
646
+ bool is_dimension = false;
647
+ bool is_fraction = false;
648
+ uint32_t complex_data = 0;
649
+
650
+ // 检查布尔值
651
+ if (new_value == "true" || new_value == "false") {
652
+ is_bool = true;
653
+ bool_value = (new_value == "true");
654
+ }
655
+ // 检查颜色值 #RRGGBB 或 #AARRGGBB
656
+ else if (parse_color_string(new_value, color_data, color_type)) {
657
+ is_color = true;
658
+ }
659
+ // 检查尺寸值 (dp, sp, px, pt, in, mm)
660
+ else if (encode_complex_value(new_value, complex_data, is_dimension)) {
661
+ is_fraction = !is_dimension;
662
+ }
663
+ // 检查整数
664
+ else {
665
+ try {
666
+ size_t pos;
667
+ long long parsed = std::stoll(new_value, &pos);
668
+ if (pos == new_value.length()) {
669
+ is_int = true;
670
+ int_value = static_cast<int32_t>(parsed);
671
+ }
672
+ } catch (...) {
673
+ is_int = false;
674
+ }
675
+ }
676
+
677
+ // 记录原始字符串池大小
678
+ size_t original_pool_size = string_pool_.size();
679
+ int new_string_idx = -1;
680
+
681
+ // 对于字符串类型的值,需要添加到字符串池
682
+ if (!is_int) {
683
+ new_string_idx = find_or_add_string(new_value);
684
+
685
+ // 如果添加了新字符串,需要重建字符串池
686
+ bool need_rebuild = (string_pool_.size() > original_pool_size);
687
+ if (need_rebuild) {
688
+ rebuild_binary();
689
+ }
690
+ }
691
+
692
+ size_t offset = chunk_info_.xml_content_offset;
693
+
694
+ while (offset < data_.size()) {
695
+ if (offset + 8 > data_.size()) break;
696
+
697
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
698
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
699
+
700
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
701
+
702
+ if (chunk_type == 0x0102) {
703
+ uint32_t name_idx = read_le<uint32_t>(&data_[offset + 20]);
704
+ std::string elem_name = (name_idx < string_pool_.size()) ? string_pool_[name_idx] : "";
705
+
706
+ // 元素匹配:精确匹配或路径包含元素名(元素名不能为空)
707
+ bool elem_match = element_path.empty() ||
708
+ (elem_name == element_path) ||
709
+ (!elem_name.empty() && element_path.find(elem_name) != std::string::npos);
710
+
711
+ if (elem_match) {
712
+ uint16_t attr_count = read_le<uint16_t>(&data_[offset + 28]);
713
+ uint16_t attr_start = read_le<uint16_t>(&data_[offset + 24]);
714
+ uint16_t attr_size = 20;
715
+
716
+ // Attributes start after: chunk header (16) + attr_start offset
717
+ size_t attr_pos = offset + 16 + attr_start;
718
+ for (uint16_t i = 0; i < attr_count && attr_pos + 20 <= data_.size(); i++) {
719
+ uint32_t attr_name_idx = read_le<uint32_t>(&data_[attr_pos + 4]);
720
+ std::string current_attr_name = (attr_name_idx < string_pool_.size()) ? string_pool_[attr_name_idx] : "";
721
+
722
+ // 尝试通过资源ID映射获取属性名
723
+ std::string res_attr_name;
724
+ if (attr_name_idx < resource_ids_.size()) {
725
+ const char* res_name = get_android_attr_name(resource_ids_[attr_name_idx]);
726
+ if (res_name) {
727
+ res_attr_name = res_name;
728
+ }
729
+ }
730
+
731
+ // 匹配:字符串池名称或资源ID映射名称
732
+ bool name_match = (current_attr_name == attr_name) ||
733
+ (!res_attr_name.empty() && res_attr_name == attr_name);
734
+
735
+ if (name_match) {
736
+ uint16_t attr_type_field = read_le<uint16_t>(&data_[attr_pos + 14]);
737
+ uint8_t attr_type = attr_type_field >> 8;
738
+
739
+ // 根据原始属性类型决定如何修改
740
+ if (attr_type == ResourceValueType::TYPE_STRING) {
741
+ // 字符串类型:修改 rawValue 和 data 为新字符串索引
742
+ if (new_string_idx < 0) {
743
+ new_string_idx = find_or_add_string(new_value);
744
+ if (string_pool_.size() > original_pool_size) {
745
+ rebuild_binary();
746
+ return set_attribute(element_path, attr_name, new_value);
747
+ }
748
+ }
749
+ write_le<uint32_t>(&data_[attr_pos + 8], static_cast<uint32_t>(new_string_idx));
750
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(new_string_idx));
751
+ } else if (attr_type == ResourceValueType::TYPE_INT_DEC || attr_type == ResourceValueType::TYPE_INT_HEX) {
752
+ // 整数类型
753
+ if (is_int) {
754
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
755
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
756
+ } else if (new_value.length() > 2 && (new_value.substr(0, 2) == "0x" || new_value.substr(0, 2) == "0X")) {
757
+ try {
758
+ uint32_t hex_val = std::stoul(new_value, nullptr, 16);
759
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
760
+ write_le<uint32_t>(&data_[attr_pos + 16], hex_val);
761
+ } catch (...) {
762
+ return false;
763
+ }
764
+ } else {
765
+ return false;
766
+ }
767
+ } else if (attr_type == ResourceValueType::TYPE_INT_BOOLEAN) {
768
+ // 布尔类型
769
+ bool bval = (new_value == "true" || new_value == "1" || (is_int && int_value != 0));
770
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
771
+ write_le<uint32_t>(&data_[attr_pos + 16], bval ? 0xFFFFFFFF : 0);
772
+ } else if (attr_type == ResourceValueType::TYPE_REFERENCE || attr_type == ResourceValueType::TYPE_ATTRIBUTE) {
773
+ // 资源引用类型 @resource 或 ?attr
774
+ if (is_int) {
775
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
776
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
777
+ } else if (!new_value.empty() && (new_value[0] == '@' || new_value[0] == '?')) {
778
+ try {
779
+ uint32_t res_id = std::stoul(new_value.substr(1), nullptr, 0);
780
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
781
+ write_le<uint32_t>(&data_[attr_pos + 16], res_id);
782
+ } catch (...) {
783
+ return false;
784
+ }
785
+ } else {
786
+ return false;
787
+ }
788
+ } else if (attr_type == ResourceValueType::TYPE_DIMENSION) {
789
+ // 尺寸类型 (dp, sp, px, pt, in, mm)
790
+ uint32_t dim_data = 0;
791
+ bool is_dim = false;
792
+ if (encode_complex_value(new_value, dim_data, is_dim)) {
793
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
794
+ write_le<uint32_t>(&data_[attr_pos + 16], dim_data);
795
+ } else if (is_int) {
796
+ // 整数作为像素处理
797
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
798
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value) << 8);
799
+ } else {
800
+ return false;
801
+ }
802
+ } else if (attr_type == ResourceValueType::TYPE_FRACTION) {
803
+ // 百分比类型 (%, %p)
804
+ uint32_t frac_data = 0;
805
+ bool is_dim = false;
806
+ if (encode_complex_value(new_value, frac_data, is_dim)) {
807
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
808
+ write_le<uint32_t>(&data_[attr_pos + 16], frac_data);
809
+ } else {
810
+ return false;
811
+ }
812
+ } else if (attr_type >= ResourceValueType::TYPE_INT_COLOR_ARGB8 && attr_type <= ResourceValueType::TYPE_INT_COLOR_RGB4) {
813
+ // 颜色类型
814
+ uint32_t clr_data = 0;
815
+ uint8_t clr_type = 0;
816
+ if (parse_color_string(new_value, clr_data, clr_type)) {
817
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
818
+ write_le<uint32_t>(&data_[attr_pos + 16], clr_data);
819
+ } else if (is_int) {
820
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
821
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
822
+ } else {
823
+ return false;
824
+ }
825
+ } else if (attr_type == ResourceValueType::TYPE_FLOAT) {
826
+ // 浮点类型
827
+ try {
828
+ float fval = std::stof(new_value);
829
+ uint32_t fdata;
830
+ std::memcpy(&fdata, &fval, sizeof(fdata));
831
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
832
+ write_le<uint32_t>(&data_[attr_pos + 16], fdata);
833
+ } catch (...) {
834
+ return false;
835
+ }
836
+ } else {
837
+ // 其他类型:智能处理
838
+ if (is_int) {
839
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
840
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
841
+ } else {
842
+ if (new_string_idx < 0) {
843
+ new_string_idx = find_or_add_string(new_value);
844
+ if (string_pool_.size() > original_pool_size) {
845
+ rebuild_binary();
846
+ return set_attribute(element_path, attr_name, new_value);
847
+ }
848
+ }
849
+ write_le<uint32_t>(&data_[attr_pos + 8], static_cast<uint32_t>(new_string_idx));
850
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(new_string_idx));
851
+ }
852
+ }
853
+
854
+ parse_internal();
855
+ return true;
856
+ }
857
+ attr_pos += attr_size;
858
+ }
859
+ }
860
+ }
861
+
862
+ offset += chunk_size;
863
+ }
864
+
865
+ return false;
866
+ }
867
+
868
+ bool AxmlEditor::set_attribute_by_index(int element_index, const std::string& attr_name, const std::string& new_value) {
869
+ // 智能解析 new_value 的类型
870
+ bool is_int = false;
871
+ int32_t int_value = 0;
872
+
873
+ // 检查整数
874
+ try {
875
+ size_t pos;
876
+ long long parsed = std::stoll(new_value, &pos);
877
+ if (pos == new_value.length()) {
878
+ is_int = true;
879
+ int_value = static_cast<int32_t>(parsed);
880
+ }
881
+ } catch (...) {
882
+ is_int = false;
883
+ }
884
+
885
+ // 记录原始字符串池大小
886
+ size_t original_pool_size = string_pool_.size();
887
+ int new_string_idx = -1;
888
+
889
+ // 对于纯字符串类型的值,需要添加到字符串池
890
+ if (!is_int) {
891
+ new_string_idx = find_or_add_string(new_value);
892
+
893
+ // 如果添加了新字符串,需要重建字符串池
894
+ bool need_rebuild = (string_pool_.size() > original_pool_size);
895
+ if (need_rebuild) {
896
+ rebuild_binary();
897
+ }
898
+ }
899
+
900
+ int current_index = 0;
901
+ size_t offset = chunk_info_.xml_content_offset;
902
+
903
+ while (offset < data_.size()) {
904
+ if (offset + 8 > data_.size()) break;
905
+
906
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
907
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
908
+
909
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
910
+
911
+ if (chunk_type == 0x0102) {
912
+ if (current_index == element_index) {
913
+ uint16_t attr_count = read_le<uint16_t>(&data_[offset + 28]);
914
+ uint16_t attr_start = read_le<uint16_t>(&data_[offset + 24]);
915
+ uint16_t attr_size = 20;
916
+
917
+ size_t attr_pos = offset + 16 + attr_start;
918
+ for (uint16_t i = 0; i < attr_count && attr_pos + 20 <= data_.size(); i++) {
919
+ uint32_t attr_name_idx = read_le<uint32_t>(&data_[attr_pos + 4]);
920
+ std::string current_attr_name = (attr_name_idx < string_pool_.size()) ? string_pool_[attr_name_idx] : "";
921
+
922
+ // 尝试通过资源ID映射获取属性名
923
+ std::string res_attr_name;
924
+ if (attr_name_idx < resource_ids_.size()) {
925
+ const char* res_name = get_android_attr_name(resource_ids_[attr_name_idx]);
926
+ if (res_name) {
927
+ res_attr_name = res_name;
928
+ }
929
+ }
930
+
931
+ // 匹配:字符串池名称或资源ID映射名称
932
+ bool name_match = (current_attr_name == attr_name) ||
933
+ (!res_attr_name.empty() && res_attr_name == attr_name);
934
+
935
+ if (name_match) {
936
+ uint16_t attr_type_field = read_le<uint16_t>(&data_[attr_pos + 14]);
937
+ uint8_t attr_type = attr_type_field >> 8;
938
+
939
+ // 根据原始属性类型决定如何修改
940
+ if (attr_type == ResourceValueType::TYPE_STRING) {
941
+ if (new_string_idx < 0) {
942
+ new_string_idx = find_or_add_string(new_value);
943
+ if (string_pool_.size() > original_pool_size) {
944
+ rebuild_binary();
945
+ return set_attribute_by_index(element_index, attr_name, new_value);
946
+ }
947
+ }
948
+ write_le<uint32_t>(&data_[attr_pos + 8], static_cast<uint32_t>(new_string_idx));
949
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(new_string_idx));
950
+ } else if (attr_type == ResourceValueType::TYPE_INT_DEC || attr_type == ResourceValueType::TYPE_INT_HEX) {
951
+ if (is_int) {
952
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
953
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
954
+ } else if (new_value.length() > 2 && (new_value.substr(0, 2) == "0x" || new_value.substr(0, 2) == "0X")) {
955
+ try {
956
+ uint32_t hex_val = std::stoul(new_value, nullptr, 16);
957
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
958
+ write_le<uint32_t>(&data_[attr_pos + 16], hex_val);
959
+ } catch (...) {
960
+ return false;
961
+ }
962
+ } else {
963
+ return false;
964
+ }
965
+ } else if (attr_type == ResourceValueType::TYPE_INT_BOOLEAN) {
966
+ bool bval = (new_value == "true" || new_value == "1" || (is_int && int_value != 0));
967
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
968
+ write_le<uint32_t>(&data_[attr_pos + 16], bval ? 0xFFFFFFFF : 0);
969
+ } else if (attr_type == ResourceValueType::TYPE_REFERENCE || attr_type == ResourceValueType::TYPE_ATTRIBUTE) {
970
+ if (is_int) {
971
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
972
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
973
+ } else if (!new_value.empty() && (new_value[0] == '@' || new_value[0] == '?')) {
974
+ try {
975
+ uint32_t res_id = std::stoul(new_value.substr(1), nullptr, 0);
976
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
977
+ write_le<uint32_t>(&data_[attr_pos + 16], res_id);
978
+ } catch (...) {
979
+ return false;
980
+ }
981
+ } else {
982
+ return false;
983
+ }
984
+ } else if (attr_type == ResourceValueType::TYPE_DIMENSION) {
985
+ uint32_t dim_data = 0;
986
+ bool is_dim = false;
987
+ if (encode_complex_value(new_value, dim_data, is_dim)) {
988
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
989
+ write_le<uint32_t>(&data_[attr_pos + 16], dim_data);
990
+ } else if (is_int) {
991
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
992
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value) << 8);
993
+ } else {
994
+ return false;
995
+ }
996
+ } else if (attr_type == ResourceValueType::TYPE_FRACTION) {
997
+ uint32_t frac_data = 0;
998
+ bool is_dim = false;
999
+ if (encode_complex_value(new_value, frac_data, is_dim)) {
1000
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
1001
+ write_le<uint32_t>(&data_[attr_pos + 16], frac_data);
1002
+ } else {
1003
+ return false;
1004
+ }
1005
+ } else if (attr_type >= ResourceValueType::TYPE_INT_COLOR_ARGB8 && attr_type <= ResourceValueType::TYPE_INT_COLOR_RGB4) {
1006
+ uint32_t clr_data = 0;
1007
+ uint8_t clr_type = 0;
1008
+ if (parse_color_string(new_value, clr_data, clr_type)) {
1009
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
1010
+ write_le<uint32_t>(&data_[attr_pos + 16], clr_data);
1011
+ } else if (is_int) {
1012
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
1013
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
1014
+ } else {
1015
+ return false;
1016
+ }
1017
+ } else if (attr_type == ResourceValueType::TYPE_FLOAT) {
1018
+ try {
1019
+ float fval = std::stof(new_value);
1020
+ uint32_t fdata;
1021
+ std::memcpy(&fdata, &fval, sizeof(fdata));
1022
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
1023
+ write_le<uint32_t>(&data_[attr_pos + 16], fdata);
1024
+ } catch (...) {
1025
+ return false;
1026
+ }
1027
+ } else {
1028
+ if (is_int) {
1029
+ write_le<uint32_t>(&data_[attr_pos + 8], 0xFFFFFFFF);
1030
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(int_value));
1031
+ } else {
1032
+ if (new_string_idx < 0) {
1033
+ new_string_idx = find_or_add_string(new_value);
1034
+ if (string_pool_.size() > original_pool_size) {
1035
+ rebuild_binary();
1036
+ return set_attribute_by_index(element_index, attr_name, new_value);
1037
+ }
1038
+ }
1039
+ write_le<uint32_t>(&data_[attr_pos + 8], static_cast<uint32_t>(new_string_idx));
1040
+ write_le<uint32_t>(&data_[attr_pos + 16], static_cast<uint32_t>(new_string_idx));
1041
+ }
1042
+ }
1043
+
1044
+ parse_internal();
1045
+ return true;
1046
+ }
1047
+ attr_pos += attr_size;
1048
+ }
1049
+ }
1050
+ current_index++;
1051
+ }
1052
+
1053
+ offset += chunk_size;
1054
+ }
1055
+
1056
+ return false;
1057
+ }
1058
+
1059
+ bool AxmlEditor::set_package_name(const std::string& name) {
1060
+ return set_attribute("manifest", "package", name);
1061
+ }
1062
+
1063
+ bool AxmlEditor::set_version_name(const std::string& name) {
1064
+ return set_attribute("manifest", "versionName", name);
1065
+ }
1066
+
1067
+ bool AxmlEditor::set_version_code(int code) {
1068
+ return set_attribute("manifest", "versionCode", std::to_string(code));
1069
+ }
1070
+
1071
+ bool AxmlEditor::set_min_sdk(int sdk) {
1072
+ // 先搜索uses-sdk元素的索引
1073
+ auto results = search_by_attribute("minSdkVersion", "");
1074
+ for (const auto& r : results) {
1075
+ if (r.element_name == "uses-sdk") {
1076
+ return set_attribute_by_index(r.element_index, "minSdkVersion", std::to_string(sdk));
1077
+ }
1078
+ }
1079
+ return set_attribute("uses-sdk", "minSdkVersion", std::to_string(sdk));
1080
+ }
1081
+
1082
+ bool AxmlEditor::set_target_sdk(int sdk) {
1083
+ // 先搜索uses-sdk元素的索引
1084
+ auto results = search_by_attribute("targetSdkVersion", "");
1085
+ for (const auto& r : results) {
1086
+ if (r.element_name == "uses-sdk") {
1087
+ return set_attribute_by_index(r.element_index, "targetSdkVersion", std::to_string(sdk));
1088
+ }
1089
+ }
1090
+ return set_attribute("uses-sdk", "targetSdkVersion", std::to_string(sdk));
1091
+ }
1092
+
1093
+ bool AxmlEditor::add_permission(const std::string& permission) {
1094
+ // Android namespace URI
1095
+ const std::string android_ns = "http://schemas.android.com/apk/res/android";
1096
+
1097
+ // Add required strings to string pool
1098
+ int name_attr_idx = find_or_add_string("name");
1099
+ int perm_value_idx = find_or_add_string(permission);
1100
+ int uses_perm_idx = find_or_add_string("uses-permission");
1101
+ int android_ns_idx = find_or_add_string(android_ns);
1102
+
1103
+ // Rebuild string pool after adding new strings
1104
+ rebuild_binary();
1105
+
1106
+ // Find the position right after <manifest> opening tag (after first RES_XML_START_ELEMENT_TYPE)
1107
+ size_t insert_offset = 0;
1108
+ size_t offset = chunk_info_.xml_content_offset;
1109
+ bool found_manifest = false;
1110
+
1111
+ while (offset < data_.size()) {
1112
+ if (offset + 8 > data_.size()) break;
1113
+
1114
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
1115
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
1116
+
1117
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
1118
+
1119
+ if (chunk_type == 0x0102) { // RES_XML_START_ELEMENT_TYPE
1120
+ uint32_t name_idx = read_le<uint32_t>(&data_[offset + 20]);
1121
+ if (name_idx < string_pool_.size() && string_pool_[name_idx] == "manifest") {
1122
+ insert_offset = offset + chunk_size;
1123
+ found_manifest = true;
1124
+ break;
1125
+ }
1126
+ }
1127
+
1128
+ offset += chunk_size;
1129
+ }
1130
+
1131
+ if (!found_manifest) return false;
1132
+
1133
+ // Create uses-permission element
1134
+ // Start element chunk: header(16) + extended(20) + attrs(attr_count * 20)
1135
+ std::vector<uint8_t> start_elem(16 + 20 + 20); // 56 bytes total, 1 attribute
1136
+
1137
+ // Chunk header
1138
+ write_le<uint16_t>(&start_elem[0], 0x0102); // RES_XML_START_ELEMENT_TYPE
1139
+ write_le<uint16_t>(&start_elem[2], 16); // header size
1140
+ write_le<uint32_t>(&start_elem[4], static_cast<uint32_t>(start_elem.size())); // chunk size
1141
+
1142
+ // Extended header
1143
+ write_le<uint32_t>(&start_elem[8], 1); // line number
1144
+ write_le<uint32_t>(&start_elem[12], 0xFFFFFFFF); // comment (none)
1145
+
1146
+ // Element info
1147
+ write_le<uint32_t>(&start_elem[16], 0xFFFFFFFF); // namespace (none)
1148
+ write_le<uint32_t>(&start_elem[20], uses_perm_idx); // name
1149
+ write_le<uint16_t>(&start_elem[24], 0x14); // attribute start (20 bytes after element start)
1150
+ write_le<uint16_t>(&start_elem[26], 0x14); // attribute size (20 bytes per attr)
1151
+ write_le<uint16_t>(&start_elem[28], 1); // attribute count
1152
+ write_le<uint16_t>(&start_elem[30], 0); // id index
1153
+ write_le<uint16_t>(&start_elem[32], 0); // class index
1154
+ write_le<uint16_t>(&start_elem[34], 0); // style index
1155
+
1156
+ // Attribute: android:name="permission"
1157
+ size_t attr_offset = 36;
1158
+ write_le<uint32_t>(&start_elem[attr_offset + 0], android_ns_idx); // namespace
1159
+ write_le<uint32_t>(&start_elem[attr_offset + 4], name_attr_idx); // name (index of "name")
1160
+ write_le<uint32_t>(&start_elem[attr_offset + 8], perm_value_idx); // rawValue (string index)
1161
+ write_le<uint16_t>(&start_elem[attr_offset + 12], 8); // size
1162
+ write_le<uint8_t>(&start_elem[attr_offset + 14], 0); // res0
1163
+ write_le<uint8_t>(&start_elem[attr_offset + 15], 0x03); // dataType: TYPE_STRING
1164
+ write_le<uint32_t>(&start_elem[attr_offset + 16], perm_value_idx); // data (string index)
1165
+
1166
+ // End element chunk
1167
+ std::vector<uint8_t> end_elem(24);
1168
+ write_le<uint16_t>(&end_elem[0], 0x0103); // RES_XML_END_ELEMENT_TYPE
1169
+ write_le<uint16_t>(&end_elem[2], 16); // header size
1170
+ write_le<uint32_t>(&end_elem[4], 24); // chunk size
1171
+ write_le<uint32_t>(&end_elem[8], 1); // line number
1172
+ write_le<uint32_t>(&end_elem[12], 0xFFFFFFFF); // comment
1173
+ write_le<uint32_t>(&end_elem[16], 0xFFFFFFFF); // namespace (none)
1174
+ write_le<uint32_t>(&end_elem[20], uses_perm_idx); // name
1175
+
1176
+ // Insert both chunks
1177
+ std::vector<uint8_t> new_data;
1178
+ new_data.reserve(data_.size() + start_elem.size() + end_elem.size());
1179
+
1180
+ new_data.insert(new_data.end(), data_.begin(), data_.begin() + insert_offset);
1181
+ new_data.insert(new_data.end(), start_elem.begin(), start_elem.end());
1182
+ new_data.insert(new_data.end(), end_elem.begin(), end_elem.end());
1183
+ new_data.insert(new_data.end(), data_.begin() + insert_offset, data_.end());
1184
+
1185
+ // Update file size in header
1186
+ uint32_t new_file_size = static_cast<uint32_t>(new_data.size());
1187
+ write_le<uint32_t>(&new_data[4], new_file_size);
1188
+
1189
+ data_ = std::move(new_data);
1190
+
1191
+ // Re-parse to update internal state
1192
+ parse_internal();
1193
+
1194
+ return true;
1195
+ }
1196
+
1197
+ bool AxmlEditor::remove_permission(const std::string& permission) {
1198
+ size_t offset = chunk_info_.xml_content_offset;
1199
+ size_t perm_start = 0;
1200
+ size_t perm_end = 0;
1201
+ bool found = false;
1202
+
1203
+ while (offset < data_.size()) {
1204
+ if (offset + 8 > data_.size()) break;
1205
+
1206
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
1207
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
1208
+
1209
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
1210
+
1211
+ if (chunk_type == 0x0102) { // RES_XML_START_ELEMENT_TYPE
1212
+ uint32_t name_idx = read_le<uint32_t>(&data_[offset + 20]);
1213
+ if (name_idx < string_pool_.size() && string_pool_[name_idx] == "uses-permission") {
1214
+ // Check if this is the permission we're looking for
1215
+ uint16_t attr_count = read_le<uint16_t>(&data_[offset + 28]);
1216
+ uint16_t attr_start = read_le<uint16_t>(&data_[offset + 24]);
1217
+
1218
+ // Attributes start after: chunk header (16) + element info start + attr_start offset
1219
+ size_t attr_pos = offset + 16 + attr_start;
1220
+ for (uint16_t i = 0; i < attr_count && attr_pos + 20 <= data_.size(); i++) {
1221
+ uint32_t attr_name_idx = read_le<uint32_t>(&data_[attr_pos + 4]);
1222
+ uint32_t attr_value_idx = read_le<uint32_t>(&data_[attr_pos + 8]);
1223
+
1224
+ if (attr_name_idx < string_pool_.size() && string_pool_[attr_name_idx] == "name" &&
1225
+ attr_value_idx < string_pool_.size() && string_pool_[attr_value_idx] == permission) {
1226
+ perm_start = offset;
1227
+ found = true;
1228
+ break;
1229
+ }
1230
+ attr_pos += 20;
1231
+ }
1232
+
1233
+ if (found) {
1234
+ // Find the matching end element
1235
+ size_t search_offset = offset + chunk_size;
1236
+ while (search_offset < data_.size()) {
1237
+ if (search_offset + 8 > data_.size()) break;
1238
+
1239
+ uint16_t search_type = read_le<uint16_t>(&data_[search_offset]);
1240
+ uint32_t search_size = read_le<uint32_t>(&data_[search_offset + 4]);
1241
+
1242
+ if (search_type == 0x0103) { // RES_XML_END_ELEMENT_TYPE
1243
+ uint32_t end_name_idx = read_le<uint32_t>(&data_[search_offset + 20]);
1244
+ if (end_name_idx == name_idx) {
1245
+ perm_end = search_offset + search_size;
1246
+ break;
1247
+ }
1248
+ }
1249
+ search_offset += search_size;
1250
+ }
1251
+ break;
1252
+ }
1253
+ }
1254
+ }
1255
+
1256
+ offset += chunk_size;
1257
+ }
1258
+
1259
+ if (!found || perm_end <= perm_start) return false;
1260
+
1261
+ // Remove the element
1262
+ std::vector<uint8_t> new_data;
1263
+ new_data.reserve(data_.size() - (perm_end - perm_start));
1264
+
1265
+ new_data.insert(new_data.end(), data_.begin(), data_.begin() + perm_start);
1266
+ new_data.insert(new_data.end(), data_.begin() + perm_end, data_.end());
1267
+
1268
+ // Update file size
1269
+ uint32_t new_file_size = static_cast<uint32_t>(new_data.size());
1270
+ write_le<uint32_t>(&new_data[4], new_file_size);
1271
+
1272
+ data_ = std::move(new_data);
1273
+
1274
+ // Re-parse
1275
+ parse_internal();
1276
+
1277
+ return true;
1278
+ }
1279
+
1280
+ bool AxmlEditor::add_activity(const std::string& activity_name, bool exported) {
1281
+ const std::string android_ns = "http://schemas.android.com/apk/res/android";
1282
+
1283
+ // Add required strings
1284
+ int name_attr_idx = find_or_add_string("name");
1285
+ int exported_attr_idx = find_or_add_string("exported");
1286
+ int activity_value_idx = find_or_add_string(activity_name);
1287
+ int activity_tag_idx = find_or_add_string("activity");
1288
+ int application_idx = find_or_add_string("application");
1289
+ int android_ns_idx = find_or_add_string(android_ns);
1290
+
1291
+ // Rebuild string pool
1292
+ rebuild_binary();
1293
+
1294
+ // Find application element's end position (insert before </application>)
1295
+ size_t insert_offset = 0;
1296
+ size_t offset = chunk_info_.xml_content_offset;
1297
+ bool in_application = false;
1298
+ int depth = 0;
1299
+
1300
+ while (offset < data_.size()) {
1301
+ if (offset + 8 > data_.size()) break;
1302
+
1303
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
1304
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
1305
+
1306
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
1307
+
1308
+ if (chunk_type == 0x0102) { // Start element
1309
+ uint32_t name_idx = read_le<uint32_t>(&data_[offset + 20]);
1310
+ if (name_idx < string_pool_.size() && string_pool_[name_idx] == "application") {
1311
+ in_application = true;
1312
+ depth = 1;
1313
+ } else if (in_application) {
1314
+ depth++;
1315
+ }
1316
+ } else if (chunk_type == 0x0103) { // End element
1317
+ if (in_application) {
1318
+ depth--;
1319
+ if (depth == 0) {
1320
+ // This is </application>
1321
+ insert_offset = offset;
1322
+ break;
1323
+ }
1324
+ }
1325
+ }
1326
+
1327
+ offset += chunk_size;
1328
+ }
1329
+
1330
+ if (insert_offset == 0) return false;
1331
+
1332
+ // Create activity element with 2 attributes: name and exported
1333
+ std::vector<uint8_t> start_elem(16 + 20 + 40); // header + ext + 2 attrs
1334
+
1335
+ write_le<uint16_t>(&start_elem[0], 0x0102);
1336
+ write_le<uint16_t>(&start_elem[2], 16);
1337
+ write_le<uint32_t>(&start_elem[4], static_cast<uint32_t>(start_elem.size()));
1338
+ write_le<uint32_t>(&start_elem[8], 1);
1339
+ write_le<uint32_t>(&start_elem[12], 0xFFFFFFFF);
1340
+ write_le<uint32_t>(&start_elem[16], 0xFFFFFFFF);
1341
+ write_le<uint32_t>(&start_elem[20], activity_tag_idx);
1342
+ write_le<uint16_t>(&start_elem[24], 0x14);
1343
+ write_le<uint16_t>(&start_elem[26], 0x14);
1344
+ write_le<uint16_t>(&start_elem[28], 2);
1345
+ write_le<uint16_t>(&start_elem[30], 0);
1346
+ write_le<uint16_t>(&start_elem[32], 0);
1347
+ write_le<uint16_t>(&start_elem[34], 0);
1348
+
1349
+ // Attr 1: android:name
1350
+ size_t attr_offset = 36;
1351
+ write_le<uint32_t>(&start_elem[attr_offset + 0], android_ns_idx);
1352
+ write_le<uint32_t>(&start_elem[attr_offset + 4], name_attr_idx);
1353
+ write_le<uint32_t>(&start_elem[attr_offset + 8], activity_value_idx);
1354
+ write_le<uint16_t>(&start_elem[attr_offset + 12], 8);
1355
+ write_le<uint8_t>(&start_elem[attr_offset + 14], 0);
1356
+ write_le<uint8_t>(&start_elem[attr_offset + 15], 0x03);
1357
+ write_le<uint32_t>(&start_elem[attr_offset + 16], activity_value_idx);
1358
+
1359
+ // Attr 2: android:exported
1360
+ attr_offset += 20;
1361
+ write_le<uint32_t>(&start_elem[attr_offset + 0], android_ns_idx);
1362
+ write_le<uint32_t>(&start_elem[attr_offset + 4], exported_attr_idx);
1363
+ write_le<uint32_t>(&start_elem[attr_offset + 8], 0xFFFFFFFF);
1364
+ write_le<uint16_t>(&start_elem[attr_offset + 12], 8);
1365
+ write_le<uint8_t>(&start_elem[attr_offset + 14], 0);
1366
+ write_le<uint8_t>(&start_elem[attr_offset + 15], 0x12); // TYPE_INT_BOOLEAN
1367
+ write_le<uint32_t>(&start_elem[attr_offset + 16], exported ? 0xFFFFFFFF : 0);
1368
+
1369
+ // End element
1370
+ std::vector<uint8_t> end_elem(24);
1371
+ write_le<uint16_t>(&end_elem[0], 0x0103);
1372
+ write_le<uint16_t>(&end_elem[2], 16);
1373
+ write_le<uint32_t>(&end_elem[4], 24);
1374
+ write_le<uint32_t>(&end_elem[8], 1);
1375
+ write_le<uint32_t>(&end_elem[12], 0xFFFFFFFF);
1376
+ write_le<uint32_t>(&end_elem[16], 0xFFFFFFFF);
1377
+ write_le<uint32_t>(&end_elem[20], activity_tag_idx);
1378
+
1379
+ // Insert
1380
+ std::vector<uint8_t> new_data;
1381
+ new_data.reserve(data_.size() + start_elem.size() + end_elem.size());
1382
+ new_data.insert(new_data.end(), data_.begin(), data_.begin() + insert_offset);
1383
+ new_data.insert(new_data.end(), start_elem.begin(), start_elem.end());
1384
+ new_data.insert(new_data.end(), end_elem.begin(), end_elem.end());
1385
+ new_data.insert(new_data.end(), data_.begin() + insert_offset, data_.end());
1386
+
1387
+ write_le<uint32_t>(&new_data[4], static_cast<uint32_t>(new_data.size()));
1388
+ data_ = std::move(new_data);
1389
+
1390
+ parse_internal();
1391
+ return true;
1392
+ }
1393
+
1394
+ bool AxmlEditor::remove_activity(const std::string& activity_name) {
1395
+ size_t offset = chunk_info_.xml_content_offset;
1396
+ size_t activity_start = 0;
1397
+ size_t activity_end = 0;
1398
+ bool found = false;
1399
+ int depth = 0;
1400
+
1401
+ while (offset < data_.size()) {
1402
+ if (offset + 8 > data_.size()) break;
1403
+
1404
+ uint16_t chunk_type = read_le<uint16_t>(&data_[offset]);
1405
+ uint32_t chunk_size = read_le<uint32_t>(&data_[offset + 4]);
1406
+
1407
+ if (chunk_size == 0 || offset + chunk_size > data_.size()) break;
1408
+
1409
+ if (chunk_type == 0x0102) { // Start element
1410
+ if (!found) {
1411
+ uint32_t name_idx = read_le<uint32_t>(&data_[offset + 20]);
1412
+ if (name_idx < string_pool_.size() && string_pool_[name_idx] == "activity") {
1413
+ // Check android:name attribute
1414
+ uint16_t attr_count = read_le<uint16_t>(&data_[offset + 28]);
1415
+ uint16_t attr_start = read_le<uint16_t>(&data_[offset + 24]);
1416
+
1417
+ // Attributes start after: chunk header (16) + element info start + attr_start offset
1418
+ size_t attr_pos = offset + 16 + attr_start;
1419
+ for (uint16_t i = 0; i < attr_count && attr_pos + 20 <= data_.size(); i++) {
1420
+ uint32_t attr_name_idx = read_le<uint32_t>(&data_[attr_pos + 4]);
1421
+ uint32_t attr_value_idx = read_le<uint32_t>(&data_[attr_pos + 8]);
1422
+
1423
+ if (attr_name_idx < string_pool_.size() && string_pool_[attr_name_idx] == "name" &&
1424
+ attr_value_idx < string_pool_.size() && string_pool_[attr_value_idx] == activity_name) {
1425
+ activity_start = offset;
1426
+ found = true;
1427
+ depth = 1;
1428
+ break;
1429
+ }
1430
+ attr_pos += 20;
1431
+ }
1432
+ }
1433
+ } else {
1434
+ depth++;
1435
+ }
1436
+ } else if (chunk_type == 0x0103) { // End element
1437
+ if (found) {
1438
+ depth--;
1439
+ if (depth == 0) {
1440
+ activity_end = offset + chunk_size;
1441
+ break;
1442
+ }
1443
+ }
1444
+ }
1445
+
1446
+ offset += chunk_size;
1447
+ }
1448
+
1449
+ if (!found || activity_end <= activity_start) return false;
1450
+
1451
+ std::vector<uint8_t> new_data;
1452
+ new_data.reserve(data_.size() - (activity_end - activity_start));
1453
+ new_data.insert(new_data.end(), data_.begin(), data_.begin() + activity_start);
1454
+ new_data.insert(new_data.end(), data_.begin() + activity_end, data_.end());
1455
+
1456
+ write_le<uint32_t>(&new_data[4], static_cast<uint32_t>(new_data.size()));
1457
+ data_ = std::move(new_data);
1458
+
1459
+ parse_internal();
1460
+ return true;
1461
+ }
1462
+
1463
+ bool AxmlEditor::add_element(const std::string& parent_path, const std::string& element_name,
1464
+ const std::vector<std::pair<std::string, std::string>>& attributes) {
1465
+ // Generic add element - similar logic to add_activity
1466
+ // This is a simplified implementation
1467
+ return false; // TODO: implement full generic version
1468
+ }
1469
+
1470
+ bool AxmlEditor::remove_element(const std::string& element_path) {
1471
+ // Generic remove element - similar logic to remove_activity
1472
+ return false; // TODO: implement full generic version
1473
+ }
1474
+
1475
+ int AxmlEditor::find_or_add_string(const std::string& str) {
1476
+ for (size_t i = 0; i < string_pool_.size(); i++) {
1477
+ if (string_pool_[i] == str) {
1478
+ return static_cast<int>(i);
1479
+ }
1480
+ }
1481
+ string_pool_.push_back(str);
1482
+ return static_cast<int>(string_pool_.size() - 1);
1483
+ }
1484
+
1485
+ // 计算 UTF-8 字符串的 Unicode 字符数量
1486
+ static size_t utf8_char_count(const std::string& str) {
1487
+ size_t count = 0;
1488
+ size_t i = 0;
1489
+ while (i < str.length()) {
1490
+ uint8_t c = static_cast<uint8_t>(str[i]);
1491
+ if ((c & 0x80) == 0) {
1492
+ // ASCII: 0xxxxxxx
1493
+ i += 1;
1494
+ } else if ((c & 0xE0) == 0xC0) {
1495
+ // 2字节序列: 110xxxxx 10xxxxxx
1496
+ i += 2;
1497
+ } else if ((c & 0xF0) == 0xE0) {
1498
+ // 3字节序列: 1110xxxx 10xxxxxx 10xxxxxx
1499
+ i += 3;
1500
+ } else if ((c & 0xF8) == 0xF0) {
1501
+ // 4字节序列: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1502
+ i += 4;
1503
+ } else {
1504
+ // 无效的 UTF-8,按单字节处理
1505
+ i += 1;
1506
+ }
1507
+ count++;
1508
+ }
1509
+ return count;
1510
+ }
1511
+
1512
+ // 将 UTF-8 字符串转换为 UTF-16LE 编码
1513
+ static std::vector<uint16_t> utf8_to_utf16(const std::string& str) {
1514
+ std::vector<uint16_t> result;
1515
+ size_t i = 0;
1516
+ while (i < str.length()) {
1517
+ uint32_t codepoint = 0;
1518
+ uint8_t c = static_cast<uint8_t>(str[i]);
1519
+
1520
+ if ((c & 0x80) == 0) {
1521
+ codepoint = c;
1522
+ i += 1;
1523
+ } else if ((c & 0xE0) == 0xC0) {
1524
+ codepoint = (c & 0x1F) << 6;
1525
+ if (i + 1 < str.length()) {
1526
+ codepoint |= (static_cast<uint8_t>(str[i + 1]) & 0x3F);
1527
+ }
1528
+ i += 2;
1529
+ } else if ((c & 0xF0) == 0xE0) {
1530
+ codepoint = (c & 0x0F) << 12;
1531
+ if (i + 1 < str.length()) {
1532
+ codepoint |= (static_cast<uint8_t>(str[i + 1]) & 0x3F) << 6;
1533
+ }
1534
+ if (i + 2 < str.length()) {
1535
+ codepoint |= (static_cast<uint8_t>(str[i + 2]) & 0x3F);
1536
+ }
1537
+ i += 3;
1538
+ } else if ((c & 0xF8) == 0xF0) {
1539
+ codepoint = (c & 0x07) << 18;
1540
+ if (i + 1 < str.length()) {
1541
+ codepoint |= (static_cast<uint8_t>(str[i + 1]) & 0x3F) << 12;
1542
+ }
1543
+ if (i + 2 < str.length()) {
1544
+ codepoint |= (static_cast<uint8_t>(str[i + 2]) & 0x3F) << 6;
1545
+ }
1546
+ if (i + 3 < str.length()) {
1547
+ codepoint |= (static_cast<uint8_t>(str[i + 3]) & 0x3F);
1548
+ }
1549
+ i += 4;
1550
+ } else {
1551
+ i += 1;
1552
+ continue;
1553
+ }
1554
+
1555
+ // 转换为 UTF-16
1556
+ if (codepoint <= 0xFFFF) {
1557
+ result.push_back(static_cast<uint16_t>(codepoint));
1558
+ } else {
1559
+ // 使用代理对表示超过 BMP 的字符
1560
+ codepoint -= 0x10000;
1561
+ result.push_back(static_cast<uint16_t>(0xD800 | (codepoint >> 10)));
1562
+ result.push_back(static_cast<uint16_t>(0xDC00 | (codepoint & 0x3FF)));
1563
+ }
1564
+ }
1565
+ return result;
1566
+ }
1567
+
1568
+ bool AxmlEditor::rebuild_binary() {
1569
+ if (data_.size() < 8) return false;
1570
+
1571
+ bool is_utf8 = true;
1572
+ if (chunk_info_.string_pool_offset + 16 < data_.size()) {
1573
+ uint32_t flags = read_le<uint32_t>(&data_[chunk_info_.string_pool_offset + 16]);
1574
+ is_utf8 = (flags & (1 << 8)) != 0;
1575
+ }
1576
+
1577
+ std::vector<uint8_t> string_data;
1578
+ std::vector<uint32_t> string_offsets;
1579
+
1580
+ for (const auto& str : string_pool_) {
1581
+ string_offsets.push_back(static_cast<uint32_t>(string_data.size()));
1582
+
1583
+ if (is_utf8) {
1584
+ // UTF-8 编码格式:
1585
+ // - 字符长度 (1或2字节): Unicode 字符数量
1586
+ // - 字节长度 (1或2字节): UTF-8 字节数
1587
+ // - UTF-8 字符串数据
1588
+ // - null 终止符
1589
+ size_t char_len = utf8_char_count(str);
1590
+ size_t byte_len = str.length();
1591
+
1592
+ // 写入字符长度
1593
+ if (char_len < 128) {
1594
+ string_data.push_back(static_cast<uint8_t>(char_len));
1595
+ } else {
1596
+ string_data.push_back(static_cast<uint8_t>((char_len >> 8) | 0x80));
1597
+ string_data.push_back(static_cast<uint8_t>(char_len & 0xFF));
1598
+ }
1599
+
1600
+ // 写入字节长度
1601
+ if (byte_len < 128) {
1602
+ string_data.push_back(static_cast<uint8_t>(byte_len));
1603
+ } else {
1604
+ string_data.push_back(static_cast<uint8_t>((byte_len >> 8) | 0x80));
1605
+ string_data.push_back(static_cast<uint8_t>(byte_len & 0xFF));
1606
+ }
1607
+
1608
+ // 写入 UTF-8 字符串数据
1609
+ for (char c : str) {
1610
+ string_data.push_back(static_cast<uint8_t>(c));
1611
+ }
1612
+ // null 终止符
1613
+ string_data.push_back(0);
1614
+ } else {
1615
+ // UTF-16LE 编码格式:
1616
+ // - 字符长度 (2或4字节): UTF-16 单元数量
1617
+ // - UTF-16LE 字符串数据
1618
+ // - null 终止符 (2字节)
1619
+ std::vector<uint16_t> utf16_str = utf8_to_utf16(str);
1620
+ uint32_t len = static_cast<uint32_t>(utf16_str.size());
1621
+
1622
+ // 写入长度
1623
+ if (len < 0x8000) {
1624
+ // 短字符串格式: 2字节长度
1625
+ string_data.push_back(static_cast<uint8_t>(len & 0xFF));
1626
+ string_data.push_back(static_cast<uint8_t>((len >> 8) & 0x7F));
1627
+ } else {
1628
+ // 长字符串格式: 4字节长度,高位设置 0x8000 标志
1629
+ uint16_t high = static_cast<uint16_t>((len >> 16) & 0x7FFF) | 0x8000;
1630
+ uint16_t low = static_cast<uint16_t>(len & 0xFFFF);
1631
+ string_data.push_back(static_cast<uint8_t>(high & 0xFF));
1632
+ string_data.push_back(static_cast<uint8_t>(high >> 8));
1633
+ string_data.push_back(static_cast<uint8_t>(low & 0xFF));
1634
+ string_data.push_back(static_cast<uint8_t>(low >> 8));
1635
+ }
1636
+
1637
+ // 写入 UTF-16LE 数据
1638
+ for (uint16_t ch : utf16_str) {
1639
+ string_data.push_back(static_cast<uint8_t>(ch & 0xFF));
1640
+ string_data.push_back(static_cast<uint8_t>(ch >> 8));
1641
+ }
1642
+ // null 终止符
1643
+ string_data.push_back(0);
1644
+ string_data.push_back(0);
1645
+ }
1646
+ }
1647
+
1648
+ while (string_data.size() % 4 != 0) {
1649
+ string_data.push_back(0);
1650
+ }
1651
+
1652
+ uint32_t header_size = 28;
1653
+ uint32_t offsets_size = static_cast<uint32_t>(string_pool_.size() * 4);
1654
+ uint32_t strings_start = header_size + offsets_size;
1655
+ uint32_t new_chunk_size = strings_start + static_cast<uint32_t>(string_data.size());
1656
+
1657
+ std::vector<uint8_t> new_string_pool(new_chunk_size);
1658
+
1659
+ write_le<uint16_t>(&new_string_pool[0], 0x0001);
1660
+ write_le<uint16_t>(&new_string_pool[2], static_cast<uint16_t>(header_size));
1661
+ write_le<uint32_t>(&new_string_pool[4], new_chunk_size);
1662
+ write_le<uint32_t>(&new_string_pool[8], static_cast<uint32_t>(string_pool_.size()));
1663
+ write_le<uint32_t>(&new_string_pool[12], 0);
1664
+ write_le<uint32_t>(&new_string_pool[16], is_utf8 ? 0x100 : 0);
1665
+ write_le<uint32_t>(&new_string_pool[20], strings_start);
1666
+ write_le<uint32_t>(&new_string_pool[24], 0);
1667
+
1668
+ for (size_t i = 0; i < string_offsets.size(); i++) {
1669
+ write_le<uint32_t>(&new_string_pool[header_size + i * 4], string_offsets[i]);
1670
+ }
1671
+
1672
+ std::memcpy(&new_string_pool[strings_start], string_data.data(), string_data.size());
1673
+
1674
+ int32_t size_diff = static_cast<int32_t>(new_chunk_size) - static_cast<int32_t>(chunk_info_.string_pool_size);
1675
+
1676
+ std::vector<uint8_t> new_data;
1677
+ new_data.reserve(data_.size() + size_diff);
1678
+
1679
+ new_data.insert(new_data.end(), data_.begin(), data_.begin() + chunk_info_.string_pool_offset);
1680
+ new_data.insert(new_data.end(), new_string_pool.begin(), new_string_pool.end());
1681
+ new_data.insert(new_data.end(),
1682
+ data_.begin() + chunk_info_.string_pool_offset + chunk_info_.string_pool_size,
1683
+ data_.end());
1684
+
1685
+ uint32_t new_file_size = static_cast<uint32_t>(new_data.size());
1686
+ write_le<uint32_t>(&new_data[4], new_file_size);
1687
+
1688
+ data_ = std::move(new_data);
1689
+
1690
+ chunk_info_.string_pool_size = new_chunk_size;
1691
+ if (chunk_info_.resource_map_offset > chunk_info_.string_pool_offset) {
1692
+ chunk_info_.resource_map_offset += size_diff;
1693
+ }
1694
+ if (chunk_info_.xml_content_offset > chunk_info_.string_pool_offset) {
1695
+ chunk_info_.xml_content_offset += size_diff;
1696
+ }
1697
+
1698
+ return true;
1699
+ }
1700
+
1701
+ } // namespace axml