Skip to content

Commit

Permalink
Feature Request: Force Wi-Fi on option or Wi-Fi on/off switch in "Con…
Browse files Browse the repository at this point in the history
…figure Wi-Fi" #58
  • Loading branch information
twocanoes committed Jan 2, 2024
1 parent ee95927 commit bfa2801
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 49 deletions.
9 changes: 1 addition & 8 deletions Profile Manifest/com.twocanoes.xcreds.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<key>pfm_app_url</key>
<string>https://github.com/twocanoes/xcreds</string>
<key>pfm_description</key>
<string>XCreds 4.0 (6177) OAuth Settings</string>
<string>XCreds 4.0 (6186) OAuth Settings</string>
<key>pfm_documentation_url</key>
<string>https://twocanoes.com/knowledge-base/xcreds-admin-guide/#preferences</string>
<key>pfm_domain</key>
Expand Down Expand Up @@ -356,8 +356,6 @@ A profile can consist of payloads with different version numbers. For example, c
<key>pfm_type</key>
<string>integer</string>
</dict>


<dict>
<key>pfm_default</key>
<string>Please Wait....</string>
Expand Down Expand Up @@ -386,11 +384,6 @@ A profile can consist of payloads with different version numbers. For example, c
<key>pfm_type</key>
<string>string</string>
</dict>





