@swiftpatch/react-native 2.0.0

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 (182) hide show
  1. package/README.md +430 -0
  2. package/android/build.gradle +105 -0
  3. package/android/src/main/AndroidManifest.xml +6 -0
  4. package/android/src/main/java/com/swiftpatch/BundleManager.kt +107 -0
  5. package/android/src/main/java/com/swiftpatch/CrashDetector.kt +79 -0
  6. package/android/src/main/java/com/swiftpatch/CryptoVerifier.kt +69 -0
  7. package/android/src/main/java/com/swiftpatch/DownloadManager.kt +120 -0
  8. package/android/src/main/java/com/swiftpatch/EventQueue.kt +86 -0
  9. package/android/src/main/java/com/swiftpatch/FileUtils.kt +60 -0
  10. package/android/src/main/java/com/swiftpatch/PatchApplier.kt +60 -0
  11. package/android/src/main/java/com/swiftpatch/SignalCrashHandler.kt +84 -0
  12. package/android/src/main/java/com/swiftpatch/SlotManager.kt +299 -0
  13. package/android/src/main/java/com/swiftpatch/SwiftPatchModule.kt +630 -0
  14. package/android/src/main/java/com/swiftpatch/SwiftPatchPackage.kt +21 -0
  15. package/android/src/main/jni/CMakeLists.txt +12 -0
  16. package/android/src/main/jni/bspatch.c +188 -0
  17. package/android/src/main/jni/bspatch.h +57 -0
  18. package/android/src/main/jni/bspatch_jni.c +28 -0
  19. package/ios/Libraries/bspatch/bspatch.c +188 -0
  20. package/ios/Libraries/bspatch/bspatch.h +50 -0
  21. package/ios/Libraries/bspatch/module.modulemap +4 -0
  22. package/ios/SwiftPatch/BundleManager.swift +113 -0
  23. package/ios/SwiftPatch/CrashDetector.swift +71 -0
  24. package/ios/SwiftPatch/CryptoVerifier.swift +70 -0
  25. package/ios/SwiftPatch/DownloadManager.swift +125 -0
  26. package/ios/SwiftPatch/EventQueue.swift +116 -0
  27. package/ios/SwiftPatch/FileUtils.swift +38 -0
  28. package/ios/SwiftPatch/PatchApplier.swift +41 -0
  29. package/ios/SwiftPatch/SignalCrashHandler.swift +129 -0
  30. package/ios/SwiftPatch/SlotManager.swift +360 -0
  31. package/ios/SwiftPatch/SwiftPatchModule.m +56 -0
  32. package/ios/SwiftPatch/SwiftPatchModule.swift +621 -0
  33. package/lib/commonjs/SwiftPatchCore.js +140 -0
  34. package/lib/commonjs/SwiftPatchCore.js.map +1 -0
  35. package/lib/commonjs/SwiftPatchProvider.js +617 -0
  36. package/lib/commonjs/SwiftPatchProvider.js.map +1 -0
  37. package/lib/commonjs/constants.js +50 -0
  38. package/lib/commonjs/constants.js.map +1 -0
  39. package/lib/commonjs/core/Downloader.js +63 -0
  40. package/lib/commonjs/core/Downloader.js.map +1 -0
  41. package/lib/commonjs/core/Installer.js +46 -0
  42. package/lib/commonjs/core/Installer.js.map +1 -0
  43. package/lib/commonjs/core/Rollback.js +36 -0
  44. package/lib/commonjs/core/Rollback.js.map +1 -0
  45. package/lib/commonjs/core/UpdateChecker.js +57 -0
  46. package/lib/commonjs/core/UpdateChecker.js.map +1 -0
  47. package/lib/commonjs/core/Verifier.js +82 -0
  48. package/lib/commonjs/core/Verifier.js.map +1 -0
  49. package/lib/commonjs/core/index.js +41 -0
  50. package/lib/commonjs/core/index.js.map +1 -0
  51. package/lib/commonjs/index.js +154 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/modal/SwiftPatchModal.js +667 -0
  54. package/lib/commonjs/modal/SwiftPatchModal.js.map +1 -0
  55. package/lib/commonjs/modal/useSwiftPatchModal.js +26 -0
  56. package/lib/commonjs/modal/useSwiftPatchModal.js.map +1 -0
  57. package/lib/commonjs/native/NativeSwiftPatch.js +85 -0
  58. package/lib/commonjs/native/NativeSwiftPatch.js.map +1 -0
  59. package/lib/commonjs/native/NativeSwiftPatchSpec.js +15 -0
  60. package/lib/commonjs/native/NativeSwiftPatchSpec.js.map +1 -0
  61. package/lib/commonjs/package.json +1 -0
  62. package/lib/commonjs/types.js +126 -0
  63. package/lib/commonjs/types.js.map +1 -0
  64. package/lib/commonjs/useSwiftPatch.js +31 -0
  65. package/lib/commonjs/useSwiftPatch.js.map +1 -0
  66. package/lib/commonjs/utils/api.js +206 -0
  67. package/lib/commonjs/utils/api.js.map +1 -0
  68. package/lib/commonjs/utils/device.js +23 -0
  69. package/lib/commonjs/utils/device.js.map +1 -0
  70. package/lib/commonjs/utils/logger.js +30 -0
  71. package/lib/commonjs/utils/logger.js.map +1 -0
  72. package/lib/commonjs/utils/storage.js +31 -0
  73. package/lib/commonjs/utils/storage.js.map +1 -0
  74. package/lib/commonjs/withSwiftPatch.js +42 -0
  75. package/lib/commonjs/withSwiftPatch.js.map +1 -0
  76. package/lib/module/SwiftPatchCore.js +135 -0
  77. package/lib/module/SwiftPatchCore.js.map +1 -0
  78. package/lib/module/SwiftPatchProvider.js +611 -0
  79. package/lib/module/SwiftPatchProvider.js.map +1 -0
  80. package/lib/module/constants.js +46 -0
  81. package/lib/module/constants.js.map +1 -0
  82. package/lib/module/core/Downloader.js +57 -0
  83. package/lib/module/core/Downloader.js.map +1 -0
  84. package/lib/module/core/Installer.js +41 -0
  85. package/lib/module/core/Installer.js.map +1 -0
  86. package/lib/module/core/Rollback.js +31 -0
  87. package/lib/module/core/Rollback.js.map +1 -0
  88. package/lib/module/core/UpdateChecker.js +51 -0
  89. package/lib/module/core/UpdateChecker.js.map +1 -0
  90. package/lib/module/core/Verifier.js +76 -0
  91. package/lib/module/core/Verifier.js.map +1 -0
  92. package/lib/module/core/index.js +8 -0
  93. package/lib/module/core/index.js.map +1 -0
  94. package/lib/module/index.js +34 -0
  95. package/lib/module/index.js.map +1 -0
  96. package/lib/module/modal/SwiftPatchModal.js +661 -0
  97. package/lib/module/modal/SwiftPatchModal.js.map +1 -0
  98. package/lib/module/modal/useSwiftPatchModal.js +22 -0
  99. package/lib/module/modal/useSwiftPatchModal.js.map +1 -0
  100. package/lib/module/native/NativeSwiftPatch.js +78 -0
  101. package/lib/module/native/NativeSwiftPatch.js.map +1 -0
  102. package/lib/module/native/NativeSwiftPatchSpec.js +12 -0
  103. package/lib/module/native/NativeSwiftPatchSpec.js.map +1 -0
  104. package/lib/module/types.js +139 -0
  105. package/lib/module/types.js.map +1 -0
  106. package/lib/module/useSwiftPatch.js +26 -0
  107. package/lib/module/useSwiftPatch.js.map +1 -0
  108. package/lib/module/utils/api.js +197 -0
  109. package/lib/module/utils/api.js.map +1 -0
  110. package/lib/module/utils/device.js +18 -0
  111. package/lib/module/utils/device.js.map +1 -0
  112. package/lib/module/utils/logger.js +26 -0
  113. package/lib/module/utils/logger.js.map +1 -0
  114. package/lib/module/utils/storage.js +24 -0
  115. package/lib/module/utils/storage.js.map +1 -0
  116. package/lib/module/withSwiftPatch.js +37 -0
  117. package/lib/module/withSwiftPatch.js.map +1 -0
  118. package/lib/typescript/SwiftPatchCore.d.ts +64 -0
  119. package/lib/typescript/SwiftPatchCore.d.ts.map +1 -0
  120. package/lib/typescript/SwiftPatchProvider.d.ts +22 -0
  121. package/lib/typescript/SwiftPatchProvider.d.ts.map +1 -0
  122. package/lib/typescript/constants.d.ts +33 -0
  123. package/lib/typescript/constants.d.ts.map +1 -0
  124. package/lib/typescript/core/Downloader.d.ts +34 -0
  125. package/lib/typescript/core/Downloader.d.ts.map +1 -0
  126. package/lib/typescript/core/Installer.d.ts +25 -0
  127. package/lib/typescript/core/Installer.d.ts.map +1 -0
  128. package/lib/typescript/core/Rollback.d.ts +18 -0
  129. package/lib/typescript/core/Rollback.d.ts.map +1 -0
  130. package/lib/typescript/core/UpdateChecker.d.ts +27 -0
  131. package/lib/typescript/core/UpdateChecker.d.ts.map +1 -0
  132. package/lib/typescript/core/Verifier.d.ts +31 -0
  133. package/lib/typescript/core/Verifier.d.ts.map +1 -0
  134. package/lib/typescript/core/index.d.ts +8 -0
  135. package/lib/typescript/core/index.d.ts.map +1 -0
  136. package/lib/typescript/index.d.ts +13 -0
  137. package/lib/typescript/index.d.ts.map +1 -0
  138. package/lib/typescript/modal/SwiftPatchModal.d.ts +11 -0
  139. package/lib/typescript/modal/SwiftPatchModal.d.ts.map +1 -0
  140. package/lib/typescript/modal/useSwiftPatchModal.d.ts +7 -0
  141. package/lib/typescript/modal/useSwiftPatchModal.d.ts.map +1 -0
  142. package/lib/typescript/native/NativeSwiftPatch.d.ts +61 -0
  143. package/lib/typescript/native/NativeSwiftPatch.d.ts.map +1 -0
  144. package/lib/typescript/native/NativeSwiftPatchSpec.d.ts +67 -0
  145. package/lib/typescript/native/NativeSwiftPatchSpec.d.ts.map +1 -0
  146. package/lib/typescript/types.d.ts +266 -0
  147. package/lib/typescript/types.d.ts.map +1 -0
  148. package/lib/typescript/useSwiftPatch.d.ts +12 -0
  149. package/lib/typescript/useSwiftPatch.d.ts.map +1 -0
  150. package/lib/typescript/utils/api.d.ts +87 -0
  151. package/lib/typescript/utils/api.d.ts.map +1 -0
  152. package/lib/typescript/utils/device.d.ts +9 -0
  153. package/lib/typescript/utils/device.d.ts.map +1 -0
  154. package/lib/typescript/utils/logger.d.ts +8 -0
  155. package/lib/typescript/utils/logger.d.ts.map +1 -0
  156. package/lib/typescript/utils/storage.d.ts +14 -0
  157. package/lib/typescript/utils/storage.d.ts.map +1 -0
  158. package/lib/typescript/withSwiftPatch.d.ts +12 -0
  159. package/lib/typescript/withSwiftPatch.d.ts.map +1 -0
  160. package/package.json +99 -0
  161. package/react-native-swiftpatch.podspec +50 -0
  162. package/src/SwiftPatchCore.ts +148 -0
  163. package/src/SwiftPatchProvider.tsx +514 -0
  164. package/src/constants.ts +49 -0
  165. package/src/core/Downloader.ts +74 -0
  166. package/src/core/Installer.ts +38 -0
  167. package/src/core/Rollback.ts +28 -0
  168. package/src/core/UpdateChecker.ts +70 -0
  169. package/src/core/Verifier.ts +92 -0
  170. package/src/core/index.ts +11 -0
  171. package/src/index.ts +64 -0
  172. package/src/modal/SwiftPatchModal.tsx +657 -0
  173. package/src/modal/useSwiftPatchModal.ts +24 -0
  174. package/src/native/NativeSwiftPatch.ts +205 -0
  175. package/src/native/NativeSwiftPatchSpec.ts +139 -0
  176. package/src/types.ts +336 -0
  177. package/src/useSwiftPatch.ts +29 -0
  178. package/src/utils/api.ts +244 -0
  179. package/src/utils/device.ts +15 -0
  180. package/src/utils/logger.ts +29 -0
  181. package/src/utils/storage.ts +23 -0
  182. package/src/withSwiftPatch.tsx +41 -0
