react-native-stallion 2.4.0-alpha.3 → 2.4.0-alpha.5
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.
- package/android/src/main/cpp/CMakeLists.txt +41 -0
- package/android/src/main/cpp/bspatch_bridge.c +268 -0
- package/android/src/main/cpp/bspatch_bridge.h +26 -0
- package/android/src/main/cpp/bzip2/blocksort.c +1094 -0
- package/android/src/main/cpp/bzip2/bzlib.c +1572 -0
- package/android/src/main/cpp/bzip2/bzlib.h +282 -0
- package/android/src/main/cpp/bzip2/bzlib_private.h +509 -0
- package/android/src/main/cpp/bzip2/compress.c +672 -0
- package/android/src/main/cpp/bzip2/crctable.c +104 -0
- package/android/src/main/cpp/bzip2/decompress.c +652 -0
- package/android/src/main/cpp/bzip2/huffman.c +205 -0
- package/android/src/main/cpp/bzip2/randtable.c +84 -0
- package/android/src/main/cpp/stallion_bspatch_jni.cpp +39 -0
- package/android/src/main/java/com/stallion/StallionModule.java +13 -1
- package/android/src/main/java/com/stallion/networkmanager/StallionPatchHandler.java +222 -0
- package/android/src/main/java/com/stallion/networkmanager/StallionSyncHandler.java +88 -16
- package/android/src/main/java/com/stallion/storage/StallionMeta.java +12 -0
- package/android/src/main/java/com/stallion/storage/StallionStateManager.java +25 -0
- package/android/src/main/java/com/stallion/utils/StallionBSPatch.java +30 -0
- package/ios/Stallion.xcodeproj/project.pbxproj +6 -0
- package/ios/main/Stallion-Bridging-Header.h +1 -0
- package/ios/main/Stallion.m +22 -0
- package/ios/main/Stallion.swift +8 -1
- package/ios/main/StallionBSPatch.swift +35 -0
- package/ios/main/StallionMeta.h +1 -0
- package/ios/main/StallionMeta.m +12 -0
- package/ios/main/StallionModule.m +3 -3
- package/ios/main/StallionPatchHandler.swift +206 -0
- package/ios/main/StallionSignatureVerification.swift +1 -1
- package/ios/main/StallionStateManager.h +3 -0
- package/ios/main/StallionStateManager.m +3 -0
- package/ios/main/StallionSyncHandler.swift +86 -10
- package/ios/main/bspatch.c +270 -0
- package/ios/main/bspatch_bridge.h +25 -0
- package/package.json +1 -1
- package/react-native-stallion.podspec +3 -1
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/main/utils/StallionNativeUtils.js +3 -0
- package/src/main/utils/StallionNativeUtils.js.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/main/utils/StallionNativeUtils.d.ts +2 -1
- package/types/main/utils/StallionNativeUtils.d.ts.map +1 -1
- package/types/types/utils.types.d.ts +1 -0
- package/types/types/utils.types.d.ts.map +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
|
|
2
|
+
/*-------------------------------------------------------------*/
|
|
3
|
+
/*--- Huffman coding low-level stuff ---*/
|
|
4
|
+
/*--- huffman.c ---*/
|
|
5
|
+
/*-------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------
|
|
8
|
+
This file is part of bzip2/libbzip2, a program and library for
|
|
9
|
+
lossless, block-sorting data compression.
|
|
10
|
+
|
|
11
|
+
bzip2/libbzip2 version 1.0.8 of 13 July 2019
|
|
12
|
+
Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
|
|
13
|
+
|
|
14
|
+
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
|
15
|
+
README file.
|
|
16
|
+
|
|
17
|
+
This program is released under the terms of the license contained
|
|
18
|
+
in the file LICENSE.
|
|
19
|
+
------------------------------------------------------------------ */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#include "bzlib_private.h"
|
|
23
|
+
|
|
24
|
+
/*---------------------------------------------------*/
|
|
25
|
+
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
|
|
26
|
+
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
|
|
27
|
+
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
|
|
28
|
+
|
|
29
|
+
#define ADDWEIGHTS(zw1,zw2) \
|
|
30
|
+
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
|
|
31
|
+
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
|
|
32
|
+
|
|
33
|
+
#define UPHEAP(z) \
|
|
34
|
+
{ \
|
|
35
|
+
Int32 zz, tmp; \
|
|
36
|
+
zz = z; tmp = heap[zz]; \
|
|
37
|
+
while (weight[tmp] < weight[heap[zz >> 1]]) { \
|
|
38
|
+
heap[zz] = heap[zz >> 1]; \
|
|
39
|
+
zz >>= 1; \
|
|
40
|
+
} \
|
|
41
|
+
heap[zz] = tmp; \
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#define DOWNHEAP(z) \
|
|
45
|
+
{ \
|
|
46
|
+
Int32 zz, yy, tmp; \
|
|
47
|
+
zz = z; tmp = heap[zz]; \
|
|
48
|
+
while (True) { \
|
|
49
|
+
yy = zz << 1; \
|
|
50
|
+
if (yy > nHeap) break; \
|
|
51
|
+
if (yy < nHeap && \
|
|
52
|
+
weight[heap[yy+1]] < weight[heap[yy]]) \
|
|
53
|
+
yy++; \
|
|
54
|
+
if (weight[tmp] < weight[heap[yy]]) break; \
|
|
55
|
+
heap[zz] = heap[yy]; \
|
|
56
|
+
zz = yy; \
|
|
57
|
+
} \
|
|
58
|
+
heap[zz] = tmp; \
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/*---------------------------------------------------*/
|
|
63
|
+
void BZ2_hbMakeCodeLengths ( UChar *len,
|
|
64
|
+
Int32 *freq,
|
|
65
|
+
Int32 alphaSize,
|
|
66
|
+
Int32 maxLen )
|
|
67
|
+
{
|
|
68
|
+
/*--
|
|
69
|
+
Nodes and heap entries run from 1. Entry 0
|
|
70
|
+
for both the heap and nodes is a sentinel.
|
|
71
|
+
--*/
|
|
72
|
+
Int32 nNodes, nHeap, n1, n2, i, j, k;
|
|
73
|
+
Bool tooLong;
|
|
74
|
+
|
|
75
|
+
Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
|
|
76
|
+
Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
|
|
77
|
+
Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
|
|
78
|
+
|
|
79
|
+
for (i = 0; i < alphaSize; i++)
|
|
80
|
+
weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
|
|
81
|
+
|
|
82
|
+
while (True) {
|
|
83
|
+
|
|
84
|
+
nNodes = alphaSize;
|
|
85
|
+
nHeap = 0;
|
|
86
|
+
|
|
87
|
+
heap[0] = 0;
|
|
88
|
+
weight[0] = 0;
|
|
89
|
+
parent[0] = -2;
|
|
90
|
+
|
|
91
|
+
for (i = 1; i <= alphaSize; i++) {
|
|
92
|
+
parent[i] = -1;
|
|
93
|
+
nHeap++;
|
|
94
|
+
heap[nHeap] = i;
|
|
95
|
+
UPHEAP(nHeap);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
|
|
99
|
+
|
|
100
|
+
while (nHeap > 1) {
|
|
101
|
+
n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
|
102
|
+
n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
|
103
|
+
nNodes++;
|
|
104
|
+
parent[n1] = parent[n2] = nNodes;
|
|
105
|
+
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
|
|
106
|
+
parent[nNodes] = -1;
|
|
107
|
+
nHeap++;
|
|
108
|
+
heap[nHeap] = nNodes;
|
|
109
|
+
UPHEAP(nHeap);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
|
|
113
|
+
|
|
114
|
+
tooLong = False;
|
|
115
|
+
for (i = 1; i <= alphaSize; i++) {
|
|
116
|
+
j = 0;
|
|
117
|
+
k = i;
|
|
118
|
+
while (parent[k] >= 0) { k = parent[k]; j++; }
|
|
119
|
+
len[i-1] = j;
|
|
120
|
+
if (j > maxLen) tooLong = True;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (! tooLong) break;
|
|
124
|
+
|
|
125
|
+
/* 17 Oct 04: keep-going condition for the following loop used
|
|
126
|
+
to be 'i < alphaSize', which missed the last element,
|
|
127
|
+
theoretically leading to the possibility of the compressor
|
|
128
|
+
looping. However, this count-scaling step is only needed if
|
|
129
|
+
one of the generated Huffman code words is longer than
|
|
130
|
+
maxLen, which up to and including version 1.0.2 was 20 bits,
|
|
131
|
+
which is extremely unlikely. In version 1.0.3 maxLen was
|
|
132
|
+
changed to 17 bits, which has minimal effect on compression
|
|
133
|
+
ratio, but does mean this scaling step is used from time to
|
|
134
|
+
time, enough to verify that it works.
|
|
135
|
+
|
|
136
|
+
This means that bzip2-1.0.3 and later will only produce
|
|
137
|
+
Huffman codes with a maximum length of 17 bits. However, in
|
|
138
|
+
order to preserve backwards compatibility with bitstreams
|
|
139
|
+
produced by versions pre-1.0.3, the decompressor must still
|
|
140
|
+
handle lengths of up to 20. */
|
|
141
|
+
|
|
142
|
+
for (i = 1; i <= alphaSize; i++) {
|
|
143
|
+
j = weight[i] >> 8;
|
|
144
|
+
j = 1 + (j / 2);
|
|
145
|
+
weight[i] = j << 8;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
/*---------------------------------------------------*/
|
|
152
|
+
void BZ2_hbAssignCodes ( Int32 *code,
|
|
153
|
+
UChar *length,
|
|
154
|
+
Int32 minLen,
|
|
155
|
+
Int32 maxLen,
|
|
156
|
+
Int32 alphaSize )
|
|
157
|
+
{
|
|
158
|
+
Int32 n, vec, i;
|
|
159
|
+
|
|
160
|
+
vec = 0;
|
|
161
|
+
for (n = minLen; n <= maxLen; n++) {
|
|
162
|
+
for (i = 0; i < alphaSize; i++)
|
|
163
|
+
if (length[i] == n) { code[i] = vec; vec++; };
|
|
164
|
+
vec <<= 1;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
/*---------------------------------------------------*/
|
|
170
|
+
void BZ2_hbCreateDecodeTables ( Int32 *limit,
|
|
171
|
+
Int32 *base,
|
|
172
|
+
Int32 *perm,
|
|
173
|
+
UChar *length,
|
|
174
|
+
Int32 minLen,
|
|
175
|
+
Int32 maxLen,
|
|
176
|
+
Int32 alphaSize )
|
|
177
|
+
{
|
|
178
|
+
Int32 pp, i, j, vec;
|
|
179
|
+
|
|
180
|
+
pp = 0;
|
|
181
|
+
for (i = minLen; i <= maxLen; i++)
|
|
182
|
+
for (j = 0; j < alphaSize; j++)
|
|
183
|
+
if (length[j] == i) { perm[pp] = j; pp++; };
|
|
184
|
+
|
|
185
|
+
for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
|
|
186
|
+
for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
|
|
187
|
+
|
|
188
|
+
for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
|
|
189
|
+
|
|
190
|
+
for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
|
|
191
|
+
vec = 0;
|
|
192
|
+
|
|
193
|
+
for (i = minLen; i <= maxLen; i++) {
|
|
194
|
+
vec += (base[i+1] - base[i]);
|
|
195
|
+
limit[i] = vec-1;
|
|
196
|
+
vec <<= 1;
|
|
197
|
+
}
|
|
198
|
+
for (i = minLen + 1; i <= maxLen; i++)
|
|
199
|
+
base[i] = ((limit[i-1] + 1) << 1) - base[i];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
/*-------------------------------------------------------------*/
|
|
204
|
+
/*--- end huffman.c ---*/
|
|
205
|
+
/*-------------------------------------------------------------*/
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
/*-------------------------------------------------------------*/
|
|
3
|
+
/*--- Table for randomising repetitive blocks ---*/
|
|
4
|
+
/*--- randtable.c ---*/
|
|
5
|
+
/*-------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------
|
|
8
|
+
This file is part of bzip2/libbzip2, a program and library for
|
|
9
|
+
lossless, block-sorting data compression.
|
|
10
|
+
|
|
11
|
+
bzip2/libbzip2 version 1.0.8 of 13 July 2019
|
|
12
|
+
Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
|
|
13
|
+
|
|
14
|
+
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
|
15
|
+
README file.
|
|
16
|
+
|
|
17
|
+
This program is released under the terms of the license contained
|
|
18
|
+
in the file LICENSE.
|
|
19
|
+
------------------------------------------------------------------ */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#include "bzlib_private.h"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/*---------------------------------------------*/
|
|
26
|
+
Int32 BZ2_rNums[512] = {
|
|
27
|
+
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
|
28
|
+
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
|
29
|
+
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
|
30
|
+
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
|
31
|
+
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
|
32
|
+
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
|
33
|
+
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
|
34
|
+
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
|
35
|
+
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
|
36
|
+
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
|
37
|
+
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
|
38
|
+
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
|
39
|
+
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
|
40
|
+
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
|
41
|
+
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
|
42
|
+
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
|
43
|
+
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
|
44
|
+
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
|
45
|
+
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
|
46
|
+
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
|
47
|
+
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
|
48
|
+
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
|
49
|
+
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
|
50
|
+
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
|
51
|
+
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
|
52
|
+
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
|
53
|
+
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
|
54
|
+
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
|
55
|
+
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
|
56
|
+
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
|
57
|
+
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
|
58
|
+
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
|
59
|
+
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
|
60
|
+
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
|
61
|
+
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
|
62
|
+
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
|
63
|
+
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
|
64
|
+
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
|
65
|
+
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
|
66
|
+
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
|
67
|
+
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
|
68
|
+
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
|
69
|
+
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
|
70
|
+
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
|
71
|
+
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
|
72
|
+
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
|
73
|
+
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
|
74
|
+
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
|
75
|
+
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
|
76
|
+
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
|
77
|
+
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
|
78
|
+
936, 638
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
/*-------------------------------------------------------------*/
|
|
83
|
+
/*--- end randtable.c ---*/
|
|
84
|
+
/*-------------------------------------------------------------*/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// stallion_bspatch_jni.cpp
|
|
3
|
+
// react-native-stallion
|
|
4
|
+
//
|
|
5
|
+
// JNI bridge for bspatch functionality
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include <jni.h>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include "bspatch_bridge.h"
|
|
11
|
+
|
|
12
|
+
extern "C" JNIEXPORT jint JNICALL
|
|
13
|
+
Java_com_stallion_utils_StallionBSPatch_nativeApplyPatch(
|
|
14
|
+
JNIEnv *env,
|
|
15
|
+
jobject /* this */,
|
|
16
|
+
jstring oldPath,
|
|
17
|
+
jstring newPath,
|
|
18
|
+
jstring patchPath) {
|
|
19
|
+
|
|
20
|
+
const char *oldPathStr = env->GetStringUTFChars(oldPath, nullptr);
|
|
21
|
+
const char *newPathStr = env->GetStringUTFChars(newPath, nullptr);
|
|
22
|
+
const char *patchPathStr = env->GetStringUTFChars(patchPath, nullptr);
|
|
23
|
+
|
|
24
|
+
if (!oldPathStr || !newPathStr || !patchPathStr) {
|
|
25
|
+
if (oldPathStr) env->ReleaseStringUTFChars(oldPath, oldPathStr);
|
|
26
|
+
if (newPathStr) env->ReleaseStringUTFChars(newPath, newPathStr);
|
|
27
|
+
if (patchPathStr) env->ReleaseStringUTFChars(patchPath, patchPathStr);
|
|
28
|
+
return -1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
int result = bspatch_apply(oldPathStr, newPathStr, patchPathStr);
|
|
32
|
+
|
|
33
|
+
env->ReleaseStringUTFChars(oldPath, oldPathStr);
|
|
34
|
+
env->ReleaseStringUTFChars(newPath, newPathStr);
|
|
35
|
+
env->ReleaseStringUTFChars(patchPath, patchPathStr);
|
|
36
|
+
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
|
|
@@ -84,7 +84,10 @@ public class StallionModule extends ReactContextBaseJavaModule implements Lifecy
|
|
|
84
84
|
String pendingReleaseUrl = stallionStateManager.getPendingReleaseUrl();
|
|
85
85
|
String pendingReleaseHash = stallionStateManager.getPendingReleaseHash();
|
|
86
86
|
if(!pendingReleaseUrl.isEmpty() && !pendingReleaseHash.isEmpty()) {
|
|
87
|
-
|
|
87
|
+
String pendingReleaseDiffUrl = stallionStateManager.getPendingReleaseDiffUrl();
|
|
88
|
+
boolean pendingReleaseIsBundlePatched = stallionStateManager.getPendingReleaseIsBundlePatched();
|
|
89
|
+
String pendingReleaseBundleDiffId = stallionStateManager.getPendingReleaseBundleDiffId();
|
|
90
|
+
StallionSyncHandler.downloadNewRelease(pendingReleaseHash, pendingReleaseUrl, pendingReleaseDiffUrl, pendingReleaseIsBundlePatched, pendingReleaseBundleDiffId);
|
|
88
91
|
stallionStateManager.setPendingRelease("", "");
|
|
89
92
|
}
|
|
90
93
|
}
|
|
@@ -180,6 +183,15 @@ public class StallionModule extends ReactContextBaseJavaModule implements Lifecy
|
|
|
180
183
|
ProcessPhoenix.triggerRebirth(getReactApplicationContext());
|
|
181
184
|
}
|
|
182
185
|
|
|
186
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
187
|
+
public String getActiveReleaseHash() {
|
|
188
|
+
try {
|
|
189
|
+
return stallionStateManager.stallionMeta.getActiveReleaseHash();
|
|
190
|
+
} catch (Exception e) {
|
|
191
|
+
return "";
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
183
195
|
@ReactMethod
|
|
184
196
|
public void addListener(String eventName) {
|
|
185
197
|
// No-op: required for RN event emitter contract
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
package com.stallion.networkmanager;
|
|
2
|
+
|
|
3
|
+
import com.stallion.storage.StallionConfigConstants;
|
|
4
|
+
import com.stallion.utils.StallionFileManager;
|
|
5
|
+
import com.stallion.utils.StallionBSPatch;
|
|
6
|
+
|
|
7
|
+
import org.json.JSONArray;
|
|
8
|
+
import org.json.JSONObject;
|
|
9
|
+
|
|
10
|
+
import java.io.File;
|
|
11
|
+
import java.io.FileInputStream;
|
|
12
|
+
import java.io.IOException;
|
|
13
|
+
import java.nio.charset.Charset;
|
|
14
|
+
|
|
15
|
+
public class StallionPatchHandler {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Applies a patch to the base bundle using the diff file.
|
|
19
|
+
*
|
|
20
|
+
* @param baseBundlePath The path to the base bundle folder
|
|
21
|
+
* @param diffPath The path to the downloaded diff folder
|
|
22
|
+
* @param isBundlePatched Whether the bundle file uses bspatch (true) or file-based patching (false)
|
|
23
|
+
* @throws Exception if patch application fails at any point
|
|
24
|
+
*/
|
|
25
|
+
public static void applyPatch(String baseBundlePath, String diffPath, boolean isBundlePatched) throws Exception {
|
|
26
|
+
File baseBundleDir = new File(baseBundlePath);
|
|
27
|
+
File diffDir = new File(diffPath);
|
|
28
|
+
|
|
29
|
+
// Validate inputs
|
|
30
|
+
if (!baseBundleDir.exists() || !baseBundleDir.isDirectory()) {
|
|
31
|
+
throw new IllegalArgumentException("Base bundle path does not exist or is not a directory: " + baseBundlePath);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!diffDir.exists() || !diffDir.isDirectory()) {
|
|
35
|
+
throw new IllegalArgumentException("Diff path does not exist or is not a directory: " + diffPath);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Path to the unzipped diff folder
|
|
39
|
+
File diffUnzipDir = new File(diffDir, StallionConfigConstants.UNZIP_FOLDER_NAME);
|
|
40
|
+
if (!diffUnzipDir.exists() || !diffUnzipDir.isDirectory()) {
|
|
41
|
+
throw new IllegalArgumentException("Diff unzip folder does not exist: " + diffUnzipDir.getAbsolutePath());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Path to manifest.json
|
|
45
|
+
File manifestFile = new File(diffDir, "manifest.json");
|
|
46
|
+
if (!manifestFile.exists() || !manifestFile.isFile()) {
|
|
47
|
+
throw new IllegalArgumentException("Manifest file does not exist: " + manifestFile.getAbsolutePath());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Create a temporary directory for the patched bundle
|
|
51
|
+
File tempPatchedDir = new File(diffDir.getParent(), diffDir.getName() + "_patched_temp");
|
|
52
|
+
try {
|
|
53
|
+
// Copy base bundle to temporary location
|
|
54
|
+
StallionFileManager.copyDirectory(baseBundleDir, tempPatchedDir);
|
|
55
|
+
|
|
56
|
+
// Read and parse manifest.json
|
|
57
|
+
JSONObject manifest = readManifest(manifestFile);
|
|
58
|
+
|
|
59
|
+
// Apply manifest changes
|
|
60
|
+
applyManifestChanges(manifest, diffDir, tempPatchedDir, isBundlePatched);
|
|
61
|
+
|
|
62
|
+
// Replace diffPath contents with patched result
|
|
63
|
+
// First, clear the diffPath
|
|
64
|
+
File[] diffDirFiles = diffDir.listFiles();
|
|
65
|
+
if (diffDirFiles != null) {
|
|
66
|
+
for (File file : diffDirFiles) {
|
|
67
|
+
StallionFileManager.deleteFileOrFolderSilently(file);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Copy patched result to diffPath
|
|
72
|
+
File[] tempPatchedFiles = tempPatchedDir.listFiles();
|
|
73
|
+
if (tempPatchedFiles != null) {
|
|
74
|
+
for (File file : tempPatchedFiles) {
|
|
75
|
+
File destFile = new File(diffDir, file.getName());
|
|
76
|
+
if (file.isDirectory()) {
|
|
77
|
+
StallionFileManager.copyDirectory(file, destFile);
|
|
78
|
+
} else {
|
|
79
|
+
StallionFileManager.copyFile(file, destFile);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
} finally {
|
|
85
|
+
// Clean up temporary directory
|
|
86
|
+
if (tempPatchedDir.exists()) {
|
|
87
|
+
StallionFileManager.deleteFileOrFolderSilently(tempPatchedDir);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Reads and parses the manifest.json file.
|
|
94
|
+
*/
|
|
95
|
+
private static JSONObject readManifest(File manifestFile) throws Exception {
|
|
96
|
+
try (FileInputStream fis = new FileInputStream(manifestFile)) {
|
|
97
|
+
byte[] data = new byte[(int) manifestFile.length()];
|
|
98
|
+
int bytesRead = 0;
|
|
99
|
+
int totalBytesRead = 0;
|
|
100
|
+
while (totalBytesRead < data.length && (bytesRead = fis.read(data, totalBytesRead, data.length - totalBytesRead)) != -1) {
|
|
101
|
+
totalBytesRead += bytesRead;
|
|
102
|
+
}
|
|
103
|
+
if (totalBytesRead != data.length) {
|
|
104
|
+
throw new IOException("Failed to read all bytes from manifest file");
|
|
105
|
+
}
|
|
106
|
+
String manifestJson = new String(data, Charset.forName("UTF-8"));
|
|
107
|
+
return new JSONObject(manifestJson);
|
|
108
|
+
} catch (IOException e) {
|
|
109
|
+
throw new Exception("Failed to read manifest file: " + e.getMessage(), e);
|
|
110
|
+
} catch (org.json.JSONException e) {
|
|
111
|
+
throw new Exception("Failed to parse manifest JSON: " + e.getMessage(), e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Applies the changes specified in the manifest to the patched directory.
|
|
117
|
+
*/
|
|
118
|
+
private static void applyManifestChanges(JSONObject manifest, File diffUnzipDir, File patchedDir, boolean isBundlePatched) throws Exception {
|
|
119
|
+
// Apply deletions first
|
|
120
|
+
if (manifest.has("deleted")) {
|
|
121
|
+
JSONArray deleted = manifest.getJSONArray("deleted");
|
|
122
|
+
for (int i = 0; i < deleted.length(); i++) {
|
|
123
|
+
String filePath = deleted.getString(i);
|
|
124
|
+
File fileToDelete = new File(patchedDir, filePath);
|
|
125
|
+
if (fileToDelete.exists()) {
|
|
126
|
+
StallionFileManager.deleteFileOrFolderSilently(fileToDelete);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Apply modifications (files that already exist)
|
|
132
|
+
if (manifest.has("modified")) {
|
|
133
|
+
JSONArray modified = manifest.getJSONArray("modified");
|
|
134
|
+
for (int i = 0; i < modified.length(); i++) {
|
|
135
|
+
String filePath = modified.getString(i);
|
|
136
|
+
applyFileFromDiff(diffUnzipDir, patchedDir, filePath, isBundlePatched);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Apply additions (new files)
|
|
141
|
+
if (manifest.has("added")) {
|
|
142
|
+
JSONArray added = manifest.getJSONArray("added");
|
|
143
|
+
for (int i = 0; i < added.length(); i++) {
|
|
144
|
+
String filePath = added.getString(i);
|
|
145
|
+
applyFileFromDiff(diffUnzipDir, patchedDir, filePath, isBundlePatched);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Copies a file from the diff directory to the patched directory.
|
|
152
|
+
* If the file is index.android.bundle and isBundlePatched is true, applies bspatch instead of copying.
|
|
153
|
+
*/
|
|
154
|
+
private static void applyFileFromDiff(File diffUnzipDir, File patchedDir, String relativeFilePath, boolean isBundlePatched) throws Exception {
|
|
155
|
+
File sourceFile = new File(diffUnzipDir, relativeFilePath);
|
|
156
|
+
File destFile = new File(patchedDir, relativeFilePath);
|
|
157
|
+
|
|
158
|
+
if (!sourceFile.exists()) {
|
|
159
|
+
throw new Exception("Source file does not exist in diff: " + sourceFile.getAbsolutePath());
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Ensure parent directory exists
|
|
163
|
+
File parentDir = destFile.getParentFile();
|
|
164
|
+
if (parentDir != null && !parentDir.exists()) {
|
|
165
|
+
if (!parentDir.mkdirs()) {
|
|
166
|
+
throw new Exception("Failed to create parent directory: " + parentDir.getAbsolutePath());
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Check if this is the index.android.bundle file
|
|
171
|
+
String bundleFileName = StallionConfigConstants.ANDROID_BUNDLE_FILE_NAME;
|
|
172
|
+
// Remove leading slash if present for comparison
|
|
173
|
+
String normalizedBundleName = bundleFileName.startsWith("/") ? bundleFileName.substring(1) : bundleFileName;
|
|
174
|
+
String normalizedPath = relativeFilePath.replace("\\", "/");
|
|
175
|
+
boolean isBundleFile = normalizedPath.endsWith("/" + normalizedBundleName) || normalizedPath.equals(normalizedBundleName);
|
|
176
|
+
|
|
177
|
+
if (isBundleFile && isBundlePatched) {
|
|
178
|
+
// This is the bundle file and it's a binary patch - use bspatch
|
|
179
|
+
// The sourceFile is the patch file, destFile is where the patched bundle should go
|
|
180
|
+
// The base bundle file should already exist in the patched directory (from the initial copy)
|
|
181
|
+
File baseBundleFile = destFile;
|
|
182
|
+
|
|
183
|
+
if (!baseBundleFile.exists()) {
|
|
184
|
+
throw new Exception("Base bundle file does not exist for patching: " + baseBundleFile.getAbsolutePath());
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Create a temporary file for the patched output
|
|
188
|
+
File tempPatchedFile = new File(destFile.getParent(), destFile.getName() + ".tmp");
|
|
189
|
+
try {
|
|
190
|
+
// Apply bspatch: patch the base bundle using the diff file
|
|
191
|
+
boolean success = StallionBSPatch.applyPatch(
|
|
192
|
+
baseBundleFile.getAbsolutePath(), // old file (base bundle)
|
|
193
|
+
tempPatchedFile.getAbsolutePath(), // new file (temporary output)
|
|
194
|
+
sourceFile.getAbsolutePath() // patch file
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (!success) {
|
|
198
|
+
throw new Exception("Failed to apply bspatch to " + relativeFilePath);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Replace the original file with the patched one
|
|
202
|
+
if (destFile.exists()) {
|
|
203
|
+
StallionFileManager.deleteFileOrFolderSilently(destFile);
|
|
204
|
+
}
|
|
205
|
+
StallionFileManager.moveFile(tempPatchedFile, destFile);
|
|
206
|
+
} catch (Exception e) {
|
|
207
|
+
// Clean up temp file on error
|
|
208
|
+
if (tempPatchedFile.exists()) {
|
|
209
|
+
StallionFileManager.deleteFileOrFolderSilently(tempPatchedFile);
|
|
210
|
+
}
|
|
211
|
+
throw e;
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
// Regular file - copy normally
|
|
215
|
+
if (sourceFile.isDirectory()) {
|
|
216
|
+
StallionFileManager.copyDirectory(sourceFile, destFile);
|
|
217
|
+
} else {
|
|
218
|
+
StallionFileManager.copyFile(sourceFile, destFile);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|