Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b954e9a4fd | |||
| 76894fba68 | |||
| 89a564ce62 | |||
| 178fe86d36 |
@@ -52,6 +52,7 @@
|
|||||||
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
|
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
|
||||||
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
|
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
|
||||||
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
|
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
|
||||||
|
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */; };
|
||||||
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
||||||
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
||||||
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
||||||
@@ -298,6 +299,7 @@
|
|||||||
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
|
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
|
||||||
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTunnelsConfirmationAlert.swift; sourceTree = "<group>"; };
|
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTunnelsConfirmationAlert.swift; sourceTree = "<group>"; };
|
||||||
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
|
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
|
||||||
|
6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacAppStoreUpdateDetector.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
||||||
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
||||||
@@ -632,6 +634,7 @@
|
|||||||
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */,
|
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */,
|
||||||
6FBA104121D6BC210051C35F /* ErrorPresenter.swift */,
|
6FBA104121D6BC210051C35F /* ErrorPresenter.swift */,
|
||||||
6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */,
|
6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */,
|
||||||
|
6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */,
|
||||||
6FB1BD6121D2607E00A991BF /* Assets.xcassets */,
|
6FB1BD6121D2607E00A991BF /* Assets.xcassets */,
|
||||||
6FB1BD6621D2607E00A991BF /* Info.plist */,
|
6FB1BD6621D2607E00A991BF /* Info.plist */,
|
||||||
6FB1BD6721D2607E00A991BF /* WireGuard.entitlements */,
|
6FB1BD6721D2607E00A991BF /* WireGuard.entitlements */,
|
||||||
@@ -1304,6 +1307,7 @@
|
|||||||
6FBA104321D6BC250051C35F /* ErrorPresenter.swift in Sources */,
|
6FBA104321D6BC250051C35F /* ErrorPresenter.swift in Sources */,
|
||||||
6FB1BDC521D50F0300A991BF /* Endpoint.swift in Sources */,
|
6FB1BDC521D50F0300A991BF /* Endpoint.swift in Sources */,
|
||||||
6FB1BDC621D50F0300A991BF /* DNSServer.swift in Sources */,
|
6FB1BDC621D50F0300A991BF /* DNSServer.swift in Sources */,
|
||||||
|
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */,
|
||||||
6FB1BDC721D50F0300A991BF /* InterfaceConfiguration.swift in Sources */,
|
6FB1BDC721D50F0300A991BF /* InterfaceConfiguration.swift in Sources */,
|
||||||
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */,
|
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */,
|
||||||
6FB1BDC821D50F0300A991BF /* PeerConfiguration.swift in Sources */,
|
6FB1BDC821D50F0300A991BF /* PeerConfiguration.swift in Sources */,
|
||||||
@@ -1687,6 +1691,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
|
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@@ -1752,6 +1757,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
|
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
|||||||
@@ -405,3 +405,9 @@
|
|||||||
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
|
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
|
||||||
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
|
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
|
||||||
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
|
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
|
||||||
|
|
||||||
|
// Mac App Store updating alert
|
||||||
|
|
||||||
|
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
|
||||||
|
"macAppStoreUpdatingAlertInfoWithOnDemand (%@)" = "Please disable on-demand for tunnel ‘%@’, deactivate it, and then continue updating in App Store.";
|
||||||
|
"macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)" = "Please deactivate tunnel ‘%@’ and then continue updating in App Store.";
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
VERSION_NAME = 0.0.20190409
|
VERSION_NAME = 0.0.20190423
|
||||||
VERSION_ID = 7
|
VERSION_ID = 8
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class TunnelsManager {
|
|||||||
startObservingTunnelConfigurations()
|
startObservingTunnelConfigurations()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func create(completionHandler: @escaping (WireGuardResult<TunnelsManager>) -> Void) {
|
static func create(completionHandler: @escaping (Result<TunnelsManager, TunnelsManagerError>) -> Void) {
|
||||||
#if targetEnvironment(simulator)
|
#if targetEnvironment(simulator)
|
||||||
completionHandler(.success(TunnelsManager(tunnelProviders: MockTunnels.createMockTunnels())))
|
completionHandler(.success(TunnelsManager(tunnelProviders: MockTunnels.createMockTunnels())))
|
||||||
#else
|
#else
|
||||||
@@ -104,7 +104,7 @@ class TunnelsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(tunnelConfiguration: TunnelConfiguration, onDemandOption: ActivateOnDemandOption = .off, completionHandler: @escaping (WireGuardResult<TunnelContainer>) -> Void) {
|
func add(tunnelConfiguration: TunnelConfiguration, onDemandOption: ActivateOnDemandOption = .off, completionHandler: @escaping (Result<TunnelContainer, TunnelsManagerError>) -> Void) {
|
||||||
let tunnelName = tunnelConfiguration.name ?? ""
|
let tunnelName = tunnelConfiguration.name ?? ""
|
||||||
if tunnelName.isEmpty {
|
if tunnelName.isEmpty {
|
||||||
completionHandler(.failure(TunnelsManagerError.tunnelNameEmpty))
|
completionHandler(.failure(TunnelsManagerError.tunnelNameEmpty))
|
||||||
@@ -167,9 +167,15 @@ class TunnelsManager {
|
|||||||
let tail = tunnelConfigurations.dropFirst()
|
let tail = tunnelConfigurations.dropFirst()
|
||||||
add(tunnelConfiguration: head) { [weak self, tail] result in
|
add(tunnelConfiguration: head) { [weak self, tail] result in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let numberSuccessful = numberSuccessful + (result.isSuccess ? 1 : 0)
|
var numberSuccessfulCount = numberSuccessful
|
||||||
let lastError = lastError ?? (result.error as? TunnelsManagerError)
|
var lastError: TunnelsManagerError?
|
||||||
self?.addMultiple(tunnelConfigurations: tail, numberSuccessful: numberSuccessful, lastError: lastError, completionHandler: completionHandler)
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
|
lastError = error
|
||||||
|
case .success:
|
||||||
|
numberSuccessfulCount = numberSuccessful + 1
|
||||||
|
}
|
||||||
|
self?.addMultiple(tunnelConfigurations: tail, numberSuccessful: numberSuccessfulCount, lastError: lastError, completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ class TunnelImporter {
|
|||||||
if url.pathExtension.lowercased() == "zip" {
|
if url.pathExtension.lowercased() == "zip" {
|
||||||
dispatchGroup.enter()
|
dispatchGroup.enter()
|
||||||
ZipImporter.importConfigFiles(from: url) { result in
|
ZipImporter.importConfigFiles(from: url) { result in
|
||||||
if let error = result.error {
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
lastFileImportErrorText = error.alertText
|
lastFileImportErrorText = error.alertText
|
||||||
}
|
case .success(let configsInZip):
|
||||||
if let configsInZip = result.value {
|
|
||||||
configs.append(contentsOf: configsInZip)
|
configs.append(contentsOf: configsInZip)
|
||||||
}
|
}
|
||||||
dispatchGroup.leave()
|
dispatchGroup.leave()
|
||||||
|
|||||||
@@ -42,19 +42,18 @@ class MainViewController: UISplitViewController {
|
|||||||
TunnelsManager.create { [weak self] result in
|
TunnelsManager.create { [weak self] result in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
if let error = result.error {
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
return
|
case .success(let tunnelsManager):
|
||||||
|
self.tunnelsManager = tunnelsManager
|
||||||
|
self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
|
||||||
|
|
||||||
|
tunnelsManager.activationDelegate = self
|
||||||
|
|
||||||
|
self.onTunnelsManagerReady?(tunnelsManager)
|
||||||
|
self.onTunnelsManagerReady = nil
|
||||||
}
|
}
|
||||||
let tunnelsManager: TunnelsManager = result.value!
|
|
||||||
|
|
||||||
self.tunnelsManager = tunnelsManager
|
|
||||||
self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
|
|
||||||
|
|
||||||
tunnelsManager.activationDelegate = self
|
|
||||||
|
|
||||||
self.onTunnelsManagerReady?(tunnelsManager)
|
|
||||||
self.onTunnelsManagerReady = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,10 +127,10 @@ class TunnelEditTableViewController: UITableViewController {
|
|||||||
} else {
|
} else {
|
||||||
// We're adding a new tunnel
|
// We're adding a new tunnel
|
||||||
tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
|
tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
|
||||||
if let error = result.error {
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
} else {
|
case .success(let tunnel):
|
||||||
let tunnel: TunnelContainer = result.value!
|
|
||||||
self?.dismiss(animated: true, completion: nil)
|
self?.dismiss(animated: true, completion: nil)
|
||||||
self?.delegate?.tunnelSaved(tunnel: tunnel)
|
self?.delegate?.tunnelSaved(tunnel: tunnel)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,9 +264,10 @@ extension TunnelsListTableViewController: QRScanViewControllerDelegate {
|
|||||||
func addScannedQRCode(tunnelConfiguration: TunnelConfiguration, qrScanViewController: QRScanViewController,
|
func addScannedQRCode(tunnelConfiguration: TunnelConfiguration, qrScanViewController: QRScanViewController,
|
||||||
completionHandler: (() -> Void)?) {
|
completionHandler: (() -> Void)?) {
|
||||||
tunnelsManager?.add(tunnelConfiguration: tunnelConfiguration) { result in
|
tunnelsManager?.add(tunnelConfiguration: tunnelConfiguration) { result in
|
||||||
if let error = result.error {
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: qrScanViewController, onDismissal: completionHandler)
|
ErrorPresenter.showErrorAlert(error: error, from: qrScanViewController, onDismissal: completionHandler)
|
||||||
} else {
|
case .success:
|
||||||
completionHandler?()
|
completionHandler?()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,26 +20,25 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
|
|
||||||
TunnelsManager.create { [weak self] result in
|
TunnelsManager.create { [weak self] result in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if let error = result.error {
|
|
||||||
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: nil)
|
ErrorPresenter.showErrorAlert(error: error, from: nil)
|
||||||
return
|
case .success(let tunnelsManager):
|
||||||
|
let statusMenu = StatusMenu(tunnelsManager: tunnelsManager)
|
||||||
|
statusMenu.windowDelegate = self
|
||||||
|
|
||||||
|
let statusItemController = StatusItemController()
|
||||||
|
statusItemController.statusItem.menu = statusMenu
|
||||||
|
|
||||||
|
let tunnelsTracker = TunnelsTracker(tunnelsManager: tunnelsManager)
|
||||||
|
tunnelsTracker.statusMenu = statusMenu
|
||||||
|
tunnelsTracker.statusItemController = statusItemController
|
||||||
|
|
||||||
|
self.tunnelsManager = tunnelsManager
|
||||||
|
self.tunnelsTracker = tunnelsTracker
|
||||||
|
self.statusItemController = statusItemController
|
||||||
}
|
}
|
||||||
|
|
||||||
let tunnelsManager: TunnelsManager = result.value!
|
|
||||||
|
|
||||||
let statusMenu = StatusMenu(tunnelsManager: tunnelsManager)
|
|
||||||
statusMenu.windowDelegate = self
|
|
||||||
|
|
||||||
let statusItemController = StatusItemController()
|
|
||||||
statusItemController.statusItem.menu = statusMenu
|
|
||||||
|
|
||||||
let tunnelsTracker = TunnelsTracker(tunnelsManager: tunnelsManager)
|
|
||||||
tunnelsTracker.statusMenu = statusMenu
|
|
||||||
tunnelsTracker.statusItemController = statusItemController
|
|
||||||
|
|
||||||
self.tunnelsManager = tunnelsManager
|
|
||||||
self.tunnelsTracker = tunnelsTracker
|
|
||||||
self.statusItemController = statusItemController
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +67,36 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
NSApp.terminate(nil)
|
NSApp.terminate(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
||||||
|
if UserDefaults.standard.bool(forKey: "shouldSuppressAppStoreUpdateDetection") {
|
||||||
|
wg_log(.debug, staticMessage: "App Store update detection is suppressed")
|
||||||
|
return .terminateNow
|
||||||
|
}
|
||||||
|
guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
|
||||||
|
return .terminateNow
|
||||||
|
}
|
||||||
|
guard let appleEvent = NSAppleEventManager.shared().currentAppleEvent else {
|
||||||
|
return .terminateNow
|
||||||
|
}
|
||||||
|
guard MacAppStoreUpdateDetector.isUpdatingFromMacAppStore(quitAppleEvent: appleEvent) else {
|
||||||
|
return .terminateNow
|
||||||
|
}
|
||||||
|
let alert = NSAlert()
|
||||||
|
alert.messageText = tr("macAppStoreUpdatingAlertMessage")
|
||||||
|
if currentTunnel.isActivateOnDemandEnabled {
|
||||||
|
alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithOnDemand (%@)", currentTunnel.name)
|
||||||
|
} else {
|
||||||
|
alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)", currentTunnel.name)
|
||||||
|
}
|
||||||
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
|
if let manageWindow = manageTunnelsWindowObject {
|
||||||
|
alert.beginSheetModal(for: manageWindow) { _ in }
|
||||||
|
} else {
|
||||||
|
alert.runModal()
|
||||||
|
}
|
||||||
|
return .terminateCancel
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppDelegate: StatusMenuWindowDelegate {
|
extension AppDelegate: StatusMenuWindowDelegate {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class MacAppStoreUpdateDetector {
|
||||||
|
static func isUpdatingFromMacAppStore(quitAppleEvent: NSAppleEventDescriptor) -> Bool {
|
||||||
|
guard isQuitEvent(quitAppleEvent) else { return false }
|
||||||
|
guard let senderPIDDescriptor = quitAppleEvent.attributeDescriptor(forKeyword: keySenderPIDAttr) else { return false }
|
||||||
|
let pid = senderPIDDescriptor.int32Value
|
||||||
|
guard let executablePath = getExecutablePath(from: pid) else { return false }
|
||||||
|
wg_log(.debug, message: "aevt/quit Apple event received from: \(executablePath)")
|
||||||
|
if executablePath.hasPrefix("/System/Library/") {
|
||||||
|
let executableName = URL(fileURLWithPath: executablePath, isDirectory: false).lastPathComponent
|
||||||
|
return executableName == "com.apple.CommerceKit.StoreAEService"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func isQuitEvent(_ event: NSAppleEventDescriptor) -> Bool {
|
||||||
|
if let eventClassDescriptor = event.attributeDescriptor(forKeyword: keyEventClassAttr),
|
||||||
|
let eventIdDescriptor = event.attributeDescriptor(forKeyword: keyEventIDAttr) {
|
||||||
|
return eventClassDescriptor.typeCodeValue == kCoreEventClass && eventIdDescriptor.typeCodeValue == kAEQuitApplication
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getExecutablePath(from pid: pid_t) -> String? {
|
||||||
|
let bufferSize = Int(PATH_MAX)
|
||||||
|
var buffer = Data(capacity: bufferSize)
|
||||||
|
return buffer.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> String? in
|
||||||
|
if let basePtr = ptr.baseAddress {
|
||||||
|
let byteCount = proc_pidpath(pid, basePtr, UInt32(bufferSize))
|
||||||
|
return byteCount > 0 ? String(cString: basePtr.bindMemory(to: CChar.self, capacity: bufferSize)) : nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -247,13 +247,13 @@ class TunnelEditViewController: NSViewController {
|
|||||||
// We're creating a new tunnel
|
// We're creating a new tunnel
|
||||||
self.tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
|
self.tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
|
||||||
self?.setUserInteractionEnabled(true)
|
self?.setUserInteractionEnabled(true)
|
||||||
if let error = result.error {
|
switch result {
|
||||||
|
case .failure(let error):
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self)
|
ErrorPresenter.showErrorAlert(error: error, from: self)
|
||||||
return
|
case .success(let tunnel):
|
||||||
|
self?.dismiss(self)
|
||||||
|
self?.delegate?.tunnelSaved(tunnel: tunnel)
|
||||||
}
|
}
|
||||||
let tunnel: TunnelContainer = result.value!
|
|
||||||
self?.dismiss(self)
|
|
||||||
self?.delegate?.tunnelSaved(tunnel: tunnel)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,3 +5,8 @@
|
|||||||
#include "ringlogger.h"
|
#include "ringlogger.h"
|
||||||
#include "highlighter.h"
|
#include "highlighter.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
||||||
|
#import "TargetConditionals.h"
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
#include <libproc.h>
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ enum ZipArchiveError: WireGuardAppError {
|
|||||||
case cantOpenInputZipFile
|
case cantOpenInputZipFile
|
||||||
case cantOpenOutputZipFileForWriting
|
case cantOpenOutputZipFileForWriting
|
||||||
case badArchive
|
case badArchive
|
||||||
|
case noTunnelsInZipArchive
|
||||||
|
|
||||||
var alertText: AlertText {
|
var alertText: AlertText {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -16,6 +17,8 @@ enum ZipArchiveError: WireGuardAppError {
|
|||||||
return (tr("alertCantOpenOutputZipFileForWritingTitle"), tr("alertCantOpenOutputZipFileForWritingMessage"))
|
return (tr("alertCantOpenOutputZipFileForWritingTitle"), tr("alertCantOpenOutputZipFileForWritingMessage"))
|
||||||
case .badArchive:
|
case .badArchive:
|
||||||
return (tr("alertBadArchiveTitle"), tr("alertBadArchiveMessage"))
|
return (tr("alertBadArchiveTitle"), tr("alertBadArchiveMessage"))
|
||||||
|
case .noTunnelsInZipArchive:
|
||||||
|
return (tr("alertNoTunnelsInImportedZipArchiveTitle"), tr("alertNoTunnelsInImportedZipArchiveMessage"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,8 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum ZipImporterError: WireGuardAppError {
|
|
||||||
case noTunnelsInZipArchive
|
|
||||||
|
|
||||||
var alertText: AlertText {
|
|
||||||
return (tr("alertNoTunnelsInImportedZipArchiveTitle"), tr("alertNoTunnelsInImportedZipArchiveMessage"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ZipImporter {
|
class ZipImporter {
|
||||||
static func importConfigFiles(from url: URL, completion: @escaping (WireGuardResult<[TunnelConfiguration?]>) -> Void) {
|
static func importConfigFiles(from url: URL, completion: @escaping (Result<[TunnelConfiguration?], ZipArchiveError>) -> Void) {
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
DispatchQueue.global(qos: .userInitiated).async {
|
||||||
var unarchivedFiles: [(fileBaseName: String, contents: Data)]
|
var unarchivedFiles: [(fileBaseName: String, contents: Data)]
|
||||||
do {
|
do {
|
||||||
@@ -28,9 +20,9 @@ class ZipImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if unarchivedFiles.isEmpty {
|
if unarchivedFiles.isEmpty {
|
||||||
throw ZipImporterError.noTunnelsInZipArchive
|
throw ZipArchiveError.noTunnelsInZipArchive
|
||||||
}
|
}
|
||||||
} catch let error as WireGuardAppError {
|
} catch let error as ZipArchiveError {
|
||||||
DispatchQueue.main.async { completion(.failure(error)) }
|
DispatchQueue.main.async { completion(.failure(error)) }
|
||||||
return
|
return
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user