@capacitor-community/sqlite 5.7.2 → 5.7.3-1
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/README.md +3 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsDownloadFromHTTP.java +71 -46
- package/electron/dist/plugin.js +37 -27
- package/electron/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorSQLite.swift +13 -12
- package/ios/Plugin/CapacitorSQLitePlugin.swift +9 -14
- package/ios/Plugin/Utils/UtilsBinding.swift +2 -3
- package/ios/Plugin/Utils/UtilsDelete.swift +25 -12
- package/ios/Plugin/Utils/UtilsDownloadFromHTTP.swift +168 -98
- package/ios/Plugin/Utils/UtilsJson.swift +6 -6
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +4 -4
- package/ios/Plugin/Utils/UtilsSQLStatement.swift +284 -90
- package/package.json +7 -7
|
@@ -589,12 +589,9 @@ enum CapacitorSQLiteError: Error {
|
|
|
589
589
|
self.retHandler.rResult(call: call)
|
|
590
590
|
return
|
|
591
591
|
case .failure(let error):
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
self.retHandler.rResult(call: call, message: msg)
|
|
596
|
-
return
|
|
597
|
-
}
|
|
592
|
+
let msg = "Download from HTTP failed: \(error.localizedDescription)"
|
|
593
|
+
self.retHandler.rResult(call: call, message: msg)
|
|
594
|
+
return
|
|
598
595
|
|
|
599
596
|
}
|
|
600
597
|
|
|
@@ -1013,6 +1010,7 @@ enum CapacitorSQLiteError: Error {
|
|
|
1013
1010
|
// MARK: - deleteDatabase
|
|
1014
1011
|
|
|
1015
1012
|
// swiftlint:disable cyclomatic_complexity
|
|
1013
|
+
// swiftlint:disable function_body_length
|
|
1016
1014
|
@objc func deleteDatabase(_ dbName: String, readonly: Bool) throws {
|
|
1017
1015
|
guard isInit else {
|
|
1018
1016
|
throw CapacitorSQLiteError.failed(message: initMessage)
|
|
@@ -1030,10 +1028,12 @@ enum CapacitorSQLiteError: Error {
|
|
|
1030
1028
|
do {
|
|
1031
1029
|
if !mDb.isDBOpen() {
|
|
1032
1030
|
// check the state of the DB
|
|
1033
|
-
let state: State = UtilsSQLCipher.getDatabaseState(databaseLocation: databaseLocation,
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1031
|
+
let state: State = UtilsSQLCipher.getDatabaseState(databaseLocation: databaseLocation,
|
|
1032
|
+
databaseName: "\(mDbName)SQLite.db",
|
|
1033
|
+
account: account)
|
|
1034
|
+
if !isEncryption &&
|
|
1035
|
+
(state.rawValue == "ENCRYPTEDGLOBALSECRET" ||
|
|
1036
|
+
state.rawValue == "ENCRYPTEDSECRET") {
|
|
1037
1037
|
var msg = "Cannot delete an Encrypted database with "
|
|
1038
1038
|
msg += "No Encryption set in capacitor.config"
|
|
1039
1039
|
throw CapacitorSQLiteError.failed(message: msg)
|
|
@@ -1066,6 +1066,7 @@ enum CapacitorSQLiteError: Error {
|
|
|
1066
1066
|
throw CapacitorSQLiteError.failed(message: msg)
|
|
1067
1067
|
}
|
|
1068
1068
|
}
|
|
1069
|
+
// swiftlint:enable function_body_length
|
|
1069
1070
|
// swiftlint:enable cyclomatic_complexity
|
|
1070
1071
|
|
|
1071
1072
|
// MARK: - isJsonValid
|
|
@@ -1547,7 +1548,7 @@ enum CapacitorSQLiteError: Error {
|
|
|
1547
1548
|
// get the database files
|
|
1548
1549
|
let dbList: [String] = try UtilsFile.getFileList(path: aPath, ext: ".db")
|
|
1549
1550
|
// filter for db including SQLite
|
|
1550
|
-
let dbWithSQLite = dbList.filter
|
|
1551
|
+
let dbWithSQLite = dbList.filter({ $0.contains("SQLite") })
|
|
1551
1552
|
|
|
1552
1553
|
return dbWithSQLite
|
|
1553
1554
|
|
|
@@ -1567,7 +1568,7 @@ enum CapacitorSQLiteError: Error {
|
|
|
1567
1568
|
let dbList: [String] = try UtilsMigrate
|
|
1568
1569
|
.getMigratableList(folderPath: folderPath)
|
|
1569
1570
|
// filter for db not including SQLite
|
|
1570
|
-
let dbNoSQLite = dbList.filter
|
|
1571
|
+
let dbNoSQLite = dbList.filter({ !$0.contains("SQLite") })
|
|
1571
1572
|
|
|
1572
1573
|
return dbNoSQLite
|
|
1573
1574
|
|
|
@@ -1369,14 +1369,13 @@ public class CapacitorSQLitePlugin: CAPPlugin {
|
|
|
1369
1369
|
implementation?.addUpgradeStatement(dbName,
|
|
1370
1370
|
upgrade: upgrade) {
|
|
1371
1371
|
if
|
|
1372
|
-
versionUpgrades[dbName] != nil {
|
|
1372
|
+
self.versionUpgrades["\(dbName)"] != nil {
|
|
1373
1373
|
for (versionKey, upgObj) in upgVersionDict {
|
|
1374
|
-
versionUpgrades[dbName]?[versionKey] = upgObj
|
|
1374
|
+
self.versionUpgrades["\(dbName)"]?[versionKey] = upgObj
|
|
1375
1375
|
}
|
|
1376
1376
|
} else {
|
|
1377
|
-
versionUpgrades
|
|
1377
|
+
self.versionUpgrades["\(dbName)"] = upgVersionDict
|
|
1378
1378
|
}
|
|
1379
|
-
|
|
1380
1379
|
retHandler.rResult(call: call)
|
|
1381
1380
|
return
|
|
1382
1381
|
} else {
|
|
@@ -1542,29 +1541,25 @@ public class CapacitorSQLitePlugin: CAPPlugin {
|
|
|
1542
1541
|
message: "GetFromHTTPRequest: Must provide a database url")
|
|
1543
1542
|
return
|
|
1544
1543
|
}
|
|
1545
|
-
DispatchQueue.global(qos: .background).async {
|
|
1544
|
+
DispatchQueue.global(qos: .background).async(execute: {
|
|
1546
1545
|
do {
|
|
1547
1546
|
try self.implementation?.getFromHTTPRequest(call, url: url)
|
|
1548
|
-
DispatchQueue.main.async {
|
|
1549
|
-
self.retHandler.rResult(call: call)
|
|
1550
|
-
return
|
|
1551
|
-
}
|
|
1552
1547
|
} catch CapacitorSQLiteError.failed(let message) {
|
|
1553
1548
|
|
|
1554
|
-
DispatchQueue.main.async {
|
|
1549
|
+
DispatchQueue.main.async(execute: {
|
|
1555
1550
|
let msg = "GetFromHTTPRequest: \(message)"
|
|
1556
1551
|
self.retHandler.rResult(call: call, message: msg)
|
|
1557
1552
|
return
|
|
1558
|
-
}
|
|
1553
|
+
})
|
|
1559
1554
|
} catch let error {
|
|
1560
|
-
DispatchQueue.main.async {
|
|
1555
|
+
DispatchQueue.main.async(execute: {
|
|
1561
1556
|
let msg = "GetFromHTTPRequest: " +
|
|
1562
1557
|
"\(error.localizedDescription)"
|
|
1563
1558
|
self.retHandler.rResult(call: call, message: msg)
|
|
1564
1559
|
return
|
|
1565
|
-
}
|
|
1560
|
+
})
|
|
1566
1561
|
}
|
|
1567
|
-
}
|
|
1562
|
+
})
|
|
1568
1563
|
|
|
1569
1564
|
}
|
|
1570
1565
|
|
|
@@ -84,10 +84,9 @@ class UtilsBinding {
|
|
|
84
84
|
// swiftlint:enable cyclomatic_complexity
|
|
85
85
|
class func extractSortedValues(from queryValues: [String: Int]) -> [UInt8] {
|
|
86
86
|
// Extract keys and sort them
|
|
87
|
-
let sortedKeys = queryValues.keys.sorted { $0.localizedStandardCompare($1) == .orderedAscending
|
|
88
|
-
|
|
87
|
+
let sortedKeys = queryValues.keys.sorted { $0.localizedStandardCompare($1) == .orderedAscending}
|
|
89
88
|
// Extract corresponding values and sort them based on keys
|
|
90
|
-
let sortedValues = sortedKeys.compactMap
|
|
89
|
+
let sortedValues = sortedKeys.compactMap({ UInt8(queryValues[$0] ?? 0) })
|
|
91
90
|
|
|
92
91
|
return sortedValues
|
|
93
92
|
}
|
|
@@ -289,19 +289,19 @@ class UtilsDelete {
|
|
|
289
289
|
throws -> (String, [[String: Any]]) {
|
|
290
290
|
var relatedItems: [[String: Any]] = []
|
|
291
291
|
var key: String = ""
|
|
292
|
-
let t1Names = withRefsNames.map
|
|
293
|
-
let t2Names = colNames.map
|
|
292
|
+
let t1Names = withRefsNames.map({ "t1.\($0)" })
|
|
293
|
+
let t2Names = colNames.map({ "t2.\($0)"})
|
|
294
294
|
|
|
295
295
|
do {
|
|
296
296
|
var whereClause = try UtilsSQLStatement
|
|
297
297
|
.addPrefixToWhereClause(whStmt, from: colNames,
|
|
298
|
-
|
|
298
|
+
destination: withRefsNames,
|
|
299
299
|
prefix: "t2.")
|
|
300
300
|
if whereClause.hasSuffix(";") {
|
|
301
301
|
whereClause = String(whereClause.dropLast())
|
|
302
302
|
}
|
|
303
303
|
let resultString = zip(t1Names, t2Names)
|
|
304
|
-
.map
|
|
304
|
+
.map({ "\($0) = \($1)"})
|
|
305
305
|
.joined(separator: " AND ")
|
|
306
306
|
let sql = "SELECT t1.rowid FROM \(updTableName) t1 " +
|
|
307
307
|
"JOIN \(tableName) t2 ON \(resultString) " +
|
|
@@ -312,9 +312,12 @@ class UtilsDelete {
|
|
|
312
312
|
if let mVals = vals[0]["ios_columns"] as? [String] {
|
|
313
313
|
key = mVals[0]
|
|
314
314
|
let keyToRemove = "ios_columns"
|
|
315
|
-
|
|
315
|
+
|
|
316
|
+
// Remove dictionaries where the keys contain "ios_columns"
|
|
317
|
+
vals.removeAll { (dict: [String: Any]) in
|
|
316
318
|
return dict.keys.contains(keyToRemove)
|
|
317
319
|
}
|
|
320
|
+
// Append the remaining dictionaries to relatedItems
|
|
318
321
|
for val in vals {
|
|
319
322
|
relatedItems.append(val)
|
|
320
323
|
}
|
|
@@ -440,9 +443,15 @@ class UtilsDelete {
|
|
|
440
443
|
.firstMatch(in: statement, options: [],
|
|
441
444
|
range: NSRange(location: 0,
|
|
442
445
|
length: statement.utf16.count)) {
|
|
443
|
-
let tableNameRange = Range(tableNameMatch.range(
|
|
444
|
-
|
|
445
|
-
|
|
446
|
+
if let tableNameRange = Range(tableNameMatch.range(at: 1), in: statement) {
|
|
447
|
+
tableName = String(statement[tableNameRange])
|
|
448
|
+
} else {
|
|
449
|
+
let msg = "getRefs: Error creating tableNameRange "
|
|
450
|
+
throw UtilsDeleteError.getRefs(message: msg)
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
let msg = "getRefs: Error creating tableNameMatch "
|
|
454
|
+
throw UtilsDeleteError.getRefs(message: msg)
|
|
446
455
|
}
|
|
447
456
|
|
|
448
457
|
// Regular expression pattern to match the FOREIGN KEY
|
|
@@ -458,10 +467,14 @@ class UtilsDelete {
|
|
|
458
467
|
range: NSRange(location: 0,
|
|
459
468
|
length: statement.utf16.count))
|
|
460
469
|
for foreignKeyMatch in foreignKeyMatches {
|
|
461
|
-
let foreignKeyRange = Range(
|
|
462
|
-
foreignKeyMatch.range(at: 0), in: statement)
|
|
463
|
-
|
|
464
|
-
|
|
470
|
+
if let foreignKeyRange = Range(
|
|
471
|
+
foreignKeyMatch.range(at: 0), in: statement) {
|
|
472
|
+
let foreignKey = String(statement[foreignKeyRange])
|
|
473
|
+
foreignKeys.append(foreignKey)
|
|
474
|
+
} else {
|
|
475
|
+
let msg = "getRefs: Error creating foreignKeyRange "
|
|
476
|
+
throw UtilsDeleteError.getRefs(message: msg)
|
|
477
|
+
}
|
|
465
478
|
}
|
|
466
479
|
} catch {
|
|
467
480
|
let msg = "getRefs: Error creating regular expression: " +
|
|
@@ -9,114 +9,184 @@ import Foundation
|
|
|
9
9
|
import ZIPFoundation
|
|
10
10
|
|
|
11
11
|
enum UtilsDownloadError: Error {
|
|
12
|
-
case downloadFromHTTPFailed
|
|
12
|
+
case downloadFromHTTPFailed(message: String)
|
|
13
|
+
case fileNotFound(message: String)
|
|
14
|
+
case fileMoveFailed(message: String)
|
|
15
|
+
case fileExtractionFailed(message: String)
|
|
16
|
+
case invalidArchive(message: String)
|
|
13
17
|
}
|
|
18
|
+
|
|
14
19
|
class UtilsDownloadFromHTTP {
|
|
15
|
-
|
|
16
|
-
// swiftlint:disable function_body_length
|
|
20
|
+
|
|
17
21
|
class func download(databaseLocation: String, url: String,
|
|
18
|
-
completion: @escaping (Result<Bool, UtilsDownloadError>)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
completion: @escaping (Result<Bool, UtilsDownloadError>) -> Void) {
|
|
23
|
+
guard let fileDetails = getFileDetails(url: url),
|
|
24
|
+
let fileExtension = fileDetails.extension ,
|
|
25
|
+
fileExtension == "db" || fileExtension == "zip" else {
|
|
26
|
+
let msg = "download: Not a .zip or .db url"
|
|
27
|
+
print("\(msg)")
|
|
28
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
guard let dbUrl = try? UtilsFile.getDatabaseLocationURL(databaseLocation: databaseLocation) else {
|
|
33
|
+
let msg = "databaseLocation failed"
|
|
34
|
+
print("\(msg)")
|
|
35
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
downloadFile(url: url) { result in
|
|
40
|
+
switch result {
|
|
41
|
+
case .success(let cachedFile):
|
|
42
|
+
if fileExtension == "zip" {
|
|
43
|
+
handleZipFile(cachedFile: cachedFile, dbUrl: dbUrl, completion: completion)
|
|
44
|
+
} else {
|
|
45
|
+
handleNonZipFile(cachedFile: cachedFile, dbUrl: dbUrl, completion: completion)
|
|
31
46
|
}
|
|
47
|
+
case .failure:
|
|
48
|
+
let msg = "Failed to download file: "
|
|
49
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
32
50
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let msg = "\(String(describing: error?.localizedDescription))"
|
|
47
|
-
print("\(msg)")
|
|
48
|
-
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class func handleZipFile(cachedFile: URL, dbUrl: URL, completion: @escaping (Result<Bool, UtilsDownloadError>) -> Void) {
|
|
55
|
+
extractDBFiles(from: cachedFile) { dbFiles, error in
|
|
56
|
+
if let error = error {
|
|
57
|
+
let msg = "\(error.localizedDescription)"
|
|
58
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
59
|
+
} else {
|
|
60
|
+
for file in dbFiles {
|
|
61
|
+
if let moveError = moveAndRenameFile(from: file, to: dbUrl) {
|
|
62
|
+
let msg = "Failed to move file: \(moveError.localizedDescription)"
|
|
63
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
49
64
|
return
|
|
50
65
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
dirUrl: dbURL)
|
|
92
|
-
completion(.success(true))
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Handle potential file system errors
|
|
97
|
-
catch let error {
|
|
98
|
-
let msg = "\(error.localizedDescription)"
|
|
99
|
-
print("\(msg)")
|
|
100
|
-
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed))
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
default:
|
|
104
|
-
let msg = "Download: GET resquest not successful. http status code \(httpResponse.statusCode)"
|
|
105
|
-
print("\(msg)")
|
|
106
|
-
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed))
|
|
107
|
-
return
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
let msg = "Download: not a valid http response"
|
|
111
|
-
print("\(msg)")
|
|
112
|
-
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed))
|
|
66
|
+
}
|
|
67
|
+
completion(.success(true))
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class func handleNonZipFile(cachedFile: URL, dbUrl: URL, completion: @escaping (Result<Bool, UtilsDownloadError>) -> Void) {
|
|
73
|
+
if let moveError = moveAndRenameFile(from: cachedFile, to: dbUrl) {
|
|
74
|
+
let msg = "Failed to move file: \(moveError.localizedDescription)"
|
|
75
|
+
completion(.failure(UtilsDownloadError.downloadFromHTTPFailed(message: msg)))
|
|
76
|
+
} else {
|
|
77
|
+
completion(.success(true))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class func getFileDetails(url: String) -> (filename: String, extension: String?)? {
|
|
82
|
+
guard let fileURL = URL(string: url) else { return nil }
|
|
83
|
+
let filename = fileURL.lastPathComponent
|
|
84
|
+
let ext = fileURL.pathExtension
|
|
85
|
+
return (filename, ext.isEmpty ? nil : ext)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class func downloadFile(url: String, completion: @escaping (Result<URL, Error>) -> Void) {
|
|
89
|
+
guard let fileURL = URL(string: url) else { return }
|
|
90
|
+
|
|
91
|
+
URLSession.shared.downloadTask(with: fileURL) { (location, _, error) in
|
|
92
|
+
if let location = location {
|
|
93
|
+
let tmpURL = UtilsFile.getTmpURL()
|
|
94
|
+
let suggestedFilename = fileURL.lastPathComponent
|
|
95
|
+
|
|
96
|
+
// Construct the destination URL
|
|
97
|
+
let destinationURL = tmpURL.appendingPathComponent(suggestedFilename)
|
|
98
|
+
|
|
99
|
+
// Check if the destination file already exists
|
|
100
|
+
if FileManager.default.fileExists(atPath: destinationURL.path) {
|
|
101
|
+
// Remove the existing file
|
|
102
|
+
do {
|
|
103
|
+
try FileManager.default.removeItem(at: destinationURL)
|
|
104
|
+
} catch {
|
|
105
|
+
completion(.failure(error))
|
|
113
106
|
return
|
|
114
107
|
}
|
|
115
108
|
}
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
|
|
110
|
+
do {
|
|
111
|
+
try FileManager.default.moveItem(at: location, to: destinationURL)
|
|
112
|
+
completion(.success(destinationURL))
|
|
113
|
+
} catch {
|
|
114
|
+
print("Moving file \(error.localizedDescription)")
|
|
115
|
+
completion(.failure(error))
|
|
116
|
+
}
|
|
117
|
+
} else if let error = error {
|
|
118
|
+
print("Location file \(error.localizedDescription)")
|
|
119
|
+
completion(.failure(error))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}.resume()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
class func moveAndRenameFile(from sourceURL: URL, to dbURL: URL) -> Error? {
|
|
126
|
+
let fileManager = FileManager.default
|
|
127
|
+
|
|
128
|
+
do {
|
|
129
|
+
let destinationURL = dbURL.appendingPathComponent(sourceURL.lastPathComponent).absoluteURL
|
|
130
|
+
|
|
131
|
+
// Ensure the destination directory exists
|
|
132
|
+
try fileManager.createDirectory(at: dbURL, withIntermediateDirectories: true, attributes: nil)
|
|
133
|
+
// Check if the destination file already exists and delete it if necessary
|
|
134
|
+
if fileManager.fileExists(atPath: destinationURL.path) {
|
|
135
|
+
try fileManager.removeItem(at: destinationURL)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Move the file to the destination URL
|
|
139
|
+
try fileManager.moveItem(at: sourceURL, to: destinationURL)
|
|
140
|
+
|
|
141
|
+
// Rename the file if needed
|
|
142
|
+
let lastPathComponent = destinationURL.lastPathComponent
|
|
143
|
+
if lastPathComponent.hasSuffix(".db") && !lastPathComponent.contains("SQLite") {
|
|
144
|
+
let newLastPathComponent = lastPathComponent.replacingOccurrences(of: ".db", with: "SQLite.db")
|
|
145
|
+
let newDestinationURL = dbURL.appendingPathComponent(newLastPathComponent)
|
|
146
|
+
// Check if the destination file already exists and delete it if necessary
|
|
147
|
+
if fileManager.fileExists(atPath: newDestinationURL.path) {
|
|
148
|
+
try fileManager.removeItem(at: newDestinationURL)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try fileManager.moveItem(at: destinationURL, to: newDestinationURL)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return nil
|
|
155
|
+
} catch {
|
|
156
|
+
return error
|
|
118
157
|
}
|
|
119
158
|
}
|
|
120
|
-
|
|
121
|
-
|
|
159
|
+
|
|
160
|
+
class func extractDBFiles(from zipFile: URL, completion: @escaping ([URL], Error?) -> Void) {
|
|
161
|
+
DispatchQueue.global().async(execute: {
|
|
162
|
+
var dbFiles: [URL] = []
|
|
163
|
+
|
|
164
|
+
do {
|
|
165
|
+
let destinationURL = zipFile.deletingLastPathComponent()
|
|
166
|
+
|
|
167
|
+
guard let archive = Archive(url: zipFile, accessMode: .read) else {
|
|
168
|
+
let msg = "Failed in reading Archive"
|
|
169
|
+
completion([], UtilsDownloadError.invalidArchive(message: msg))
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for entry in archive where entry.type == .file {
|
|
174
|
+
let fileURL = destinationURL.appendingPathComponent(entry.path)
|
|
175
|
+
let fileExtension = URL(fileURLWithPath: entry.path).pathExtension
|
|
176
|
+
|
|
177
|
+
if fileExtension == "db" {
|
|
178
|
+
_ = try archive.extract(entry, to: fileURL)
|
|
179
|
+
dbFiles.append(fileURL)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Delete the zip file
|
|
183
|
+
try FileManager.default.removeItem(at: zipFile)
|
|
184
|
+
|
|
185
|
+
completion(dbFiles, nil)
|
|
186
|
+
} catch {
|
|
187
|
+
completion([], error)
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
}
|
|
122
192
|
}
|
|
@@ -569,9 +569,9 @@ class UtilsJson {
|
|
|
569
569
|
let iterations: UInt32 = 10000
|
|
570
570
|
var derivedKeyData = Data(count: keyLength)
|
|
571
571
|
let derivedCount = derivedKeyData.count
|
|
572
|
-
let derivationStatus = derivedKeyData.withUnsafeMutableBytes
|
|
573
|
-
passphraseData.withUnsafeBytes
|
|
574
|
-
salt.withUnsafeBytes
|
|
572
|
+
let derivationStatus = derivedKeyData.withUnsafeMutableBytes({ derivedKeyUnsafeMutableRawBufferPointer in
|
|
573
|
+
passphraseData.withUnsafeBytes({ passphraseUnsafeRawBufferPointer in
|
|
574
|
+
salt.withUnsafeBytes({ saltUnsafeRawBufferPointer in
|
|
575
575
|
CCKeyDerivationPBKDF(
|
|
576
576
|
CCPBKDFAlgorithm(kCCPBKDF2),
|
|
577
577
|
passphraseUnsafeRawBufferPointer.baseAddress,
|
|
@@ -583,9 +583,9 @@ class UtilsJson {
|
|
|
583
583
|
derivedKeyUnsafeMutableRawBufferPointer.baseAddress,
|
|
584
584
|
derivedCount
|
|
585
585
|
)
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
586
|
+
})
|
|
587
|
+
})
|
|
588
|
+
})
|
|
589
589
|
return derivationStatus == kCCSuccess ? derivedKeyData : nil
|
|
590
590
|
}
|
|
591
591
|
}
|
|
@@ -468,7 +468,7 @@ class UtilsSQLCipher {
|
|
|
468
468
|
retMode = "wA\(retMode)"
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
if
|
|
471
|
+
if retMode == "no" || retMode.prefix(2) == "wA" {
|
|
472
472
|
let stmtNames = UtilsSQLStatement
|
|
473
473
|
.getStmtAndRetColNames(sqlStmt: sqlStmt,
|
|
474
474
|
retMode: retMode)
|
|
@@ -845,7 +845,7 @@ class UtilsSQLCipher {
|
|
|
845
845
|
}
|
|
846
846
|
|
|
847
847
|
// MARK: - dbLastId
|
|
848
|
-
|
|
848
|
+
|
|
849
849
|
class func dbLastId(mDB: OpaquePointer?) -> Int64 {
|
|
850
850
|
return Int64(sqlite3_last_insert_rowid(mDB))
|
|
851
851
|
}
|
|
@@ -1015,12 +1015,12 @@ class UtilsSQLCipher {
|
|
|
1015
1015
|
var mRespSet = respSet
|
|
1016
1016
|
if !retResponse.isEmpty {
|
|
1017
1017
|
let keysInArray1 = ["ios_columns"]
|
|
1018
|
-
mRespSet = mRespSet.filter
|
|
1018
|
+
mRespSet = mRespSet.filter({ dict2 in
|
|
1019
1019
|
guard let dict2Key = dict2.keys.first else {
|
|
1020
1020
|
return true // Keep dictionaries without any keys
|
|
1021
1021
|
}
|
|
1022
1022
|
return !keysInArray1.contains(dict2Key)
|
|
1023
|
-
}
|
|
1023
|
+
})
|
|
1024
1024
|
}
|
|
1025
1025
|
retResponse.append(contentsOf: mRespSet)
|
|
1026
1026
|
|