aboutsummaryrefslogtreecommitdiffstats
path: root/Sources/WireGuardApp/UI/TunnelImporter.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Sources/WireGuardApp/UI/TunnelImporter.swift')
-rw-r--r--Sources/WireGuardApp/UI/TunnelImporter.swift94
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?()
+ }
+ }
+ }
+ }
+}