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