11 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
Patrick Wardle 292699e5f5 v.1.2.2
updated project to be buildable as an archive
minor UI fixes
2018-06-15 11:32:36 -10:00
Patrick Wardle 681f836fbb always unset 'undelivered' alert after timeout
if alert was not delivered after multiple attempts (i.e. network offline), it wouldn't be cleared, preventing new alerts from being delivered
2018-06-15 08:24:08 -10:00
Patrick Wardle 641e1a9640 v.1.2.1
bumped version strings
2018-06-10 12:59:28 -10:00
Patrick Wardle 8c7c44432f carthage update 2018-05-29 10:43:33 -10:00
Patrick Wardle 4101c011fe cmdline install/uninstall
-see: https://github.com/objective-see/DoNotDisturb/issues/9
2018-05-29 10:18:10 -10:00
Patrick Wardle 76b6271a0c v 1.2.0 (RC)
-linked with updated DND framework (iOS notifications)
-bumped version #
-compiled with update version of Xcode
-minor UI improvements
2018-05-28 10:30:32 -10:00
Patrick Wardle 4927324f85 improved network alert queuing 2018-05-05 11:37:54 -10:00
Patrick Wardle eead935265 alerting queing, UI improvements, etc
-alert(s) now queued if network connectivity isn't immediately present on lid event
-installer now shows 'upgrade' if app is already installed
-certain preference access is now synchronized
2018-05-03 15:40:10 -10:00
Patrick Wardle e5323156a8 improved unistaller, improved (multi)camera selection
-uninstall cleans up empty directory
-uninstall keeps going if it can't login item
-linked w/ new framework which improves camera selection
  --first, looks for apple built in camera
  --otherwise, falls back to default
