diff --git a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift index 796c030..6e77433 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift @@ -160,20 +160,18 @@ class TunnelsListTableViewController: UIViewController { func importFromFile(url: URL) { guard let tunnelsManager = tunnelsManager else { return } if (url.pathExtension == "zip") { - let zipImporter = ZipImporter(url: url) - let configs: [TunnelConfiguration?] - do { - configs = try zipImporter.importConfigFiles() - } catch (let error) { - ErrorPresenter.showErrorAlert(error: error, from: self) - return - } - tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { [weak self] (numberSuccessful) in - if numberSuccessful == configs.count { + ZipImporter.importConfigFiles(from: url) { (configs, error) in + if let error = error { + ErrorPresenter.showErrorAlert(error: error, from: self) return } - self?.showErrorAlert(title: "Created \(numberSuccessful) tunnels", - message: "Created \(numberSuccessful) of \(configs.count) tunnels from zip archive") + tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { [weak self] (numberSuccessful) in + if numberSuccessful == configs.count { + return + } + self?.showErrorAlert(title: "Created \(numberSuccessful) tunnels", + message: "Created \(numberSuccessful) of \(configs.count) tunnels from zip archive") + } } } else /* if (url.pathExtension == "conf") -- we assume everything else is a conf */ { let fileBaseName = url.deletingPathExtension().lastPathComponent.trimmingCharacters(in: .whitespacesAndNewlines) diff --git a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift index 7ee5c32..4c439d4 100644 --- a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift +++ b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift @@ -8,41 +8,44 @@ enum ZipImporterError: Error { } class ZipImporter { - let url: URL - init(url: URL) { - self.url = url - } + static func importConfigFiles(from url: URL, completion: @escaping ([TunnelConfiguration?], Error?) -> Void) { + DispatchQueue.global(qos: .userInitiated).async { + var unarchivedFiles: [(fileName: String, contents: Data)] + do { + unarchivedFiles = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"]) - func importConfigFiles() throws -> [TunnelConfiguration?] { - var unarchivedFiles: [(fileName: String, contents: Data)] = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"]) + for (i, unarchivedFile) in unarchivedFiles.enumerated().reversed() { + let fileBaseName = URL(string: unarchivedFile.fileName)?.deletingPathExtension().lastPathComponent + if let trimmedName = fileBaseName?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmedName.isEmpty { + unarchivedFiles[i].fileName = trimmedName + } else { + unarchivedFiles.remove(at: i) + } + } - for (i, unarchivedFile) in unarchivedFiles.enumerated().reversed() { - let fileBaseName = URL(string: unarchivedFile.fileName)?.deletingPathExtension().lastPathComponent - if let trimmedName = fileBaseName?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmedName.isEmpty { - unarchivedFiles[i].fileName = trimmedName - } else { - unarchivedFiles.remove(at: i) + if (unarchivedFiles.isEmpty) { + throw ZipImporterError.noTunnelsInZipArchive + } + } catch (let error) { + DispatchQueue.main.async { completion([], error) } + return } + + unarchivedFiles.sort { $0.fileName < $1.fileName } + var configs = Array(repeating: nil, count: unarchivedFiles.count) + for (i, file) in unarchivedFiles.enumerated() { + if (i > 0 && file == unarchivedFiles[i - 1]) { + continue + } + guard let fileContents = String(data: file.contents, encoding: .utf8) else { + continue + } + guard let tunnelConfig = try? WgQuickConfigFileParser.parse(fileContents, name: file.fileName) else { + continue + } + configs[i] = tunnelConfig + } + DispatchQueue.main.async { completion(configs, nil) } } - - if (unarchivedFiles.isEmpty) { - throw ZipImporterError.noTunnelsInZipArchive - } - - unarchivedFiles.sort { $0.fileName < $1.fileName } - var configs = Array(repeating: nil, count: unarchivedFiles.count) - for (i, file) in unarchivedFiles.enumerated() { - if (i > 0 && file == unarchivedFiles[i - 1]) { - continue - } - guard let fileContents = String(data: file.contents, encoding: .utf8) else { - continue - } - guard let tunnelConfig = try? WgQuickConfigFileParser.parse(fileContents, name: file.fileName) else { - continue - } - configs[i] = tunnelConfig - } - return configs } }