<dict>
<key>pfm_default</key>
<string>file:///System/Library/Desktop Pictures/Monterey Graphic.heic</string>
Expand Down
1 change: 1 addition & 0 deletions TCTaskWrapperWithBlocks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import <Foundation/Foundation.h>@interface TCTaskWrapperWithBlocks : NSObject { NSTask *task; void (^StartBlock)(void); void (^EndBlock)(void); void (^OutputBlock)(NSString *output); void (^ErrorOutputBlock)(NSString *errorOutput); NSArray *arguments; BOOL isBinaryOutput;}// This is the designated initializer - pass in your controller and any task arguments.// The first argument should be the path to the executable to launch with the NSTask.- (id)initWithStartBlock:(void(^)(void))inStartBlock endBlock:(void(^)(void))inEndBlock outputBlock:(void(^)(NSString *output))inOutputBlock errorOutputBlock:(void(^)(NSString *errorOutput))inErrorOutputBlockBlock arguments:(NSArray *)args;// This method launches the process, setting up asynchronous feedback notifications.- (void) startProcess;// This method stops the process, stoping asynchronous feedback notifications.- (void) stopProcess;-(int)terminationStatus;-(BOOL)isRunning;-(void)terminate;@end
Expand Down
1 change: 1 addition & 0 deletions TCTaskWrapperWithBlocks.m
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import "TCTaskWrapperWithBlocks.h"@implementation TCTaskWrapperWithBlocks// Do basic initialization//- (id)initWithController:(id <TaskWrapperController>)cont arguments:(NSArray *)args//{//// self = [super init];// controller = cont;// arguments = args;// // return self;//}-(id)initWithStartBlock:(void (^)(void))inStartBlock endBlock:(void (^)(void))inEndBlock outputBlock:(void (^)(NSString *))inOutputBlock errorOutputBlock:(void (^)(NSString *))inErrorOutputBlockBlock arguments:(NSArray *)args{ self = [super init]; if (self){ StartBlock=inStartBlock; EndBlock=inEndBlock; OutputBlock=inOutputBlock; ErrorOutputBlock=inErrorOutputBlockBlock; arguments=args; } return self;}// tear things down-(int)terminationStatus{ if ([task isRunning]==YES) { sleep(5); if ([task isRunning]==YES) return -999; } return [task terminationStatus];}// Here's where we actually kick off the process via an NSTask.- (void) startProcess{ // We first let the controller know that we are starting StartBlock(); task=nil; task = [[NSTask alloc] init]; // The output of stdout and stderr is sent to a pipe so that we can catch it later // and send it along to the controller; notice that we don't bother to do anything with stdin, // so this class isn't as useful for a task that you need to send info to, not just receive. [task setStandardOutput: [NSPipe pipe]]; [task setStandardError: [NSPipe pipe]]; [task setStandardInput:[NSPipe pipe]]; [task setLaunchPath: [arguments objectAtIndex:0]]; // The rest of the task arguments are just grabbed from the array [task setArguments: [arguments subarrayWithRange: NSMakeRange (1, ([arguments count] - 1))]]; // Here we register as an observer of the NSFileHandleReadCompletionNotification, which lets // us know when there is data waiting for us to grab it in the task's file handle (the pipe // to which we connected stdout and stderr above). -getData: will be called when there // is data waiting. The reason we need to do this is because if the file handle gets // filled up, the task will block waiting to send data and we'll never get anywhere. // So we have to keep reading data from the file handle as we go. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getData:) name: NSFileHandleReadCompletionNotification object: [[task standardOutput] fileHandleForReading]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getStdErr:) name: NSFileHandleReadCompletionNotification object: [[task standardError] fileHandleForReading]]; // We tell the file handle to go ahead and read in the background asynchronously, and notify // us via the callback registered above when we signed up as an observer. The file handle will // send a NSFileHandleReadCompletionNotification when it has data that is available. [[[task standardOutput] fileHandleForReading] readInBackgroundAndNotify]; [[[task standardError] fileHandleForReading] readInBackgroundAndNotify]; // launch the task asynchronously [task launch]; }// If the task ends, there is no more data coming through the file handle even when the notification is// sent, or the process object is released, then this method is called.- (void) stopProcess{/* // we tell the controller that we finished, via the callback, and then blow away our connection // to the controller. NSTasks are one-shot (not for reuse), so we might as well be too. [controller processFinished]; controller = nil;*/ // It is important to clean up after ourselves so that we don't leave potentially deallocated // objects as observers in the notification center; this can lead to crashes. [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadCompletionNotification object: nil]; // [[NSNotificationCenter defaultCenter] removeObserver:self name:NSTaskDidTerminateNotification object:nil]; // Make sure the task has actually stopped! [task terminate]; EndBlock(); // we tell the controller that we finished, via the callback, and then blow away our connection // to the controller. NSTasks are one-shot (not for reuse), so we might as well be too. // [controller processFinished];// controller = nil;}// This method is called asynchronously when data is available from the task's file handle.// We just pass the data along to the controller as an NSString.- (void) getData: (NSNotification *)aNotification{ NSData *data = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem]; // If the length of the data is zero, then the task is basically over - there is nothing // more to get from the handle so we may as well shut down. if ([data length]) { OutputBlock( [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } else { // We're finished here [self stopProcess]; return; } // we need to schedule the file handle go read more data in the background again. [[aNotification object] readInBackgroundAndNotify]; }- (void) getStdErr: (NSNotification *)aNotification{ NSData *data = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];// // If the length of the data is zero, then the task is basically over - there is nothing// // more to get from the handle so we may as well shut down. if ([data length]) { ErrorOutputBlock([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } //// // we need to schedule the file handle go read more data in the background again. [[aNotification object] readInBackgroundAndNotify];}-(void)dealloc{ }-(void)terminate{ if (task && self.isRunning){ [task terminate]; }}-(BOOL)isRunning{ return task.running;}-(int)pid{ return task==nil?-1:task.processIdentifier;}@end
Expand Down
1 change: 1 addition & 0 deletions XCreds/XCreds-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import <ProductLicense/ProductLicense.h>
#import "TCSLoginWindowUtilities.h"
#import "DNSResolver.h"
#import "TCTaskWrapperWithBlocks.h"

// Kerb bits
#import "KerbUtil.h"
Expand Down
2 changes: 1 addition & 1 deletion XCreds/XCredsLoginPlugin-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#import <ProductLicense/ProductLicense.h>
#include <membership.h>
#import "DNSResolver.h"

#import "TCTaskWrapperWithBlocks.h"
// Kerb bits
#import "KerbUtil.h"
#import "GSSItem.h"
Expand Down
66 changes: 65 additions & 1 deletion XCredsLoginPlugIn/WifiManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ enum SecurityType {
case enterpriseUserPassword //show user and password
}