2018-04-27 10:18:05 -10:00
Patrick Wardle 2510865c24 improved uninstall logic
on uninstall, if no other Objective-See tools are installed remove the '/Library/Objective-See/' directory as well...
2018-04-26 12:11:41 -10:00
55 changed files with 2079 additions and 1103 deletions
+5 -5
View File
@@ -1,14 +1,14 @@
github "Alamofire/Alamofire" "4.7.2"
github "Alamofire/AlamofireImage" "3.3.1"
github "DigitaSecurity/CocoaMQTT" "0c56a9397d5d3fcea4472671e24014a5f31f9b15"
github "DigitaSecurity/dnd" "35e24a1a4397c7b2c08b3bdc0df4a160ad340064"
github "DigitaSecurity/CocoaAsyncSocket" "79a11b7036d0a77ca95de42cc1c92b5a4c50f0c9"
github "DigitaSecurity/dnd" "02b4b2c6d495ebafda648e6ca6ebfbed7c20d0e7"
github "SnapKit/SnapKit" "4.0.0"
github "SwiftyJSON/SwiftyJSON" "4.1.0"
github "emaloney/CleanroomLogger" "5.1.0"
github "emqtt/CocoaMQTT" "4ef7bdcf3f0a754790dab8bff86dec67a695ee3c"
github "getsentry/sentry-cocoa" "3.12.0"
github "ninjaprox/NVActivityIndicatorView" "4.2.0"
github "ninjaprox/NVActivityIndicatorView" "4.2.1"
github "radex/SwiftyTimer" "2.0.0"
github "realm/realm-cocoa" "v3.3.2"
github "robbiehanson/CocoaAsyncSocket" "7.6.3"
github "realm/realm-cocoa" "v3.7.1"
github "saoudrizwan/Disk" "0.3.3"
github "soffes/CommonCrypto" "v1.1.0"
-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
+18 -27
View File
@@ -301,17 +301,12 @@ bail:
//define block
void (^block)(NSNumber *) = ^(NSNumber *result)
{
//callback from XPC will be a bg thread
// so since we're updating UI, invoke on main thread
dispatch_async(dispatch_get_main_queue(), ^{
//signal sema
dispatch_semaphore_signal(semaphore);
//signal sema
dispatch_semaphore_signal(semaphore);
//save result
wasInstalled = (BOOL)(result.intValue == 0);
});
//save result
wasInstalled = (BOOL)(result.intValue == 0);
};
//install
@@ -377,17 +372,11 @@ bail:
//define block
void (^block)(NSNumber *) = ^(NSNumber *result)
{
//callback from XPC will be a bg thread
// so since we're updating UI, invoke on main thread
dispatch_async(dispatch_get_main_queue(), ^{
//signal sema
dispatch_semaphore_signal(semaphore);
//signal sema
dispatch_semaphore_signal(semaphore);
//save result
wasUninstalled = (BOOL)(result.intValue == 0);
});
//save result
wasUninstalled = (BOOL)(result.intValue == 0);
};
//init path to login item
@@ -400,22 +389,24 @@ bail:
//err msg
logMsg(LOG_ERR, @"failed to uninstall login item");
//bail
goto bail;
//keep going though...
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"uninstalled login item (%@)", loginItem]);
#ifdef DEBUG
else
{
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"uninstalled login item (%@)", loginItem]);
}
#endif
//uninstall
// also sets return var/flag
// also sets return var/flag in block
[xpcComms uninstall:full reply:block];
//wait for install to be completed by XPC
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
bail:
return wasUninstalled;
}
@end
@@ -50,14 +50,22 @@
// also brings window to front
-(void)configure:(BOOL)isInstalled
{
//set title
self.window.title = [NSString stringWithFormat:@"Do Not Disturb (v. %@)", getAppVersion()];
//init status msg
[self.statusMsg setStringValue:@"evil maids: stay out! 🙅‍♀️🚪"];
//enable 'uninstall' button when app is installed already
//app already installed?
// enable 'uninstall' button
// change install button to say 'upgrade'
if(YES == isInstalled)
{
//enable
//enable 'uninstall'
self.uninstallButton.enabled = YES;
//set to 'upgrade'
self.installButton.title = ACTION_UPGRADE;
}
//otherwise disable
else
@@ -1,8 +1,8 @@
<?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">
<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="13771"/>
<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"/>
@@ -67,11 +67,6 @@
<action selector="buttonHandler:" target="-2" id="1wC-Ls-D2F"/>
</connections>
</button>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K52-9g-sjn">
<rect key="frame" x="138" y="109" width="243" height="67"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="dndText" id="WRg-I2-vkK"/>
</imageView>
<button hidden="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QWu-qZ-Za2">
<rect key="frame" x="414" y="33" width="25" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
@@ -83,6 +78,11 @@
<action selector="info:" target="-2" id="tg3-SV-AH9"/>
</connections>
</button>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hGI-P1-hcr">
<rect key="frame" x="140" y="113" width="302" height="46"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="dndText" id="ZKa-1w-mi3"/>
</imageView>
</subviews>
</view>
<connections>
@@ -136,7 +136,7 @@
</objects>
<resources>
<image name="dndIcon" width="256" height="256"/>
<image name="dndText" width="266.605712890625" height="34.354286193847656"/>
<image name="dndText" width="164.57142639160156" height="21.188571929931641"/>
<image name="objectiveSee" width="943" height="236"/>
</resources>
</document>
@@ -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: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>
+2 -2
View File
@@ -13,11 +13,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) 2018 Objective-See</string>
<key>NSMainNibFile</key>
+8
View File
@@ -75,6 +75,14 @@ elif [ "${1}" == "-uninstall" ]; then
if [[ "${2}" -eq "1" ]]; then
rm -rf $INSTALL_DIRECTORY
#no other objective-see tools?
# then delete that directory too
baseDir=$(dirname $INSTALL_DIRECTORY)
if [ ! "$(ls -A $baseDir)" ]; then
rm -rf $baseDir
fi
#partial
# just delete daemon, leaving prefs, etc
else
+116 -1
View File
@@ -9,7 +9,122 @@
@import Cocoa;
#import "Consts.h"
#import "Logging.h"
#import "utilities.h"
#import "Configure.h"
//cmdline interface
// install or uninstall
BOOL cmdlineInterface(int action);
//main interface
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
//status
int status = -1;
//cmdline install?
if(YES == [[[NSProcessInfo processInfo] arguments] containsObject:CMDLINE_FLAG_INSTALL])
{
//dbg msg
logMsg(LOG_DEBUG, @"performing commandline install");
//install
if(YES != cmdlineInterface(ACTION_INSTALL_FLAG))
{
//err msg
printf("\nDND ERROR: install failed\n\n");
//bail
goto bail;
}
//dbg msg
printf("DND: install ok!\n");
//happy
status = 0;
}
//cmdline uninstall?
else if(YES == [[[NSProcessInfo processInfo] arguments] containsObject:CMDLINE_FLAG_UNINSTALL])
{
//dbg msg
logMsg(LOG_DEBUG, @"performing commandline uninstall");
//install
if(YES != cmdlineInterface(ACTION_UNINSTALL_FLAG))
{
//err msg
printf("\nDND ERROR: uninstall failed\n\n");
//bail
goto bail;
}
//dbg msg
printf("DND: uninstall ok!\n");
//happy
status = 0;
}
//default run mode
// just kick off main app logic
else
{
//app main
status = NSApplicationMain(argc, (const char **) argv);
}
bail:
return status;
}
//cmdline interface
// install or uninstall
BOOL cmdlineInterface(int action)
{
//flag
BOOL wasConfigured = NO;
//configure obj
Configure* configure = nil;
//alloc/init
configure = [[Configure alloc] init];
//first check root
if(0 != geteuid())
{
//err msg
printf("\nDND ERROR: cmdline interface actions require root!\n\n");
//bail
goto bail;
}
//configure
wasConfigured = [configure configure:action];
if(YES != wasConfigured)
{
//bail
goto bail;
}
//happy
wasConfigured = YES;
bail:
//cleanup
if(nil != configure)
{
//cleanup
[configure removeHelper];
}
return wasConfigured;
}
+2 -2
View File
@@ -37,7 +37,7 @@ dispatch_source_t dispatchSource = nil;
//configure
// pass in 'install' flag
result = [NSNumber numberWithInt:[self configure:app arguements:@[@"-install"]]];
result = [NSNumber numberWithInt:[self configure:app arguements:@[CMDLINE_FLAG_INSTALL]]];
//reply to client
reply(result);
@@ -57,7 +57,7 @@ dispatch_source_t dispatchSource = nil;
//configure
// pass in 'uninstall' flag, and partial/full
result = [NSNumber numberWithInt:[self configure:app arguements:@[@"-uninstall", [NSNumber numberWithBool:full].stringValue]]];
result = [NSNumber numberWithInt:[self configure:app arguements:@[CMDLINE_FLAG_UNINSTALL, [NSNumber numberWithBool:full].stringValue]]];
//reply to client
reply(result);
+1 -1
View File
@@ -9,7 +9,7 @@
<key>CFBundleName</key>
<string>helper</string>
<key>CFBundleVersion</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright (c) 2018 Objective-See</string>
<key>SMAuthorizedClients</key>
+16 -20
View File
@@ -11,22 +11,20 @@
4BE4906110445E13006BE471 /* Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE4905510445DDD006BE471 /* Helper.m */; };
4BE4906410445F2F006BE471 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BE4906310445F2F006BE471 /* Security.framework */; };
4BE4906810445F36006BE471 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BE4906710445F36006BE471 /* ServiceManagement.framework */; };
4BE49092104463A0006BE471 /* com.objective-see.dnd.installer.helper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BE4905D10445E0A006BE471 /* com.objective-see.dnd.installer.helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
4BE49092104463A0006BE471 /* com.objective-see.dnd.installer.helper in Copy Helper */ = {isa = PBXBuildFile; fileRef = 4BE4905D10445E0A006BE471 /* com.objective-see.dnd.installer.helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
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 */; };
CD20A0D02057992F0044BCC5 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD20A0CF2057992F0044BCC5 /* Sentry.framework */; };
CD20A0D320579A380044BCC5 /* Sentry.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = CD20A0CF2057992F0044BCC5 /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CD20A0D320579A380044BCC5 /* Sentry.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = CD20A0CF2057992F0044BCC5 /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CD2F4082204B462E0066673E /* dndText.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAAC24A20226DFB0032F2E6 /* dndText.png */; };
CD3307AE203567D500F10D71 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD3307AD203567D400F10D71 /* Assets.xcassets */; };
CD73DA912004629D001FFC84 /* HelperInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = CD73DA902004629D001FFC84 /* HelperInterface.m */; };
@@ -53,24 +51,26 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
4BE49098104463C5006BE471 /* CopyFiles */ = {
4BE49098104463C5006BE471 /* Copy Helper */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = Contents/Library/LaunchServices;
dstSubfolderSpec = 1;
files = (
4BE49092104463A0006BE471 /* com.objective-see.dnd.installer.helper in CopyFiles */,
4BE49092104463A0006BE471 /* com.objective-see.dnd.installer.helper in Copy Helper */,
);
name = "Copy Helper";
runOnlyForDeploymentPostprocessing = 0;
};
CD20A0D220579A1B0044BCC5 /* CopyFiles */ = {
CD20A0D220579A1B0044BCC5 /* Copy Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
CD20A0D320579A380044BCC5 /* Sentry.framework in CopyFiles */,
CD20A0D320579A380044BCC5 /* Sentry.framework in Copy Frameworks */,
);
name = "Copy Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
@@ -93,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; };
@@ -190,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 */,
@@ -286,9 +280,9 @@
8D1107290486CEB800E47090 /* Resources */,
8D11072C0486CEB800E47090 /* Sources */,
8D11072E0486CEB800E47090 /* Frameworks */,
4BE49098104463C5006BE471 /* CopyFiles */,
4BE49098104463C5006BE471 /* Copy Helper */,
CD17D55F20115E5E00F798D7 /* ShellScript */,
CD20A0D220579A1B0044BCC5 /* CopyFiles */,
CD20A0D220579A1B0044BCC5 /* Copy Frameworks */,
);
buildRules = (
);
@@ -307,7 +301,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0920;
LastUpgradeCheck = 0930;
TargetAttributes = {
4BE4905C10445E0A006BE471 = {
DevelopmentTeam = VBG97UB4TA;
@@ -342,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 */,
@@ -369,7 +362,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"\n\nrm -rf \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/Do Not Disturb.bundle\"\ncp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb.bundle\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"";
shellScript = "#archiving\nif [[ $BUILT_PRODUCTS_DIR = *\"ArchiveIntermediates\"* ]]; then\n\ncp -R -f \"$PROJECT_TEMP_ROOT/UninstalledProducts/macosx/Do Not Disturb.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"\ncp -R -f \"$PROJECT_TEMP_ROOT/UninstalledProducts/macosx/Do Not Disturb.bundle\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"\n\n#normal build\nelse\n\ncp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"\nrm -rf \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources/Do Not Disturb.bundle\"\ncp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb.bundle\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Resources\"\n\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -390,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 */,
@@ -489,6 +481,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd.installer";
PRODUCT_NAME = "Do Not Disturb Installer";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = NO;
VALID_ARCHS = x86_64;
};
name = Debug;
@@ -511,6 +504,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd.installer";
PRODUCT_NAME = "Do Not Disturb Installer";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = NO;
VALID_ARCHS = x86_64;
};
name = Release;
@@ -529,6 +523,7 @@
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -580,6 +575,7 @@
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@@ -68,7 +68,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -88,7 +87,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+4 -2
View File
@@ -15,13 +15,15 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>CFBundleVersion</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>NSHumanReadableCopyright</key>
<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 = (
@@ -393,7 +416,7 @@
7D7755C81F02DF9400D0017D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Objective-See";
TargetAttributes = {
2063725A203DC70A006D4C38 = {
@@ -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 */,
@@ -537,6 +563,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -544,6 +571,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -590,6 +618,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -597,6 +626,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -642,6 +672,7 @@
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_NAME = "Do Not Disturb";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Debug;
};
@@ -665,6 +696,7 @@
OTHER_LDFLAGS = "";
PRODUCT_NAME = "Do Not Disturb";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
-79
View File
@@ -1,79 +0,0 @@
//
// file: Lid.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 <dnd/dnd-Swift.h>
@import Foundation;
#import <IOKit/IOKitLib.h>
#import <IOKit/pwr_mgt/IOPM.h>
/* FUNCTIONS */
//check if user auth'd
// a) within last 10 seconds
// b) via biometrics (touchID)
BOOL authViaTouchID(void);
/* CLASS INTERFACE */
@interface Lid : NSObject <DNDClientMacDelegate>
{
//lid state
LidState lidState;
//dispatch queue
dispatch_queue_t dispatchQ;
//notification port
IONotificationPortRef notificationPort;
//notification object
io_object_t notification;
}
/* PROPERTIES */
//client
@property(nonatomic, retain)DNDClientMac *client;
//dismiss dispatch group
@property(nonatomic, retain)dispatch_group_t dispatchGroup;
//dispatch group flag
@property BOOL dispatchGroupEmpty;
//dispatch blocks
@property(nonatomic, retain)NSMutableArray* dispatchBlocks;
/* METHODS */
//check if client should be init'd
-(BOOL)shouldInitClient;
//init dnd client
-(BOOL)clientInit;
//cancel all dipatch blocks
-(void)cancelDispatchBlocks;
//register for notifications
-(BOOL)register4Notifications;
//register for notifications
-(void)unregister4Notifications;
//proces lid open event
-(void)processEvent:(NSDate*)timestamp;
//execute action
-(int)executeAction:(NSString*)path user:(NSString*)user;
@end
+95 -25
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,21 +189,88 @@ 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];
}
}
//sync prefs
@synchronized(self.preferences)
{
//updating list of registered devices?
// it's a dictionary so requires an extra merge
if( (nil != updates[PREF_REGISTERED_DEVICES]) &&
@@ -221,6 +287,8 @@ bail:
//merge
[self.preferences addEntriesFromDictionary:updates];
}
}//sync
//save
if(YES != [self save])
@@ -244,9 +312,6 @@ bail:
// then update preferences with this list...
-(void)updateRegisteredDevices
{
//current devices
NSDictionary* currentDevices = nil;
//client
DNDClientMac *client;
@@ -262,10 +327,9 @@ bail:
//alloc dictionary
devices = [NSMutableDictionary dictionary];
//get current devices
// aren't any, just bail
currentDevices = self.preferences[PREF_REGISTERED_DEVICES];
if(0 == currentDevices.count)
//aren't any registered devices?
// just bail
if(0 == [self.preferences[PREF_REGISTERED_DEVICES] count])
{
//bail
goto bail;
@@ -305,20 +369,26 @@ bail:
goto bail;
}
//sync prefs
@synchronized(self.preferences)
{
//get list of registered devices from server
// build (updated) list of devices id : device name mappings
for(NSString* deviceID in macShadow.state.reported.endpoints)
{
//sanity check
if(nil == currentDevices[deviceID])
if(nil == self.preferences[PREF_REGISTERED_DEVICES][deviceID])
{
//skip
continue;
}
//add current device name
devices[deviceID] = currentDevices[deviceID];
devices[deviceID] = self.preferences[PREF_REGISTERED_DEVICES][deviceID];
}
}//sync
//no registered devices?
// remove key from preferences
+83
View File
@@ -0,0 +1,83 @@
// file: Triggers.m
// project: DND (launch daemon)
// 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;
/* FUNCTIONS */
//check if user auth'd
// a) within last 10 seconds
// b) via biometrics (touchID)
BOOL authViaTouchID(void);
/* CLASS INTERFACE */
@interface Triggers : NSObject <DNDClientMacDelegate>
{
}
/* 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;
//dismiss dispatch group
@property(nonatomic, retain)dispatch_group_t dispatchGroup;
//dispatch group flag
@property BOOL dispatchGroupEmpty;
//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;
//init dnd client
-(BOOL)clientInit;
//cancel all dipatch blocks
-(void)cancelDispatchBlocks;
//process trigger event
-(void)processEvent:(NSUInteger)type info:(NSDictionary*)info;
//wait for dismiss
// note: handles multiple client via dispatch group
-(void)wait4Dismiss;
//execute action
-(int)executeAction:(NSString*)path user:(NSString*)user;
@end
@@ -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];
}
//(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,11 +118,17 @@ 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
@@ -256,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();
@@ -344,164 +220,128 @@ 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
-(void)processEvent:(NSUInteger)type info:(NSDictionary*)info
{
//monitor obj
Monitor* monitor = nil;
//console user
NSString* consoleUser = nil;
//current prefs
NSDictionary* currentPrefs = nil;
//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
@@ -534,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,41 +404,43 @@ bail:
logMsg(LOG_DEBUG, @"(re)initialized DND client for framework");
}
//send to server
// and wait for dismiss
//registered device?
// send alert to server
if(nil != self.client)
{
//get user
consoleUser = getConsoleUser();
if(0 == consoleUser.length)
//dbg msg
logMsg(LOG_DEBUG, @"found registerd device/client, will try send alert to server");
//no undelivered alert?
// spawn off dispatch to deliver
if(nil == self.undeliveredAlert)
{
//defult
consoleUser = @"unknown";
//dbg msg
logMsg(LOG_DEBUG, @"no (prev) alerts undelivered");
//save 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:getConsoleUser()];
});
}
//dbg msg
// and log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"sending alert to server (user: %@)", consoleUser]);
//send
[self.client sendAlertWithUuid:[NSUUID UUID] userName:consoleUser date:timestamp completion:^(NSNumber* response)
//already send(ing) alert
// just update, so if network comes online, will use this one (as latest)
else
{
//log
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"response from server: %@", response]);
//dbg msg
logMsg(LOG_DEBUG, @"previously alert undelivered, just updating that...");
//after getting server response
// update list of registered devices...
[preferences updateRegisteredDevices];
}];
//wait for dismiss
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//wait
[self wait4Dismiss];
});
//save timestamp
self.undeliveredAlert = [NSDate date];
}
}
//didn't send
@@ -607,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:
@@ -615,6 +456,94 @@ bail:
return;
}
//send alert to server
// contains extra logic to check/wait for network connectivty
-(void)send2Server:(NSString*)user
{
//flag
BOOL sent = NO;
//response
__block NSNumber* response = nil;
//no user?
// set to default, but will try again
if(0 == user.length)
{
//default
user = USER_UNKNOWN;
}
//try send up to 10 times
// basically gives time for network to reconnect if lid-shut disconnected wifi, etc...
for(NSUInteger i=0; i<10; i++)
{
//unknown user?
// try get user again
if(YES == [user isEqualToString:USER_UNKNOWN])
{
//get user
user = getConsoleUser();
if(0 == user.length)
{
//default
user = USER_UNKNOWN;
}
}
//dbg msg
// and log to file
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"sending alert to server (user: %@)", user]);
//send
response = [self.client sendAlertSyncWithUuid:[NSUUID UUID] userName:user date:self.undeliveredAlert];
if(nil != response)
{
//log
logMsg(LOG_DEBUG|LOG_TO_FILE, [NSString stringWithFormat:@"response from server: %@", response]);
//after getting server response
// update list of registered devices
[preferences updateRegisteredDevices];
//set flag
sent = YES;
//wait for dismiss
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//wait
[self wait4Dismiss];
});
//done
break;
}
//dbg msg
logMsg(LOG_DEBUG, @"could not reach endpoint - network offline?");
//not online
//... so tak a nap
[NSThread sleepForTimeInterval:i*1.5];
}
//check
// log err
if(YES != sent)
{
//log
logMsg(LOG_DEBUG|LOG_TO_FILE, @"unable to deliver alert (network offline?)");
}
//unset
// even if we failed to send
self.undeliveredAlert = nil;
return;
}
//wait for dismiss
// note: handles multiple client via dispatch group
-(void)wait4Dismiss
@@ -754,7 +683,7 @@ bail:
int result = -1;
//exec script
// su man -c <user> <path>
// su -c <user> <path>
results = execTask(@"/usr/bin/su", @[user, @"-c", path], YES);
//dbg msg
+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
@@ -18,23 +18,23 @@
// note: will only detect files downloaded from apps such as browsers (that have 'kMDItemWhereFroms' key set)
-(void)start
{
//has to be run on the main thread!
dispatch_async(dispatch_get_main_queue(), ^{
//alloc/init query
query = [[NSMetadataQuery alloc] init];
//add observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDownloadEvent:) name:NSMetadataQueryDidUpdateNotification object:query];
//has to be run on the main thread!
dispatch_async(dispatch_get_main_queue(), ^{
//add observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDownloadEvent:) name:NSMetadataQueryDidUpdateNotification object:self.query];
//set delegate
self.query.delegate = self;
//set delegate
self.query.delegate = self;
//set predicate
self.query.predicate = [NSPredicate predicateWithFormat:@"%K like '*'", @"kMDItemWhereFroms"];
//set predicate
self.query.predicate = [NSPredicate predicateWithFormat:@"%K like '*'", @"kMDItemWhereFroms"];
//start
[query startQuery];
//start
[self.query startQuery];
});
+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
@@ -233,7 +233,7 @@
7D7755DB1F02E05B00D0017D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Objective-See";
TargetAttributes = {
7D7755E21F02E05B00D0017D = {
@@ -345,6 +345,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -352,6 +353,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -398,6 +400,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -405,6 +408,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -447,6 +451,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd.helper";
PRODUCT_NAME = "Do Not Disturb Helper";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Debug;
};
@@ -467,6 +472,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd.helper";
PRODUCT_NAME = "Do Not Disturb Helper";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
+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];
+2 -2
View File
@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
+20 -6
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 */,
@@ -330,7 +336,7 @@
7D564DA11F18434F00B8AAD6 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Objective-See";
TargetAttributes = {
7D564DA81F18434F00B8AAD6 = {
@@ -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 */,
@@ -418,7 +426,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "#for normal builds\n# ->just copy into app\nmkdir -p \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems\"\ncp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb Helper.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems\"";
shellScript = "mkdir -p \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems\"\n\n#archiving\nif [[ $BUILT_PRODUCTS_DIR = *\"ArchiveIntermediates\"* ]]; then\n cp -R -f \"$PROJECT_TEMP_ROOT/UninstalledProducts/macosx/Do Not Disturb Helper.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems\"\n\n#normal build\nelse\n cp -R -f \"$BUILT_PRODUCTS_DIR/Do Not Disturb Helper.app\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Library/LoginItems\"\nfi";
};
/* End PBXShellScriptBuildPhase section */
@@ -477,6 +485,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -484,6 +493,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -530,6 +540,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -537,6 +548,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -580,6 +592,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd";
PRODUCT_NAME = "Do Not Disturb";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Debug;
};
@@ -601,6 +614,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.dnd";
PRODUCT_NAME = "Do Not Disturb";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
};
name = Release;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@@ -40,7 +40,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -58,9 +57,8 @@
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
language = ""
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -77,6 +75,12 @@
ReferencedContainer = "container:mainApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-prefs"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
+2 -2
View File
@@ -1,8 +1,8 @@
<?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">
<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="13771"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
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

