@capgo/capacitor-updater 6.11.1 → 6.12.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.
@@ -5,262 +5,19 @@
5
5
  */
6
6
 
7
7
  import Foundation
8
+ #if canImport(ZipArchive)
9
+ import ZipArchive
10
+ #else
8
11
  import SSZipArchive
12
+ #endif
9
13
  import Alamofire
10
- import zlib
11
- import CryptoKit
12
14
  import Compression
13
15
 
14
- extension Collection {
15
- subscript(safe index: Index) -> Element? {
16
- return indices.contains(index) ? self[index] : nil
17
- }
18
- }
19
- extension URL {
20
- var isDirectory: Bool {
21
- (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true
22
- }
23
- var exist: Bool {
24
- return FileManager().fileExists(atPath: self.path)
25
- }
26
- }
27
- struct SetChannelDec: Decodable {
28
- let status: String?
29
- let error: String?
30
- let message: String?
31
- }
32
- public class SetChannel: NSObject {
33
- var status: String = ""
34
- var error: String = ""
35
- var message: String = ""
36
- }
37
- extension SetChannel {
38
- func toDict() -> [String: Any] {
39
- var dict: [String: Any] = [String: Any]()
40
- let otherSelf: Mirror = Mirror(reflecting: self)
41
- for child: Mirror.Child in otherSelf.children {
42
- if let key: String = child.label {
43
- dict[key] = child.value
44
- }
45
- }
46
- return dict
47
- }
48
- }
49
- struct GetChannelDec: Decodable {
50
- let channel: String?
51
- let status: String?
52
- let error: String?
53
- let message: String?
54
- let allowSet: Bool?
55
- }
56
- public class GetChannel: NSObject {
57
- var channel: String = ""
58
- var status: String = ""
59
- var error: String = ""
60
- var message: String = ""
61
- var allowSet: Bool = true
62
- }
63
- extension GetChannel {
64
- func toDict() -> [String: Any] {
65
- var dict: [String: Any] = [String: Any]()
66
- let otherSelf: Mirror = Mirror(reflecting: self)
67
- for child: Mirror.Child in otherSelf.children {
68
- if let key: String = child.label {
69
- dict[key] = child.value
70
- }
71
- }
72
- return dict
73
- }
74
- }
75
- struct InfoObject: Codable {
76
- let platform: String?
77
- let device_id: String?
78
- let app_id: String?
79
- let custom_id: String?
80
- let version_build: String?
81
- let version_code: String?
82
- let version_os: String?
83
- var version_name: String?
84
- var old_version_name: String?
85
- let plugin_version: String?
86
- let is_emulator: Bool?
87
- let is_prod: Bool?
88
- var action: String?
89
- var channel: String?
90
- var defaultChannel: String?
91
- }
92
-
93
- public struct ManifestEntry: Codable {
94
- let file_name: String?
95
- let file_hash: String?
96
- let download_url: String?
97
- }
98
-
99
- extension ManifestEntry {
100
- func toDict() -> [String: Any] {
101
- var dict: [String: Any] = [String: Any]()
102
- let mirror = Mirror(reflecting: self)
103
- for child in mirror.children {
104
- if let key = child.label {
105
- dict[key] = child.value
106
- }
107
- }
108
- return dict
109
- }
110
- }
111
-
112
- struct AppVersionDec: Decodable {
113
- let version: String?
114
- let checksum: String?
115
- let url: String?
116
- let message: String?
117
- let error: String?
118
- let session_key: String?
119
- let major: Bool?
120
- let data: [String: String]?
121
- let manifest: [ManifestEntry]?
122
- }
123
-
124
- public class AppVersion: NSObject {
125
- var version: String = ""
126
- var checksum: String = ""
127
- var url: String = ""
128
- var message: String?
129
- var error: String?
130
- var sessionKey: String?
131
- var major: Bool?
132
- var data: [String: String]?
133
- var manifest: [ManifestEntry]?
134
- }
135
-
136
- extension AppVersion {
137
- func toDict() -> [String: Any] {
138
- var dict: [String: Any] = [String: Any]()
139
- let otherSelf: Mirror = Mirror(reflecting: self)
140
- for child: Mirror.Child in otherSelf.children {
141
- if let key: String = child.label {
142
- if key == "manifest", let manifestEntries = child.value as? [ManifestEntry] {
143
- dict[key] = manifestEntries.map { $0.toDict() }
144
- } else {
145
- dict[key] = child.value
146
- }
147
- }
148
- }
149
- return dict
150
- }
151
- }
152
-
153
- extension OperatingSystemVersion {
154
- func getFullVersion(separator: String = ".") -> String {
155
- return "\(majorVersion)\(separator)\(minorVersion)\(separator)\(patchVersion)"
156
- }
157
- }
158
- extension Bundle {
159
- var versionName: String? {
160
- return infoDictionary?["CFBundleShortVersionString"] as? String
161
- }
162
- var versionCode: String? {
163
- return infoDictionary?["CFBundleVersion"] as? String
164
- }
165
- }
166
-
167
- extension ISO8601DateFormatter {
168
- convenience init(_ formatOptions: Options) {
169
- self.init()
170
- self.formatOptions = formatOptions
171
- }
172
- }
173
- extension Formatter {
174
- static let iso8601withFractionalSeconds: ISO8601DateFormatter = ISO8601DateFormatter([.withInternetDateTime, .withFractionalSeconds])
175
- }
176
- extension Date {
177
- var iso8601withFractionalSeconds: String { return Formatter.iso8601withFractionalSeconds.string(from: self) }
178
- }
179
- extension String {
180
-
181
- var fileURL: URL {
182
- return URL(fileURLWithPath: self)
183
- }
184
-
185
- var lastPathComponent: String {
186
- get {
187
- return fileURL.lastPathComponent
188
- }
189
- }
190
- var iso8601withFractionalSeconds: Date? {
191
- return Formatter.iso8601withFractionalSeconds.date(from: self)
192
- }
193
- func trim(using characterSet: CharacterSet = .whitespacesAndNewlines) -> String {
194
- return trimmingCharacters(in: characterSet)
195
- }
196
- }
197
-
198
- enum CustomError: Error {
199
- // Throw when an unzip fail
200
- case cannotUnzip
201
- case cannotWrite
202
- case cannotDecode
203
- case cannotUnflat
204
- case cannotCreateDirectory
205
- case cannotDeleteDirectory
206
- case cannotDecryptSessionKey
207
- case invalidBase64
208
-
209
- // Throw in all other cases
210
- case unexpected(code: Int)
211
- }
212
-
213
- extension CustomError: LocalizedError {
214
- public var errorDescription: String? {
215
- switch self {
216
- case .cannotUnzip:
217
- return NSLocalizedString(
218
- "The file cannot be unzip",
219
- comment: "Invalid zip"
220
- )
221
- case .cannotCreateDirectory:
222
- return NSLocalizedString(
223
- "The folder cannot be created",
224
- comment: "Invalid folder"
225
- )
226
- case .cannotDeleteDirectory:
227
- return NSLocalizedString(
228
- "The folder cannot be deleted",
229
- comment: "Invalid folder"
230
- )
231
- case .cannotUnflat:
232
- return NSLocalizedString(
233
- "The file cannot be unflat",
234
- comment: "Invalid folder"
235
- )
236
- case .unexpected:
237
- return NSLocalizedString(
238
- "An unexpected error occurred.",
239
- comment: "Unexpected Error"
240
- )
241
- case .cannotDecode:
242
- return NSLocalizedString(
243
- "Decoding the zip failed with this key",
244
- comment: "Invalid public key"
245
- )
246
- case .cannotWrite:
247
- return NSLocalizedString(
248
- "Cannot write to the destination",
249
- comment: "Invalid destination"
250
- )
251
- case .cannotDecryptSessionKey:
252
- return NSLocalizedString(
253
- "Decrypting the session key failed",
254
- comment: "Invalid session key"
255
- )
256
- case .invalidBase64:
257
- return NSLocalizedString(
258
- "Decrypting the base64 failed",
259
- comment: "Invalid checksum key"
260
- )
261
- }
262
- }
263
- }
16
+ #if canImport(ZipArchive)
17
+ typealias ZipArchiveHelper = ZipArchive
18
+ #else
19
+ typealias ZipArchiveHelper = SSZipArchive
20
+ #endif
264
21
 
265
22
  @objc public class CapacitorUpdater: NSObject {
266
23
 
@@ -277,7 +34,7 @@ extension CustomError: LocalizedError {
277
34
  // Add this line to declare cacheFolder
278
35
  private let cacheFolder: URL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("capgo_downloads")
279
36
 
280
- public let TAG: String = "✨ Capacitor-updater:"
37
+ static public let TAG: String = "✨ Capacitor-updater:"
281
38
  public let CAP_SERVER_PATH: String = "serverBasePath"
282
39
  public var versionBuild: String = ""
283
40
  public var customId: String = ""
@@ -358,7 +115,7 @@ extension CustomError: LocalizedError {
358
115
  do {
359
116
  try FileManager.default.createDirectory(atPath: source.path, withIntermediateDirectories: true, attributes: nil)
360
117
  } catch {
361
- print("\(self.TAG) Cannot createDirectory \(source.path)")
118
+ print("\(CapacitorUpdater.TAG) Cannot createDirectory \(source.path)")
362
119
  throw CustomError.cannotCreateDirectory
363
120
  }
364
121
  }
@@ -368,7 +125,7 @@ extension CustomError: LocalizedError {
368
125
  do {
369
126
  try FileManager.default.removeItem(atPath: source.path)
370
127
  } catch {
371
- print("\(self.TAG) File not removed. \(source.path)")
128
+ print("\(CapacitorUpdater.TAG) File not removed. \(source.path)")
372
129
  throw CustomError.cannotDeleteDirectory
373
130
  }
374
131
  }
@@ -385,105 +142,14 @@ extension CustomError: LocalizedError {
385
142
  return false
386
143
  }
387
144
  } catch {
388
- print("\(self.TAG) File not moved. source: \(source.path) dest: \(dest.path)")
145
+ print("\(CapacitorUpdater.TAG) File not moved. source: \(source.path) dest: \(dest.path)")
389
146
  throw CustomError.cannotUnflat
390
147
  }
391
148
  }
392
149
 
393
- private func decryptFileV2(filePath: URL, sessionKey: String, version: String) throws {
394
- if self.publicKey.isEmpty || sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
395
- print("\(self.TAG) Cannot find public key or sessionKey")
396
- return
397
- }
398
- do {
399
- guard let rsaPublicKey: RSAPublicKey = .load(rsaPublicKey: self.publicKey) else {
400
- print("cannot decode publicKey", self.publicKey)
401
- throw CustomError.cannotDecode
402
- }
403
-
404
- let sessionKeyArray: [String] = sessionKey.components(separatedBy: ":")
405
- guard let ivData: Data = Data(base64Encoded: sessionKeyArray[0]) else {
406
- print("cannot decode sessionKey", sessionKey)
407
- throw CustomError.cannotDecode
408
- }
409
-
410
- guard let sessionKeyDataEncrypted = Data(base64Encoded: sessionKeyArray[1]) else {
411
- throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
412
- }
413
-
414
- guard let sessionKeyDataDecrypted = rsaPublicKey.decrypt(data: sessionKeyDataEncrypted) else {
415
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
416
- }
417
-
418
- let aesPrivateKey = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted)
419
-
420
- guard let encryptedData = try? Data(contentsOf: filePath) else {
421
- throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
422
- }
423
-
424
- guard let decryptedData = aesPrivateKey.decrypt(data: encryptedData) else {
425
- throw NSError(domain: "Failed to decrypt data", code: 4, userInfo: nil)
426
- }
427
-
428
- try decryptedData.write(to: filePath)
429
-
430
- } catch {
431
- print("\(self.TAG) Cannot decode: \(filePath.path)", error)
432
- self.sendStats(action: "decrypt_fail", versionName: version)
433
- throw CustomError.cannotDecode
434
- }
435
- }
436
-
437
- private func decryptFile(filePath: URL, sessionKey: String, version: String) throws {
438
- if self.privateKey.isEmpty {
439
- print("\(self.TAG) Cannot found privateKey")
440
- return
441
- } else if sessionKey.isEmpty || sessionKey.components(separatedBy: ":").count != 2 {
442
- print("\(self.TAG) Cannot found sessionKey")
443
- return
444
- }
445
- do {
446
- guard let rsaPrivateKey: RSAPrivateKey = .load(rsaPrivateKey: self.privateKey) else {
447
- print("cannot decode privateKey", self.privateKey)
448
- throw CustomError.cannotDecode
449
- }
450
-
451
- let sessionKeyArray: [String] = sessionKey.components(separatedBy: ":")
452
- guard let ivData: Data = Data(base64Encoded: sessionKeyArray[0]) else {
453
- print("cannot decode sessionKey", sessionKey)
454
- throw CustomError.cannotDecode
455
- }
456
-
457
- guard let sessionKeyDataEncrypted = Data(base64Encoded: sessionKeyArray[1]) else {
458
- throw NSError(domain: "Invalid session key data", code: 1, userInfo: nil)
459
- }
460
-
461
- guard let sessionKeyDataDecrypted = rsaPrivateKey.decrypt(data: sessionKeyDataEncrypted) else {
462
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
463
- }
464
-
465
- let aesPrivateKey = AES128Key(iv: ivData, aes128Key: sessionKeyDataDecrypted)
466
-
467
- guard let encryptedData = try? Data(contentsOf: filePath) else {
468
- throw NSError(domain: "Failed to read encrypted data", code: 3, userInfo: nil)
469
- }
470
-
471
- guard let decryptedData = aesPrivateKey.decrypt(data: encryptedData) else {
472
- throw NSError(domain: "Failed to decrypt data", code: 4, userInfo: nil)
473
- }
474
-
475
- try decryptedData.write(to: filePath)
476
-
477
- } catch {
478
- print("\(self.TAG) Cannot decode: \(filePath.path)", error)
479
- self.sendStats(action: "decrypt_fail", versionName: version)
480
- throw CustomError.cannotDecode
481
- }
482
- }
483
-
484
150
  private func unzipProgressHandler(entry: String, zipInfo: unz_file_info, entryNumber: Int, total: Int, destUnZip: URL, id: String, unzipError: inout NSError?) {
485
151
  if entry.contains("\\") {
486
- print("\(self.TAG) unzip: Windows path is not supported, please use unix path as required by zip RFC: \(entry)")
152
+ print("\(CapacitorUpdater.TAG) unzip: Windows path is not supported, please use unix path as required by zip RFC: \(entry)")
487
153
  self.sendStats(action: "windows_path_fail")
488
154
  }
489
155
 
@@ -527,7 +193,7 @@ extension CustomError: LocalizedError {
527
193
  let semaphore = DispatchSemaphore(value: 0)
528
194
  var unzipError: NSError?
529
195
 
530
- let success = SSZipArchive.unzipFile(atPath: sourceZip.path,
196
+ let success = ZipArchiveHelper.unzipFile(atPath: sourceZip.path,
531
197
  toDestination: destUnZip.path,
532
198
  preserveAttributes: true,
533
199
  overwrite: true,
@@ -586,7 +252,7 @@ extension CustomError: LocalizedError {
586
252
  if let channel = channel {
587
253
  parameters.defaultChannel = channel
588
254
  }
589
- print("\(self.TAG) Auto-update parameters: \(parameters)")
255
+ print("\(CapacitorUpdater.TAG) Auto-update parameters: \(parameters)")
590
256
  let request = AF.request(url, method: .post, parameters: parameters, encoder: JSONParameterEncoder.default, requestModifier: { $0.timeoutInterval = self.timeout })
591
257
 
592
258
  request.validate().responseDecodable(of: AppVersionDec.self) { response in
@@ -620,7 +286,7 @@ extension CustomError: LocalizedError {
620
286
  latest.manifest = manifest
621
287
  }
622
288
  case let .failure(error):
623
- print("\(self.TAG) Error getting Latest", response.value ?? "", error )
289
+ print("\(CapacitorUpdater.TAG) Error getting Latest", response.value ?? "", error )
624
290
  latest.message = "Error getting Latest \(String(describing: response.value))"
625
291
  latest.error = "response_error"
626
292
  }
@@ -633,63 +299,7 @@ extension CustomError: LocalizedError {
633
299
  private func setCurrentBundle(bundle: String) {
634
300
  UserDefaults.standard.set(bundle, forKey: self.CAP_SERVER_PATH)
635
301
  UserDefaults.standard.synchronize()
636
- print("\(self.TAG) Current bundle set to: \((bundle ).isEmpty ? BundleInfo.ID_BUILTIN : bundle)")
637
- }
638
- private func calcChecksum(filePath: URL) -> String {
639
- let bufferSize = 1024 * 1024 * 5 // 5 MB
640
- var checksum = uLong(0)
641
-
642
- do {
643
- let fileHandle = try FileHandle(forReadingFrom: filePath)
644
- defer {
645
- fileHandle.closeFile()
646
- }
647
-
648
- while autoreleasepool(invoking: {
649
- let fileData = fileHandle.readData(ofLength: bufferSize)
650
- if fileData.count > 0 {
651
- checksum = fileData.withUnsafeBytes {
652
- crc32(checksum, $0.bindMemory(to: Bytef.self).baseAddress, uInt(fileData.count))
653
- }
654
- return true // Continue
655
- } else {
656
- return false // End of file
657
- }
658
- }) {}
659
-
660
- return String(format: "%08X", checksum).lowercased()
661
- } catch {
662
- print("\(self.TAG) Cannot get checksum: \(filePath.path)", error)
663
- return ""
664
- }
665
- }
666
-
667
- private func calcChecksumV2(filePath: URL) -> String {
668
- let bufferSize = 1024 * 1024 * 5 // 5 MB
669
- var sha256 = SHA256()
670
-
671
- do {
672
- let fileHandle = try FileHandle(forReadingFrom: filePath)
673
- defer {
674
- fileHandle.closeFile()
675
- }
676
-
677
- while autoreleasepool(invoking: {
678
- let fileData = fileHandle.readData(ofLength: bufferSize)
679
- if fileData.count > 0 {
680
- sha256.update(data: fileData)
681
- return true // Continue
682
- } else {
683
- return false // End of file
684
- }
685
- }) {}
686
-
687
- let digest = sha256.finalize()
688
- return digest.compactMap { String(format: "%02x", $0) }.joined()
689
- } catch {
690
- print("\(self.TAG) Cannot get checksum: \(filePath.path)", error)
691
- return ""
692
- }
302
+ print("\(CapacitorUpdater.TAG) Current bundle set to: \((bundle ).isEmpty ? BundleInfo.ID_BUILTIN : bundle)")
693
303
  }
694
304
 
695
305
  private var tempDataPath: URL {
@@ -701,35 +311,14 @@ extension CustomError: LocalizedError {
701
311
  }
702
312
  private var tempData = Data()
703
313
 
704
- public func decryptChecksum(checksum: String, version: String) throws -> String {
705
- if self.publicKey.isEmpty {
706
- return checksum
707
- }
708
- do {
709
- let checksumBytes: Data = Data(base64Encoded: checksum)!
710
- guard let rsaPublicKey: RSAPublicKey = .load(rsaPublicKey: self.publicKey) else {
711
- print("cannot decode publicKey", self.publicKey)
712
- throw CustomError.cannotDecode
713
- }
714
- guard let decryptedChecksum = try? rsaPublicKey.decrypt(data: checksumBytes) else {
715
- throw NSError(domain: "Failed to decrypt session key data", code: 2, userInfo: nil)
716
- }
717
- return decryptedChecksum.base64EncodedString()
718
- } catch {
719
- print("\(self.TAG) Cannot decrypt checksum: \(checksum)", error)
720
- self.sendStats(action: "decrypt_fail", versionName: version)
721
- throw CustomError.cannotDecode
722
- }
723
- }
724
-
725
314
  private func verifyChecksum(file: URL, expectedHash: String) -> Bool {
726
- let actualHash = calcChecksumV2(filePath: file)
315
+ let actualHash = CryptoCipherV2.calcChecksum(filePath: file)
727
316
  return actualHash == expectedHash
728
317
  }
729
318
 
730
319
  public func downloadManifest(manifest: [ManifestEntry], version: String, sessionKey: String) throws -> BundleInfo {
731
320
  let id = self.randomString(length: 10)
732
- print("\(self.TAG) downloadManifest start \(id)")
321
+ print("\(CapacitorUpdater.TAG) downloadManifest start \(id)")
733
322
  let destFolder = self.getBundleDirectory(id: id)
734
323
  let builtinFolder = Bundle.main.bundleURL.appendingPathComponent("public")
735
324
 
@@ -751,10 +340,19 @@ extension CustomError: LocalizedError {
751
340
 
752
341
  for entry in manifest {
753
342
  guard let fileName = entry.file_name,
754
- let fileHash = entry.file_hash,
343
+ var fileHash = entry.file_hash,
755
344
  let downloadUrl = entry.download_url else {
756
345
  continue
757
346
  }
347
+
348
+ if (!self.hasOldPrivateKeyPropertyInConfig && !self.publicKey.isEmpty && !sessionKey.isEmpty) {
349
+ do {
350
+ fileHash = try CryptoCipherV2.decryptChecksum(checksum: fileHash, publicKey: self.publicKey, version: version)
351
+ } catch {
352
+ downloadError = error
353
+ print("\(CapacitorUpdater.TAG) CryptoCipherV2.decryptChecksum error \(id) \(fileName) error: \(error)")
354
+ }
355
+ }
758
356
 
759
357
  let fileNameWithoutPath = (fileName as NSString).lastPathComponent
760
358
  let cacheFileName = "\(fileHash)_\(fileNameWithoutPath)"
@@ -769,13 +367,13 @@ extension CustomError: LocalizedError {
769
367
 
770
368
  if FileManager.default.fileExists(atPath: builtinFilePath.path) && verifyChecksum(file: builtinFilePath, expectedHash: fileHash) {
771
369
  try FileManager.default.copyItem(at: builtinFilePath, to: destFilePath)
772
- print("\(self.TAG) downloadManifest \(fileName) using builtin file \(id)")
370
+ print("\(CapacitorUpdater.TAG) downloadManifest \(fileName) using builtin file \(id)")
773
371
  completedFiles += 1
774
372
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
775
373
  dispatchGroup.leave()
776
374
  } else if FileManager.default.fileExists(atPath: cacheFilePath.path) && verifyChecksum(file: cacheFilePath, expectedHash: fileHash) {
777
375
  try FileManager.default.copyItem(at: cacheFilePath, to: destFilePath)
778
- print("\(self.TAG) downloadManifest \(fileName) copy from cache \(id)")
376
+ print("\(CapacitorUpdater.TAG) downloadManifest \(fileName) copy from cache \(id)")
779
377
  completedFiles += 1
780
378
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
781
379
  dispatchGroup.leave()
@@ -787,25 +385,51 @@ extension CustomError: LocalizedError {
787
385
  switch response.result {
788
386
  case .success(let data):
789
387
  do {
388
+ // Add decryption step if public key is set and sessionKey is provided
389
+ var finalData = data
390
+ if !self.publicKey.isEmpty && !sessionKey.isEmpty {
391
+ let tempFile = self.cacheFolder.appendingPathComponent("temp_\(UUID().uuidString)")
392
+ try finalData.write(to: tempFile)
393
+ do {
394
+ try CryptoCipherV2.decryptFile(filePath: tempFile, publicKey: self.publicKey, sessionKey: sessionKey, version: version)
395
+ } catch {
396
+ self.sendStats(action: "decrypt_fail", versionName: version)
397
+ throw error
398
+ }
399
+ // TODO: try and do self.sendStats(action: "decrypt_fail", versionName: version) if fail
400
+ finalData = try Data(contentsOf: tempFile)
401
+ try FileManager.default.removeItem(at: tempFile)
402
+ }
403
+
790
404
  // Decompress the Brotli data
791
- guard let decompressedData = self.decompressBrotli(data: data) else {
405
+ guard let decompressedData = self.decompressBrotli(data: finalData) else {
792
406
  throw NSError(domain: "BrotliDecompressionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decompress Brotli data"])
793
407
  }
794
- // Save decompressed data to cache
795
- try decompressedData.write(to: cacheFilePath)
796
- // Save decompressed data to destination
797
- try decompressedData.write(to: destFilePath)
408
+ finalData = decompressedData
409
+
410
+ try finalData.write(to: destFilePath)
411
+ if (!self.hasOldPrivateKeyPropertyInConfig && !self.publicKey.isEmpty && !sessionKey.isEmpty) {
412
+ // assume that calcChecksum != null
413
+ let calculatedChecksum = CryptoCipherV2.calcChecksum(filePath: destFilePath)
414
+ if (calculatedChecksum != fileHash) {
415
+ throw NSError(domain: "ChecksumError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Computed checksum is not equal to required checksum (\(calculatedChecksum) != \(fileHash))"])
416
+ }
417
+ }
418
+
419
+ // Save decrypted data to cache and destination
420
+ try finalData.write(to: cacheFilePath)
421
+
798
422
 
799
423
  completedFiles += 1
800
424
  self.notifyDownload(id: id, percent: self.calcTotalPercent(percent: Int((Double(completedFiles) / Double(totalFiles)) * 100), min: 10, max: 70))
801
- print("\(self.TAG) downloadManifest \(id) \(fileName) downloaded, decompressed, and cached")
425
+ print("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) downloaded, decompressed, decrypted, and cached")
802
426
  } catch {
803
427
  downloadError = error
804
- print("\(self.TAG) downloadManifest \(id) \(fileName) error: \(error)")
428
+ print("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) error: \(error)")
805
429
  }
806
430
  case .failure(let error):
807
431
  downloadError = error
808
- print("\(self.TAG) downloadManifest \(id) \(fileName) download error: \(error)")
432
+ print("\(CapacitorUpdater.TAG) downloadManifest \(id) \(fileName) download error: \(error)")
809
433
  }
810
434
  }
811
435
  }
@@ -824,7 +448,7 @@ extension CustomError: LocalizedError {
824
448
  let updatedBundle = bundleInfo.setStatus(status: BundleStatus.PENDING.localizedString)
825
449
  self.saveBundleInfo(id: id, bundle: updatedBundle)
826
450
 
827
- print("\(self.TAG) downloadManifest done \(id)")
451
+ print("\(CapacitorUpdater.TAG) downloadManifest done \(id)")
828
452
  return updatedBundle
829
453
  }
830
454
 
@@ -836,7 +460,7 @@ extension CustomError: LocalizedError {
836
460
  let streamPointer = UnsafeMutablePointer<compression_stream>.allocate(capacity: 1)
837
461
  var status = compression_stream_init(streamPointer, COMPRESSION_STREAM_DECODE, COMPRESSION_BROTLI)
838
462
  guard status != COMPRESSION_STATUS_ERROR else {
839
- print("\(self.TAG) Unable to initialize the decompression stream.")
463
+ print("\(CapacitorUpdater.TAG) Unable to initialize the decompression stream.")
840
464
  return nil
841
465
  }
842
466
 
@@ -858,7 +482,7 @@ extension CustomError: LocalizedError {
858
482
  if let baseAddress = rawBufferPointer.baseAddress {
859
483
  streamPointer.pointee.src_ptr = baseAddress.assumingMemoryBound(to: UInt8.self)
860
484
  } else {
861
- print("\(self.TAG) Error: Unable to get base address of input data")
485
+ print("\(CapacitorUpdater.TAG) Error: Unable to get base address of input data")
862
486
  status = COMPRESSION_STATUS_ERROR
863
487
  return
864
488
  }
@@ -879,7 +503,7 @@ extension CustomError: LocalizedError {
879
503
  if status == COMPRESSION_STATUS_END {
880
504
  break
881
505
  } else if status == COMPRESSION_STATUS_ERROR {
882
- print("\(self.TAG) Error during Brotli decompression")
506
+ print("\(CapacitorUpdater.TAG) Error during Brotli decompression")
883
507
  return nil
884
508
  }
885
509
 
@@ -917,7 +541,7 @@ extension CustomError: LocalizedError {
917
541
  let monitor = ClosureEventMonitor()
918
542
  monitor.requestDidCompleteTaskWithError = { (_, _, error) in
919
543
  if error != nil {
920
- print("\(self.TAG) Downloading failed - ClosureEventMonitor activated")
544
+ print("\(CapacitorUpdater.TAG) Downloading failed - ClosureEventMonitor activated")
921
545
  mainError = error as NSError?
922
546
  }
923
547
  }
@@ -948,11 +572,11 @@ extension CustomError: LocalizedError {
948
572
  }
949
573
 
950
574
  } else {
951
- print("\(self.TAG) Download failed")
575
+ print("\(CapacitorUpdater.TAG) Download failed")
952
576
  }
953
577
 
954
578
  case .complete:
955
- print("\(self.TAG) Download complete, total received bytes: \(totalReceivedBytes)")
579
+ print("\(CapacitorUpdater.TAG) Download complete, total received bytes: \(totalReceivedBytes)")
956
580
  self.notifyDownload(id: id, percent: 70, ignoreMultipleOfTen: true)
957
581
  semaphore.signal()
958
582
  }
@@ -974,7 +598,7 @@ extension CustomError: LocalizedError {
974
598
  reachabilityManager?.stopListening()
975
599
 
976
600
  if mainError != nil {
977
- print("\(self.TAG) Failed to download: \(String(describing: mainError))")
601
+ print("\(CapacitorUpdater.TAG) Failed to download: \(String(describing: mainError))")
978
602
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum))
979
603
  throw mainError!
980
604
  }
@@ -982,14 +606,19 @@ extension CustomError: LocalizedError {
982
606
  let finalPath = tempDataPath.deletingLastPathComponent().appendingPathComponent("\(id)")
983
607
  do {
984
608
  var checksumDecrypted = checksum
985
- if !self.hasOldPrivateKeyPropertyInConfig {
986
- try self.decryptFileV2(filePath: tempDataPath, sessionKey: sessionKey, version: version)
987
- } else {
988
- try self.decryptFile(filePath: tempDataPath, sessionKey: sessionKey, version: version)
609
+ do {
610
+ if !self.hasOldPrivateKeyPropertyInConfig {
611
+ try CryptoCipherV2.decryptFile(filePath: tempDataPath, publicKey: self.publicKey, sessionKey: sessionKey, version: version)
612
+ } else {
613
+ try CryptoCipher.decryptFile(filePath: tempDataPath, privateKey: self.privateKey, sessionKey: sessionKey, version: version)
614
+ }
615
+ } catch {
616
+ self.sendStats(action: "decrypt_fail", versionName: version)
617
+ throw error
989
618
  }
990
619
  try FileManager.default.moveItem(at: tempDataPath, to: finalPath)
991
620
  } catch {
992
- print("\(self.TAG) Failed decrypt file : \(error)")
621
+ print("\(CapacitorUpdater.TAG) Failed decrypt file : \(error)")
993
622
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum))
994
623
  cleanDownloadData()
995
624
  throw error
@@ -997,15 +626,15 @@ extension CustomError: LocalizedError {
997
626
 
998
627
  do {
999
628
  if !self.hasOldPrivateKeyPropertyInConfig && !sessionKey.isEmpty {
1000
- checksum = self.calcChecksumV2(filePath: finalPath)
629
+ checksum = CryptoCipherV2.calcChecksum(filePath: finalPath)
1001
630
  } else {
1002
- checksum = self.calcChecksum(filePath: finalPath)
631
+ checksum = CryptoCipher.calcChecksum(filePath: finalPath)
1003
632
  }
1004
- print("\(self.TAG) Downloading: 80% (unzipping)")
633
+ print("\(CapacitorUpdater.TAG) Downloading: 80% (unzipping)")
1005
634
  try self.saveDownloaded(sourceZip: finalPath, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory), notify: true)
1006
635
 
1007
636
  } catch {
1008
- print("\(self.TAG) Failed to unzip file: \(error)")
637
+ print("\(CapacitorUpdater.TAG) Failed to unzip file: \(error)")
1009
638
  self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.ERROR, downloaded: Date(), checksum: checksum))
1010
639
  cleanDownloadData()
1011
640
  // todo: cleanup zip attempts
@@ -1013,25 +642,25 @@ extension CustomError: LocalizedError {
1013
642
  }
1014
643
 
1015
644
  self.notifyDownload(id: id, percent: 90)
1016
- print("\(self.TAG) Downloading: 90% (wrapping up)")
645
+ print("\(CapacitorUpdater.TAG) Downloading: 90% (wrapping up)")
1017
646
  let info = BundleInfo(id: id, version: version, status: BundleStatus.PENDING, downloaded: Date(), checksum: checksum)
1018
647
  self.saveBundleInfo(id: id, bundle: info)
1019
648
  self.cleanDownloadData()
1020
649
  self.notifyDownload(id: id, percent: 100)
1021
- print("\(self.TAG) Downloading: 100% (complete)")
650
+ print("\(CapacitorUpdater.TAG) Downloading: 100% (complete)")
1022
651
  return info
1023
652
  }
1024
653
  private func ensureResumableFilesExist() {
1025
654
  let fileManager = FileManager.default
1026
655
  if !fileManager.fileExists(atPath: tempDataPath.path) {
1027
656
  if !fileManager.createFile(atPath: tempDataPath.path, contents: Data()) {
1028
- print("\(self.TAG) Cannot ensure that a file at \(tempDataPath.path) exists")
657
+ print("\(CapacitorUpdater.TAG) Cannot ensure that a file at \(tempDataPath.path) exists")
1029
658
  }
1030
659
  }
1031
660
 
1032
661
  if !fileManager.fileExists(atPath: updateInfo.path) {
1033
662
  if !fileManager.createFile(atPath: updateInfo.path, contents: Data()) {
1034
- print("\(self.TAG) Cannot ensure that a file at \(updateInfo.path) exists")
663
+ print("\(CapacitorUpdater.TAG) Cannot ensure that a file at \(updateInfo.path) exists")
1035
664
  }
1036
665
  }
1037
666
  }
@@ -1043,7 +672,7 @@ extension CustomError: LocalizedError {
1043
672
  do {
1044
673
  try fileManager.removeItem(at: tempDataPath)
1045
674
  } catch {
1046
- print("\(self.TAG) Could not delete file at \(tempDataPath): \(error)")
675
+ print("\(CapacitorUpdater.TAG) Could not delete file at \(tempDataPath): \(error)")
1047
676
  }
1048
677
  }
1049
678
  // Deleting update.dat
@@ -1051,7 +680,7 @@ extension CustomError: LocalizedError {
1051
680
  do {
1052
681
  try fileManager.removeItem(at: updateInfo)
1053
682
  } catch {
1054
- print("\(self.TAG) Could not delete file at \(updateInfo): \(error)")
683
+ print("\(CapacitorUpdater.TAG) Could not delete file at \(updateInfo): \(error)")
1055
684
  }
1056
685
  }
1057
686
  }
@@ -1079,7 +708,7 @@ extension CustomError: LocalizedError {
1079
708
  do {
1080
709
  try "\(version)".write(to: updateInfo, atomically: true, encoding: .utf8)
1081
710
  } catch {
1082
- print("\(self.TAG) Failed to save progress: \(error)")
711
+ print("\(CapacitorUpdater.TAG) Failed to save progress: \(error)")
1083
712
  }
1084
713
  }
1085
714
  private func getLocalUpdateVersion() -> String { // Return the version that was tried to be downloaded on last download attempt
@@ -1101,7 +730,7 @@ extension CustomError: LocalizedError {
1101
730
  return fileSize.int64Value
1102
731
  }
1103
732
  } catch {
1104
- print("\(self.TAG) Could not retrieve already downloaded data size : \(error)")
733
+ print("\(CapacitorUpdater.TAG) Could not retrieve already downloaded data size : \(error)")
1105
734
  }
1106
735
  return 0
1107
736
  }
@@ -1111,7 +740,7 @@ extension CustomError: LocalizedError {
1111
740
  do {
1112
741
  let files: [String] = try FileManager.default.contentsOfDirectory(atPath: dest.path)
1113
742
  var res: [BundleInfo] = []
1114
- print("\(self.TAG) list File : \(dest.path)")
743
+ print("\(CapacitorUpdater.TAG) list File : \(dest.path)")
1115
744
  if dest.exist {
1116
745
  for id: String in files {
1117
746
  res.append(self.getBundleInfo(id: id))
@@ -1119,7 +748,7 @@ extension CustomError: LocalizedError {
1119
748
  }
1120
749
  return res
1121
750
  } catch {
1122
- print("\(self.TAG) No version available \(dest.path)")
751
+ print("\(CapacitorUpdater.TAG) No version available \(dest.path)")
1123
752
  return []
1124
753
  }
1125
754
  }
@@ -1127,7 +756,7 @@ extension CustomError: LocalizedError {
1127
756
  public func delete(id: String, removeInfo: Bool) -> Bool {
1128
757
  let deleted: BundleInfo = self.getBundleInfo(id: id)
1129
758
  if deleted.isBuiltin() || self.getCurrentBundleId() == id {
1130
- print("\(self.TAG) Cannot delete \(id)")
759
+ print("\(CapacitorUpdater.TAG) Cannot delete \(id)")
1131
760
  return false
1132
761
  }
1133
762
 
@@ -1136,7 +765,7 @@ extension CustomError: LocalizedError {
1136
765
  !next.isDeleted() &&
1137
766
  !next.isErrorStatus() &&
1138
767
  next.getId() == id {
1139
- print("\(self.TAG) Cannot delete the next bundle \(id)")
768
+ print("\(CapacitorUpdater.TAG) Cannot delete the next bundle \(id)")
1140
769
  return false
1141
770
  }
1142
771
 
@@ -1144,7 +773,7 @@ extension CustomError: LocalizedError {
1144
773
  do {
1145
774
  try FileManager.default.removeItem(atPath: destPersist.path)
1146
775
  } catch {
1147
- print("\(self.TAG) Folder \(destPersist.path), not removed.")
776
+ print("\(CapacitorUpdater.TAG) Folder \(destPersist.path), not removed.")
1148
777
  return false
1149
778
  }
1150
779
  if removeInfo {
@@ -1152,7 +781,7 @@ extension CustomError: LocalizedError {
1152
781
  } else {
1153
782
  self.saveBundleInfo(id: id, bundle: deleted.setStatus(status: BundleStatus.DELETED.localizedString))
1154
783
  }
1155
- print("\(self.TAG) bundle delete \(deleted.getVersionName())")
784
+ print("\(CapacitorUpdater.TAG) bundle delete \(deleted.getVersionName())")
1156
785
  self.sendStats(action: "delete", versionName: deleted.getVersionName())
1157
786
  return true
1158
787
  }
@@ -1205,7 +834,7 @@ extension CustomError: LocalizedError {
1205
834
  public func autoReset() {
1206
835
  let currentBundle: BundleInfo = self.getCurrentBundle()
1207
836
  if !currentBundle.isBuiltin() && !self.bundleExists(id: currentBundle.getId()) {
1208
- print("\(self.TAG) Folder at bundle path does not exist. Triggering reset.")
837
+ print("\(CapacitorUpdater.TAG) Folder at bundle path does not exist. Triggering reset.")
1209
838
  self.reset()
1210
839
  }
1211
840
  }
@@ -1215,7 +844,7 @@ extension CustomError: LocalizedError {
1215
844
  }
1216
845
 
1217
846
  public func reset(isInternal: Bool) {
1218
- print("\(self.TAG) reset: \(isInternal)")
847
+ print("\(CapacitorUpdater.TAG) reset: \(isInternal)")
1219
848
  let currentBundleName = self.getCurrentBundle().getVersionName()
1220
849
  self.setCurrentBundle(bundle: "")
1221
850
  self.setFallbackBundle(fallback: Optional<BundleInfo>.none)
@@ -1228,14 +857,14 @@ extension CustomError: LocalizedError {
1228
857
  public func setSuccess(bundle: BundleInfo, autoDeletePrevious: Bool) {
1229
858
  self.setBundleStatus(id: bundle.getId(), status: BundleStatus.SUCCESS)
1230
859
  let fallback: BundleInfo = self.getFallbackBundle()
1231
- print("\(self.TAG) Fallback bundle is: \(fallback.toString())")
1232
- print("\(self.TAG) Version successfully loaded: \(bundle.toString())")
860
+ print("\(CapacitorUpdater.TAG) Fallback bundle is: \(fallback.toString())")
861
+ print("\(CapacitorUpdater.TAG) Version successfully loaded: \(bundle.toString())")
1233
862
  if autoDeletePrevious && !fallback.isBuiltin() && fallback.getId() != bundle.getId() {
1234
863
  let res = self.delete(id: fallback.getId())
1235
864
  if res {
1236
- print("\(self.TAG) Deleted previous bundle: \(fallback.toString())")
865
+ print("\(CapacitorUpdater.TAG) Deleted previous bundle: \(fallback.toString())")
1237
866
  } else {
1238
- print("\(self.TAG) Failed to delete previous bundle: \(fallback.toString())")
867
+ print("\(CapacitorUpdater.TAG) Failed to delete previous bundle: \(fallback.toString())")
1239
868
  }
1240
869
  }
1241
870
  self.setFallbackBundle(fallback: bundle)
@@ -1248,7 +877,7 @@ extension CustomError: LocalizedError {
1248
877
  func unsetChannel() -> SetChannel {
1249
878
  let setChannel: SetChannel = SetChannel()
1250
879
  if (self.channelUrl ).isEmpty {
1251
- print("\(self.TAG) Channel URL is not set")
880
+ print("\(CapacitorUpdater.TAG) Channel URL is not set")
1252
881
  setChannel.message = "Channel URL is not set"
1253
882
  setChannel.error = "missing_config"
1254
883
  return setChannel
@@ -1271,7 +900,7 @@ extension CustomError: LocalizedError {
1271
900
  setChannel.message = message
1272
901
  }
1273
902
  case let .failure(error):
1274
- print("\(self.TAG) Error unset Channel", response.value ?? "", error)
903
+ print("\(CapacitorUpdater.TAG) Error unset Channel", response.value ?? "", error)
1275
904
  setChannel.message = "Error unset Channel \(String(describing: response.value))"
1276
905
  setChannel.error = "response_error"
1277
906
  }
@@ -1284,7 +913,7 @@ extension CustomError: LocalizedError {
1284
913
  func setChannel(channel: String) -> SetChannel {
1285
914
  let setChannel: SetChannel = SetChannel()
1286
915
  if (self.channelUrl ).isEmpty {
1287
- print("\(self.TAG) Channel URL is not set")
916
+ print("\(CapacitorUpdater.TAG) Channel URL is not set")
1288
917
  setChannel.message = "Channel URL is not set"
1289
918
  setChannel.error = "missing_config"
1290
919
  return setChannel
@@ -1308,7 +937,7 @@ extension CustomError: LocalizedError {
1308
937
  setChannel.message = message
1309
938
  }
1310
939
  case let .failure(error):
1311
- print("\(self.TAG) Error set Channel", response.value ?? "", error)
940
+ print("\(CapacitorUpdater.TAG) Error set Channel", response.value ?? "", error)
1312
941
  setChannel.message = "Error set Channel \(String(describing: response.value))"
1313
942
  setChannel.error = "response_error"
1314
943
  }
@@ -1321,7 +950,7 @@ extension CustomError: LocalizedError {
1321
950
  func getChannel() -> GetChannel {
1322
951
  let getChannel: GetChannel = GetChannel()
1323
952
  if (self.channelUrl ).isEmpty {
1324
- print("\(self.TAG) Channel URL is not set")
953
+ print("\(CapacitorUpdater.TAG) Channel URL is not set")
1325
954
  getChannel.message = "Channel URL is not set"
1326
955
  getChannel.error = "missing_config"
1327
956
  return getChannel
@@ -1360,7 +989,7 @@ extension CustomError: LocalizedError {
1360
989
  }
1361
990
  }
1362
991
 
1363
- print("\(self.TAG) Error get Channel", response.value ?? "", error)
992
+ print("\(CapacitorUpdater.TAG) Error get Channel", response.value ?? "", error)
1364
993
  getChannel.message = "Error get Channel \(String(describing: response.value)))"
1365
994
  getChannel.error = "response_error"
1366
995
  }
@@ -1395,9 +1024,9 @@ extension CustomError: LocalizedError {
1395
1024
  ).responseData { response in
1396
1025
  switch response.result {
1397
1026
  case .success:
1398
- print("\(self.TAG) Stats sent for \(action), version \(versionName)")
1027
+ print("\(CapacitorUpdater.TAG) Stats sent for \(action), version \(versionName)")
1399
1028
  case let .failure(error):
1400
- print("\(self.TAG) Error sending stats: ", response.value ?? "", error.localizedDescription)
1029
+ print("\(CapacitorUpdater.TAG) Error sending stats: ", response.value ?? "", error.localizedDescription)
1401
1030
  }
1402
1031
  semaphore.signal()
1403
1032
  }
@@ -1412,7 +1041,7 @@ extension CustomError: LocalizedError {
1412
1041
  if id != nil {
1413
1042
  trueId = id!
1414
1043
  }
1415
- // print("\(self.TAG) Getting info for bundle [\(trueId)]")
1044
+ // print("\(CapacitorUpdater.TAG) Getting info for bundle [\(trueId)]")
1416
1045
  let result: BundleInfo
1417
1046
  if BundleInfo.ID_BUILTIN == trueId {
1418
1047
  result = BundleInfo(id: trueId, version: "", status: BundleStatus.SUCCESS, checksum: "")
@@ -1422,11 +1051,11 @@ extension CustomError: LocalizedError {
1422
1051
  do {
1423
1052
  result = try UserDefaults.standard.getObj(forKey: "\(trueId)\(self.INFO_SUFFIX)", castTo: BundleInfo.self)
1424
1053
  } catch {
1425
- print("\(self.TAG) Failed to parse info for bundle [\(trueId)]", error.localizedDescription)
1054
+ print("\(CapacitorUpdater.TAG) Failed to parse info for bundle [\(trueId)]", error.localizedDescription)
1426
1055
  result = BundleInfo(id: trueId, version: "", status: BundleStatus.PENDING, checksum: "")
1427
1056
  }
1428
1057
  }
1429
- // print("\(self.TAG) Returning info bundle [\(result.toString())]")
1058
+ // print("\(CapacitorUpdater.TAG) Returning info bundle [\(result.toString())]")
1430
1059
  return result
1431
1060
  }
1432
1061
 
@@ -1446,26 +1075,26 @@ extension CustomError: LocalizedError {
1446
1075
 
1447
1076
  public func saveBundleInfo(id: String, bundle: BundleInfo?) {
1448
1077
  if bundle != nil && (bundle!.isBuiltin() || bundle!.isUnknown()) {
1449
- print("\(self.TAG) Not saving info for bundle [\(id)]", bundle?.toString() ?? "")
1078
+ print("\(CapacitorUpdater.TAG) Not saving info for bundle [\(id)]", bundle?.toString() ?? "")
1450
1079
  return
1451
1080
  }
1452
1081
  if bundle == nil {
1453
- print("\(self.TAG) Removing info for bundle [\(id)]")
1082
+ print("\(CapacitorUpdater.TAG) Removing info for bundle [\(id)]")
1454
1083
  UserDefaults.standard.removeObject(forKey: "\(id)\(self.INFO_SUFFIX)")
1455
1084
  } else {
1456
1085
  let update = bundle!.setId(id: id)
1457
- print("\(self.TAG) Storing info for bundle [\(id)]", update.toString())
1086
+ print("\(CapacitorUpdater.TAG) Storing info for bundle [\(id)]", update.toString())
1458
1087
  do {
1459
1088
  try UserDefaults.standard.setObj(update, forKey: "\(id)\(self.INFO_SUFFIX)")
1460
1089
  } catch {
1461
- print("\(self.TAG) Failed to save info for bundle [\(id)]", error.localizedDescription)
1090
+ print("\(CapacitorUpdater.TAG) Failed to save info for bundle [\(id)]", error.localizedDescription)
1462
1091
  }
1463
1092
  }
1464
1093
  UserDefaults.standard.synchronize()
1465
1094
  }
1466
1095
 
1467
1096
  private func setBundleStatus(id: String, status: BundleStatus) {
1468
- print("\(self.TAG) Setting status for bundle [\(id)] to \(status)")
1097
+ print("\(CapacitorUpdater.TAG) Setting status for bundle [\(id)] to \(status)")
1469
1098
  let info = self.getBundleInfo(id: id)
1470
1099
  self.saveBundleInfo(id: id, bundle: info.setStatus(status: status.localizedString))
1471
1100
  }