@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,175 @@
1
+ #import "CodePush.h"
2
+
3
+ static NSString *const AppVersionKey = @"appVersion";
4
+ static NSString *const DeploymentFailed = @"DeploymentFailed";
5
+ static NSString *const DeploymentKeyKey = @"deploymentKey";
6
+ static NSString *const DeploymentSucceeded = @"DeploymentSucceeded";
7
+ static NSString *const LabelKey = @"label";
8
+ static NSString *const LastDeploymentReportKey = @"CODE_PUSH_LAST_DEPLOYMENT_REPORT";
9
+ static NSString *const PackageKey = @"package";
10
+ static NSString *const PreviousDeploymentKeyKey = @"previousDeploymentKey";
11
+ static NSString *const PreviousLabelOrAppVersionKey = @"previousLabelOrAppVersion";
12
+ static NSString *const RetryDeploymentReportKey = @"CODE_PUSH_RETRY_DEPLOYMENT_REPORT";
13
+ static NSString *const StatusKey = @"status";
14
+
15
+ @implementation CodePushTelemetryManager
16
+
17
+ + (NSDictionary *)getBinaryUpdateReport:(NSString *)appVersion
18
+ {
19
+ NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier];
20
+ if (previousStatusReportIdentifier == nil) {
21
+ [self clearRetryStatusReport];
22
+ return @{ AppVersionKey: appVersion };
23
+ } else if (![previousStatusReportIdentifier isEqualToString:appVersion]) {
24
+ if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) {
25
+ NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier];
26
+ NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier];
27
+ [self clearRetryStatusReport];
28
+ return @{
29
+ AppVersionKey: appVersion,
30
+ PreviousDeploymentKeyKey: previousDeploymentKey,
31
+ PreviousLabelOrAppVersionKey: previousLabel
32
+ };
33
+ } else {
34
+ [self clearRetryStatusReport];
35
+ // Previous status report was with a binary app version.
36
+ return @{
37
+ AppVersionKey: appVersion,
38
+ PreviousLabelOrAppVersionKey: previousStatusReportIdentifier
39
+ };
40
+ }
41
+ }
42
+
43
+ return nil;
44
+ }
45
+
46
+ + (NSDictionary *)getRetryStatusReport
47
+ {
48
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
49
+ NSDictionary *retryStatusReport = [preferences objectForKey:RetryDeploymentReportKey];
50
+ if (retryStatusReport) {
51
+ [self clearRetryStatusReport];
52
+ return retryStatusReport;
53
+ } else {
54
+ return nil;
55
+ }
56
+ }
57
+
58
+ + (NSDictionary *)getRollbackReport:(NSDictionary *)lastFailedPackage
59
+ {
60
+ return @{
61
+ PackageKey: lastFailedPackage,
62
+ StatusKey: DeploymentFailed
63
+ };
64
+ }
65
+
66
+ + (NSDictionary *)getUpdateReport:(NSDictionary *)currentPackage
67
+ {
68
+ NSString *currentPackageIdentifier = [self getPackageStatusReportIdentifier:currentPackage];
69
+ NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier];
70
+ if (currentPackageIdentifier) {
71
+ if (previousStatusReportIdentifier == nil) {
72
+ [self clearRetryStatusReport];
73
+ return @{
74
+ PackageKey: currentPackage,
75
+ StatusKey: DeploymentSucceeded
76
+ };
77
+ } else if (![previousStatusReportIdentifier isEqualToString:currentPackageIdentifier]) {
78
+ [self clearRetryStatusReport];
79
+ if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) {
80
+ NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier];
81
+ NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier];
82
+ return @{
83
+ PackageKey: currentPackage,
84
+ StatusKey: DeploymentSucceeded,
85
+ PreviousDeploymentKeyKey: previousDeploymentKey,
86
+ PreviousLabelOrAppVersionKey: previousLabel
87
+ };
88
+ } else {
89
+ // Previous status report was with a binary app version.
90
+ return @{
91
+ PackageKey: currentPackage,
92
+ StatusKey: DeploymentSucceeded,
93
+ PreviousLabelOrAppVersionKey: previousStatusReportIdentifier
94
+ };
95
+ }
96
+ }
97
+ }
98
+
99
+ return nil;
100
+ }
101
+
102
+ + (void)recordStatusReported:(NSDictionary *)statusReport
103
+ {
104
+ // We don't need to record rollback reports, so exit early if that's what was specified.
105
+ if ([DeploymentFailed isEqualToString:statusReport[StatusKey]]) {
106
+ return;
107
+ }
108
+
109
+ if (statusReport[AppVersionKey]) {
110
+ [self saveStatusReportedForIdentifier:statusReport[AppVersionKey]];
111
+ } else if (statusReport[PackageKey]) {
112
+ NSString *packageIdentifier = [self getPackageStatusReportIdentifier:statusReport[PackageKey]];
113
+ [self saveStatusReportedForIdentifier:packageIdentifier];
114
+ }
115
+ }
116
+
117
+ + (void)saveStatusReportForRetry:(NSDictionary *)statusReport
118
+ {
119
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
120
+ [preferences setValue:statusReport forKey:RetryDeploymentReportKey];
121
+ [preferences synchronize];
122
+ }
123
+
124
+ #pragma mark - private methods
125
+
126
+ + (void)clearRetryStatusReport
127
+ {
128
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
129
+ [preferences setValue:nil forKey:RetryDeploymentReportKey];
130
+ [preferences synchronize];
131
+ }
132
+
133
+ + (NSString *)getDeploymentKeyFromStatusReportIdentifier:(NSString *)statusReportIdentifier
134
+ {
135
+ return [[statusReportIdentifier componentsSeparatedByString:@":"] firstObject];
136
+ }
137
+
138
+ + (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package
139
+ {
140
+ // Because deploymentKeys can be dynamically switched, we use a
141
+ // combination of the deploymentKey and label as the packageIdentifier.
142
+ NSString *deploymentKey = [package objectForKey:DeploymentKeyKey];
143
+ NSString *label = [package objectForKey:LabelKey];
144
+ if (deploymentKey && label) {
145
+ return [[deploymentKey stringByAppendingString:@":"] stringByAppendingString:label];
146
+ } else {
147
+ return nil;
148
+ }
149
+ }
150
+
151
+ + (NSString *)getPreviousStatusReportIdentifier
152
+ {
153
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
154
+ NSString *sentStatusReportIdentifier = [preferences objectForKey:LastDeploymentReportKey];
155
+ return sentStatusReportIdentifier;
156
+ }
157
+
158
+ + (NSString *)getVersionLabelFromStatusReportIdentifier:(NSString *)statusReportIdentifier
159
+ {
160
+ return [[statusReportIdentifier componentsSeparatedByString:@":"] lastObject];
161
+ }
162
+
163
+ + (BOOL)isStatusReportIdentifierCodePushLabel:(NSString *)statusReportIdentifier
164
+ {
165
+ return statusReportIdentifier != nil && [statusReportIdentifier rangeOfString:@":"].location != NSNotFound;
166
+ }
167
+
168
+ + (void)saveStatusReportedForIdentifier:(NSString *)appVersionOrPackageIdentifier
169
+ {
170
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
171
+ [preferences setValue:appVersionOrPackageIdentifier forKey:LastDeploymentReportKey];
172
+ [preferences synchronize];
173
+ }
174
+
175
+ @end
@@ -0,0 +1,376 @@
1
+ #import "CodePush.h"
2
+ #include <CommonCrypto/CommonDigest.h>
3
+ #import "JWT.h"
4
+
5
+ @implementation CodePushUpdateUtils
6
+
7
+ NSString * const AssetsFolderName = @"assets";
8
+ NSString * const BinaryHashKey = @"CodePushBinaryHash";
9
+ NSString * const ManifestFolderPrefix = @"CodePush";
10
+ NSString * const BundleJWTFile = @".codepushrelease";
11
+
12
+ /*
13
+ Ignore list for hashing
14
+ */
15
+ NSString * const IgnoreMacOSX= @"__MACOSX/";
16
+ NSString * const IgnoreDSStore = @".DS_Store";
17
+ NSString * const IgnoreCodePushMetadata = @".codepushrelease";
18
+
19
+ + (BOOL)isHashIgnoredFor:(NSString *) relativePath
20
+ {
21
+ return [relativePath hasPrefix:IgnoreMacOSX]
22
+ || [relativePath isEqualToString:IgnoreDSStore]
23
+ || [relativePath hasSuffix:[NSString stringWithFormat:@"/%@", IgnoreDSStore]]
24
+ || [relativePath isEqualToString:IgnoreCodePushMetadata]
25
+ || [relativePath hasSuffix:[NSString stringWithFormat:@"/%@", IgnoreCodePushMetadata]];
26
+ }
27
+
28
+ + (BOOL)addContentsOfFolderToManifest:(NSString *)folderPath
29
+ pathPrefix:(NSString *)pathPrefix
30
+ manifest:(NSMutableArray *)manifest
31
+ error:(NSError **)error
32
+ {
33
+ NSArray *folderFiles = [[NSFileManager defaultManager]
34
+ contentsOfDirectoryAtPath:folderPath
35
+ error:error];
36
+ if (!folderFiles) {
37
+ return NO;
38
+ }
39
+
40
+ for (NSString *fileName in folderFiles) {
41
+
42
+ NSString *fullFilePath = [folderPath stringByAppendingPathComponent:fileName];
43
+ NSString *relativePath = [pathPrefix stringByAppendingPathComponent:fileName];
44
+
45
+ if([self isHashIgnoredFor:relativePath]){
46
+ continue;
47
+ }
48
+
49
+ BOOL isDir = NO;
50
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
51
+ isDirectory:&isDir] && isDir) {
52
+ BOOL result = [self addContentsOfFolderToManifest:fullFilePath
53
+ pathPrefix:relativePath
54
+ manifest:manifest
55
+ error:error];
56
+ if (!result) {
57
+ return NO;
58
+ }
59
+ } else {
60
+ NSData *fileContents = [NSData dataWithContentsOfFile:fullFilePath];
61
+ NSString *fileContentsHash = [self computeHashForData:fileContents];
62
+ [manifest addObject:[[relativePath stringByAppendingString:@":"] stringByAppendingString:fileContentsHash]];
63
+ }
64
+ }
65
+
66
+ return YES;
67
+ }
68
+
69
+ + (void)addFileToManifest:(NSURL *)fileURL
70
+ manifest:(NSMutableArray *)manifest
71
+ {
72
+ if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
73
+ NSData *fileContents = [NSData dataWithContentsOfURL:fileURL];
74
+ NSString *fileContentsHash = [self computeHashForData:fileContents];
75
+ [manifest addObject:[NSString stringWithFormat:@"%@/%@:%@", [self manifestFolderPrefix], [fileURL lastPathComponent], fileContentsHash]];
76
+ }
77
+ }
78
+
79
+ + (NSString *)computeFinalHashFromManifest:(NSMutableArray *)manifest
80
+ error:(NSError **)error
81
+ {
82
+ //sort manifest strings to make sure, that they are completely equal with manifest strings has been generated in cli!
83
+ NSArray *sortedManifest = [manifest sortedArrayUsingSelector:@selector(compare:)];
84
+ NSData *manifestData = [NSJSONSerialization dataWithJSONObject:sortedManifest
85
+ options:kNilOptions
86
+ error:error];
87
+ if (!manifestData) {
88
+ return nil;
89
+ }
90
+
91
+ NSString *manifestString = [[NSString alloc] initWithData:manifestData
92
+ encoding:NSUTF8StringEncoding];
93
+ // The JSON serialization turns path separators into "\/", e.g. "CodePush\/assets\/image.png"
94
+ manifestString = [manifestString stringByReplacingOccurrencesOfString:@"\\/"
95
+ withString:@"/"];
96
+ return [self computeHashForData:[NSData dataWithBytes:manifestString.UTF8String length:manifestString.length]];
97
+ }
98
+
99
+ + (NSString *)computeHashForData:(NSData *)inputData
100
+ {
101
+ uint8_t digest[CC_SHA256_DIGEST_LENGTH];
102
+ CC_SHA256(inputData.bytes, (CC_LONG)inputData.length, digest);
103
+ NSMutableString* inputHash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
104
+ for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
105
+ [inputHash appendFormat:@"%02x", digest[i]];
106
+ }
107
+
108
+ return inputHash;
109
+ }
110
+
111
+ + (BOOL)copyEntriesInFolder:(NSString *)sourceFolder
112
+ destFolder:(NSString *)destFolder
113
+ error:(NSError **)error
114
+ {
115
+ NSArray *files = [[NSFileManager defaultManager]
116
+ contentsOfDirectoryAtPath:sourceFolder
117
+ error:error];
118
+ if (!files) {
119
+ return NO;
120
+ }
121
+
122
+ for (NSString *fileName in files) {
123
+ NSString * fullFilePath = [sourceFolder stringByAppendingPathComponent:fileName];
124
+ BOOL isDir = NO;
125
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
126
+ isDirectory:&isDir] && isDir) {
127
+ NSString *nestedDestFolder = [destFolder stringByAppendingPathComponent:fileName];
128
+ BOOL result = [self copyEntriesInFolder:fullFilePath
129
+ destFolder:nestedDestFolder
130
+ error:error];
131
+
132
+ if (!result) {
133
+ return NO;
134
+ }
135
+
136
+ } else {
137
+ NSString *destFileName = [destFolder stringByAppendingPathComponent:fileName];
138
+ if ([[NSFileManager defaultManager] fileExistsAtPath:destFileName]) {
139
+ BOOL result = [[NSFileManager defaultManager] removeItemAtPath:destFileName error:error];
140
+ if (!result) {
141
+ return NO;
142
+ }
143
+ }
144
+ if (![[NSFileManager defaultManager] fileExistsAtPath:destFolder]) {
145
+ BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:destFolder
146
+ withIntermediateDirectories:YES
147
+ attributes:nil
148
+ error:error];
149
+ if (!result) {
150
+ return NO;
151
+ }
152
+ }
153
+
154
+ BOOL result = [[NSFileManager defaultManager] copyItemAtPath:fullFilePath toPath:destFileName error:error];
155
+ if (!result) {
156
+ return NO;
157
+ }
158
+ }
159
+ }
160
+ return YES;
161
+ }
162
+
163
+ + (NSString *)findMainBundleInFolder:(NSString *)folderPath
164
+ expectedFileName:(NSString *)expectedFileName
165
+ error:(NSError **)error
166
+ {
167
+ NSArray* folderFiles = [[NSFileManager defaultManager]
168
+ contentsOfDirectoryAtPath:folderPath
169
+ error:error];
170
+ if (!folderFiles) {
171
+ return nil;
172
+ }
173
+
174
+ for (NSString *fileName in folderFiles) {
175
+ NSString *fullFilePath = [folderPath stringByAppendingPathComponent:fileName];
176
+ BOOL isDir = NO;
177
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fullFilePath
178
+ isDirectory:&isDir] && isDir) {
179
+ NSString *mainBundlePathInFolder = [self findMainBundleInFolder:fullFilePath
180
+ expectedFileName:expectedFileName
181
+ error:error];
182
+ if (mainBundlePathInFolder) {
183
+ return [fileName stringByAppendingPathComponent:mainBundlePathInFolder];
184
+ }
185
+ } else if ([fileName isEqualToString:expectedFileName]) {
186
+ return fileName;
187
+ }
188
+ }
189
+
190
+ return nil;
191
+ }
192
+
193
+ + (NSString *)assetsFolderName
194
+ {
195
+ return AssetsFolderName;
196
+ }
197
+
198
+ + (NSString *)getHashForBinaryContents:(NSURL *)binaryBundleUrl
199
+ error:(NSError **)error
200
+ {
201
+ // Get the cached hash from user preferences if it exists.
202
+ NSString *binaryModifiedDate = [self modifiedDateStringOfFileAtURL:binaryBundleUrl];
203
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
204
+ NSMutableDictionary *binaryHashDictionary = [preferences objectForKey:BinaryHashKey];
205
+ NSString *binaryHash = nil;
206
+ if (binaryHashDictionary != nil) {
207
+ binaryHash = [binaryHashDictionary objectForKey:binaryModifiedDate];
208
+ if (binaryHash == nil) {
209
+ [preferences removeObjectForKey:BinaryHashKey];
210
+ [preferences synchronize];
211
+ } else {
212
+ return binaryHash;
213
+ }
214
+ }
215
+
216
+ binaryHashDictionary = [NSMutableDictionary dictionary];
217
+ NSMutableArray *manifest = [NSMutableArray array];
218
+
219
+ // If the app is using assets, then add
220
+ // them to the generated content manifest.
221
+ NSString *assetsPath = [CodePush bundleAssetsPath];
222
+ if ([[NSFileManager defaultManager] fileExistsAtPath:assetsPath]) {
223
+
224
+ BOOL result = [self addContentsOfFolderToManifest:assetsPath
225
+ pathPrefix:[NSString stringWithFormat:@"%@/%@", [self manifestFolderPrefix], @"assets"]
226
+ manifest:manifest
227
+ error:error];
228
+ if (!result) {
229
+ return nil;
230
+ }
231
+ }
232
+
233
+ [self addFileToManifest:binaryBundleUrl manifest:manifest];
234
+ [self addFileToManifest:[binaryBundleUrl URLByAppendingPathExtension:@"meta"] manifest:manifest];
235
+
236
+ binaryHash = [self computeFinalHashFromManifest:manifest error:error];
237
+
238
+ // Cache the hash in user preferences. This assumes that the modified date for the
239
+ // JS bundle changes every time a new bundle is generated by the packager.
240
+ [binaryHashDictionary setObject:binaryHash forKey:binaryModifiedDate];
241
+ [preferences setObject:binaryHashDictionary forKey:BinaryHashKey];
242
+ [preferences synchronize];
243
+ return binaryHash;
244
+ }
245
+
246
+ + (NSString *)manifestFolderPrefix
247
+ {
248
+ return ManifestFolderPrefix;
249
+ }
250
+
251
+ + (NSString *)modifiedDateStringOfFileAtURL:(NSURL *)fileURL
252
+ {
253
+ if (fileURL != nil) {
254
+ NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:nil];
255
+ NSDate *modifiedDate = [fileAttributes objectForKey:NSFileModificationDate];
256
+ return [NSString stringWithFormat:@"%f", [modifiedDate timeIntervalSince1970]];
257
+ } else {
258
+ return nil;
259
+ }
260
+ }
261
+
262
+ + (BOOL)verifyFolderHash:(NSString *)finalUpdateFolder
263
+ expectedHash:(NSString *)expectedHash
264
+ error:(NSError **)error
265
+ {
266
+ CPLog(@"Verifying hash for folder path: %@", finalUpdateFolder);
267
+
268
+ NSMutableArray *updateContentsManifest = [NSMutableArray array];
269
+ BOOL result = [self addContentsOfFolderToManifest:finalUpdateFolder
270
+ pathPrefix:@""
271
+ manifest:updateContentsManifest
272
+ error:error];
273
+
274
+ CPLog(@"Manifest string: %@", updateContentsManifest);
275
+
276
+ if (!result) {
277
+ return NO;
278
+ }
279
+
280
+ NSString *updateContentsManifestHash = [self computeFinalHashFromManifest:updateContentsManifest
281
+ error:error];
282
+ if (!updateContentsManifestHash) {
283
+ return NO;
284
+ }
285
+
286
+ CPLog(@"Expected hash: %@, actual hash: %@", expectedHash, updateContentsManifestHash);
287
+
288
+ return [updateContentsManifestHash isEqualToString:expectedHash];
289
+ }
290
+
291
+ // remove BEGIN / END tags and line breaks from public key string
292
+ + (NSString *)getKeyValueFromPublicKeyString:(NSString *)publicKeyString
293
+ {
294
+ publicKeyString = [publicKeyString stringByReplacingOccurrencesOfString:@"-----BEGIN PUBLIC KEY-----\n"
295
+ withString:@""];
296
+ publicKeyString = [publicKeyString stringByReplacingOccurrencesOfString:@"-----END PUBLIC KEY-----"
297
+ withString:@""];
298
+ publicKeyString = [publicKeyString stringByReplacingOccurrencesOfString:@"\n"
299
+ withString:@""];
300
+
301
+ return publicKeyString;
302
+ }
303
+
304
+ + (NSString *)getSignatureFilePath:(NSString *)updateFolderPath
305
+ {
306
+ return [NSString stringWithFormat:@"%@/%@/%@", updateFolderPath, ManifestFolderPrefix, BundleJWTFile];
307
+ }
308
+
309
+ + (NSString *)getSignatureFor:(NSString *)folderPath
310
+ error:(NSError **)error
311
+ {
312
+ NSString *signatureFilePath = [self getSignatureFilePath:folderPath];
313
+ if ([[NSFileManager defaultManager] fileExistsAtPath:signatureFilePath]) {
314
+ return [NSString stringWithContentsOfFile:signatureFilePath encoding:NSUTF8StringEncoding error:error];
315
+ } else {
316
+ *error = [CodePushErrorUtils errorWithMessage:[NSString stringWithFormat: @"Cannot find signature at %@", signatureFilePath]];
317
+ return nil;
318
+ }
319
+ }
320
+
321
+ + (NSDictionary *) verifyAndDecodeJWT:(NSString *)jwt
322
+ withPublicKey:(NSString *)publicKey
323
+ error:(NSError **)error
324
+ {
325
+ id <JWTAlgorithmDataHolderProtocol> verifyDataHolder = [JWTAlgorithmRSFamilyDataHolder new].keyExtractorType([JWTCryptoKeyExtractor publicKeyWithPEMBase64].type).algorithmName(@"RS256").secret(publicKey);
326
+
327
+ JWTCodingBuilder *verifyBuilder = [JWTDecodingBuilder decodeMessage:jwt].addHolder(verifyDataHolder);
328
+ JWTCodingResultType *verifyResult = verifyBuilder.result;
329
+ if (verifyResult.successResult) {
330
+ return verifyResult.successResult.payload;
331
+ }
332
+ else {
333
+ *error = verifyResult.errorResult.error;
334
+ return nil;
335
+ }
336
+ }
337
+
338
+ + (BOOL)verifyUpdateSignatureFor:(NSString *)folderPath
339
+ expectedHash:(NSString *)newUpdateHash
340
+ withPublicKey:(NSString *)publicKeyString
341
+ error:(NSError **)error
342
+ {
343
+ NSLog(@"Verifying signature for folder path: %@", folderPath);
344
+
345
+ NSString *publicKey = [self getKeyValueFromPublicKeyString: publicKeyString];
346
+
347
+ NSError *signatureVerificationError;
348
+ NSString *signature = [self getSignatureFor: folderPath
349
+ error: &signatureVerificationError];
350
+ if (signatureVerificationError) {
351
+ CPLog(@"The update could not be verified because no signature was found. %@", signatureVerificationError);
352
+ *error = signatureVerificationError;
353
+ return false;
354
+ }
355
+
356
+ NSError *payloadDecodingError;
357
+ NSDictionary *envelopedPayload = [self verifyAndDecodeJWT:signature withPublicKey:publicKey error:&payloadDecodingError];
358
+ if(payloadDecodingError){
359
+ CPLog(@"The update could not be verified because it was not signed by a trusted party. %@", payloadDecodingError);
360
+ *error = payloadDecodingError;
361
+ return false;
362
+ }
363
+
364
+ CPLog(@"JWT signature verification succeeded, payload content: %@", envelopedPayload);
365
+
366
+ if(![envelopedPayload objectForKey:@"contentHash"]){
367
+ CPLog(@"The update could not be verified because the signature did not specify a content hash.");
368
+ return false;
369
+ }
370
+
371
+ NSString *contentHash = envelopedPayload[@"contentHash"];
372
+
373
+ return [contentHash isEqualToString:newUpdateHash];
374
+ }
375
+
376
+ @end
@@ -0,0 +1,9 @@
1
+ #import "CodePush.h"
2
+
3
+ void CPLog(NSString *formatString, ...) {
4
+ va_list args;
5
+ va_start(args, formatString);
6
+ NSString *prependedFormatString = [NSString stringWithFormat:@"\n[CodePush] %@", formatString];
7
+ NSLogv(prependedFormatString, args);
8
+ va_end(args);
9
+ }
@@ -0,0 +1,69 @@
1
+ //
2
+ // JWTAlgorithm.h
3
+ // JWT
4
+ //
5
+ // Created by Klaas Pieter Annema on 31-05-13.
6
+ // Copyright (c) 2013 Karma. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+ #import "JWTDeprecations.h"
11
+
12
+ @protocol JWTAlgorithm <NSObject>
13
+
14
+ @required
15
+ /**
16
+ Signs data using provided secret data.
17
+ @param hash The data to sign.
18
+ @param key The secret to use for signing.
19
+ @param error The inout error.
20
+ */
21
+ - (NSData *)signHash:(NSData *)hash key:(NSData *)key error:(NSError *__autoreleasing*)error;
22
+ /**
23
+ Verifies data using.
24
+ @param hash The data to sign.
25
+ @param signature The secret to use for signing.
26
+ @param error The inout error.
27
+ */
28
+ - (BOOL)verifyHash:(NSData *)hash signature:(NSData *)signature key:(NSData *)key error:(NSError *__autoreleasing*)error;
29
+
30
+ //@required
31
+
32
+ @property (nonatomic, readonly, copy) NSString *name;
33
+
34
+ /**
35
+ Encodes and encrypts the provided payload using the provided secret key
36
+ @param theString The string to encode
37
+ @param theSecret The secret to use for encryption
38
+ @return An NSData object containing the encrypted payload, or nil if something went wrong.
39
+ */
40
+ - (NSData *)encodePayload:(NSString *)theString withSecret:(NSString *)theSecret __deprecated_and_will_be_removed_in_release_version(JWTVersion_3_0_0);
41
+
42
+ /**
43
+ Verifies the provided signature using the signed input and verification key
44
+ @param input The header and payload encoded string
45
+ @param signature The JWT provided signature
46
+ @param verificationKey The key to use for verifying the signature
47
+ @return YES if the provided signature is valid, NO otherwise
48
+ */
49
+ - (BOOL)verifySignedInput:(NSString *)input withSignature:(NSString *)signature verificationKey:(NSString *)verificationKey __deprecated_and_will_be_removed_in_release_version(JWTVersion_3_0_0);
50
+
51
+ @optional
52
+
53
+ /**
54
+ Encodes and encrypts the provided payload using the provided secret key
55
+ @param theStringData The data to encode
56
+ @param theSecretData The secret data to use for encryption
57
+ @return An NSData object containing the encrypted payload, or nil if something went wrong.
58
+ */
59
+ - (NSData *)encodePayloadData:(NSData *)theStringData withSecret:(NSData *)theSecretData;
60
+
61
+ /**
62
+ Verifies the provided signature using the signed input and verification key (as data)
63
+ @param input The header and payload encoded string
64
+ @param signature The JWT provided signature
65
+ @param verificationKeyData The key data to use for verifying the signature
66
+ @return YES if the provided signature is valid, NO otherwise
67
+ */
68
+ - (BOOL)verifySignedInput:(NSString *)input withSignature:(NSString *)signature verificationKeyData:(NSData *)verificationKeyData;
69
+ @end
@@ -0,0 +1,16 @@
1
+ //
2
+ // JWTAlgorithmFactory.h
3
+ // JWT
4
+ //
5
+ // Created by Lobanov Dmitry on 07.10.15.
6
+ // Copyright © 2015 Karma. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+ #import "JWTAlgorithm.h"
11
+ @interface JWTAlgorithmFactory : NSObject
12
+
13
+ + (NSArray *)algorithms;
14
+ + (id<JWTAlgorithm>)algorithmByName:(NSString *)name;
15
+
16
+ @end