@@ -0,0 +1,188 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * Copyright 2012 Matthew Endsley
4
+ * All rights reserved
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted providing that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include "bspatch.h"
29
+
30
+ #include <stdlib.h>
31
+ #include <stdio.h>
32
+ #include <string.h>
33
+
34
+ static int64_t offtin(uint8_t *buf)
35
+ {
36
+ int64_t y;
37
+
38
+ y = buf[7] & 0x7F;
39
+ y = y * 256; y += buf[6];
40
+ y = y * 256; y += buf[5];
41
+ y = y * 256; y += buf[4];
42
+ y = y * 256; y += buf[3];
43
+ y = y * 256; y += buf[2];
44
+ y = y * 256; y += buf[1];
45
+ y = y * 256; y += buf[0];
46
+
47
+ if (buf[7] & 0x80) y = -y;
48
+
49
+ return y;
50
+ }
51
+
52
+ int bspatch(const uint8_t* old_data, int64_t old_size,
53
+ uint8_t** new_data, int64_t* new_size,
54
+ const uint8_t* patch_data, int64_t patch_size)
55
+ {
56
+ int64_t newsize;
57
+ int64_t bzctrllen, bzdatalen;
58
+ uint8_t header[32];
59
+ uint8_t buf[8];
60
+ int64_t oldpos, newpos;
61
+ int64_t ctrl[3];
62
+ int64_t i;
63
+ const uint8_t *ctrl_block, *diff_block, *extra_block;
64
+ uint8_t *new_buf;
65
+
66
+ if (patch_size < 32) return -1;
67
+
68
+ /* Read header */
69
+ memcpy(header, patch_data, 32);
70
+
71
+ /* Check for appropriate magic */
72
+ if (memcmp(header, "BSDIFF40", 8) != 0) return -1;
73
+
74
+ /* Read lengths from header */
75
+ bzctrllen = offtin(header + 8);
76
+ bzdatalen = offtin(header + 16);
77
+ newsize = offtin(header + 24);
78
+
79
+ if (bzctrllen < 0 || bzdatalen < 0 || newsize < 0) return -1;
80
+
81
+ /* Set up pointers into patch data */
82
+ ctrl_block = patch_data + 32;
83
+ diff_block = ctrl_block + bzctrllen;
84
+ extra_block = diff_block + bzdatalen;
85
+
86
+ /* Allocate new buffer */
87
+ new_buf = (uint8_t*)malloc(newsize + 1);
88
+ if (new_buf == NULL) return -1;
89
+
90
+ oldpos = 0;
91
+ newpos = 0;
92
+
93
+ while (newpos < newsize) {
94
+ /* Read control data */
95
+ for (i = 0; i < 3; i++) {
96
+ memcpy(buf, ctrl_block, 8);
97
+ ctrl_block += 8;
98
+ ctrl[i] = offtin(buf);
99
+ }
100
+
101
+ /* Sanity check */
102
+ if (newpos + ctrl[0] > newsize) {
103
+ free(new_buf);
104
+ return -1;
105
+ }
106
+
107
+ /* Read diff string */
108
+ memcpy(new_buf + newpos, diff_block, ctrl[0]);
109
+ diff_block += ctrl[0];
110
+
111
+ /* Add old data to diff string */
112
+ for (i = 0; i < ctrl[0]; i++) {
113
+ if ((oldpos + i >= 0) && (oldpos + i < old_size)) {
114
+ new_buf[newpos + i] += old_data[oldpos + i];
115
+ }
116
+ }
117
+
118
+ /* Adjust pointers */
119
+ newpos += ctrl[0];
120
+ oldpos += ctrl[0];
121
+
122
+ /* Sanity check */
123
+ if (newpos + ctrl[1] > newsize) {
124
+ free(new_buf);
125
+ return -1;
126
+ }
127
+
128
+ /* Read extra string */
129
+ memcpy(new_buf + newpos, extra_block, ctrl[1]);
130
+ extra_block += ctrl[1];
131
+
132
+ newpos += ctrl[1];
133
+ oldpos += ctrl[2];
134
+ }
135
+
136
+ *new_data = new_buf;
137
+ *new_size = newsize;
138
+
139
+ return 0;
140
+ }
141
+
142
+ int bspatch_files(const char* old_path, const char* patch_path, const char* new_path)
143
+ {
144
+ FILE *f;
145
+ uint8_t *old_data = NULL, *patch_data = NULL, *new_data = NULL;
146
+ int64_t old_size, patch_size, new_size;
147
+ int result = -1;
148
+
149
+ /* Read old file */
150
+ f = fopen(old_path, "rb");
151
+ if (f == NULL) goto cleanup;
152
+ fseek(f, 0, SEEK_END);
153
+ old_size = ftell(f);
154
+ fseek(f, 0, SEEK_SET);
155
+ old_data = (uint8_t*)malloc(old_size);
156
+ if (old_data == NULL) { fclose(f); goto cleanup; }
157
+ if (fread(old_data, 1, old_size, f) != (size_t)old_size) { fclose(f); goto cleanup; }
158
+ fclose(f);
159
+
160
+ /* Read patch file */
161
+ f = fopen(patch_path, "rb");
162
+ if (f == NULL) goto cleanup;
163
+ fseek(f, 0, SEEK_END);
164
+ patch_size = ftell(f);
165
+ fseek(f, 0, SEEK_SET);
166
+ patch_data = (uint8_t*)malloc(patch_size);
167
+ if (patch_data == NULL) { fclose(f); goto cleanup; }
168
+ if (fread(patch_data, 1, patch_size, f) != (size_t)patch_size) { fclose(f); goto cleanup; }
169
+ fclose(f);
170
+
171
+ /* Apply patch */
172
+ if (bspatch(old_data, old_size, &new_data, &new_size, patch_data, patch_size) != 0)
173
+ goto cleanup;
174
+
175
+ /* Write new file */
176
+ f = fopen(new_path, "wb");
177
+ if (f == NULL) goto cleanup;
178
+ if (fwrite(new_data, 1, new_size, f) != (size_t)new_size) { fclose(f); goto cleanup; }
179
+ fclose(f);
180
+
181
+ result = 0;
182
+
183
+ cleanup:
184
+ free(old_data);
185
+ free(patch_data);
186
+ free(new_data);
187
+ return result;
188
+ }
@@ -0,0 +1,57 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * All rights reserved
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted providing that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ * POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+
27
+ #ifndef BSPATCH_H
28
+ #define BSPATCH_H
29
+
30
+ #include <stdint.h>
31
+
32
+ /**
33
+ * Apply a bsdiff patch.
34
+ *
35
+ * @param old_data Pointer to the old file data
36
+ * @param old_size Size of the old file
37
+ * @param new_data Output pointer that will be allocated with the new file data
38
+ * @param new_size Output size of the new file
39
+ * @param patch_data Pointer to the patch file data
40
+ * @param patch_size Size of the patch file
41
+ * @return 0 on success, -1 on failure
42
+ */
43
+ int bspatch(const uint8_t* old_data, int64_t old_size,
44
+ uint8_t** new_data, int64_t* new_size,
45
+ const uint8_t* patch_data, int64_t patch_size);
46
+
47
+ /**
48
+ * Apply a bsdiff patch using file paths.
49
+ *
50
+ * @param old_path Path to the old file
51
+ * @param patch_path Path to the patch file
52
+ * @param new_path Path to write the new file
53
+ * @return 0 on success, non-zero on failure
54
+ */
55
+ int bspatch_files(const char* old_path, const char* patch_path, const char* new_path);
56
+
57
+ #endif /* BSPATCH_H */
@@ -0,0 +1,28 @@
1
+ /*
2
+ * JNI wrapper for bspatch
3
+ */
4
+
5
+ #include <jni.h>
6
+ #include <string.h>
7
+ #include "bspatch.h"
8
+
9
+ JNIEXPORT jint JNICALL
10
+ Java_com_swiftpatch_PatchApplier_nativeApplyPatch(
11
+ JNIEnv *env,
12
+ jobject thiz,
13
+ jstring old_path,
14
+ jstring patch_path,
15
+ jstring new_path)
16
+ {
17
+ const char *old_path_str = (*env)->GetStringUTFChars(env, old_path, NULL);
18
+ const char *patch_path_str = (*env)->GetStringUTFChars(env, patch_path, NULL);
19
+ const char *new_path_str = (*env)->GetStringUTFChars(env, new_path, NULL);
20
+
21
+ int result = bspatch_files(old_path_str, patch_path_str, new_path_str);
22
+
23
+ (*env)->ReleaseStringUTFChars(env, old_path, old_path_str);
24
+ (*env)->ReleaseStringUTFChars(env, patch_path, patch_path_str);
25
+ (*env)->ReleaseStringUTFChars(env, new_path, new_path_str);
26
+
27
+ return result;
28
+ }
@@ -0,0 +1,188 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * Copyright 2012 Matthew Endsley
4
+ * All rights reserved
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted providing that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include "bspatch.h"
29
+
30
+ #include <stdlib.h>
31
+ #include <stdio.h>
32
+ #include <string.h>
33
+
34
+ static int64_t offtin(uint8_t *buf)
35
+ {
36
+ int64_t y;
37
+
38
+ y = buf[7] & 0x7F;
39
+ y = y * 256; y += buf[6];
40
+ y = y * 256; y += buf[5];
41
+ y = y * 256; y += buf[4];
42
+ y = y * 256; y += buf[3];
43
+ y = y * 256; y += buf[2];
44
+ y = y * 256; y += buf[1];
45
+ y = y * 256; y += buf[0];
46
+
47
+ if (buf[7] & 0x80) y = -y;
48
+
49
+ return y;
50
+ }
51
+
52
+ static int bspatch_internal(const uint8_t* old_data, int64_t old_size,
53
+ uint8_t** new_data, int64_t* new_size,
54
+ const uint8_t* patch_data, int64_t patch_size)
55
+ {
56
+ int64_t newsize;
57
+ int64_t bzctrllen, bzdatalen;
58
+ uint8_t header[32];
59
+ uint8_t buf[8];
60
+ int64_t oldpos, newpos;
61
+ int64_t ctrl[3];
62
+ int64_t i;
63
+ const uint8_t *ctrl_block, *diff_block, *extra_block;
64
+ uint8_t *new_buf;
65
+
66
+ if (patch_size < 32) return -1;
67
+
68
+ /* Read header */
69
+ memcpy(header, patch_data, 32);
70
+
71
+ /* Check for appropriate magic */
72
+ if (memcmp(header, "BSDIFF40", 8) != 0) return -1;
73
+
74
+ /* Read lengths from header */
75
+ bzctrllen = offtin(header + 8);
76
+ bzdatalen = offtin(header + 16);
77
+ newsize = offtin(header + 24);
78
+
79
+ if (bzctrllen < 0 || bzdatalen < 0 || newsize < 0) return -1;
80
+
81
+ /* Set up pointers into patch data */
82
+ ctrl_block = patch_data + 32;
83
+ diff_block = ctrl_block + bzctrllen;
84
+ extra_block = diff_block + bzdatalen;
85
+
86
+ /* Allocate new buffer */
87
+ new_buf = (uint8_t*)malloc((size_t)(newsize + 1));
88
+ if (new_buf == NULL) return -1;
89
+
90
+ oldpos = 0;
91
+ newpos = 0;
92
+
93
+ while (newpos < newsize) {
94
+ /* Read control data */
95
+ for (i = 0; i < 3; i++) {
96
+ memcpy(buf, ctrl_block, 8);
97
+ ctrl_block += 8;
98
+ ctrl[i] = offtin(buf);
99
+ }
100
+
101
+ /* Sanity check */
102
+ if (newpos + ctrl[0] > newsize) {
103
+ free(new_buf);
104
+ return -1;
105
+ }
106
+
107
+ /* Read diff string */
108
+ memcpy(new_buf + newpos, diff_block, (size_t)ctrl[0]);
109
+ diff_block += ctrl[0];
110
+
111
+ /* Add old data to diff string */
112
+ for (i = 0; i < ctrl[0]; i++) {
113
+ if ((oldpos + i >= 0) && (oldpos + i < old_size)) {
114
+ new_buf[newpos + i] += old_data[oldpos + i];
115
+ }
116
+ }
117
+
118
+ /* Adjust pointers */
119
+ newpos += ctrl[0];
120
+ oldpos += ctrl[0];
121
+
122
+ /* Sanity check */
123
+ if (newpos + ctrl[1] > newsize) {
124
+ free(new_buf);
125
+ return -1;
126
+ }
127
+
128
+ /* Read extra string */
129
+ memcpy(new_buf + newpos, extra_block, (size_t)ctrl[1]);
130
+ extra_block += ctrl[1];
131
+
132
+ newpos += ctrl[1];
133
+ oldpos += ctrl[2];
134
+ }
135
+
136
+ *new_data = new_buf;
137
+ *new_size = newsize;
138
+
139
+ return 0;
140
+ }
141
+
142
+ int bspatch_files(const char* old_path, const char* patch_path, const char* new_path)
143
+ {
144
+ FILE *f;
145
+ uint8_t *old_data = NULL, *patch_data = NULL, *new_data = NULL;
146
+ int64_t old_size, patch_size, new_size;
147
+ int result = -1;
148
+
149
+ /* Read old file */
150
+ f = fopen(old_path, "rb");
151
+ if (f == NULL) goto cleanup;
152
+ fseek(f, 0, SEEK_END);
153
+ old_size = ftell(f);
154
+ fseek(f, 0, SEEK_SET);
155
+ old_data = (uint8_t*)malloc((size_t)old_size);
156
+ if (old_data == NULL) { fclose(f); goto cleanup; }
157
+ if (fread(old_data, 1, (size_t)old_size, f) != (size_t)old_size) { fclose(f); goto cleanup; }
158
+ fclose(f);
159
+
160
+ /* Read patch file */
161
+ f = fopen(patch_path, "rb");
162
+ if (f == NULL) goto cleanup;
163
+ fseek(f, 0, SEEK_END);
164
+ patch_size = ftell(f);
165
+ fseek(f, 0, SEEK_SET);
166
+ patch_data = (uint8_t*)malloc((size_t)patch_size);
167
+ if (patch_data == NULL) { fclose(f); goto cleanup; }
168
+ if (fread(patch_data, 1, (size_t)patch_size, f) != (size_t)patch_size) { fclose(f); goto cleanup; }
169
+ fclose(f);
170
+
171
+ /* Apply patch */
172
+ if (bspatch_internal(old_data, old_size, &new_data, &new_size, patch_data, patch_size) != 0)
173
+ goto cleanup;
174
+
175
+ /* Write new file */
176
+ f = fopen(new_path, "wb");
177
+ if (f == NULL) goto cleanup;
178
+ if (fwrite(new_data, 1, (size_t)new_size, f) != (size_t)new_size) { fclose(f); goto cleanup; }
179
+ fclose(f);
180
+
181
+ result = 0;
182
+
183
+ cleanup:
184
+ free(old_data);
185
+ free(patch_data);
186
+ free(new_data);
187
+ return result;
188
+ }
@@ -0,0 +1,50 @@
1
+ /*-
2
+ * Copyright 2003-2005 Colin Percival
3
+ * All rights reserved
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted providing that the following conditions
7
+ * are met:
8
+ * 1. Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ * POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+
27
+ #ifndef BSPATCH_H
28
+ #define BSPATCH_H
29
+
30
+ #include <stdint.h>
31
+
32
+ #ifdef __cplusplus
33
+ extern "C" {
34
+ #endif
35
+
36
+ /**
37
+ * Apply a bsdiff patch using file paths.
38
+ *
39
+ * @param old_path Path to the old file
40
+ * @param patch_path Path to the patch file
41
+ * @param new_path Path to write the new file
42
+ * @return 0 on success, non-zero on failure
43
+ */
44
+ int bspatch_files(const char* old_path, const char* patch_path, const char* new_path);
45
+
46
+ #ifdef __cplusplus
47
+ }
48
+ #endif
49
+
50
+ #endif /* BSPATCH_H */
@@ -0,0 +1,4 @@
1
+ module BSpatch {
2
+ header "bspatch.h"
3
+ export *
4
+ }
@@ -0,0 +1,113 @@
1
+ import Foundation
2
+
3
+ class BundleManager {
4
+
5
+ var baseDir: URL {
6
+ let documentsDir = FileManager.default.urls(
7
+ for: .documentDirectory,
8
+ in: .userDomainMask
9
+ ).first!
10
+ return documentsDir.appendingPathComponent("swiftpatch")
11
+ }
12
+
13
+ private var bundlesDir: URL {
14
+ baseDir.appendingPathComponent("bundles")
15
+ }
16
+
17
+ private var patchesDir: URL {
18
+ baseDir.appendingPathComponent("patches")
19
+ }
20
+
21
+ private var tempDir: URL {
22
+ baseDir.appendingPathComponent("temp")
23
+ }
24
+
25
+ /// Ensure all required directories exist
26
+ func ensureDirectoriesExist() {
27
+ let fm = FileManager.default
28
+ try? fm.createDirectory(at: bundlesDir, withIntermediateDirectories: true)
29
+ try? fm.createDirectory(at: patchesDir, withIntermediateDirectories: true)
30
+ try? fm.createDirectory(at: tempDir, withIntermediateDirectories: true)
31
+ }
32
+
33
+ /// Get the file URL for a downloaded update (before processing)
34
+ func getDownloadFile(hash: String) -> URL {
35
+ tempDir.appendingPathComponent("\(hash).download")
36
+ }
37
+
38
+ /// Get the file URL for a decompressed file
39
+ func getDecompressedFile(hash: String) -> URL {
40
+ tempDir.appendingPathComponent("\(hash).decompressed")
41
+ }
42
+
43
+ /// Get the file URL for a bundle by its hash
44
+ func getBundleFile(hash: String) -> URL {
45
+ bundlesDir.appendingPathComponent("\(hash).bundle")
46
+ }
47
+
48
+ /// Extract the original bundled JS bundle from the app bundle
49
+ func extractOriginalBundle() throws -> URL {
50
+ let originalFile = tempDir.appendingPathComponent("original.bundle")
51
+
52
+ if FileManager.default.fileExists(atPath: originalFile.path) {
53
+ return originalFile
54
+ }
55
+
56
+ // Try main.jsbundle first
57
+ if let bundledURL = Bundle.main.url(forResource: "main", withExtension: "jsbundle") {
58
+ try FileManager.default.copyItem(at: bundledURL, to: originalFile)
59
+ return originalFile
60
+ }
61
+
62
+ // Try index.ios.bundle
63
+ if let bundledURL = Bundle.main.url(forResource: "index.ios", withExtension: "bundle") {
64
+ try FileManager.default.copyItem(at: bundledURL, to: originalFile)
65
+ return originalFile
66
+ }
67
+
68
+ throw SwiftPatchError.patchFailed
69
+ }
70
+
71
+ /// Clean up old bundles that are no longer needed
72
+ func cleanupOldBundles(userDefaults: UserDefaults, prefsKey: String) {
73
+ let currentHash = userDefaults.string(forKey: "\(prefsKey)_current_bundle_hash")
74
+ let previousHash = userDefaults.string(forKey: "\(prefsKey)_previous_bundle_hash")
75
+
76
+ let keepHashes = Set([currentHash, previousHash].compactMap { $0 })
77
+
78
+ let fm = FileManager.default
79
+
80
+ // Clean up bundles
81
+ if let files = try? fm.contentsOfDirectory(
82
+ at: bundlesDir,
83
+ includingPropertiesForKeys: nil
84
+ ) {
85
+ for file in files {
86
+ let fileHash = file.deletingPathExtension().lastPathComponent
87
+ if !keepHashes.contains(fileHash) {
88
+ try? fm.removeItem(at: file)
89
+ }
90
+ }
91
+ }
92
+
93
+ // Clean up temp directory
94
+ if let files = try? fm.contentsOfDirectory(
95
+ at: tempDir,
96
+ includingPropertiesForKeys: nil
97
+ ) {
98
+ for file in files {
99
+ try? fm.removeItem(at: file)
100
+ }
101
+ }
102
+
103
+ // Clean up patches
104
+ if let files = try? fm.contentsOfDirectory(
105
+ at: patchesDir,
106
+ includingPropertiesForKeys: nil
107
+ ) {
108
+ for file in files {
109
+ try? fm.removeItem(at: file)
110
+ }
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,71 @@
1
+ import Foundation
2
+
3
+ class CrashDetector {
4
+
5
+ private static let crashDetectionWindowSeconds: TimeInterval = 10.0
6
+ private static let maxCrashesBeforeRollback = 2
7
+
8
+ private let userDefaults: UserDefaults
9
+ private let prefsKey: String
10
+
11
+ init(userDefaults: UserDefaults, prefsKey: String) {
12
+ self.userDefaults = userDefaults
13
+ self.prefsKey = prefsKey
14
+ }
15
+
16
+ /// Check if we need to rollback due to a crash after install.
17
+ /// Called during native module initialization.
18
+ func checkForPendingRollback(onRollback: @escaping (String) -> Void) {
19
+ let pendingConfirmation = userDefaults.bool(
20
+ forKey: "\(prefsKey)_pending_install_confirmation"
21
+ )
22
+ guard pendingConfirmation else { return }
23
+
24
+ let installTimestamp = userDefaults.double(
25
+ forKey: "\(prefsKey)_install_timestamp"
26
+ )
27
+ let currentTime = Date().timeIntervalSince1970
28
+
29
+ if currentTime - installTimestamp < Self.crashDetectionWindowSeconds {
30
+ // Within crash detection window - this might be a crash-restart cycle
31
+ let crashCount = userDefaults.integer(forKey: "\(prefsKey)_crash_count") + 1
32
+
33
+ if crashCount >= Self.maxCrashesBeforeRollback {
34
+ let reason = "Automatic rollback after \(crashCount) crashes"
35
+ performRollback(reason: reason)
36
+ onRollback("Crashed \(crashCount) times within detection window")
37
+ } else {
38
+ userDefaults.set(crashCount, forKey: "\(prefsKey)_crash_count")
39
+ }
40
+ } else {
41
+ // We survived the crash detection window, mark as stable
42
+ confirmStable()
43
+ }
44
+ }
45
+
46
+ /// Mark the current installation as stable
47
+ func confirmStable() {
48
+ userDefaults.set(false, forKey: "\(prefsKey)_pending_install_confirmation")
49
+ userDefaults.set(0, forKey: "\(prefsKey)_crash_count")
50
+ }
51
+
52
+ private func performRollback(reason: String) {
53
+ let previousHash = userDefaults.string(forKey: "\(prefsKey)_previous_bundle_hash")
54
+ let previousPath = userDefaults.string(forKey: "\(prefsKey)_previous_bundle_path")
55
+
56
+ if let hash = previousHash, let path = previousPath {
57
+ userDefaults.set(hash, forKey: "\(prefsKey)_current_bundle_hash")
58
+ userDefaults.set(path, forKey: "\(prefsKey)_current_bundle_path")
59
+ userDefaults.removeObject(forKey: "\(prefsKey)_previous_bundle_hash")
60
+ userDefaults.removeObject(forKey: "\(prefsKey)_previous_bundle_path")
61
+ } else {
62
+ // Rollback to original bundled version
63
+ userDefaults.removeObject(forKey: "\(prefsKey)_current_bundle_hash")
64
+ userDefaults.removeObject(forKey: "\(prefsKey)_current_bundle_path")
65
+ }
66
+
67
+ userDefaults.set(false, forKey: "\(prefsKey)_pending_install_confirmation")
68
+ userDefaults.set(0, forKey: "\(prefsKey)_crash_count")
69
+ userDefaults.set(reason, forKey: "\(prefsKey)_last_rollback_reason")
70
+ }
71
+ }