@revopush/react-native-code-push 1.5.0 → 2.5.0-rc.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.
- package/CodePush.js +8 -5
- package/CodePush.podspec +9 -0
- package/android/build.gradle +52 -40
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +3 -1
- package/android/gradle.properties +1 -1
- package/android/libs/revopush-diff-release-v0.0.1.aar +0 -0
- package/android/settings.gradle +31 -0
- package/android/src/main/java/com/microsoft/codepush/react/CodePush.java +8 -4
- package/android/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +11 -7
- package/android/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +48 -41
- package/android/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +67 -175
- package/android/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +7 -244
- package/android/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +16 -51
- package/android/src/main/java/com/microsoft/codepush/react/FileUtils.java +1 -130
- package/ios/CodePush/CodePush.h +1 -30
- package/ios/CodePush/CodePush.m +23 -7
- package/ios/CodePush/CodePushPackage.m +363 -294
- package/ios/CodePush/CodePushUpdateUtils.m +77 -28
- package/ios/CodePush.xcodeproj/project.pbxproj +0 -18
- package/ios/Frameworks/DiffUpdates.xcframework/Info.plist +44 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64/DiffUpdates.framework/DiffUpdates +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64/DiffUpdates.framework/Headers/DiffUpdates.h +61 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64/DiffUpdates.framework/Info.plist +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64/DiffUpdates.framework/Modules/module.modulemap +6 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/DiffUpdates +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/Headers/DiffUpdates.h +61 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/Info.plist +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/Modules/module.modulemap +6 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/_CodeSignature/CodeDirectory +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/_CodeSignature/CodeRequirements +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/_CodeSignature/CodeRequirements-1 +0 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/_CodeSignature/CodeResources +132 -0
- package/ios/Frameworks/DiffUpdates.xcframework/ios-arm64_x86_64-simulator/DiffUpdates.framework/_CodeSignature/CodeSignature +0 -0
- package/package.json +2 -2
- package/request-fetch-adapter.js +2 -2
- package/scripts/generateBundledResourcesHash.js +102 -65
- package/android/src/main/java/com/microsoft/codepush/react/TLSSocketFactory.java +0 -72
- package/ios/CodePush/CodePushDownloadHandler.m +0 -130
- package/ios/CodePush/CodePushErrorUtils.m +0 -20
- package/ios/CodePush/CodePushUtils.m +0 -9
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
#import "SSZipArchive.h"
|
|
6
6
|
#endif
|
|
7
7
|
|
|
8
|
+
#import <DiffUpdates/DiffUpdates.h>
|
|
9
|
+
|
|
8
10
|
@implementation CodePushPackage
|
|
9
11
|
|
|
10
12
|
#pragma mark - Private constants
|
|
@@ -31,7 +33,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
31
33
|
NSString *downloadedBundle = [NSString stringWithContentsOfURL:urlRequest
|
|
32
34
|
encoding:NSUTF8StringEncoding
|
|
33
35
|
error:&error];
|
|
34
|
-
|
|
36
|
+
|
|
35
37
|
if (error) {
|
|
36
38
|
CPLog(@"Error downloading from URL %@", remoteBundleUrl);
|
|
37
39
|
} else {
|
|
@@ -51,11 +53,12 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
51
53
|
doneCallback:(void (^)())doneCallback
|
|
52
54
|
failCallback:(void (^)(NSError *err))failCallback
|
|
53
55
|
{
|
|
56
|
+
CPLog(@"updatePackage = %@", updatePackage);
|
|
54
57
|
NSString *newUpdateHash = updatePackage[@"packageHash"];
|
|
55
58
|
NSString *newUpdateFolderPath = [self getPackageFolderPath:newUpdateHash];
|
|
56
59
|
NSString *newUpdateMetadataPath = [newUpdateFolderPath stringByAppendingPathComponent:UpdateMetadataFileName];
|
|
57
60
|
NSError *error;
|
|
58
|
-
|
|
61
|
+
|
|
59
62
|
if ([[NSFileManager defaultManager] fileExistsAtPath:newUpdateFolderPath]) {
|
|
60
63
|
// This removes any stale data in newUpdateFolderPath that could have been left
|
|
61
64
|
// uncleared due to a crash or error during the download or install process.
|
|
@@ -66,282 +69,348 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
66
69
|
withIntermediateDirectories:YES
|
|
67
70
|
attributes:nil
|
|
68
71
|
error:&error];
|
|
69
|
-
|
|
72
|
+
|
|
70
73
|
// Ensure that none of the CodePush updates we store on disk are
|
|
71
74
|
// ever included in the end users iTunes and/or iCloud backups
|
|
72
75
|
NSURL *codePushURL = [NSURL fileURLWithPath:[self getCodePushPath]];
|
|
73
76
|
[codePushURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
|
|
74
77
|
}
|
|
75
|
-
|
|
78
|
+
|
|
76
79
|
if (error) {
|
|
77
80
|
return failCallback(error);
|
|
78
81
|
}
|
|
79
|
-
|
|
82
|
+
|
|
80
83
|
NSString *downloadFilePath = [self getDownloadFilePath];
|
|
81
84
|
NSString *bundleFilePath = [newUpdateFolderPath stringByAppendingPathComponent:UpdateBundleFileName];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
85
|
+
|
|
86
|
+
id rawDiff = updatePackage[@"bundleDiffBlobUrl"] ?: updatePackage[@"bundle_diff_blob_url"];
|
|
87
|
+
NSString *bundleDiffUrl = [rawDiff isKindOfClass:NSString.class] ? (NSString *)rawDiff : nil;
|
|
88
|
+
NSString *assetsUrl = updatePackage[@"assetDownloadUrl"] ?: updatePackage[@"asset_download_url"];
|
|
89
|
+
NSString *assetHash = updatePackage[@"assetHash"] ?: updatePackage[@"asset_hash"];
|
|
90
|
+
NSString *singleUrl = updatePackage[@"downloadUrl"] ?: updatePackage[@"download_url"];
|
|
91
|
+
|
|
92
|
+
__block BOOL cameFromDiffHandler = (bundleDiffUrl.length > 0);
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
void (^commonDone)(BOOL) = ^(BOOL isZip) {
|
|
96
|
+
NSError *error = nil;
|
|
97
|
+
NSString * unzippedFolderPath = [CodePushPackage getUnzippedFolderPath];
|
|
98
|
+
NSMutableDictionary * mutableUpdatePackage = [updatePackage mutableCopy];
|
|
99
|
+
if (isZip) {
|
|
100
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:unzippedFolderPath]) {
|
|
101
|
+
// This removes any unzipped download data that could have been left
|
|
102
|
+
// uncleared due to a crash or error during the download process.
|
|
103
|
+
[[NSFileManager defaultManager] removeItemAtPath:unzippedFolderPath
|
|
104
|
+
error:&error];
|
|
105
|
+
if (error) {
|
|
106
|
+
failCallback(error);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
NSError *nonFailingError = nil;
|
|
112
|
+
[SSZipArchive unzipFileAtPath:downloadFilePath
|
|
113
|
+
toDestination:unzippedFolderPath];
|
|
114
|
+
[[NSFileManager defaultManager] removeItemAtPath:downloadFilePath
|
|
115
|
+
error:&nonFailingError];
|
|
116
|
+
if (nonFailingError) {
|
|
117
|
+
CPLog(@"Error deleting downloaded file: %@", nonFailingError);
|
|
118
|
+
nonFailingError = nil;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
NSString *diffManifestFilePath = [unzippedFolderPath stringByAppendingPathComponent:DiffManifestFileName];
|
|
122
|
+
BOOL isDiffUpdate = [[NSFileManager defaultManager] fileExistsAtPath:diffManifestFilePath];
|
|
123
|
+
|
|
124
|
+
if (isDiffUpdate) {
|
|
125
|
+
// Copy the current package to the new package.
|
|
126
|
+
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:&error];
|
|
127
|
+
if (error) {
|
|
128
|
+
failCallback(error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (currentPackageFolderPath == nil) {
|
|
133
|
+
// Currently running the binary version, copy files from the bundled resources
|
|
134
|
+
NSString *newUpdateCodePushPath = [newUpdateFolderPath stringByAppendingPathComponent:[CodePushUpdateUtils manifestFolderPrefix]];
|
|
135
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:newUpdateCodePushPath
|
|
136
|
+
withIntermediateDirectories:YES
|
|
137
|
+
attributes:nil
|
|
138
|
+
error:&error];
|
|
139
|
+
if (error) {
|
|
140
|
+
failCallback(error);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
[[NSFileManager defaultManager] copyItemAtPath:[CodePush bundleAssetsPath]
|
|
145
|
+
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[CodePushUpdateUtils assetsFolderName]]
|
|
146
|
+
error:&error];
|
|
147
|
+
if (error) {
|
|
148
|
+
failCallback(error);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
[[NSFileManager defaultManager] copyItemAtPath:[[CodePush binaryBundleURL] path]
|
|
153
|
+
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[[CodePush binaryBundleURL] lastPathComponent]]
|
|
154
|
+
error:&error];
|
|
155
|
+
if (error) {
|
|
156
|
+
failCallback(error);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
[[NSFileManager defaultManager] copyItemAtPath:currentPackageFolderPath
|
|
161
|
+
toPath:newUpdateFolderPath
|
|
162
|
+
error:&error];
|
|
163
|
+
if (error) {
|
|
164
|
+
failCallback(error);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Delete files mentioned in the manifest.
|
|
170
|
+
NSString *manifestContent = [NSString stringWithContentsOfFile:diffManifestFilePath
|
|
171
|
+
encoding:NSUTF8StringEncoding
|
|
172
|
+
error:&error];
|
|
173
|
+
if (error) {
|
|
174
|
+
failCallback(error);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
NSData *data = [manifestContent dataUsingEncoding:NSUTF8StringEncoding];
|
|
179
|
+
NSDictionary *manifestJSON = [NSJSONSerialization JSONObjectWithData:data
|
|
180
|
+
options:kNilOptions
|
|
181
|
+
error:&error];
|
|
182
|
+
NSArray *deletedFiles = manifestJSON[@"deletedFiles"];
|
|
183
|
+
for (NSString *deletedFileName in deletedFiles) {
|
|
184
|
+
NSString *absoluteDeletedFilePath = [newUpdateFolderPath stringByAppendingPathComponent:deletedFileName];
|
|
185
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:absoluteDeletedFilePath]) {
|
|
186
|
+
[[NSFileManager defaultManager] removeItemAtPath:absoluteDeletedFilePath
|
|
187
|
+
error:&error];
|
|
188
|
+
if (error) {
|
|
189
|
+
failCallback(error);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
[[NSFileManager defaultManager] removeItemAtPath:diffManifestFilePath
|
|
196
|
+
error:&error];
|
|
197
|
+
if (error) {
|
|
198
|
+
failCallback(error);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
[CodePushUpdateUtils copyEntriesInFolder:unzippedFolderPath
|
|
204
|
+
destFolder:newUpdateFolderPath
|
|
205
|
+
error:&error];
|
|
206
|
+
if (error) {
|
|
207
|
+
failCallback(error);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
[[NSFileManager defaultManager] removeItemAtPath:unzippedFolderPath
|
|
212
|
+
error:&nonFailingError];
|
|
213
|
+
if (nonFailingError) {
|
|
214
|
+
CPLog(@"Error deleting downloaded file: %@", nonFailingError);
|
|
215
|
+
nonFailingError = nil;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
NSString *relativeBundlePath = [CodePushUpdateUtils findMainBundleInFolder:newUpdateFolderPath
|
|
219
|
+
expectedFileName:expectedBundleFileName
|
|
220
|
+
error:&error];
|
|
221
|
+
|
|
222
|
+
if (error) {
|
|
223
|
+
failCallback(error);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (relativeBundlePath) {
|
|
228
|
+
[mutableUpdatePackage setValue:relativeBundlePath forKey:RelativeBundlePathKey];
|
|
229
|
+
} else {
|
|
230
|
+
NSString *errorMessage = [NSString stringWithFormat:@"Update is invalid - A JS bundle file named \"%@\" could not be found within the downloaded contents. Please ensure that your app is syncing with the correct deployment and that you are releasing your CodePush updates using the exact same JS bundle file name that was shipped with your app's binary.", expectedBundleFileName];
|
|
231
|
+
|
|
232
|
+
error = [CodePushErrorUtils errorWithMessage:errorMessage];
|
|
233
|
+
|
|
234
|
+
failCallback(error);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:newUpdateMetadataPath]) {
|
|
239
|
+
[[NSFileManager defaultManager] removeItemAtPath:newUpdateMetadataPath
|
|
240
|
+
error:&error];
|
|
241
|
+
if (error) {
|
|
242
|
+
failCallback(error);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
CPLog((isDiffUpdate) ? @"Applying diff update." : @"Applying full update.");
|
|
248
|
+
|
|
249
|
+
BOOL isSignatureVerificationEnabled = (publicKey != nil);
|
|
250
|
+
|
|
251
|
+
NSString *signatureFilePath = [CodePushUpdateUtils getSignatureFilePath:newUpdateFolderPath];
|
|
252
|
+
BOOL isSignatureAppearedInBundle = [[NSFileManager defaultManager] fileExistsAtPath:signatureFilePath];
|
|
253
|
+
|
|
254
|
+
if (isSignatureVerificationEnabled) {
|
|
255
|
+
if (isSignatureAppearedInBundle) {
|
|
256
|
+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
|
|
257
|
+
expectedHash:newUpdateHash
|
|
258
|
+
error:&error]) {
|
|
259
|
+
CPLog(@"The update contents failed the data integrity check.");
|
|
260
|
+
if (!error) {
|
|
261
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
failCallback(error);
|
|
265
|
+
return;
|
|
266
|
+
} else {
|
|
267
|
+
CPLog(@"The update contents succeeded the data integrity check.");
|
|
268
|
+
}
|
|
269
|
+
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
|
|
270
|
+
expectedHash:newUpdateHash
|
|
271
|
+
withPublicKey:publicKey
|
|
272
|
+
error:&error];
|
|
273
|
+
if (!isSignatureValid) {
|
|
274
|
+
CPLog(@"The update contents failed code signing check.");
|
|
275
|
+
if (!error) {
|
|
276
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
|
|
277
|
+
}
|
|
278
|
+
failCallback(error);
|
|
279
|
+
return;
|
|
280
|
+
} else {
|
|
281
|
+
CPLog(@"The update contents succeeded the code signing check.");
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
error = [CodePushErrorUtils errorWithMessage:
|
|
285
|
+
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
|
|
286
|
+
"Possible reasons, why that might happen: \n" \
|
|
287
|
+
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
|
|
288
|
+
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
|
|
289
|
+
failCallback(error);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
} else {
|
|
294
|
+
BOOL needToVerifyHash;
|
|
295
|
+
if (isSignatureAppearedInBundle) {
|
|
296
|
+
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
|
|
297
|
+
" because there is no public key configured. " \
|
|
298
|
+
"Please ensure that public key is properly configured within your application.");
|
|
299
|
+
needToVerifyHash = true;
|
|
300
|
+
} else {
|
|
301
|
+
needToVerifyHash = (isDiffUpdate || cameFromDiffHandler);
|
|
302
|
+
}
|
|
303
|
+
if(needToVerifyHash){
|
|
304
|
+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
|
|
305
|
+
expectedHash:newUpdateHash
|
|
306
|
+
error:&error]) {
|
|
307
|
+
CPLog(@"The update contents failed the data integrity check.");
|
|
308
|
+
if (!error) {
|
|
309
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
failCallback(error);
|
|
313
|
+
return;
|
|
314
|
+
} else {
|
|
315
|
+
CPLog(@"The update contents succeeded the data integrity check.");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:newUpdateFolderPath
|
|
321
|
+
withIntermediateDirectories:YES
|
|
322
|
+
attributes:nil
|
|
323
|
+
error:&error];
|
|
324
|
+
[[NSFileManager defaultManager] moveItemAtPath:downloadFilePath
|
|
325
|
+
toPath:bundleFilePath
|
|
326
|
+
error:&error];
|
|
327
|
+
if (error) {
|
|
328
|
+
failCallback(error);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
NSData *updateSerializedData = [NSJSONSerialization dataWithJSONObject:mutableUpdatePackage
|
|
334
|
+
options:0
|
|
335
|
+
error:&error];
|
|
336
|
+
NSString *packageJsonString = [[NSString alloc] initWithData:updateSerializedData
|
|
337
|
+
encoding:NSUTF8StringEncoding];
|
|
338
|
+
|
|
339
|
+
[packageJsonString writeToFile:newUpdateMetadataPath
|
|
340
|
+
atomically:YES
|
|
341
|
+
encoding:NSUTF8StringEncoding
|
|
342
|
+
error:&error];
|
|
343
|
+
if (error) {
|
|
344
|
+
failCallback(error);
|
|
345
|
+
} else {
|
|
346
|
+
doneCallback();
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
__block BOOL fallbackStarted = NO;
|
|
351
|
+
|
|
352
|
+
void (^startFullDownload)(void) = ^{
|
|
353
|
+
if (fallbackStarted) return;
|
|
354
|
+
fallbackStarted = YES;
|
|
355
|
+
|
|
356
|
+
NSError *cleanupErr = nil;
|
|
357
|
+
[[NSFileManager defaultManager] removeItemAtPath:downloadFilePath error:&cleanupErr];
|
|
358
|
+
[[NSFileManager defaultManager] removeItemAtPath:[CodePushPackage getUnzippedFolderPath] error:nil];
|
|
359
|
+
|
|
360
|
+
CodePushDownloadHandler *downloadHandler = [[CodePushDownloadHandler alloc]
|
|
361
|
+
init:downloadFilePath
|
|
362
|
+
operationQueue:operationQueue
|
|
363
|
+
progressCallback:progressCallback
|
|
364
|
+
doneCallback:commonDone
|
|
365
|
+
failCallback:failCallback];
|
|
366
|
+
|
|
367
|
+
CPLog(@"Fallback to FULL download handler");
|
|
368
|
+
[downloadHandler download:singleUrl];
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
void (^diffFailThenFallback)(NSError *err) = ^(NSError *err) {
|
|
372
|
+
if (singleUrl.length == 0) {
|
|
373
|
+
failCallback(err);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
startFullDownload();
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
if (cameFromDiffHandler) {
|
|
381
|
+
NSString *assetsUrl = updatePackage[@"assetDownloadUrl"] ?: updatePackage[@"asset_download_url"];
|
|
382
|
+
NSString *assetHash = updatePackage[@"assetHash"] ?: updatePackage[@"asset_hash"];
|
|
383
|
+
|
|
384
|
+
NSError *pkgErr = nil;
|
|
385
|
+
NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&pkgErr];
|
|
386
|
+
|
|
387
|
+
NSError *assetsError = nil;
|
|
388
|
+
NSString *nativeAssetHash = [CodePushUpdateUtils getHashForBinaryAssets:&assetsError];
|
|
389
|
+
|
|
390
|
+
CodePushDiffDownloadHandler *diffHandler = [[CodePushDiffDownloadHandler alloc]
|
|
391
|
+
init:downloadFilePath
|
|
392
|
+
operationQueue:operationQueue
|
|
393
|
+
progressCallback:progressCallback
|
|
394
|
+
doneCallback:commonDone
|
|
395
|
+
failCallback:diffFailThenFallback];
|
|
396
|
+
|
|
397
|
+
CPLog(@"Diff download handler");
|
|
398
|
+
|
|
399
|
+
[diffHandler downloadWithDiffUrl:bundleDiffUrl assetsUrl:assetsUrl assetHash:assetHash nativeAssetHash:nativeAssetHash currentPackage:currentPackage];
|
|
400
|
+
} else {
|
|
401
|
+
NSString *singleUrl = updatePackage[@"downloadUrl"] ?: updatePackage[@"download_url"];
|
|
402
|
+
|
|
403
|
+
CodePushDownloadHandler *downloadHandler = [[CodePushDownloadHandler alloc]
|
|
404
|
+
init:downloadFilePath
|
|
405
|
+
operationQueue:operationQueue
|
|
406
|
+
progressCallback:progressCallback
|
|
407
|
+
doneCallback:commonDone
|
|
408
|
+
failCallback:failCallback];
|
|
409
|
+
|
|
410
|
+
CPLog(@"Full download handler");
|
|
411
|
+
|
|
412
|
+
[downloadHandler download:singleUrl];
|
|
413
|
+
}
|
|
345
414
|
}
|
|
346
415
|
|
|
347
416
|
+ (NSString *)getCodePushPath
|
|
@@ -350,7 +419,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
350
419
|
if ([CodePush isUsingTestConfiguration]) {
|
|
351
420
|
codePushPath = [codePushPath stringByAppendingPathComponent:@"TestPackages"];
|
|
352
421
|
}
|
|
353
|
-
|
|
422
|
+
|
|
354
423
|
return codePushPath;
|
|
355
424
|
}
|
|
356
425
|
|
|
@@ -367,17 +436,17 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
367
436
|
+ (NSString *)getCurrentPackageBundlePath:(NSError **)error
|
|
368
437
|
{
|
|
369
438
|
NSString *packageFolder = [self getCurrentPackageFolderPath:error];
|
|
370
|
-
|
|
439
|
+
|
|
371
440
|
if (!packageFolder) {
|
|
372
441
|
return nil;
|
|
373
442
|
}
|
|
374
|
-
|
|
443
|
+
|
|
375
444
|
NSDictionary *currentPackage = [self getCurrentPackage:error];
|
|
376
|
-
|
|
445
|
+
|
|
377
446
|
if (!currentPackage) {
|
|
378
447
|
return nil;
|
|
379
448
|
}
|
|
380
|
-
|
|
449
|
+
|
|
381
450
|
NSString *relativeBundlePath = [currentPackage objectForKey:RelativeBundlePathKey];
|
|
382
451
|
if (relativeBundlePath) {
|
|
383
452
|
return [packageFolder stringByAppendingPathComponent:relativeBundlePath];
|
|
@@ -392,24 +461,24 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
392
461
|
if (!info) {
|
|
393
462
|
return nil;
|
|
394
463
|
}
|
|
395
|
-
|
|
464
|
+
|
|
396
465
|
return info[@"currentPackage"];
|
|
397
466
|
}
|
|
398
467
|
|
|
399
468
|
+ (NSString *)getCurrentPackageFolderPath:(NSError **)error
|
|
400
469
|
{
|
|
401
470
|
NSDictionary *info = [self getCurrentPackageInfo:error];
|
|
402
|
-
|
|
471
|
+
|
|
403
472
|
if (!info) {
|
|
404
473
|
return nil;
|
|
405
474
|
}
|
|
406
|
-
|
|
475
|
+
|
|
407
476
|
NSString *packageHash = info[@"currentPackage"];
|
|
408
|
-
|
|
477
|
+
|
|
409
478
|
if (!packageHash) {
|
|
410
479
|
return nil;
|
|
411
480
|
}
|
|
412
|
-
|
|
481
|
+
|
|
413
482
|
return [self getPackageFolderPath:packageHash];
|
|
414
483
|
}
|
|
415
484
|
|
|
@@ -419,14 +488,14 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
419
488
|
if (![[NSFileManager defaultManager] fileExistsAtPath:statusFilePath]) {
|
|
420
489
|
return [NSMutableDictionary dictionary];
|
|
421
490
|
}
|
|
422
|
-
|
|
491
|
+
|
|
423
492
|
NSString *content = [NSString stringWithContentsOfFile:statusFilePath
|
|
424
493
|
encoding:NSUTF8StringEncoding
|
|
425
494
|
error:error];
|
|
426
495
|
if (!content) {
|
|
427
496
|
return nil;
|
|
428
497
|
}
|
|
429
|
-
|
|
498
|
+
|
|
430
499
|
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
|
|
431
500
|
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data
|
|
432
501
|
options:kNilOptions
|
|
@@ -434,7 +503,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
434
503
|
if (!json) {
|
|
435
504
|
return nil;
|
|
436
505
|
}
|
|
437
|
-
|
|
506
|
+
|
|
438
507
|
return [json mutableCopy];
|
|
439
508
|
}
|
|
440
509
|
|
|
@@ -448,18 +517,18 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
448
517
|
{
|
|
449
518
|
NSString *updateDirectoryPath = [self getPackageFolderPath:packageHash];
|
|
450
519
|
NSString *updateMetadataFilePath = [updateDirectoryPath stringByAppendingPathComponent:UpdateMetadataFileName];
|
|
451
|
-
|
|
520
|
+
|
|
452
521
|
if (![[NSFileManager defaultManager] fileExistsAtPath:updateMetadataFilePath]) {
|
|
453
522
|
return nil;
|
|
454
523
|
}
|
|
455
|
-
|
|
524
|
+
|
|
456
525
|
NSString *updateMetadataString = [NSString stringWithContentsOfFile:updateMetadataFilePath
|
|
457
526
|
encoding:NSUTF8StringEncoding
|
|
458
527
|
error:error];
|
|
459
528
|
if (!updateMetadataString) {
|
|
460
529
|
return nil;
|
|
461
530
|
}
|
|
462
|
-
|
|
531
|
+
|
|
463
532
|
NSData *updateMetadata = [updateMetadataString dataUsingEncoding:NSUTF8StringEncoding];
|
|
464
533
|
return [NSJSONSerialization JSONObjectWithData:updateMetadata
|
|
465
534
|
options:kNilOptions
|
|
@@ -477,7 +546,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
477
546
|
if (!packageHash) {
|
|
478
547
|
return nil;
|
|
479
548
|
}
|
|
480
|
-
|
|
549
|
+
|
|
481
550
|
return [CodePushPackage getPackage:packageHash error:error];
|
|
482
551
|
}
|
|
483
552
|
|
|
@@ -487,7 +556,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
487
556
|
if (!info) {
|
|
488
557
|
return nil;
|
|
489
558
|
}
|
|
490
|
-
|
|
559
|
+
|
|
491
560
|
return info[@"previousPackage"];
|
|
492
561
|
}
|
|
493
562
|
|
|
@@ -507,11 +576,11 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
507
576
|
{
|
|
508
577
|
NSString *packageHash = updatePackage[@"packageHash"];
|
|
509
578
|
NSMutableDictionary *info = [self getCurrentPackageInfo:error];
|
|
510
|
-
|
|
579
|
+
|
|
511
580
|
if (!info) {
|
|
512
581
|
return NO;
|
|
513
582
|
}
|
|
514
|
-
|
|
583
|
+
|
|
515
584
|
if (packageHash && [packageHash isEqualToString:info[@"currentPackage"]]) {
|
|
516
585
|
// The current package is already the one being installed, so we should no-op.
|
|
517
586
|
return YES;
|
|
@@ -542,7 +611,7 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
542
611
|
}
|
|
543
612
|
[info setValue:info[@"currentPackage"] forKey:@"previousPackage"];
|
|
544
613
|
}
|
|
545
|
-
|
|
614
|
+
|
|
546
615
|
[info setValue:packageHash forKey:@"currentPackage"];
|
|
547
616
|
return [self updateCurrentPackageInfo:info
|
|
548
617
|
error:error];
|
|
@@ -556,23 +625,23 @@ static NSString *const UnzippedFolderName = @"unzipped";
|
|
|
556
625
|
CPLog(@"Error getting current package info: %@", error);
|
|
557
626
|
return;
|
|
558
627
|
}
|
|
559
|
-
|
|
560
|
-
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:&error];
|
|
628
|
+
|
|
629
|
+
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:&error];
|
|
561
630
|
if (!currentPackageFolderPath) {
|
|
562
631
|
CPLog(@"Error getting current package folder path: %@", error);
|
|
563
632
|
return;
|
|
564
633
|
}
|
|
565
|
-
|
|
634
|
+
|
|
566
635
|
NSError *deleteError;
|
|
567
636
|
BOOL result = [[NSFileManager defaultManager] removeItemAtPath:currentPackageFolderPath
|
|
568
637
|
error:&deleteError];
|
|
569
638
|
if (!result) {
|
|
570
639
|
CPLog(@"Error deleting current package contents at %@ error %@", currentPackageFolderPath, deleteError);
|
|
571
640
|
}
|
|
572
|
-
|
|
641
|
+
|
|
573
642
|
[info setValue:info[@"previousPackage"] forKey:@"currentPackage"];
|
|
574
643
|
[info removeObjectForKey:@"previousPackage"];
|
|
575
|
-
|
|
644
|
+
|
|
576
645
|
[self updateCurrentPackageInfo:info error:&error];
|
|
577
646
|
}
|
|
578
647
|
|