diff --git a/Shared/Const.swift b/Shared/Const.swift index 99e82d0..bc5684b 100644 --- a/Shared/Const.swift +++ b/Shared/Const.swift @@ -14,3 +14,15 @@ let config_paths = [ "\(brew_prefix)/etc/wireguard", "/etc/wireguard", ] +let wireguard_bin = "\(brew_prefix)/bin/wg" +let wgquick_bin = "\(brew_prefix)/bin/wg-quick" + +let install_instructions = """ +Currently this Application does not come with WireGuard binaries. It is required to manually install these using Homebrew. + +Please follow the instructions on: + + https://www.wireguard.com/install/ + +and restart this Application afterwards. +""" diff --git a/WireGuardStatusbar.xcodeproj/project.pbxproj b/WireGuardStatusbar.xcodeproj/project.pbxproj index 514db71..9a08fb8 100644 --- a/WireGuardStatusbar.xcodeproj/project.pbxproj +++ b/WireGuardStatusbar.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 04B4BE46211E1E030001213A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04B4BE45211E1E030001213A /* Assets.xcassets */; }; 04B4BE49211E1E030001213A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04B4BE47211E1E030001213A /* MainMenu.xib */; }; 04B92495211F6A68008D964A /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B92494211F6A68008D964A /* Helper.swift */; }; + 04C5AE7621BB13E6007F56D1 /* InstallInstructions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04C5AE7521BB13E6007F56D1 /* InstallInstructions.xib */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -73,6 +74,7 @@ 04B92494211F6A68008D964A /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = ""; }; 04B9249B211F7200008D964A /* Launchd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Launchd.plist; sourceTree = ""; }; 04B9249C211F7215008D964A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 04C5AE7521BB13E6007F56D1 /* InstallInstructions.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstallInstructions.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -126,6 +128,7 @@ 04B4BE43211E1E010001213A /* AppDelegate.swift */, 04B4BE45211E1E030001213A /* Assets.xcassets */, 04B4BE47211E1E030001213A /* MainMenu.xib */, + 04C5AE7521BB13E6007F56D1 /* InstallInstructions.xib */, 04B4BE4A211E1E030001213A /* Info.plist */, 0428EA0A21BAFF0200178BA0 /* PrivilegedHelper.swift */, ); @@ -222,6 +225,7 @@ files = ( 04B4BE46211E1E030001213A /* Assets.xcassets in Resources */, 04B4BE49211E1E030001213A /* MainMenu.xib in Resources */, + 04C5AE7621BB13E6007F56D1 /* InstallInstructions.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WireGuardStatusbar/AppDelegate.swift b/WireGuardStatusbar/AppDelegate.swift index 01a2017..2bca744 100644 --- a/WireGuardStatusbar/AppDelegate.swift +++ b/WireGuardStatusbar/AppDelegate.swift @@ -117,42 +117,55 @@ class AppDelegate: NSObject, NSApplicationDelegate, SKQueueDelegate { // TODO: currently just rebuilding the entire menu, maybe opt for replacing the tunnel entries instead? statusMenu.removeAllItems() - statusMenu.addItem(NSMenuItem(title: "About", action: #selector(AppDelegate.about(_:)), keyEquivalent: "")) statusMenu.addItem(NSMenuItem.separator()) - var connected = false + let fileManager = FileManager.default + if tunnels.isEmpty { statusMenu.addItem(NSMenuItem(title: "No tunnel configurations found", action: nil, keyEquivalent: "")) + } else if fileManager.fileExists(atPath:wireguard_bin) != true { + NSLog("Wireguard binary not found at \(wireguard_bin)") + statusMenu.addItem(NSMenuItem(title: "Wireguard not installed! Click here for instructions", action: #selector(AppDelegate.showInstallInstructions(_:)), keyEquivalent: "")) } else { for (id, tunnel) in tunnels.sorted(by: { $0.0 < $1.0 }) { - let item = NSMenuItem(title: "\(tunnel.interface): \(tunnel.address)", action: #selector(AppDelegate.toggleTunnel(_:)), keyEquivalent: "") - item.representedObject = id - if tunnel.connected { - item.state = NSControl.StateValue.on - connected = true - } - statusMenu.addItem(item) - for peer in tunnel.peers { - statusMenu.addItem(NSMenuItem(title: " \(peer.endpoint): \(peer.allowedIps.joined(separator: ", "))", action: nil, keyEquivalent: "")) - } + addTunnelMenuItem(statusMenu: statusMenu, id: id, tunnel: tunnel) } } statusMenu.addItem(NSMenuItem.separator()) + statusMenu.addItem(NSMenuItem(title: "About", action: #selector(AppDelegate.about(_:)), keyEquivalent: "")) // statusMenu.addItem(NSMenuItem(title: "Preferences...", action: #selector(AppDelegate.preferences(_:)), keyEquivalent: ",")) statusMenu.addItem(NSMenuItem(title: "Quit", action: #selector(AppDelegate.quit(_:)), keyEquivalent: "q")) - // TODO: find better way to do this, computed property or something? - if connected { - let icon = NSImage(named: .connected) + let connected_tunnels = tunnels.filter {$1.connected} + if connected_tunnels.isEmpty { + let icon = NSImage(named: .disconnected) icon!.isTemplate = true statusItem.image = icon } else { - let icon = NSImage(named: .disconnected) + let icon = NSImage(named: .connected) icon!.isTemplate = true statusItem.image = icon } } + func addTunnelMenuItem(statusMenu: NSMenu, id: String, tunnel: Tunnel){ + let item = NSMenuItem(title: "\(tunnel.interface): \(tunnel.address)", action: #selector(AppDelegate.toggleTunnel(_:)), keyEquivalent: "") + item.representedObject = id + if tunnel.connected { + item.state = NSControl.StateValue.on + } + statusMenu.addItem(item) + for peer in tunnel.peers { + statusMenu.addItem(NSMenuItem(title: " \(peer.endpoint): \(peer.allowedIps.joined(separator: ", "))", action: nil, keyEquivalent: "")) + } + } + + @objc func showInstallInstructions(_ sender: NSMenuItem) { + let alert = NSAlert() + alert.messageText = install_instructions + alert.runModal() + } + // load tunnel from configuration files func loadConfiguration() { for config_path in config_paths { diff --git a/WireGuardStatusbar/Info.plist b/WireGuardStatusbar/Info.plist index bd65e79..016b195 100644 --- a/WireGuardStatusbar/Info.plist +++ b/WireGuardStatusbar/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.8 + 1.9 CFBundleVersion 1 LSApplicationCategoryType diff --git a/WireGuardStatusbar/InstallInstructions.xib b/WireGuardStatusbar/InstallInstructions.xib new file mode 100644 index 0000000..c17e76c --- /dev/null +++ b/WireGuardStatusbar/InstallInstructions.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WireGuardStatusbarHelper/WireGuard.swift b/WireGuardStatusbarHelper/WireGuard.swift index 28ca45d..e0dfb7d 100644 --- a/WireGuardStatusbarHelper/WireGuard.swift +++ b/WireGuardStatusbarHelper/WireGuard.swift @@ -11,8 +11,9 @@ import Foundation public class WireGuard { func wg(_ arguments:[String]) -> NSNumber { let task = Process() - task.launchPath = "\(brew_prefix)/bin/wg-quick" + task.launchPath = wgquick_bin task.arguments = arguments + // Add brew bin to path as wg-quick requires Bash 4 instead of macOS provided Bash 3 task.environment = ["PATH": "\(brew_prefix)/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"] let outpipe = Pipe() task.standardOutput = outpipe