enum WiFiPowerState:String {
case off = "off"
case on = "on"
}
@objc protocol WifiManagerDelegate: AnyObject {
func wifiManagerFullyFinishedInternetConnectionTimer()
@objc optional func wifiManagerConnectedToNetwork()
Expand All @@ -30,7 +34,7 @@ class WifiManager: CWEventDelegate {
var timer: Timer?
weak var delegate: WifiManagerDelegate?
var monitor:NWPathMonitor?

var task:TCTaskWrapperWithBlocks?
init() {
let defaultInterface = CWWiFiClient.shared().interface()
// CWWiFiClient.shared().delegate = self
Expand All @@ -50,8 +54,64 @@ class WifiManager: CWEventDelegate {
currentInterface = CWWiFiClient.shared().interface(withName: "en1")
}
}

}
func wifiState(completion:@escaping(WiFiPowerState)->Void) {
let interface = wifiInterface()

var output:String = ""
var errOutput = ""
task = TCTaskWrapperWithBlocks(start: {

}, end: {

if output.contains("On") {
completion(.on)
}
else {
completion(.off)

}
}, outputBlock: { outputMsg in
if let outputMsg = outputMsg {
output += outputMsg
}
}, errorOutputBlock: { outputErr in
if let outputErr = outputErr {
errOutput += outputErr
}
}, arguments: ["/usr/sbin/networksetup","-getairportpower", interface])
task?.startProcess()


}

func setWiFiState(_ powerState:WiFiPowerState,completion:@escaping()->Void) {

let interface = wifiInterface()

task = TCTaskWrapperWithBlocks(start: {

}, end: {
completion()
}, outputBlock: { outputMsg in
TCSLogWithMark(outputMsg ?? "")
}, errorOutputBlock: { outputErr in
TCSLogWithMark(outputErr ?? "")
}, arguments: ["/usr/sbin/networksetup","-setairportpower", interface,powerState.rawValue])
task?.startProcess()

}
func wifiInterface() -> String {
let names = CWWiFiClient.interfaceNames()

if names?.contains("en0") != nil {
return "en0"
}
else {
return "en1"
}
}
func getCurrentSSID() -> String? {
TCSLogWithMark()
return currentInterface?.ssid()
Expand Down Expand Up @@ -132,6 +192,10 @@ class WifiManager: CWEventDelegate {
return false
}

func turnWiFiOff() {


}
func connectWifi(with network: CWNetwork, password: String?, username: String?, identity: SecIdentity? = nil) -> Bool {
var result = false

Expand Down
37 changes: 36 additions & 1 deletion XCredsLoginPlugIn/WifiWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class WifiWindowController: NSWindowController, WifiManagerDelegate, NSMenuDeleg
@IBOutlet weak var addSSIDText: NSTextField?
@IBOutlet weak var addSSIDLabel: NSTextField?

@IBOutlet weak var wifiSwitch: NSSwitch!
@IBOutlet weak var networkUsernameLabel: NSTextField!
@IBOutlet weak var wifiPopupMenu: NSMenu!
@IBAction func help(_ sender: Any) {
Expand Down Expand Up @@ -65,6 +66,16 @@ class WifiWindowController: NSWindowController, WifiManagerDelegate, NSMenuDeleg
TCSLogWithMark("adding wifi networks")
certificatePopupButton.addItems(withTitles: WifiManager().identityCommonNames())


wifiManager.wifiState() { state in
switch state {
case .off:
self.wifiSwitch.state = .off

case .on:
self.wifiSwitch.state = .on
}
}
}


Expand Down Expand Up @@ -105,7 +116,6 @@ class WifiWindowController: NSWindowController, WifiManagerDelegate, NSMenuDeleg
self.networkConnectionSpinner?.stopAnimation(self)
self.networkConnectionSpinner?.isHidden=true
self.updateNetworks()

}
}

Expand Down Expand Up @@ -199,6 +209,31 @@ class WifiWindowController: NSWindowController, WifiManagerDelegate, NSMenuDeleg
}


@IBAction func wifiButtonPressed(_ sender: NSSwitch) {

if sender.state == .off {
wifiManager.setWiFiState(.off) {
self.updateAvailableNetworks()



}
}
else {
wifiManager.setWiFiState(.on) {
self.networkWifiPopup?.isEnabled=false
self.networkConnectionSpinner?.startAnimation(true)
self.networkConnectionSpinner?.isHidden=false

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.updateAvailableNetworks()
}
}
}
TCSLogWithMark("Wifi Button Switch changed")


}
func configureUIForSelectedNetwork(network: CWNetwork) {
self.networkUsername?.stringValue = ""
self.networkPassword?.stringValue = ""
Expand Down

0 comments on commit bfa2801

Please sign in to comment.