@capgo/capacitor-updater 7.0.37 → 7.0.39
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 +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipherV2.java +0 -18
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +23 -9
- package/ios/Plugin/CapacitorUpdater.swift +13 -6
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +3 -3
- package/ios/Plugin/CryptoCipherV2.swift +1 -1
- package/package.json +1 -1
|
@@ -57,7 +57,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
57
57
|
private static final String statsUrlDefault = "https://plugin.capgo.app/stats";
|
|
58
58
|
private static final String channelUrlDefault = "https://plugin.capgo.app/channel_self";
|
|
59
59
|
|
|
60
|
-
private final String PLUGIN_VERSION = "7.0.
|
|
60
|
+
private final String PLUGIN_VERSION = "7.0.39";
|
|
61
61
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
62
62
|
|
|
63
63
|
private SharedPreferences.Editor editor;
|
|
@@ -192,24 +192,6 @@ public class CryptoCipherV2 {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
public static String decryptChecksum(String checksum, String publicKey, String version) throws IOException {
|
|
196
|
-
if (publicKey.isEmpty()) {
|
|
197
|
-
Log.e(CapacitorUpdater.TAG, "The public key is empty");
|
|
198
|
-
return checksum;
|
|
199
|
-
}
|
|
200
|
-
try {
|
|
201
|
-
byte[] checksumBytes = Base64.decode(checksum, Base64.DEFAULT);
|
|
202
|
-
PublicKey pKey = CryptoCipherV2.stringToPublicKey(publicKey);
|
|
203
|
-
byte[] decryptedChecksum = CryptoCipherV2.decryptRSA(checksumBytes, pKey);
|
|
204
|
-
// return Base64.encodeToString(decryptedChecksum, Base64.DEFAULT);
|
|
205
|
-
String result = Base64.encodeToString(decryptedChecksum, Base64.DEFAULT);
|
|
206
|
-
return result.replaceAll("\\s", ""); // Remove all whitespace, including newlines
|
|
207
|
-
} catch (GeneralSecurityException e) {
|
|
208
|
-
Log.e(CapacitorUpdater.TAG, "decryptChecksum fail: " + e.getMessage());
|
|
209
|
-
throw new IOException("Decryption failed: " + e.getMessage());
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
195
|
public static String calcChecksum(File file) {
|
|
214
196
|
final int BUFFER_SIZE = 1024 * 1024 * 5; // 5 MB buffer size
|
|
215
197
|
MessageDigest digest;
|
|
@@ -167,7 +167,7 @@ public class DownloadService extends Worker {
|
|
|
167
167
|
try {
|
|
168
168
|
fileHash = CryptoCipherV2.decryptChecksum(fileHash, publicKey);
|
|
169
169
|
} catch (Exception e) {
|
|
170
|
-
Log.e(TAG, "Error decrypting checksum for " + fileName
|
|
170
|
+
Log.e(TAG, "Error decrypting checksum for " + fileName + "fileHash: " + fileHash);
|
|
171
171
|
hasError.set(true);
|
|
172
172
|
continue;
|
|
173
173
|
}
|
|
@@ -377,8 +377,16 @@ public class DownloadService extends Worker {
|
|
|
377
377
|
|
|
378
378
|
Request request = new Request.Builder().url(downloadUrl).build();
|
|
379
379
|
|
|
380
|
+
// Check if file is a Brotli file
|
|
381
|
+
boolean isBrotli = targetFile.getName().endsWith(".br");
|
|
382
|
+
|
|
383
|
+
// Create final target file with .br extension removed if it's a Brotli file
|
|
384
|
+
File finalTargetFile = isBrotli
|
|
385
|
+
? new File(targetFile.getParentFile(), targetFile.getName().substring(0, targetFile.getName().length() - 3))
|
|
386
|
+
: targetFile;
|
|
387
|
+
|
|
380
388
|
// Create a temporary file for the compressed data
|
|
381
|
-
File compressedFile = new File(getApplicationContext().getCacheDir(), "temp_" + targetFile.getName() + ".
|
|
389
|
+
File compressedFile = new File(getApplicationContext().getCacheDir(), "temp_" + targetFile.getName() + ".tmp");
|
|
382
390
|
|
|
383
391
|
try (Response response = client.newCall(request).execute()) {
|
|
384
392
|
if (!response.isSuccessful()) {
|
|
@@ -405,21 +413,27 @@ public class DownloadService extends Worker {
|
|
|
405
413
|
CryptoCipherV2.decryptFile(compressedFile, publicKey, sessionKey);
|
|
406
414
|
}
|
|
407
415
|
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
416
|
+
// Only decompress if file has .br extension
|
|
417
|
+
if (isBrotli) {
|
|
418
|
+
// Use new decompression method
|
|
419
|
+
byte[] compressedData = Files.readAllBytes(compressedFile.toPath());
|
|
420
|
+
byte[] decompressedData = decompressBrotli(compressedData, targetFile.getName());
|
|
421
|
+
Files.write(finalTargetFile.toPath(), decompressedData);
|
|
422
|
+
} else {
|
|
423
|
+
// Just copy the file without decompression
|
|
424
|
+
Files.copy(compressedFile.toPath(), finalTargetFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
|
425
|
+
}
|
|
412
426
|
|
|
413
427
|
// Delete the compressed file
|
|
414
428
|
compressedFile.delete();
|
|
415
|
-
String calculatedHash = CryptoCipherV2.calcChecksum(
|
|
429
|
+
String calculatedHash = CryptoCipherV2.calcChecksum(finalTargetFile);
|
|
416
430
|
|
|
417
431
|
// Verify checksum
|
|
418
432
|
if (calculatedHash.equals(expectedHash)) {
|
|
419
433
|
// Only cache if checksum is correct
|
|
420
|
-
copyFile(
|
|
434
|
+
copyFile(finalTargetFile, cacheFile);
|
|
421
435
|
} else {
|
|
422
|
-
|
|
436
|
+
finalTargetFile.delete();
|
|
423
437
|
throw new IOException(
|
|
424
438
|
"Checksum verification failed for: " +
|
|
425
439
|
downloadUrl +
|
|
@@ -340,7 +340,7 @@ import UIKit
|
|
|
340
340
|
|
|
341
341
|
if !self.publicKey.isEmpty && !sessionKey.isEmpty {
|
|
342
342
|
do {
|
|
343
|
-
fileHash = try CryptoCipherV2.decryptChecksum(checksum: fileHash, publicKey: self.publicKey
|
|
343
|
+
fileHash = try CryptoCipherV2.decryptChecksum(checksum: fileHash, publicKey: self.publicKey)
|
|
344
344
|
} catch {
|
|
345
345
|
downloadError = error
|
|
346
346
|
print("\(CapacitorUpdater.TAG) CryptoCipherV2.decryptChecksum error \(id) \(fileName) error: \(error)")
|
|
@@ -403,11 +403,18 @@ import UIKit
|
|
|
403
403
|
try FileManager.default.removeItem(at: tempFile)
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
-
//
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
// Check if file has .br extension for Brotli decompression
|
|
407
|
+
let isBrotli = fileName.hasSuffix(".br")
|
|
408
|
+
let finalFileName = isBrotli ? String(fileName.dropLast(3)) : fileName
|
|
409
|
+
let destFilePath = destFolder.appendingPathComponent(finalFileName)
|
|
410
|
+
|
|
411
|
+
if isBrotli {
|
|
412
|
+
// Decompress the Brotli data
|
|
413
|
+
guard let decompressedData = self.decompressBrotli(data: finalData, fileName: fileName) else {
|
|
414
|
+
throw NSError(domain: "BrotliDecompressionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decompress Brotli data for file \(fileName) at url \(downloadUrl)"])
|
|
415
|
+
}
|
|
416
|
+
finalData = decompressedData
|
|
409
417
|
}
|
|
410
|
-
finalData = decompressedData
|
|
411
418
|
|
|
412
419
|
try finalData.write(to: destFilePath)
|
|
413
420
|
if !self.publicKey.isEmpty && !sessionKey.isEmpty {
|
|
@@ -423,7 +430,7 @@ import UIKit
|
|
|
423
430
|
|
|
424
431
|
completedFiles += 1
|
|
425
432
|
self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
|
|
426
|
-
print("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) downloaded, decompressed\(!self.publicKey.isEmpty && !sessionKey.isEmpty ? ", decrypted" : ""), and cached")
|
|
433
|
+
print("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) downloaded\(isBrotli ? ", decompressed" : "")\(!self.publicKey.isEmpty && !sessionKey.isEmpty ? ", decrypted" : ""), and cached")
|
|
427
434
|
} catch {
|
|
428
435
|
downloadError = error
|
|
429
436
|
NSLog("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) error: \(error.localizedDescription)")
|
|
@@ -45,7 +45,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
45
45
|
CAPPluginMethod(name: "getNextBundle", returnType: CAPPluginReturnPromise)
|
|
46
46
|
]
|
|
47
47
|
public var implementation = CapacitorUpdater()
|
|
48
|
-
private let PLUGIN_VERSION: String = "7.0.
|
|
48
|
+
private let PLUGIN_VERSION: String = "7.0.39"
|
|
49
49
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
50
50
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
51
51
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -291,7 +291,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
291
291
|
DispatchQueue.global(qos: .background).async {
|
|
292
292
|
do {
|
|
293
293
|
let next = try self.implementation.download(url: url!, version: version, sessionKey: sessionKey)
|
|
294
|
-
checksum = try CryptoCipherV2.decryptChecksum(checksum: checksum, publicKey: self.implementation.publicKey
|
|
294
|
+
checksum = try CryptoCipherV2.decryptChecksum(checksum: checksum, publicKey: self.implementation.publicKey)
|
|
295
295
|
if (checksum != "" || self.implementation.publicKey != "") && next.getChecksum() != checksum {
|
|
296
296
|
print("\(CapacitorUpdater.TAG) Error checksum", next.getChecksum(), checksum)
|
|
297
297
|
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
@@ -805,7 +805,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
805
805
|
self.endBackGroundTaskWithNotif(msg: "Latest version is in error state. Aborting update.", latestVersionName: latestVersionName, current: current)
|
|
806
806
|
return
|
|
807
807
|
}
|
|
808
|
-
res.checksum = try CryptoCipherV2.decryptChecksum(checksum: res.checksum, publicKey: self.implementation.publicKey
|
|
808
|
+
res.checksum = try CryptoCipherV2.decryptChecksum(checksum: res.checksum, publicKey: self.implementation.publicKey)
|
|
809
809
|
if res.checksum != "" && next.getChecksum() != res.checksum && res.manifest == nil {
|
|
810
810
|
print("\(CapacitorUpdater.TAG) Error checksum", next.getChecksum(), res.checksum)
|
|
811
811
|
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
@@ -10,7 +10,7 @@ import BigInt
|
|
|
10
10
|
|
|
11
11
|
public struct CryptoCipherV2 {
|
|
12
12
|
|
|
13
|
-
public static func decryptChecksum(checksum: String, publicKey: String
|
|
13
|
+
public static func decryptChecksum(checksum: String, publicKey: String) throws -> String {
|
|
14
14
|
if publicKey.isEmpty {
|
|
15
15
|
print("\(CapacitorUpdater.TAG) The public key is empty")
|
|
16
16
|
return checksum
|