diff --git a/LinkLiar.xcodeproj/project.pbxproj b/LinkLiar.xcodeproj/project.pbxproj index 27311a3..d68b531 100644 --- a/LinkLiar.xcodeproj/project.pbxproj +++ b/LinkLiar.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ C20B96BC2B767D0000F1E2E8 /* CGKeyCode+optionKeyPressed.swift in Sources */ = {isa = PBXBuildFile; fileRef = C20B96BB2B767D0000F1E2E8 /* CGKeyCode+optionKeyPressed.swift */; }; C20B96BD2B767D0000F1E2E8 /* CGKeyCode+optionKeyPressed.swift in Sources */ = {isa = PBXBuildFile; fileRef = C20B96BB2B767D0000F1E2E8 /* CGKeyCode+optionKeyPressed.swift */; }; + C20B96C02B76ACF900F1E2E8 /* PopularVendorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C20B96BF2B76ACF900F1E2E8 /* PopularVendorsTests.swift */; }; C225BDAA2B1FBA3100FFD119 /* ConfigDirectory.swift in Sources */ = {isa = PBXBuildFile; fileRef = C225BDA92B1FBA3100FFD119 /* ConfigDirectory.swift */; }; C225BDAD2B1FBA3A00FFD119 /* Executor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C225BDAB2B1FBA3A00FFD119 /* Executor.swift */; }; C225BDB02B1FBA4000FFD119 /* Listener.swift in Sources */ = {isa = PBXBuildFile; fileRef = C225BDAF2B1FBA4000FFD119 /* Listener.swift */; }; @@ -244,6 +245,7 @@ /* Begin PBXFileReference section */ C20B96BB2B767D0000F1E2E8 /* CGKeyCode+optionKeyPressed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGKeyCode+optionKeyPressed.swift"; sourceTree = ""; }; + C20B96BF2B76ACF900F1E2E8 /* PopularVendorsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopularVendorsTests.swift; sourceTree = ""; }; C225BDA92B1FBA3100FFD119 /* ConfigDirectory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConfigDirectory.swift; path = Classes/ConfigDirectory.swift; sourceTree = ""; }; C225BDAB2B1FBA3A00FFD119 /* Executor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Executor.swift; path = Classes/Executor.swift; sourceTree = ""; }; C225BDAF2B1FBA4000FFD119 /* Listener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Listener.swift; path = Classes/Listener.swift; sourceTree = ""; }; @@ -380,6 +382,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + C20B96BE2B76ACD100F1E2E8 /* Backends */ = { + isa = PBXGroup; + children = ( + C20B96BF2B76ACF900F1E2E8 /* PopularVendorsTests.swift */, + ); + name = Backends; + sourceTree = ""; + }; C225BDA82B1FB9B500FFD119 /* Classes */ = { isa = PBXGroup; children = ( @@ -413,6 +423,7 @@ C23F0DC42B66929100EE94F5 /* LinkTools */ = { isa = PBXGroup; children = ( + C20B96BE2B76ACD100F1E2E8 /* Backends */, C2F701592B6C3553001390E1 /* Config */, C23F0DC52B66929A00EE94F5 /* Models */, ); @@ -1016,6 +1027,7 @@ C24570142B3DB6C5007D7AEA /* MAC.swift in Sources */, C24570122B3DB6B2007D7AEA /* Vendors.swift in Sources */, C24570302B484DFA007D7AEA /* StageTests.swift in Sources */, + C20B96C02B76ACF900F1E2E8 /* PopularVendorsTests.swift in Sources */, C24570112B3DB6AC007D7AEA /* General.swift in Sources */, C2AA40AC2B59A0C4007CD6CB /* SSID.swift in Sources */, C2F7015D2B6C380C001390E1 /* BSSID.swift in Sources */, diff --git a/LinkLiar/Classes/Config/Builder.swift b/LinkLiar/Classes/Config/Builder.swift index d0ef0a8..c67e897 100644 --- a/LinkLiar/Classes/Config/Builder.swift +++ b/LinkLiar/Classes/Config/Builder.swift @@ -235,6 +235,18 @@ extension Config { return dictionary } + func allowScan() -> [String: Any] { + var dictionary = configDictionary + dictionary[Config.Key.scan.rawValue] = true + return dictionary + } + + func denyScan() -> [String: Any] { + var dictionary = configDictionary + dictionary.removeValue(forKey: Config.Key.scan.rawValue) + return dictionary + } + // MARK: - Private Instance Properties private var configDictionary: [String: Any] diff --git a/LinkLiar/Classes/Config/Writer.swift b/LinkLiar/Classes/Config/Writer.swift index d7161b0..dca8e8d 100644 --- a/LinkLiar/Classes/Config/Writer.swift +++ b/LinkLiar/Classes/Config/Writer.swift @@ -165,6 +165,24 @@ extension Config { } } + func allowScan() { + var newDictionary = Config.Builder(state.configDictionary).allowScan() + + newDictionary[Config.Key.version.rawValue] = state.version.formatted + if JSONWriter(Paths.configFile).write(newDictionary) { + state.configDictionary = newDictionary + } + } + + func denyScan() { + var newDictionary = Config.Builder(state.configDictionary).denyScan() + + newDictionary[Config.Key.version.rawValue] = state.version.formatted + if JSONWriter(Paths.configFile).write(newDictionary) { + state.configDictionary = newDictionary + } + } + // MARK: Private Instance Properties private var state: LinkState diff --git a/LinkLiar/Views/Settings/Sections/PreferencesView.swift b/LinkLiar/Views/Settings/Sections/PreferencesView.swift index 9ae5436..5b7981a 100644 --- a/LinkLiar/Views/Settings/Sections/PreferencesView.swift +++ b/LinkLiar/Views/Settings/Sections/PreferencesView.swift @@ -9,8 +9,44 @@ extension SettingsView { @Environment(LinkState.self) private var state var body: some View { - VStack { - Text("Preferences...") + ScrollView { + + GroupBox { + HStack(alignment: .top) { + let scanPermission = Binding( + get: { state.config.general.scan }, + set: { value, _ in + value ? Config.Writer(state).allowScan() : Config.Writer(state).denyScan() + } + ) + + VStack(alignment: .leading, spacing: 3) { + Text("Allow Wi-Fi Network Scanning") + if scanPermission.wrappedValue { + Text(""" + Currently, LinkLiar scans for Wi-Fi networks if you configured \ + an interface to have a specific MAC depending on the presence of a Wi-Fi network SSID. \ + Deactivate this, to prevent LinkLiar from ever scanning for networks. + """) + .font(.caption) + .foregroundColor(.secondary) + } else { + Text(""" + Currently, LinkLiar will never scan for Wi-Fi networks. \ + Even if you configured an Interface to have a specific MAC address \ + if a certain Wi-Fi network SSID is found. Activate this to stat scanning for networks. + """) + .font(.caption) + .foregroundColor(.secondary) + } + } + Spacer() + Toggle(isOn: scanPermission) {} + .toggleStyle(.switch) + .controlSize(.small) + }.padding(4) + } + }.padding() } } diff --git a/LinkLiar/Views/Settings/Sections/TroubleshootView.swift b/LinkLiar/Views/Settings/Sections/TroubleshootView.swift index 9c985ea..42e6080 100644 --- a/LinkLiar/Views/Settings/Sections/TroubleshootView.swift +++ b/LinkLiar/Views/Settings/Sections/TroubleshootView.swift @@ -98,57 +98,57 @@ extension SettingsView { }.padding(4) } - Text("Wi-Fi").font(.headline).padding(.top) - - ForEach(CWWiFiClient.shared().interfaces()!, id: \.self) { interface in - GroupBox { - HStack(alignment: .top) { - Menu { - Button(action: { disassociateWifi() }, label: { - Text("Disassociate") - }) - - Button(action: { LocationManager.instance.requestAlwaysAuthorization() }, label: { - Text("Request authorization") - }) - Divider() - Button(action: { NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices")!) }, label: { - Text("Show Location Settings") - }) - } label: { - if let BSDName = interface.interfaceName { - Text("SSID of \(BSDName)") - - } else { - Text("SSID...") - } - }.menuStyle(.borderlessButton).fixedSize() - Spacer() - - if LocationManager.instance.authorizationStatus == .denied { - Text("L denied") - } else if LocationManager.instance.authorizationStatus == .authorizedAlways { - Text("L authorizedAlways") - } else if LocationManager.instance.authorizationStatus == .notDetermined { - Text("L notDetermined") - - } - - if let ssid = interface.ssid() { - Text(ssid) - } else { - Text("(no SSID)") - } - - if let bssid = interface.bssid() { - Text(bssid) - } else { - Text("(no BSSID)") - } - - }.padding(4) - } - } +// Text("Wi-Fi").font(.headline).padding(.top) + +// ForEach(CWWiFiClient.shared().interfaces()!, id: \.self) { interface in +// GroupBox { +// HStack(alignment: .top) { +// Menu { +// Button(action: { disassociateWifi() }, label: { +// Text("Disassociate") +// }) +// +// Button(action: { LocationManager.instance.requestAlwaysAuthorization() }, label: { +// Text("Request authorization") +// }) +// Divider() +// Button(action: { NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices")!) }, label: { +// Text("Show Location Settings") +// }) +// } label: { +// if let BSDName = interface.interfaceName { +// Text("SSID of \(BSDName)") +// +// } else { +// Text("SSID...") +// } +// }.menuStyle(.borderlessButton).fixedSize() +// Spacer() +// +// if LocationManager.instance.authorizationStatus == .denied { +// Text("L denied") +// } else if LocationManager.instance.authorizationStatus == .authorizedAlways { +// Text("L authorizedAlways") +// } else if LocationManager.instance.authorizationStatus == .notDetermined { +// Text("L notDetermined") +// +// } +// +// if let ssid = interface.ssid() { +// Text(ssid) +// } else { +// Text("(no SSID)") +// } +// +// if let bssid = interface.bssid() { +// Text(bssid) +// } else { +// Text("(no BSSID)") +// } +// +// }.padding(4) +// } +// } Spacer() }.padding() diff --git a/LinkLiar/Views/Settings/Sections/VendorsView.swift b/LinkLiar/Views/Settings/Sections/VendorsView.swift index 073bbcb..4cc0997 100644 --- a/LinkLiar/Views/Settings/Sections/VendorsView.swift +++ b/LinkLiar/Views/Settings/Sections/VendorsView.swift @@ -8,7 +8,6 @@ extension SettingsView { struct VendorsView: View { @Environment(LinkState.self) private var state - @State private var vendors = [Vendor]() @State private var selectedVendors = Set() var body: some View { @@ -32,7 +31,7 @@ extension SettingsView { .width(340) TableColumn("Prefixes") { vendor in - Text("\(vendor.prefixes.count)") + Text("\(vendor.prefixCount)") }.width(50) } }.padding().onAppear { @@ -71,7 +70,6 @@ extension SettingsView { Config.Writer(state).addVendor(vendor) } } - Log.debug("You’ve hit the Space key with \(vendors.count)") } } } diff --git a/LinkLiarTests/PopularVendorsTests.swift b/LinkLiarTests/PopularVendorsTests.swift new file mode 100644 index 0000000..3e0f279 --- /dev/null +++ b/LinkLiarTests/PopularVendorsTests.swift @@ -0,0 +1,14 @@ +// Copyright (c) halo https://github.com/halo/LinkLiar +// SPDX-License-Identifier: MIT + +import XCTest +@testable import LinkLiar + +class PopularVendorsTests: XCTestCase { + func testFind() { + let vendor = PopularVendors.find("dlink") + + XCTAssertEqual("D-link", vendor?.name) + XCTAssertEqual(82, vendor?.prefixCount) + } +} diff --git a/LinkTools/Backends/PopularVendors.swift b/LinkTools/Backends/PopularVendors.swift index 67c6b26..b234ed9 100644 --- a/LinkTools/Backends/PopularVendors.swift +++ b/LinkTools/Backends/PopularVendors.swift @@ -21,8 +21,8 @@ struct PopularVendors { let id = id.filter("0123456789abcdefghijklmnopqrstuvwxyz".contains) guard let vendorData = PopularVendorsDatabase.dictionaryWithCounts[id] else { return nil } - guard let rawPrefixCount = vendorData.values.first else { return nil } guard let name = vendorData.keys.first else { return nil } + guard let rawPrefixCount = vendorData.values.first else { return nil } return Vendor(id: id, name: name, prefixCount: rawPrefixCount) }