@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.
Files changed (191) hide show
  1. package/AlertAdapter.js +24 -0
  2. package/CONTRIBUTING.md +136 -0
  3. package/CodePush.js +666 -0
  4. package/CodePush.podspec +27 -0
  5. package/LICENSE.md +13 -0
  6. package/README.md +386 -0
  7. package/RestartManager.js +59 -0
  8. package/android/app/build.gradle +31 -0
  9. package/android/app/proguard-rules.pro +25 -0
  10. package/android/app/src/main/AndroidManifest.xml +10 -0
  11. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +395 -0
  12. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBuilder.java +37 -0
  13. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +34 -0
  14. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java +102 -0
  15. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java +16 -0
  16. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +12 -0
  17. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidUpdateException.java +7 -0
  18. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java +12 -0
  19. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +641 -0
  20. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNotInitializedException.java +12 -0
  21. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushTelemetryManager.java +175 -0
  22. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java +12 -0
  23. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +369 -0
  24. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateState.java +15 -0
  25. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +267 -0
  26. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +236 -0
  27. package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java +30 -0
  28. package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java +5 -0
  29. package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +190 -0
  30. package/android/app/src/main/java/com/microsoft/codepush/react/ReactInstanceHolder.java +17 -0
  31. package/android/app/src/main/java/com/microsoft/codepush/react/SettingsManager.java +173 -0
  32. package/android/build.gradle +20 -0
  33. package/android/codepush.gradle +113 -0
  34. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  35. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  36. package/android/gradle.properties +20 -0
  37. package/android/gradlew +164 -0
  38. package/android/gradlew.bat +90 -0
  39. package/android/settings.gradle +1 -0
  40. package/docs/api-android.md +65 -0
  41. package/docs/api-ios.md +31 -0
  42. package/docs/api-js.md +592 -0
  43. package/docs/multi-deployment-testing-android.md +107 -0
  44. package/docs/multi-deployment-testing-ios.md +53 -0
  45. package/docs/setup-android.md +406 -0
  46. package/docs/setup-ios.md +229 -0
  47. package/docs/setup-windows.md +65 -0
  48. package/gulpfile.js +302 -0
  49. package/ios/CodePush/Base64/Base64/MF_Base64Additions.h +34 -0
  50. package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +252 -0
  51. package/ios/CodePush/Base64/README.md +47 -0
  52. package/ios/CodePush/CodePush.h +235 -0
  53. package/ios/CodePush/CodePush.m +1041 -0
  54. package/ios/CodePush/CodePushConfig.m +116 -0
  55. package/ios/CodePush/CodePushDownloadHandler.m +130 -0
  56. package/ios/CodePush/CodePushErrorUtils.m +20 -0
  57. package/ios/CodePush/CodePushPackage.m +598 -0
  58. package/ios/CodePush/CodePushTelemetryManager.m +175 -0
  59. package/ios/CodePush/CodePushUpdateUtils.m +376 -0
  60. package/ios/CodePush/CodePushUtils.m +9 -0
  61. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +69 -0
  62. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +16 -0
  63. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +51 -0
  64. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +15 -0
  65. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +55 -0
  66. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +24 -0
  67. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +41 -0
  68. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +28 -0
  69. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +205 -0
  70. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +103 -0
  71. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +322 -0
  72. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +37 -0
  73. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +145 -0
  74. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +35 -0
  75. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +551 -0
  76. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +23 -0
  77. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +43 -0
  78. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +230 -0
  79. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +31 -0
  80. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +113 -0
  81. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +38 -0
  82. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +500 -0
  83. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +18 -0
  84. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +214 -0
  85. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +23 -0
  86. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +29 -0
  87. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +19 -0
  88. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +68 -0
  89. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +18 -0
  90. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +72 -0
  91. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +67 -0
  92. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +111 -0
  93. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +119 -0
  94. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +307 -0
  95. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +94 -0
  96. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +619 -0
  97. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +164 -0
  98. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +514 -0
  99. package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +24 -0
  100. package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +11 -0
  101. package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +52 -0
  102. package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +5 -0
  103. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +28 -0
  104. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +70 -0
  105. package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +22 -0
  106. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +34 -0
  107. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +73 -0
  108. package/ios/CodePush/JWT/LICENSE +19 -0
  109. package/ios/CodePush/JWT/README.md +489 -0
  110. package/ios/CodePush/RCTConvert+CodePushInstallMode.m +20 -0
  111. package/ios/CodePush/RCTConvert+CodePushUpdateState.m +20 -0
  112. package/ios/CodePush/SSZipArchive/Common.h +81 -0
  113. package/ios/CodePush/SSZipArchive/README.md +1 -0
  114. package/ios/CodePush/SSZipArchive/SSZipArchive.h +76 -0
  115. package/ios/CodePush/SSZipArchive/SSZipArchive.m +691 -0
  116. package/ios/CodePush/SSZipArchive/aes/aes.h +198 -0
  117. package/ios/CodePush/SSZipArchive/aes/aes_via_ace.h +541 -0
  118. package/ios/CodePush/SSZipArchive/aes/aescrypt.c +294 -0
  119. package/ios/CodePush/SSZipArchive/aes/aeskey.c +548 -0
  120. package/ios/CodePush/SSZipArchive/aes/aesopt.h +739 -0
  121. package/ios/CodePush/SSZipArchive/aes/aestab.c +391 -0
  122. package/ios/CodePush/SSZipArchive/aes/aestab.h +173 -0
  123. package/ios/CodePush/SSZipArchive/aes/brg_endian.h +126 -0
  124. package/ios/CodePush/SSZipArchive/aes/brg_types.h +219 -0
  125. package/ios/CodePush/SSZipArchive/aes/entropy.c +54 -0
  126. package/ios/CodePush/SSZipArchive/aes/entropy.h +16 -0
  127. package/ios/CodePush/SSZipArchive/aes/fileenc.c +144 -0
  128. package/ios/CodePush/SSZipArchive/aes/fileenc.h +121 -0
  129. package/ios/CodePush/SSZipArchive/aes/hmac.c +145 -0
  130. package/ios/CodePush/SSZipArchive/aes/hmac.h +103 -0
  131. package/ios/CodePush/SSZipArchive/aes/prng.c +155 -0
  132. package/ios/CodePush/SSZipArchive/aes/prng.h +82 -0
  133. package/ios/CodePush/SSZipArchive/aes/pwd2key.c +103 -0
  134. package/ios/CodePush/SSZipArchive/aes/pwd2key.h +57 -0
  135. package/ios/CodePush/SSZipArchive/aes/sha1.c +258 -0
  136. package/ios/CodePush/SSZipArchive/aes/sha1.h +73 -0
  137. package/ios/CodePush/SSZipArchive/minizip/crypt.h +130 -0
  138. package/ios/CodePush/SSZipArchive/minizip/ioapi.c +369 -0
  139. package/ios/CodePush/SSZipArchive/minizip/ioapi.h +175 -0
  140. package/ios/CodePush/SSZipArchive/minizip/mztools.c +284 -0
  141. package/ios/CodePush/SSZipArchive/minizip/mztools.h +31 -0
  142. package/ios/CodePush/SSZipArchive/minizip/unzip.c +1839 -0
  143. package/ios/CodePush/SSZipArchive/minizip/unzip.h +248 -0
  144. package/ios/CodePush/SSZipArchive/minizip/zip.c +1910 -0
  145. package/ios/CodePush/SSZipArchive/minizip/zip.h +202 -0
  146. package/ios/CodePush.xcodeproj/project.pbxproj +937 -0
  147. package/ios/CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  148. package/ios/CodePush.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  149. package/logging.js +6 -0
  150. package/package-mixins.js +69 -0
  151. package/package.json +47 -0
  152. package/request-fetch-adapter.js +52 -0
  153. package/scripts/generateBundledResourcesHash.js +125 -0
  154. package/scripts/getFilesInFolder.js +19 -0
  155. package/scripts/postlink/android/postlink.js +87 -0
  156. package/scripts/postlink/ios/postlink.js +116 -0
  157. package/scripts/postlink/run.js +11 -0
  158. package/scripts/postunlink/android/postunlink.js +74 -0
  159. package/scripts/postunlink/ios/postunlink.js +87 -0
  160. package/scripts/postunlink/run.js +11 -0
  161. package/scripts/recordFilesBeforeBundleCommand.js +41 -0
  162. package/scripts/tools/linkToolsAndroid.js +57 -0
  163. package/scripts/tools/linkToolsIos.js +130 -0
  164. package/typings/react-native-code-push.d.ts +446 -0
  165. package/windows/CodePush/CodePush.csproj +128 -0
  166. package/windows/CodePush/CodePushUtils.cs +47 -0
  167. package/windows/CodePush/FileUtils.cs +40 -0
  168. package/windows/CodePush/Properties/AssemblyInfo.cs +29 -0
  169. package/windows/CodePush/Properties/CodePush.rd.xml +33 -0
  170. package/windows/CodePush/UpdateManager.cs +305 -0
  171. package/windows/CodePush/UpdateUtils.cs +46 -0
  172. package/windows/CodePush.Net46/Adapters/Http/HttpProgress.cs +28 -0
  173. package/windows/CodePush.Net46/Adapters/Storage/ApplicationDataContainer.cs +106 -0
  174. package/windows/CodePush.Net46/CodePush.Net46.csproj +103 -0
  175. package/windows/CodePush.Net46/CodePushUtils.cs +158 -0
  176. package/windows/CodePush.Net46/FileUtils.cs +55 -0
  177. package/windows/CodePush.Net46/Properties/AssemblyInfo.cs +36 -0
  178. package/windows/CodePush.Net46/UpdateManager.cs +330 -0
  179. package/windows/CodePush.Net46/UpdateUtils.cs +70 -0
  180. package/windows/CodePush.Net46/packages.config +5 -0
  181. package/windows/CodePush.Shared/CodePush.Shared.projitems +22 -0
  182. package/windows/CodePush.Shared/CodePush.Shared.shproj +13 -0
  183. package/windows/CodePush.Shared/CodePushConstants.cs +35 -0
  184. package/windows/CodePush.Shared/CodePushNativeModule.cs +329 -0
  185. package/windows/CodePush.Shared/CodePushReactPackage.cs +235 -0
  186. package/windows/CodePush.Shared/CodePushUtils.cs +70 -0
  187. package/windows/CodePush.Shared/InstallMode.cs +9 -0
  188. package/windows/CodePush.Shared/MinimumBackgroundListener.cs +44 -0
  189. package/windows/CodePush.Shared/SettingsManager.cs +148 -0
  190. package/windows/CodePush.Shared/TelemetryManager.cs +250 -0
  191. 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