+2 -2
View File
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>CFBundleVersion</key>
<string>1.1.0</string>
<string>1.2.2</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
+138 -35
View File
@@ -1,8 +1,8 @@
<?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" 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="13771"/>
<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"/>
@@ -36,15 +37,15 @@
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="196" y="240" width="600" height="383"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="600" height="383"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X2d-3b-ceM">
<rect key="frame" x="0.0" y="0.0" width="600" height="62"/>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TfC-c7-kXd">
<rect key="frame" x="154" y="0.0" width="293" height="46"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" image="dndText" id="W8J-sT-YoM"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="dndText" id="EOL-U2-Wgh"/>
</imageView>
</subviews>
</view>
@@ -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"/>
@@ -523,7 +625,7 @@
<windowStyleMask key="styleMask" utility="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="2832" y="172" width="594" height="440"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="jEo-ef-0kG">
<rect key="frame" x="0.0" y="0.0" width="594" height="440"/>
<autoresizingMask key="autoresizingMask"/>
@@ -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
+154 -44
View File
@@ -1,8 +1,8 @@
<?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" 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="13771"/>
<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>
@@ -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">
<rect key="frame" x="345" y="100" width="110" height="49"/>
<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="bevel" bezelStyle="rounded" image="appStore" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="cPG-lr-39E">
<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="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[])
{
+1 -1
View File
@@ -1 +1 @@
Lance Gaines, Ash Morgan, Jeff Golden, Nando Mendonca, Khalil Sehnaoui, Gamer_Bot
Halo Privacy, Ash Morgan, Geoffrey Weber, Jeff Golden, Khalil Sehnaoui, Nando Mendonca, Gamer_Bot
+51 -23
View File
@@ -43,28 +43,19 @@
//iOS companion app URL
#define IOS_APP_URL @"https://itunes.apple.com/us/app/do-not-disturb-companion/id1345055731?mt=8"
//action to install
// also button title
#define ACTION_INSTALL @"Install"
//button title: upgrade
#define ACTION_UPGRADE @"Upgrade"
//action to uninstall
// also button title
#define ACTION_UNINSTALL @"Uninstall"
//button title
// close
//button title: close
#define ACTION_CLOSE @"Close"
//button title
// next
//button title: next
#define ACTION_NEXT @"Next »"
//button title
// no
//button title: no
#define ACTION_NO @"No"
//button title
// yes
//button title: yes
#define ACTION_YES @"Yes!"
//frame shift
@@ -144,12 +135,6 @@
//product version url
#define PRODUCT_VERSIONS_URL @"https://objective-see.com/products.json"
//flag to uninstall
#define ACTION_UNINSTALL_FLAG 0
//flag to install
#define ACTION_INSTALL_FLAG 1
//login item name
#define LOGIN_ITEM_NAME @"Do Not Disturb Helper"
@@ -163,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"
@@ -172,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
@@ -195,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"
@@ -203,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"
@@ -210,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"
@@ -294,5 +319,8 @@
//monitoring timeout
#define MONITORING_TIMEOUT 60*3
//unknown user
#define USER_UNKNOWN @"unknown"
#endif