diff --git a/WireGuard/AppDelegate.swift b/WireGuard/AppDelegate.swift deleted file mode 100644 index 6380636..0000000 --- a/WireGuard/AppDelegate.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import os.log - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - var appCoordinator: AppCoordinator! - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - - self.window = UIWindow(frame: UIScreen.main.bounds) - appCoordinator = AppCoordinator(window: self.window!) - appCoordinator.start() - - appCoordinator.checkAndCleanConfigs() - - return true - } - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - defer { - do { - try FileManager.default.removeItem(at: url) - } catch { - os_log("Failed to remove item from Inbox: %{public}@", log: Log.general, type: .error, url.absoluteString) - } - } - if url.pathExtension == "conf" { - do { - try appCoordinator.importConfig(config: url) - } catch { - os_log("Unable to import config: %{public}@", log: Log.general, type: .error, url.absoluteString) - return false - } - return true - } else if url.pathExtension == "zip" { - do { - try appCoordinator.importConfigs(configZip: url) - } catch { - os_log("Unable to import config: %{public}@", log: Log.general, type: .error, url.absoluteString) - return false - } - return true - } - return false - - } - - func applicationWillEnterForeground(_ application: UIApplication) { - appCoordinator.checkAndCleanConfigs() - } -} diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/Contents.json b/WireGuard/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 29d9125..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "icon_20pt@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "icon_20pt@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "icon_29pt@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "icon_29pt@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "icon_40pt@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "icon_40pt@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_60pt@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_60pt@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "icon_20pt.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "icon_20pt@2x-1.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "icon_29pt.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "icon_29pt@2x-1.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "icon_40pt.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "icon_40pt@2x-1.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_76pt.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_76pt@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "icon_83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/Icon.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/Icon.png deleted file mode 100644 index 7b0779f..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/Icon.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png deleted file mode 100644 index d12a297..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png deleted file mode 100644 index 7f1668d..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png deleted file mode 100644 index 7f1668d..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png deleted file mode 100644 index 28c67d4..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png deleted file mode 100644 index 8ec8d93..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png deleted file mode 100644 index a7739f5..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png deleted file mode 100644 index ed8332f..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png deleted file mode 100644 index e436f81..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png deleted file mode 100644 index 7f1668d..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png deleted file mode 100644 index d0e7d2c..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png deleted file mode 100644 index bc73ca8..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png deleted file mode 100644 index 410f082..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png deleted file mode 100644 index 410f082..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png deleted file mode 100644 index 4c799aa..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png deleted file mode 100644 index 0565869..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png deleted file mode 100644 index 8c378fd..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png deleted file mode 100644 index f575275..0000000 Binary files a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf b/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf deleted file mode 100644 index 781e309..0000000 Binary files a/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf and /dev/null differ diff --git a/WireGuard/Assets.xcassets/Arrow.imageset/Contents.json b/WireGuard/Assets.xcassets/Arrow.imageset/Contents.json deleted file mode 100644 index 77459c6..0000000 --- a/WireGuard/Assets.xcassets/Arrow.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "Arrow.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/Contents.json b/WireGuard/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/WireGuard/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/settings.imageset/Contents.json b/WireGuard/Assets.xcassets/settings.imageset/Contents.json deleted file mode 100644 index ab3fbb2..0000000 --- a/WireGuard/Assets.xcassets/settings.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "Dots.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/settings.imageset/Dots.pdf b/WireGuard/Assets.xcassets/settings.imageset/Dots.pdf deleted file mode 100644 index c5a2168..0000000 Binary files a/WireGuard/Assets.xcassets/settings.imageset/Dots.pdf and /dev/null differ diff --git a/WireGuard/Assets.xcassets/trash.imageset/Contents.json b/WireGuard/Assets.xcassets/trash.imageset/Contents.json deleted file mode 100644 index af5374f..0000000 --- a/WireGuard/Assets.xcassets/trash.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "ic_action_delete.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "ic_action_delete@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "ic_action_delete@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete.png b/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete.png deleted file mode 100644 index de3dd1c..0000000 Binary files a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png b/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png deleted file mode 100644 index e542a9b..0000000 Binary files a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png b/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png deleted file mode 100644 index 1b6b07c..0000000 Binary files a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png and /dev/null differ diff --git a/WireGuard/Assets.xcassets/wireguard.imageset/Contents.json b/WireGuard/Assets.xcassets/wireguard.imageset/Contents.json deleted file mode 100644 index 6c935c1..0000000 --- a/WireGuard/Assets.xcassets/wireguard.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "wireguard.pdf" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "preserves-vector-representation" : true - } -} \ No newline at end of file diff --git a/WireGuard/Assets.xcassets/wireguard.imageset/wireguard.pdf b/WireGuard/Assets.xcassets/wireguard.imageset/wireguard.pdf deleted file mode 100644 index f404859..0000000 Binary files a/WireGuard/Assets.xcassets/wireguard.imageset/wireguard.pdf and /dev/null differ diff --git a/WireGuard/Base.lproj/LaunchScreen.storyboard b/WireGuard/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 4b77684..0000000 --- a/WireGuard/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WireGuard/Base.lproj/Main.storyboard b/WireGuard/Base.lproj/Main.storyboard deleted file mode 100644 index c9ae86c..0000000 --- a/WireGuard/Base.lproj/Main.storyboard +++ /dev/null @@ -1,1010 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift deleted file mode 100644 index d76470b..0000000 --- a/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension AppCoordinator: QRScanViewControllerDelegate { - func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) { - qrScanViewController.navigationController?.popViewController(animated: true) - showTunnelInfoViewController(tunnel: tunnel, context: tunnel.managedObjectContext!) - saveTunnel(tunnel) - } - - func didCancel(qrScanViewController: QRScanViewController) { - qrScanViewController.navigationController?.popViewController(animated: true) - } -} diff --git a/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift deleted file mode 100644 index 9961043..0000000 --- a/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import PromiseKit -import NetworkExtension - -enum GoVersionCoordinatorError: Error { - case noEnabledSession - case noResponse -} - -extension AppCoordinator: SettingsTableViewControllerDelegate { - func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) { - self.exportConfigs(sourceView: sourceView) - } -} diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift deleted file mode 100644 index 0b96762..0000000 --- a/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate { - func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) { - saveTunnel(tunnel) - } -} diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift deleted file mode 100644 index aa6f3f2..0000000 --- a/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import NetworkExtension - -extension AppCoordinator: TunnelInfoTableViewControllerDelegate { - func connect(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) { - connect(tunnel: tunnel) - } - - func disconnect(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) { - disconnect(tunnel: tunnel) - } - - func status(for tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) -> NEVPNStatus { - let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession - return session?.status ?? .invalid - } - - func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) { - let editContext = persistentContainer.newBackgroundContext() - var backgroundTunnel: Tunnel? - editContext.performAndWait { - backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel - } - - showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext) - } - -} diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift deleted file mode 100644 index 0357c40..0000000 --- a/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import NetworkExtension -import os.log - -import MobileCoreServices - -import ZIPFoundation -import PromiseKit - -extension AppCoordinator: TunnelsTableViewControllerDelegate { - func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus { - let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession - return session?.status ?? .invalid - } - - func addProvider(tunnelsTableViewController: TunnelsTableViewController) { - let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from file or archive", comment: ""), style: .default) { [unowned self] _ in - self.addProviderFromFile() - }) - actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from QR code", comment: ""), style: .default) { [unowned self] _ in - self.addProviderWithQRScan() - }) - actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from scratch", comment: ""), style: .default) { [unowned self] _ in - self.addProviderManually() - }) - actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel)) - - tunnelsTableViewController.present(actionSheet, animated: true, completion: nil) - } - - func addProviderFromFile() { - let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypeZipArchive), "com.wireguard.config.quick"], in: .import) - documentPickerController.delegate = documentPickerDelegateObject - tunnelsTableViewController.present(documentPickerController, animated: true, completion: nil) - } - - func addProviderManually() { - let addContext = persistentContainer.newBackgroundContext() - showTunnelConfigurationViewController(tunnel: nil, context: addContext) - } - - func addProviderWithQRScan() { - let addContext = persistentContainer.newBackgroundContext() - - let qrScanViewController = storyboard.instantiateViewController(type: QRScanViewController.self) - - qrScanViewController.configure(context: addContext, delegate: self) - - self.navigationController.pushViewController(qrScanViewController, animated: true) - } - - func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { - connect(tunnel: tunnel) - } - - func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { - disconnect(tunnel: tunnel) - } - - func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { - showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext) - } - - func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { - if let moc = tunnel.managedObjectContext { - moc.perform { - moc.delete(tunnel) - moc.saveContextToStore() - } - let manager = providerManager(for: tunnel) - manager?.removeFromPreferences { (error) in - if let error = error { - os_log("error removing preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription) - return - } - self.providerManagers?.removeAll { $0 == manager } - os_log("removed preferences", log: Log.general, type: .info) - } - } - } - - func saveTunnel(_ tunnel: Tunnel) { - let manager = providerManager(for: tunnel) ?? NETunnelProviderManager() - manager.localizedDescription = tunnel.title - - let protocolConfiguration = NETunnelProviderProtocol() - protocolConfiguration.providerBundleIdentifier = VPNBUNDLE - protocolConfiguration.serverAddress = (tunnel.peers?.array as? [Peer])?.compactMap { $0.endpoint}.joined(separator: ", ") - protocolConfiguration.providerConfiguration = tunnel.generateProviderConfiguration() - - manager.protocolConfiguration = protocolConfiguration - let connectRule = NEOnDemandRuleConnect() - connectRule.interfaceTypeMatch = .any - manager.onDemandRules = [connectRule] - - manager.saveToPreferences { (error) in - if let error = error { - os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription) - return - } - os_log("saved preferences", log: Log.general, type: .info) - } - - _ = refreshProviderManagers().then { () -> Promise in - self.navigationController.popViewController(animated: true) - return Promise.value(()) - } - } -} diff --git a/WireGuard/Coordinators/AppCoordinator.swift b/WireGuard/Coordinators/AppCoordinator.swift deleted file mode 100644 index aa20c16..0000000 --- a/WireGuard/Coordinators/AppCoordinator.swift +++ /dev/null @@ -1,468 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import NetworkExtension -import os.log -import ZIPFoundation -import PromiseKit - -import CoreData -import BNRCoreDataStack - -import MobileCoreServices - -enum AppCoordinatorError: Error { - case configImportError(msg: String) -} - -extension UINavigationController: Identifyable {} - -let APPGROUP = "group.com.wireguard.ios" -let VPNBUNDLE = "com.wireguard.ios.network-extension" - -class AppCoordinator: RootViewCoordinator { // swiftlint:disable:this type_body_length - - let persistentContainer = NSPersistentContainer(name: "WireGuard") - let storyboard = UIStoryboard(name: "Main", bundle: nil) - var providerManagers: [NETunnelProviderManager]? - let documentPickerDelegateObject: AppDocumentPickerDelegate - - // MARK: - Properties - - var childCoordinators: [Coordinator] = [] - - var rootViewController: UIViewController { - return self.tunnelsTableViewController - } - - var tunnelsTableViewController: TunnelsTableViewController! - - /// Window to manage - let window: UIWindow - - let navigationController: UINavigationController = { - let navController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(type: UINavigationController.self) - return navController - }() - - // MARK: - Init - public init(window: UIWindow) { - self.window = window - - self.window.rootViewController = self.navigationController - self.window.makeKeyAndVisible() - - documentPickerDelegateObject = AppDocumentPickerDelegate() - documentPickerDelegateObject.appCoordinator = self - - NotificationCenter.default.addObserver(self, - selector: #selector(VPNStatusDidChange(notification:)), - name: .NEVPNStatusDidChange, - object: nil) - } - - // MARK: - Functions - - /// Starts the coordinator - public func start() { - _ = refreshProviderManagers().then { () -> Promise in - self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true - self.persistentContainer.loadPersistentStores { [weak self] (_, error) in - if let error = error { - os_log("Unable to load Persistent Store: %{public}@", log: Log.general, type: .error, error.localizedDescription) - } else { - DispatchQueue.main.async { - //start - if let tunnelsTableViewController = self?.storyboard.instantiateViewController(type: TunnelsTableViewController.self) { - self?.tunnelsTableViewController = tunnelsTableViewController - self?.tunnelsTableViewController.viewContext = self?.persistentContainer.viewContext - self?.tunnelsTableViewController.delegate = self - self?.navigationController.viewControllers = [tunnelsTableViewController] - } - } - } - } - return Promise.value(()) - } - } - - func refreshProviderManagers() -> Promise { - return Promise { (resolver) in - NETunnelProviderManager.loadAllFromPreferences { [weak self] (managers, error) in - if let error = error { - os_log("Unable to load provider managers: %{public}@", log: Log.general, type: .error, error.localizedDescription) - } - self?.providerManagers = managers - resolver.fulfill(()) - } - } - } - - func importConfig(config: URL) throws { - do { - try importConfig(configString: try String(contentsOf: config), title: config.deletingPathExtension().lastPathComponent) - } catch { - throw AppCoordinatorError.configImportError(msg: "Failed") - } - } - - func importConfig(configString: String, title: String) throws { - do { - let addContext = persistentContainer.newBackgroundContext() - let tunnel = try Tunnel.fromConfig(configString, context: addContext) - tunnel.title = title - addContext.saveContext() - self.saveTunnel(tunnel) - } catch { - throw AppCoordinatorError.configImportError(msg: "Failed") - } - } - - func importConfigs(configZip: URL) throws { - if let archive = Archive(url: configZip, accessMode: .read) { - for entry in archive { - var entryData = Data(capacity: 0) - _ = try archive.extract(entry) { (data) in - entryData.append(data) - } - if let config = String(data: entryData, encoding: .utf8) { - try importConfig(configString: config, title: entry.path) - } - } - } - } - - func checkAndCleanConfigs() { - _ = refreshProviderManagers().then { () -> Promise in - guard let providerManagers = self.providerManagers else { - return Promise.value(()) - } - let tunnels = try Tunnel.allInContext(self.persistentContainer.viewContext) - let tunnelIdentifiers = tunnels.compactMap {$0.tunnelIdentifier} - - let unknownManagers = providerManagers.filter { - guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else { - return false - } - guard let candidateTunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else { - return false - } - - return !tunnelIdentifiers.contains(candidateTunnelIdentifier) - } - - let deletionPromises = unknownManagers.map({ (manager) -> Promise in - return Promise(resolver: { resolver in - return manager.removeFromPreferences(completionHandler: { (error) in - if let error = error { - resolver.reject(error) - } else { - resolver.fulfill(manager) - } - }) - }) - }) - - return when(resolved: deletionPromises).asVoid() - - } - } - - // swiftlint:disable next function_body_length - func exportConfigs(sourceView: UIView) { - guard let path = FileManager.default - .urls(for: .documentDirectory, in: .userDomainMask).first else { - return - } - let saveFileURL = path.appendingPathComponent("wireguard-export.zip") - do { - try FileManager.default.removeItem(at: saveFileURL) - } catch { - os_log("Failed to delete file: %{public}@ : %{public}@", log: Log.general, type: .error, saveFileURL.absoluteString, error.localizedDescription) - } - - guard let archive = Archive(url: saveFileURL, accessMode: .create) else { - return - } - - do { - var tunnelsByTitle = [String: [Tunnel]]() - let tunnels = try Tunnel.allInContext(persistentContainer.viewContext) - tunnels.forEach { - guard let title = $0.title ?? $0.tunnelIdentifier else { - // there is always a tunnelidentifier. - return - } - if let tunnels = tunnelsByTitle[title] { - tunnelsByTitle[title] = tunnels + [$0] - } else { - tunnelsByTitle[title] = [$0] - } - } - - func addEntry(title: String, tunnel: Tunnel) throws { - let data = tunnel.export().data(using: .utf8)! - let byteCount: UInt32 = UInt32(data.count) - try archive.addEntry(with: "\(title).conf", type: .file, uncompressedSize: byteCount, provider: { (position, size) -> Data in - return data.subdata(in: position ..< size) - }) - } - - try tunnelsByTitle.keys.forEach { - if let tunnels = tunnelsByTitle[$0] { - if tunnels.count == 1 { - try addEntry(title: $0, tunnel: tunnels[0]) - } else { - for (index, tunnel) in tunnels.enumerated() { - try addEntry(title: $0 + "-\(index + 1)", tunnel: tunnel) - } - } - } - } - } catch { - os_log("Failed to create archive file: %{public}@ : %{public}@", log: Log.general, type: .error, saveFileURL.absoluteString, error.localizedDescription) - return - } - - let activityViewController = UIActivityViewController( - activityItems: [saveFileURL], - applicationActivities: nil) - if let popoverPresentationController = activityViewController.popoverPresentationController { - popoverPresentationController.sourceView = sourceView - } - navigationController.present(activityViewController, animated: true) { - } - } - - func exportConfig(tunnel: Tunnel, barButtonItem: UIBarButtonItem) { - let exportString = tunnel.export() - - guard let path = FileManager.default - .urls(for: .documentDirectory, in: .userDomainMask).first else { - return - } - let saveFileURL = path.appendingPathComponent("/\(tunnel.title ?? "wireguard").conf") - do { - try exportString.write(to: saveFileURL, atomically: true, encoding: .utf8) - } catch { - os_log("Failed to export tunnel to: %{public}@", log: Log.general, type: .error, saveFileURL.absoluteString) - return - } - - let activityViewController = UIActivityViewController( - activityItems: [saveFileURL], - applicationActivities: nil) - if let popoverPresentationController = activityViewController.popoverPresentationController { - popoverPresentationController.barButtonItem = barButtonItem - } - self.navigationController.present(activityViewController, animated: true) { - } - } - - // MARK: - NEVPNManager handling - - @objc private func VPNStatusDidChange(notification: NSNotification) { - guard let session = notification.object as? NETunnelProviderSession else { - return - } - - guard let prot = session.manager.protocolConfiguration as? NETunnelProviderProtocol else { - return - } - - guard let changedTunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else { - return - } - - providerManagers?.first(where: { (manager) -> Bool in - guard let prot = manager.protocolConfiguration as? NETunnelProviderProtocol else { - return false - } - guard let candidateTunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else { - return false - } - - return changedTunnelIdentifier == candidateTunnelIdentifier - - })?.loadFromPreferences(completionHandler: { [weak self] (_) in - self?.tunnelsTableViewController.updateStatus(for: changedTunnelIdentifier) - }) - } - - func showTunnelInfoViewController(tunnel: Tunnel, context: NSManagedObjectContext) { - let tunnelInfoViewController = storyboard.instantiateViewController(type: TunnelInfoTableViewController.self) - - tunnelInfoViewController.configure(context: context, delegate: self, tunnel: tunnel) - - self.navigationController.pushViewController(tunnelInfoViewController, animated: true) - } - - func showTunnelConfigurationViewController(tunnel: Tunnel?, context: NSManagedObjectContext) { - let tunnelConfigurationViewController = storyboard.instantiateViewController(type: TunnelConfigurationTableViewController.self) - - tunnelConfigurationViewController.configure(context: context, delegate: self, tunnel: tunnel) - - self.navigationController.pushViewController(tunnelConfigurationViewController, animated: true) - } - - func showSettings() { - let settingsTableViewController = storyboard.instantiateViewController(type: SettingsTableViewController.self) - - settingsTableViewController.delegate = self - - self.navigationController.pushViewController(settingsTableViewController, animated: true) - } - - public func showError(_ error: Error) { - showAlert(title: NSLocalizedString("Error", comment: "Error alert title"), message: error.localizedDescription) - } - - func connect(tunnel: Tunnel) { - _ = refreshProviderManagers().then { () -> Promise in - guard let manager = self.providerManager(for: tunnel) else { - return Promise.value(()) - } - let block = { - switch manager.connection.status { - case .invalid, .disconnected: - os_log("connect tunnel: %{public}@", log: Log.general, type: .info, tunnel.description) - // Should the manager be enabled? - - let manager = self.providerManager(for: tunnel) - manager?.isEnabled = true - manager?.saveToPreferences { (error) in - if let error = error { - os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription) - return - } - os_log("saved preferences", log: Log.general, type: .info) - - let session = manager?.connection as! NETunnelProviderSession //swiftlint:disable:this force_cast - do { - try session.startTunnel() - } catch let error { - os_log("error starting tunnel: %{public}@", log: Log.general, type: .error, error.localizedDescription) - } - } - - default: - break - } - } - - if manager.connection.status == .invalid { - manager.loadFromPreferences { (_) in - block() - } - } else { - block() - } - - return Promise.value(()) - } - } - - func disconnect(tunnel: Tunnel) { - _ = refreshProviderManagers().then { () -> Promise in - let manager = self.providerManager(for: tunnel)! - let block = { - switch manager.connection.status { - case .connected, .connecting: - let manager = self.providerManager(for: tunnel) - manager?.connection.stopVPNTunnel() - default: - break - } - } - - if manager.connection.status == .invalid { - manager.loadFromPreferences { (_) in - block() - } - } else { - block() - } - return Promise.value(()) - } - } - - private func showAlert(title: String, message: String) { - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "OK button"), style: .default)) - self.navigationController.present(alert, animated: true) - } - - func providerManager(for tunnel: Tunnel) -> NETunnelProviderManager? { - return self.providerManagers?.first { - guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else { - return false - } - guard let tunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else { - return false - } - return tunnelIdentifier == tunnel.tunnelIdentifier - } - } - - func extensionGoVersionInformation() -> Promise { - return Promise(resolver: { (resolver) in - guard let session = self.providerManagers?.first(where: { $0.isEnabled })?.connection as? NETunnelProviderSession else { - resolver.reject(GoVersionCoordinatorError.noEnabledSession) - return - } - do { - try session.sendProviderMessage(ExtensionMessage.requestVersion.data, responseHandler: { (data) in - guard let data = data, let responseString = String(data: data, encoding: .utf8) else { - resolver.reject(GoVersionCoordinatorError.noResponse) - return - } - resolver.fulfill(responseString) - }) - } catch { - resolver.reject(error) - } - }) - } -} - -class AppDocumentPickerDelegate: NSObject, UIDocumentPickerDelegate { - weak var appCoordinator: AppCoordinator? - - func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { - if url.pathExtension == "conf" { - do { - try appCoordinator?.importConfig(config: url) - } catch { - os_log("Unable to import config: %{public}@", log: Log.general, type: .error, url.absoluteString) - } - } else if url.pathExtension == "zip" { - do { - try appCoordinator?.importConfigs(configZip: url) - } catch { - os_log("Unable to import config: %{public}@", log: Log.general, type: .error, url.absoluteString) - } - } - - } -} - -extension NEVPNStatus { - var statusDescription: String { - switch self { - case .connected: - return "Connected" - case .connecting: - return "Connecting" - case .disconnected: - return "Disconnected" - case .disconnecting: - return "Disconnecting" - case .invalid: - return "Invalid" - case .reasserting: - return "Reasserting" - } - } -} diff --git a/WireGuard/Coordinators/Coordinator.swift b/WireGuard/Coordinators/Coordinator.swift deleted file mode 100644 index d4263fc..0000000 --- a/WireGuard/Coordinators/Coordinator.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -/// The Coordinator protocol -public protocol Coordinator: class { - - /// Starts the coordinator - func start() - - /// The array containing any child Coordinators - var childCoordinators: [Coordinator] { get set } - -} - -public extension Coordinator { - - /// Add a child coordinator to the parent - public func addChildCoordinator(_ childCoordinator: Coordinator) { - self.childCoordinators.append(childCoordinator) - } - - /// Remove a child coordinator from the parent - public func removeChildCoordinator(_ childCoordinator: Coordinator) { - self.childCoordinators = self.childCoordinators.filter { $0 !== childCoordinator } - } - -} diff --git a/WireGuard/Coordinators/RootCoordinator.swift b/WireGuard/Coordinators/RootCoordinator.swift deleted file mode 100644 index 79ca0ad..0000000 --- a/WireGuard/Coordinators/RootCoordinator.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import UIKit - -public protocol RootViewControllerProvider: class { - // The coordinators 'rootViewController'. It helps to think of this as the view - // controller that can be used to dismiss the coordinator from the view hierarchy. - var rootViewController: UIViewController { get } -} - -/// A Coordinator type that provides a root UIViewController -public typealias RootViewCoordinator = Coordinator & RootViewControllerProvider diff --git a/WireGuard/Crypto/x25519.c b/WireGuard/Crypto/x25519.c deleted file mode 100644 index 6569e11..0000000 --- a/WireGuard/Crypto/x25519.c +++ /dev/null @@ -1,177 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ - * - * Copyright (C) 2015-2018 WireGuard LLC. All Rights Reserved. - * - * Curve25519 ECDH functions, based on TweetNaCl but cleaned up. - */ - -#include -#include -#include - -#include "x25519.h" - -typedef int64_t fe[16]; - -static inline void carry(fe o) -{ - int i; - - for (i = 0; i < 16; ++i) { - o[(i + 1) % 16] += (i == 15 ? 38 : 1) * (o[i] >> 16); - o[i] &= 0xffff; - } -} - -static inline void cswap(fe p, fe q, int b) -{ - int i; - int64_t t, c = ~(b - 1); - - for (i = 0; i < 16; ++i) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -static inline void pack(uint8_t *o, const fe n) -{ - int i, j, b; - fe m, t; - - memcpy(t, n, sizeof(t)); - carry(t); - carry(t); - carry(t); - for (j = 0; j < 2; ++j) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; ++i) { - m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); - m[i - 1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); - b = (m[15] >> 16) & 1; - m[14] &= 0xffff; - cswap(t, m, 1 - b); - } - for (i = 0; i < 16; ++i) { - o[2 * i] = t[i] & 0xff; - o[2 * i + 1] = t[i] >> 8; - } -} - -static inline void unpack(fe o, const uint8_t *n) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = n[2 * i] + ((int64_t)n[2 * i + 1] << 8); - o[15] &= 0x7fff; -} - -static inline void add(fe o, const fe a, const fe b) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = a[i] + b[i]; -} - -static inline void subtract(fe o, const fe a, const fe b) -{ - int i; - - for (i = 0; i < 16; ++i) - o[i] = a[i] - b[i]; -} - -static inline void multmod(fe o, const fe a, const fe b) -{ - int i, j; - int64_t t[31] = { 0 }; - - for (i = 0; i < 16; ++i) { - for (j = 0; j < 16; ++j) - t[i + j] += a[i] * b[j]; - } - for (i = 0; i < 15; ++i) - t[i] += 38 * t[i + 16]; - memcpy(o, t, sizeof(fe)); - carry(o); - carry(o); -} - -static inline void invert(fe o, const fe i) -{ - fe c; - int a; - - memcpy(c, i, sizeof(c)); - for (a = 253; a >= 0; --a) { - multmod(c, c, c); - if (a != 2 && a != 4) - multmod(c, c, i); - } - memcpy(o, c, sizeof(fe)); -} - -static void curve25519_shared_secret(uint8_t shared_secret[32], const uint8_t private_key[32], const uint8_t public_key[32]) -{ - static const fe a24 = { 0xdb41, 1 }; - uint8_t z[32]; - int64_t r; - int i; - fe a = { 1 }, b, c = { 0 }, d = { 1 }, e, f, x; - - memcpy(z, private_key, sizeof(z)); - - z[31] = (z[31] & 127) | 64; - z[0] &= 248; - - unpack(x, public_key); - memcpy(b, x, sizeof(b)); - - for (i = 254; i >= 0; --i) { - r = (z[i >> 3] >> (i & 7)) & 1; - cswap(a, b, (int)r); - cswap(c, d, (int)r); - add(e, a, c); - subtract(a, a, c); - add(c, b, d); - subtract(b, b, d); - multmod(d, e, e); - multmod(f, a, a); - multmod(a, c, a); - multmod(c, b, e); - add(e, a, c); - subtract(a, a, c); - multmod(b, a, a); - subtract(c, d, f); - multmod(a, c, a24); - add(a, a, d); - multmod(c, c, a); - multmod(a, d, f); - multmod(d, b, x); - multmod(b, e, e); - cswap(a, b, (int)r); - cswap(c, d, (int)r); - } - invert(c, c); - multmod(a, a, c); - pack(shared_secret, a); -} - -void curve25519_derive_public_key(uint8_t public_key[32], const uint8_t private_key[32]) -{ - static const uint8_t basepoint[32] = { 9 }; - - curve25519_shared_secret(public_key, private_key, basepoint); -} - -void curve25519_generate_private_key(uint8_t private_key[32]) -{ - CCRandomGenerateBytes(private_key, 32); - private_key[31] = (private_key[31] & 127) | 64; - private_key[0] &= 248; -} diff --git a/WireGuard/Crypto/x25519.h b/WireGuard/Crypto/x25519.h deleted file mode 100644 index 7d8440d..0000000 --- a/WireGuard/Crypto/x25519.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef X25519_H -#define X25519_H - -void curve25519_derive_public_key(unsigned char public_key[32], const unsigned char private_key[32]); -void curve25519_generate_private_key(unsigned char private_key[32]); - -#endif diff --git a/WireGuard/CustomViews/CopyableLabel.swift b/WireGuard/CustomViews/CopyableLabel.swift deleted file mode 100644 index 1bca7e3..0000000 --- a/WireGuard/CustomViews/CopyableLabel.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit - -@IBDesignable -class CopyableLabel: UILabel { - override func awakeFromNib() { - super.awakeFromNib() - let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:))) - self.addGestureRecognizer(gestureRecognizer) - self.isUserInteractionEnabled = true - } - - // MARK: - UIGestureRecognizer - @objc func handleTapGesture(_ recognizer: UIGestureRecognizer) { - guard recognizer.state == .recognized else { return } - - if let recognizerView = recognizer.view, - let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder() { - let menuController = UIMenuController.shared - menuController.setTargetRect(recognizerView.frame, in: recognizerSuperView) - menuController.setMenuVisible(true, animated: true) - } - } - - override var canBecomeFirstResponder: Bool { - return true - } - - override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { - return (action == #selector(UIResponderStandardEditActions.copy(_:))) - - } - - override func copy(_ sender: Any?) { - UIPasteboard.general.string = text - } -} diff --git a/WireGuard/Extensions/String+Arrays.swift b/WireGuard/Extensions/String+Arrays.swift deleted file mode 100644 index b142202..0000000 --- a/WireGuard/Extensions/String+Arrays.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension String { - - static func commaSeparatedStringFrom(elements: [String]) -> String { - return elements.joined(separator: ",") - } - - func commaSeparatedToArray() -> [String] { - return components(separatedBy: .whitespaces) - .joined() - .split(separator: ",") - .map(String.init) - } - -} diff --git a/WireGuard/Extensions/String+Base64.swift b/WireGuard/Extensions/String+Base64.swift deleted file mode 100644 index ae70010..0000000 --- a/WireGuard/Extensions/String+Base64.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension String { - - func isBase64() -> Bool { - let base64Predicate = NSPredicate(format: "SELF MATCHES %@", "^[a-zA-Z0-9+/]{43}=$") - return base64Predicate.evaluate(with: self) - } - -} diff --git a/WireGuard/Info.plist b/WireGuard/Info.plist deleted file mode 100644 index 842a2a2..0000000 --- a/WireGuard/Info.plist +++ /dev/null @@ -1,173 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - conf - - CFBundleTypeIconFiles - - icon_20pt - icon_20pt@3x - icon_60pt@3x - - CFBundleTypeName - WireGuard configuration - CFBundleTypeRole - Viewer - LSHandlerRank - Owner - LSItemContentTypes - - com.wireguard.config.quick - - - - CFBundleTypeExtensions - - zip - - CFBundleTypeIconFile - zip - CFBundleTypeIconFiles - - CFBundleTypeMIMETypes - - application/zip - application/x-zip - application/x-zip-compressed - - CFBundleTypeName - WireGuard Config Zip - CFBundleTypeOSTypes - - ZIP - - CFBundleTypeRole - Viewer - LSItemContentTypes - - com.pkware.zip-archive - - - - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - WireGuardGoVersion - unknown - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - auto-generated - LSRequiresIPhoneOS - - LSSupportsOpeningDocumentsInPlace - - NSCameraUsageDescription - Camera is used to scan QR codes - UIFileSharingEnabled - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarStyle - UIStatusBarStyleLightContent - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - UTExportedTypeDeclarations - - - UTTypeConformsTo - - public.data - - UTTypeDescription - WireGuard configuration - UTTypeIconFiles - - icon_20pt@3x - icon_60pt@3x - - UTTypeIdentifier - com.wireguard.config.quick - UTTypeTagSpecification - - public.filename-extension - conf - - - - UTImportedTypeDeclarations - - - UTTypeConformsTo - - com.pkware.zip-archive - - UTTypeDescription - WireGuard configuration - UTTypeIconFiles - - icon_20pt@3x - icon_60pt@3x - - UTTypeIdentifier - com.wireguard.config.quick - UTTypeTagSpecification - - public.filename-extension - conf - - - - UTTypeConformsTo - - public.data - - UTTypeDescription - WireGuard configurations - UTTypeIconFiles - - icon_20pt.png - icon_60pt@3x.png - - UTTypeIdentifier - com.wireguard.config.quick.confs - public.filename-extension - zip - - - - diff --git a/WireGuard/Log.swift b/WireGuard/Log.swift deleted file mode 100644 index 7472934..0000000 --- a/WireGuard/Log.swift +++ /dev/null @@ -1,9 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import os.log - -struct Log { - static var general = OSLog(subsystem: "com.wireguard.ios", category: "general") -} diff --git a/WireGuard/Models/Attribute.swift b/WireGuard/Models/Attribute.swift deleted file mode 100644 index 61e7246..0000000 --- a/WireGuard/Models/Attribute.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -struct Attribute { - - enum Key: String, CaseIterable { - case address = "Address" - case allowedIPs = "AllowedIPs" - case dns = "DNS" - case endpoint = "Endpoint" - case listenPort = "ListenPort" - case mtu = "MTU" - case persistentKeepalive = "PersistentKeepalive" - case presharedKey = "PresharedKey" - case privateKey = "PrivateKey" - case publicKey = "PublicKey" - } - - private static let separatorPattern = (try? NSRegularExpression(pattern: "\\s|=", options: []))! - - let line: String - let key: Key - let stringValue: String - var arrayValue: [String] { - return stringValue.commaSeparatedToArray() - } - - static func match(line: String) -> Attribute? { - guard let equalsIndex = line.firstIndex(of: "=") else { return nil } - let keyString = line[.. NSFetchRequest { - return NSFetchRequest(entityName: "Interface") - } - - @NSManaged public var addresses: String? - @NSManaged public var listenPort: Int16 - @NSManaged public var privateKey: String? - @NSManaged public var mtu: Int32 - @NSManaged public var dns: String? - @NSManaged public var tunnel: Tunnel? - -} - -// MARK: Generated accessors for adresses -extension Interface { -} diff --git a/WireGuard/Models/Interface+Extension.swift b/WireGuard/Models/Interface+Extension.swift deleted file mode 100644 index 848f29e..0000000 --- a/WireGuard/Models/Interface+Extension.swift +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension Interface { - - var publicKey: String? { - if let privateKeyString = privateKey, let privateKey = Data(base64Encoded: privateKeyString) { - var publicKey = Data(count: 32) - privateKey.withUnsafeBytes({ (privateKeyBytes) -> Void in - publicKey.withUnsafeMutableBytes({ (mutableBytes) -> Void in - curve25519_derive_public_key(mutableBytes, privateKeyBytes) - }) - }) - return publicKey.base64EncodedString() - } else { - return nil - } - } - - func validate() throws { - guard let privateKey = privateKey, !privateKey.isEmpty else { - throw InterfaceValidationError.emptyPrivateKey - } - - guard privateKey.isBase64() else { - throw InterfaceValidationError.invalidPrivateKey - } - - try addresses?.commaSeparatedToArray().forEach { address in - do { - try _ = CIDRAddress(stringRepresentation: address) - } catch { - throw InterfaceValidationError.invalidAddress(cause: error) - } - } - - try dns?.commaSeparatedToArray().forEach { address in - do { - try _ = Endpoint(endpointString: address, needsPort: false) - } catch { - throw InterfaceValidationError.invalidDNSServer(cause: error) - } - } - } - - func parse(attribute: Attribute) throws { - switch attribute.key { - case .address: - addresses = attribute.stringValue - case .dns: - dns = attribute.stringValue - case .listenPort: - if let port = Int16(attribute.stringValue) { - listenPort = port - } - case .mtu: - if let mtu = Int32(attribute.stringValue) { - self.mtu = mtu - } - case .privateKey: - privateKey = attribute.stringValue - default: - throw TunnelParseError.invalidLine(attribute.line) - } - } - - func export() -> String { - var exportString = "[Interface]\n" - if let privateKey = privateKey { - exportString.append("PrivateKey=\(privateKey)\n") - } - if let addresses = addresses { - exportString.append("Address=\(addresses)\n") - } - if let dns = dns { - exportString.append("DNS=\(dns)\n") - } - if mtu > 0 { - exportString.append("MTU=\(mtu)\n") - } - if listenPort > 0 { - exportString.append("ListenPort=\(listenPort)\n") - } - - exportString.append("\n") - - return exportString - } - -} - -enum InterfaceValidationError: Error { - case emptyPrivateKey - case invalidPrivateKey - case invalidAddress(cause: Error) - case invalidDNSServer(cause: Error) -} diff --git a/WireGuard/Models/Peer+CoreDataClass.swift b/WireGuard/Models/Peer+CoreDataClass.swift deleted file mode 100644 index d8c4664..0000000 --- a/WireGuard/Models/Peer+CoreDataClass.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -@objc(Peer) -public class Peer: NSManagedObject { - -} diff --git a/WireGuard/Models/Peer+CoreDataProperties.swift b/WireGuard/Models/Peer+CoreDataProperties.swift deleted file mode 100644 index 50132e7..0000000 --- a/WireGuard/Models/Peer+CoreDataProperties.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -extension Peer { - - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "Peer") - } - - @NSManaged public var publicKey: String? - @NSManaged public var presharedKey: String? - @NSManaged public var allowedIPs: String? - @NSManaged public var endpoint: String? - @NSManaged public var persistentKeepalive: Int32 - @NSManaged public var tunnel: Tunnel? - -} diff --git a/WireGuard/Models/Peer+Extension.swift b/WireGuard/Models/Peer+Extension.swift deleted file mode 100644 index 4472b0c..0000000 --- a/WireGuard/Models/Peer+Extension.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -extension Peer { - - func validate() throws { - guard let publicKey = publicKey, !publicKey.isEmpty else { - throw PeerValidationError.emptyPublicKey - } - - guard publicKey.isBase64() else { - throw PeerValidationError.invalidPublicKey - } - - guard let allowedIPs = allowedIPs, !allowedIPs.isEmpty else { - throw PeerValidationError.nilAllowedIps - } - - try allowedIPs.commaSeparatedToArray().forEach { address in - do { - try _ = CIDRAddress(stringRepresentation: address) - } catch { - throw PeerValidationError.invalidAllowedIPs(cause: error) - } - } - - if let endpoint = endpoint { - do { - try _ = Endpoint(endpointString: endpoint) - } catch { - throw PeerValidationError.invalidEndpoint(cause: error) - } - } - - guard persistentKeepalive >= 0, persistentKeepalive <= 65535 else { - throw PeerValidationError.invalidPersistedKeepAlive - } - } - - func parse(attribute: Attribute) throws { - switch attribute.key { - case .allowedIPs: - allowedIPs = attribute.stringValue - case .endpoint: - endpoint = attribute.stringValue - case .persistentKeepalive: - if let keepAlive = Int32(attribute.stringValue) { - persistentKeepalive = keepAlive - } - case .presharedKey: - presharedKey = attribute.stringValue - case .publicKey: - publicKey = attribute.stringValue - default: - throw TunnelParseError.invalidLine(attribute.line) - } - } - - func export() -> String { - var exportString = "[Peer]\n" - if let publicKey = publicKey { - exportString.append("PublicKey=\(publicKey)\n") - } - if let presharedKey = presharedKey { - exportString.append("PresharedKey=\(presharedKey)\n") - } - if let allowedIPs = allowedIPs { - exportString.append("AllowedIPs=\(allowedIPs)\n") - } - if let endpoint = endpoint { - exportString.append("Endpoint=\(endpoint)\n") - } - if persistentKeepalive > 0 { - exportString.append("PersistentKeepalive=\(persistentKeepalive)\n") - } - - exportString.append("\n") - - return exportString - } - -} - -enum PeerValidationError: Error { - case emptyPublicKey - case invalidPublicKey - case nilAllowedIps - case invalidAllowedIPs(cause: Error) - case invalidEndpoint(cause: Error) - case invalidPersistedKeepAlive -} diff --git a/WireGuard/Models/Tunnel+CoreDataClass.swift b/WireGuard/Models/Tunnel+CoreDataClass.swift deleted file mode 100644 index f26d33c..0000000 --- a/WireGuard/Models/Tunnel+CoreDataClass.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -@objc(Tunnel) -public class Tunnel: NSManagedObject { - -} diff --git a/WireGuard/Models/Tunnel+CoreDataProperties.swift b/WireGuard/Models/Tunnel+CoreDataProperties.swift deleted file mode 100644 index 2bfad02..0000000 --- a/WireGuard/Models/Tunnel+CoreDataProperties.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -extension Tunnel { - - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "Tunnel") - } - - @NSManaged public var tunnelIdentifier: String? - @NSManaged public var title: String? - @NSManaged public var interface: Interface? - @NSManaged public var peers: NSOrderedSet? - -} - -// MARK: Generated accessors for peers -extension Tunnel { - - @objc(insertObject:inPeersAtIndex:) - @NSManaged public func insertIntoPeers(_ value: Peer, at idx: Int) - - @objc(removeObjectFromPeersAtIndex:) - @NSManaged public func removeFromPeers(at idx: Int) - - @objc(insertPeers:atIndexes:) - @NSManaged public func insertIntoPeers(_ values: [Peer], at indexes: NSIndexSet) - - @objc(removePeersAtIndexes:) - @NSManaged public func removeFromPeers(at indexes: NSIndexSet) - - @objc(replaceObjectInPeersAtIndex:withObject:) - @NSManaged public func replacePeers(at idx: Int, with value: Peer) - - @objc(replacePeersAtIndexes:withPeers:) - @NSManaged public func replacePeers(at indexes: NSIndexSet, with values: [Peer]) - - @objc(addPeersObject:) - @NSManaged public func addToPeers(_ value: Peer) - - @objc(removePeersObject:) - @NSManaged public func removeFromPeers(_ value: Peer) - - @objc(addPeers:) - @NSManaged public func addToPeers(_ values: NSOrderedSet) - - @objc(removePeers:) - @NSManaged public func removeFromPeers(_ values: NSOrderedSet) - -} diff --git a/WireGuard/Models/Tunnel+Extension.swift b/WireGuard/Models/Tunnel+Extension.swift deleted file mode 100644 index 99271a1..0000000 --- a/WireGuard/Models/Tunnel+Extension.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -extension Tunnel { - public func generateProviderConfiguration() -> [String: Any] { - var providerConfiguration = [String: Any]() - - providerConfiguration[PCKeys.title.rawValue] = self.title - providerConfiguration[PCKeys.tunnelIdentifier.rawValue] = self.tunnelIdentifier - providerConfiguration[PCKeys.endpoints.rawValue] = peers?.array.compactMap {($0 as? Peer)?.endpoint}.joined(separator: ", ") - providerConfiguration[PCKeys.dns.rawValue] = interface?.dns - providerConfiguration[PCKeys.addresses.rawValue] = interface?.addresses - if let mtu = interface?.mtu, mtu > 0 { - providerConfiguration[PCKeys.mtu.rawValue] = NSNumber(value: mtu) - } - - var settingsString = "replace_peers=true\n" - if let interface = interface { - settingsString += generateInterfaceProviderConfiguration(interface) - } - - if let peers = peers?.array as? [Peer] { - peers.forEach { - settingsString += generatePeerProviderConfiguration($0) - } - - } - - providerConfiguration["settings"] = settingsString - - return providerConfiguration - } - - private func generateInterfaceProviderConfiguration(_ interface: Interface) -> String { - var settingsString = "" - - if let hexPrivateKey = base64KeyToHex(interface.privateKey) { - settingsString += "private_key=\(hexPrivateKey)\n" - } - if interface.listenPort > 0 { - settingsString += "listen_port=\(interface.listenPort)\n" - } - if interface.mtu > 0 { - settingsString += "mtu=\(interface.mtu)\n" - } - - return settingsString - } - - private func generatePeerProviderConfiguration(_ peer: Peer) -> String { - var settingsString = "" - - if let hexPublicKey = base64KeyToHex(peer.publicKey) { - settingsString += "public_key=\(hexPublicKey)\n" - } - if let presharedKey = peer.presharedKey { - settingsString += "preshared_key=\(presharedKey)\n" - } - if let endpoint = peer.endpoint { - settingsString += "endpoint=\(endpoint)\n" - } - if peer.persistentKeepalive > 0 { - settingsString += "persistent_keepalive_interval=\(peer.persistentKeepalive)\n" - } - if let allowedIPs = peer.allowedIPs?.commaSeparatedToArray() { - allowedIPs.forEach { - settingsString += "allowed_ip=\($0.trimmingCharacters(in: .whitespaces))\n" - } - } - - return settingsString - } - - func validate() throws { - let nameRegex = "[a-zA-Z0-9_=+.-]{1,15}" - let nameTest = NSPredicate(format: "SELF MATCHES %@", nameRegex) - guard let title = title, nameTest.evaluate(with: title) else { - throw TunnelValidationError.invalidTitle - } - - let fetchRequest: NSFetchRequest = Tunnel.fetchRequest() - fetchRequest.predicate = NSPredicate(format: "title == %@", title) - guard (try? managedObjectContext?.count(for: fetchRequest)) == 1 else { - throw TunnelValidationError.titleExists - } - - guard let interface = interface else { - throw TunnelValidationError.nilInterface - } - - try interface.validate() - - guard let peers = peers else { - throw TunnelValidationError.nilPeers - } - - try peers.forEach { - guard let peer = $0 as? Peer else { - throw TunnelValidationError.invalidPeer - } - - try peer.validate() - } - } - - static func fromConfig(_ text: String, context: NSManagedObjectContext) throws -> Tunnel { - let lines = text.split(separator: "\n") - - var currentPeer: Peer? - var isInInterfaceSection = false - - var tunnel: Tunnel! - context.performAndWait { - tunnel = Tunnel(context: context) - tunnel.interface = Interface(context: context) - } - tunnel.tunnelIdentifier = UUID().uuidString - - for line in lines { - var trimmedLine: String - if let commentRange = line.range(of: "#") { - trimmedLine = String(line[.. 0 else { continue } - - if "[interface]" == line.lowercased() { - currentPeer = nil - isInInterfaceSection = true - } else if "[peer]" == line.lowercased() { - context.performAndWait { currentPeer = Peer(context: context) } - tunnel.insertIntoPeers(currentPeer!, at: tunnel.peers?.count ?? 0) - isInInterfaceSection = false - } else if isInInterfaceSection, let attribute = Attribute.match(line: String(line)) { - try tunnel.interface!.parse(attribute: attribute) - } else if let currentPeer = currentPeer, let attribute = Attribute.match(line: String(line)) { - try currentPeer.parse(attribute: attribute) - } else { - throw TunnelParseError.invalidLine(String(line)) - } - } - - if !isInInterfaceSection && currentPeer == nil { - throw TunnelParseError.noConfigInfo - } - - return tunnel - } - - func export() -> String { - var exportString = "" - if let interfaceExport = self.interface?.export() { - exportString.append(interfaceExport) - } - - if let peers = peers?.array as? [Peer] { - peers.forEach { - exportString.append($0.export()) - } - } - - return exportString - } - -} - -private func base64KeyToHex(_ base64: String?) -> String? { - guard let base64 = base64 else { - return nil - } - - guard base64.count == 44 else { - return nil - } - - guard base64.last == "=" else { - return nil - } - - guard let keyData = Data(base64Encoded: base64) else { - return nil - } - - guard keyData.count == 32 else { - return nil - } - - let hexKey = keyData.reduce("") {$0 + String(format: "%02x", $1)} - - return hexKey -} - -enum TunnelValidationError: Error { - case invalidTitle - case titleExists - case nilInterface - case nilPeers - case invalidPeer -} - -enum TunnelParseError: Error { - case invalidLine(_ line: String) - case noConfigInfo -} diff --git a/WireGuard/Models/WireGuard.xcdatamodeld/WireGuard.xcdatamodel/contents b/WireGuard/Models/WireGuard.xcdatamodeld/WireGuard.xcdatamodel/contents deleted file mode 100644 index eeb1155..0000000 --- a/WireGuard/Models/WireGuard.xcdatamodeld/WireGuard.xcdatamodel/contents +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WireGuard/ViewControllers/Identifyable.swift b/WireGuard/ViewControllers/Identifyable.swift deleted file mode 100644 index c94a399..0000000 --- a/WireGuard/ViewControllers/Identifyable.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import UIKit - -public protocol Identifyable: class { - static var identifier: String { get } -} - -public extension Identifyable { - static var identifier: String { - return String(describing: Self.self) - } -} - -extension UIStoryboard { - - public func instantiateViewController(type: T.Type) -> T where T: UIViewController { - return self.instantiateViewController(withIdentifier: type.identifier) as! T // swiftlint:disable:this force_cast - } -} diff --git a/WireGuard/ViewControllers/QRScanViewController.swift b/WireGuard/ViewControllers/QRScanViewController.swift deleted file mode 100644 index 30fd79d..0000000 --- a/WireGuard/ViewControllers/QRScanViewController.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import AVFoundation -import CoreData -import UIKit - -protocol QRScanViewControllerDelegate: class { - func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) - func didCancel(qrScanViewController: QRScanViewController) -} - -class QRScanViewController: UIViewController { - - private var viewContext: NSManagedObjectContext! - private weak var delegate: QRScanViewControllerDelegate? - var captureSession: AVCaptureSession? = AVCaptureSession() - let metadataOutput = AVCaptureMetadataOutput() - var previewLayer: AVCaptureVideoPreviewLayer! - - func configure(context: NSManagedObjectContext, delegate: QRScanViewControllerDelegate? = nil) { - viewContext = context - self.delegate = delegate - } - - override func viewDidLoad() { - super.viewDidLoad() - - guard let videoCaptureDevice = AVCaptureDevice.default(for: .video), - let videoInput = try? AVCaptureDeviceInput(device: videoCaptureDevice), - let captureSession = captureSession, - captureSession.canAddInput(videoInput), - captureSession.canAddOutput(metadataOutput) else { - scanDidEncounterError(title: "Scanning Not Supported", message: "This device does not have the ability to scan QR codes.") - return - } - - captureSession.addInput(videoInput) - captureSession.addOutput(metadataOutput) - - metadataOutput.setMetadataObjectsDelegate(self, queue: .main) - metadataOutput.metadataObjectTypes = [.qr] - - previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) - previewLayer.frame = view.layer.bounds - previewLayer.videoGravity = .resizeAspectFill - view.layer.insertSublayer(previewLayer, at: 0) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - if captureSession?.isRunning == false { - captureSession?.startRunning() - } - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - if captureSession?.isRunning == true { - captureSession?.stopRunning() - } - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - if let connection = previewLayer.connection { - - let currentDevice: UIDevice = UIDevice.current - - let orientation: UIDeviceOrientation = currentDevice.orientation - - let previewLayerConnection: AVCaptureConnection = connection - - if previewLayerConnection.isVideoOrientationSupported { - - switch orientation { - case .portrait: - previewLayerConnection.videoOrientation = .portrait - case .landscapeRight: - previewLayerConnection.videoOrientation = .landscapeLeft - case .landscapeLeft: - previewLayerConnection.videoOrientation = .landscapeRight - case .portraitUpsideDown: - previewLayerConnection.videoOrientation = .portraitUpsideDown - default: - previewLayerConnection.videoOrientation = .portrait - - } - } - } - - previewLayer.frame = self.view.bounds - } - - func scanDidComplete(withCode code: String) { - do { - let tunnel = try Tunnel.fromConfig(code, context: viewContext) - let alert = UIAlertController(title: NSLocalizedString("Enter a title for new tunnel", comment: ""), message: nil, preferredStyle: .alert) - alert.addTextField(configurationHandler: nil) - alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: { [weak self] _ in - self?.delegate?.didCancel(qrScanViewController: self!) - })) - alert.addAction(UIAlertAction(title: NSLocalizedString("Save", comment: ""), style: .default, handler: { [weak self] _ in - do { - tunnel.title = alert.textFields?[0].text - try self?.viewContext.save() - self?.delegate?.didSave(tunnel: tunnel, qrScanViewController: self!) - } catch { - self?.scanDidEncounterError(title: "Invalid Code", message: "The scanned code is not a valid WireGuard config file.") - } - })) - - self.present(alert, animated: true) - - } catch { - scanDidEncounterError(title: "Invalid Code", message: "The scanned code is not a valid WireGuard config file.") - } - } - - func scanDidEncounterError(title: String, message: String) { - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in - self?.navigationController?.popViewController(animated: true) - })) - present(alertController, animated: true) - captureSession = nil - } - -} - -extension QRScanViewController: AVCaptureMetadataOutputObjectsDelegate { - func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { - captureSession?.stopRunning() - - guard let metadataObject = metadataObjects.first, - let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject, - let stringValue = readableObject.stringValue else { - scanDidEncounterError(title: "Invalid Code", message: "The scanned code could not be read.") - return - } - - AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate)) - scanDidComplete(withCode: stringValue) - } - -} - -extension QRScanViewController: Identifyable {} diff --git a/WireGuard/ViewControllers/SetttingsTableViewController.swift b/WireGuard/ViewControllers/SetttingsTableViewController.swift deleted file mode 100644 index 50832eb..0000000 --- a/WireGuard/ViewControllers/SetttingsTableViewController.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import PromiseKit - -enum GoVersionError: Error { - case noDelegate -} - -protocol SettingsTableViewControllerDelegate: class { - func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) -} - -class SettingsTableViewController: UITableViewController { - - weak var delegate: SettingsTableViewControllerDelegate? - @IBOutlet weak var versionInfoCell: UITableViewCell! - @IBOutlet weak var goVersionInfoCell: UITableViewCell! - @IBOutlet weak var exportCell: UITableViewCell! - - @IBOutlet weak var versionInfoLabel: UILabel! - @IBOutlet weak var goVersionInfoLabel: UILabel! - - override func viewDidLoad() { - super.viewDidLoad() - versionInfoLabel.text = versionInformation - goVersionInfoLabel.text = goVersionInformation - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let cell = tableView.cellForRow(at: indexPath) { - switch cell { - case versionInfoCell, goVersionInfoCell: - UIPasteboard.general.string = ["WireGuard for iOS:", versionInformation, "Go userspace backend:", goVersionInfoLabel.text ?? ""].joined(separator: "\n") - showCopyConfirmation() - case exportCell: - delegate?.exportTunnels(settingsTableViewController: self, sourceView: exportCell) - default: - () - } - tableView.deselectRow(at: indexPath, animated: true) - } - } - - var versionInformation: String { - var versionElements: [String] = [] - if let appBuildNumber = Bundle.main.infoDictionary!["CFBundleVersion"] as? String, let appVersion = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String { - versionElements.append(appVersion) - versionElements.append("(\(appBuildNumber))") - } - - return versionElements.joined(separator: " ") - } - - var goVersionInformation: String { - return Bundle.main.infoDictionary!["WireGuardGoVersion"] as? String ?? "Unknown!!!" - } - - private func showNotEnabledAlert() { - let notEnabledAlertController = UIAlertController(title: NSLocalizedString("Go version", comment: ""), message: NSLocalizedString("Enable a WireGuard config by connecting or by selecting one in the VPN section of the device Settings app.", comment: ""), preferredStyle: .alert) - notEnabledAlertController.addAction(UIAlertAction(title: NSLocalizedString("Ok", comment: "Generic OK button"), style: .default, handler: nil)) - - present(notEnabledAlertController, animated: true, completion: nil) - } - - private func showCopyConfirmation() { - let confirmationAlertController = UIAlertController(title: NSLocalizedString("Copied version information", comment: ""), message: UIPasteboard.general.string, preferredStyle: .alert) - confirmationAlertController.addAction(UIAlertAction(title: NSLocalizedString("Ok", comment: "Generic OK button"), style: .default, handler: nil)) - - present(confirmationAlertController, animated: true, completion: nil) - - } -} - -extension SettingsTableViewController: Identifyable {} diff --git a/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift b/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift deleted file mode 100644 index 65679c7..0000000 --- a/WireGuard/ViewControllers/TunnelConfigurationTableViewController.swift +++ /dev/null @@ -1,300 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import CoreData -import BNRCoreDataStack -import PromiseKit - -protocol TunnelConfigurationTableViewControllerDelegate: class { - func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) - func showSettings() -} - -class TunnelConfigurationTableViewController: UITableViewController { - - @IBOutlet weak var saveButton: UIBarButtonItem! - - private var viewContext: NSManagedObjectContext! - private weak var delegate: TunnelConfigurationTableViewControllerDelegate? - private var tunnel: Tunnel! - - override func viewDidLoad() { - super.viewDidLoad() - - // Get rid of seperator lines in table. - tableView.tableFooterView = UIView(frame: CGRect.zero) - } - - func configure(context: NSManagedObjectContext, delegate: TunnelConfigurationTableViewControllerDelegate? = nil, tunnel: Tunnel? = nil) { - viewContext = context - self.delegate = delegate - self.tunnel = tunnel ?? generateNewTunnelConfig() - } - - private func generateNewTunnelConfig() -> Tunnel { - var tunnel: Tunnel! = nil - - viewContext.performAndWait { - tunnel = Tunnel(context: viewContext) - tunnel.tunnelIdentifier = UUID().uuidString - - let interface = Interface(context: viewContext) - - tunnel.interface = interface - } - return tunnel - } - - @IBAction func showSettings(_ sender: Any) { - delegate?.showSettings() - } - - @IBAction func addPeer(_ sender: Any) { - if let moc = tunnel.managedObjectContext { - tableView.beginUpdates() - let insertedAt = IndexPath(row: tunnel.peers?.count ?? 0, section: 1) - tableView.insertRows(at: [insertedAt], with: .automatic) - - let peer = Peer(context: moc) - tunnel.addToPeers(peer) - - tableView.endUpdates() - tableView.scrollToRow(at: insertedAt, at: .middle, animated: true) - } - } - - override func numberOfSections(in tableView: UITableView) -> Int { - return 3 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - switch section { - case 1: - return tunnel?.peers?.count ?? 1 - default: - return 1 - } - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell(type: InterfaceTableViewCell.self, for: indexPath) - cell.model = tunnel.interface - cell.delegate = self - return cell - case 1: - let cell = tableView.dequeueReusableCell(type: PeerTableViewCell.self, for: indexPath) - if let peer = tunnel.peers?.object(at: indexPath.row) as? Peer { - cell.peer = peer - } else { - let peer = Peer(context: tunnel.managedObjectContext!) - tunnel.addToPeers(peer) - cell.peer = peer - } - cell.delegate = self - return cell - default: - let cell = tableView.dequeueReusableCell(type: AddPeerTableViewCell.self, for: indexPath) - cell.tunnel = tunnel - return cell - } - } - - @IBAction func saveTunnelConfiguration(_ sender: Any) { - Promise(resolver: { (seal) in - do { - try tunnel.validate() - } catch { - seal.reject(error) - return - } - - viewContext.perform({ - self.viewContext.saveContext({ (result) in - switch result { - case .success: - seal.fulfill(()) - case .failure(let error): - seal.reject(error) - } - }) - }) - }).then { () -> Promise in - self.delegate?.didSave(tunnel: self.tunnel, tunnelConfigurationTableViewController: self) - return Promise.value(()) - }.catch { error in - let alert = UIAlertController(title: "Error", message: "\(error)", preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) - self.present(alert, animated: true, completion: nil) - } - } -} - -extension TunnelConfigurationTableViewController: PeerTableViewCellDelegate { - func delete(peer: Peer) { - if let moc = tunnel.managedObjectContext { - tableView.beginUpdates() - let deletedAt = IndexPath(row: tunnel.peers?.index(of: peer) ?? 0, section: 1) - tableView.deleteRows(at: [deletedAt], with: .automatic) - tunnel.removeFromPeers(peer) - moc.delete(peer) - tableView.endUpdates() - } - } -} - -extension TunnelConfigurationTableViewController: InterfaceTableViewCellDelegate { - func generateKeys() { - if let moc = tunnel.managedObjectContext { - moc.perform { - var privateKey = Data(count: 32) - privateKey.withUnsafeMutableBytes { (mutableBytes) -> Void in - curve25519_generate_private_key(mutableBytes) - } - - self.tunnel.interface?.privateKey = privateKey.base64EncodedString() - } - } - self.tableView.reloadData() - } -} - -protocol InterfaceTableViewCellDelegate: class { - func generateKeys() -} - -class InterfaceTableViewCell: UITableViewCell { - var model: Interface! { - didSet { - nameField.text = model.tunnel?.title - addressesField.text = model.addresses - privateKeyField.text = model.privateKey - publicKeyField.text = model.publicKey - - listenPortField.text = model.listenPort > 0 ? String(model.listenPort) : nil - dnsField.text = model.dns - mtuField.text = model.mtu > 0 ? String(model.mtu) : nil - } - } - - weak var delegate: InterfaceTableViewCellDelegate? - - @IBOutlet weak var nameField: UITextField! - @IBOutlet weak var addressesField: UITextField! - @IBOutlet weak var privateKeyField: UITextField! - @IBOutlet weak var publicKeyField: CopyableLabel! - @IBOutlet weak var listenPortField: UITextField! - @IBOutlet weak var dnsField: UITextField! - @IBOutlet weak var mtuField: UITextField! - - @IBAction func generateTapped(_ sender: Any) { - delegate?.generateKeys() - } -} - -extension InterfaceTableViewCell: UITextFieldDelegate { - - @IBAction - func textfieldDidChange(_ sender: UITextField) { - let string = sender.text - - if sender == nameField { - model.tunnel?.title = string - } else if sender == privateKeyField { - model.privateKey = string - publicKeyField.text = model.publicKey - } else if sender == addressesField { - model.addresses = string - } else if sender == listenPortField { - if let string = string, let port = Int16(string) { - model.listenPort = port - } else { - model.listenPort = 0 - } - } else if sender == dnsField { - model.dns = string - } else if sender == mtuField { - if let string = string, let mtu = Int32(string) { - model.mtu = mtu - } else { - model.mtu = 0 - } - } - } - - func textFieldDidEndEditing(_ textField: UITextField) { - if textField == addressesField { - if let addresses = model.addresses?.commaSeparatedToArray() { - textField.text = addresses.compactMap { try? CIDRAddress(stringRepresentation: $0 ) }.compactMap { $0?.stringRepresentation }.joined(separator: ", ") - } - } - } -} - -protocol PeerTableViewCellDelegate: class { - func delete(peer: Peer) -} - -class PeerTableViewCell: UITableViewCell { - var peer: Peer! { - didSet { - publicKeyField.text = peer.publicKey - preSharedKeyField.text = peer.presharedKey - allowedIpsField.text = peer.allowedIPs - endpointField.text = peer.endpoint - persistentKeepaliveField.text = peer.persistentKeepalive > 0 ? String(peer.persistentKeepalive) : nil - } - } - weak var delegate: PeerTableViewCellDelegate? - - @IBOutlet weak var publicKeyField: UITextField! - @IBOutlet weak var preSharedKeyField: UITextField! - @IBOutlet weak var allowedIpsField: UITextField! - @IBOutlet weak var endpointField: UITextField! - @IBOutlet weak var persistentKeepaliveField: UITextField! - - @IBAction func deletePeer(_ sender: Any) { - delegate?.delete(peer: peer) - } -} - -extension PeerTableViewCell: UITextFieldDelegate { - @IBAction - func textfieldDidChange(_ sender: UITextField) { - let string = sender.text - - if sender == publicKeyField { - peer.publicKey = string - } else if sender == preSharedKeyField { - peer.presharedKey = string - } else if sender == allowedIpsField { - peer.allowedIPs = string - } else if sender == endpointField { - peer.endpoint = string - } else if sender == persistentKeepaliveField { - if let string = string, let persistentKeepalive = Int32(string) { - peer.persistentKeepalive = persistentKeepalive - } else { - peer.persistentKeepalive = 0 - } - } - } -} - -class AddPeerTableViewCell: UITableViewCell { - var tunnel: Tunnel! - - @IBAction func addPeer(_ sender: Any) { - if let moc = tunnel.managedObjectContext { - tunnel.addToPeers(Peer(context: moc)) - } - } -} - -extension TunnelConfigurationTableViewController: Identifyable {} -extension InterfaceTableViewCell: Identifyable {} -extension PeerTableViewCell: Identifyable {} -extension AddPeerTableViewCell: Identifyable {} diff --git a/WireGuard/ViewControllers/TunnelInfoTableViewController.swift b/WireGuard/ViewControllers/TunnelInfoTableViewController.swift deleted file mode 100644 index 1eb898a..0000000 --- a/WireGuard/ViewControllers/TunnelInfoTableViewController.swift +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import CoreData -import NetworkExtension - -import BNRCoreDataStack -import PromiseKit - -protocol TunnelInfoTableViewControllerDelegate: class { - func connect(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) - func disconnect(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) - func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) - func showSettings() - func status(for tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) -> NEVPNStatus -} - -class TunnelInfoTableViewController: UITableViewController { - - @IBOutlet weak var editButton: UIBarButtonItem! - - private var viewContext: NSManagedObjectContext! - private weak var delegate: TunnelInfoTableViewControllerDelegate? - private var tunnel: Tunnel! - - func configure(context: NSManagedObjectContext, delegate: TunnelInfoTableViewControllerDelegate? = nil, tunnel: Tunnel) { - viewContext = context - self.delegate = delegate - self.tunnel = tunnel - } - - override func viewDidLoad() { - super.viewDidLoad() - - // Get rid of seperator lines in table. - tableView.tableFooterView = UIView(frame: CGRect.zero) - - NotificationCenter.default.addObserver(self, - selector: #selector(VPNStatusDidChange(notification:)), - name: .NEVPNStatusDidChange, - object: nil) - } - - override func viewWillAppear(_ animated: Bool) { - super .viewWillAppear(animated) - - self.tableView.reloadData() - } - - override func numberOfSections(in tableView: UITableView) -> Int { - return 2 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - switch section { - case 1: - return tunnel?.peers?.count ?? 0 - default: - return 1 - } - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell(type: InterfaceInfoTableViewCell.self, for: indexPath) - cell.delegate = self - cell.configure(model: tunnel.interface, status: delegate?.status(for: tunnel, tunnelInfoTableViewController: self) ?? .invalid) - return cell - default: - let cell = tableView.dequeueReusableCell(type: PeerInfoTableViewCell.self, for: indexPath) - if let peer = tunnel.peers?.object(at: indexPath.row) as? Peer { - cell.peer = peer - } else { - let peer = Peer(context: tunnel.managedObjectContext!) - tunnel.addToPeers(peer) - cell.peer = peer - } - return cell - } - } - - @IBAction func showSettings(_ sender: Any) { - delegate?.showSettings() - } - - @IBAction func editTunnelConfiguration(_ sender: Any) { - delegate?.configure(tunnel: self.tunnel, tunnelInfoTableViewController: self) - } - - @objc private func VPNStatusDidChange(notification: NSNotification) { - guard let session = notification.object as? NETunnelProviderSession else { - return - } - - guard let prot = session.manager.protocolConfiguration as? NETunnelProviderProtocol else { - return - } - - guard let changedTunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else { - return - } - - guard tunnel.tunnelIdentifier == changedTunnelIdentifier else { - return - } - - self.tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .none) - } -} - -extension TunnelInfoTableViewController: InterfaceInfoTableViewCellDelegate { - func connect(tunnelIdentifier: String) { - delegate?.connect(tunnel: tunnel, tunnelInfoTableViewController: self) - } - - func disconnect(tunnelIdentifier: String) { - delegate?.disconnect(tunnel: tunnel, tunnelInfoTableViewController: self) - } -} - -protocol InterfaceInfoTableViewCellDelegate: class { - func connect(tunnelIdentifier: String) - func disconnect(tunnelIdentifier: String) -} - -class InterfaceInfoTableViewCell: UITableViewCell { - weak var delegate: InterfaceInfoTableViewCellDelegate? - private var model: Interface! { - didSet { - nameField.text = model.tunnel?.title - addressesField.text = model.addresses - publicKeyField.text = model.publicKey - } - } - - func configure(model: Interface!, status: NEVPNStatus) { - self.model = model - - if status == .connecting || status == .disconnecting || status == .reasserting { - activityIndicator.startAnimating() - tunnelSwitch.isHidden = true - } else { - activityIndicator.stopAnimating() - tunnelSwitch.isHidden = false - } - - tunnelSwitch.isOn = status == .connected - tunnelSwitch.onTintColor = status == .invalid || status == .reasserting ? .gray : .green - tunnelSwitch.isEnabled = true - } - - @IBAction func tunnelSwitchChanged(_ sender: Any) { - tunnelSwitch.isEnabled = false - - guard let tunnelIdentifier = model.tunnel?.tunnelIdentifier else { - return - } - - if tunnelSwitch.isOn { - delegate?.connect(tunnelIdentifier: tunnelIdentifier) - } else { - delegate?.disconnect(tunnelIdentifier: tunnelIdentifier) - } - } - - @IBOutlet weak var nameField: UILabel! - @IBOutlet weak var addressesField: UILabel! - @IBOutlet weak var publicKeyField: CopyableLabel! - @IBOutlet weak var tunnelSwitch: UISwitch! - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! -} - -class PeerInfoTableViewCell: UITableViewCell { - var peer: Peer! { - didSet { - publicKeyField.text = peer.publicKey - allowedIpsField.text = peer.allowedIPs - endpointField.text = peer.endpoint - } - } - - @IBOutlet weak var publicKeyField: CopyableLabel! - @IBOutlet weak var allowedIpsField: UILabel! - @IBOutlet weak var endpointField: UILabel! - @IBOutlet weak var copiedStatusLabel: UILabel! - -} - -extension TunnelInfoTableViewController: Identifyable {} -extension InterfaceInfoTableViewCell: Identifyable {} -extension PeerInfoTableViewCell: Identifyable {} diff --git a/WireGuard/ViewControllers/TunnelsTableViewController.swift b/WireGuard/ViewControllers/TunnelsTableViewController.swift deleted file mode 100644 index 26932d9..0000000 --- a/WireGuard/ViewControllers/TunnelsTableViewController.swift +++ /dev/null @@ -1,308 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import UIKit -import os.log -import CoreData - -import BNRCoreDataStack -import NetworkExtension - -protocol TunnelsTableViewControllerDelegate: class { - func addProvider(tunnelsTableViewController: TunnelsTableViewController) - func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus - func showSettings() -} - -class TunnelsTableViewController: UITableViewController { - weak var delegate: TunnelsTableViewControllerDelegate? - - var viewContext: NSManagedObjectContext! - - @IBOutlet var settingsButton: UIBarButtonItem! - @IBOutlet var editButton: UIBarButtonItem! - @IBOutlet var doneButton: UIBarButtonItem! - - private lazy var fetchedResultsController: FetchedResultsController = { - let fetchRequest = NSFetchRequest() - fetchRequest.entity = Tunnel.entity() - fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] - let frc = FetchedResultsController(fetchRequest: fetchRequest, - managedObjectContext: viewContext) - frc.setDelegate(self.frcDelegate) - return frc - }() - - public func updateStatus(for tunnelIdentifier: String) { - viewContext.perform { - do { - let tunnel = try Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - if let indexPath = self.fetchedResultsController.indexPathForObject(tunnel) { - self.tableView.reloadRows(at: [indexPath], with: .none) - } - } - } catch { - os_log("Unable to load tunnel for tunnel identifier: %{public}@", log: Log.general, type: .error, error.localizedDescription) - - } - } - } - - private lazy var frcDelegate: TunnelFetchedResultsControllerDelegate = { // swiftlint:disable:this weak_delegate - return TunnelFetchedResultsControllerDelegate(tableView: self.tableView) - }() - - override func viewDidLoad() { - super.viewDidLoad() - do { - try fetchedResultsController.performFetch() - } catch { - print("Failed to fetch objects: \(error)") - } - - // Get rid of seperator lines in table. - tableView.tableFooterView = UIView(frame: CGRect.zero) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - updateBarButtons() - } - - @IBAction func editTunnels(_ sender: Any) { - tableView.setEditing(!tableView.isEditing, animated: true) - updateBarButtons() - - } - - private func updateBarButtons() { - navigationController?.setToolbarHidden(tableView.isEditing, animated: true) - if tableView.isEditing { - self.navigationItem.setRightBarButtonItems([doneButton], animated: true) - } else { - self.navigationItem.setRightBarButtonItems([settingsButton, editButton], animated: true) - } - } - - @IBAction func showSettings(_ sender: Any) { - delegate?.showSettings() - } - - @IBAction func addProvider(_ sender: UIBarButtonItem) { - delegate?.addProvider(tunnelsTableViewController: self) - } - - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return fetchedResultsController.sections?[0].objects.count ?? 0 - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(type: TunnelTableViewCell.self, for: indexPath) - cell.delegate = self - - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - cell.configure(tunnel: tunnel, status: delegate?.status(for: tunnel, tunnelsTableViewController: self) ?? .invalid) - - return cell - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) - - tableView.deselectRow(at: indexPath, animated: true) - } - - override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) - - } - - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - return true - } - - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - - guard let sections = fetchedResultsController.sections else { - fatalError("FetchedResultsController \(fetchedResultsController) should have sections, but found nil") - } - - let section = sections[indexPath.section] - let tunnel = section.objects[indexPath.row] - - delegate?.delete(tunnel: tunnel, tunnelsTableViewController: self) - } - } -} - -extension TunnelsTableViewController: TunnelTableViewCellDelegate { - func connect(tunnelIdentifier: String) { - let tunnel = try? Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - self.delegate?.connect(tunnel: tunnel!, tunnelsTableViewController: self) - } - } - - func disconnect(tunnelIdentifier: String) { - let tunnel = try? Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - self.delegate?.disconnect(tunnel: tunnel!, tunnelsTableViewController: self) - } - } - -} - -extension TunnelsTableViewController: Identifyable {} - -class TunnelFetchedResultsControllerDelegate: NSObject, FetchedResultsControllerDelegate { - - private weak var tableView: UITableView? - private var arrowImage: UIImageView? - - // MARK: - Lifecycle - init(tableView: UITableView) { - self.tableView = tableView - } - - func fetchedResultsControllerDidPerformFetch(_ controller: FetchedResultsController) { - tableView?.reloadData() - updateEmptyIndicator(controller) - } - - func fetchedResultsControllerWillChangeContent(_ controller: FetchedResultsController) { - tableView?.beginUpdates() - } - - func fetchedResultsControllerDidChangeContent(_ controller: FetchedResultsController) { - tableView?.endUpdates() - updateEmptyIndicator(controller) - } - - func fetchedResultsController(_ controller: FetchedResultsController, didChangeObject change: FetchedResultsObjectChange) { - guard let tableView = tableView else { return } - switch change { - case let .insert(_, indexPath): - tableView.insertRows(at: [indexPath], with: .automatic) - - case let .delete(_, indexPath): - tableView.deleteRows(at: [indexPath], with: .automatic) - - case let .move(_, fromIndexPath, toIndexPath): - tableView.moveRow(at: fromIndexPath, to: toIndexPath) - - case let .update(_, indexPath): - tableView.reloadRows(at: [indexPath], with: .automatic) - } - } - - func fetchedResultsController(_ controller: FetchedResultsController, didChangeSection change: FetchedResultsSectionChange) { - guard let tableView = tableView else { return } - switch change { - case let .insert(_, index): - tableView.insertSections(IndexSet(integer: index), with: .automatic) - - case let .delete(_, index): - tableView.deleteSections(IndexSet(integer: index), with: .automatic) - } - } - - private func updateEmptyIndicator(_ controller: FetchedResultsController) { - guard let tableView = tableView else { return } - if controller.count > 0 { - tableView.backgroundView = nil - arrowImage = nil - } else { - if arrowImage == nil { - let imageView = UIImageView(image: UIImage(named: "Arrow")) - imageView.autoresizingMask = [.flexibleHeight, .flexibleWidth] - imageView.frame = tableView.bounds - imageView.contentMode = .bottomRight - tableView.backgroundView = imageView - arrowImage = imageView - } - } - } -} - -protocol TunnelTableViewCellDelegate: class { - func connect(tunnelIdentifier: String) - func disconnect(tunnelIdentifier: String) -} - -class TunnelTableViewCell: UITableViewCell { - - @IBOutlet weak var tunnelTitleLabel: UILabel! - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! - @IBOutlet weak var tunnelSwitch: UISwitch! - - weak var delegate: TunnelTableViewCellDelegate? - private var tunnelIdentifier: String? - - @IBAction func tunnelSwitchChanged(_ sender: Any) { - tunnelSwitch.isEnabled = false - guard let tunnelIdentifier = tunnelIdentifier else { - return - } - - if tunnelSwitch.isOn { - delegate?.connect(tunnelIdentifier: tunnelIdentifier) - } else { - delegate?.disconnect(tunnelIdentifier: tunnelIdentifier) - } - } - - func configure(tunnel: Tunnel, status: NEVPNStatus) { - self.tunnelTitleLabel?.text = tunnel.title - tunnelIdentifier = tunnel.tunnelIdentifier - - if status == .connecting || status == .disconnecting || status == .reasserting { - activityIndicator.startAnimating() - tunnelSwitch.isHidden = true - } else { - activityIndicator.stopAnimating() - tunnelSwitch.isHidden = false - } - - tunnelSwitch.isOn = status == .connected - tunnelSwitch.onTintColor = status == .invalid || status == .reasserting ? .gray : .green - tunnelSwitch.isEnabled = true - } - - override func setEditing(_ editing: Bool, animated: Bool) { - super.setEditing(editing, animated: animated) - tunnelSwitch.isHidden = editing - } -} - -extension TunnelTableViewCell: Identifyable {} diff --git a/WireGuard/ViewControllers/UITableView+WireGuard.swift b/WireGuard/ViewControllers/UITableView+WireGuard.swift deleted file mode 100644 index a8b913b..0000000 --- a/WireGuard/ViewControllers/UITableView+WireGuard.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation - -import UIKit - -extension UITableView { - - func register(type: T.Type, prefix: String = "") where T: UITableViewCell { - register(type, forCellReuseIdentifier: prefix + type.identifier) - } - - func dequeueReusableCell(type: T.Type, for indexPath: IndexPath, prefix: String = "") -> T where T: UITableViewCell { - return dequeueReusableCell(withIdentifier: prefix + type.identifier, for: indexPath) as! T // swiftlint:disable:this force_cast - } - - func registerNib(type: T.Type, prefix: String = "") where T: UITableViewCell { - let nib = UINib(nibName: prefix + type.identifier, bundle: nil) - register(nib, forCellReuseIdentifier: prefix + type.identifier) - } - - func registerNib(type: T.Type, prefix: String = "") where T: UITableViewHeaderFooterView { - let nib = UINib(nibName: prefix + type.identifier, bundle: nil) - register(nib, forHeaderFooterViewReuseIdentifier: prefix + type.identifier) - } - - func dequeueReusableHeaderFooterView(type: T.Type, prefix: String = "") -> T where T: UITableViewHeaderFooterView { - return dequeueReusableHeaderFooterView(withIdentifier: prefix + type.identifier) as! T // swiftlint:disable:this force_cast - } -} diff --git a/WireGuard/WireGuard-Bridging-Header.h b/WireGuard/WireGuard-Bridging-Header.h deleted file mode 100644 index 95922cc..0000000 --- a/WireGuard/WireGuard-Bridging-Header.h +++ /dev/null @@ -1,6 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "Crypto/x25519.h" -#import "../wireguard-go-bridge/wireguard.h" diff --git a/WireGuard/WireGuard.entitlements b/WireGuard/WireGuard.entitlements deleted file mode 100644 index a4774c6..0000000 --- a/WireGuard/WireGuard.entitlements +++ /dev/null @@ -1,18 +0,0 @@ - - - - - com.apple.developer.networking.networkextension - - packet-tunnel-provider - - com.apple.security.application-groups - - group.com.wireguard.ios - - keychain-access-groups - - $(AppIdentifierPrefix)com.wireguard.ios - - - diff --git a/WireGuardTests/Info.plist b/WireGuardTests/Info.plist deleted file mode 100644 index 6c40a6c..0000000 --- a/WireGuardTests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/WireGuardTests/ValidatorsTests.swift b/WireGuardTests/ValidatorsTests.swift deleted file mode 100644 index 39acd06..0000000 --- a/WireGuardTests/ValidatorsTests.swift +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import XCTest -@testable import WireGuard - -class ValidatorsTests: XCTestCase { - func testEndpoint() throws { - _ = try Endpoint(endpointString: "[2607:f938:3001:4000::aac]:12345") - _ = try Endpoint(endpointString: "192.168.0.1:12345") - } - - func testEndpoint_invalidIP() throws { - func executeTest(endpointString: String, ipString: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try Endpoint(endpointString: endpointString)) { (error) in - guard case EndpointValidationError.invalidIP(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, ipString, file: file, line: line) - } - } - - executeTest(endpointString: "12345:12345", ipString: "12345") - executeTest(endpointString: ":12345", ipString: "") - } - - func testEndpoint_invalidPort() throws { - func executeTest(endpointString: String, portString: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try Endpoint(endpointString: endpointString)) { (error) in - guard case EndpointValidationError.invalidPort(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, portString, file: file, line: line) - } - } - - executeTest(endpointString: ":", portString: "") - executeTest(endpointString: "[2607:f938:3001:4000::aac]:-12345", portString: "-12345") - executeTest(endpointString: "[2607:f938:3001:4000::aac]", portString: "aac]") - executeTest(endpointString: "[2607:f938:3001:4000::aac]:", portString: "") - executeTest(endpointString: "192.168.0.1:-12345", portString: "-12345") - executeTest(endpointString: "192.168.0.1:", portString: "") - - } - - func testEndpoint_noIpAndPort() throws { - - func executeTest(endpointString: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try Endpoint(endpointString: endpointString)) { (error) in - guard case EndpointValidationError.noIpAndPort(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, endpointString, file: file, line: line) - } - } - - executeTest(endpointString: "192.168.0.1") - executeTest(endpointString: "12345") - } - - func testCIDRAddress() throws { - _ = try CIDRAddress(stringRepresentation: "2607:f938:3001:4000::aac/24") - _ = try CIDRAddress(stringRepresentation: "192.168.0.1/24") - } - - func testIPv4CIDRAddress() throws { - _ = try CIDRAddress(stringRepresentation: "192.168.0.1/24") - } - - func testCIDRAddress_invalidIP() throws { - func executeTest(stringRepresentation: String, ipString: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try CIDRAddress(stringRepresentation: stringRepresentation)) { (error) in - guard case CIDRAddressValidationError.invalidIP(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, ipString, file: file, line: line) - } - } - - executeTest(stringRepresentation: "12345/12345", ipString: "12345") - executeTest(stringRepresentation: "/12345", ipString: "") - } - - func testCIDRAddress_invalidSubnet() throws { - func executeTest(stringRepresentation: String, subnetString: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try CIDRAddress(stringRepresentation: stringRepresentation)) { (error) in - guard case CIDRAddressValidationError.invalidSubnet(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, subnetString, file: file, line: line) - } - } - - executeTest(stringRepresentation: "/", subnetString: "") - executeTest(stringRepresentation: "2607:f938:3001:4000::aac/a", subnetString: "a") - executeTest(stringRepresentation: "2607:f938:3001:4000:/aac", subnetString: "aac") - executeTest(stringRepresentation: "2607:f938:3001:4000::aac/", subnetString: "") - executeTest(stringRepresentation: "192.168.0.1/a", subnetString: "a") - executeTest(stringRepresentation: "192.168.0.1/", subnetString: "") - - } - - func testCIDRAddress_noIpAndSubnet() throws { - - func executeTest(stringRepresentation: String, file: StaticString = #file, line: UInt = #line) { - XCTAssertThrowsError(try CIDRAddress(stringRepresentation: stringRepresentation)) { (error) in - guard case CIDRAddressValidationError.noIpAndSubnet(let value) = error else { - return XCTFail("Unexpected error: \(error)", file: file, line: line) - } - XCTAssertEqual(value, stringRepresentation, file: file, line: line) - } - } - - executeTest(stringRepresentation: "192.168.0.1") - executeTest(stringRepresentation: "12345") - } - - // swiftlint:disable next function_body_length - func testIPv4CIDRAddressSubnetConversion() throws { - // swiftlint:disable force_try - let cidrAddress1 = try! CIDRAddress(stringRepresentation: "128.0.0.0/1")! - XCTAssertEqual(cidrAddress1.ipAddress, cidrAddress1.subnetString) - let cidrAddress2 = try! CIDRAddress(stringRepresentation: "192.0.0.0/2")! - XCTAssertEqual(cidrAddress2.ipAddress, cidrAddress2.subnetString) - let cidrAddress3 = try! CIDRAddress(stringRepresentation: "224.0.0.0/3")! - XCTAssertEqual(cidrAddress3.ipAddress, cidrAddress3.subnetString) - let cidrAddress4 = try! CIDRAddress(stringRepresentation: "240.0.0.0/4")! - XCTAssertEqual(cidrAddress4.ipAddress, cidrAddress4.subnetString) - let cidrAddress5 = try! CIDRAddress(stringRepresentation: "248.0.0.0/5")! - XCTAssertEqual(cidrAddress5.ipAddress, cidrAddress5.subnetString) - let cidrAddress6 = try! CIDRAddress(stringRepresentation: "252.0.0.0/6")! - XCTAssertEqual(cidrAddress6.ipAddress, cidrAddress6.subnetString) - let cidrAddress7 = try! CIDRAddress(stringRepresentation: "254.0.0.0/7")! - XCTAssertEqual(cidrAddress7.ipAddress, cidrAddress7.subnetString) - let cidrAddress8 = try! CIDRAddress(stringRepresentation: "255.0.0.0/8")! - XCTAssertEqual(cidrAddress8.ipAddress, cidrAddress8.subnetString) - let cidrAddress9 = try! CIDRAddress(stringRepresentation: "255.128.0.0/9")! - XCTAssertEqual(cidrAddress9.ipAddress, cidrAddress9.subnetString) - let cidrAddress10 = try! CIDRAddress(stringRepresentation: "255.192.0.0/10")! - XCTAssertEqual(cidrAddress10.ipAddress, cidrAddress10.subnetString) - let cidrAddress11 = try! CIDRAddress(stringRepresentation: "255.224.0.0/11")! - XCTAssertEqual(cidrAddress11.ipAddress, cidrAddress11.subnetString) - let cidrAddress12 = try! CIDRAddress(stringRepresentation: "255.240.0.0/12")! - XCTAssertEqual(cidrAddress12.ipAddress, cidrAddress12.subnetString) - let cidrAddress13 = try! CIDRAddress(stringRepresentation: "255.248.0.0/13")! - XCTAssertEqual(cidrAddress13.ipAddress, cidrAddress13.subnetString) - let cidrAddress14 = try! CIDRAddress(stringRepresentation: "255.252.0.0/14")! - XCTAssertEqual(cidrAddress14.ipAddress, cidrAddress14.subnetString) - let cidrAddress15 = try! CIDRAddress(stringRepresentation: "255.254.0.0/15")! - XCTAssertEqual(cidrAddress15.ipAddress, cidrAddress15.subnetString) - let cidrAddress16 = try! CIDRAddress(stringRepresentation: "255.255.0.0/16")! - XCTAssertEqual(cidrAddress16.ipAddress, cidrAddress16.subnetString) - let cidrAddress17 = try! CIDRAddress(stringRepresentation: "255.255.128.0/17")! - XCTAssertEqual(cidrAddress17.ipAddress, cidrAddress17.subnetString) - let cidrAddress18 = try! CIDRAddress(stringRepresentation: "255.255.192.0/18")! - XCTAssertEqual(cidrAddress18.ipAddress, cidrAddress18.subnetString) - let cidrAddress19 = try! CIDRAddress(stringRepresentation: "255.255.224.0/19")! - XCTAssertEqual(cidrAddress19.ipAddress, cidrAddress19.subnetString) - let cidrAddress20 = try! CIDRAddress(stringRepresentation: "255.255.240.0/20")! - XCTAssertEqual(cidrAddress20.ipAddress, cidrAddress20.subnetString) - let cidrAddress21 = try! CIDRAddress(stringRepresentation: "255.255.248.0/21")! - XCTAssertEqual(cidrAddress21.ipAddress, cidrAddress21.subnetString) - let cidrAddress22 = try! CIDRAddress(stringRepresentation: "255.255.252.0/22")! - XCTAssertEqual(cidrAddress22.ipAddress, cidrAddress22.subnetString) - let cidrAddress23 = try! CIDRAddress(stringRepresentation: "255.255.254.0/23")! - XCTAssertEqual(cidrAddress23.ipAddress, cidrAddress23.subnetString) - let cidrAddress24 = try! CIDRAddress(stringRepresentation: "255.255.255.0/24")! - XCTAssertEqual(cidrAddress24.ipAddress, cidrAddress24.subnetString) - let cidrAddress25 = try! CIDRAddress(stringRepresentation: "255.255.255.128/25")! - XCTAssertEqual(cidrAddress25.ipAddress, cidrAddress25.subnetString) - let cidrAddress26 = try! CIDRAddress(stringRepresentation: "255.255.255.192/26")! - XCTAssertEqual(cidrAddress26.ipAddress, cidrAddress26.subnetString) - let cidrAddress27 = try! CIDRAddress(stringRepresentation: "255.255.255.224/27")! - XCTAssertEqual(cidrAddress27.ipAddress, cidrAddress27.subnetString) - let cidrAddress28 = try! CIDRAddress(stringRepresentation: "255.255.255.240/28")! - XCTAssertEqual(cidrAddress28.ipAddress, cidrAddress28.subnetString) - let cidrAddress29 = try! CIDRAddress(stringRepresentation: "255.255.255.248/29")! - XCTAssertEqual(cidrAddress29.ipAddress, cidrAddress29.subnetString) - let cidrAddress30 = try! CIDRAddress(stringRepresentation: "255.255.255.252/30")! - XCTAssertEqual(cidrAddress30.ipAddress, cidrAddress30.subnetString) - let cidrAddress31 = try! CIDRAddress(stringRepresentation: "255.255.255.254/31")! - XCTAssertEqual(cidrAddress31.ipAddress, cidrAddress31.subnetString) - let cidrAddress32 = try! CIDRAddress(stringRepresentation: "255.255.255.255/32")! - XCTAssertEqual(cidrAddress32.ipAddress, cidrAddress32.subnetString) - // swiftlint:enable force_try - } - -}