diff options
70 files changed, 0 insertions, 4379 deletions
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 Binary files differdeleted file mode 100644 index 7b0779f..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/Icon.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png Binary files differdeleted file mode 100644 index d12a297..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png Binary files differdeleted file mode 100644 index 7f1668d..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png Binary files differdeleted file mode 100644 index 7f1668d..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png Binary files differdeleted file mode 100644 index 28c67d4..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png Binary files differdeleted file mode 100644 index 8ec8d93..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png Binary files differdeleted file mode 100644 index a7739f5..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png Binary files differdeleted file mode 100644 index ed8332f..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png Binary files differdeleted file mode 100644 index e436f81..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png Binary files differdeleted file mode 100644 index 7f1668d..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png Binary files differdeleted file mode 100644 index d0e7d2c..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png Binary files differdeleted file mode 100644 index bc73ca8..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png Binary files differdeleted file mode 100644 index 410f082..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png Binary files differdeleted file mode 100644 index 410f082..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png Binary files differdeleted file mode 100644 index 4c799aa..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png Binary files differdeleted file mode 100644 index 0565869..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png Binary files differdeleted file mode 100644 index 8c378fd..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png b/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png Binary files differdeleted file mode 100644 index f575275..0000000 --- a/WireGuard/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf b/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf Binary files differdeleted file mode 100644 index 781e309..0000000 --- a/WireGuard/Assets.xcassets/Arrow.imageset/Arrow.pdf +++ /dev/null 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 Binary files differdeleted file mode 100644 index c5a2168..0000000 --- a/WireGuard/Assets.xcassets/settings.imageset/Dots.pdf +++ /dev/null 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 Binary files differdeleted file mode 100644 index de3dd1c..0000000 --- a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png b/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png Binary files differdeleted file mode 100644 index e542a9b..0000000 --- a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@2x.png +++ /dev/null diff --git a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png b/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png Binary files differdeleted file mode 100644 index 1b6b07c..0000000 --- a/WireGuard/Assets.xcassets/trash.imageset/ic_action_delete@3x.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index f404859..0000000 --- a/WireGuard/Assets.xcassets/wireguard.imageset/wireguard.pdf +++ /dev/null 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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="fHK-5V-Wmb"> - <device id="retina4_7" orientation="portrait"> - <adaptation id="fullscreen"/> - </device> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/> - <capability name="Safe area layout guides" minToolsVersion="9.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <scenes> - <!--Navigation Controller--> - <scene sceneID="KXE-tg-GCt"> - <objects> - <navigationController id="fHK-5V-Wmb" sceneMemberID="viewController"> - <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="kSJ-B6-Sbs"> - <rect key="frame" x="0.0" y="20" width="375" height="96"/> - <autoresizingMask key="autoresizingMask"/> - <color key="barTintColor" red="0.53333333329999999" green="0.090196078430000007" blue="0.1019607843" alpha="1" colorSpace="calibratedRGB"/> - </navigationBar> - <connections> - <segue destination="ZbP-GT-mQn" kind="relationship" relationship="rootViewController" id="ejS-gV-hxU"/> - </connections> - </navigationController> - <placeholder placeholderIdentifier="IBFirstResponder" id="bEx-a1-E4B" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="150" y="313"/> - </scene> - <!--View Controller--> - <scene sceneID="QPe-xp-OsR"> - <objects> - <viewController id="ZbP-GT-mQn" sceneMemberID="viewController"> - <view key="view" contentMode="scaleToFill" id="LhN-TB-3GI"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <viewLayoutGuide key="safeArea" id="qsB-da-p6j"/> - </view> - <navigationItem key="navigationItem" id="Qbp-DQ-urz"/> - </viewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="Sdb-mk-Xj1" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="910" y="313"/> - </scene> - </scenes> -</document> 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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> - <device id="retina4_7" orientation="portrait"> - <adaptation id="fullscreen"/> - </device> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/> - <capability name="Safe area layout guides" minToolsVersion="9.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <scenes> - <!--Navigation Controller--> - <scene sceneID="1sx-zW-OnW"> - <objects> - <navigationController storyboardIdentifier="UINavigationController" toolbarHidden="NO" id="JOA-JU-iCW" sceneMemberID="viewController"> - <toolbarItems/> - <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="GsQ-3q-wZr"> - <rect key="frame" x="0.0" y="20" width="375" height="96"/> - <autoresizingMask key="autoresizingMask"/> - <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <color key="barTintColor" red="0.53333333333333333" green="0.090196078431372548" blue="0.10196078431372549" alpha="1" colorSpace="calibratedRGB"/> - <textAttributes key="titleTextAttributes"> - <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - </textAttributes> - <textAttributes key="largeTitleTextAttributes"> - <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - </textAttributes> - </navigationBar> - <toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="Gaw-oA-bsm"> - <rect key="frame" x="0.0" y="623" width="375" height="44"/> - <autoresizingMask key="autoresizingMask"/> - </toolbar> - </navigationController> - <placeholder placeholderIdentifier="IBFirstResponder" id="cAJ-Ch-uyg" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="-1403" y="201"/> - </scene> - <!--WireGuard--> - <scene sceneID="Tud-vM-cYZ"> - <objects> - <tableViewController storyboardIdentifier="TunnelsTableViewController" id="kTU-BV-32R" customClass="TunnelsTableViewController" customModule="WireGuard" customModuleProvider="target" sceneMemberID="viewController"> - <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" estimatedRowHeight="60" sectionHeaderHeight="28" sectionFooterHeight="28" id="AJg-r0-KJH"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <inset key="separatorInset" minX="15" minY="0.0" maxX="0.0" maxY="0.0"/> - <prototypes> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="TunnelTableViewCell" rowHeight="60" id="a0u-k7-l2a" customClass="TunnelTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="28" width="375" height="60"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="a0u-k7-l2a" id="5vz-m1-nzL"> - <rect key="frame" x="0.0" y="0.0" width="341" height="59.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LTX-Ir-wae"> - <rect key="frame" x="16" y="11" width="42" height="38"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="Lfv-Kt-u7M"> - <rect key="frame" x="298" y="20" width="20" height="20"/> - </activityIndicatorView> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3kG-Lh-YJw"> - <rect key="frame" x="292" y="14.5" width="51" height="31"/> - <connections> - <action selector="tunnelSwitchChanged:" destination="a0u-k7-l2a" eventType="valueChanged" id="9bz-IV-8hb"/> - </connections> - </switch> - </subviews> - <constraints> - <constraint firstItem="3kG-Lh-YJw" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="LTX-Ir-wae" secondAttribute="trailing" constant="10" id="2fo-Df-eKg"/> - <constraint firstAttribute="bottomMargin" secondItem="LTX-Ir-wae" secondAttribute="bottom" id="S3B-b1-6Qv"/> - <constraint firstAttribute="trailing" secondItem="3kG-Lh-YJw" secondAttribute="trailing" id="hT2-xN-OxL"/> - <constraint firstItem="LTX-Ir-wae" firstAttribute="leading" secondItem="5vz-m1-nzL" secondAttribute="leadingMargin" id="n1M-My-hfr"/> - <constraint firstItem="LTX-Ir-wae" firstAttribute="top" secondItem="5vz-m1-nzL" secondAttribute="topMargin" id="xcD-dj-Mkb"/> - <constraint firstItem="Lfv-Kt-u7M" firstAttribute="centerY" secondItem="5vz-m1-nzL" secondAttribute="centerY" id="xcc-16-Z3J"/> - <constraint firstAttribute="trailingMargin" secondItem="Lfv-Kt-u7M" secondAttribute="trailing" constant="15" id="yIh-CA-dGh"/> - <constraint firstItem="3kG-Lh-YJw" firstAttribute="centerY" secondItem="5vz-m1-nzL" secondAttribute="centerY" id="yYd-ax-nhH"/> - </constraints> - </tableViewCellContentView> - <connections> - <outlet property="activityIndicator" destination="Lfv-Kt-u7M" id="eg5-uH-cH9"/> - <outlet property="tunnelSwitch" destination="3kG-Lh-YJw" id="pCW-UC-DBx"/> - <outlet property="tunnelTitleLabel" destination="LTX-Ir-wae" id="NiF-vE-EGL"/> - </connections> - </tableViewCell> - </prototypes> - <connections> - <outlet property="dataSource" destination="kTU-BV-32R" id="E0F-RC-fZE"/> - <outlet property="delegate" destination="kTU-BV-32R" id="b6T-ZR-cmO"/> - </connections> - </tableView> - <toolbarItems> - <barButtonItem style="plain" systemItem="flexibleSpace" id="TXL-1f-4BY"/> - <barButtonItem systemItem="add" id="h2H-H8-3Tn"> - <connections> - <action selector="addProvider:" destination="kTU-BV-32R" id="xSg-ap-3Fx"/> - </connections> - </barButtonItem> - </toolbarItems> - <navigationItem key="navigationItem" title="WireGuard" largeTitleDisplayMode="always" id="j0L-5U-jDs"> - <barButtonItem key="backBarButtonItem" title="Tunnels" id="pxL-gR-QXU"/> - <rightBarButtonItems> - <barButtonItem image="settings" id="DZP-sp-Hsg"> - <connections> - <action selector="showSettings:" destination="kTU-BV-32R" id="UfC-XY-zhW"/> - </connections> - </barButtonItem> - <barButtonItem systemItem="trash" id="Bj0-7o-icS"> - <connections> - <action selector="editTunnels:" destination="kTU-BV-32R" id="NzT-sl-F5r"/> - </connections> - </barButtonItem> - <barButtonItem systemItem="done" id="X9a-Od-S2p"> - <connections> - <action selector="editTunnels:" destination="kTU-BV-32R" id="n7j-D7-moO"/> - </connections> - </barButtonItem> - </rightBarButtonItems> - </navigationItem> - <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/> - <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/> - <connections> - <outlet property="doneButton" destination="X9a-Od-S2p" id="Dc9-5g-IBV"/> - <outlet property="editButton" destination="Bj0-7o-icS" id="iAH-Vk-xLg"/> - <outlet property="settingsButton" destination="DZP-sp-Hsg" id="6YI-c0-U9w"/> - </connections> - </tableViewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="4uZ-Vv-Fry" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="-670" y="200"/> - </scene> - <!--Tunnel settings--> - <scene sceneID="xV8-BW-4R7"> - <objects> - <tableViewController storyboardIdentifier="TunnelConfigurationTableViewController" useStoryboardIdentifierAsRestorationIdentifier="YES" id="0VM-73-EPX" customClass="TunnelConfigurationTableViewController" customModule="WireGuard" customModuleProvider="target" sceneMemberID="viewController"> - <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="0Uy-k2-O3i"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> - <prototypes> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="InterfaceTableViewCell" rowHeight="452" id="06N-KU-LSv" customClass="InterfaceTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="28" width="375" height="452"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="06N-KU-LSv" id="CSX-Am-ix0"> - <rect key="frame" x="0.0" y="0.0" width="375" height="451.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="DIe-hK-tf6"> - <rect key="frame" x="16" y="11" width="343" height="430"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Interface" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uku-6H-QWf"> - <rect key="frame" x="0.0" y="0.0" width="343" height="49.5"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="uLA-3S-jCk"> - <rect key="frame" x="0.0" y="63.5" width="343" height="49.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uJE-LK-T3Y"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="6y9-eJ-8fF"> - <rect key="frame" x="0.0" y="16" width="343" height="33.5"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="Ike-ou-qa9"/> - <outlet property="delegate" destination="06N-KU-LSv" id="TuA-ac-TIy"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="wwN-OL-XUr"> - <rect key="frame" x="0.0" y="127" width="343" height="49.5"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="26U-vy-7Lc"> - <rect key="frame" x="0.0" y="0.0" width="343" height="19.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Private key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fMQ-kK-FD5"> - <rect key="frame" x="0.0" y="0.0" width="235" height="19.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="C1M-bh-5mf"> - <rect key="frame" x="243" y="0.0" width="100" height="19.5"/> - <constraints> - <constraint firstAttribute="width" constant="100" id="EvB-pb-J1d"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <state key="normal" title="Generate"/> - <connections> - <action selector="generateTapped:" destination="06N-KU-LSv" eventType="touchUpInside" id="efE-zK-eCe"/> - </connections> - </button> - </subviews> - </stackView> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hYd-0L-nnY"> - <rect key="frame" x="0.0" y="19.5" width="343" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="CQd-My-M7G"/> - <outlet property="delegate" destination="06N-KU-LSv" id="7YF-mU-HZT"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="wbd-4k-oxV"> - <rect key="frame" x="0.0" y="190.5" width="343" height="49"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Cuy-Vl-A3X"> - <rect key="frame" x="0.0" y="0.0" width="343" height="15.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jrM-B3-YSD"> - <rect key="frame" x="0.0" y="0.0" width="343" height="15.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qks-JK-qzc" customClass="CopyableLabel" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="15.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="YP4-TS-hbj"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="nv7-4q-QjM"> - <rect key="frame" x="0.0" y="253.5" width="343" height="49.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Listen port" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h1p-Ea-ler"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="(random)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="CSv-At-WVr"> - <rect key="frame" x="0.0" y="16" width="343" height="33.5"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="z45-u7-zCB"/> - <outlet property="delegate" destination="06N-KU-LSv" id="YZ0-LC-PjW"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="PJF-32-WyF"> - <rect key="frame" x="0.0" y="317" width="343" height="49.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="L6l-5D-oKQ"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="oOY-vP-nYT"> - <rect key="frame" x="0.0" y="16" width="343" height="33.5"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="HAL-o6-G7A"/> - <outlet property="delegate" destination="06N-KU-LSv" id="M1a-B6-Cl2"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="7fC-XV-6KP"> - <rect key="frame" x="0.0" y="380.5" width="343" height="49.5"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="NR3-Me-yLc"> - <rect key="frame" x="0.0" y="0.0" width="235" height="49.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="DNS servers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SA3-N0-wfi"> - <rect key="frame" x="0.0" y="0.0" width="235" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ByK-wW-6Q4"> - <rect key="frame" x="0.0" y="16" width="235" height="33.5"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="8gN-mk-GtN"/> - <outlet property="delegate" destination="06N-KU-LSv" id="YjV-8W-z5Q"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="UId-O4-q3t"> - <rect key="frame" x="243" y="0.0" width="100" height="49.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MTU" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vYu-BI-0Gj"> - <rect key="frame" x="0.0" y="0.0" width="100" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="(auto)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="myM-B2-sjT"> - <rect key="frame" x="0.0" y="16" width="100" height="33.5"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="06N-KU-LSv" eventType="editingChanged" id="fgZ-LJ-ksN"/> - <outlet property="delegate" destination="06N-KU-LSv" id="F1E-lK-AsD"/> - </connections> - </textField> - </subviews> - <constraints> - <constraint firstAttribute="width" constant="100" id="4BH-E4-p8q"/> - </constraints> - </stackView> - </subviews> - </stackView> - </subviews> - </stackView> - </subviews> - <constraints> - <constraint firstAttribute="trailingMargin" secondItem="DIe-hK-tf6" secondAttribute="trailing" id="GkT-4C-4uN"/> - <constraint firstItem="DIe-hK-tf6" firstAttribute="top" secondItem="CSX-Am-ix0" secondAttribute="topMargin" id="Mul-xA-cN9"/> - <constraint firstAttribute="bottomMargin" secondItem="DIe-hK-tf6" secondAttribute="bottom" id="jBh-kE-ZBG"/> - <constraint firstItem="DIe-hK-tf6" firstAttribute="leading" secondItem="CSX-Am-ix0" secondAttribute="leadingMargin" id="sab-5q-2rU"/> - </constraints> - </tableViewCellContentView> - <connections> - <outlet property="addressesField" destination="oOY-vP-nYT" id="qcc-pN-5ug"/> - <outlet property="dnsField" destination="ByK-wW-6Q4" id="gZ4-7d-AHM"/> - <outlet property="listenPortField" destination="CSv-At-WVr" id="xnx-xz-pqS"/> - <outlet property="mtuField" destination="myM-B2-sjT" id="ppo-pV-tMl"/> - <outlet property="nameField" destination="6y9-eJ-8fF" id="PKk-lj-jK9"/> - <outlet property="privateKeyField" destination="hYd-0L-nnY" id="JLS-5M-E3T"/> - <outlet property="publicKeyField" destination="Qks-JK-qzc" id="20S-qa-P0O"/> - </connections> - </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="AddPeerTableViewCell" rowHeight="60" id="RyR-s5-lBV" customClass="AddPeerTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="480" width="375" height="60"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="RyR-s5-lBV" id="gPY-qW-fbd"> - <rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fVu-Aa-9dn"> - <rect key="frame" x="0.0" y="0.0" width="375" height="59.5"/> - <state key="normal" title="Add peer"/> - <connections> - <action selector="addPeer:" destination="0VM-73-EPX" eventType="touchUpInside" id="Udv-Os-ZWn"/> - </connections> - </button> - </subviews> - <constraints> - <constraint firstAttribute="bottom" secondItem="fVu-Aa-9dn" secondAttribute="bottom" id="AyE-qC-Rye"/> - <constraint firstAttribute="bottom" secondItem="fVu-Aa-9dn" secondAttribute="bottom" id="G8D-HX-t2n"/> - <constraint firstItem="fVu-Aa-9dn" firstAttribute="leading" secondItem="gPY-qW-fbd" secondAttribute="leading" id="GQn-8W-GpX"/> - <constraint firstAttribute="trailing" secondItem="fVu-Aa-9dn" secondAttribute="trailing" id="H9S-Km-FDv"/> - <constraint firstItem="fVu-Aa-9dn" firstAttribute="top" secondItem="gPY-qW-fbd" secondAttribute="top" id="Wv9-c4-I9v"/> - <constraint firstItem="fVu-Aa-9dn" firstAttribute="top" secondItem="gPY-qW-fbd" secondAttribute="top" id="fcp-SS-lbr"/> - </constraints> - </tableViewCellContentView> - </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="PeerTableViewCell" rowHeight="308" id="gzz-88-0IG" customClass="PeerTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="540" width="375" height="308"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="gzz-88-0IG" id="XA6-EM-5V9"> - <rect key="frame" x="0.0" y="0.0" width="375" height="307.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="NIK-2J-pTR"> - <rect key="frame" x="16" y="11" width="343" height="286"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dk9-qH-XaO"> - <rect key="frame" x="0.0" y="0.0" width="343" height="46"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Peer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42P-f9-Rft"> - <rect key="frame" x="0.0" y="0.0" width="303" height="46"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageSizeForAccessibilityContentSizeCategory="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SfN-pE-Y3t"> - <rect key="frame" x="303" y="0.0" width="40" height="46"/> - <accessibility key="accessibilityConfiguration" hint="Delete peer from tunnel configuration" label="Delete"/> - <constraints> - <constraint firstAttribute="width" constant="40" id="Sj9-zg-bBf"/> - </constraints> - <state key="normal" image="trash"/> - <connections> - <action selector="deletePeer:" destination="gzz-88-0IG" eventType="touchUpInside" id="PIg-AX-df7"/> - </connections> - </button> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="zcF-NC-5kf"> - <rect key="frame" x="0.0" y="60" width="343" height="46"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sN7-yp-U0M"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="s9R-Af-RNn"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="RLw-0o-akQ"> - <rect key="frame" x="0.0" y="16" width="343" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="gzz-88-0IG" eventType="editingChanged" id="taX-Ji-pVu"/> - <outlet property="delegate" destination="gzz-88-0IG" id="bkQ-Nc-VH4"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="miX-4O-NOP"> - <rect key="frame" x="0.0" y="120" width="343" height="46"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pre-shared key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iID-O4-iis"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="(optional)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="wkY-3s-yTK"> - <rect key="frame" x="0.0" y="16" width="343" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="gzz-88-0IG" eventType="editingChanged" id="Cxh-YH-bZv"/> - <outlet property="delegate" destination="gzz-88-0IG" id="oAu-VZ-2dn"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="vxg-u7-VjZ"> - <rect key="frame" x="0.0" y="180" width="343" height="46"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SJS-V6-FwE"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Allowed IPs" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hDL-EX-UqG"> - <rect key="frame" x="0.0" y="0.0" width="343" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="iiY-Tl-UcH"> - <rect key="frame" x="0.0" y="16" width="343" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="gzz-88-0IG" eventType="editingChanged" id="k1U-vW-Jom"/> - <outlet property="delegate" destination="gzz-88-0IG" id="DXo-0s-9sc"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="rgQ-cM-hwa"> - <rect key="frame" x="0.0" y="240" width="343" height="46"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="8uI-Ux-Xhj"> - <rect key="frame" x="0.0" y="0.0" width="232" height="46"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Endpoint" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P3u-6Z-3Hk"> - <rect key="frame" x="0.0" y="0.0" width="232" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="W88-H0-dFZ"> - <rect key="frame" x="0.0" y="16" width="232" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="gzz-88-0IG" eventType="editingChanged" id="bjR-TZ-Sx8"/> - <outlet property="delegate" destination="gzz-88-0IG" id="PLB-sa-SBV"/> - </connections> - </textField> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="eLi-QT-QwF"> - <rect key="frame" x="240" y="0.0" width="103" height="46"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Persistent keepalive" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="tja-cM-cGL"> - <rect key="frame" x="0.0" y="0.0" width="103" height="16"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="(optional)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Q8w-jh-0ox"> - <rect key="frame" x="0.0" y="16" width="103" height="30"/> - <nil key="textColor"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/> - <connections> - <action selector="textfieldDidChange:" destination="gzz-88-0IG" eventType="editingChanged" id="fQC-Pf-jUQ"/> - <outlet property="delegate" destination="gzz-88-0IG" id="sbH-Sb-rcW"/> - </connections> - </textField> - </subviews> - </stackView> - </subviews> - </stackView> - </subviews> - <constraints> - <constraint firstItem="eLi-QT-QwF" firstAttribute="width" secondItem="NIK-2J-pTR" secondAttribute="width" multiplier="0.3" id="Zid-UY-cdO"/> - </constraints> - </stackView> - </subviews> - <constraints> - <constraint firstItem="NIK-2J-pTR" firstAttribute="top" secondItem="XA6-EM-5V9" secondAttribute="topMargin" id="5YR-8M-6M5"/> - <constraint firstAttribute="trailingMargin" secondItem="NIK-2J-pTR" secondAttribute="trailing" id="AJ6-FH-zGS"/> - <constraint firstItem="NIK-2J-pTR" firstAttribute="leading" secondItem="XA6-EM-5V9" secondAttribute="leadingMargin" id="f2r-kN-RKk"/> - <constraint firstAttribute="bottomMargin" secondItem="NIK-2J-pTR" secondAttribute="bottom" id="rRD-SV-Wft"/> - </constraints> - </tableViewCellContentView> - <connections> - <outlet property="allowedIpsField" destination="iiY-Tl-UcH" id="QQK-x0-C3T"/> - <outlet property="endpointField" destination="W88-H0-dFZ" id="l0A-57-I5p"/> - <outlet property="persistentKeepaliveField" destination="Q8w-jh-0ox" id="thE-f2-vzz"/> - <outlet property="preSharedKeyField" destination="wkY-3s-yTK" id="0Tn-cP-uXS"/> - <outlet property="publicKeyField" destination="RLw-0o-akQ" id="teS-po-0h2"/> - </connections> - </tableViewCell> - </prototypes> - <connections> - <outlet property="dataSource" destination="0VM-73-EPX" id="f9B-xZ-gS4"/> - <outlet property="delegate" destination="0VM-73-EPX" id="oHt-UY-XIz"/> - </connections> - </tableView> - <navigationItem key="navigationItem" title="Tunnel settings" id="PPu-rX-T38"> - <rightBarButtonItems> - <barButtonItem image="settings" id="Ph6-EV-NlT"> - <connections> - <action selector="showSettings:" destination="0VM-73-EPX" id="wx3-3w-OhG"/> - </connections> - </barButtonItem> - <barButtonItem systemItem="save" id="mft-1l-bWa"> - <connections> - <action selector="saveTunnelConfiguration:" destination="0VM-73-EPX" id="Hni-0w-hFF"/> - </connections> - </barButtonItem> - </rightBarButtonItems> - </navigationItem> - <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/> - <connections> - <outlet property="saveButton" destination="mft-1l-bWa" id="Uif-KZ-isx"/> - </connections> - </tableViewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="j96-PK-ghN" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="-671" y="-1262"/> - </scene> - <!--Tunnel info--> - <scene sceneID="jJx-Qm-bKA"> - <objects> - <tableViewController storyboardIdentifier="TunnelInfoTableViewController" hidesBottomBarWhenPushed="YES" useStoryboardIdentifierAsRestorationIdentifier="YES" id="h8W-vj-IcI" customClass="TunnelInfoTableViewController" customModule="WireGuard" customModuleProvider="target" sceneMemberID="viewController"> - <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="I7I-Kf-A49"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> - <prototypes> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="InterfaceInfoTableViewCell" rowHeight="268" id="4nk-ch-nYS" customClass="InterfaceInfoTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="28" width="375" height="268"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="4nk-ch-nYS" id="eBg-fg-M9P"> - <rect key="frame" x="0.0" y="0.0" width="375" height="267.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="LbD-1j-3B4"> - <rect key="frame" x="16" y="11" width="343" height="246"/> - <subviews> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Sa-Tj-Ueo"> - <rect key="frame" x="0.0" y="0.0" width="343" height="51"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Interface" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qcg-LJ-nRV"> - <rect key="frame" x="0.0" y="15.5" width="286" height="20.5"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="odM-GH-fla"> - <rect key="frame" x="294" y="10" width="51" height="31"/> - <connections> - <action selector="tunnelSwitchChanged:" destination="4nk-ch-nYS" eventType="valueChanged" id="u0k-RB-DqP"/> - </connections> - </switch> - <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="EcT-Wp-yDm"> - <rect key="frame" x="308" y="15.5" width="20" height="20"/> - </activityIndicatorView> - </subviews> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <constraints> - <constraint firstItem="EcT-Wp-yDm" firstAttribute="centerY" secondItem="9Sa-Tj-Ueo" secondAttribute="centerY" id="DcF-AC-6ha"/> - <constraint firstItem="odM-GH-fla" firstAttribute="centerY" secondItem="9Sa-Tj-Ueo" secondAttribute="centerY" id="Y9x-NO-H4S"/> - <constraint firstAttribute="trailing" secondItem="odM-GH-fla" secondAttribute="trailing" id="hMu-gM-CG1"/> - <constraint firstItem="odM-GH-fla" firstAttribute="leading" secondItem="Qcg-LJ-nRV" secondAttribute="trailing" constant="8" id="iDB-Jf-5Ad"/> - <constraint firstAttribute="trailing" secondItem="EcT-Wp-yDm" secondAttribute="trailing" constant="15" id="mDG-cy-oEG"/> - <constraint firstItem="Qcg-LJ-nRV" firstAttribute="centerY" secondItem="9Sa-Tj-Ueo" secondAttribute="centerY" id="piF-RV-qzI"/> - <constraint firstItem="Qcg-LJ-nRV" firstAttribute="leading" secondItem="9Sa-Tj-Ueo" secondAttribute="leading" id="vpU-wH-wQf"/> - </constraints> - </view> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="wJ9-cl-tZH"> - <rect key="frame" x="0.0" y="65" width="343" height="51"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mov-bF-HkG"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t89-wK-B5h"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="gFw-bj-ygR"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Ao6-49-xJm"> - <rect key="frame" x="0.0" y="130" width="343" height="51"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5W3-mw-rz8"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vWC-ql-O8v"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bCm-fp-MGf" customClass="CopyableLabel" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <gestureRecognizers/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="tj9-5o-wt9"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="bu6-xb-eu0"> - <rect key="frame" x="0.0" y="195" width="343" height="51"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GWn-Of-NWj"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nxw-Kz-Bhj"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="Pzj-Qq-uXx"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - </subviews> - </stackView> - </subviews> - <constraints> - <constraint firstItem="LbD-1j-3B4" firstAttribute="leading" secondItem="eBg-fg-M9P" secondAttribute="leadingMargin" id="MpF-dU-5q1"/> - <constraint firstItem="LbD-1j-3B4" firstAttribute="top" secondItem="eBg-fg-M9P" secondAttribute="topMargin" id="Zyd-bw-Q0S"/> - <constraint firstAttribute="bottomMargin" secondItem="LbD-1j-3B4" secondAttribute="bottom" id="vpm-rN-QXf"/> - <constraint firstAttribute="trailingMargin" secondItem="LbD-1j-3B4" secondAttribute="trailing" id="whd-a8-RKi"/> - </constraints> - </tableViewCellContentView> - <connections> - <outlet property="activityIndicator" destination="EcT-Wp-yDm" id="0YQ-7s-ckk"/> - <outlet property="addressesField" destination="nxw-Kz-Bhj" id="e7Y-Z0-3Mk"/> - <outlet property="nameField" destination="t89-wK-B5h" id="6fz-z4-Gf5"/> - <outlet property="publicKeyField" destination="bCm-fp-MGf" id="O6Q-Tf-gKf"/> - <outlet property="tunnelSwitch" destination="odM-GH-fla" id="m31-9W-GgE"/> - </connections> - </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="PeerInfoTableViewCell" rowHeight="268" id="E8O-dS-GmI" customClass="PeerInfoTableViewCell" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="296" width="375" height="268"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="E8O-dS-GmI" id="Igy-0b-NWe"> - <rect key="frame" x="0.0" y="0.0" width="375" height="267.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="QR4-dk-gU5"> - <rect key="frame" x="16" y="11" width="343" height="246"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Peer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5qD-R9-tZb"> - <rect key="frame" x="0.0" y="0.0" width="343" height="51"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="1NC-ix-aSU"> - <rect key="frame" x="0.0" y="65" width="343" height="51"/> - <subviews> - <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7mv-Bm-kLf"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="quD-G5-mlN"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Copied" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zGI-77-A75"> - <rect key="frame" x="0.0" y="0.0" width="0.0" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.52156862749999999" green="0.21176470589999999" blue="0.1764705882" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QB9-fz-eN5" customClass="CopyableLabel" customModule="WireGuard" customModuleProvider="target"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="T62-rA-BQP"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="1v9-H0-PWt"> - <rect key="frame" x="0.0" y="130" width="343" height="51"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Allowed IPs" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3fw-zF-zA7"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h84-DM-thL"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="VAA-Cv-By1"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="2h1-6W-ZsL"> - <rect key="frame" x="0.0" y="195" width="343" height="51"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Endpoint" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TYO-NN-8gk"> - <rect key="frame" x="0.0" y="0.0" width="343" height="17.5"/> - <fontDescription key="fontDescription" type="system" pointSize="13"/> - <color key="textColor" red="0.60784313729999995" green="0.60784313729999995" blue="0.60784313729999995" alpha="1" colorSpace="calibratedRGB"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pju-S6-5Ls"> - <rect key="frame" x="0.0" y="17.5" width="343" height="33.5"/> - <constraints> - <constraint firstAttribute="height" constant="33.5" id="hBg-pD-foN"/> - </constraints> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </stackView> - </subviews> - </stackView> - </subviews> - <constraints> - <constraint firstAttribute="trailingMargin" secondItem="QR4-dk-gU5" secondAttribute="trailing" id="gEw-tD-Dbc"/> - <constraint firstItem="QR4-dk-gU5" firstAttribute="top" secondItem="Igy-0b-NWe" secondAttribute="topMargin" id="gH2-UQ-fHW"/> - <constraint firstItem="QR4-dk-gU5" firstAttribute="leading" secondItem="Igy-0b-NWe" secondAttribute="leadingMargin" id="nQT-10-aQB"/> - <constraint firstAttribute="bottomMargin" secondItem="QR4-dk-gU5" secondAttribute="bottom" id="uxe-Fp-xgz"/> - </constraints> - </tableViewCellContentView> - <connections> - <outlet property="allowedIpsField" destination="h84-DM-thL" id="CR8-i3-y2q"/> - <outlet property="copiedStatusLabel" destination="zGI-77-A75" id="zev-Na-P2u"/> - <outlet property="endpointField" destination="pju-S6-5Ls" id="y3c-20-rkp"/> - <outlet property="publicKeyField" destination="QB9-fz-eN5" id="hfg-EO-IRw"/> - </connections> - </tableViewCell> - </prototypes> - <connections> - <outlet property="dataSource" destination="h8W-vj-IcI" id="BDC-pZ-8RJ"/> - <outlet property="delegate" destination="h8W-vj-IcI" id="Huk-uM-0lZ"/> - </connections> - </tableView> - <navigationItem key="navigationItem" title="Tunnel info" id="Eh1-Vi-78e"> - <rightBarButtonItems> - <barButtonItem image="settings" id="OME-id-5vt"> - <connections> - <action selector="showSettings:" destination="h8W-vj-IcI" id="mZN-SL-gZJ"/> - </connections> - </barButtonItem> - <barButtonItem systemItem="edit" id="YRj-Ox-eKc"> - <connections> - <action selector="editTunnelConfiguration:" destination="h8W-vj-IcI" id="f1k-Y6-4c3"/> - </connections> - </barButtonItem> - </rightBarButtonItems> - </navigationItem> - <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/> - <connections> - <outlet property="editButton" destination="YRj-Ox-eKc" id="nIf-WD-pml"/> - </connections> - </tableViewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="cXx-q2-SBO" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="-671" y="-469"/> - </scene> - <!--Scan Code--> - <scene sceneID="gKN-k2-HoW"> - <objects> - <viewController storyboardIdentifier="QRScanViewController" hidesBottomBarWhenPushed="YES" useStoryboardIdentifierAsRestorationIdentifier="YES" id="Efe-yN-iDH" customClass="QRScanViewController" customModule="WireGuard" customModuleProvider="target" sceneMemberID="viewController"> - <view key="view" contentMode="scaleToFill" id="NXo-On-ea8"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tip: generate with `qrencode -t ansiutf8 < tunnel.conf`" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XYc-tx-YNF"> - <rect key="frame" x="16" y="628.5" width="343" height="14.5"/> - <fontDescription key="fontDescription" type="system" pointSize="12"/> - <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <nil key="highlightedColor"/> - </label> - </subviews> - <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <constraints> - <constraint firstItem="Soo-c9-MsX" firstAttribute="bottom" secondItem="XYc-tx-YNF" secondAttribute="bottom" constant="24" id="QhS-p5-jbw"/> - <constraint firstItem="XYc-tx-YNF" firstAttribute="leading" secondItem="NXo-On-ea8" secondAttribute="leading" constant="16" id="Y3P-Py-ueV"/> - <constraint firstAttribute="trailing" secondItem="XYc-tx-YNF" secondAttribute="trailing" constant="16" id="sB1-h9-ueh"/> - </constraints> - <viewLayoutGuide key="safeArea" id="Soo-c9-MsX"/> - </view> - <navigationItem key="navigationItem" title="Scan Code" largeTitleDisplayMode="always" id="WGY-tY-ySz"/> - <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/> - </viewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="TQ2-zp-o40" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="162" y="793"/> - </scene> - <!--Settings--> - <scene sceneID="LLL-0v-1Z9"> - <objects> - <tableViewController storyboardIdentifier="SettingsTableViewController" hidesBottomBarWhenPushed="YES" id="0L2-ND-Twh" customClass="SettingsTableViewController" customModule="WireGuard" customModuleProvider="target" sceneMemberID="viewController"> - <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="xce-Ka-TsV"> - <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/> - <imageView key="tableFooterView" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="wireguard" id="s2Q-Rh-mqC"> - <rect key="frame" x="0.0" y="261.5" width="375" height="55"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> - </imageView> - <sections> - <tableViewSection headerTitle="Version Information" id="zRZ-jm-jpm"> - <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="4T9-BK-cKk"> - <rect key="frame" x="0.0" y="55.5" width="375" height="44"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="4T9-BK-cKk" id="oh2-fj-cpB"> - <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="WireGuard for iOS" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="9LF-1X-BRX"> - <rect key="frame" x="16" y="11.5" width="139" height="21"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(x.y.z)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="64F-sz-1fb"> - <rect key="frame" x="313" y="11.5" width="46" height="21"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - <constraints> - <constraint firstItem="9LF-1X-BRX" firstAttribute="centerY" secondItem="oh2-fj-cpB" secondAttribute="centerY" id="0vh-j4-spD"/> - <constraint firstItem="64F-sz-1fb" firstAttribute="centerY" secondItem="oh2-fj-cpB" secondAttribute="centerY" id="30t-Be-YBk"/> - <constraint firstItem="64F-sz-1fb" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="9LF-1X-BRX" secondAttribute="trailing" constant="16" id="Nl3-vZ-7lQ"/> - <constraint firstItem="9LF-1X-BRX" firstAttribute="leading" secondItem="oh2-fj-cpB" secondAttribute="leadingMargin" id="atb-WE-sm5"/> - <constraint firstItem="64F-sz-1fb" firstAttribute="trailing" secondItem="oh2-fj-cpB" secondAttribute="trailingMargin" id="omW-fc-mV3"/> - </constraints> - </tableViewCellContentView> - </tableViewCell> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="7To-1u-V41"> - <rect key="frame" x="0.0" y="99.5" width="375" height="44"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7To-1u-V41" id="R1k-wj-XjQ"> - <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Go userspace backend" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="ZrW-kK-iNG"> - <rect key="frame" x="16" y="11.5" width="175.5" height="21"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(x.y.z)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZLF-fc-FG0"> - <rect key="frame" x="313" y="11.5" width="46" height="21"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - <constraints> - <constraint firstItem="ZLF-fc-FG0" firstAttribute="centerY" secondItem="R1k-wj-XjQ" secondAttribute="centerY" id="COd-8Q-MkD"/> - <constraint firstItem="ZLF-fc-FG0" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="ZrW-kK-iNG" secondAttribute="trailing" constant="16" id="mZA-b5-OXz"/> - <constraint firstItem="ZrW-kK-iNG" firstAttribute="leading" secondItem="R1k-wj-XjQ" secondAttribute="leadingMargin" id="v9L-hc-VeV"/> - <constraint firstItem="ZLF-fc-FG0" firstAttribute="trailing" secondItem="R1k-wj-XjQ" secondAttribute="trailingMargin" id="vbt-K7-zSd"/> - <constraint firstItem="ZrW-kK-iNG" firstAttribute="centerY" secondItem="R1k-wj-XjQ" secondAttribute="centerY" id="zMO-S4-aZv"/> - </constraints> - </tableViewCellContentView> - </tableViewCell> - </cells> - </tableViewSection> - <tableViewSection headerTitle="Export" id="A0i-t0-uNU"> - <cells> - <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Xti-BC-KTP" detailTextLabel="qYk-Nl-mLx" style="IBUITableViewCellStyleSubtitle" id="J1T-67-jcC"> - <rect key="frame" x="0.0" y="199.5" width="375" height="44"/> - <autoresizingMask key="autoresizingMask"/> - <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="J1T-67-jcC" id="OTJ-zk-hYF"> - <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/> - <autoresizingMask key="autoresizingMask"/> - <subviews> - <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Export tunnels to zip file" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Xti-BC-KTP"> - <rect key="frame" x="16" y="5" width="185" height="20.5"/> - <autoresizingMask key="autoresizingMask"/> - <fontDescription key="fontDescription" type="system" pointSize="17"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Zip file should be shared with a location for storage." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qYk-Nl-mLx"> - <rect key="frame" x="16" y="25.5" width="294.5" height="14.5"/> - <autoresizingMask key="autoresizingMask"/> - <fontDescription key="fontDescription" type="system" pointSize="12"/> - <nil key="textColor"/> - <nil key="highlightedColor"/> - </label> - </subviews> - </tableViewCellContentView> - </tableViewCell> - </cells> - </tableViewSection> - </sections> - <connections> - <outlet property="dataSource" destination="0L2-ND-Twh" id="iHC-iG-by3"/> - <outlet property="delegate" destination="0L2-ND-Twh" id="nAg-yY-JmZ"/> - </connections> - </tableView> - <navigationItem key="navigationItem" title="Settings" id="jxD-pO-Xgu"/> - <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/> - <connections> - <outlet property="exportCell" destination="J1T-67-jcC" id="VZX-ue-ZCE"/> - <outlet property="goVersionInfoCell" destination="7To-1u-V41" id="CeX-R9-6Qh"/> - <outlet property="goVersionInfoLabel" destination="ZLF-fc-FG0" id="5si-K0-QJL"/> - <outlet property="versionInfoCell" destination="4T9-BK-cKk" id="QrQ-73-Cpq"/> - <outlet property="versionInfoLabel" destination="64F-sz-1fb" id="O1J-1X-GvV"/> - </connections> - </tableViewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="DXL-eC-zr0" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="726" y="-469"/> - </scene> - </scenes> - <resources> - <image name="settings" width="4" height="13"/> - <image name="trash" width="14" height="18"/> - <image name="wireguard" width="1875" height="334"/> - </resources> - <color key="tintColor" red="0.53333333333333333" green="0.090196078431372548" blue="0.10196078431372549" alpha="1" colorSpace="calibratedRGB"/> -</document> 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<Void> 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<Void> 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<Void> { - 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<Void> 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<NETunnelProviderManager> 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<Void> 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<Void> 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<String> { - 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 <stdint.h> -#include <string.h> -#include <CommonCrypto/CommonRandom.h> - -#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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>$(DEVELOPMENT_LANGUAGE)</string> - <key>CFBundleDisplayName</key> - <string>${PRODUCT_NAME}</string> - <key>CFBundleDocumentTypes</key> - <array> - <dict> - <key>CFBundleTypeExtensions</key> - <array> - <string>conf</string> - </array> - <key>CFBundleTypeIconFiles</key> - <array> - <string>icon_20pt</string> - <string>icon_20pt@3x</string> - <string>icon_60pt@3x</string> - </array> - <key>CFBundleTypeName</key> - <string>WireGuard configuration</string> - <key>CFBundleTypeRole</key> - <string>Viewer</string> - <key>LSHandlerRank</key> - <string>Owner</string> - <key>LSItemContentTypes</key> - <array> - <string>com.wireguard.config.quick</string> - </array> - </dict> - <dict> - <key>CFBundleTypeExtensions</key> - <array> - <string>zip</string> - </array> - <key>CFBundleTypeIconFile</key> - <string>zip</string> - <key>CFBundleTypeIconFiles</key> - <array/> - <key>CFBundleTypeMIMETypes</key> - <array> - <string>application/zip</string> - <string>application/x-zip</string> - <string>application/x-zip-compressed</string> - </array> - <key>CFBundleTypeName</key> - <string>WireGuard Config Zip</string> - <key>CFBundleTypeOSTypes</key> - <array> - <string>ZIP </string> - </array> - <key>CFBundleTypeRole</key> - <string>Viewer</string> - <key>LSItemContentTypes</key> - <array> - <string>com.pkware.zip-archive</string> - </array> - </dict> - </array> - <key>CFBundleExecutable</key> - <string>$(EXECUTABLE_NAME)</string> - <key>CFBundleIdentifier</key> - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>$(PRODUCT_NAME)</string> - <key>WireGuardGoVersion</key> - <string>unknown</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>CFBundleVersion</key> - <string>auto-generated</string> - <key>LSRequiresIPhoneOS</key> - <true/> - <key>LSSupportsOpeningDocumentsInPlace</key> - <false/> - <key>NSCameraUsageDescription</key> - <string>Camera is used to scan QR codes</string> - <key>UIFileSharingEnabled</key> - <true/> - <key>UILaunchStoryboardName</key> - <string>LaunchScreen</string> - <key>UIRequiredDeviceCapabilities</key> - <array> - <string>armv7</string> - </array> - <key>UIStatusBarStyle</key> - <string>UIStatusBarStyleLightContent</string> - <key>UISupportedInterfaceOrientations</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> - <key>UISupportedInterfaceOrientations~ipad</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> - <key>UIViewControllerBasedStatusBarAppearance</key> - <false/> - <key>UTExportedTypeDeclarations</key> - <array> - <dict> - <key>UTTypeConformsTo</key> - <array> - <string>public.data</string> - </array> - <key>UTTypeDescription</key> - <string>WireGuard configuration</string> - <key>UTTypeIconFiles</key> - <array> - <string>icon_20pt@3x</string> - <string>icon_60pt@3x</string> - </array> - <key>UTTypeIdentifier</key> - <string>com.wireguard.config.quick</string> - <key>UTTypeTagSpecification</key> - <dict> - <key>public.filename-extension</key> - <string>conf</string> - </dict> - </dict> - </array> - <key>UTImportedTypeDeclarations</key> - <array> - <dict> - <key>UTTypeConformsTo</key> - <array> - <string>com.pkware.zip-archive</string> - </array> - <key>UTTypeDescription</key> - <string>WireGuard configuration</string> - <key>UTTypeIconFiles</key> - <array> - <string>icon_20pt@3x</string> - <string>icon_60pt@3x</string> - </array> - <key>UTTypeIdentifier</key> - <string>com.wireguard.config.quick</string> - <key>UTTypeTagSpecification</key> - <dict> - <key>public.filename-extension</key> - <string>conf</string> - </dict> - </dict> - <dict> - <key>UTTypeConformsTo</key> - <array> - <string>public.data</string> - </array> - <key>UTTypeDescription</key> - <string>WireGuard configurations</string> - <key>UTTypeIconFiles</key> - <array> - <string>icon_20pt.png</string> - <string>icon_60pt@3x.png</string> - </array> - <key>UTTypeIdentifier</key> - <string>com.wireguard.config.quick.confs</string> - <key>public.filename-extension</key> - <string>zip</string> - </dict> - </array> -</dict> -</plist> 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[..<equalsIndex].trimmingCharacters(in: .whitespaces) - let value = line[line.index(equalsIndex, offsetBy: 1)...].trimmingCharacters(in: .whitespaces) - guard let key = Key.allCases.first(where: { $0.rawValue.lowercased() == keyString.lowercased() }) else { return nil } - - return Attribute(line: line, key: key, stringValue: value) - } - -} diff --git a/WireGuard/Models/Interface+CoreDataClass.swift b/WireGuard/Models/Interface+CoreDataClass.swift deleted file mode 100644 index f57b5a9..0000000 --- a/WireGuard/Models/Interface+CoreDataClass.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -@objc(Interface) -public class Interface: NSManagedObject { - -} diff --git a/WireGuard/Models/Interface+CoreDataProperties.swift b/WireGuard/Models/Interface+CoreDataProperties.swift deleted file mode 100644 index b512dc0..0000000 --- a/WireGuard/Models/Interface+CoreDataProperties.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright © 2018 WireGuard LLC. All rights reserved. -// - -import Foundation -import CoreData - -extension Interface { - - @nonobjc public class func fetchRequest() -> NSFetchRequest<Interface> { - return NSFetchRequest<Interface>(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<Peer> { - return NSFetchRequest<Peer>(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<Tunnel> { - return NSFetchRequest<Tunnel>(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> = 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[..<commentRange.lowerBound]) - } else { - trimmedLine = String(line) - } - - trimmedLine = trimmedLine.trimmingCharacters(in: .whitespaces) - - guard trimmedLine.count > 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 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14315.18" systemVersion="18A391" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> - <entity name="Interface" representedClassName="Interface" syncable="YES"> - <attribute name="addresses" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="dns" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="listenPort" optional="YES" attributeType="Integer 16" usesScalarValueType="YES" syncable="YES"/> - <attribute name="mtu" optional="YES" attributeType="Integer 32" usesScalarValueType="YES" syncable="YES"/> - <attribute name="privateKey" attributeType="String" syncable="YES"/> - <relationship name="tunnel" maxCount="1" deletionRule="Nullify" destinationEntity="Tunnel" inverseName="interface" inverseEntity="Tunnel" syncable="YES"/> - </entity> - <entity name="Peer" representedClassName="Peer" syncable="YES"> - <attribute name="allowedIPs" attributeType="String" syncable="YES"/> - <attribute name="endpoint" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="persistentKeepalive" attributeType="Integer 32" minValueString="0" maxValueString="65535" defaultValueString="0" usesScalarValueType="YES" syncable="YES"/> - <attribute name="presharedKey" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="publicKey" attributeType="String" syncable="YES"/> - <relationship name="tunnel" maxCount="1" deletionRule="Nullify" destinationEntity="Tunnel" inverseName="peers" inverseEntity="Tunnel" syncable="YES"/> - </entity> - <entity name="Tunnel" representedClassName="Tunnel" syncable="YES"> - <attribute name="title" optional="YES" attributeType="String" syncable="YES"/> - <attribute name="tunnelIdentifier" attributeType="String" syncable="YES"/> - <relationship name="interface" maxCount="1" deletionRule="Cascade" destinationEntity="Interface" inverseName="tunnel" inverseEntity="Interface" syncable="YES"/> - <relationship name="peers" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="Peer" inverseName="tunnel" inverseEntity="Peer" syncable="YES"/> - </entity> - <elements> - <element name="Interface" positionX="-54" positionY="-9" width="128" height="135"/> - <element name="Peer" positionX="-36" positionY="9" width="128" height="135"/> - <element name="Tunnel" positionX="160" positionY="192" width="128" height="105"/> - </elements> -</model>
\ 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<T: Identifyable>(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<Void>(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<Void> 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<Tunnel> = { - let fetchRequest = NSFetchRequest<Tunnel>() - fetchRequest.entity = Tunnel.entity() - fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] - let frc = FetchedResultsController<Tunnel>(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<Tunnel>) { - tableView?.reloadData() - updateEmptyIndicator(controller) - } - - func fetchedResultsControllerWillChangeContent(_ controller: FetchedResultsController<Tunnel>) { - tableView?.beginUpdates() - } - - func fetchedResultsControllerDidChangeContent(_ controller: FetchedResultsController<Tunnel>) { - tableView?.endUpdates() - updateEmptyIndicator(controller) - } - - func fetchedResultsController(_ controller: FetchedResultsController<Tunnel>, didChangeObject change: FetchedResultsObjectChange<Tunnel>) { - 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<Tunnel>, didChangeSection change: FetchedResultsSectionChange<Tunnel>) { - 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<Tunnel>) { - 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<T: Identifyable>(type: T.Type, prefix: String = "") where T: UITableViewCell { - register(type, forCellReuseIdentifier: prefix + type.identifier) - } - - func dequeueReusableCell<T: Identifyable>(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<T: Identifyable>(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<T: Identifyable>(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<T: Identifyable>(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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>com.apple.developer.networking.networkextension</key> - <array> - <string>packet-tunnel-provider</string> - </array> - <key>com.apple.security.application-groups</key> - <array> - <string>group.com.wireguard.ios</string> - </array> - <key>keychain-access-groups</key> - <array> - <string>$(AppIdentifierPrefix)com.wireguard.ios</string> - </array> -</dict> -</plist> 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 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>$(DEVELOPMENT_LANGUAGE)</string> - <key>CFBundleExecutable</key> - <string>$(EXECUTABLE_NAME)</string> - <key>CFBundleIdentifier</key> - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>$(PRODUCT_NAME)</string> - <key>CFBundlePackageType</key> - <string>BNDL</string> - <key>CFBundleShortVersionString</key> - <string>1.0</string> - <key>CFBundleVersion</key> - <string>1</string> -</dict> -</plist> 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 - } - -} |