diff options
Diffstat (limited to 'Sources/WireGuardApp/UI/TunnelImporter.swift')
-rw-r--r-- | Sources/WireGuardApp/UI/TunnelImporter.swift | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/Sources/WireGuardApp/UI/TunnelImporter.swift b/Sources/WireGuardApp/UI/TunnelImporter.swift new file mode 100644 index 0000000..65349bc --- /dev/null +++ b/Sources/WireGuardApp/UI/TunnelImporter.swift @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2023 WireGuard LLC. All Rights Reserved. + +import Foundation + +class TunnelImporter { + static func importFromFile(urls: [URL], into tunnelsManager: TunnelsManager, sourceVC: AnyObject?, errorPresenterType: ErrorPresenterProtocol.Type, completionHandler: (() -> Void)? = nil) { + guard !urls.isEmpty else { + completionHandler?() + return + } + let dispatchGroup = DispatchGroup() + var configs = [TunnelConfiguration?]() + var lastFileImportErrorText: (title: String, message: String)? + for url in urls { + if url.pathExtension.lowercased() == "zip" { + dispatchGroup.enter() + ZipImporter.importConfigFiles(from: url) { result in + switch result { + case .failure(let error): + lastFileImportErrorText = error.alertText + case .success(let configsInZip): + configs.append(contentsOf: configsInZip) + } + dispatchGroup.leave() + } + } else { /* if it is not a zip, we assume it is a conf */ + let fileName = url.lastPathComponent + let fileBaseName = url.deletingPathExtension().lastPathComponent.trimmingCharacters(in: .whitespacesAndNewlines) + dispatchGroup.enter() + DispatchQueue.global(qos: .userInitiated).async { + let fileContents: String + do { + fileContents = try String(contentsOf: url) + } catch let error { + DispatchQueue.main.async { + if let cocoaError = error as? CocoaError, cocoaError.isFileError { + lastFileImportErrorText = (title: tr("alertCantOpenInputConfFileTitle"), message: error.localizedDescription) + } else { + lastFileImportErrorText = (title: tr("alertCantOpenInputConfFileTitle"), message: tr(format: "alertCantOpenInputConfFileMessage (%@)", fileName)) + } + configs.append(nil) + dispatchGroup.leave() + } + return + } + var parseError: Error? + var tunnelConfiguration: TunnelConfiguration? + do { + tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: fileContents, called: fileBaseName) + } catch let error { + parseError = error + } + DispatchQueue.main.async { + if parseError != nil { + if let parseError = parseError as? WireGuardAppError { + lastFileImportErrorText = parseError.alertText + } else { + lastFileImportErrorText = (title: tr("alertBadConfigImportTitle"), message: tr(format: "alertBadConfigImportMessage (%@)", fileName)) + } + } + configs.append(tunnelConfiguration) + dispatchGroup.leave() + } + } + } + } + dispatchGroup.notify(queue: .main) { + tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { numberSuccessful, lastAddError in + if !configs.isEmpty && numberSuccessful == configs.count { + completionHandler?() + return + } + let alertText: (title: String, message: String)? + if urls.count == 1 { + if urls.first!.pathExtension.lowercased() == "zip" && !configs.isEmpty { + alertText = (title: tr(format: "alertImportedFromZipTitle (%d)", numberSuccessful), + message: tr(format: "alertImportedFromZipMessage (%1$d of %2$d)", numberSuccessful, configs.count)) + } else { + alertText = lastFileImportErrorText ?? lastAddError?.alertText + } + } else { + alertText = (title: tr(format: "alertImportedFromMultipleFilesTitle (%d)", numberSuccessful), + message: tr(format: "alertImportedFromMultipleFilesMessage (%1$d of %2$d)", numberSuccessful, configs.count)) + } + if let alertText = alertText { + errorPresenterType.showErrorAlert(title: alertText.title, message: alertText.message, from: sourceVC, onPresented: completionHandler) + } else { + completionHandler?() + } + } + } + } +} |