@capgo/capacitor-updater 8.41.5 → 8.41.7
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/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +4 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +17 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +2 -2
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +6 -3
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +13 -5
- package/package.json +1 -1
|
@@ -84,7 +84,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
84
84
|
private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
|
|
85
85
|
private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
|
|
86
86
|
|
|
87
|
-
private final String pluginVersion = "8.41.
|
|
87
|
+
private final String pluginVersion = "8.41.7";
|
|
88
88
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
89
89
|
|
|
90
90
|
private SharedPreferences.Editor editor;
|
|
@@ -2109,6 +2109,9 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2109
2109
|
}
|
|
2110
2110
|
|
|
2111
2111
|
public void appMovedToBackground() {
|
|
2112
|
+
// Reset timeout flag at start of each background cycle
|
|
2113
|
+
this.autoSplashscreenTimedOut = false;
|
|
2114
|
+
|
|
2112
2115
|
final BundleInfo current = CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
2113
2116
|
|
|
2114
2117
|
// Show splashscreen FIRST, before any other background work to ensure launcher shows it
|
|
@@ -153,12 +153,25 @@ public class CapgoUpdater {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
public void setPublicKey(String publicKey) {
|
|
156
|
-
|
|
157
|
-
if (
|
|
158
|
-
this.
|
|
159
|
-
} else {
|
|
156
|
+
// Empty string means no encryption - proceed normally
|
|
157
|
+
if (publicKey == null || publicKey.isEmpty()) {
|
|
158
|
+
this.publicKey = "";
|
|
160
159
|
this.cachedKeyId = "";
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Non-empty: must be a valid RSA key or crash
|
|
164
|
+
try {
|
|
165
|
+
CryptoCipher.stringToPublicKey(publicKey);
|
|
166
|
+
} catch (Exception e) {
|
|
167
|
+
throw new RuntimeException(
|
|
168
|
+
"Invalid public key in capacitor.config.json: failed to parse RSA key. Remove the key or provide a valid PEM-formatted RSA public key.",
|
|
169
|
+
e
|
|
170
|
+
);
|
|
161
171
|
}
|
|
172
|
+
|
|
173
|
+
this.publicKey = publicKey;
|
|
174
|
+
this.cachedKeyId = CryptoCipher.calcKeyId(publicKey);
|
|
162
175
|
}
|
|
163
176
|
|
|
164
177
|
public String getKeyId() {
|
|
@@ -291,7 +291,7 @@ public class DownloadService extends Worker {
|
|
|
291
291
|
String fileHash = entry.getString("file_hash");
|
|
292
292
|
String downloadUrl = entry.getString("download_url");
|
|
293
293
|
|
|
294
|
-
if (!publicKey.isEmpty() && sessionKey != null && !sessionKey.isEmpty()) {
|
|
294
|
+
if (publicKey != null && !publicKey.isEmpty() && sessionKey != null && !sessionKey.isEmpty()) {
|
|
295
295
|
try {
|
|
296
296
|
fileHash = CryptoCipher.decryptChecksum(fileHash, publicKey);
|
|
297
297
|
} catch (Exception e) {
|
|
@@ -633,7 +633,7 @@ public class DownloadService extends Worker {
|
|
|
633
633
|
// Use OkIO for atomic write
|
|
634
634
|
writeFileAtomic(compressedFile, responseBody.byteStream(), null);
|
|
635
635
|
|
|
636
|
-
if (!publicKey.isEmpty() && sessionKey != null && !sessionKey.isEmpty()) {
|
|
636
|
+
if (publicKey != null && !publicKey.isEmpty() && sessionKey != null && !sessionKey.isEmpty()) {
|
|
637
637
|
logger.debug("Decrypting file " + targetFile.getName());
|
|
638
638
|
CryptoCipher.decryptFile(compressedFile, publicKey, sessionKey);
|
|
639
639
|
}
|
|
@@ -60,7 +60,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
60
60
|
CAPPluginMethod(name: "completeFlexibleUpdate", returnType: CAPPluginReturnPromise)
|
|
61
61
|
]
|
|
62
62
|
public var implementation = CapgoUpdater()
|
|
63
|
-
private let pluginVersion: String = "8.41.
|
|
63
|
+
private let pluginVersion: String = "8.41.7"
|
|
64
64
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
65
65
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
66
66
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -387,13 +387,13 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
387
387
|
// The initial report: https://discord.com/channels/912707985829163099/1456985639345061969
|
|
388
388
|
// The bug happens in a very specific scenario. Here is the reproduction steps, followed by the lackof busniess impact
|
|
389
389
|
// Reproduction steps:
|
|
390
|
-
// 1. Install iOS app via app store. Version: 10.13.0. Version v10 of the app uses Capacitor 6 (6.3.13) - a version where the key was still "LatestVersionNative"
|
|
390
|
+
// 1. Install iOS app via app store. Version: 10.13.0. Version v10 of the app uses Capacitor 6 (6.3.13) - a version where the key was still "LatestVersionNative"
|
|
391
391
|
// 2. The plugin writes "10.13.0" to the key "LatestVersionNative"
|
|
392
392
|
// 3. Update the app to version 10.17.0 via Capgo.
|
|
393
393
|
// 4. Update the app via testflight to version 11.0.0. This version uses Capacitor 8 (8.41.3) - a version where the key was changed to "LatestNativeBuildVersion"
|
|
394
394
|
// 5. During the initial load of then new native version, the plugin will read "LatestNativeBuildVersion", not find it, read "LatestVersionNative", find it and revert to builtin version sucessfully.
|
|
395
395
|
// 6. The plugin writes "11.0.0" to the key "LatestNativeBuildVersion"
|
|
396
|
-
// 7. The app is now in a state where it is using the builtin version, but the key "LatestNativeBuildVersion" is still set to "11.0.0" and "LatestVersionNative" is still set to "10.13.0".
|
|
396
|
+
// 7. The app is now in a state where it is using the builtin version, but the key "LatestNativeBuildVersion" is still set to "11.0.0" and "LatestVersionNative" is still set to "10.13.0".
|
|
397
397
|
// 8. The user downgrades using app store back to version 10.13.0.
|
|
398
398
|
// 9. The old plugin reads "LatestVersionNative", finds "10.13.0," so it doesn't revert to builtin version. // <--- THIS IS THE FIRST PART OF THE BUG
|
|
399
399
|
// 10. "LatestVersionNative" is written to "10.13.0" but "LatestNativeBuildVersion" is not touched, and stays at "11.0.0"
|
|
@@ -1597,6 +1597,9 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1597
1597
|
}
|
|
1598
1598
|
|
|
1599
1599
|
@objc func appMovedToBackground() {
|
|
1600
|
+
// Reset timeout flag at start of each background cycle
|
|
1601
|
+
self.autoSplashscreenTimedOut = false
|
|
1602
|
+
|
|
1600
1603
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
1601
1604
|
self.implementation.sendStats(action: "app_moved_to_background", versionName: current.getVersionName())
|
|
1602
1605
|
logger.info("Check for pending update")
|
|
@@ -80,12 +80,20 @@ import UIKit
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
public func setPublicKey(_ publicKey: String) {
|
|
83
|
-
|
|
84
|
-
if
|
|
85
|
-
self.
|
|
86
|
-
} else {
|
|
83
|
+
// Empty string means no encryption - proceed normally
|
|
84
|
+
if publicKey.isEmpty {
|
|
85
|
+
self.publicKey = ""
|
|
87
86
|
self.cachedKeyId = nil
|
|
87
|
+
return
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
// Non-empty: must be a valid RSA key or crash
|
|
91
|
+
guard RSAPublicKey.load(rsaPublicKey: publicKey) != nil else {
|
|
92
|
+
fatalError("Invalid public key in capacitor.config.json: failed to parse RSA key. Remove the key or provide a valid PEM-formatted RSA public key.")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
self.publicKey = publicKey
|
|
96
|
+
self.cachedKeyId = CryptoCipher.calcKeyId(publicKey: publicKey)
|
|
89
97
|
}
|
|
90
98
|
|
|
91
99
|
public func getKeyId() -> String? {
|
|
@@ -1306,7 +1314,7 @@ import UIKit
|
|
|
1306
1314
|
let fileName = url.lastPathComponent
|
|
1307
1315
|
// Only cleanup package_*.tmp and update_*.dat files
|
|
1308
1316
|
let isDownloadTemp = (fileName.hasPrefix("package_") && fileName.hasSuffix(".tmp")) ||
|
|
1309
|
-
|
|
1317
|
+
(fileName.hasPrefix("update_") && fileName.hasSuffix(".dat"))
|
|
1310
1318
|
if !isDownloadTemp {
|
|
1311
1319
|
continue
|
|
1312
1320
|
}
|