@capgo/capacitor-updater 8.51.8 → 8.51.10
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/CapgoUpdater.java +72 -23
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +129 -23
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +306 -115
- package/ios/Sources/CapacitorUpdaterPlugin/AES.swift +119 -0
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +249 -160
- package/ios/Sources/CapacitorUpdaterPlugin/CryptoCipher.swift +41 -29
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import CommonCrypto
|
|
3
3
|
import CryptoKit
|
|
4
|
+
import Darwin
|
|
4
5
|
|
|
5
6
|
///
|
|
6
7
|
/// Constants
|
|
@@ -83,4 +84,122 @@ public struct AES128Key {
|
|
|
83
84
|
return nil
|
|
84
85
|
}
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
/// AES-CBC file-to-file. Never holds the whole ciphertext in RAM.
|
|
89
|
+
func decrypt(from source: URL, to destination: URL) throws {
|
|
90
|
+
var cryptor: CCCryptorRef?
|
|
91
|
+
let createStatus: CCCryptorStatus = aes128Key.withUnsafeBytes { keyBytes in
|
|
92
|
+
initVector.withUnsafeBytes { ivBytes in
|
|
93
|
+
guard let keyPtr = keyBytes.baseAddress, let ivPtr = ivBytes.baseAddress else {
|
|
94
|
+
return CCCryptorStatus(kCCParamError)
|
|
95
|
+
}
|
|
96
|
+
return CCCryptorCreate(
|
|
97
|
+
CCOperation(kCCDecrypt),
|
|
98
|
+
AESConstants.aesAlgorithm,
|
|
99
|
+
AESConstants.aesOptions,
|
|
100
|
+
keyPtr,
|
|
101
|
+
keyBytes.count,
|
|
102
|
+
ivPtr,
|
|
103
|
+
&cryptor
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
guard createStatus == kCCSuccess, let cryptor else {
|
|
108
|
+
logger.error("Failed to create AES cryptor")
|
|
109
|
+
throw NSError(domain: "AESDecryptError", code: Int(createStatus), userInfo: nil)
|
|
110
|
+
}
|
|
111
|
+
defer {
|
|
112
|
+
CCCryptorRelease(cryptor)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
guard let input = InputStream(url: source) else {
|
|
116
|
+
throw NSError(domain: "AESDecryptError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to open AES source"])
|
|
117
|
+
}
|
|
118
|
+
input.open()
|
|
119
|
+
defer {
|
|
120
|
+
input.close()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let tempURL = destination.deletingLastPathComponent().appendingPathComponent("capgo-aes-\(UUID().uuidString).tmp")
|
|
124
|
+
let fileManager = FileManager.default
|
|
125
|
+
fileManager.createFile(atPath: tempURL.path, contents: nil)
|
|
126
|
+
let output = try FileHandle(forWritingTo: tempURL)
|
|
127
|
+
defer {
|
|
128
|
+
try? output.close()
|
|
129
|
+
try? fileManager.removeItem(at: tempURL)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let bufferSize = CryptoCipher.ioBufferBytes()
|
|
133
|
+
let outBufSize = bufferSize + kCCBlockSizeAES128
|
|
134
|
+
var inBuf = [UInt8](repeating: 0, count: bufferSize)
|
|
135
|
+
var outBuf = [UInt8](repeating: 0, count: outBufSize)
|
|
136
|
+
let outFd = output.fileDescriptor
|
|
137
|
+
|
|
138
|
+
while true {
|
|
139
|
+
let n = inBuf.withUnsafeMutableBufferPointer { ptr in
|
|
140
|
+
input.read(ptr.baseAddress!, maxLength: ptr.count)
|
|
141
|
+
}
|
|
142
|
+
if n == 0 {
|
|
143
|
+
break
|
|
144
|
+
}
|
|
145
|
+
if n < 0 {
|
|
146
|
+
throw input.streamError ?? NSError(domain: "AESDecryptError", code: 2, userInfo: [NSLocalizedDescriptionKey: "AES stream read failed"])
|
|
147
|
+
}
|
|
148
|
+
var moved: size_t = 0
|
|
149
|
+
let status: CCCryptorStatus = inBuf.withUnsafeBufferPointer { inRaw in
|
|
150
|
+
outBuf.withUnsafeMutableBytes { outRaw in
|
|
151
|
+
CCCryptorUpdate(
|
|
152
|
+
cryptor,
|
|
153
|
+
inRaw.baseAddress,
|
|
154
|
+
n,
|
|
155
|
+
outRaw.baseAddress,
|
|
156
|
+
outBufSize,
|
|
157
|
+
&moved
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
guard status == kCCSuccess else {
|
|
162
|
+
logger.error("AES stream update failed")
|
|
163
|
+
throw NSError(domain: "AESDecryptError", code: Int(status), userInfo: nil)
|
|
164
|
+
}
|
|
165
|
+
if moved > 0 {
|
|
166
|
+
try Self.writeAll(fd: outFd, buffer: &outBuf, count: moved)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var moved: size_t = 0
|
|
171
|
+
let finalStatus: CCCryptorStatus = outBuf.withUnsafeMutableBytes { outRaw in
|
|
172
|
+
CCCryptorFinal(cryptor, outRaw.baseAddress, outBufSize, &moved)
|
|
173
|
+
}
|
|
174
|
+
guard finalStatus == kCCSuccess else {
|
|
175
|
+
logger.error("AES stream finalize failed")
|
|
176
|
+
throw NSError(domain: "AESDecryptError", code: Int(finalStatus), userInfo: nil)
|
|
177
|
+
}
|
|
178
|
+
if moved > 0 {
|
|
179
|
+
try Self.writeAll(fd: outFd, buffer: &outBuf, count: moved)
|
|
180
|
+
}
|
|
181
|
+
try output.close()
|
|
182
|
+
|
|
183
|
+
do {
|
|
184
|
+
_ = try fileManager.replaceItemAt(destination, withItemAt: tempURL)
|
|
185
|
+
} catch {
|
|
186
|
+
if fileManager.fileExists(atPath: destination.path) {
|
|
187
|
+
throw error
|
|
188
|
+
}
|
|
189
|
+
try fileManager.moveItem(at: tempURL, to: destination)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private static func writeAll(fd: Int32, buffer: inout [UInt8], count: Int) throws {
|
|
194
|
+
var offset = 0
|
|
195
|
+
while offset < count {
|
|
196
|
+
let written = buffer.withUnsafeBufferPointer { ptr -> Int in
|
|
197
|
+
Darwin.write(fd, ptr.baseAddress!.advanced(by: offset), count - offset)
|
|
198
|
+
}
|
|
199
|
+
if written <= 0 {
|
|
200
|
+
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: [NSLocalizedDescriptionKey: "AES stream write failed"])
|
|
201
|
+
}
|
|
202
|
+
offset += written
|
|
203
|
+
}
|
|
204
|
+
}
|
|
86
205
|
}
|
|
@@ -96,7 +96,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
96
96
|
deinit {
|
|
97
97
|
implementation.shutdown()
|
|
98
98
|
}
|
|
99
|
-
private let pluginVersion: String = "8.51.
|
|
99
|
+
private let pluginVersion: String = "8.51.10"
|
|
100
100
|
private let launchStartedAtMs = Int64(Date().timeIntervalSince1970 * 1000)
|
|
101
101
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
102
102
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|