|
1 | 1 | #ifndef CHROME_PLUS_SRC_PAKFILE_H_ |
2 | 2 | #define CHROME_PLUS_SRC_PAKFILE_H_ |
3 | 3 |
|
4 | | -#pragma warning(disable : 4334) |
5 | | -#pragma warning(disable : 4267) |
| 4 | +#include <functional> |
6 | 5 |
|
7 | | -extern "C" |
8 | | -{ |
9 | | -#include "..\mini_gzip\miniz.c" |
10 | | -#include "..\mini_gzip\mini_gzip.h" |
11 | | -#include "..\mini_gzip\mini_gzip.c" |
12 | | -} |
13 | | - |
14 | | -#pragma pack(push) |
15 | | -#pragma pack(1) |
16 | | - |
17 | | -#define PACK4_FILE_VERSION (4) |
18 | | -#define PACK5_FILE_VERSION (5) |
19 | | - |
20 | | -#include "utils.h" |
21 | | - |
22 | | -struct PAK4_HEADER { |
23 | | - uint32_t num_entries; |
24 | | - uint8_t encodeing; |
25 | | -}; |
26 | | - |
27 | | -struct PAK5_HEADER { |
28 | | - uint32_t encodeing; |
29 | | - uint16_t resource_count; |
30 | | - uint16_t alias_count; |
31 | | -}; |
32 | | - |
33 | | -struct PAK_ENTRY { |
34 | | - uint16_t resource_id; |
35 | | - uint32_t file_offset; |
36 | | -}; |
37 | | - |
38 | | -struct PAK_ALIAS { |
39 | | - uint16_t resource_id; |
40 | | - uint16_t entry_index; |
41 | | -}; |
42 | | -#pragma pack(pop) |
43 | | - |
44 | | -bool CheckHeader(uint8_t* buffer, |
45 | | - PAK_ENTRY*& pak_entry, |
46 | | - PAK_ENTRY*& end_entry) { |
47 | | - uint32_t version = *(uint32_t*)buffer; |
48 | | - |
49 | | - if (version != PACK4_FILE_VERSION && version != PACK5_FILE_VERSION) |
50 | | - return false; |
51 | | - |
52 | | - if (version == PACK4_FILE_VERSION) { |
53 | | - PAK4_HEADER* pak_header = (PAK4_HEADER*)(buffer + sizeof(uint32_t)); |
54 | | - if (pak_header->encodeing != 1) |
55 | | - return false; |
56 | | - |
57 | | - pak_entry = (PAK_ENTRY*)(buffer + sizeof(uint32_t) + sizeof(PAK4_HEADER)); |
58 | | - end_entry = pak_entry + pak_header->num_entries; |
59 | | - } |
60 | | - |
61 | | - if (version == PACK5_FILE_VERSION) { |
62 | | - PAK5_HEADER* pak_header = (PAK5_HEADER*)(buffer + sizeof(uint32_t)); |
63 | | - if (pak_header->encodeing != 1) |
64 | | - return false; |
65 | | - |
66 | | - pak_entry = (PAK_ENTRY*)(buffer + sizeof(uint32_t) + sizeof(PAK5_HEADER)); |
67 | | - end_entry = pak_entry + pak_header->resource_count; |
68 | | - } |
69 | | - |
70 | | - // In order to save the "next item" of the last item, |
71 | | - // the id of this special item must be 0 |
72 | | - if (!end_entry || end_entry->resource_id != 0) |
73 | | - return false; |
74 | | - |
75 | | - return true; |
76 | | -} |
77 | | - |
78 | | -template <typename Function> |
79 | | -void PakFind(uint8_t* buffer, uint8_t* pos, Function f) { |
80 | | - PAK_ENTRY* pak_entry = nullptr; |
81 | | - PAK_ENTRY* end_entry = nullptr; |
82 | | - |
83 | | - // Check the file header. |
84 | | - if (!CheckHeader(buffer, pak_entry, end_entry)) |
85 | | - return; |
86 | | - |
87 | | - do { |
88 | | - PAK_ENTRY* next_entry = pak_entry + 1; |
89 | | - if (pos >= buffer + pak_entry->file_offset && |
90 | | - pos <= buffer + next_entry->file_offset) { |
91 | | - f(buffer + pak_entry->file_offset, |
92 | | - next_entry->file_offset - pak_entry->file_offset); |
93 | | - break; |
94 | | - } |
95 | | - |
96 | | - pak_entry = next_entry; |
97 | | - } while (pak_entry->resource_id != 0); |
98 | | -} |
99 | | - |
100 | | -template <typename Function> |
101 | | -void TraversalGZIPFile(uint8_t* buffer, Function f) { |
102 | | - PAK_ENTRY* pak_entry = NULL; |
103 | | - PAK_ENTRY* end_entry = NULL; |
104 | | - |
105 | | - // Check the file header. |
106 | | - if (!CheckHeader(buffer, pak_entry, end_entry)) |
107 | | - return; |
108 | | - |
109 | | - do { |
110 | | - PAK_ENTRY* next_entry = pak_entry + 1; |
111 | | - uint32_t old_size = next_entry->file_offset - pak_entry->file_offset; |
112 | | - |
113 | | - if (old_size < 10 * 1024) { |
114 | | - // Files smaller than 10 kb are skipped. |
115 | | - pak_entry = next_entry; |
116 | | - continue; |
117 | | - } |
118 | | - |
119 | | - BYTE gzip[] = {0x1F, 0x8B, 0x08}; |
120 | | - size_t gzip_len = sizeof(gzip); |
121 | | - if (memcmp(buffer + pak_entry->file_offset, gzip, gzip_len) != 0) { |
122 | | - // Files that are not gzip format are skipped. |
123 | | - pak_entry = next_entry; |
124 | | - continue; |
125 | | - } |
126 | | - |
127 | | - uint32_t original_size = *(uint32_t*)(buffer + next_entry->file_offset - 4); |
128 | | - uint8_t* unpack_buffer = (uint8_t*)malloc(original_size); |
129 | | - if (!unpack_buffer) |
130 | | - return; |
131 | | - |
132 | | - struct mini_gzip gz; |
133 | | - mini_gz_start(&gz, buffer + pak_entry->file_offset, old_size); |
134 | | - int unpack_len = mini_gz_unpack(&gz, unpack_buffer, original_size); |
135 | | - |
136 | | - if (original_size == unpack_len) { |
137 | | - uint32_t new_len = old_size; |
138 | | - bool changed = f(unpack_buffer, unpack_len, new_len); |
139 | | - if (changed) { |
140 | | - // If the file is changed. |
141 | | - size_t compress_size = 0; |
142 | | - uint8_t* compress_buffer = |
143 | | - (uint8_t*)gzip_compress(unpack_buffer, new_len, &compress_size); |
144 | | - if (compress_buffer && compress_size < old_size) { |
145 | | - /*FILE *fp = fopen("test.gz", "wb"); |
146 | | - fwrite(compress_buffer, compress_size, 1, fp); |
147 | | - fclose(fp);*/ |
148 | | - |
149 | | - // gzip header |
150 | | - memcpy(buffer + pak_entry->file_offset, compress_buffer, 10); |
151 | | - |
152 | | - // extra |
153 | | - buffer[pak_entry->file_offset + 3] = 0x04; |
154 | | - uint16_t extra_length = old_size - compress_size - 2; |
155 | | - memcpy(buffer + pak_entry->file_offset + 10, &extra_length, |
156 | | - sizeof(extra_length)); |
157 | | - memset(buffer + pak_entry->file_offset + 12, '\0', extra_length); |
158 | | - |
159 | | - // compress |
160 | | - memcpy(buffer + pak_entry->file_offset + 12 + extra_length, |
161 | | - compress_buffer + 10, compress_size - 10); |
162 | | - |
163 | | - /*fp = fopen("test2.gz", "wb"); |
164 | | - fwrite(buffer + pak_entry->file_offset, old_size, 1, fp); |
165 | | - fclose(fp);*/ |
166 | | - } else { |
167 | | - DebugLog(L"gzip compress error %d %d", compress_size, old_size); |
168 | | - } |
169 | | - |
170 | | - if (compress_buffer) |
171 | | - free(compress_buffer); |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - free(unpack_buffer); |
176 | | - pak_entry = next_entry; |
177 | | - } while (pak_entry->resource_id != 0); |
178 | | -} |
| 6 | +void TraversalGZIPFile(uint8_t* buffer, |
| 7 | + std::function<bool(uint8_t*, uint32_t, size_t&)>&& f); |
179 | 8 |
|
180 | 9 | #endif // CHROME_PLUS_SRC_PAKFILE_H_ |
0 commit comments