@bravemobile/react-native-code-push 12.3.2 → 12.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CodePush.podspec +0 -2
- package/README.md +4 -2
- package/android/app/build.gradle +0 -1
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +0 -35
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +0 -1
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +1 -1
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +1 -28
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +1 -99
- package/cli/commands/bundleCommand/bundleCodePush.ts +29 -0
- package/cli/commands/bundleCommand/index.ts +3 -0
- package/cli/commands/releaseCommand/index.ts +3 -0
- package/cli/commands/releaseCommand/release.ts +2 -1
- package/cli/dist/commands/bundleCommand/bundleCodePush.js +14 -1
- package/cli/dist/commands/bundleCommand/index.js +2 -1
- package/cli/dist/commands/releaseCommand/index.js +2 -1
- package/cli/dist/commands/releaseCommand/release.js +2 -2
- package/cli/dist/utils/hash-utils.js +1 -4
- package/cli/utils/hash-utils.ts +1 -4
- package/ios/CodePush/CodePush.h +0 -16
- package/ios/CodePush/CodePush.m +0 -12
- package/ios/CodePush/CodePushConfig.m +0 -10
- package/ios/CodePush/CodePushPackage.m +0 -39
- package/ios/CodePush/CodePushUpdateUtils.m +1 -91
- package/ios/CodePush.xcodeproj/project.pbxproj +0 -324
- package/package.json +1 -1
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +0 -12
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.h +0 -34
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +0 -252
- package/ios/CodePush/Base64/README.md +0 -47
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +0 -69
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +0 -16
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +0 -51
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +0 -15
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +0 -55
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +0 -24
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +0 -41
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +0 -28
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +0 -205
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +0 -103
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +0 -322
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +0 -37
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +0 -145
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +0 -35
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +0 -551
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +0 -23
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +0 -43
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +0 -230
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +0 -31
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +0 -113
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +0 -38
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +0 -500
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +0 -18
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +0 -214
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +0 -23
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +0 -29
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +0 -19
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +0 -68
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +0 -18
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +0 -72
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +0 -67
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +0 -111
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +0 -119
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +0 -307
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +0 -94
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +0 -619
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +0 -164
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +0 -514
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +0 -24
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +0 -11
- package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +0 -52
- package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +0 -5
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +0 -28
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +0 -70
- package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +0 -22
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +0 -34
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +0 -73
- package/ios/CodePush/JWT/LICENSE +0 -19
- package/ios/CodePush/JWT/README.md +0 -489
package/CodePush.podspec
CHANGED
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
### 🚀 New Architecture support
|
|
10
10
|
|
|
11
|
-
Supports React Native 0.
|
|
11
|
+
Supports React Native 0.77 ~ 0.84.
|
|
12
12
|
|
|
13
13
|
> [!NOTE]
|
|
14
14
|
> If you are using React Native 0.76 or lower, please use version `12.0.2` of this library.
|
|
@@ -17,7 +17,7 @@ Supports React Native 0.74 ~ 0.84.
|
|
|
17
17
|
|
|
18
18
|
### ✅ Requirements
|
|
19
19
|
|
|
20
|
-
- **React Native**: 0.
|
|
20
|
+
- **React Native**: 0.77 or higher
|
|
21
21
|
- **iOS**: 15.5 or higher
|
|
22
22
|
- **Android**: API level 16 or higher
|
|
23
23
|
|
|
@@ -397,6 +397,8 @@ module.exports = Config;
|
|
|
397
397
|
|
|
398
398
|
> [!TIP]
|
|
399
399
|
> You can use `--help` command to see the available commands and options.
|
|
400
|
+
>
|
|
401
|
+
> For detailed documentation, see the [CLI README](cli/README.md) ([한국어](cli/README.ko.md)).
|
|
400
402
|
|
|
401
403
|
(interactive mode not supported yet)
|
|
402
404
|
|
package/android/app/build.gradle
CHANGED
|
@@ -3,10 +3,8 @@ package com.microsoft.codepush.react;
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
import android.content.pm.PackageInfo;
|
|
5
5
|
import android.content.pm.PackageManager;
|
|
6
|
-
import android.content.res.Resources;
|
|
7
6
|
|
|
8
7
|
import com.facebook.react.ReactPackage;
|
|
9
|
-
import com.facebook.react.bridge.JavaScriptModule;
|
|
10
8
|
import com.facebook.react.bridge.NativeModule;
|
|
11
9
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
12
10
|
import com.facebook.react.uimanager.ViewManager;
|
|
@@ -40,8 +38,6 @@ public class CodePush implements ReactPackage {
|
|
|
40
38
|
private Context mContext;
|
|
41
39
|
private final boolean mIsDebugMode;
|
|
42
40
|
|
|
43
|
-
private static String mPublicKey;
|
|
44
|
-
|
|
45
41
|
private static CodePush mCurrentInstance;
|
|
46
42
|
|
|
47
43
|
public static String getServiceUrl() {
|
|
@@ -75,33 +71,12 @@ public class CodePush implements ReactPackage {
|
|
|
75
71
|
|
|
76
72
|
mCurrentInstance = this;
|
|
77
73
|
|
|
78
|
-
String publicKeyFromStrings = getCustomPropertyFromStringsIfExist("PublicKey");
|
|
79
|
-
if (publicKeyFromStrings != null) mPublicKey = publicKeyFromStrings;
|
|
80
|
-
|
|
81
74
|
String serverUrlFromStrings = getCustomPropertyFromStringsIfExist("ServerUrl");
|
|
82
75
|
if (serverUrlFromStrings != null) mServerUrl = serverUrlFromStrings;
|
|
83
76
|
|
|
84
77
|
initializeUpdateAfterRestart();
|
|
85
78
|
}
|
|
86
79
|
|
|
87
|
-
private String getPublicKeyByResourceDescriptor(int publicKeyResourceDescriptor){
|
|
88
|
-
String publicKey;
|
|
89
|
-
try {
|
|
90
|
-
publicKey = mContext.getString(publicKeyResourceDescriptor);
|
|
91
|
-
} catch (Resources.NotFoundException e) {
|
|
92
|
-
throw new CodePushInvalidPublicKeyException(
|
|
93
|
-
"Unable to get public key, related resource descriptor " +
|
|
94
|
-
publicKeyResourceDescriptor +
|
|
95
|
-
" can not be found", e
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (publicKey.isEmpty()) {
|
|
100
|
-
throw new CodePushInvalidPublicKeyException("Specified public key is empty");
|
|
101
|
-
}
|
|
102
|
-
return publicKey;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
80
|
private String getCustomPropertyFromStringsIfExist(String propertyName) {
|
|
106
81
|
String property;
|
|
107
82
|
|
|
@@ -133,10 +108,6 @@ public class CodePush implements ReactPackage {
|
|
|
133
108
|
return mAssetsBundleFileName;
|
|
134
109
|
}
|
|
135
110
|
|
|
136
|
-
public String getPublicKey() {
|
|
137
|
-
return mPublicKey;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
111
|
public String getPackageFolder() {
|
|
141
112
|
JSONObject codePushLocalPackage = mUpdateManager.getCurrentPackage();
|
|
142
113
|
if (codePushLocalPackage == null) {
|
|
@@ -338,12 +309,6 @@ public class CodePush implements ReactPackage {
|
|
|
338
309
|
nativeModules.add(dialogModule);
|
|
339
310
|
return nativeModules;
|
|
340
311
|
}
|
|
341
|
-
|
|
342
|
-
// Deprecated in RN v0.47.
|
|
343
|
-
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
|
344
|
-
return new ArrayList<>();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
312
|
@Override
|
|
348
313
|
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
|
|
349
314
|
return new ArrayList<>();
|
|
@@ -24,7 +24,6 @@ public class CodePushConstants {
|
|
|
24
24
|
public static final String RELATIVE_BUNDLE_PATH_KEY = "bundlePath";
|
|
25
25
|
public static final String STATUS_FILE = "codepush.json";
|
|
26
26
|
public static final String UNZIPPED_FOLDER_NAME = "unzipped";
|
|
27
|
-
public static final String BUNDLE_JWT_FILE = ".codepushrelease";
|
|
28
27
|
public static final String LATEST_ROLLBACK_INFO_KEY = "LATEST_ROLLBACK_INFO";
|
|
29
28
|
public static final String LATEST_ROLLBACK_PACKAGE_HASH_KEY = "packageHash";
|
|
30
29
|
public static final String LATEST_ROLLBACK_TIME_KEY = "time";
|
|
@@ -384,7 +384,7 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
|
|
|
384
384
|
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
385
385
|
.emit(CodePushConstants.DOWNLOAD_PROGRESS_EVENT_NAME, latestDownloadProgress.createWritableMap());
|
|
386
386
|
}
|
|
387
|
-
}
|
|
387
|
+
});
|
|
388
388
|
|
|
389
389
|
JSONObject newPackage = mUpdateManager.getPackage(CodePushUtils.tryGetString(updatePackage, CodePushConstants.PACKAGE_HASH_KEY));
|
|
390
390
|
promise.resolve(CodePushUtils.convertJsonObjectToWritable(newPackage));
|
|
@@ -144,8 +144,7 @@ public class CodePushUpdateManager {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
public void downloadPackage(JSONObject updatePackage, String expectedBundleFileName,
|
|
147
|
-
DownloadProgressCallback progressCallback
|
|
148
|
-
String stringPublicKey) throws IOException {
|
|
147
|
+
DownloadProgressCallback progressCallback) throws IOException {
|
|
149
148
|
String newUpdateHash = updatePackage.optString(CodePushConstants.PACKAGE_HASH_KEY, null);
|
|
150
149
|
String newUpdateFolderPath = getPackageFolderPath(newUpdateHash);
|
|
151
150
|
String newUpdateMetadataPath = CodePushUtils.appendPathComponent(newUpdateFolderPath, CodePushConstants.PACKAGE_FILE_NAME);
|
|
@@ -266,32 +265,6 @@ public class CodePushUpdateManager {
|
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
|
|
269
|
-
|
|
270
|
-
boolean isSignatureVerificationEnabled = (stringPublicKey != null);
|
|
271
|
-
|
|
272
|
-
String signaturePath = CodePushUpdateUtils.getSignatureFilePath(newUpdateFolderPath);
|
|
273
|
-
boolean isSignatureAppearedInBundle = FileUtils.fileAtPathExists(signaturePath);
|
|
274
|
-
|
|
275
|
-
if (isSignatureVerificationEnabled) {
|
|
276
|
-
if (isSignatureAppearedInBundle) {
|
|
277
|
-
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
|
|
278
|
-
} else {
|
|
279
|
-
throw new CodePushInvalidUpdateException(
|
|
280
|
-
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +
|
|
281
|
-
"Possible reasons, why that might happen: \n" +
|
|
282
|
-
"1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.\n" +
|
|
283
|
-
"2. You've been released CodePush bundle update without providing --privateKeyPath option."
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
if (isSignatureAppearedInBundle) {
|
|
288
|
-
CodePushUtils.log(
|
|
289
|
-
"Warning! JWT signature exists in codepush update but code integrity check couldn't be performed because there is no public key configured. " +
|
|
290
|
-
"Please ensure that public key is properly configured within your application."
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
268
|
CodePushUtils.setJSONValueForKey(updatePackage, CodePushConstants.RELATIVE_BUNDLE_PATH_KEY, relativeBundlePath);
|
|
296
269
|
}
|
|
297
270
|
} else {
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
package com.microsoft.codepush.react;
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
|
-
import android.util.Base64;
|
|
5
|
-
|
|
6
|
-
import com.nimbusds.jose.JWSVerifier;
|
|
7
|
-
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
|
8
|
-
import com.nimbusds.jwt.SignedJWT;
|
|
9
|
-
|
|
10
|
-
import java.security.interfaces.*;
|
|
11
4
|
|
|
12
5
|
import org.json.JSONArray;
|
|
13
6
|
import org.json.JSONException;
|
|
@@ -20,14 +13,10 @@ import java.io.FileNotFoundException;
|
|
|
20
13
|
import java.io.IOException;
|
|
21
14
|
import java.io.InputStream;
|
|
22
15
|
import java.security.DigestInputStream;
|
|
23
|
-
import java.security.KeyFactory;
|
|
24
16
|
import java.security.MessageDigest;
|
|
25
17
|
import java.security.NoSuchAlgorithmException;
|
|
26
|
-
import java.security.PublicKey;
|
|
27
|
-
import java.security.spec.X509EncodedKeySpec;
|
|
28
18
|
import java.util.ArrayList;
|
|
29
19
|
import java.util.Collections;
|
|
30
|
-
import java.util.Map;
|
|
31
20
|
|
|
32
21
|
public class CodePushUpdateUtils {
|
|
33
22
|
|
|
@@ -38,13 +27,10 @@ public class CodePushUpdateUtils {
|
|
|
38
27
|
public static boolean isHashIgnored(String relativeFilePath) {
|
|
39
28
|
final String __MACOSX = "__MACOSX/";
|
|
40
29
|
final String DS_STORE = ".DS_Store";
|
|
41
|
-
final String CODEPUSH_METADATA = ".codepushrelease";
|
|
42
30
|
|
|
43
31
|
return relativeFilePath.startsWith(__MACOSX)
|
|
44
32
|
|| relativeFilePath.equals(DS_STORE)
|
|
45
|
-
|| relativeFilePath.endsWith("/" + DS_STORE)
|
|
46
|
-
|| relativeFilePath.equals(CODEPUSH_METADATA)
|
|
47
|
-
|| relativeFilePath.endsWith("/" + CODEPUSH_METADATA);
|
|
33
|
+
|| relativeFilePath.endsWith("/" + DS_STORE);
|
|
48
34
|
}
|
|
49
35
|
|
|
50
36
|
private static void addContentsOfFolderToManifest(String folderPath, String pathPrefix, ArrayList<String> manifest) {
|
|
@@ -183,88 +169,4 @@ public class CodePushUpdateUtils {
|
|
|
183
169
|
CodePushUtils.log("The update contents succeeded the data integrity check.");
|
|
184
170
|
}
|
|
185
171
|
|
|
186
|
-
public static Map<String, Object> verifyAndDecodeJWT(String jwt, PublicKey publicKey) {
|
|
187
|
-
try {
|
|
188
|
-
SignedJWT signedJWT = SignedJWT.parse(jwt);
|
|
189
|
-
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
|
|
190
|
-
if (signedJWT.verify(verifier)) {
|
|
191
|
-
Map<String, Object> claims = signedJWT.getJWTClaimsSet().getClaims();
|
|
192
|
-
CodePushUtils.log("JWT verification succeeded, payload content: " + claims.toString());
|
|
193
|
-
return claims;
|
|
194
|
-
}
|
|
195
|
-
return null;
|
|
196
|
-
} catch (Exception ex) {
|
|
197
|
-
CodePushUtils.log(ex.getMessage());
|
|
198
|
-
CodePushUtils.log(ex.getStackTrace().toString());
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
public static PublicKey parsePublicKey(String stringPublicKey) {
|
|
204
|
-
try {
|
|
205
|
-
//remove unnecessary "begin/end public key" entries from string
|
|
206
|
-
stringPublicKey = stringPublicKey
|
|
207
|
-
.replace("-----BEGIN PUBLIC KEY-----", "")
|
|
208
|
-
.replace("-----END PUBLIC KEY-----", "")
|
|
209
|
-
.replace(NEW_LINE, "");
|
|
210
|
-
byte[] byteKey = Base64.decode(stringPublicKey.getBytes(), Base64.DEFAULT);
|
|
211
|
-
X509EncodedKeySpec X509Key = new X509EncodedKeySpec(byteKey);
|
|
212
|
-
KeyFactory kf = KeyFactory.getInstance("RSA");
|
|
213
|
-
|
|
214
|
-
return kf.generatePublic(X509Key);
|
|
215
|
-
} catch (Exception e) {
|
|
216
|
-
CodePushUtils.log(e.getMessage());
|
|
217
|
-
CodePushUtils.log(e.getStackTrace().toString());
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
public static String getSignatureFilePath(String updateFolderPath) {
|
|
223
|
-
return CodePushUtils.appendPathComponent(
|
|
224
|
-
CodePushUtils.appendPathComponent(updateFolderPath, CodePushConstants.CODE_PUSH_FOLDER_PREFIX),
|
|
225
|
-
CodePushConstants.BUNDLE_JWT_FILE
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
public static String getSignature(String folderPath) {
|
|
230
|
-
final String signatureFilePath = getSignatureFilePath(folderPath);
|
|
231
|
-
|
|
232
|
-
try {
|
|
233
|
-
return FileUtils.readFileToString(signatureFilePath);
|
|
234
|
-
} catch (IOException e) {
|
|
235
|
-
CodePushUtils.log(e.getMessage());
|
|
236
|
-
CodePushUtils.log(e.getStackTrace().toString());
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
public static void verifyUpdateSignature(String folderPath, String packageHash, String stringPublicKey) throws CodePushInvalidUpdateException {
|
|
242
|
-
CodePushUtils.log("Verifying signature for folder path: " + folderPath);
|
|
243
|
-
|
|
244
|
-
final PublicKey publicKey = parsePublicKey(stringPublicKey);
|
|
245
|
-
if (publicKey == null) {
|
|
246
|
-
throw new CodePushInvalidUpdateException("The update could not be verified because no public key was found.");
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
final String signature = getSignature(folderPath);
|
|
250
|
-
if (signature == null) {
|
|
251
|
-
throw new CodePushInvalidUpdateException("The update could not be verified because no signature was found.");
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
final Map<String, Object> claims = verifyAndDecodeJWT(signature, publicKey);
|
|
255
|
-
if (claims == null) {
|
|
256
|
-
throw new CodePushInvalidUpdateException("The update could not be verified because it was not signed by a trusted party.");
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
final String contentHash = (String) claims.get("contentHash");
|
|
260
|
-
if (contentHash == null) {
|
|
261
|
-
throw new CodePushInvalidUpdateException("The update could not be verified because the signature did not specify a content hash.");
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (!contentHash.equals(packageHash)) {
|
|
265
|
-
throw new CodePushInvalidUpdateException("The update contents failed the code signing check.");
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
CodePushUtils.log("The update contents succeeded the code signing check.");
|
|
269
|
-
}
|
|
270
172
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
2
3
|
import { prepareToBundleJS } from "../../functions/prepareToBundleJS.js";
|
|
3
4
|
import { runReactNativeBundleCommand } from "../../functions/runReactNativeBundleCommand.js";
|
|
4
5
|
import { runExpoBundleCommand } from "../../functions/runExpoBundleCommand.js";
|
|
@@ -17,6 +18,7 @@ export async function bundleCodePush(
|
|
|
17
18
|
entryFile: string = ENTRY_FILE,
|
|
18
19
|
jsBundleName: string, // JS bundle file name (not CodePush bundle file)
|
|
19
20
|
bundleDirectory: string, // CodePush bundle output directory
|
|
21
|
+
outputMetroDir?: string,
|
|
20
22
|
): Promise<string> {
|
|
21
23
|
if (fs.existsSync(outputRootPath)) {
|
|
22
24
|
fs.rmSync(outputRootPath, { recursive: true });
|
|
@@ -49,6 +51,8 @@ export async function bundleCodePush(
|
|
|
49
51
|
|
|
50
52
|
console.log('log: JS bundling complete');
|
|
51
53
|
|
|
54
|
+
copyMetroOutputsIfNeeded(outputRootPath, outputMetroDir, OUTPUT_CONTENT_PATH, _jsBundleName, SOURCEMAP_OUTPUT);
|
|
55
|
+
|
|
52
56
|
await runHermesEmitBinaryCommand(
|
|
53
57
|
_jsBundleName,
|
|
54
58
|
OUTPUT_CONTENT_PATH,
|
|
@@ -61,3 +65,28 @@ export async function bundleCodePush(
|
|
|
61
65
|
|
|
62
66
|
return codePushBundleFileName;
|
|
63
67
|
}
|
|
68
|
+
|
|
69
|
+
function copyMetroOutputsIfNeeded(
|
|
70
|
+
outputRootPath: string,
|
|
71
|
+
outputMetroDir: string | undefined,
|
|
72
|
+
outputContentPath: string,
|
|
73
|
+
jsBundleName: string,
|
|
74
|
+
sourceMapOutputPath: string,
|
|
75
|
+
) {
|
|
76
|
+
if (!outputMetroDir) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const resolvedOutputMetroDir = path.join(outputRootPath, outputMetroDir);
|
|
81
|
+
|
|
82
|
+
fs.mkdirSync(resolvedOutputMetroDir, { recursive: true });
|
|
83
|
+
fs.copyFileSync(
|
|
84
|
+
path.join(outputContentPath, jsBundleName),
|
|
85
|
+
path.join(resolvedOutputMetroDir, jsBundleName),
|
|
86
|
+
);
|
|
87
|
+
fs.copyFileSync(
|
|
88
|
+
sourceMapOutputPath,
|
|
89
|
+
path.join(resolvedOutputMetroDir, path.basename(sourceMapOutputPath)),
|
|
90
|
+
);
|
|
91
|
+
console.log(`log: Metro outputs copied to: ${resolvedOutputMetroDir}`);
|
|
92
|
+
}
|
|
@@ -9,6 +9,7 @@ type Options = {
|
|
|
9
9
|
entryFile: string;
|
|
10
10
|
bundleName: string;
|
|
11
11
|
outputBundleDir: string;
|
|
12
|
+
outputMetroDir?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
program.command('bundle')
|
|
@@ -18,6 +19,7 @@ program.command('bundle')
|
|
|
18
19
|
.option('-o, --output-path <string>', 'path to output root directory', ROOT_OUTPUT_DIR)
|
|
19
20
|
.option('-e, --entry-file <string>', 'path to JS/TS entry file', ENTRY_FILE)
|
|
20
21
|
.option('-b, --bundle-name <string>', 'bundle file name (default-ios: "main.jsbundle" / default-android: "index.android.bundle")')
|
|
22
|
+
.option('--output-metro-dir <string>', 'name of directory to copy the Metro JS bundle and sourcemap before Hermes compilation')
|
|
21
23
|
.option('--output-bundle-dir <string>', 'name of directory containing the bundle file created by the "bundle" command', OUTPUT_BUNDLE_DIR)
|
|
22
24
|
.action((options: Options) => {
|
|
23
25
|
bundleCodePush(
|
|
@@ -27,5 +29,6 @@ program.command('bundle')
|
|
|
27
29
|
options.entryFile,
|
|
28
30
|
options.bundleName,
|
|
29
31
|
`${options.outputPath}/${options.outputBundleDir}`,
|
|
32
|
+
options.outputMetroDir,
|
|
30
33
|
)
|
|
31
34
|
});
|
|
@@ -19,6 +19,7 @@ type Options = {
|
|
|
19
19
|
skipBundle: boolean;
|
|
20
20
|
skipCleanup: boolean;
|
|
21
21
|
outputBundleDir: string;
|
|
22
|
+
outputMetroDir?: string;
|
|
22
23
|
hashCalc?: boolean;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -39,6 +40,7 @@ program.command('release')
|
|
|
39
40
|
.option('--skip-bundle <bool>', 'skip bundle process', parseBoolean, false)
|
|
40
41
|
.option('--hash-calc <bool>', 'calculates the bundle file hash used for packageHash in the release history (Requires setting --skip-bundle to true)', parseBoolean)
|
|
41
42
|
.option('--skip-cleanup <bool>', 'skip cleanup process', parseBoolean, false)
|
|
43
|
+
.option('--output-metro-dir <string>', 'name of directory to copy the Metro JS bundle and sourcemap before Hermes compilation')
|
|
42
44
|
.option('--output-bundle-dir <string>', 'name of directory containing the bundle file created by the "bundle" command', OUTPUT_BUNDLE_DIR)
|
|
43
45
|
.action(async (options: Options) => {
|
|
44
46
|
const config = findAndReadConfigFile(process.cwd(), options.config);
|
|
@@ -71,6 +73,7 @@ program.command('release')
|
|
|
71
73
|
options.skipBundle,
|
|
72
74
|
options.skipCleanup,
|
|
73
75
|
`${options.outputPath}/${options.outputBundleDir}`,
|
|
76
|
+
options.outputMetroDir,
|
|
74
77
|
options.hashCalc,
|
|
75
78
|
)
|
|
76
79
|
|
|
@@ -24,11 +24,12 @@ export async function release(
|
|
|
24
24
|
skipBundle: boolean,
|
|
25
25
|
skipCleanup: boolean,
|
|
26
26
|
bundleDirectory: string,
|
|
27
|
+
outputMetroDir?: string,
|
|
27
28
|
hashCalc?: boolean,
|
|
28
29
|
): Promise<void> {
|
|
29
30
|
const bundleFileName = skipBundle
|
|
30
31
|
? readBundleFileNameFrom(bundleDirectory)
|
|
31
|
-
: await bundleCodePush(framework, platform, outputPath, entryFile, jsBundleName, bundleDirectory);
|
|
32
|
+
: await bundleCodePush(framework, platform, outputPath, entryFile, jsBundleName, bundleDirectory, outputMetroDir);
|
|
32
33
|
const bundleFilePath = `${bundleDirectory}/${bundleFileName}`;
|
|
33
34
|
|
|
34
35
|
const packageHash = await (() => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
2
3
|
import { prepareToBundleJS } from "../../functions/prepareToBundleJS.js";
|
|
3
4
|
import { runReactNativeBundleCommand } from "../../functions/runReactNativeBundleCommand.js";
|
|
4
5
|
import { runExpoBundleCommand } from "../../functions/runExpoBundleCommand.js";
|
|
@@ -10,7 +11,8 @@ import { ROOT_OUTPUT_DIR, ENTRY_FILE } from "../../constant.js";
|
|
|
10
11
|
* @return {Promise<string>} CodePush bundle file name (equals to packageHash)
|
|
11
12
|
*/
|
|
12
13
|
export async function bundleCodePush(framework, platform = 'ios', outputRootPath = ROOT_OUTPUT_DIR, entryFile = ENTRY_FILE, jsBundleName, // JS bundle file name (not CodePush bundle file)
|
|
13
|
-
bundleDirectory
|
|
14
|
+
bundleDirectory, // CodePush bundle output directory
|
|
15
|
+
outputMetroDir) {
|
|
14
16
|
if (fs.existsSync(outputRootPath)) {
|
|
15
17
|
fs.rmSync(outputRootPath, { recursive: true });
|
|
16
18
|
}
|
|
@@ -26,9 +28,20 @@ bundleDirectory) {
|
|
|
26
28
|
runReactNativeBundleCommand(_jsBundleName, OUTPUT_CONTENT_PATH, platform, SOURCEMAP_OUTPUT, entryFile);
|
|
27
29
|
}
|
|
28
30
|
console.log('log: JS bundling complete');
|
|
31
|
+
copyMetroOutputsIfNeeded(outputRootPath, outputMetroDir, OUTPUT_CONTENT_PATH, _jsBundleName, SOURCEMAP_OUTPUT);
|
|
29
32
|
await runHermesEmitBinaryCommand(_jsBundleName, OUTPUT_CONTENT_PATH, SOURCEMAP_OUTPUT);
|
|
30
33
|
console.log('log: Hermes compilation complete');
|
|
31
34
|
const { bundleFileName: codePushBundleFileName } = await makeCodePushBundle(OUTPUT_CONTENT_PATH, bundleDirectory);
|
|
32
35
|
console.log(`log: CodePush bundle created (file path: ./${bundleDirectory}/${codePushBundleFileName})`);
|
|
33
36
|
return codePushBundleFileName;
|
|
34
37
|
}
|
|
38
|
+
function copyMetroOutputsIfNeeded(outputRootPath, outputMetroDir, outputContentPath, jsBundleName, sourceMapOutputPath) {
|
|
39
|
+
if (!outputMetroDir) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const resolvedOutputMetroDir = path.join(outputRootPath, outputMetroDir);
|
|
43
|
+
fs.mkdirSync(resolvedOutputMetroDir, { recursive: true });
|
|
44
|
+
fs.copyFileSync(path.join(outputContentPath, jsBundleName), path.join(resolvedOutputMetroDir, jsBundleName));
|
|
45
|
+
fs.copyFileSync(sourceMapOutputPath, path.join(resolvedOutputMetroDir, path.basename(sourceMapOutputPath)));
|
|
46
|
+
console.log(`log: Metro outputs copied to: ${resolvedOutputMetroDir}`);
|
|
47
|
+
}
|
|
@@ -8,7 +8,8 @@ program.command('bundle')
|
|
|
8
8
|
.option('-o, --output-path <string>', 'path to output root directory', ROOT_OUTPUT_DIR)
|
|
9
9
|
.option('-e, --entry-file <string>', 'path to JS/TS entry file', ENTRY_FILE)
|
|
10
10
|
.option('-b, --bundle-name <string>', 'bundle file name (default-ios: "main.jsbundle" / default-android: "index.android.bundle")')
|
|
11
|
+
.option('--output-metro-dir <string>', 'name of directory to copy the Metro JS bundle and sourcemap before Hermes compilation')
|
|
11
12
|
.option('--output-bundle-dir <string>', 'name of directory containing the bundle file created by the "bundle" command', OUTPUT_BUNDLE_DIR)
|
|
12
13
|
.action((options) => {
|
|
13
|
-
bundleCodePush(options.framework, options.platform, options.outputPath, options.entryFile, options.bundleName, `${options.outputPath}/${options.outputBundleDir}
|
|
14
|
+
bundleCodePush(options.framework, options.platform, options.outputPath, options.entryFile, options.bundleName, `${options.outputPath}/${options.outputBundleDir}`, options.outputMetroDir);
|
|
14
15
|
});
|
|
@@ -19,6 +19,7 @@ program.command('release')
|
|
|
19
19
|
.option('--skip-bundle <bool>', 'skip bundle process', parseBoolean, false)
|
|
20
20
|
.option('--hash-calc <bool>', 'calculates the bundle file hash used for packageHash in the release history (Requires setting --skip-bundle to true)', parseBoolean)
|
|
21
21
|
.option('--skip-cleanup <bool>', 'skip cleanup process', parseBoolean, false)
|
|
22
|
+
.option('--output-metro-dir <string>', 'name of directory to copy the Metro JS bundle and sourcemap before Hermes compilation')
|
|
22
23
|
.option('--output-bundle-dir <string>', 'name of directory containing the bundle file created by the "bundle" command', OUTPUT_BUNDLE_DIR)
|
|
23
24
|
.action(async (options) => {
|
|
24
25
|
const config = findAndReadConfigFile(process.cwd(), options.config);
|
|
@@ -30,7 +31,7 @@ program.command('release')
|
|
|
30
31
|
console.error('--hash-calc option can be used only when --skip-bundle is set to true.');
|
|
31
32
|
process.exit(1);
|
|
32
33
|
}
|
|
33
|
-
await release(config.bundleUploader, config.getReleaseHistory, config.setReleaseHistory, options.binaryVersion, options.appVersion, options.framework, options.platform, options.identifier, options.outputPath, options.entryFile, options.bundleName, options.mandatory, options.enable, options.rollout, options.skipBundle, options.skipCleanup, `${options.outputPath}/${options.outputBundleDir}`, options.hashCalc);
|
|
34
|
+
await release(config.bundleUploader, config.getReleaseHistory, config.setReleaseHistory, options.binaryVersion, options.appVersion, options.framework, options.platform, options.identifier, options.outputPath, options.entryFile, options.bundleName, options.mandatory, options.enable, options.rollout, options.skipBundle, options.skipCleanup, `${options.outputPath}/${options.outputBundleDir}`, options.outputMetroDir, options.hashCalc);
|
|
34
35
|
console.log('🚀 Release completed.');
|
|
35
36
|
});
|
|
36
37
|
function parseBoolean(value) {
|
|
@@ -4,10 +4,10 @@ import { bundleCodePush } from "../bundleCommand/bundleCodePush.js";
|
|
|
4
4
|
import { addToReleaseHistory } from "./addToReleaseHistory.js";
|
|
5
5
|
import { generatePackageHashFromDirectory } from "../../utils/hash-utils.js";
|
|
6
6
|
import { unzip } from "../../utils/unzip.js";
|
|
7
|
-
export async function release(bundleUploader, getReleaseHistory, setReleaseHistory, binaryVersion, appVersion, framework, platform, identifier, outputPath, entryFile, jsBundleName, mandatory, enable, rollout, skipBundle, skipCleanup, bundleDirectory, hashCalc) {
|
|
7
|
+
export async function release(bundleUploader, getReleaseHistory, setReleaseHistory, binaryVersion, appVersion, framework, platform, identifier, outputPath, entryFile, jsBundleName, mandatory, enable, rollout, skipBundle, skipCleanup, bundleDirectory, outputMetroDir, hashCalc) {
|
|
8
8
|
const bundleFileName = skipBundle
|
|
9
9
|
? readBundleFileNameFrom(bundleDirectory)
|
|
10
|
-
: await bundleCodePush(framework, platform, outputPath, entryFile, jsBundleName, bundleDirectory);
|
|
10
|
+
: await bundleCodePush(framework, platform, outputPath, entryFile, jsBundleName, bundleDirectory, outputMetroDir);
|
|
11
11
|
const bundleFilePath = `${bundleDirectory}/${bundleFileName}`;
|
|
12
12
|
const packageHash = await (() => {
|
|
13
13
|
if (skipBundle && hashCalc) {
|
|
@@ -48,12 +48,9 @@ class PackageManifest {
|
|
|
48
48
|
static isIgnored(relativeFilePath) {
|
|
49
49
|
const __MACOSX = '__MACOSX/';
|
|
50
50
|
const DS_STORE = '.DS_Store';
|
|
51
|
-
const CODEPUSH_METADATA = '.codepushrelease';
|
|
52
51
|
return (relativeFilePath.startsWith(__MACOSX) ||
|
|
53
52
|
relativeFilePath === DS_STORE ||
|
|
54
|
-
relativeFilePath.endsWith('/' + DS_STORE)
|
|
55
|
-
relativeFilePath === CODEPUSH_METADATA ||
|
|
56
|
-
relativeFilePath.endsWith('/' + CODEPUSH_METADATA));
|
|
53
|
+
relativeFilePath.endsWith('/' + DS_STORE));
|
|
57
54
|
}
|
|
58
55
|
}
|
|
59
56
|
export async function generatePackageHashFromDirectory(directoryPath, basePath) {
|
package/cli/utils/hash-utils.ts
CHANGED
|
@@ -61,13 +61,10 @@ class PackageManifest {
|
|
|
61
61
|
static isIgnored(relativeFilePath: string): boolean {
|
|
62
62
|
const __MACOSX = '__MACOSX/';
|
|
63
63
|
const DS_STORE = '.DS_Store';
|
|
64
|
-
const CODEPUSH_METADATA = '.codepushrelease';
|
|
65
64
|
return (
|
|
66
65
|
relativeFilePath.startsWith(__MACOSX) ||
|
|
67
66
|
relativeFilePath === DS_STORE ||
|
|
68
|
-
relativeFilePath.endsWith('/' + DS_STORE)
|
|
69
|
-
relativeFilePath === CODEPUSH_METADATA ||
|
|
70
|
-
relativeFilePath.endsWith('/' + CODEPUSH_METADATA)
|
|
67
|
+
relativeFilePath.endsWith('/' + DS_STORE)
|
|
71
68
|
);
|
|
72
69
|
}
|
|
73
70
|
}
|
package/ios/CodePush/CodePush.h
CHANGED
|
@@ -102,7 +102,6 @@
|
|
|
102
102
|
@property (readonly) NSDictionary *configuration;
|
|
103
103
|
@property (copy) NSString *deploymentKey;
|
|
104
104
|
@property (copy) NSString *serverURL;
|
|
105
|
-
@property (copy) NSString *publicKey;
|
|
106
105
|
|
|
107
106
|
+ (instancetype)current;
|
|
108
107
|
|
|
@@ -140,7 +139,6 @@ failCallback:(void (^)(NSError *err))failCallback;
|
|
|
140
139
|
|
|
141
140
|
+ (void)downloadPackage:(NSDictionary *)updatePackage
|
|
142
141
|
expectedBundleFileName:(NSString *)expectedBundleFileName
|
|
143
|
-
publicKey:(NSString *)publicKey
|
|
144
142
|
operationQueue:(dispatch_queue_t)operationQueue
|
|
145
143
|
progressCallback:(void (^)(long long, long long))progressCallback
|
|
146
144
|
doneCallback:(void (^)())doneCallback
|
|
@@ -203,20 +201,6 @@ failCallback:(void (^)(NSError *err))failCallback;
|
|
|
203
201
|
expectedHash:(NSString *)expectedHash
|
|
204
202
|
error:(NSError **)error;
|
|
205
203
|
|
|
206
|
-
// remove BEGIN / END tags and line breaks from public key string
|
|
207
|
-
+ (NSString *)getKeyValueFromPublicKeyString:(NSString *)publicKeyString;
|
|
208
|
-
|
|
209
|
-
+ (NSString *)getSignatureFilePath:(NSString *)updateFolderPath;
|
|
210
|
-
|
|
211
|
-
+ (NSDictionary *) verifyAndDecodeJWT:(NSString *) jwt
|
|
212
|
-
withPublicKey:(NSString *)publicKey
|
|
213
|
-
error:(NSError **)error;
|
|
214
|
-
|
|
215
|
-
+ (BOOL)verifyUpdateSignatureFor:(NSString *)updateFolderPath
|
|
216
|
-
expectedHash:(NSString *)newUpdateHash
|
|
217
|
-
withPublicKey:(NSString *)publicKeyString
|
|
218
|
-
error:(NSError **)error;
|
|
219
|
-
|
|
220
204
|
@end
|
|
221
205
|
|
|
222
206
|
void CPLog(NSString *formatString, ...);
|
package/ios/CodePush/CodePush.m
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#if __has_include(<React/RCTAssert.h>)
|
|
2
1
|
#import <React/RCTAssert.h>
|
|
3
2
|
#import <React/RCTBridgeModule.h>
|
|
4
3
|
#import <React/RCTConvert.h>
|
|
@@ -6,14 +5,6 @@
|
|
|
6
5
|
#import <React/RCTRootView.h>
|
|
7
6
|
#import <React/RCTUtils.h>
|
|
8
7
|
#import <React/RCTReloadCommand.h>
|
|
9
|
-
#else // back compatibility for RN version < 0.40
|
|
10
|
-
#import "RCTAssert.h"
|
|
11
|
-
#import "RCTBridgeModule.h"
|
|
12
|
-
#import "RCTConvert.h"
|
|
13
|
-
#import "RCTEventDispatcher.h"
|
|
14
|
-
#import "RCTRootView.h"
|
|
15
|
-
#import "RCTUtils.h"
|
|
16
|
-
#endif
|
|
17
8
|
|
|
18
9
|
#import "CodePush.h"
|
|
19
10
|
|
|
@@ -740,12 +731,9 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
|
|
|
740
731
|
_lastProgressEventTime = 0;
|
|
741
732
|
}
|
|
742
733
|
|
|
743
|
-
NSString * publicKey = [[CodePushConfig current] publicKey];
|
|
744
|
-
|
|
745
734
|
[CodePushPackage
|
|
746
735
|
downloadPackage:mutableUpdatePackage
|
|
747
736
|
expectedBundleFileName:[bundleResourceName stringByAppendingPathExtension:bundleResourceExtension]
|
|
748
|
-
publicKey:publicKey
|
|
749
737
|
operationQueue:_methodQueue
|
|
750
738
|
// The download is progressing forward
|
|
751
739
|
progressCallback:^(long long expectedContentLength, long long receivedContentLength) {
|
|
@@ -12,7 +12,6 @@ static NSString * const BuildVersionConfigKey = @"buildVersion";
|
|
|
12
12
|
static NSString * const ClientUniqueIDConfigKey = @"clientUniqueId";
|
|
13
13
|
static NSString * const DeploymentKeyConfigKey = @"deploymentKey";
|
|
14
14
|
static NSString * const ServerURLConfigKey = @"serverUrl";
|
|
15
|
-
static NSString * const PublicKeyKey = @"publicKey";
|
|
16
15
|
|
|
17
16
|
+ (instancetype)current
|
|
18
17
|
{
|
|
@@ -35,7 +34,6 @@ static NSString * const PublicKeyKey = @"publicKey";
|
|
|
35
34
|
NSString *buildVersion = [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey];
|
|
36
35
|
NSString *deploymentKey = [infoDictionary objectForKey:@"CodePushDeploymentKey"];
|
|
37
36
|
NSString *serverURL = [infoDictionary objectForKey:@"CodePushServerURL"];
|
|
38
|
-
NSString *publicKey = [infoDictionary objectForKey:@"CodePushPublicKey"];
|
|
39
37
|
|
|
40
38
|
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
|
|
41
39
|
NSString *clientUniqueId = [userDefaults stringForKey:ClientUniqueIDConfigKey];
|
|
@@ -56,7 +54,6 @@ static NSString * const PublicKeyKey = @"publicKey";
|
|
|
56
54
|
if (serverURL) [_configDictionary setObject:serverURL forKey:ServerURLConfigKey];
|
|
57
55
|
if (clientUniqueId) [_configDictionary setObject:clientUniqueId forKey:ClientUniqueIDConfigKey];
|
|
58
56
|
if (deploymentKey) [_configDictionary setObject:deploymentKey forKey:DeploymentKeyConfigKey];
|
|
59
|
-
if (publicKey) [_configDictionary setObject:publicKey forKey:PublicKeyKey];
|
|
60
57
|
|
|
61
58
|
return self;
|
|
62
59
|
}
|
|
@@ -91,11 +88,6 @@ static NSString * const PublicKeyKey = @"publicKey";
|
|
|
91
88
|
return [_configDictionary objectForKey:ClientUniqueIDConfigKey];
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
- (NSString *)publicKey
|
|
95
|
-
{
|
|
96
|
-
return [_configDictionary objectForKey:PublicKeyKey];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
91
|
- (void)setAppVersion:(NSString *)appVersion
|
|
100
92
|
{
|
|
101
93
|
[_configDictionary setValue:appVersion forKey:AppVersionConfigKey];
|
|
@@ -111,6 +103,4 @@ static NSString * const PublicKeyKey = @"publicKey";
|
|
|
111
103
|
[_configDictionary setValue:serverURL forKey:ServerURLConfigKey];
|
|
112
104
|
}
|
|
113
105
|
|
|
114
|
-
//no setter for PublicKey, because it's need to be hard coded within Info.plist for safety
|
|
115
|
-
|
|
116
106
|
@end
|