1 Commits
Author SHA1 Message Date
Patrick Wardle 829f0d779d new triggers (work in progress)
expanding triggers to include:
 usb trigger
 power trigger
2018-08-23 16:25:32 -10:00
39 changed files with 1634 additions and 901 deletions
-7
View File
@@ -12,7 +12,6 @@
#import "Configure.h"
#import "HelperComms.h"
#import "AboutWindowController.h"
#import "ErrorWindowController.h"
#import "ConfigureWindowController.h"
//block for install/uninstall
@@ -41,16 +40,10 @@ typedef void (^block)(NSNumber*);
//configure window controller
@property(nonatomic, retain)ConfigureWindowController* configureWindowController;
//error window controller
@property(nonatomic, retain)ErrorWindowController* errorWindowController;
/* METHODS */
//display configuration window w/ 'install' || 'uninstall' button
-(void)displayConfigureWindow:(BOOL)isInstalled;
//display error window
-(void)displayErrorWindow:(NSDictionary*)errorInfo;
@end
-109
View File
@@ -27,7 +27,6 @@
@synthesize configureObj;
@synthesize aboutWindowController;
@synthesize errorWindowController;
@synthesize configureWindowController;
//main app interface
@@ -41,17 +40,6 @@
//start crash handler
[SentryClient.sharedClient startCrashHandlerWithError:nil];
//make sure system is supported (lid)
// if not, will inform user via alert
if(YES != [self isSupported])
{
//dbg msg
logMsg(LOG_ERR, @"device doesn't appear to have a lid (i.e. is unsupported)");
//exit
[NSApp terminate:self];
}
//alloc/init Config obj
configureObj = [[Configure alloc] init];
@@ -61,51 +49,6 @@
return;
}
//check if there's a lid
// if not, alert to tell user
-(BOOL)isSupported
{
//flag
BOOL supported = NO;
//alert
NSAlert* alert = nil;
//no lid
// can't support!
if(stateUnavailable == getLidState())
{
//init alert
alert = [[NSAlert alloc] init];
//set main text
alert.messageText = @"Unsupported Device";
//set informative text
alert.informativeText = [NSString stringWithFormat:@"'%@' does not appear to be a laptop", [[NSHost currentHost] localizedName]];
//add button
[alert addButtonWithTitle:@"Ok"];
//set style
alert.alertStyle = NSAlertStyleWarning;
//show it
[alert runModal];
//bail
goto bail;
}
//happy
supported = YES;
bail:
return supported;
}
//exit when last window is closed
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
@@ -143,58 +86,6 @@ bail:
return;
}
//display error window
-(void)displayErrorWindow:(NSDictionary*)errorInfo
{
//alloc error window
errorWindowController = [[ErrorWindowController alloc] initWithWindowNibName:@"ErrorWindowController"];
//main thread
// just show UI alert, unless its fatal (then load URL)
if(YES == [NSThread isMainThread])
{
//non-fatal errors
// show error error popup
if(YES != [errorInfo[KEY_ERROR_URL] isEqualToString:FATAL_ERROR_URL])
{
//display it
// call this first to so that outlets are connected
[self.errorWindowController display];
//configure it
[self.errorWindowController configure:errorInfo];
}
//fatal error
// launch browser to go to fatal error page, then exit
else
{
//launch browser
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:errorInfo[KEY_ERROR_URL]]];
//then exit
[NSApp terminate:self];
}
}
//background thread
// have to show error window on main thread
else
{
//show alert
// in main UI thread
dispatch_sync(dispatch_get_main_queue(), ^{
//display it
// call this first to so that outlets are connected
[self.errorWindowController display];
//configure it
[self.errorWindowController configure:errorInfo];
});
}
return;
}
//menu handler for 'about'
-(IBAction)displayAboutWindow:(id)sender
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -22,7 +22,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="460" height="176"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
<autoresizingMask key="autoresizingMask"/>
@@ -1,43 +0,0 @@
//
// file: ErrorWindowController.h
// project: DND (config)
// description: error window (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
@import Cocoa;
@interface ErrorWindowController : NSWindowController <NSWindowDelegate>
{
}
//main msg in window
@property (weak, atomic) IBOutlet NSTextField *errMsg;
//sub msg in window
@property (weak, atomic) IBOutlet NSTextField *errSubMsg;
//info/help/fix button
@property (weak, atomic) IBOutlet NSButton *infoButton;
//close button
@property (weak, atomic) IBOutlet NSButton *closeButton;
//(optional) url for 'Info' button
@property(nonatomic, retain) NSURL* errorURL;
//flag indicating close button should exit app
@property(atomic) BOOL shouldExit;
/* METHODS */
//configure the object/window
-(void)configure:(NSDictionary*)errorInfo;
//display (show) window
-(void)display;
@end
-156
View File
@@ -1,156 +0,0 @@
//
// file: ErrorWindowController.m
// project: DND (config)
// description: error window
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "ErrorWindowController.h"
@interface ErrorWindowController ()
@end
@implementation ErrorWindowController
@synthesize errorURL;
@synthesize shouldExit;
@synthesize closeButton;
//automatically called when nib is loaded
// center window
-(void)awakeFromNib
{
//center
[self.window center];
return;
}
//configure the object/window
-(void)configure:(NSDictionary*)errorInfo
{
//set error msg
self.errMsg.stringValue = errorInfo[KEY_ERROR_MSG];
//set error sub msg
self.errSubMsg.stringValue = errorInfo[KEY_ERROR_SUB_MSG];
//save exit
self.shouldExit = [errorInfo[KEY_ERROR_SHOULD_EXIT] boolValue];
//grab optional error url
if(nil != errorInfo[KEY_ERROR_URL])
{
//extract/convert
self.errorURL = [NSURL URLWithString:errorInfo[KEY_ERROR_URL]];
}
//when exiting
// change 'close' to 'exit'
if(YES == self.shouldExit)
{
//change title
self.closeButton.title = @"Exit";
}
//for fatal errors
// change 'Info' to 'help fix'
if(YES == [[self.errorURL absoluteString] isEqualToString:FATAL_ERROR_URL])
{
//change title
self.infoButton.title = @"Help Fix";
}
//set delegate
[self.window setDelegate:self];
return;
}
//display (show) window
-(void)display
{
//show (now configured), alert
[self showWindow:self];
//make it key window
[self.window makeKeyAndOrderFront:self];
//make window front
[NSApp activateIgnoringOtherApps:YES];
//make 'close' have focus
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
//make close button active
[self.window makeFirstResponder:self.closeButton];
});
//make white
[self.window setBackgroundColor: NSColor.whiteColor];
return;
}
//invoked when user clicks '?' (help button)
// open url with more info about the error(s)
-(IBAction)help:(id)sender
{
#pragma unused(sender)
//if a url was specified
// use that one
if(nil != self.errorURL)
{
//open URL
// invokes user's default browser
[[NSWorkspace sharedWorkspace] openURL:self.errorURL];
}
//use default URL
else
{
//open URL
// invokes user's default browser
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:FATAL_ERROR_URL]];
}
return;
}
//invoked when user clicks 'close'
// just close window
-(IBAction)close:(id)sender
{
#pragma unused(sender)
//close
[self.window close];
return;
}
//automatically invoked when window is closing
// exit the app if specified...
-(void)windowWillClose:(NSNotification *)notification
{
#pragma unused(notification)
//check if should exit process
// e.g. an error during install, etc
if(YES == self.shouldExit)
{
//dbg msg
//logMsg(LOG_DEBUG, @"exiting application");
//exit
[NSApp terminate:self];
}
return;
}
@end
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ErrorWindowController">
<connections>
<outlet property="closeButton" destination="zbs-ul-WTJ" id="1fu-zv-brA"/>
<outlet property="errMsg" destination="Act-U9-8G9" id="PMa-6M-gwu"/>
<outlet property="errSubMsg" destination="tQ0-f2-G4C" id="4hz-9M-Gub"/>
<outlet property="infoButton" destination="sNV-Jw-9dZ" id="qdf-xQ-ubf"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Do Not Disturb Error" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="744" y="427" width="380" height="137"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="380" height="137"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zbs-ul-WTJ">
<rect key="frame" x="284" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pjp-Se-SfK">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="close:" target="-2" id="sez-MW-4AE"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="0.0" translatesAutoresizingMaskIntoConstraints="NO" id="tQ0-f2-G4C">
<rect key="frame" x="114" y="49" width="248" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Label" id="sk0-EF-ZfG">
<font key="font" size="11" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="0.0" translatesAutoresizingMaskIntoConstraints="NO" id="Act-U9-8G9">
<rect key="frame" x="114" y="88" width="248" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="ERROR msg" id="VCu-zh-Vcs">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sNV-Jw-9dZ">
<rect key="frame" x="202" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Info" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="L1w-RB-EC4">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="help:" target="-2" id="gCm-No-dHq"/>
</connections>
</button>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sRj-I0-15e">
<rect key="frame" x="12" y="35" width="92" height="92"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="dndIcon" id="9iG-ot-b7i"/>
</imageView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="257" y="269.5"/>
</window>
</objects>
<resources>
<image name="dndIcon" width="256" height="256"/>
</resources>
</document>
@@ -16,12 +16,10 @@
BF04235611C0531400431286 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BF04235511C0531400431286 /* AppDelegate.m */; };
BF65C19111B985C0007C20AB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF65C19011B985C0007C20AB /* MainMenu.xib */; };
CD17D53B20104DD700F798D7 /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17D53820104DD700F798D7 /* Logging.m */; };
CD17D54D20104EE700F798D7 /* ErrorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD17D54320104EE600F798D7 /* ErrorWindowController.xib */; };
CD17D54E20104EE700F798D7 /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD17D54420104EE700F798D7 /* AboutWindow.xib */; };
CD17D54F20104EE700F798D7 /* Configure.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17D54720104EE700F798D7 /* Configure.m */; };
CD17D55020104EE700F798D7 /* ConfigureWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17D54820104EE700F798D7 /* ConfigureWindowController.m */; };
CD17D55120104EE700F798D7 /* ConfigureWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD17D54920104EE700F798D7 /* ConfigureWindowController.xib */; };
CD17D55220104EE700F798D7 /* ErrorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17D54A20104EE700F798D7 /* ErrorWindowController.m */; };
CD17D55320104EE700F798D7 /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17D54B20104EE700F798D7 /* AboutWindowController.m */; };
CD17D55E201148F900F798D7 /* configure.sh in Resources */ = {isa = PBXBuildFile; fileRef = CD17D55D201148F900F798D7 /* configure.sh */; };
CD17D56320116C3800F798D7 /* com.objective-see.dnd.plist in Resources */ = {isa = PBXBuildFile; fileRef = CD17D56220116C3800F798D7 /* com.objective-see.dnd.plist */; };
@@ -95,16 +93,13 @@
CD17D53A20104DD700F798D7 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../shared/Logging.h; sourceTree = "<group>"; };
CD17D53E20104E5A00F798D7 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Consts.h; path = ../../shared/Consts.h; sourceTree = "<group>"; };
CD17D54220104EE600F798D7 /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutWindowController.h; sourceTree = "<group>"; };
CD17D54320104EE600F798D7 /* ErrorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ErrorWindowController.xib; sourceTree = "<group>"; };
CD17D54420104EE700F798D7 /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutWindow.xib; sourceTree = "<group>"; };
CD17D54520104EE700F798D7 /* Configure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Configure.h; sourceTree = "<group>"; };
CD17D54620104EE700F798D7 /* ConfigureWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigureWindowController.h; sourceTree = "<group>"; };
CD17D54720104EE700F798D7 /* Configure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Configure.m; sourceTree = "<group>"; };
CD17D54820104EE700F798D7 /* ConfigureWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigureWindowController.m; sourceTree = "<group>"; };
CD17D54920104EE700F798D7 /* ConfigureWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ConfigureWindowController.xib; sourceTree = "<group>"; };
CD17D54A20104EE700F798D7 /* ErrorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ErrorWindowController.m; sourceTree = "<group>"; };
CD17D54B20104EE700F798D7 /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutWindowController.m; sourceTree = "<group>"; };
CD17D54C20104EE700F798D7 /* ErrorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorWindowController.h; sourceTree = "<group>"; };
CD17D55D201148F900F798D7 /* configure.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.sh; sourceTree = "<group>"; };
CD17D56220116C3800F798D7 /* com.objective-see.dnd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "com.objective-see.dnd.plist"; path = "../launchDaemon/launchDaemon/com.objective-see.dnd.plist"; sourceTree = "<group>"; };
CD18D64C200DA301005609F9 /* XPCProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPCProtocol.h; path = Shared/XPCProtocol.h; sourceTree = SOURCE_ROOT; };
@@ -192,9 +187,6 @@
CD17D54620104EE700F798D7 /* ConfigureWindowController.h */,
CD17D54820104EE700F798D7 /* ConfigureWindowController.m */,
CD17D54920104EE700F798D7 /* ConfigureWindowController.xib */,
CD17D54C20104EE700F798D7 /* ErrorWindowController.h */,
CD17D54A20104EE700F798D7 /* ErrorWindowController.m */,
CD17D54320104EE600F798D7 /* ErrorWindowController.xib */,
CD73DA98200490B4001FFC84 /* HelperComms.h */,
CD73DA97200490B4001FFC84 /* HelperComms.m */,
4BE4904C10445D49006BE471 /* Info.plist */,
@@ -344,7 +336,6 @@
buildActionMask = 2147483647;
files = (
CD2F4082204B462E0066673E /* dndText.png in Resources */,
CD17D54D20104EE700F798D7 /* ErrorWindowController.xib in Resources */,
CDAAC24C20226DFB0032F2E6 /* logo.png in Resources */,
CD17D56320116C3800F798D7 /* com.objective-see.dnd.plist in Resources */,
CDAAC24B20226DFB0032F2E6 /* objectiveSee.png in Resources */,
@@ -392,7 +383,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CD17D55220104EE700F798D7 /* ErrorWindowController.m in Sources */,
4BE4905110445D49006BE471 /* main.m in Sources */,
CD73DA942004633A001FFC84 /* HelperListener.m in Sources */,
CD17D55320104EE700F798D7 /* AboutWindowController.m in Sources */,
@@ -84,7 +84,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
+2
View File
@@ -22,6 +22,8 @@
<string>Copyright © 2018 Objective-See. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
<key>NSCameraUsageDescription</key>
<string></string>
<key>LSUIElement</key>
<true/>
</dict>
@@ -55,8 +55,11 @@
CD256E062050DE9B00768457 /* ThunderboltMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = CD256DF32050DE4C00768457 /* ThunderboltMonitor.m */; };
CD256E072050DE9B00768457 /* USBMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = CD256DF52050DE4C00768457 /* USBMonitor.m */; };
CD256E082050DE9B00768457 /* UserAuthMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = CD256DED2050DE4B00768457 /* UserAuthMonitor.m */; };
CD2C85F42119D9D5007CF784 /* LidTrigger.m in Sources */ = {isa = PBXBuildFile; fileRef = CD27BC6321139AD70017AEFD /* LidTrigger.m */; };
CD2C85F82119FC02007CF784 /* DeviceTrigger.m in Sources */ = {isa = PBXBuildFile; fileRef = CD2C85F52119FB2A007CF784 /* DeviceTrigger.m */; };
CD2C85FC211A0084007CF784 /* PowerTrigger.m in Sources */ = {isa = PBXBuildFile; fileRef = CD2C85FA211A006F007CF784 /* PowerTrigger.m */; };
CDA993A62048905D00C1E9CD /* FrameworkInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA993A42048905D00C1E9CD /* FrameworkInterface.m */; };
CE60F9C91FC9BBE500EFFDDA /* Lid.m in Sources */ = {isa = PBXBuildFile; fileRef = CE60F9C81FC9BBE500EFFDDA /* Lid.m */; };
CE60F9C91FC9BBE500EFFDDA /* Triggers.m in Sources */ = {isa = PBXBuildFile; fileRef = CE60F9C81FC9BBE500EFFDDA /* Triggers.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -179,13 +182,19 @@
CD256DF82050DE4C00768457 /* Monitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Monitor.h; path = launchDaemon/monitor/Monitor.h; sourceTree = SOURCE_ROOT; };
CD256DFF2050DE6600768457 /* ProcListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProcListener.h; path = launchDaemon/monitor/ProcListener.h; sourceTree = SOURCE_ROOT; };
CD256E002050DE6600768457 /* ProcListener.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProcListener.m; path = launchDaemon/monitor/ProcListener.m; sourceTree = SOURCE_ROOT; };
CD27BC6321139AD70017AEFD /* LidTrigger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LidTrigger.m; path = triggers/LidTrigger.m; sourceTree = "<group>"; };
CD27BC6421139AD70017AEFD /* LidTrigger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LidTrigger.h; path = triggers/LidTrigger.h; sourceTree = "<group>"; };
CD2C85F52119FB2A007CF784 /* DeviceTrigger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DeviceTrigger.m; path = triggers/DeviceTrigger.m; sourceTree = "<group>"; };
CD2C85F62119FB2A007CF784 /* DeviceTrigger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeviceTrigger.h; path = triggers/DeviceTrigger.h; sourceTree = "<group>"; };
CD2C85F9211A006F007CF784 /* PowerTrigger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PowerTrigger.h; path = triggers/PowerTrigger.h; sourceTree = "<group>"; };
CD2C85FA211A006F007CF784 /* PowerTrigger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PowerTrigger.m; path = triggers/PowerTrigger.m; sourceTree = "<group>"; };
CD3307C5203639AD00F10D71 /* procInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = procInfo.h; path = launchDaemon/libs/procInfo.h; sourceTree = "<group>"; };
CD3307C82036518400F10D71 /* main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = "<group>"; };
CDA993A32048905D00C1E9CD /* FrameworkInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameworkInterface.h; sourceTree = "<group>"; };
CDA993A42048905D00C1E9CD /* FrameworkInterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FrameworkInterface.m; sourceTree = "<group>"; };
CDAAC245202259B50032F2E6 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Consts.h; path = ../../shared/Consts.h; sourceTree = "<group>"; };
CE60F9C71FC9BBE500EFFDDA /* Lid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Lid.h; sourceTree = "<group>"; };
CE60F9C81FC9BBE500EFFDDA /* Lid.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Lid.m; sourceTree = "<group>"; };
CE60F9C71FC9BBE500EFFDDA /* Triggers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Triggers.h; sourceTree = "<group>"; };
CE60F9C81FC9BBE500EFFDDA /* Triggers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Triggers.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -277,12 +286,13 @@
7D7755D21F02DF9500D0017D /* src */ = {
isa = PBXGroup;
children = (
CD27BC6221139A800017AEFD /* triggers */,
CD256DEC2050DE3200768457 /* monitor */,
7D7756071F05D62E00D0017D /* shared */,
7DD2BF721F1E9CE700B33214 /* NSMutableArray+QueueAdditions.h */,
7DD2BF731F1E9CE700B33214 /* NSMutableArray+QueueAdditions.m */,
CE60F9C71FC9BBE500EFFDDA /* Lid.h */,
CE60F9C81FC9BBE500EFFDDA /* Lid.m */,
CE60F9C71FC9BBE500EFFDDA /* Triggers.h */,
CE60F9C81FC9BBE500EFFDDA /* Triggers.m */,
CDA993A32048905D00C1E9CD /* FrameworkInterface.h */,
CDA993A42048905D00C1E9CD /* FrameworkInterface.m */,
CD227869204648E000C72C76 /* Preferences.h */,
@@ -336,6 +346,19 @@
path = monitor;
sourceTree = "<group>";
};
CD27BC6221139A800017AEFD /* triggers */ = {
isa = PBXGroup;
children = (
CD2C85F9211A006F007CF784 /* PowerTrigger.h */,
CD2C85FA211A006F007CF784 /* PowerTrigger.m */,
CD2C85F62119FB2A007CF784 /* DeviceTrigger.h */,
CD2C85F52119FB2A007CF784 /* DeviceTrigger.m */,
CD27BC6421139AD70017AEFD /* LidTrigger.h */,
CD27BC6321139AD70017AEFD /* LidTrigger.m */,
);
name = triggers;
sourceTree = "<group>";
};
CD3307C42036399900F10D71 /* Supporting Files */ = {
isa = PBXGroup;
children = (
@@ -446,6 +469,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CD2C85FC211A0084007CF784 /* PowerTrigger.m in Sources */,
CD2C85F82119FC02007CF784 /* DeviceTrigger.m in Sources */,
CD2C85F42119D9D5007CF784 /* LidTrigger.m in Sources */,
CD20869B208E8F0200BA1D0A /* VolumeMonitor.m in Sources */,
CD256E022050DE9B00768457 /* ProcListener.m in Sources */,
CD256E032050DE9B00768457 /* AuthEvent.m in Sources */,
@@ -457,7 +483,7 @@
CD22786C20464A6E00C72C76 /* Preferences.m in Sources */,
CDA993A62048905D00C1E9CD /* FrameworkInterface.m in Sources */,
7D46FEFF1F5E41F000FEB0F8 /* UserCommsListener.m in Sources */,
CE60F9C91FC9BBE500EFFDDA /* Lid.m in Sources */,
CE60F9C91FC9BBE500EFFDDA /* Triggers.m in Sources */,
7DD2BF761F1E9CE700B33214 /* NSMutableArray+QueueAdditions.m in Sources */,
7DD2BF681F1DC42700B33214 /* Utilities.m in Sources */,
7DD2BF771F1E9CE700B33214 /* Queue.m in Sources */,
+78 -16
View File
@@ -7,16 +7,16 @@
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Lid.h"
#import "consts.h"
#import "logging.h"
#import "Triggers.h"
#import "Preferences.h"
#import "FrameworkInterface.h"
/* GLOBALS */
//lid obj
extern Lid* lid;
//trigger obj
extern Triggers* triggers;
//DND framework interface obj
extern FrameworkInterface* framework;
@@ -160,28 +160,27 @@ bail:
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"updating preferences (%@)", updates]);
//user setting state?
// toggle the state of the daemon (lid) watcher too
// toggle the state of the daemon triggers too
if(nil != updates[PREF_IS_DISABLED])
{
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"client toggling state: %@", updates[PREF_IS_DISABLED]]);
//disable?
//disable triggers
if(YES == [updates[PREF_IS_DISABLED] boolValue])
{
//dbg msg
// and log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, @"disabling...");
//unregister for lid notifications
[lid unregister4Notifications];
//turn off all triggers
[triggers toggle:ALL_TRIGGERS state:NSOffState];
//dbg msg
logMsg(LOG_DEBUG, @"unregistered for lid change notifications");
logMsg(LOG_DEBUG, @"disabled triggers");
//cancel all lid notifications
// ...will also disconnect client
[lid cancelDispatchBlocks];
//cancel all dispatch blocks
[triggers cancelDispatchBlocks];
//dbg msg
logMsg(LOG_DEBUG, @"cancelled all dispatch blocks (disconnecting any connected iOS client)");
@@ -190,18 +189,81 @@ bail:
[[NSNotificationCenter defaultCenter] postNotificationName:DISMISS_NOTIFICATION object:nil userInfo:nil];
}
//enable?
//enable triggers
else
{
//dbg msg
// and log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, @"enabling...");
//register for lid notifications
[lid register4Notifications];
//turn off all triggers
[triggers toggle:ALL_TRIGGERS state:NSOnState];
//dbg msg
logMsg(LOG_DEBUG, @"registered for lid change notifications");
logMsg(LOG_DEBUG, @"enabled (all) triggers");
}
}
//toggle lid triggers
if(nil != updates[PREF_LID_TRIGGER])
{
//dbg msg
logMsg(LOG_DEBUG, @"toggling lid notifications");
//enable lid trigger
if(YES == [updates[PREF_LID_TRIGGER] boolValue])
{
//enable
[triggers toggle:LID_TRIGGER state:NSOnState];
}
//disable lid trigger
else
{
//disable
[triggers toggle:LID_TRIGGER state:NSOffState];
}
}
//toggle device triggers
if(nil != updates[PREF_DEVICE_TRIGGER])
{
//dbg msg
logMsg(LOG_DEBUG, @"toggling device notifications");
//enable device trigger
if(YES == [updates[PREF_DEVICE_TRIGGER] boolValue])
{
//enable
[triggers toggle:DEVICE_TRIGGER state:NSOnState];
}
//disable device trigger
else
{
//disable
[triggers toggle:DEVICE_TRIGGER state:NSOffState];
}
}
//toggle power triggers
if(nil != updates[PREF_POWER_TRIGGER])
{
//dbg msg
logMsg(LOG_DEBUG, @"toggling power notifications");
//enable power trigger
if(YES == [updates[PREF_POWER_TRIGGER] boolValue])
{
//enable
[triggers toggle:POWER_TRIGGER state:NSOnState];
}
//disable power trigger
else
{
//disable
[triggers toggle:POWER_TRIGGER state:NSOffState];
}
}
@@ -1,20 +1,19 @@
//
// file: Lid.h
// file: Triggers.m
// project: DND (launch daemon)
// description: monitor and alert logic for lid open events (header)
// description: generic management of various triggers (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Utilities.h"
#import "LidTrigger.h"
#import "PowerTrigger.h"
#import "DeviceTrigger.h"
#import <dnd/dnd-Swift.h>
@import Foundation;
#import <IOKit/IOKitLib.h>
#import <IOKit/pwr_mgt/IOPM.h>
/* FUNCTIONS */
//check if user auth'd
@@ -24,26 +23,25 @@ BOOL authViaTouchID(void);
/* CLASS INTERFACE */
@interface Lid : NSObject <DNDClientMacDelegate>
@interface Triggers : NSObject <DNDClientMacDelegate>
{
//lid state
LidState lidState;
//dispatch queue
dispatch_queue_t dispatchQ;
//notification port
IONotificationPortRef notificationPort;
//notification object
io_object_t notification;
}
/* PROPERTIES */
//lid trigger obj
@property(nonatomic, retain)LidTrigger* lidTrigger;
//device(s) trigger obj
@property(nonatomic, retain)DeviceTrigger* deviceTrigger;
//power trigger obj
@property(nonatomic, retain)PowerTrigger* powerTrigger;
//client
@property(nonatomic, retain)DNDClientMac *client;
@property(nonatomic, retain)DNDClientMac* client;
//dismiss dispatch group
@property(nonatomic, retain)dispatch_group_t dispatchGroup;
@@ -54,11 +52,15 @@ BOOL authViaTouchID(void);
//dispatch blocks
@property(nonatomic, retain)NSMutableArray* dispatchBlocks;
//TODO: make dictionary w/ alert
//latest undeliveried alert
@property(nonatomic, retain)NSDate* undeliveredAlert;
/* METHODS */
//toggle trigger(s)
-(void)toggle:(NSUInteger)type state:(NSControlStateValue)state;
//check if client should be init'd
-(BOOL)shouldInitClient;
@@ -68,14 +70,8 @@ BOOL authViaTouchID(void);
//cancel all dipatch blocks
-(void)cancelDispatchBlocks;
//register for notifications
-(BOOL)register4Notifications;
//register for notifications
-(void)unregister4Notifications;
//proces lid open event
-(void)processEvent:(NSDate*)timestamp user:(NSString*)user;
//process trigger event
-(void)processEvent:(NSUInteger)type info:(NSDictionary*)info;
//wait for dismiss
// note: handles multiple client via dispatch group
@@ -1,19 +1,16 @@
// file: Lid.m
// file: Triggers.m
// project: DND (launch daemon)
// description: monitor and alert logic for lid open events
// description: generic management of various triggers
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
// code inspired by:
// https://github.com/zarigani/ClamshellWake/blob/master/ClamshellWake.cpp
// https://github.com/dustinrue/ControlPlane/blob/master/Source/LaptopLidEvidenceSource.m
// note: manually get state from terminal via:
// ioreg -r -k AppleClamshellState -d 4 | grep AppleClamshellState
#import "Lid.h"
#import "Consts.h"
#import "Queue.h"
#import "Logging.h"
#import "Monitor.h"
#import "Triggers.h"
#import "AuthEvent.h"
#import "Utilities.h"
#import "Preferences.h"
@@ -22,12 +19,8 @@
/* GLOBALS */
//last state
// sometimes multiple notifications are delivered!?
LidState lastLidState;
//lid obj
extern Lid* lid;
//trigger obj
extern Triggers* triggers;
//queue object
extern Queue* eventQueue;
@@ -41,123 +34,6 @@ extern Preferences* preferences;
//DND framework interface obj
extern FrameworkInterface* framework;
//callback for power/lid events
static void pmDomainChange(void *refcon, io_service_t service, uint32_t messageType, void *messageArgument)
{
//lid state
int lidState = stateUnavailable;
//sleep bit
int sleepState = -1;
//preferences
NSDictionary* currentPrefs = nil;
//timestamp
NSDate* timestamp = nil;
//init timestamp
timestamp = [NSDate date];
//ignore any messages that are related to lid state
if(kIOPMMessageClamshellStateChange != messageType)
{
//bail
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, @"got 'kIOPMMessageClamshellStateChange' message");
//get prefs
currentPrefs = [preferences get:nil];
//if user explicity set disabled
// bail here, to ignore everything
if(YES == [currentPrefs[PREF_IS_DISABLED] boolValue])
{
//dbg msg
logMsg(LOG_DEBUG, @"client disabled DND, so ignoring lid event");
//bail
goto bail;
}
//get state
lidState = ((int) messageArgument & kClamshellStateBit);
//get sleep state
sleepState = !!(((int)messageArgument & kClamshellSleepBit));
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"lid state: %@ (sleep bit: %d)", (lidState) ? @"closed" : @"open", sleepState]);
//(new) open?
// OS sometimes delivers 2x events, so ignore same same
if( (stateOpen == lidState) &&
(stateOpen != lastLidState) )
{
//ignore if lid isn't really open
// on reboot, OS may deliver 'open' message if external monitors are connected
if(stateOpen != getLidState())
{
//bail
goto bail;
}
//update 'prev' state
lastLidState = stateOpen;
//dbg msg
// log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"[NEW EVENT] lid state: open (sleep state: %d)", sleepState]);
//touch id mode?
// wait up to 10 seconds, and ignore event if user auth'd via biometrics
if(YES == [currentPrefs[PREF_TOUCHID_MODE] boolValue])
{
//dbg msg
logMsg(LOG_DEBUG, @"'touch id' mode enabled, waiting up to 10 seconds for biometric auth event");
//user auth'd via touchID?
// will wait for up to 10 seconds
if(YES == authViaTouchID())
{
//dbg msg
// log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, @"user authenticated via touchID, so ignoring event");
//bail
// will ignore the event
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, @"no touch id auth event found, so will process event");
}
//process event
// report to user, execute actions, etc
[lid processEvent:timestamp user:getConsoleUser()];
}
//(new) close?
// OS sometimes delivers 2x events, so ignore same same
else if( (stateClosed == lidState) &&
(stateClosed != lastLidState) )
{
//update 'prev' state
lastLidState = stateClosed;
//dbg msg
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"[NEW EVENT] lid state: closed (sleep state: %d)", sleepState]);
}
bail:
return;
}
//check if user auth'd
// a) within last 10 seconds
// b) via biometrics (touchID)
@@ -230,7 +106,7 @@ BOOL authViaTouchID()
});
//wait for touch id auth
// ...up to five seconds
// ...up to ten seconds for event
dispatch_semaphore_wait(semaphore, dispatch_time(0, 10*NSEC_PER_SEC));
//tell user auth monitor to stop
@@ -242,15 +118,19 @@ BOOL authViaTouchID()
return touchIDAuth;
}
@implementation Lid
@implementation Triggers
@synthesize client;
@synthesize lidTrigger;
@synthesize powerTrigger;
@synthesize deviceTrigger;
@synthesize dispatchGroup;
@synthesize dispatchBlocks;
@synthesize undeliveredAlert;
@synthesize dispatchGroupEmpty;
//init
-(id)init
{
@@ -258,21 +138,15 @@ BOOL authViaTouchID()
self = [super init];
if(nil != self)
{
//init
dispatchQ = NULL;
//init lid (trigger) obj
lidTrigger = [[LidTrigger alloc] init];
//init
notificationPort = NULL;
//init device (trigger) obj
deviceTrigger = [[DeviceTrigger alloc] init];
//init
notification = 0;
//init power (trigger) obj
powerTrigger = [[PowerTrigger alloc] init];
//init to current state
lastLidState = getLidState();
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"initial lid state: %d", lastLidState]);
//init dispatch group for dismiss events
dispatchGroup = dispatch_group_create();
@@ -346,144 +220,86 @@ bail:
return initialized;
}
//register for notifications
-(BOOL)register4Notifications
//toggle trigger(s)
-(void)toggle:(NSUInteger)type state:(NSControlStateValue)state
{
//return var
BOOL registered = NO;
//current prefs
NSDictionary* currentPrefs = nil;
//status var
kern_return_t status = kIOReturnError;
//dbd msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"toggling trigger (type: %lu, state: %lu)", (unsigned long)type, state]);
//root domain for power management
io_service_t powerManagementRD = MACH_PORT_NULL;
//dbg msg
logMsg(LOG_DEBUG, @"registering for lid notifications");
//make sure state is ok
if(stateUnavailable == getLidState())
//enable based on type
switch(type)
{
//err msg
logMsg(LOG_ERR, @"failed to get lid state, so aborting lid notifications registration");
//all
// based on triggers
case ALL_TRIGGERS:
//dbg msg
logMsg(LOG_DEBUG, @"toggling all triggers");
//get current prefs
currentPrefs = [preferences get:nil];
//lid trigger?
if(YES == [currentPrefs[PREF_LID_TRIGGER] boolValue])
{
//toggle
[self.lidTrigger toggle:state];
}
//device trigger?
if(YES == [currentPrefs[PREF_DEVICE_TRIGGER] boolValue])
{
//toggle
[self.deviceTrigger toggle:state];
}
//power trigger
if(YES == [currentPrefs[PREF_POWER_TRIGGER] boolValue])
{
//toggle
[self.powerTrigger toggle:state];
}
break;
//lid trigger
case LID_TRIGGER:
//toggle
[self.lidTrigger toggle:state];
break;
//error
goto bail;
}
//device trigger
case DEVICE_TRIGGER:
//toggle
[self.deviceTrigger toggle:state];
break;
//power trigger
case POWER_TRIGGER:
//toggle
[self.powerTrigger toggle:state];
break;
//create queue
dispatchQ = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
if(NULL == dispatchQ)
{
//err msg
logMsg(LOG_ERR, @"failed to create dispatch queue for lid notifications");
//error
goto bail;
}
//set target
dispatch_set_target_queue(dispatchQ, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
//create notification port
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
if(NULL == notificationPort)
{
//err msg
logMsg(LOG_ERR, @"failed to create notification port for lid notifications");
//error
goto bail;
}
//set dispatch queue
IONotificationPortSetDispatchQueue(notificationPort, dispatchQ);
//get matching service for power management root domain
powerManagementRD = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPMrootDomain"));
if(0 == powerManagementRD)
{
//err msg
logMsg(LOG_ERR, @"failed to get power management root domain for lid notifications");
//error
goto bail;
}
//add interest notification
status = IOServiceAddInterestNotification(notificationPort, powerManagementRD, kIOGeneralInterest,
pmDomainChange, &lidState, &notification);
if(KERN_SUCCESS != status)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to get add interest notifcation for lid notifications (error: 0x:%x)", status]);
//error
goto bail;
}
//happy
registered = YES;
bail:
//release
if(MACH_PORT_NULL != powerManagementRD)
{
//release
IOObjectRelease(powerManagementRD);
//unset
powerManagementRD = MACH_PORT_NULL;
}
return registered;
}
//unregister for notifications
-(void)unregister4Notifications
{
//dbg msg
logMsg(LOG_DEBUG, @"unregistering lid notifications");
//release notification
if(0 != notification)
{
//release
IOObjectRelease(notification);
//unset
notification = 0;
//dbg msg
logMsg(LOG_DEBUG, @"released service interest notification");
}
//destroy notification port
if(NULL != notificationPort)
{
//set queue to NULL
IONotificationPortSetDispatchQueue(notificationPort, NULL);
//unset dispatch queue
dispatchQ = NULL;
//destroy port
IONotificationPortDestroy(notificationPort);
//unset
notificationPort = NULL;
//dbg msg
logMsg(LOG_DEBUG, @"destroyed notification port");
default:
break;
}
return;
}
//proces lid open event
//proces trigger event
// report to user, execute cmd, send alert to server, etc
-(void)processEvent:(NSDate*)timestamp user:(NSString*)user
-(void)processEvent:(NSUInteger)type info:(NSDictionary*)info
{
//monitor obj
Monitor* monitor = nil;
@@ -494,13 +310,38 @@ bail:
//get current prefs
currentPrefs = [preferences get:nil];
//auth mode?
// wait up to 10 seconds, and ignore event if user auth'd via biometrics or apple watch
if(YES == [currentPrefs[PREF_AUTH_MODE] boolValue])
{
//dbg msg
logMsg(LOG_DEBUG, @"'auth' mode enabled, waiting up to 10 seconds for biometric auth || apple watch event");
//TODO: add apple watch
//user auth'd via touchID?
// will wait for up to 10 seconds
if(YES == authViaTouchID())
{
//dbg msg
// log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, @"user authenticated via touchID, so ignoring event");
//bail
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, @"no touch id auth event found, so will continue processing event");
}
//only add events to queue
// when client is not running in passive mode
if(YES != [currentPrefs[PREF_PASSIVE_MODE] boolValue])
{
//add to global queue
// this will trigger processing of alert to user
[eventQueue enqueue:@{ALERT_TIMESTAMP:timestamp}];
[eventQueue enqueue:@{ALERT_TYPE:[NSNumber numberWithInteger:type], ALERT_TIMESTAMP:[NSDate date], ALERT_INFO:info}];
}
//passive mode
// just log a msg about this fact
@@ -533,7 +374,6 @@ bail:
if( (YES == [currentPrefs[PREF_EXECUTE_ACTION] boolValue]) &&
(0 != [currentPrefs[PREF_EXECUTE_PATH] length] ) )
{
//dbg msg
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"executing: %@ as %@", currentPrefs[PREF_EXECUTE_PATH], currentPrefs[PREF_EXECUTE_USER]]);
@@ -565,7 +405,7 @@ bail:
}
//registered device?
// send to alert to server
// send alert to server
if(nil != self.client)
{
//dbg msg
@@ -579,14 +419,14 @@ bail:
logMsg(LOG_DEBUG, @"no (prev) alerts undelivered");
//save timestamp
self.undeliveredAlert = timestamp;
self.undeliveredAlert = [NSDate date];
//send to server
// will wait up to x minutes if there's no network connectivity
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//wait
[self send2Server:user];
[self send2Server:getConsoleUser()];
});
}
@@ -599,7 +439,7 @@ bail:
logMsg(LOG_DEBUG, @"previously alert undelivered, just updating that...");
//save timestamp
self.undeliveredAlert = timestamp;
self.undeliveredAlert = [NSDate date];
}
}
@@ -608,7 +448,7 @@ bail:
else
{
//dbg msg
logMsg(LOG_DEBUG, @"did not send to server - no client/registered device");
logMsg(LOG_DEBUG, @"did not send to server, as there's no client/registered device");
}
bail:
+2
View File
@@ -7,6 +7,8 @@
// copyright (c) 2018 Objective-See. All rights reserved.
//
@import Foundation;
/* FUNCTIONS */
//uninstall
+13 -18
View File
@@ -7,11 +7,11 @@
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Lid.h"
#import "main.h"
#import "Consts.h"
#import "Queue.h"
#import "Consts.h"
#import "Logging.h"
#import "Triggers.h"
#import "Utilities.h"
#import "Preferences.h"
#import "UserAuthMonitor.h"
@@ -27,7 +27,7 @@ Preferences* preferences = nil;
//lid object
// registers for notifications, gets state, etc
Lid* lid = nil;
Triggers* triggers = nil;
//queue object
// contains watch items that should be processed
@@ -48,7 +48,7 @@ int main(int argc, const char * argv[])
{
//return
int result = -1;
@autoreleasepool
{
//user comms listener (XPC) obj
@@ -123,6 +123,7 @@ int main(int argc, const char * argv[])
// allows to close logging, etc.
register4Shutdown();
//1st time identity generatation is done on demand
// subsequent times though, can just always do here
if(nil != currentPrefs[PREF_CLIENT_ID])
@@ -141,30 +142,27 @@ int main(int argc, const char * argv[])
logMsg(LOG_DEBUG, @"initialized DND identity");
}
//init global lid object
lid = [[Lid alloc] init];
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"lid state: %d", getLidState()]);
//init global triggers object
triggers = [[Triggers alloc] init];
//not (prev) disabled?
// register for lid notifications
// toggle all triggers based on their setting
if(YES != [currentPrefs[PREF_IS_DISABLED] boolValue])
{
//register for lid notifications
[lid register4Notifications];
//toggle all triggers
[triggers toggle:ALL_TRIGGERS state:NSOnState];
//dbg msg
logMsg(LOG_DEBUG, @"registered for lid change notifications");
logMsg(LOG_DEBUG, @"toggled (all) triggers");
}
//(prev) disabled
else
{
//dbg msg
logMsg(LOG_DEBUG, @"currently disabled, so did not register for lid change notifications");
logMsg(LOG_DEBUG, @"user set 'disabled' preference, so did not register for any triggers");
}
//init global queue
eventQueue = [[Queue alloc] init];
@@ -185,9 +183,6 @@ int main(int argc, const char * argv[])
//dbg msg
logMsg(LOG_DEBUG, @"listening for client XPC connections");
//run loop
[[NSRunLoop currentRunLoop] run];
}//pool
//happy
+44
View File
@@ -0,0 +1,44 @@
//
// file: DeviceTrigger.h
// project: DND (launch daemon)
// description: monitor and alert logic for device insertion events (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
@import Cocoa;
@import Foundation;
#import <IOKit/usb/IOUSBLib.h>
/* CLASS INTERFACE */
@interface DeviceTrigger : NSObject
{
}
/* PROPERTIES */
//notification port
@property(nonatomic)IONotificationPortRef notificationPort;
//callback for USB devices
void usbAppeared(void *refCon, io_iterator_t iterator);
//run loop source
@property(nonatomic)CFRunLoopSourceRef runLoopSource;
/* METHODS */
//register for notifications
-(BOOL)toggle:(NSControlStateValue)state;
//process new USB insertion
// get info about device and log
-(void)handleNewDevice:(io_iterator_t)iterator;
@end
+244
View File
@@ -0,0 +1,244 @@
// file: DeviceTrigger.m
// project: DND (launch daemon)
// description: monitor and alert logic for device insertion events
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "Logging.h"
#import "Triggers.h"
#import "Utilities.h"
#import "Preferences.h"
#import "DeviceTrigger.h"
/* GLOBALS */
//triggers object
extern Triggers* triggers;
//preferences obj
extern Preferences* preferences;
@implementation DeviceTrigger
@synthesize runLoopSource;
@synthesize notificationPort;
//callback for USB devices
void usbAppeared(void *refCon, io_iterator_t iterator)
{
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"usb device inserted"]);
//process new device
[(__bridge DeviceTrigger *)refCon handleNewDevice:iterator];
return;
}
//toggle lid notifications
-(BOOL)toggle:(NSControlStateValue)state
{
//flag
BOOL wasToggled = NO;
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"toggling devices notifications: %lu", state]);
//on?
// enable
if(NSOnState == state)
{
//enable
wasToggled = [self enable];
}
//off
// disable
else
{
//disable
[self disable];
//manually set flag
wasToggled = YES;
}
return wasToggled;
}
//start USB monitoring
-(BOOL)enable
{
//status
BOOL initialized = NO;
//status
kern_return_t status = kIOReturnError;
//iterator
io_iterator_t iterator = 0;
//device
io_service_t device = 0;
//create notification port
self.notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
//get run loop source
self.runLoopSource = IONotificationPortGetRunLoopSource(self.notificationPort);
//add source
CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, kCFRunLoopDefaultMode);
//add notification
// pass in 'self' so can access obj-c methods in callbacks
status = IOServiceAddMatchingNotification(self.notificationPort, kIOMatchedNotification, IOServiceMatching(kIOUSBDeviceClassName), usbAppeared,(__bridge void *)self, &iterator);
if(kIOReturnSuccess != status)
{
//err
logMsg(LOG_ERR, [NSString stringWithFormat:@"IOServiceAddMatchingNotification() failed with %d", status]);
//bail
goto bail;
}
//process existing devices
// also 'drains' interator...
device = IOIteratorNext(iterator);
while(0 != device)
{
//record device name/properties
//[self logDeviceProperties:device];
//release
IOObjectRelease(device);
//get next
device = IOIteratorNext(iterator);
}
//happy
initialized = YES;
bail:
return initialized;
}
//stop
// invalidate runloop src and notification port
-(void)disable
{
//invalidate runloop src
if(nil != self.runLoopSource)
{
//invalidate
CFRunLoopSourceInvalidate(self.runLoopSource);
//unset
self.runLoopSource = nil;
}
//destroy notification port
if(nil != self.notificationPort)
{
//destroy
IONotificationPortDestroy(self.notificationPort);
//unset
self.notificationPort = nil;
}
return;
}
//process new USB insertion
// get info about device and log
-(void)handleNewDevice:(io_iterator_t)iterator
{
//usb device
io_service_t device;
//device name
io_name_t deviceName = {0};
//timestamp
NSDate* timestamp = nil;
//process
while((device = IOIteratorNext(iterator)))
{
//reset
bzero(deviceName, sizeof(io_name_t));
//init timestamp
timestamp = [NSDate date];
//get device name
if(KERN_SUCCESS != IORegistryEntryGetName(device, deviceName))
{
//err msg
logMsg(LOG_ERR, @"failed to get usb device name");
//set to unknown
strncpy(deviceName, "<unknown>", sizeof(io_name_t)-1);
}
//dbg msg
// log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"[NEW EVENT] usb inserted: \"%s\"", deviceName]);
//process event
// report to user, server, execute actions, etc.
[triggers processEvent:DEVICE_TRIGGER info:@{KEY_DEVICE_NAME:[NSString stringWithUTF8String:deviceName]}];
//release device
IOObjectRelease(device);
//unset
device = 0;
}
return;
}
//log name/properties of a device
-(void)logDeviceProperties:(io_service_t)device
{
//device name
io_name_t deviceName = {0};
//device properties
CFMutableDictionaryRef deviceProperties = NULL;
//get device name
if(KERN_SUCCESS == IORegistryEntryGetName(device, deviceName))
{
//dbg msg & log
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"usb device name: %s", deviceName]);
}
//get device properties
if( (kIOReturnSuccess == IORegistryEntryCreateCFProperties(device, &deviceProperties, kCFAllocatorDefault, kNilOptions)) &&
(NULL != deviceProperties) )
{
//dbg msg & log
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"usb device properties: %@", deviceProperties]);
}
//release device props
if(NULL != deviceProperties)
{
//release
CFRelease(deviceProperties);
//unset
deviceProperties = NULL;
}
return;
}
@end
+44
View File
@@ -0,0 +1,44 @@
//
// file: LidTrigger.h
// project: DND (launch daemon)
// description: monitor and alert logic for lid open events (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Utilities.h"
@import Foundation;
#import <IOKit/IOKitLib.h>
#import <IOKit/pwr_mgt/IOPM.h>
/* CLASS INTERFACE */
@interface LidTrigger : NSObject
{
}
/* PROPERTIES */
//lid state
@property LidState lidState;
//dispatch queue
@property dispatch_queue_t dispatchQ;
//notification port
@property IONotificationPortRef notificationPort;
//notification object
@property io_object_t notification;
/* METHODS */
//register for notifications
-(BOOL)toggle:(NSControlStateValue)state;
@end
+325
View File
@@ -0,0 +1,325 @@
// file: LidTrigger.m
// project: DND (launch daemon)
// description: monitor and alert logic for lid open events
// code inspired by:
// https://github.com/zarigani/ClamshellWake/blob/master/ClamshellWake.cpp
// https://github.com/dustinrue/ControlPlane/blob/master/Source/LaptopLidEvidenceSource.m
// note: manually get state from terminal via:
// ioreg -r -k AppleClamshellState -d 4 | grep AppleClamshellState
#import "Consts.h"
#import "Logging.h"
#import "Triggers.h"
#import "Utilities.h"
#import "LidTrigger.h"
#import "Preferences.h"
/* GLOBALS */
//last state
// sometimes multiple notifications are delivered!?
LidState lastLidState;
//triggers object
extern Triggers* triggers;
//preferences obj
extern Preferences* preferences;
//callback for power/lid events
static void pmDomainChange(void *refcon, io_service_t service, uint32_t messageType, void *messageArgument)
{
//lid state
int lidState = stateUnavailable;
//sleep bit
int sleepState = -1;
//preferences
NSDictionary* currentPrefs = nil;
//timestamp
NSDate* timestamp = nil;
//init timestamp
timestamp = [NSDate date];
//ignore any messages that are related to lid state
if(kIOPMMessageClamshellStateChange != messageType)
{
//bail
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, @"got 'kIOPMMessageClamshellStateChange' message");
//get prefs
currentPrefs = [preferences get:nil];
//if user explicity set disabled
// bail here, to ignore everything
if(YES == [currentPrefs[PREF_IS_DISABLED] boolValue])
{
//dbg msg
logMsg(LOG_DEBUG, @"client disabled DND, so ignoring lid event");
//update 'prev' state?
lastLidState = stateOpen;
//bail
goto bail;
}
//get state
lidState = ((int) messageArgument & kClamshellStateBit);
//get sleep state
sleepState = !!(((int)messageArgument & kClamshellSleepBit));
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"lid state: %@ (sleep bit: %d)", (lidState) ? @"closed" : @"open", sleepState]);
//(new) open?
// OS sometimes delivers 2x events, so ignore same same
if( (stateOpen == lidState) &&
(stateOpen != lastLidState) )
{
//ignore if lid isn't really open
// on reboot, OS may deliver 'open' message if external monitors are connected
if(stateOpen != getLidState())
{
//bail
goto bail;
}
//update 'prev' state
lastLidState = stateOpen;
//dbg msg
// log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"[NEW EVENT] lid state: open (sleep state: %d)", sleepState]);
//process event
// report to user, server, execute actions, etc.
[triggers processEvent:LID_TRIGGER info:nil];
}
//(new) close?
// OS sometimes delivers 2x events, so ignore same same
else if( (stateClosed == lidState) &&
(stateClosed != lastLidState) )
{
//update 'prev' state
lastLidState = stateClosed;
//dbg msg
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"[NEW EVENT] lid state: closed (sleep state: %d)", sleepState]);
}
bail:
return;
}
@implementation LidTrigger
@synthesize lidState;
@synthesize dispatchQ;
@synthesize notification;
@synthesize notificationPort;
//init
-(id)init
{
//super
self = [super init];
if(nil != self)
{
//init
notificationPort = NULL;
//init
notification = 0;
//init to current state
lastLidState = getLidState();
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"initial lid state: %d", lastLidState]);
//init
dispatchQ = NULL;
}
return self;
}
//toggle lid notifications
-(BOOL)toggle:(NSControlStateValue)state
{
//flag
BOOL wasToggled = NO;
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"toggling lid notifications: %lu", state]);
//on?
// enable
if(NSOnState == state)
{
//enable
wasToggled = [self enable];
}
//off
// disable
else
{
//disable
[self disable];
//manually set flag
wasToggled = YES;
}
return wasToggled;
}
//register for notifications
-(BOOL)enable
{
//return var
BOOL registered = NO;
//status var
kern_return_t status = kIOReturnError;
//root domain for power management
io_service_t powerManagementRD = MACH_PORT_NULL;
//dbg msg
logMsg(LOG_DEBUG, @"registering for lid notifications");
//make sure state is ok
if(stateUnavailable == getLidState())
{
//err msg
logMsg(LOG_ERR, @"failed to get lid state, so aborting lid notifications registration");
//error
goto bail;
}
//create queue
dispatchQ = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
if(NULL == dispatchQ)
{
//err msg
logMsg(LOG_ERR, @"failed to create dispatch queue for lid notifications");
//error
goto bail;
}
//set target
dispatch_set_target_queue(dispatchQ, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
//create notification port
notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
if(NULL == notificationPort)
{
//err msg
logMsg(LOG_ERR, @"failed to create notification port for lid notifications");
//error
goto bail;
}
//set dispatch queue
IONotificationPortSetDispatchQueue(notificationPort, dispatchQ);
//get matching service for power management root domain
powerManagementRD = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPMrootDomain"));
if(0 == powerManagementRD)
{
//err msg
logMsg(LOG_ERR, @"failed to get power management root domain for lid notifications");
//error
goto bail;
}
//add interest notification
status = IOServiceAddInterestNotification(notificationPort, powerManagementRD, kIOGeneralInterest,
pmDomainChange, &lidState, &notification);
if(KERN_SUCCESS != status)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to get add interest notifcation for lid notifications (error: 0x:%x)", status]);
//error
goto bail;
}
//happy
registered = YES;
bail:
//release
if(MACH_PORT_NULL != powerManagementRD)
{
//release
IOObjectRelease(powerManagementRD);
//unset
powerManagementRD = MACH_PORT_NULL;
}
return registered;
}
//unregister for notifications
-(void)disable
{
//dbg msg
logMsg(LOG_DEBUG, @"unregistering lid notifications");
//release notification
if(0 != notification)
{
//release
IOObjectRelease(notification);
//unset
notification = 0;
//dbg msg
logMsg(LOG_DEBUG, @"released service interest notification");
}
//destroy notification port
if(NULL != notificationPort)
{
//set queue to NULL
IONotificationPortSetDispatchQueue(notificationPort, NULL);
//unset dispatch queue
dispatchQ = NULL;
//destroy port
IONotificationPortDestroy(notificationPort);
//unset
notificationPort = NULL;
//dbg msg
logMsg(LOG_DEBUG, @"destroyed notification port");
}
return;
}
@end
+35
View File
@@ -0,0 +1,35 @@
//
// file: Power.m
// project: DND (launch daemon)
// description: monitor and alert logic for power events (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
@import Cocoa;
@import Foundation;
#import <IOKit/usb/IOUSBLib.h>
/* CLASS INTERFACE */
@interface PowerTrigger : NSObject
{
}
/* PROPERTIES */
//observer for screensaver off events
@property(nonatomic, retain)id screenSaverNotification;
/* METHODS */
//register for notifications
-(BOOL)toggle:(NSControlStateValue)state;
@end
+118
View File
@@ -0,0 +1,118 @@
// file: Power.m
// project: DND (launch daemon)
// description: monitor and alert logic for power events (header)
//
// created by Patrick Wardle
// copyright (c) 2018 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "Logging.h"
#import "Triggers.h"
#import "Utilities.h"
#import "Preferences.h"
#import "PowerTrigger.h"
/* GLOBALS */
//triggers object
extern Triggers* triggers;
//preferences obj
extern Preferences* preferences;
@implementation PowerTrigger
@synthesize screenSaverNotification;
//toggle lid notifications
-(BOOL)toggle:(NSControlStateValue)state
{
//flag
BOOL wasToggled = NO;
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"toggling power notifications: %lu", state]);
//on?
// enable
if(NSOnState == state)
{
//enable
wasToggled = [self enable];
}
//off
// disable
else
{
//disable
[self disable];
//manually set flag
wasToggled = YES;
}
return wasToggled;
}
//start power event monitoring
-(BOOL)enable
{
//status
BOOL initialized = NO;
/*
com.apple.screensaver.didstart
com.apple.screensaver.willstop
com.apple.screensaver.didstop
*/
//add observer for screen save on
// we don't get a screen save stop, so this will trigger process monitoring for exit of ScreenSaverEngine
self.screenSaverNotification = [[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"com.apple.screensaver.didlaunch" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification)
{
//TODO: trigger process monitoring
//dbg msg
// log to file
//logMsg(LOG_DEBUG|LOG_TO_FILE, @"[NEW EVENT] screen saver did stop");
//process event
// report to user, server, execute actions, etc.
//[triggers processEvent:POWER_TRIGGER info:@{KEY_POWER_TYPE:@"screen saver did stop"}];
}];
//dbg msg
logMsg(LOG_DEBUG, @"enabled screen saver 'did launch'");
bail:
return initialized;
}
//disable
-(void)disable
{
//disable
// screen saver start notification
if(nil != self.screenSaverNotification)
{
//remove
[[NSNotificationCenter defaultCenter] removeObserver:self.screenSaverNotification];
//unset
self.screenSaverNotification = nil;
}
//TODO: make sure to stop process monitoring, if it's still going
return;
}
@end
+23 -7
View File
@@ -38,10 +38,6 @@
// call daemon and block, then display, and repeat!
while(YES)
{
//pool
@autoreleasepool
{
//dbg msg
logMsg(LOG_DEBUG, @"requesting alert(s) from daemon, will block");
@@ -84,8 +80,6 @@
//wait for alert to be received
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}//pool
}//forevers
return;
@@ -186,7 +180,29 @@
notification.title = @"⚠️ Do Not Disturb Alert";
//set subtitle
notification.subtitle = [NSString stringWithFormat:@"Lid Opened: %@", [dateFormat stringFromDate:alert[ALERT_TIMESTAMP]]];
// based on trigger type (lid, usb, etc.)
switch([alert[ALERT_TYPE] integerValue])
{
//lid
case LID_TRIGGER:
notification.subtitle = [NSString stringWithFormat:@"Lid Opened: %@", [dateFormat stringFromDate:alert[ALERT_TIMESTAMP]]];
break;
//device
case DEVICE_TRIGGER:
notification.subtitle = [NSString stringWithFormat:@"Device Inserted: %@", alert[ALERT_INFO][KEY_DEVICE_NAME]];
break;
//power
case POWER_TRIGGER:
notification.subtitle = [NSString stringWithFormat:@"Power Event: %@", alert[ALERT_INFO][KEY_POWER_TYPE]];
break;
default:
break;
}
//set delegate to self
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
+12 -4
View File
@@ -23,7 +23,6 @@
7D564DEB1F1855E900B8AAD6 /* UpdateWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D564DE81F1855E900B8AAD6 /* UpdateWindow.xib */; };
7D75537F1F22E40E0010FE88 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D75537D1F22E40E0010FE88 /* PrefsWindowController.m */; };
7D7553801F22E40E0010FE88 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D75537E1F22E40E0010FE88 /* Preferences.xib */; };
7D7553831F23199A0010FE88 /* prefsGeneral.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D7553811F23199A0010FE88 /* prefsGeneral.png */; };
7D7553841F23199A0010FE88 /* prefsUpdate.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D7553821F23199A0010FE88 /* prefsUpdate.png */; };
7DD2BF461F1C2B4200B33214 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 7DD2BF431F1C2B4200B33214 /* logo.png */; };
7DD2BF471F1C2B4200B33214 /* logoBG.png in Resources */ = {isa = PBXBuildFile; fileRef = 7DD2BF441F1C2B4200B33214 /* logoBG.png */; };
@@ -45,6 +44,7 @@
CD325425204DEAEA0059951B /* dndText@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD325424204DEAEA0059951B /* dndText@2x.png */; };
CD325427204E0C500059951B /* close.png in Resources */ = {isa = PBXBuildFile; fileRef = CD325426204E0C500059951B /* close.png */; };
CD32542B204E0E420059951B /* closeAlt.png in Resources */ = {isa = PBXBuildFile; fileRef = CD32542A204E0E420059951B /* closeAlt.png */; };
CD68AEE02110CD9E0019E431 /* prefsTriggers.png in Resources */ = {isa = PBXBuildFile; fileRef = CD68AEDF2110CD9D0019E431 /* prefsTriggers.png */; };
CDAAC213201D0CD90032F2E6 /* three.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC212201D0CD80032F2E6 /* three.png */; };
CDAAC215201D2DD30032F2E6 /* checkbox.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC214201D2DD30032F2E6 /* checkbox.png */; };
CDAAC217201D54C30032F2E6 /* prefsLink.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC216201D54C20032F2E6 /* prefsLink.png */; };
@@ -52,6 +52,8 @@
CDAAC21C201D77390032F2E6 /* connected.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC21A201D77390032F2E6 /* connected.png */; };
CDAAC21D201D77390032F2E6 /* unconnected.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC21B201D77390032F2E6 /* unconnected.png */; };
CDAAC238201FD4660032F2E6 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDAAC237201FD4660032F2E6 /* LocalAuthentication.framework */; };
CDEADE52210214A0005054B0 /* usb.png in Resources */ = {isa = PBXBuildFile; fileRef = CDEADE502102149F005054B0 /* usb.png */; };
CDEADE53210214A0005054B0 /* sleep.png in Resources */ = {isa = PBXBuildFile; fileRef = CDEADE51210214A0005054B0 /* sleep.png */; };
CE0F559C1FD408BB00529259 /* dndText.png in Resources */ = {isa = PBXBuildFile; fileRef = CE0F559B1FD408BB00529259 /* dndText.png */; };
CE133C5F1FD756CC00A29D67 /* dndIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CE133C5E1FD756CC00A29D67 /* dndIcon.png */; };
CE85D3FE1FDB47B200E116A5 /* settings.png in Resources */ = {isa = PBXBuildFile; fileRef = CE85D3FD1FDB47B200E116A5 /* settings.png */; };
@@ -109,7 +111,6 @@
7D75537C1F22E40E0010FE88 /* PrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrefsWindowController.h; sourceTree = "<group>"; };
7D75537D1F22E40E0010FE88 /* PrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrefsWindowController.m; sourceTree = "<group>"; };
7D75537E1F22E40E0010FE88 /* Preferences.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
7D7553811F23199A0010FE88 /* prefsGeneral.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = prefsGeneral.png; sourceTree = "<group>"; };
7D7553821F23199A0010FE88 /* prefsUpdate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = prefsUpdate.png; sourceTree = "<group>"; };
7DD2BF431F1C2B4200B33214 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
7DD2BF441F1C2B4200B33214 /* logoBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logoBG.png; sourceTree = "<group>"; };
@@ -133,6 +134,7 @@
CD325424204DEAEA0059951B /* dndText@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "dndText@2x.png"; path = "../../../shared/images/dndText@2x.png"; sourceTree = "<group>"; };
CD325426204E0C500059951B /* close.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = close.png; sourceTree = "<group>"; };
CD32542A204E0E420059951B /* closeAlt.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = closeAlt.png; sourceTree = "<group>"; };
CD68AEDF2110CD9D0019E431 /* prefsTriggers.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = prefsTriggers.png; sourceTree = "<group>"; };
CDAAC212201D0CD80032F2E6 /* three.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = three.png; sourceTree = "<group>"; };
CDAAC214201D2DD30032F2E6 /* checkbox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkbox.png; sourceTree = "<group>"; };
CDAAC216201D54C20032F2E6 /* prefsLink.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = prefsLink.png; sourceTree = "<group>"; };
@@ -140,6 +142,8 @@
CDAAC21A201D77390032F2E6 /* connected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = connected.png; sourceTree = "<group>"; };
CDAAC21B201D77390032F2E6 /* unconnected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unconnected.png; sourceTree = "<group>"; };
CDAAC237201FD4660032F2E6 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
CDEADE502102149F005054B0 /* usb.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = usb.png; sourceTree = "<group>"; };
CDEADE51210214A0005054B0 /* sleep.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sleep.png; sourceTree = "<group>"; };
CE0F559B1FD408BB00529259 /* dndText.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dndText.png; path = ../../../shared/images/dndText.png; sourceTree = "<group>"; };
CE133C5E1FD756CC00A29D67 /* dndIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dndIcon.png; path = ../../../shared/images/dndIcon.png; sourceTree = "<group>"; };
CE85D3FD1FDB47B200E116A5 /* settings.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = settings.png; sourceTree = "<group>"; };
@@ -242,6 +246,9 @@
7D564DD31F18441500B8AAD6 /* Images */ = {
isa = PBXGroup;
children = (
CD68AEDF2110CD9D0019E431 /* prefsTriggers.png */,
CDEADE51210214A0005054B0 /* sleep.png */,
CDEADE502102149F005054B0 /* usb.png */,
CD32542A204E0E420059951B /* closeAlt.png */,
CD325426204E0C500059951B /* close.png */,
CD325424204DEAEA0059951B /* dndText@2x.png */,
@@ -262,7 +269,6 @@
CE133C5E1FD756CC00A29D67 /* dndIcon.png */,
CE0F559B1FD408BB00529259 /* dndText.png */,
CE968A9E1FCC66A300AD6B78 /* prefsAction.png */,
7D7553811F23199A0010FE88 /* prefsGeneral.png */,
7D7553821F23199A0010FE88 /* prefsUpdate.png */,
7DD2BF431F1C2B4200B33214 /* logo.png */,
7DD2BF441F1C2B4200B33214 /* logoBG.png */,
@@ -368,6 +374,7 @@
buildActionMask = 2147483647;
files = (
CD32542B204E0E420059951B /* closeAlt.png in Resources */,
CDEADE53210214A0005054B0 /* sleep.png in Resources */,
CD17D56E20178DFC00F798D7 /* mobilePhone.png in Resources */,
CD1FD56B2089224F00151D1C /* appStore.pdf in Resources */,
CD2F407F204B417E0066673E /* alert.png in Resources */,
@@ -382,13 +389,14 @@
CDAAC213201D0CD90032F2E6 /* three.png in Resources */,
CDAAC219201D72780032F2E6 /* linked.png in Resources */,
CD325425204DEAEA0059951B /* dndText@2x.png in Resources */,
CDEADE52210214A0005054B0 /* usb.png in Resources */,
7DD2BF481F1C2B4200B33214 /* logoOver.png in Resources */,
7D7553801F22E40E0010FE88 /* Preferences.xib in Resources */,
7D7553831F23199A0010FE88 /* prefsGeneral.png in Resources */,
CD17D5772017941C00F798D7 /* laptop.png in Resources */,
CD17D58520179BC700F798D7 /* two.png in Resources */,
CD325427204E0C500059951B /* close.png in Resources */,
7D564DD61F18441500B8AAD6 /* Assets.xcassets in Resources */,
CD68AEE02110CD9E0019E431 /* prefsTriggers.png in Resources */,
CD17D57020178EB500F798D7 /* one.png in Resources */,
7D7553841F23199A0010FE88 /* prefsUpdate.png in Resources */,
7D564DDC1F18441500B8AAD6 /* AboutWindow.xib in Resources */,
@@ -56,9 +56,9 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -75,6 +75,12 @@
ReferencedContainer = "container:mainApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-prefs"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+133 -30
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
<capability name="box content view" minToolsVersion="7.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -24,6 +24,7 @@
<outlet property="qrcPanel" destination="vdL-RT-p6a" id="KrV-Fe-sK0"/>
<outlet property="qrcProgressIndicator" destination="pUS-KZ-De6" id="EYG-28-zkH"/>
<outlet property="toolbar" destination="V8g-Ya-LK4" id="SH2-6E-QST"/>
<outlet property="triggersView" destination="BuY-2M-Ecx" id="hrr-N9-ajg"/>
<outlet property="updateButton" destination="Mtn-pi-zIl" id="Oe1-Jy-nMH"/>
<outlet property="updateIndicator" destination="o0T-ra-4H0" id="DwL-OB-WQR"/>
<outlet property="updateLabel" destination="Oe2-Ye-1s6" id="1gP-K0-cpP"/>
@@ -52,22 +53,27 @@
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="J66-tT-qAf"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="6nW-4K-zf4"/>
<toolbarItem implicitItemIdentifier="99F00439-5E3B-4FBB-BC65-3E1F7EBDDBC6" explicitItemIdentifier="general" label="general" paletteLabel="general" image="prefsGeneral" selectable="YES" id="Twx-TJ-y2Q">
<toolbarItem implicitItemIdentifier="99F00439-5E3B-4FBB-BC65-3E1F7EBDDBC6" explicitItemIdentifier="general" label="general" paletteLabel="general" image="dndIcon" selectable="YES" id="Twx-TJ-y2Q">
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="9JH-zR-BcH"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="48B3FCFA-8A19-4D19-A840-E21E6D564389" explicitItemIdentifier="action" label="action" paletteLabel="action" tag="1" image="prefsAction" selectable="YES" id="hqU-b9-59A">
<toolbarItem implicitItemIdentifier="0204F7A2-F780-423C-89FB-28784C971A9A" explicitItemIdentifier="triggers" label="triggers" paletteLabel="triggers" tag="1" image="prefsTriggers" selectable="YES" id="pr7-Pz-jdz">
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="jYk-kP-mSc"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="48B3FCFA-8A19-4D19-A840-E21E6D564389" explicitItemIdentifier="action" label="action" paletteLabel="action" tag="2" image="prefsAction" selectable="YES" id="hqU-b9-59A">
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="dy9-vy-N89"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="B0FD7AF2-DAC5-45EF-A31B-2E2C7CB85294" explicitItemIdentifier="update" label="update" paletteLabel="update" tag="3" image="prefsUpdate" selectable="YES" id="2Fi-c8-fnE">
<toolbarItem implicitItemIdentifier="B0FD7AF2-DAC5-45EF-A31B-2E2C7CB85294" explicitItemIdentifier="update" label="update" paletteLabel="update" tag="4" image="prefsUpdate" selectable="YES" id="2Fi-c8-fnE">
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="jeu-wN-mgR"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="5DB39F09-CC43-4EC3-BF61-362FDA2DF782" explicitItemIdentifier="link" label="link" paletteLabel="link" tag="2" image="prefsLink" selectable="YES" id="43J-tU-rUa">
<toolbarItem implicitItemIdentifier="5DB39F09-CC43-4EC3-BF61-362FDA2DF782" explicitItemIdentifier="link" label="link" paletteLabel="link" tag="3" image="prefsLink" selectable="YES" id="43J-tU-rUa">
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="tSK-K0-f7H"/>
</connections>
@@ -76,6 +82,8 @@
<defaultToolbarItems>
<toolbarItem reference="Twx-TJ-y2Q"/>
<toolbarItem reference="J66-tT-qAf"/>
<toolbarItem reference="pr7-Pz-jdz"/>
<toolbarItem reference="J66-tT-qAf"/>
<toolbarItem reference="hqU-b9-59A"/>
<toolbarItem reference="J66-tT-qAf"/>
<toolbarItem reference="43J-tU-rUa"/>
@@ -153,7 +161,7 @@
<button fixedFrame="YES" tag="3" translatesAutoresizingMaskIntoConstraints="NO" id="ANF-lj-j0H">
<rect key="frame" x="37" y="156" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" enabled="NO" inset="2" id="Fpb-6d-DfT">
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="Fpb-6d-DfT">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
@@ -164,7 +172,7 @@
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F9r-H0-4xe">
<rect key="frame" x="72" y="157" width="471" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="'Touch ID' Mode" id="l1H-sS-Md8">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Authentication Mode" id="l1H-sS-Md8">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -173,13 +181,13 @@
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="BhQ-tq-9gJ">
<rect key="frame" x="72" y="138" width="508" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Suppress alerts if proceeded by a Touch ID login (10.13.4+)." id="yKN-Kc-8Q2">
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Ignore events if computer unlocked via Touch ID or Apple Watch." id="yKN-Kc-8Q2">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="7" translatesAutoresizingMaskIntoConstraints="NO" id="OkJ-ds-qSY">
<button fixedFrame="YES" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="OkJ-ds-qSY">
<rect key="frame" x="37" y="99" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="HEY-GS-vSr">
@@ -208,30 +216,95 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="5ep-7h-VpU">
<rect key="frame" x="37" y="42" width="29" height="18"/>
</subviews>
<point key="canvasLocation" x="852" y="437"/>
</customView>
<customView id="BuY-2M-Ecx" userLabel="Triggers">
<rect key="frame" x="0.0" y="0.0" width="600" height="322"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="QSk-EX-Gs3">
<rect key="frame" x="37" y="270" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="J3b-LL-38M">
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" enabled="NO" inset="2" id="4Ia-YW-I03">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
<connections>
<action selector="togglePreference:" target="-2" id="5gO-Zo-43d"/>
<action selector="togglePreference:" target="-2" id="ko3-U3-K1d"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Yza-iC-hAP">
<rect key="frame" x="72" y="42" width="160" height="19"/>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c2q-TO-7Hx">
<rect key="frame" x="72" y="271" width="160" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Start at Login" id="ksD-bk-5jE">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Laptop Lid Open" id="svL-i1-bx7">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="LOC-tP-KQd">
<rect key="frame" x="72" y="22" width="475" height="19"/>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="9cA-xI-Rkq">
<rect key="frame" x="72" y="253" width="475" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Automatically start login item." id="k4V-lS-86b">
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Alert when your laptop lid is opened." id="eYK-5x-T41">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="6" translatesAutoresizingMaskIntoConstraints="NO" id="Tdc-FL-Prs">
<rect key="frame" x="37" y="213" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="Lxz-uf-N9R">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
<connections>
<action selector="togglePreference:" target="-2" id="C4T-Ye-XAC"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wzx-aD-Ob5">
<rect key="frame" x="72" y="214" width="161" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="USB Device Insertion" id="a2r-f0-Qw2">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="xBV-DA-rOc">
<rect key="frame" x="72" y="195" width="475" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Alert when a USB device is plugged in." id="yaL-Sz-w38">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="7" translatesAutoresizingMaskIntoConstraints="NO" id="G6G-cU-bdG">
<rect key="frame" x="37" y="156" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="oKm-iS-CO8">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
<connections>
<action selector="togglePreference:" target="-2" id="whf-Fn-MSZ"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CjK-AK-Uzg">
<rect key="frame" x="72" y="157" width="471" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Power Events" id="YR8-oc-TgU">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="7Cw-J0-A9x">
<rect key="frame" x="72" y="118" width="490" height="38"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Alert when the your computer is powered on, awakened, or when the screen saver is stopped. " id="yW3-Uo-Ir7">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -244,7 +317,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="311"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="1z0-vD-5Vz">
<button fixedFrame="YES" tag="8" translatesAutoresizingMaskIntoConstraints="NO" id="1z0-vD-5Vz">
<rect key="frame" x="37" y="259" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="0eO-nb-SYy">
@@ -273,8 +346,8 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="6" translatesAutoresizingMaskIntoConstraints="NO" id="Od2-P2-SXK">
<rect key="frame" x="37" y="201" width="29" height="18"/>
<button fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="Od2-P2-SXK">
<rect key="frame" x="37" y="202" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="qyn-YP-C2s">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@@ -285,7 +358,7 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BXf-fg-RpF">
<rect key="frame" x="72" y="201" width="59" height="19"/>
<rect key="frame" x="72" y="203" width="59" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Monitor" id="YH2-4b-Iv5">
<font key="font" size="13" name="Menlo-Bold"/>
@@ -302,6 +375,26 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="10" translatesAutoresizingMaskIntoConstraints="NO" id="C6E-J8-lhh">
<rect key="frame" x="37" y="132" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="ngn-La-kHu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
<connections>
<action selector="togglePreference:" target="-2" id="d0h-1p-AtX"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Np1-aP-w1p">
<rect key="frame" x="72" y="133" width="98" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Snap Picture" id="BQ4-1f-ZXw">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eWd-63-7Gn">
<rect key="frame" x="198" y="257" width="354" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
@@ -314,6 +407,15 @@
<outlet property="delegate" destination="-2" id="DAs-b2-8Zb"/>
</connections>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="cuP-oI-A6A">
<rect key="frame" x="72" y="113" width="475" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Automatically take a picture via the webcam." id="7Xg-3U-FQp">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<point key="canvasLocation" x="911" y="901.5"/>
</customView>
@@ -366,7 +468,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button fixedFrame="YES" tag="8" translatesAutoresizingMaskIntoConstraints="NO" id="dml-JS-liI">
<button fixedFrame="YES" tag="11" translatesAutoresizingMaskIntoConstraints="NO" id="dml-JS-liI">
<rect key="frame" x="37" y="220" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="ljs-bE-JTP">
@@ -445,7 +547,7 @@
<rect key="frame" x="322" y="115" width="258" height="153"/>
<clipView key="contentView" id="FSf-NQ-BdZ">
<rect key="frame" x="1" y="1" width="256" height="151"/>
<autoresizingMask key="autoresizingMask"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView editable="NO" selectable="NO" importsGraphics="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="9cB-rx-0JH">
<rect key="frame" x="0.0" y="0.0" width="256" height="151"/>
@@ -604,6 +706,7 @@
<image name="close" width="24" height="24"/>
<image name="closeAlt" width="24" height="24"/>
<image name="connected" width="128" height="128"/>
<image name="dndIcon" width="256" height="256"/>
<image name="dndText" width="164.57142639160156" height="21.188571929931641"/>
<image name="imageCell:eTI-5p-4rR:image" width="256" height="256">
<mutableData key="keyedArchiveRepresentation">
@@ -5125,9 +5228,9 @@ IGsABCB5AAQgfQAEIIQABCCJAAQglgAEIJkABCCmAAQgqwAEILMABCC2AAQguwAEIMMABCDGAAQg2AAE
INsABCDgAAAAAAAABAEAAAAAAAAAVgAAAAAAAAAAAAAAAAAEIOI
</mutableData>
</image>
<image name="prefsAction" width="32" height="32"/>
<image name="prefsGeneral" width="32" height="32"/>
<image name="prefsLink" width="32" height="32"/>
<image name="prefsUpdate" width="32" height="32"/>
<image name="prefsAction" width="256" height="256"/>
<image name="prefsLink" width="256" height="256"/>
<image name="prefsTriggers" width="224" height="205"/>
<image name="prefsUpdate" width="256" height="256"/>
</resources>
</document>
+29 -12
View File
@@ -17,13 +17,16 @@
#define TOOLBAR_GENERAL 0
//action view
#define TOOLBAR_ACTION 1
#define TOOLBAR_TRIGGERS 1
//action view
#define TOOLBAR_ACTION 2
//link view
#define TOOLBAR_LINK 2
#define TOOLBAR_LINK 3
//update view
#define TOOLBAR_UPDATE 3
#define TOOLBAR_UPDATE 4
//tool bar id for 'general'
#define TOOLBAR_GENERAL_ID @"general"
@@ -34,23 +37,34 @@
//no icon mode button
#define BUTTON_NO_ICON_MODE 2
//touch id mode button
#define BUTTON_TOUCHID_MODE 3
//auth mode button
#define BUTTON_AUTH_MODE 3
//remote tasking
#define BUTTON_TASKING_MODE 4
//lid open trigger
#define BUTTON_LID_TRIGGER 5
//usb device trigger
#define BUTTON_DEVICE_TRIGGER 6
//power events trigger
#define BUTTON_POWER_TRIGGER 7
//start mode button
#define BUTTON_START_MODE 4
//execute action button
#define BUTTON_EXECUTE_ACTION 5
#define BUTTON_EXECUTE_ACTION 8
//monitor button
#define BUTTON_MONITOR_ACTION 6
#define BUTTON_MONITOR_ACTION 9
//no remote tasking button
#define BUTTON_NO_REMOTE_TASKING 7
//snap picture button
#define BUTTON_PHOTO_ACTION 10
//no updates button
#define BUTTON_NO_UPDATES_MODE 8
#define BUTTON_NO_UPDATES_MODE 11
@interface PrefsWindowController : NSWindowController <NSTextFieldDelegate, NSToolbarDelegate>
@@ -68,6 +82,9 @@
//general prefs view
@property (weak) IBOutlet NSView *generalView;
//triggers view
@property (strong) IBOutlet NSView *triggersView;
//action view
@property (weak) IBOutlet NSView *actionView;
+74 -34
View File
@@ -48,13 +48,12 @@
//set general prefs as default
[self toolbarButtonHandler:nil];
//enable touchID mode option
// if: < 10.13.4 (check first!) && no touch bar
if( (YES == [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 13, 4}]) &&
(YES == hasTouchID()) )
//clamshell?
// enable laptop trigger option
if(stateUnavailable != getLidState())
{
//enable button
((NSButton*)[self.generalView viewWithTag:BUTTON_TOUCHID_MODE]).enabled = YES;
((NSButton*)[self.triggersView viewWithTag:BUTTON_LID_TRIGGER]).enabled = YES;
}
return;
@@ -63,7 +62,7 @@
//required for toolbar item enable/disable
-(BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
{
return [toolbarItem isEnabled] ;
return [toolbarItem isEnabled];
}
//toolbar view handler
@@ -109,11 +108,29 @@
((NSButton*)[view viewWithTag:BUTTON_NO_ICON_MODE]).state = [self.preferences[PREF_NO_ICON_MODE] boolValue];
//set 'touch id' button state
((NSButton*)[view viewWithTag:BUTTON_TOUCHID_MODE]).state = [self.preferences[PREF_TOUCHID_MODE] boolValue];
((NSButton*)[view viewWithTag:BUTTON_AUTH_MODE]).state = [self.preferences[PREF_AUTH_MODE] boolValue];
//set 'no remote tasking' button state
((NSButton*)[view viewWithTag:BUTTON_TASKING_MODE]).state = [self.preferences[PREF_NO_REMOTE_TASKING] boolValue];
break;
}
//triggers
case TOOLBAR_TRIGGERS:
{
//set view
view = self.triggersView;
//set 'lap lid' trigger button state
((NSButton*)[view viewWithTag:BUTTON_LID_TRIGGER]).state = [self.preferences[PREF_LID_TRIGGER] boolValue];
//set 'usb device' trigger button state
((NSButton*)[view viewWithTag:BUTTON_DEVICE_TRIGGER]).state = [self.preferences[PREF_DEVICE_TRIGGER] boolValue];
//set 'power events' trigger button state
((NSButton*)[view viewWithTag:BUTTON_POWER_TRIGGER]).state = [self.preferences[PREF_POWER_TRIGGER] boolValue];
//set 'start mode' button state
((NSButton*)[view viewWithTag:BUTTON_START_MODE]).state = [self.preferences[PREF_START_MODE] boolValue];
break;
}
@@ -139,8 +156,8 @@
//set 'monitor' button state
((NSButton*)[view viewWithTag:BUTTON_MONITOR_ACTION]).state = [self.preferences[PREF_MONITOR_ACTION] boolValue];
//set 'no remote tasking' button state
((NSButton*)[view viewWithTag:BUTTON_NO_REMOTE_TASKING]).state = [self.preferences[PREF_NO_REMOTE_TASKING] boolValue];
//set 'photo action' button state
((NSButton*)[view viewWithTag:BUTTON_PHOTO_ACTION]).state = [self.preferences[PREF_PHOTO_ACTION] boolValue];
break;
}
@@ -304,6 +321,8 @@
//set appropriate preference
switch(((NSButton*)sender).tag)
{
/* GENERAL PREFS */
//passive mode
case BUTTON_PASSIVE_MODE:
{
@@ -323,35 +342,54 @@
break;
}
//touch id mode
case BUTTON_TOUCHID_MODE:
//auth mode
case BUTTON_AUTH_MODE:
{
//set pref
preferences[PREF_TOUCHID_MODE] = state;
preferences[PREF_AUTH_MODE] = state;
break;
}
//start mode
// also toggle here...
case BUTTON_START_MODE:
//remote tasking
case BUTTON_TASKING_MODE:
{
//set pref
preferences[PREF_START_MODE] = state;
//toggle login item in background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
//toggle
if(YES != toggleLoginItem([NSURL fileURLWithPath:[((AppDelegate*)[[NSApplication sharedApplication] delegate]) path2LoginItem]], [preferences[PREF_START_MODE] intValue]))
{
//err msg
logMsg(LOG_ERR, @"failed to toggle login item");
}
});
preferences[PREF_NO_REMOTE_TASKING] = state;
break;
}
/* TRIGGER PREFS */
//lid trigger
case BUTTON_LID_TRIGGER:
{
//set pref
preferences[PREF_LID_TRIGGER] = state;
break;
}
//usb device trigger
case BUTTON_DEVICE_TRIGGER:
{
//set pref
preferences[PREF_DEVICE_TRIGGER] = state;
break;
}
//power trigger
case BUTTON_POWER_TRIGGER:
{
//set pref
preferences[PREF_POWER_TRIGGER] = state;
break;
}
/* ACTION PREFS */
//execute action
// also toggle state of path
@@ -375,14 +413,16 @@
break;
}
//no camera
case BUTTON_NO_REMOTE_TASKING:
//monitor mode
case BUTTON_PHOTO_ACTION:
{
//set pref
preferences[PREF_NO_REMOTE_TASKING] = state;
preferences[PREF_PHOTO_ACTION] = state;
break;
}
/* UPDATE PREFS */
//(no) update mode
case BUTTON_NO_UPDATES_MODE:
@@ -395,7 +435,7 @@
}
//tell daemon to update preferences
[daemonComms updatePreferences:preferences];
[self.daemonComms updatePreferences:preferences];
//restart login item if user toggle'd icon state
// note: this has to be done after the prefs are written out by the daemon
+151 -41
View File
@@ -11,12 +11,16 @@
<connections>
<outlet property="activityIndicator" destination="12Q-wb-usj" id="OBk-O9-kxj"/>
<outlet property="activityMessage" destination="fFv-Gr-YPE" id="ItR-ES-c5V"/>
<outlet property="appInfo" destination="Saf-Qg-NBo" id="xs0-qj-7dm"/>
<outlet property="appInfo" destination="uXX-Wf-ZLL" id="x8l-zh-2Ww"/>
<outlet property="deviceName" destination="cwA-Cr-acf" id="2Iv-JH-zGS"/>
<outlet property="deviceTrigger" destination="1yX-PX-O3F" id="0PZ-dS-dxu"/>
<outlet property="hostName" destination="mFe-eu-nNm" id="oRs-cQ-NN6"/>
<outlet property="lidTrigger" destination="HhM-Wb-jX6" id="mqX-9A-Tlu"/>
<outlet property="linkedView" destination="Bbb-NZ-tuF" id="vGv-tV-8Mb"/>
<outlet property="powerTrigger" destination="gTR-JD-PmX" id="lLC-rw-fi7"/>
<outlet property="qrcImageView" destination="mos-zb-KRK" id="kKD-Ww-Bkx"/>
<outlet property="qrcView" destination="klO-RE-i9P" id="30O-Tc-jSC"/>
<outlet property="triggerView" destination="Saf-Qg-NBo" id="Aaf-2f-ehE"/>
<outlet property="welcomeView" destination="vZ0-Uk-9P1" id="JgS-86-4S1"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
@@ -27,7 +31,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="800" height="500"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<value key="minSize" type="size" width="800" height="500"/>
<value key="maxSize" type="size" width="800" height="500"/>
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
@@ -97,7 +101,7 @@
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" preferredMaxLayoutWidth="660" translatesAutoresizingMaskIntoConstraints="NO" id="cxG-zN-szL">
<rect key="frame" x="31" y="180" width="738" height="117"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="'Do Not Disturb' attempts to detect 'evil maid' attacks, 
alerting you if somebody tampers with your laptop!" id="tYf-YX-PsV">
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="'Do Not Disturb' attempts to detect 'evil maid' attacks, 
alerting you if somebody tampers with your Mac!" id="tYf-YX-PsV">
<font key="font" size="32" name="AvenirNextCondensed-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -106,33 +110,14 @@
</subviews>
<point key="canvasLocation" x="-156" y="647"/>
</customView>
<customView id="Saf-Qg-NBo" userLabel="App Info">
<customView id="Saf-Qg-NBo" userLabel="Triggers">
<rect key="frame" x="0.0" y="0.0" width="800" height="500"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" preferredMaxLayoutWidth="660" translatesAutoresizingMaskIntoConstraints="NO" id="qwA-lo-6xT">
<rect key="frame" x="68" y="426" width="664" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Let's link with your iPhone to enable mobile alerts" id="SFE-Jt-OYq">
<font key="font" size="32" name="AvenirNextCondensed-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hgC-yZ-fp2">
<rect key="frame" x="342" y="292" width="116" height="73"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="unconnected" id="Mpj-kB-q4i"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tSA-l2-uw1">
<rect key="frame" x="458" y="267" width="142" height="124"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="mobilePhone" id="ijd-WJ-9VT"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="388" translatesAutoresizingMaskIntoConstraints="NO" id="OFG-Gz-3rE">
<rect key="frame" x="18" y="157" width="764" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Download 'Do Not Disturb' from the iOS App Store" id="MAH-fc-gnv">
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="What should trigger 'Do Not Disturb'?" id="SFE-Jt-OYq">
<font key="font" size="32" name="AvenirNextCondensed-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -145,18 +130,7 @@
<rect key="frame" x="0.0" y="0.0" width="800" height="48"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="2" translatesAutoresizingMaskIntoConstraints="NO" id="XhZ-7d-es8">
<rect key="frame" x="14" y="6" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Skip" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="jHq-Ss-1eG">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="buttonHandler:" target="-2" id="skW-Zf-sd1"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="3" translatesAutoresizingMaskIntoConstraints="NO" id="k0d-RO-RST">
<button verticalHuggingPriority="750" fixedFrame="YES" tag="2" translatesAutoresizingMaskIntoConstraints="NO" id="k0d-RO-RST">
<rect key="frame" x="715" y="6" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Next" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7AI-8x-NIJ">
@@ -172,19 +146,153 @@
<color key="fillColor" red="0.57793885469999995" green="0.75859862570000003" blue="0.2368842065" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</box>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Stm-VG-w3v">
<rect key="frame" x="206" y="267" width="138" height="124"/>
<rect key="frame" x="76" y="150" width="180" height="200"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="laptop" id="tNr-00-iNk"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9FN-FI-sj3">
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="HhM-Wb-jX6">
<rect key="frame" x="86" y="143" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" state="on" inset="2" id="6kw-r2-rmN">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e9r-Jq-TLi">
<rect key="frame" x="111" y="143" width="140" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Laptop Lid Open" id="3rB-77-9nQ">
<font key="font" size="15" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="gTR-JD-PmX">
<rect key="frame" x="581" y="143" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="ok3-Cj-tDO">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
</button>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gYG-uo-2F5">
<rect key="frame" x="315" y="165" width="170" height="170"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="usb" id="fcP-xx-A5f"/>
</imageView>
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="1yX-PX-O3F">
<rect key="frame" x="341" y="143" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="bJj-FO-Xp6">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="14" name="Consolas-Bold"/>
</buttonCell>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="93F-5x-Nuf">
<rect key="frame" x="605" y="82" width="177" height="84"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Power On
Computer Wake
Screen Saver Off" id="uOY-7O-Nsb">
<font key="font" size="15" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fTz-Wm-yY8">
<rect key="frame" x="571" y="170" width="159" height="159"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="sleep" id="LyW-2I-nNG"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Vd-M8-05L">
<rect key="frame" x="365" y="143" width="122" height="23"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="USB Insertion" id="dHu-5b-Vk2">
<font key="font" size="15" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<point key="canvasLocation" x="831" y="-530"/>
</customView>
<customView id="uXX-Wf-ZLL" userLabel="App Info">
<rect key="frame" x="0.0" y="0.0" width="800" height="500"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" preferredMaxLayoutWidth="660" translatesAutoresizingMaskIntoConstraints="NO" id="pzP-vr-mwp">
<rect key="frame" x="68" y="426" width="664" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Let's link with your iPhone to enable mobile alerts" id="b7f-6P-fss">
<font key="font" size="32" name="AvenirNextCondensed-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Ko-5I-ZkQ">
<rect key="frame" x="342" y="292" width="116" height="73"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="unconnected" id="biq-NY-wHH"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rla-hF-y7t">
<rect key="frame" x="458" y="267" width="142" height="124"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="mobilePhone" id="ks4-qM-EJX"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="388" translatesAutoresizingMaskIntoConstraints="NO" id="1NC-nB-9TF">
<rect key="frame" x="18" y="157" width="764" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Download 'Do Not Disturb' from the iOS App Store" id="xMO-kA-ubY">
<font key="font" size="32" name="AvenirNextCondensed-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box fixedFrame="YES" boxType="custom" borderType="none" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="2wk-PX-com">
<rect key="frame" x="0.0" y="0.0" width="800" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView" ambiguous="YES" id="Cvt-0u-Fn9">
<rect key="frame" x="0.0" y="0.0" width="800" height="48"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="3" translatesAutoresizingMaskIntoConstraints="NO" id="SzW-hq-Cay">
<rect key="frame" x="14" y="6" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Skip" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="F4D-7D-b7M">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="buttonHandler:" target="-2" id="Q9F-RZ-B16"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="IYF-UZ-e79">
<rect key="frame" x="715" y="6" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Next" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="KzN-1a-Bgl">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="buttonHandler:" target="-2" id="4kt-qR-EdK"/>
</connections>
</button>
</subviews>
</view>
<color key="fillColor" red="0.57793885469999995" green="0.75859862570000003" blue="0.2368842065" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</box>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pne-xe-SXP">
<rect key="frame" x="206" y="267" width="138" height="124"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="laptop" id="Yka-Wc-tqb"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SIf-al-GRB">
<rect key="frame" x="337" y="94" width="127" height="55"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="appStore" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="cPG-lr-39E">
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="appStore" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="rpd-Oh-aLh">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="downloadApp:" target="-2" id="IrW-7u-1OG"/>
<action selector="downloadApp:" target="-2" id="u1k-Ns-xde"/>
</connections>
</button>
</subviews>
@@ -295,7 +403,7 @@
<rect key="frame" x="0.0" y="0.0" width="800" height="48"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="4" translatesAutoresizingMaskIntoConstraints="NO" id="SCr-nL-4pA">
<button verticalHuggingPriority="750" fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="SCr-nL-4pA">
<rect key="frame" x="705" y="6" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Done" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Jhe-Eu-d4x">
@@ -4853,6 +4961,8 @@ INsABCDgAAAAAAAABAEAAAAAAAAAVgAAAAAAAAAAAAAAAAAEIOI
<image name="laptop" width="256" height="256"/>
<image name="linked" width="256" height="467"/>
<image name="mobilePhone" width="512" height="512"/>
<image name="sleep" width="256" height="256"/>
<image name="unconnected" width="128" height="128"/>
<image name="usb" width="256" height="256"/>
</resources>
</document>
+15
View File
@@ -17,12 +17,27 @@
//welcome view
@property (strong) IBOutlet NSView *welcomeView;
//app info view
@property (strong) IBOutlet NSView *triggerView;
//app info view
@property (strong) IBOutlet NSView *appInfo;
//config view
@property (strong) IBOutlet NSView *qrcView;
//button
// trigger for lid opens
@property (weak) IBOutlet NSButton *lidTrigger;
//button
// trigger for device insertions
@property (weak) IBOutlet NSButton *deviceTrigger;
//button
// trigger for power events
@property (weak) IBOutlet NSButton *powerTrigger;
//activity indicator
@property (weak) IBOutlet NSProgressIndicator *activityIndicator;
+61 -5
View File
@@ -15,10 +15,11 @@
#import "WelcomeWindowController.h"
#define VIEW_WELCOME 0
#define VIEW_APP_INFO 1
#define SKIP_LINKING 2
#define VIEW_QRC 3
#define VIEW_LINKED 4
#define SELECT_TRIGGERS 1
#define VIEW_APP_INFO 2
#define SKIP_LINKING 3
#define VIEW_QRC 4
#define VIEW_LINKED 5
@implementation WelcomeWindowController
@@ -75,16 +76,48 @@
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (100 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
//set first responder
[self.window makeFirstResponder:[self.welcomeView viewWithTag:VIEW_APP_INFO]];
[self.window makeFirstResponder:[self.welcomeView viewWithTag:SELECT_TRIGGERS]];
});
break;
}
//select triggers info
case SELECT_TRIGGERS:
{
//remove prev. subview
[[[self.window.contentView subviews] lastObject] removeFromSuperview];
//no a laptop?
// uncheck and disable laptop lid trigger
if(stateUnavailable == getLidState())
{
//uncheck
self.lidTrigger.state = NSOffState;
//disable
self.lidTrigger.enabled = NO;
}
//set view
[self.window.contentView addSubview:self.triggerView];
//make 'next' button first responder
[self.window makeFirstResponder:[self.triggerView viewWithTag:VIEW_APP_INFO]];
break;
}
//app info
case VIEW_APP_INFO:
{
//save trigger prefs
[self setTriggers];
//dbg msg
logMsg(LOG_DEBUG, @"saved triggers");
//remove prev. subview
[[[self.window.contentView subviews] lastObject] removeFromSuperview];
@@ -130,6 +163,29 @@
break;
}
}
return;
}
//get user's prefs for triggers
// then send them to daemon to save into prefs
-(void)setTriggers
{
//daemon comms
DaemonComms* daemonComms = nil;
//alloc/init
daemonComms = [[DaemonComms alloc] init];
//dbg msg
logMsg(LOG_DEBUG, @"setting trigger prefs");
//send to daemon
// will update preferences
[daemonComms updatePreferences:@{PREF_LID_TRIGGER:[NSNumber numberWithInteger:self.lidTrigger.state],
PREF_DEVICE_TRIGGER:[NSNumber numberWithInteger:self.deviceTrigger.state],
PREF_POWER_TRIGGER:[NSNumber numberWithInteger:self.powerTrigger.state]}];
return;
}
-1
View File
@@ -14,7 +14,6 @@
#import "Logging.h"
#import "Utilities.h"
#import <ServiceManagement/ServiceManagement.h>
int main(int argc, const char * argv[])
{
+42 -2
View File
@@ -148,6 +148,18 @@
// status
#define PREF_IS_DISABLED @"disabled"
//prefs
// lid trigger
#define PREF_LID_TRIGGER @"lidTrigger"
//prefs
// device trigger
#define PREF_DEVICE_TRIGGER @"deviceTrigger"
//prefs
// power trigger
#define PREF_POWER_TRIGGER @"powerTrigger"
//prefs
// passive mode
#define PREF_PASSIVE_MODE @"passiveMode"
@@ -157,8 +169,8 @@
#define PREF_NO_ICON_MODE @"noIconMode"
//prefs
// touchID mode
#define PREF_TOUCHID_MODE @"touchIDMode"
// auth mode
#define PREF_AUTH_MODE @"touchIDMode"
//prefs
// start mode
@@ -180,6 +192,10 @@
// monitor stuff
#define PREF_MONITOR_ACTION @"monitorAction"
//pref
// auto take photo
#define PREF_PHOTO_ACTION @"photoAction"
//pref
// no remote tasking
#define PREF_NO_REMOTE_TASKING @"noRemoteTasking"
@@ -188,6 +204,19 @@
// update mode
#define PREF_NO_UPDATES_MODE @"noUpdatesMode"
//trigger: all
// based on prefs
#define ALL_TRIGGERS 0x0
//trigger: lid
#define LID_TRIGGER 0x1
//trigger: devices
#define DEVICE_TRIGGER 0x2
//trigger: power
#define POWER_TRIGGER 0x3
//log file
#define LOG_FILE_NAME @"DND.log"
@@ -195,9 +224,20 @@
// timestamp
#define ALERT_TIMESTAMP @"timestamp"
//alert key
// type (lid, usb, power)
#define ALERT_TYPE @"eventType"
//alert key
// info (specific to event type)
#define ALERT_INFO @"info"
//key for device name
#define KEY_DEVICE_NAME @"deviceName"
//key for power type
#define KEY_POWER_TYPE @"powerType"
//key for host name
#define KEY_HOST_NAME @"hostName"