Add import and export logic.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
4950254013
commit
2572c4781c
Binary file not shown.
After Width: | Height: | Size: 730 B |
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
|
@ -8,6 +8,8 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
48CF751B34E9703133F1B1AF /* Pods_WireGuard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 861983CAE8FDC13BC83E7E04 /* Pods_WireGuard.framework */; };
|
||||
4A430E802139DC8F0078172C /* icon_20pt@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */; };
|
||||
4A430E842139DCFB0078172C /* icon_60pt@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4A430E832139DCFB0078172C /* icon_60pt@3x.png */; };
|
||||
4A4351592124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
||||
4A43515A2124956200261999 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4351582124956200261999 /* Validators.swift */; };
|
||||
4A43515C21249E5700261999 /* ValidatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A43515B21249E5700261999 /* ValidatorsTests.swift */; };
|
||||
|
@ -85,6 +87,9 @@
|
|||
/* Begin PBXFileReference section */
|
||||
0CE52E030FAA93F3BF5747B2 /* Pods-WireGuard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.release.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.release.xcconfig"; sourceTree = "<group>"; };
|
||||
25E2BE31A33C8CCE6E79B6EF /* Pods-WireGuard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WireGuard.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WireGuard/Pods-WireGuard.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_20pt@3x.png"; sourceTree = "<group>"; };
|
||||
4A430E812139DCCB0078172C /* icon_20pt.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_20pt.png; sourceTree = "<group>"; };
|
||||
4A430E832139DCFB0078172C /* icon_60pt@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon_60pt@3x.png"; path = "WireGuard/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png"; sourceTree = SOURCE_ROOT; };
|
||||
4A4351582124956200261999 /* Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validators.swift; sourceTree = "<group>"; };
|
||||
4A43515B21249E5700261999 /* ValidatorsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorsTests.swift; sourceTree = "<group>"; };
|
||||
4A4BA6D720B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelConfigurationTableViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -223,6 +228,9 @@
|
|||
4A4BAD0720B5F4BC00F12B28 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4A430E7F2139DC8F0078172C /* icon_20pt@3x.png */,
|
||||
4A430E812139DCCB0078172C /* icon_20pt.png */,
|
||||
4A430E832139DCFB0078172C /* icon_60pt@3x.png */,
|
||||
4A4BAD0520B5F4B500F12B28 /* Settings.bundle */,
|
||||
);
|
||||
path = Resources;
|
||||
|
@ -468,6 +476,8 @@
|
|||
files = (
|
||||
4A4BAD0620B5F4B500F12B28 /* Settings.bundle in Resources */,
|
||||
4A4BACF020B5F1C100F12B28 /* LaunchScreen.storyboard in Resources */,
|
||||
4A430E842139DCFB0078172C /* icon_60pt@3x.png in Resources */,
|
||||
4A430E802139DC8F0078172C /* icon_20pt@3x.png in Resources */,
|
||||
4A4BACED20B5F1C100F12B28 /* Assets.xcassets in Resources */,
|
||||
4A4BACEB20B5F1BF00F12B28 /* Main.storyboard in Resources */,
|
||||
);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import os.log
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
@ -22,4 +23,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: 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)
|
||||
}
|
||||
}
|
||||
guard url.pathExtension == "conf" else { return false }
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
<outlet property="delegate" destination="kTU-BV-32R" id="b6T-ZR-cmO"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="WireGuard Tunnels" id="j0L-5U-jDs">
|
||||
<navigationItem key="navigationItem" title="WireGuard Tunnels" largeTitleDisplayMode="always" id="j0L-5U-jDs">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="add" id="h2H-H8-3Tn">
|
||||
<connections>
|
||||
<action selector="addProvider:" destination="kTU-BV-32R" id="xSg-ap-3Fx"/>
|
||||
|
@ -486,14 +486,22 @@
|
|||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="Tunnel settings" id="PPu-rX-T38">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="save" id="mft-1l-bWa">
|
||||
<connections>
|
||||
<action selector="saveTunnelConfiguration:" destination="0VM-73-EPX" id="Hni-0w-hFF"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<rightBarButtonItems>
|
||||
<barButtonItem systemItem="save" id="mft-1l-bWa">
|
||||
<connections>
|
||||
<action selector="saveTunnelConfiguration:" destination="0VM-73-EPX" id="Hni-0w-hFF"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem systemItem="action" id="uim-Mz-omJ">
|
||||
<connections>
|
||||
<action selector="exportTunnel:" destination="0VM-73-EPX" id="oVI-TL-4o9"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</rightBarButtonItems>
|
||||
</navigationItem>
|
||||
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
|
||||
<connections>
|
||||
<outlet property="exportButton" destination="uim-Mz-omJ" id="1Tq-ie-xo7"/>
|
||||
<outlet property="saveButton" destination="mft-1l-bWa" id="Uif-KZ-isx"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
|
@ -524,7 +532,7 @@
|
|||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="Soo-c9-MsX"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Scan Code" largeTitleDisplayMode="never" id="WGY-tY-ySz"/>
|
||||
<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"/>
|
||||
|
|
|
@ -13,6 +13,10 @@ import os.log
|
|||
import CoreData
|
||||
import BNRCoreDataStack
|
||||
|
||||
enum AppCoordinatorError: Error {
|
||||
case configImportError(msg: String)
|
||||
}
|
||||
|
||||
extension UINavigationController: Identifyable {}
|
||||
|
||||
let APPGROUP = "group.com.wireguard.ios.WireGuard"
|
||||
|
@ -92,6 +96,46 @@ class AppCoordinator: RootViewCoordinator {
|
|||
}
|
||||
}
|
||||
|
||||
func importConfig(config: URL) throws {
|
||||
do {
|
||||
let configString = try String(contentsOf: config)
|
||||
let addContext = persistentContainer.newBackgroundContext()
|
||||
let tunnel = try Tunnel.fromConfig(configString, context: addContext)
|
||||
let title = config.deletingPathExtension().lastPathComponent
|
||||
tunnel.title = title
|
||||
addContext.saveContext()
|
||||
self.saveTunnel(tunnel)
|
||||
} catch {
|
||||
throw AppCoordinatorError.configImportError(msg: "Failed")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 tunnelto: %{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) {
|
||||
|
@ -151,7 +195,6 @@ class AppCoordinator: RootViewCoordinator {
|
|||
}
|
||||
|
||||
extension AppCoordinator: TunnelsTableViewControllerDelegate {
|
||||
|
||||
func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
|
||||
let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
|
||||
return session?.status ?? .invalid
|
||||
|
@ -330,6 +373,10 @@ extension AppCoordinator: TunnelsTableViewControllerDelegate {
|
|||
}
|
||||
|
||||
extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
|
||||
func export(tunnel: Tunnel, barButtonItem: UIBarButtonItem) {
|
||||
exportConfig(tunnel: tunnel, barButtonItem: barButtonItem)
|
||||
}
|
||||
|
||||
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
|
||||
saveTunnel(tunnel)
|
||||
}
|
||||
|
|
|
@ -2,10 +2,35 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera is used to scan QR codes</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string></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>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
@ -22,6 +47,12 @@
|
|||
<string>auto-generated</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<false/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera is used to scan QR codes</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
|
@ -45,5 +76,51 @@
|
|||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<string>conf</string>
|
||||
</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>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<string>conf</string>
|
||||
</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>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -13,11 +13,13 @@ import PromiseKit
|
|||
|
||||
protocol TunnelConfigurationTableViewControllerDelegate: class {
|
||||
func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController)
|
||||
func export(tunnel: Tunnel, barButtonItem: UIBarButtonItem)
|
||||
}
|
||||
|
||||
class TunnelConfigurationTableViewController: UITableViewController {
|
||||
|
||||
@IBOutlet weak var saveButton: UIBarButtonItem!
|
||||
@IBOutlet weak var exportButton: UIBarButtonItem!
|
||||
|
||||
private var viewContext: NSManagedObjectContext!
|
||||
private weak var delegate: TunnelConfigurationTableViewControllerDelegate?
|
||||
|
@ -61,6 +63,10 @@ class TunnelConfigurationTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction func exportTunnel(_ sender: UIBarButtonItem) {
|
||||
self.delegate?.export(tunnel: tunnel, barButtonItem: sender)
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 3
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 730 B |
Loading…
Reference in New Issue