@appzung/react-native-code-push 5.7.1
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/AlertAdapter.js +24 -0
- package/CONTRIBUTING.md +136 -0
- package/CodePush.js +666 -0
- package/CodePush.podspec +27 -0
- package/LICENSE.md +13 -0
- package/README.md +386 -0
- package/RestartManager.js +59 -0
- package/android/app/build.gradle +31 -0
- package/android/app/proguard-rules.pro +25 -0
- package/android/app/src/main/AndroidManifest.xml +10 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +395 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBuilder.java +37 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +34 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java +102 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java +16 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidUpdateException.java +7 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +641 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNotInitializedException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushTelemetryManager.java +175 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +369 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateState.java +15 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +267 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +236 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java +30 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java +5 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +190 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/ReactInstanceHolder.java +17 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/SettingsManager.java +173 -0
- package/android/build.gradle +20 -0
- package/android/codepush.gradle +113 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +20 -0
- package/android/gradlew +164 -0
- package/android/gradlew.bat +90 -0
- package/android/settings.gradle +1 -0
- package/docs/api-android.md +65 -0
- package/docs/api-ios.md +31 -0
- package/docs/api-js.md +592 -0
- package/docs/multi-deployment-testing-android.md +107 -0
- package/docs/multi-deployment-testing-ios.md +53 -0
- package/docs/setup-android.md +406 -0
- package/docs/setup-ios.md +229 -0
- package/docs/setup-windows.md +65 -0
- package/gulpfile.js +302 -0
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.h +34 -0
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +252 -0
- package/ios/CodePush/Base64/README.md +47 -0
- package/ios/CodePush/CodePush.h +235 -0
- package/ios/CodePush/CodePush.m +1041 -0
- package/ios/CodePush/CodePushConfig.m +116 -0
- package/ios/CodePush/CodePushDownloadHandler.m +130 -0
- package/ios/CodePush/CodePushErrorUtils.m +20 -0
- package/ios/CodePush/CodePushPackage.m +598 -0
- package/ios/CodePush/CodePushTelemetryManager.m +175 -0
- package/ios/CodePush/CodePushUpdateUtils.m +376 -0
- package/ios/CodePush/CodePushUtils.m +9 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +69 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +16 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +51 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +15 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +55 -0
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +24 -0
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +41 -0
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +28 -0
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +205 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +103 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +322 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +37 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +145 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +35 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +551 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +23 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +43 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +230 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +31 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +113 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +38 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +500 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +18 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +214 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +23 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +29 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +19 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +68 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +18 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +72 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +67 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +111 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +119 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +307 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +94 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +619 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +164 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +514 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +24 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +11 -0
- package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +52 -0
- package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +5 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +28 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +70 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +22 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +34 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +73 -0
- package/ios/CodePush/JWT/LICENSE +19 -0
- package/ios/CodePush/JWT/README.md +489 -0
- package/ios/CodePush/RCTConvert+CodePushInstallMode.m +20 -0
- package/ios/CodePush/RCTConvert+CodePushUpdateState.m +20 -0
- package/ios/CodePush/SSZipArchive/Common.h +81 -0
- package/ios/CodePush/SSZipArchive/README.md +1 -0
- package/ios/CodePush/SSZipArchive/SSZipArchive.h +76 -0
- package/ios/CodePush/SSZipArchive/SSZipArchive.m +691 -0
- package/ios/CodePush/SSZipArchive/aes/aes.h +198 -0
- package/ios/CodePush/SSZipArchive/aes/aes_via_ace.h +541 -0
- package/ios/CodePush/SSZipArchive/aes/aescrypt.c +294 -0
- package/ios/CodePush/SSZipArchive/aes/aeskey.c +548 -0
- package/ios/CodePush/SSZipArchive/aes/aesopt.h +739 -0
- package/ios/CodePush/SSZipArchive/aes/aestab.c +391 -0
- package/ios/CodePush/SSZipArchive/aes/aestab.h +173 -0
- package/ios/CodePush/SSZipArchive/aes/brg_endian.h +126 -0
- package/ios/CodePush/SSZipArchive/aes/brg_types.h +219 -0
- package/ios/CodePush/SSZipArchive/aes/entropy.c +54 -0
- package/ios/CodePush/SSZipArchive/aes/entropy.h +16 -0
- package/ios/CodePush/SSZipArchive/aes/fileenc.c +144 -0
- package/ios/CodePush/SSZipArchive/aes/fileenc.h +121 -0
- package/ios/CodePush/SSZipArchive/aes/hmac.c +145 -0
- package/ios/CodePush/SSZipArchive/aes/hmac.h +103 -0
- package/ios/CodePush/SSZipArchive/aes/prng.c +155 -0
- package/ios/CodePush/SSZipArchive/aes/prng.h +82 -0
- package/ios/CodePush/SSZipArchive/aes/pwd2key.c +103 -0
- package/ios/CodePush/SSZipArchive/aes/pwd2key.h +57 -0
- package/ios/CodePush/SSZipArchive/aes/sha1.c +258 -0
- package/ios/CodePush/SSZipArchive/aes/sha1.h +73 -0
- package/ios/CodePush/SSZipArchive/minizip/crypt.h +130 -0
- package/ios/CodePush/SSZipArchive/minizip/ioapi.c +369 -0
- package/ios/CodePush/SSZipArchive/minizip/ioapi.h +175 -0
- package/ios/CodePush/SSZipArchive/minizip/mztools.c +284 -0
- package/ios/CodePush/SSZipArchive/minizip/mztools.h +31 -0
- package/ios/CodePush/SSZipArchive/minizip/unzip.c +1839 -0
- package/ios/CodePush/SSZipArchive/minizip/unzip.h +248 -0
- package/ios/CodePush/SSZipArchive/minizip/zip.c +1910 -0
- package/ios/CodePush/SSZipArchive/minizip/zip.h +202 -0
- package/ios/CodePush.xcodeproj/project.pbxproj +937 -0
- package/ios/CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/CodePush.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/logging.js +6 -0
- package/package-mixins.js +69 -0
- package/package.json +47 -0
- package/request-fetch-adapter.js +52 -0
- package/scripts/generateBundledResourcesHash.js +125 -0
- package/scripts/getFilesInFolder.js +19 -0
- package/scripts/postlink/android/postlink.js +87 -0
- package/scripts/postlink/ios/postlink.js +116 -0
- package/scripts/postlink/run.js +11 -0
- package/scripts/postunlink/android/postunlink.js +74 -0
- package/scripts/postunlink/ios/postunlink.js +87 -0
- package/scripts/postunlink/run.js +11 -0
- package/scripts/recordFilesBeforeBundleCommand.js +41 -0
- package/scripts/tools/linkToolsAndroid.js +57 -0
- package/scripts/tools/linkToolsIos.js +130 -0
- package/typings/react-native-code-push.d.ts +446 -0
- package/windows/CodePush/CodePush.csproj +128 -0
- package/windows/CodePush/CodePushUtils.cs +47 -0
- package/windows/CodePush/FileUtils.cs +40 -0
- package/windows/CodePush/Properties/AssemblyInfo.cs +29 -0
- package/windows/CodePush/Properties/CodePush.rd.xml +33 -0
- package/windows/CodePush/UpdateManager.cs +305 -0
- package/windows/CodePush/UpdateUtils.cs +46 -0
- package/windows/CodePush.Net46/Adapters/Http/HttpProgress.cs +28 -0
- package/windows/CodePush.Net46/Adapters/Storage/ApplicationDataContainer.cs +106 -0
- package/windows/CodePush.Net46/CodePush.Net46.csproj +103 -0
- package/windows/CodePush.Net46/CodePushUtils.cs +158 -0
- package/windows/CodePush.Net46/FileUtils.cs +55 -0
- package/windows/CodePush.Net46/Properties/AssemblyInfo.cs +36 -0
- package/windows/CodePush.Net46/UpdateManager.cs +330 -0
- package/windows/CodePush.Net46/UpdateUtils.cs +70 -0
- package/windows/CodePush.Net46/packages.config +5 -0
- package/windows/CodePush.Shared/CodePush.Shared.projitems +22 -0
- package/windows/CodePush.Shared/CodePush.Shared.shproj +13 -0
- package/windows/CodePush.Shared/CodePushConstants.cs +35 -0
- package/windows/CodePush.Shared/CodePushNativeModule.cs +329 -0
- package/windows/CodePush.Shared/CodePushReactPackage.cs +235 -0
- package/windows/CodePush.Shared/CodePushUtils.cs +70 -0
- package/windows/CodePush.Shared/InstallMode.cs +9 -0
- package/windows/CodePush.Shared/MinimumBackgroundListener.cs +44 -0
- package/windows/CodePush.Shared/SettingsManager.cs +148 -0
- package/windows/CodePush.Shared/TelemetryManager.cs +250 -0
- package/windows/CodePush.Shared/UpdateState.cs +9 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
#import "CodePush.h"
|
|
2
|
+
#import "SSZipArchive.h"
|
|
3
|
+
|
|
4
|
+
@implementation CodePushPackage
|
|
5
|
+
|
|
6
|
+
#pragma mark - Private constants
|
|
7
|
+
|
|
8
|
+
static NSString *const DiffManifestFileName = @"hotcodepush.json";
|
|
9
|
+
static NSString *const DownloadFileName = @"download.zip";
|
|
10
|
+
static NSString *const RelativeBundlePathKey = @"bundlePath";
|
|
11
|
+
static NSString *const StatusFile = @"codepush.json";
|
|
12
|
+
static NSString *const UpdateBundleFileName = @"app.jsbundle";
|
|
13
|
+
static NSString *const UpdateMetadataFileName = @"app.json";
|
|
14
|
+
static NSString *const UnzippedFolderName = @"unzipped";
|
|
15
|
+
|
|
16
|
+
#pragma mark - Public methods
|
|
17
|
+
|
|
18
|
+
+ (void)clearUpdates
|
|
19
|
+
{
|
|
20
|
+
[[NSFileManager defaultManager] removeItemAtPath:[self getCodePushPath] error:nil];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
+ (void)downloadAndReplaceCurrentBundle:(NSString *)remoteBundleUrl
|
|
24
|
+
{
|
|
25
|
+
NSURL *urlRequest = [NSURL URLWithString:remoteBundleUrl];
|
|
26
|
+
NSError *error = nil;
|
|
27
|
+
NSString *downloadedBundle = [NSString stringWithContentsOfURL:urlRequest
|
|
28
|
+
encoding:NSUTF8StringEncoding
|
|
29
|
+
error:&error];
|
|
30
|
+
|
|
31
|
+
if (error) {
|
|
32
|
+
CPLog(@"Error downloading from URL %@", remoteBundleUrl);
|
|
33
|
+
} else {
|
|
34
|
+
NSString *currentPackageBundlePath = [self getCurrentPackageBundlePath:&error];
|
|
35
|
+
[downloadedBundle writeToFile:currentPackageBundlePath
|
|
36
|
+
atomically:YES
|
|
37
|
+
encoding:NSUTF8StringEncoding
|
|
38
|
+
error:&error];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
+ (void)downloadPackage:(NSDictionary *)updatePackage
|
|
43
|
+
expectedBundleFileName:(NSString *)expectedBundleFileName
|
|
44
|
+
publicKey:(NSString *)publicKey
|
|
45
|
+
operationQueue:(dispatch_queue_t)operationQueue
|
|
46
|
+
progressCallback:(void (^)(long long, long long))progressCallback
|
|
47
|
+
doneCallback:(void (^)())doneCallback
|
|
48
|
+
failCallback:(void (^)(NSError *err))failCallback
|
|
49
|
+
{
|
|
50
|
+
NSString *newUpdateHash = updatePackage[@"packageHash"];
|
|
51
|
+
NSString *newUpdateFolderPath = [self getPackageFolderPath:newUpdateHash];
|
|
52
|
+
NSString *newUpdateMetadataPath = [newUpdateFolderPath stringByAppendingPathComponent:UpdateMetadataFileName];
|
|
53
|
+
NSError *error;
|
|
54
|
+
|
|
55
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:newUpdateFolderPath]) {
|
|
56
|
+
// This removes any stale data in newUpdateFolderPath that could have been left
|
|
57
|
+
// uncleared due to a crash or error during the download or install process.
|
|
58
|
+
[[NSFileManager defaultManager] removeItemAtPath:newUpdateFolderPath
|
|
59
|
+
error:&error];
|
|
60
|
+
} else if (![[NSFileManager defaultManager] fileExistsAtPath:[self getCodePushPath]]) {
|
|
61
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:[self getCodePushPath]
|
|
62
|
+
withIntermediateDirectories:YES
|
|
63
|
+
attributes:nil
|
|
64
|
+
error:&error];
|
|
65
|
+
|
|
66
|
+
// Ensure that none of the CodePush updates we store on disk are
|
|
67
|
+
// ever included in the end users iTunes and/or iCloud backups
|
|
68
|
+
NSURL *codePushURL = [NSURL fileURLWithPath:[self getCodePushPath]];
|
|
69
|
+
[codePushURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (error) {
|
|
73
|
+
return failCallback(error);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
NSString *downloadFilePath = [self getDownloadFilePath];
|
|
77
|
+
NSString *bundleFilePath = [newUpdateFolderPath stringByAppendingPathComponent:UpdateBundleFileName];
|
|
78
|
+
|
|
79
|
+
CodePushDownloadHandler *downloadHandler = [[CodePushDownloadHandler alloc]
|
|
80
|
+
init:downloadFilePath
|
|
81
|
+
operationQueue:operationQueue
|
|
82
|
+
progressCallback:progressCallback
|
|
83
|
+
doneCallback:^(BOOL isZip) {
|
|
84
|
+
NSError *error = nil;
|
|
85
|
+
NSString * unzippedFolderPath = [CodePushPackage getUnzippedFolderPath];
|
|
86
|
+
NSMutableDictionary * mutableUpdatePackage = [updatePackage mutableCopy];
|
|
87
|
+
if (isZip) {
|
|
88
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:unzippedFolderPath]) {
|
|
89
|
+
// This removes any unzipped download data that could have been left
|
|
90
|
+
// uncleared due to a crash or error during the download process.
|
|
91
|
+
[[NSFileManager defaultManager] removeItemAtPath:unzippedFolderPath
|
|
92
|
+
error:&error];
|
|
93
|
+
if (error) {
|
|
94
|
+
failCallback(error);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
NSError *nonFailingError = nil;
|
|
100
|
+
[SSZipArchive unzipFileAtPath:downloadFilePath
|
|
101
|
+
toDestination:unzippedFolderPath];
|
|
102
|
+
[[NSFileManager defaultManager] removeItemAtPath:downloadFilePath
|
|
103
|
+
error:&nonFailingError];
|
|
104
|
+
if (nonFailingError) {
|
|
105
|
+
CPLog(@"Error deleting downloaded file: %@", nonFailingError);
|
|
106
|
+
nonFailingError = nil;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
NSString *diffManifestFilePath = [unzippedFolderPath stringByAppendingPathComponent:DiffManifestFileName];
|
|
110
|
+
BOOL isDiffUpdate = [[NSFileManager defaultManager] fileExistsAtPath:diffManifestFilePath];
|
|
111
|
+
|
|
112
|
+
if (isDiffUpdate) {
|
|
113
|
+
// Copy the current package to the new package.
|
|
114
|
+
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:&error];
|
|
115
|
+
if (error) {
|
|
116
|
+
failCallback(error);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (currentPackageFolderPath == nil) {
|
|
121
|
+
// Currently running the binary version, copy files from the bundled resources
|
|
122
|
+
NSString *newUpdateCodePushPath = [newUpdateFolderPath stringByAppendingPathComponent:[CodePushUpdateUtils manifestFolderPrefix]];
|
|
123
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:newUpdateCodePushPath
|
|
124
|
+
withIntermediateDirectories:YES
|
|
125
|
+
attributes:nil
|
|
126
|
+
error:&error];
|
|
127
|
+
if (error) {
|
|
128
|
+
failCallback(error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
[[NSFileManager defaultManager] copyItemAtPath:[CodePush bundleAssetsPath]
|
|
133
|
+
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[CodePushUpdateUtils assetsFolderName]]
|
|
134
|
+
error:&error];
|
|
135
|
+
if (error) {
|
|
136
|
+
failCallback(error);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
[[NSFileManager defaultManager] copyItemAtPath:[[CodePush binaryBundleURL] path]
|
|
141
|
+
toPath:[newUpdateCodePushPath stringByAppendingPathComponent:[[CodePush binaryBundleURL] lastPathComponent]]
|
|
142
|
+
error:&error];
|
|
143
|
+
if (error) {
|
|
144
|
+
failCallback(error);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
[[NSFileManager defaultManager] copyItemAtPath:currentPackageFolderPath
|
|
149
|
+
toPath:newUpdateFolderPath
|
|
150
|
+
error:&error];
|
|
151
|
+
if (error) {
|
|
152
|
+
failCallback(error);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Delete files mentioned in the manifest.
|
|
158
|
+
NSString *manifestContent = [NSString stringWithContentsOfFile:diffManifestFilePath
|
|
159
|
+
encoding:NSUTF8StringEncoding
|
|
160
|
+
error:&error];
|
|
161
|
+
if (error) {
|
|
162
|
+
failCallback(error);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
NSData *data = [manifestContent dataUsingEncoding:NSUTF8StringEncoding];
|
|
167
|
+
NSDictionary *manifestJSON = [NSJSONSerialization JSONObjectWithData:data
|
|
168
|
+
options:kNilOptions
|
|
169
|
+
error:&error];
|
|
170
|
+
NSArray *deletedFiles = manifestJSON[@"deletedFiles"];
|
|
171
|
+
for (NSString *deletedFileName in deletedFiles) {
|
|
172
|
+
NSString *absoluteDeletedFilePath = [newUpdateFolderPath stringByAppendingPathComponent:deletedFileName];
|
|
173
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:absoluteDeletedFilePath]) {
|
|
174
|
+
[[NSFileManager defaultManager] removeItemAtPath:absoluteDeletedFilePath
|
|
175
|
+
error:&error];
|
|
176
|
+
if (error) {
|
|
177
|
+
failCallback(error);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
[[NSFileManager defaultManager] removeItemAtPath:diffManifestFilePath
|
|
184
|
+
error:&error];
|
|
185
|
+
if (error) {
|
|
186
|
+
failCallback(error);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
[CodePushUpdateUtils copyEntriesInFolder:unzippedFolderPath
|
|
192
|
+
destFolder:newUpdateFolderPath
|
|
193
|
+
error:&error];
|
|
194
|
+
if (error) {
|
|
195
|
+
failCallback(error);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
[[NSFileManager defaultManager] removeItemAtPath:unzippedFolderPath
|
|
200
|
+
error:&nonFailingError];
|
|
201
|
+
if (nonFailingError) {
|
|
202
|
+
CPLog(@"Error deleting downloaded file: %@", nonFailingError);
|
|
203
|
+
nonFailingError = nil;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
NSString *relativeBundlePath = [CodePushUpdateUtils findMainBundleInFolder:newUpdateFolderPath
|
|
207
|
+
expectedFileName:expectedBundleFileName
|
|
208
|
+
error:&error];
|
|
209
|
+
|
|
210
|
+
if (error) {
|
|
211
|
+
failCallback(error);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (relativeBundlePath) {
|
|
216
|
+
[mutableUpdatePackage setValue:relativeBundlePath forKey:RelativeBundlePathKey];
|
|
217
|
+
} else {
|
|
218
|
+
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];
|
|
219
|
+
|
|
220
|
+
error = [CodePushErrorUtils errorWithMessage:errorMessage];
|
|
221
|
+
|
|
222
|
+
failCallback(error);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:newUpdateMetadataPath]) {
|
|
227
|
+
[[NSFileManager defaultManager] removeItemAtPath:newUpdateMetadataPath
|
|
228
|
+
error:&error];
|
|
229
|
+
if (error) {
|
|
230
|
+
failCallback(error);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
CPLog((isDiffUpdate) ? @"Applying diff update." : @"Applying full update.");
|
|
236
|
+
|
|
237
|
+
BOOL isSignatureVerificationEnabled = (publicKey != nil);
|
|
238
|
+
|
|
239
|
+
NSString *signatureFilePath = [CodePushUpdateUtils getSignatureFilePath:newUpdateFolderPath];
|
|
240
|
+
BOOL isSignatureAppearedInBundle = [[NSFileManager defaultManager] fileExistsAtPath:signatureFilePath];
|
|
241
|
+
|
|
242
|
+
if (isSignatureVerificationEnabled) {
|
|
243
|
+
if (isSignatureAppearedInBundle) {
|
|
244
|
+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
|
|
245
|
+
expectedHash:newUpdateHash
|
|
246
|
+
error:&error]) {
|
|
247
|
+
CPLog(@"The update contents failed the data integrity check.");
|
|
248
|
+
if (!error) {
|
|
249
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
failCallback(error);
|
|
253
|
+
return;
|
|
254
|
+
} else {
|
|
255
|
+
CPLog(@"The update contents succeeded the data integrity check.");
|
|
256
|
+
}
|
|
257
|
+
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
|
|
258
|
+
expectedHash:newUpdateHash
|
|
259
|
+
withPublicKey:publicKey
|
|
260
|
+
error:&error];
|
|
261
|
+
if (!isSignatureValid) {
|
|
262
|
+
CPLog(@"The update contents failed code signing check.");
|
|
263
|
+
if (!error) {
|
|
264
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
|
|
265
|
+
}
|
|
266
|
+
failCallback(error);
|
|
267
|
+
return;
|
|
268
|
+
} else {
|
|
269
|
+
CPLog(@"The update contents succeeded the code signing check.");
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
error = [CodePushErrorUtils errorWithMessage:
|
|
273
|
+
@"Error! Public key was provided but there is no JWT signature within app bundle to verify " \
|
|
274
|
+
"Possible reasons, why that might happen: \n" \
|
|
275
|
+
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" \
|
|
276
|
+
"2. You've been released CodePush bundle update without providing --privateKeyPath option."];
|
|
277
|
+
failCallback(error);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
} else {
|
|
282
|
+
BOOL needToVerifyHash;
|
|
283
|
+
if (isSignatureAppearedInBundle) {
|
|
284
|
+
CPLog(@"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed" \
|
|
285
|
+
" because there is no public key configured. " \
|
|
286
|
+
"Please ensure that public key is properly configured within your application.");
|
|
287
|
+
needToVerifyHash = true;
|
|
288
|
+
} else {
|
|
289
|
+
needToVerifyHash = isDiffUpdate;
|
|
290
|
+
}
|
|
291
|
+
if(needToVerifyHash){
|
|
292
|
+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
|
|
293
|
+
expectedHash:newUpdateHash
|
|
294
|
+
error:&error]) {
|
|
295
|
+
CPLog(@"The update contents failed the data integrity check.");
|
|
296
|
+
if (!error) {
|
|
297
|
+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
failCallback(error);
|
|
301
|
+
return;
|
|
302
|
+
} else {
|
|
303
|
+
CPLog(@"The update contents succeeded the data integrity check.");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
} else {
|
|
308
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:newUpdateFolderPath
|
|
309
|
+
withIntermediateDirectories:YES
|
|
310
|
+
attributes:nil
|
|
311
|
+
error:&error];
|
|
312
|
+
[[NSFileManager defaultManager] moveItemAtPath:downloadFilePath
|
|
313
|
+
toPath:bundleFilePath
|
|
314
|
+
error:&error];
|
|
315
|
+
if (error) {
|
|
316
|
+
failCallback(error);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
NSData *updateSerializedData = [NSJSONSerialization dataWithJSONObject:mutableUpdatePackage
|
|
322
|
+
options:0
|
|
323
|
+
error:&error];
|
|
324
|
+
NSString *packageJsonString = [[NSString alloc] initWithData:updateSerializedData
|
|
325
|
+
encoding:NSUTF8StringEncoding];
|
|
326
|
+
|
|
327
|
+
[packageJsonString writeToFile:newUpdateMetadataPath
|
|
328
|
+
atomically:YES
|
|
329
|
+
encoding:NSUTF8StringEncoding
|
|
330
|
+
error:&error];
|
|
331
|
+
if (error) {
|
|
332
|
+
failCallback(error);
|
|
333
|
+
} else {
|
|
334
|
+
doneCallback();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
failCallback:failCallback];
|
|
339
|
+
|
|
340
|
+
[downloadHandler download:updatePackage[@"downloadUrl"]];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
+ (NSString *)getCodePushPath
|
|
344
|
+
{
|
|
345
|
+
NSString* codePushPath = [[CodePush getApplicationSupportDirectory] stringByAppendingPathComponent:@"CodePush"];
|
|
346
|
+
if ([CodePush isUsingTestConfiguration]) {
|
|
347
|
+
codePushPath = [codePushPath stringByAppendingPathComponent:@"TestPackages"];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return codePushPath;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
+ (NSDictionary *)getCurrentPackage:(NSError **)error
|
|
354
|
+
{
|
|
355
|
+
NSString *packageHash = [CodePushPackage getCurrentPackageHash:error];
|
|
356
|
+
if (!packageHash) {
|
|
357
|
+
return nil;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return [CodePushPackage getPackage:packageHash error:error];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
+ (NSString *)getCurrentPackageBundlePath:(NSError **)error
|
|
364
|
+
{
|
|
365
|
+
NSString *packageFolder = [self getCurrentPackageFolderPath:error];
|
|
366
|
+
|
|
367
|
+
if (!packageFolder) {
|
|
368
|
+
return nil;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
NSDictionary *currentPackage = [self getCurrentPackage:error];
|
|
372
|
+
|
|
373
|
+
if (!currentPackage) {
|
|
374
|
+
return nil;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
NSString *relativeBundlePath = [currentPackage objectForKey:RelativeBundlePathKey];
|
|
378
|
+
if (relativeBundlePath) {
|
|
379
|
+
return [packageFolder stringByAppendingPathComponent:relativeBundlePath];
|
|
380
|
+
} else {
|
|
381
|
+
return [packageFolder stringByAppendingPathComponent:UpdateBundleFileName];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
+ (NSString *)getCurrentPackageHash:(NSError **)error
|
|
386
|
+
{
|
|
387
|
+
NSDictionary *info = [self getCurrentPackageInfo:error];
|
|
388
|
+
if (!info) {
|
|
389
|
+
return nil;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return info[@"currentPackage"];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
+ (NSString *)getCurrentPackageFolderPath:(NSError **)error
|
|
396
|
+
{
|
|
397
|
+
NSDictionary *info = [self getCurrentPackageInfo:error];
|
|
398
|
+
|
|
399
|
+
if (!info) {
|
|
400
|
+
return nil;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
NSString *packageHash = info[@"currentPackage"];
|
|
404
|
+
|
|
405
|
+
if (!packageHash) {
|
|
406
|
+
return nil;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return [self getPackageFolderPath:packageHash];
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
+ (NSMutableDictionary *)getCurrentPackageInfo:(NSError **)error
|
|
413
|
+
{
|
|
414
|
+
NSString *statusFilePath = [self getStatusFilePath];
|
|
415
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:statusFilePath]) {
|
|
416
|
+
return [NSMutableDictionary dictionary];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
NSString *content = [NSString stringWithContentsOfFile:statusFilePath
|
|
420
|
+
encoding:NSUTF8StringEncoding
|
|
421
|
+
error:error];
|
|
422
|
+
if (!content) {
|
|
423
|
+
return nil;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
|
|
427
|
+
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data
|
|
428
|
+
options:kNilOptions
|
|
429
|
+
error:error];
|
|
430
|
+
if (!json) {
|
|
431
|
+
return nil;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return [json mutableCopy];
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
+ (NSString *)getDownloadFilePath
|
|
438
|
+
{
|
|
439
|
+
return [[self getCodePushPath] stringByAppendingPathComponent:DownloadFileName];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
+ (NSDictionary *)getPackage:(NSString *)packageHash
|
|
443
|
+
error:(NSError **)error
|
|
444
|
+
{
|
|
445
|
+
NSString *updateDirectoryPath = [self getPackageFolderPath:packageHash];
|
|
446
|
+
NSString *updateMetadataFilePath = [updateDirectoryPath stringByAppendingPathComponent:UpdateMetadataFileName];
|
|
447
|
+
|
|
448
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:updateMetadataFilePath]) {
|
|
449
|
+
return nil;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
NSString *updateMetadataString = [NSString stringWithContentsOfFile:updateMetadataFilePath
|
|
453
|
+
encoding:NSUTF8StringEncoding
|
|
454
|
+
error:error];
|
|
455
|
+
if (!updateMetadataString) {
|
|
456
|
+
return nil;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
NSData *updateMetadata = [updateMetadataString dataUsingEncoding:NSUTF8StringEncoding];
|
|
460
|
+
return [NSJSONSerialization JSONObjectWithData:updateMetadata
|
|
461
|
+
options:kNilOptions
|
|
462
|
+
error:error];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
+ (NSString *)getPackageFolderPath:(NSString *)packageHash
|
|
466
|
+
{
|
|
467
|
+
return [[self getCodePushPath] stringByAppendingPathComponent:packageHash];
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
+ (NSDictionary *)getPreviousPackage:(NSError **)error
|
|
471
|
+
{
|
|
472
|
+
NSString *packageHash = [self getPreviousPackageHash:error];
|
|
473
|
+
if (!packageHash) {
|
|
474
|
+
return nil;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return [CodePushPackage getPackage:packageHash error:error];
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
+ (NSString *)getPreviousPackageHash:(NSError **)error
|
|
481
|
+
{
|
|
482
|
+
NSDictionary *info = [self getCurrentPackageInfo:error];
|
|
483
|
+
if (!info) {
|
|
484
|
+
return nil;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return info[@"previousPackage"];
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
+ (NSString *)getStatusFilePath
|
|
491
|
+
{
|
|
492
|
+
return [[self getCodePushPath] stringByAppendingPathComponent:StatusFile];
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
+ (NSString *)getUnzippedFolderPath
|
|
496
|
+
{
|
|
497
|
+
return [[self getCodePushPath] stringByAppendingPathComponent:UnzippedFolderName];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
+ (BOOL)installPackage:(NSDictionary *)updatePackage
|
|
501
|
+
removePendingUpdate:(BOOL)removePendingUpdate
|
|
502
|
+
error:(NSError **)error
|
|
503
|
+
{
|
|
504
|
+
NSString *packageHash = updatePackage[@"packageHash"];
|
|
505
|
+
NSMutableDictionary *info = [self getCurrentPackageInfo:error];
|
|
506
|
+
|
|
507
|
+
if (!info) {
|
|
508
|
+
return NO;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (packageHash && [packageHash isEqualToString:info[@"currentPackage"]]) {
|
|
512
|
+
// The current package is already the one being installed, so we should no-op.
|
|
513
|
+
return YES;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (removePendingUpdate) {
|
|
517
|
+
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:error];
|
|
518
|
+
if (currentPackageFolderPath) {
|
|
519
|
+
// Error in deleting pending package will not cause the entire operation to fail.
|
|
520
|
+
NSError *deleteError;
|
|
521
|
+
[[NSFileManager defaultManager] removeItemAtPath:currentPackageFolderPath
|
|
522
|
+
error:&deleteError];
|
|
523
|
+
if (deleteError) {
|
|
524
|
+
CPLog(@"Error deleting pending package: %@", deleteError);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
NSString *previousPackageHash = [self getPreviousPackageHash:error];
|
|
529
|
+
if (previousPackageHash && ![previousPackageHash isEqualToString:packageHash]) {
|
|
530
|
+
NSString *previousPackageFolderPath = [self getPackageFolderPath:previousPackageHash];
|
|
531
|
+
// Error in deleting old package will not cause the entire operation to fail.
|
|
532
|
+
NSError *deleteError;
|
|
533
|
+
[[NSFileManager defaultManager] removeItemAtPath:previousPackageFolderPath
|
|
534
|
+
error:&deleteError];
|
|
535
|
+
if (deleteError) {
|
|
536
|
+
CPLog(@"Error deleting old package: %@", deleteError);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
[info setValue:info[@"currentPackage"] forKey:@"previousPackage"];
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
[info setValue:packageHash forKey:@"currentPackage"];
|
|
543
|
+
return [self updateCurrentPackageInfo:info
|
|
544
|
+
error:error];
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
+ (void)rollbackPackage
|
|
548
|
+
{
|
|
549
|
+
NSError *error;
|
|
550
|
+
NSMutableDictionary *info = [self getCurrentPackageInfo:&error];
|
|
551
|
+
if (!info) {
|
|
552
|
+
CPLog(@"Error getting current package info: %@", error);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
NSString *currentPackageFolderPath = [self getCurrentPackageFolderPath:&error];
|
|
557
|
+
if (!currentPackageFolderPath) {
|
|
558
|
+
CPLog(@"Error getting current package folder path: %@", error);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
NSError *deleteError;
|
|
563
|
+
BOOL result = [[NSFileManager defaultManager] removeItemAtPath:currentPackageFolderPath
|
|
564
|
+
error:&deleteError];
|
|
565
|
+
if (!result) {
|
|
566
|
+
CPLog(@"Error deleting current package contents at %@ error %@", currentPackageFolderPath, deleteError);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
[info setValue:info[@"previousPackage"] forKey:@"currentPackage"];
|
|
570
|
+
[info removeObjectForKey:@"previousPackage"];
|
|
571
|
+
|
|
572
|
+
[self updateCurrentPackageInfo:info error:&error];
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
+ (BOOL)updateCurrentPackageInfo:(NSDictionary *)packageInfo
|
|
576
|
+
error:(NSError **)error
|
|
577
|
+
{
|
|
578
|
+
NSData *packageInfoData = [NSJSONSerialization dataWithJSONObject:packageInfo
|
|
579
|
+
options:0
|
|
580
|
+
error:error];
|
|
581
|
+
if (!packageInfoData) {
|
|
582
|
+
return NO;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
NSString *packageInfoString = [[NSString alloc] initWithData:packageInfoData
|
|
586
|
+
encoding:NSUTF8StringEncoding];
|
|
587
|
+
BOOL result = [packageInfoString writeToFile:[self getStatusFilePath]
|
|
588
|
+
atomically:YES
|
|
589
|
+
encoding:NSUTF8StringEncoding
|
|
590
|
+
error:error];
|
|
591
|
+
|
|
592
|
+
if (!result) {
|
|
593
|
+
return NO;
|
|
594
|
+
}
|
|
595
|
+
return YES;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
@end
|