'support us' window added to installer/about
wrapped debug statements with #ifdef DEBUG improved NSTask to (hopefully) avoid hangs added dictionary of activation alerts to help with deactivation alert logic
This commit is contained in:
parent
c6eaba30f2
commit
a837ffdcf6
|
@ -23,6 +23,7 @@
|
||||||
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4F81D658DB90066232A /* ErrorWindowController.xib */; };
|
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C4F81D658DB90066232A /* ErrorWindowController.xib */; };
|
||||||
7D17C5041D658DEC0066232A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5021D658DEC0066232A /* MainMenu.xib */; };
|
7D17C5041D658DEC0066232A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D17C5021D658DEC0066232A /* MainMenu.xib */; };
|
||||||
7D6245831D87C3D700870565 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D6245821D87C3D700870565 /* Images.xcassets */; };
|
7D6245831D87C3D700870565 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D6245821D87C3D700870565 /* Images.xcassets */; };
|
||||||
|
7DEABC481E907DF10024C6AB /* objectiveSee.png in Resources */ = {isa = PBXBuildFile; fileRef = 7DEABC471E907DF10024C6AB /* objectiveSee.png */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
@ -54,6 +55,7 @@
|
||||||
7D24C8651D2CDEA7009932EE /* OverSight_Installer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OverSight_Installer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
7D24C8651D2CDEA7009932EE /* OverSight_Installer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OverSight_Installer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7D6245821D87C3D700870565 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
|
7D6245821D87C3D700870565 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
|
||||||
7D9A7DE91D8A8BDA0091C1AF /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = Installer/main.h; sourceTree = SOURCE_ROOT; };
|
7D9A7DE91D8A8BDA0091C1AF /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = Installer/main.h; sourceTree = SOURCE_ROOT; };
|
||||||
|
7DEABC471E907DF10024C6AB /* objectiveSee.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = objectiveSee.png; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -90,6 +92,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7D17C4DF1D658D9F0066232A /* icon.png */,
|
7D17C4DF1D658D9F0066232A /* icon.png */,
|
||||||
|
7DEABC471E907DF10024C6AB /* objectiveSee.png */,
|
||||||
7D17C4E01D658D9F0066232A /* overSight.png */,
|
7D17C4E01D658D9F0066232A /* overSight.png */,
|
||||||
);
|
);
|
||||||
path = Images;
|
path = Images;
|
||||||
|
@ -118,11 +121,11 @@
|
||||||
7D17C5021D658DEC0066232A /* MainMenu.xib */,
|
7D17C5021D658DEC0066232A /* MainMenu.xib */,
|
||||||
7D17C4F61D658DB90066232A /* AppDelegate.h */,
|
7D17C4F61D658DB90066232A /* AppDelegate.h */,
|
||||||
7D17C4ED1D658DB90066232A /* AppDelegate.m */,
|
7D17C4ED1D658DB90066232A /* AppDelegate.m */,
|
||||||
|
7D17C4F11D658DB90066232A /* ConfigureWindowController.h */,
|
||||||
7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */,
|
7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */,
|
||||||
7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */,
|
7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */,
|
||||||
7D17C4F01D658DB90066232A /* Configure.h */,
|
7D17C4F01D658DB90066232A /* Configure.h */,
|
||||||
7D17C4EC1D658DB90066232A /* Configure.m */,
|
7D17C4EC1D658DB90066232A /* Configure.m */,
|
||||||
7D17C4F11D658DB90066232A /* ConfigureWindowController.h */,
|
|
||||||
7D17C4F21D658DB90066232A /* ErrorWindowController.h */,
|
7D17C4F21D658DB90066232A /* ErrorWindowController.h */,
|
||||||
7D17C4F31D658DB90066232A /* ErrorWindowController.m */,
|
7D17C4F31D658DB90066232A /* ErrorWindowController.m */,
|
||||||
7D17C4F81D658DB90066232A /* ErrorWindowController.xib */,
|
7D17C4F81D658DB90066232A /* ErrorWindowController.xib */,
|
||||||
|
@ -204,6 +207,7 @@
|
||||||
7D6245831D87C3D700870565 /* Images.xcassets in Resources */,
|
7D6245831D87C3D700870565 /* Images.xcassets in Resources */,
|
||||||
7D17C4E91D658D9F0066232A /* overSight.png in Resources */,
|
7D17C4E91D658D9F0066232A /* overSight.png in Resources */,
|
||||||
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */,
|
7D17C5011D658DB90066232A /* ErrorWindowController.xib in Resources */,
|
||||||
|
7DEABC481E907DF10024C6AB /* objectiveSee.png in Resources */,
|
||||||
7D17C4E81D658D9F0066232A /* icon.png in Resources */,
|
7D17C4E81D658D9F0066232A /* icon.png in Resources */,
|
||||||
7D17C4FC1D658DB90066232A /* ConfigureWindowController.xib in Resources */,
|
7D17C4FC1D658DB90066232A /* ConfigureWindowController.xib in Resources */,
|
||||||
7D17C4E51D658D9F0066232A /* AboutWindow.xib in Resources */,
|
7D17C4E51D658D9F0066232A /* AboutWindow.xib in Resources */,
|
||||||
|
|
|
@ -27,14 +27,18 @@
|
||||||
if(ACTION_INSTALL_FLAG == parameter)
|
if(ACTION_INSTALL_FLAG == parameter)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"installing...");
|
logMsg(LOG_DEBUG, @"installing...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//if already installed though
|
//if already installed though
|
||||||
// ->uninstall everything first
|
// ->uninstall everything first
|
||||||
if(YES == [self isInstalled])
|
if(YES == [self isInstalled])
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"already installed, so stopping/uninstalling...");
|
logMsg(LOG_DEBUG, @"already installed, so stopping/uninstalling...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//stop
|
//stop
|
||||||
// ->kill login item/XPC service
|
// ->kill login item/XPC service
|
||||||
|
@ -49,7 +53,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"uninstalled");
|
logMsg(LOG_DEBUG, @"uninstalled");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//install
|
//install
|
||||||
|
@ -63,8 +69,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"installed, now will start");
|
logMsg(LOG_DEBUG, @"installed, now will start");
|
||||||
|
#endif
|
||||||
|
|
||||||
//start login item
|
//start login item
|
||||||
if(YES != [self start])
|
if(YES != [self start])
|
||||||
{
|
{
|
||||||
|
@ -80,14 +88,18 @@
|
||||||
else if(ACTION_UNINSTALL_FLAG == parameter)
|
else if(ACTION_UNINSTALL_FLAG == parameter)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"stopping login item");
|
logMsg(LOG_DEBUG, @"stopping login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//stop
|
//stop
|
||||||
// ->kill login item/XPC service
|
// ->kill login item/XPC service
|
||||||
[self stop];
|
[self stop];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"uninstalling...");
|
logMsg(LOG_DEBUG, @"uninstalling...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//uninstall
|
//uninstall
|
||||||
if(YES != [self uninstall:UNINSTALL_FULL])
|
if(YES != [self uninstall:UNINSTALL_FULL])
|
||||||
|
@ -97,7 +109,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"uninstalled!");
|
logMsg(LOG_DEBUG, @"uninstalled!");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//no errors
|
//no errors
|
||||||
|
@ -161,14 +175,18 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"copied %@ -> %@", appPathSrc, appPathDest]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"copied %@ -> %@", appPathSrc, appPathDest]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//remove xattrs
|
//remove xattrs
|
||||||
// ->otherwise app translocation causes issues
|
// ->otherwise app translocation causes issues
|
||||||
execTask(XATTR, @[@"-cr", appPathDest]);
|
execTask(XATTR, @[@"-cr", appPathDest]);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"removed xattrz");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"removed xattr");
|
||||||
|
#endif
|
||||||
|
|
||||||
//init path to login item
|
//init path to login item
|
||||||
loginItem = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
loginItem = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
||||||
|
@ -189,7 +207,9 @@ bail:
|
||||||
execTask(SUDO, @[@"-u", user, loginItem, [NSString stringWithUTF8String:CMD_INSTALL]]);
|
execTask(SUDO, @[@"-u", user, loginItem, [NSString stringWithUTF8String:CMD_INSTALL]]);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"persisted %@", loginItem]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"persisted %@", loginItem]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//init path to XPC service
|
//init path to XPC service
|
||||||
xpcServicePath = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/XPCServices/OverSightXPC.xpc"];
|
xpcServicePath = [appPathDest stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/XPCServices/OverSightXPC.xpc"];
|
||||||
|
@ -306,7 +326,9 @@ bail:
|
||||||
installedAppPath = [APPS_FOLDER stringByAppendingPathComponent:APP_NAME];
|
installedAppPath = [APPS_FOLDER stringByAppendingPathComponent:APP_NAME];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"uninstalling login item");
|
logMsg(LOG_DEBUG, @"uninstalling login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//get user
|
//get user
|
||||||
user = loggedinUser();
|
user = loggedinUser();
|
||||||
|
@ -325,18 +347,24 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"telling login item %@, to uninstall itself", loginItem]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"telling login item %@, to uninstall itself", loginItem]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//call into login item to uninstall itself
|
//call into login item to uninstall itself
|
||||||
// ->runs as logged in user, so can access user's login items, etc
|
// ->runs as logged in user, so can access user's login items, etc
|
||||||
execTask(SUDO, @[@"-u", user, loginItem, [NSString stringWithUTF8String:CMD_UNINSTALL]]);
|
execTask(SUDO, @[@"-u", user, loginItem, [NSString stringWithUTF8String:CMD_UNINSTALL]]);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"unpersisted %@", loginItem]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"unpersisted %@", loginItem]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"deleting app");
|
logMsg(LOG_DEBUG, @"deleting app");
|
||||||
|
#endif
|
||||||
|
|
||||||
//delete folder
|
//delete folder
|
||||||
if(YES != [[NSFileManager defaultManager] removeItemAtPath:installedAppPath error:&error])
|
if(YES != [[NSFileManager defaultManager] removeItemAtPath:installedAppPath error:&error])
|
||||||
|
@ -355,7 +383,9 @@ bail:
|
||||||
if(UNINSTALL_FULL == type)
|
if(UNINSTALL_FULL == type)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"full, so also deleting app support directory");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"full uninstall, so also deleting app support directory");
|
||||||
|
#endif
|
||||||
|
|
||||||
//delete app support folder
|
//delete app support folder
|
||||||
if(YES == [[NSFileManager defaultManager] fileExistsAtPath:[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]])
|
if(YES == [[NSFileManager defaultManager] fileExistsAtPath:[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]])
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
@property (weak) IBOutlet NSButton *installButton;
|
@property (weak) IBOutlet NSButton *installButton;
|
||||||
@property (weak) IBOutlet NSButton *uninstallButton;
|
@property (weak) IBOutlet NSButton *uninstallButton;
|
||||||
@property (weak) IBOutlet NSButton *moreInfoButton;
|
@property (weak) IBOutlet NSButton *moreInfoButton;
|
||||||
|
@property (weak) IBOutlet NSButton *supportButton;
|
||||||
|
@property (strong) IBOutlet NSView *supportView;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#import "Utilities.h"
|
#import "Utilities.h"
|
||||||
#import "ConfigureWindowController.h"
|
#import "ConfigureWindowController.h"
|
||||||
|
|
||||||
|
#import <Quartz/Quartz.h>
|
||||||
|
|
||||||
@implementation ConfigureWindowController
|
@implementation ConfigureWindowController
|
||||||
|
|
||||||
@synthesize statusMsg;
|
@synthesize statusMsg;
|
||||||
|
@ -110,20 +112,87 @@
|
||||||
NSUInteger action = 0;
|
NSUInteger action = 0;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling action click: %@", buttonTitle]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling action click: %@", buttonTitle]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//close?
|
//close/no?
|
||||||
// ->just exit
|
// ->just exit
|
||||||
if(YES == [buttonTitle isEqualToString:ACTION_CLOSE])
|
if( (YES == [buttonTitle isEqualToString:ACTION_CLOSE]) ||
|
||||||
|
(YES == [buttonTitle isEqualToString:ACTION_NO]) )
|
||||||
{
|
{
|
||||||
//close
|
//close
|
||||||
[self.window close];
|
[self.window close];
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
//next >>?
|
||||||
|
// ->show 'support' us view
|
||||||
|
if(YES == [buttonTitle isEqualToString:ACTION_NEXT])
|
||||||
|
{
|
||||||
|
//frame
|
||||||
|
NSRect frame = {0};
|
||||||
|
|
||||||
|
//unset window title
|
||||||
|
self.window.title = @"";
|
||||||
|
|
||||||
|
//get main window's frame
|
||||||
|
frame = self.window.contentView.frame;
|
||||||
|
|
||||||
|
//set origin to 0/0
|
||||||
|
frame.origin = CGPointZero;
|
||||||
|
|
||||||
|
//increase y offset
|
||||||
|
frame.origin.y += 5;
|
||||||
|
|
||||||
|
//reduce height
|
||||||
|
frame.size.height -= 5;
|
||||||
|
|
||||||
|
//pre-req
|
||||||
|
[self.supportView setWantsLayer:YES];
|
||||||
|
|
||||||
|
//update overlay to take up entire window
|
||||||
|
self.supportView.frame = frame;
|
||||||
|
|
||||||
|
//set overlay's view color to white
|
||||||
|
self.supportView.layer.backgroundColor = [NSColor whiteColor].CGColor;
|
||||||
|
|
||||||
|
//nap for UI purposes
|
||||||
|
[NSThread sleepForTimeInterval:0.10f];
|
||||||
|
|
||||||
|
//add to main window
|
||||||
|
[self.window.contentView addSubview:self.supportView];
|
||||||
|
|
||||||
|
//show
|
||||||
|
self.supportView.hidden = NO;
|
||||||
|
|
||||||
|
//make 'yes!' button active
|
||||||
|
[self.window makeFirstResponder:self.supportButton];
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
//'yes' for support
|
||||||
|
// ->load supprt in URL
|
||||||
|
if(YES == [buttonTitle isEqualToString:ACTION_YES])
|
||||||
|
{
|
||||||
|
//open URL
|
||||||
|
// ->invokes user's default browser
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PATREON_URL]];
|
||||||
|
|
||||||
|
//close
|
||||||
|
[self.window close];
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//install/uninstall logic handlers
|
//install/uninstall logic handlers
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
//hide 'get more info' button
|
//hide 'get more info' button
|
||||||
self.moreInfoButton.hidden = YES;
|
self.moreInfoButton.hidden = YES;
|
||||||
|
|
||||||
|
@ -159,9 +228,11 @@
|
||||||
^{
|
^{
|
||||||
//install/uninstall
|
//install/uninstall
|
||||||
[self lifeCycleEvent:action];
|
[self lifeCycleEvent:action];
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//bail
|
||||||
|
bail:
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -193,9 +264,6 @@
|
||||||
//configure object
|
//configure object
|
||||||
Configure* configureObj = nil;
|
Configure* configureObj = nil;
|
||||||
|
|
||||||
//dbg msg
|
|
||||||
//logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling life cycle event, %lu", (unsigned long)event]);
|
|
||||||
|
|
||||||
//alloc control object
|
//alloc control object
|
||||||
configureObj = [[Configure alloc] init];
|
configureObj = [[Configure alloc] init];
|
||||||
|
|
||||||
|
@ -351,11 +419,11 @@
|
||||||
[self.statusMsg setStringValue:resultMsg];
|
[self.statusMsg setStringValue:resultMsg];
|
||||||
|
|
||||||
//update button
|
//update button
|
||||||
// ->after install change butter to 'close'
|
// ->after install change butter to 'next'
|
||||||
if(ACTION_INSTALL_FLAG == event)
|
if(ACTION_INSTALL_FLAG == event)
|
||||||
{
|
{
|
||||||
//set button title to 'close'
|
//set button title to 'close'
|
||||||
self.installButton.title = ACTION_CLOSE;
|
self.installButton.title = ACTION_NEXT;
|
||||||
|
|
||||||
//enable
|
//enable
|
||||||
self.installButton.enabled = YES;
|
self.installButton.enabled = YES;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="ConfigureWindowController">
|
<customObject id="-2" userLabel="File's Owner" customClass="ConfigureWindowController">
|
||||||
|
@ -10,6 +11,8 @@
|
||||||
<outlet property="installButton" destination="553-2y-kvm" id="nxf-wO-EI3"/>
|
<outlet property="installButton" destination="553-2y-kvm" id="nxf-wO-EI3"/>
|
||||||
<outlet property="moreInfoButton" destination="QWu-qZ-Za2" id="8kC-Ga-5oJ"/>
|
<outlet property="moreInfoButton" destination="QWu-qZ-Za2" id="8kC-Ga-5oJ"/>
|
||||||
<outlet property="statusMsg" destination="SpB-Xc-WlB" id="jlm-ke-XfM"/>
|
<outlet property="statusMsg" destination="SpB-Xc-WlB" id="jlm-ke-XfM"/>
|
||||||
|
<outlet property="supportButton" destination="P9c-Mi-M5f" id="Lxc-8L-j9l"/>
|
||||||
|
<outlet property="supportView" destination="vCr-3l-dVw" id="gO5-OQ-h7d"/>
|
||||||
<outlet property="uninstallButton" destination="XrB-7g-xya" id="0Hc-Xn-STu"/>
|
<outlet property="uninstallButton" destination="XrB-7g-xya" id="0Hc-Xn-STu"/>
|
||||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
@ -20,16 +23,18 @@
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="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="contentRect" x="196" y="240" width="460" height="176"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1058"/>
|
||||||
<view key="contentView" id="se5-gp-TjO">
|
<view key="contentView" id="se5-gp-TjO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
|
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<progressIndicator hidden="YES" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="b1w-5W-ayX">
|
<progressIndicator hidden="YES" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="b1w-5W-ayX">
|
||||||
<rect key="frame" x="144" y="31" width="32" height="32"/>
|
<rect key="frame" x="144" y="31" width="32" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
</progressIndicator>
|
</progressIndicator>
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XrB-7g-xya">
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XrB-7g-xya">
|
||||||
<rect key="frame" x="138" y="76" width="115" height="32"/>
|
<rect key="frame" x="138" y="76" width="115" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="push" title="Uninstall" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="G7H-Q1-04P">
|
<buttonCell key="cell" type="push" title="Uninstall" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="G7H-Q1-04P">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" size="13" name="Menlo-Regular"/>
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
|
@ -40,10 +45,12 @@
|
||||||
</button>
|
</button>
|
||||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fgM-lv-GeJ">
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fgM-lv-GeJ">
|
||||||
<rect key="frame" x="13" y="43" width="114" height="123"/>
|
<rect key="frame" x="13" y="43" width="114" height="123"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="bCU-0f-ff8"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="bCU-0f-ff8"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="293" translatesAutoresizingMaskIntoConstraints="NO" id="SpB-Xc-WlB">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="293" translatesAutoresizingMaskIntoConstraints="NO" id="SpB-Xc-WlB">
|
||||||
<rect key="frame" x="144" y="11" width="293" height="47"/>
|
<rect key="frame" x="144" y="11" width="293" height="47"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" truncatesLastVisibleLine="YES" enabled="NO" sendsActionOnEndEditing="YES" alignment="center" id="Rib-WU-Syl">
|
<textFieldCell key="cell" truncatesLastVisibleLine="YES" enabled="NO" sendsActionOnEndEditing="YES" alignment="center" id="Rib-WU-Syl">
|
||||||
<font key="font" size="13" name="Menlo-Regular"/>
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -52,6 +59,7 @@
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="553-2y-kvm">
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="553-2y-kvm">
|
||||||
<rect key="frame" x="331" y="76" width="115" height="32"/>
|
<rect key="frame" x="331" y="76" width="115" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="push" title="Install" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="1hy-8F-qxt">
|
<buttonCell key="cell" type="push" title="Install" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="1hy-8F-qxt">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" size="13" name="Menlo-Regular"/>
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
|
@ -62,10 +70,12 @@
|
||||||
</button>
|
</button>
|
||||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K52-9g-sjn">
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="K52-9g-sjn">
|
||||||
<rect key="frame" x="138" y="109" width="243" height="67"/>
|
<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="overSight" id="WRg-I2-vkK"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="overSight" id="WRg-I2-vkK"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<button hidden="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QWu-qZ-Za2">
|
<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"/>
|
<rect key="frame" x="414" y="33" width="25" height="25"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="v1Z-aX-Wlm">
|
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="v1Z-aX-Wlm">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
|
@ -82,9 +92,53 @@
|
||||||
</connections>
|
</connections>
|
||||||
<point key="canvasLocation" x="185" y="-256"/>
|
<point key="canvasLocation" x="185" y="-256"/>
|
||||||
</window>
|
</window>
|
||||||
|
<customView id="vCr-3l-dVw" userLabel="Support">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PrA-cn-uEb">
|
||||||
|
<rect key="frame" x="0.0" y="73" width="460" height="95"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="objectiveSee" id="R16-ui-bGJ"/>
|
||||||
|
</imageView>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nMV-BX-h3q" userLabel="No">
|
||||||
|
<rect key="frame" x="216" y="13" width="115" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="push" title="no" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="mxu-rh-2Cj">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="buttonHandler:" target="-2" id="AbE-9d-JcC"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="P9c-Mi-M5f" userLabel="Yes">
|
||||||
|
<rect key="frame" x="331" y="13" width="115" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="push" title="yes!" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="TKT-GO-QZ5">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="buttonHandler:" target="-2" id="M6h-5G-Cp2"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tlG-7V-dhI">
|
||||||
|
<rect key="frame" x="144" y="60" width="306" height="25"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="support our free tools?" id="ojw-4b-aZW">
|
||||||
|
<font key="font" size="17" name="Menlo-Bold"/>
|
||||||
|
<color key="textColor" white="0.25" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
</subviews>
|
||||||
|
<point key="canvasLocation" x="785" y="-256"/>
|
||||||
|
</customView>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="icon" width="512" height="512"/>
|
<image name="icon" width="512" height="512"/>
|
||||||
|
<image name="objectiveSee" width="943" height="236"/>
|
||||||
<image name="overSight" width="1396" height="286"/>
|
<image name="overSight" width="1396" height="286"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "Consts.h"
|
#import "Consts.h"
|
||||||
|
#import "Logging.h"
|
||||||
#import "ErrorWindowController.h"
|
#import "ErrorWindowController.h"
|
||||||
|
|
||||||
@interface ErrorWindowController ()
|
@interface ErrorWindowController ()
|
||||||
|
@ -138,7 +139,9 @@
|
||||||
if(YES == self.shouldExit)
|
if(YES == self.shouldExit)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
//logMsg(LOG_DEBUG, @"exiting application");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"exiting application");
|
||||||
|
#endif
|
||||||
|
|
||||||
//exit
|
//exit
|
||||||
[NSApp terminate:self];
|
[NSApp terminate:self];
|
||||||
|
|
|
@ -82,7 +82,9 @@ int main(int argc, const char * argv[])
|
||||||
if(0 != geteuid())
|
if(0 != geteuid())
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"non-root installer instance");
|
logMsg(LOG_DEBUG, @"non-root installer instance");
|
||||||
|
#endif
|
||||||
|
|
||||||
//spawn as root
|
//spawn as root
|
||||||
if(YES != spawnAsRoot(argv[0]))
|
if(YES != spawnAsRoot(argv[0]))
|
||||||
|
@ -103,7 +105,9 @@ int main(int argc, const char * argv[])
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"root installer instance");
|
logMsg(LOG_DEBUG, @"root installer instance");
|
||||||
|
#endif
|
||||||
|
|
||||||
//app away
|
//app away
|
||||||
retVar = NSApplicationMain(argc, (const char **)argv);
|
retVar = NSApplicationMain(argc, (const char **)argv);
|
||||||
|
|
|
@ -43,12 +43,6 @@
|
||||||
//flag indicating video (camera) is active
|
//flag indicating video (camera) is active
|
||||||
@property BOOL videoActive;
|
@property BOOL videoActive;
|
||||||
|
|
||||||
//flag indicating an audio active alert was shown
|
|
||||||
@property BOOL showAudioDeactivation;
|
|
||||||
|
|
||||||
//flag indicating a video active alert was shown
|
|
||||||
@property BOOL showVideoDeactivation;
|
|
||||||
|
|
||||||
//monitor thread
|
//monitor thread
|
||||||
@property(nonatomic, retain)NSThread* videoMonitorThread;
|
@property(nonatomic, retain)NSThread* videoMonitorThread;
|
||||||
|
|
||||||
|
@ -64,6 +58,9 @@
|
||||||
//whitelisted procs
|
//whitelisted procs
|
||||||
@property(nonatomic, retain)NSMutableArray* whiteList;
|
@property(nonatomic, retain)NSMutableArray* whiteList;
|
||||||
|
|
||||||
|
//activation alerts that were displayed
|
||||||
|
@property(nonatomic, retain)NSMutableDictionary* activationAlerts;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
|
@ -21,14 +21,11 @@
|
||||||
@synthesize lastEvent;
|
@synthesize lastEvent;
|
||||||
@synthesize whiteList;
|
@synthesize whiteList;
|
||||||
@synthesize audioActive;
|
@synthesize audioActive;
|
||||||
|
@synthesize activationAlerts;
|
||||||
@synthesize lastNotification;
|
@synthesize lastNotification;
|
||||||
@synthesize videoMonitorThread;
|
@synthesize videoMonitorThread;
|
||||||
@synthesize showAudioDeactivation;
|
|
||||||
@synthesize showVideoDeactivation;
|
|
||||||
@synthesize rememberWindowController;
|
@synthesize rememberWindowController;
|
||||||
|
|
||||||
//TODO: fix hang!!
|
|
||||||
|
|
||||||
//init
|
//init
|
||||||
-(id)init
|
-(id)init
|
||||||
{
|
{
|
||||||
|
@ -36,6 +33,9 @@
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if(nil != self)
|
if(nil != self)
|
||||||
{
|
{
|
||||||
|
//alloc
|
||||||
|
activationAlerts = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
//load whitelist
|
//load whitelist
|
||||||
[self loadWhitelist];
|
[self loadWhitelist];
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,9 @@
|
||||||
path = [[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath] stringByAppendingPathComponent:FILE_WHITELIST];
|
path = [[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath] stringByAppendingPathComponent:FILE_WHITELIST];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"loading whitelist %@", path]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"loading whitelist %@", path]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//since file is created by priv'd XPC, it shouldn't be writeable
|
//since file is created by priv'd XPC, it shouldn't be writeable
|
||||||
// ...unless somebody maliciously creates it, so we check if that here
|
// ...unless somebody maliciously creates it, so we check if that here
|
||||||
|
@ -70,7 +72,9 @@
|
||||||
self.whiteList = [NSMutableArray arrayWithContentsOfFile:path];
|
self.whiteList = [NSMutableArray arrayWithContentsOfFile:path];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"whitelist: %@", self.whiteList]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"whitelist: %@", self.whiteList]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
@ -89,7 +93,9 @@ bail:
|
||||||
cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"cameras: %@", cameras]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"cameras: %@", cameras]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//look for camera that belongs to apple
|
//look for camera that belongs to apple
|
||||||
for(AVCaptureDevice* currentCamera in cameras)
|
for(AVCaptureDevice* currentCamera in cameras)
|
||||||
|
@ -113,7 +119,9 @@ bail:
|
||||||
self.camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
self.camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"didn't find apple camera, grabbed default: %@", self.camera]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"didn't find apple camera, grabbed default: %@", self.camera]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +138,9 @@ bail:
|
||||||
mics = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
|
mics = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"mics: %@", mics]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"mics: %@", mics]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//look for mic that belongs to apple
|
//look for mic that belongs to apple
|
||||||
for(AVCaptureDevice* currentMic in mics)
|
for(AVCaptureDevice* currentMic in mics)
|
||||||
|
@ -156,7 +166,9 @@ bail:
|
||||||
self.mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
|
self.mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"didn't find apple 'imic', grabbed default: %@", self.mic]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"didn't find apple 'imic', grabbed default: %@", self.mic]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -199,7 +211,9 @@ bail:
|
||||||
[xpcConnection resume];
|
[xpcConnection resume];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"telling XPC service to begin base-lining mach messages");
|
logMsg(LOG_DEBUG, @"telling XPC service to begin base-lining mach messages");
|
||||||
|
#endif
|
||||||
|
|
||||||
//init wait semaphore
|
//init wait semaphore
|
||||||
waitSema = dispatch_semaphore_create(0);
|
waitSema = dispatch_semaphore_create(0);
|
||||||
|
@ -253,14 +267,15 @@ bail:
|
||||||
if(YES == self.videoActive)
|
if(YES == self.videoActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"video already active, so will start polling for new video procs");
|
logMsg(LOG_DEBUG, @"video already active, so will start polling for new video procs");
|
||||||
|
#endif
|
||||||
|
|
||||||
//tell XPC video is active
|
//tell XPC video is active
|
||||||
[[xpcConnection remoteObjectProxy] updateVideoStatus:self.videoActive reply:^{
|
[[xpcConnection remoteObjectProxy] updateVideoStatus:self.videoActive reply:^{
|
||||||
|
|
||||||
//signal sema
|
//signal sema
|
||||||
dispatch_semaphore_signal(waitSema);
|
dispatch_semaphore_signal(waitSema);
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
//wait until XPC is done
|
//wait until XPC is done
|
||||||
|
@ -281,7 +296,9 @@ bail:
|
||||||
if(YES != [self watchVideo:connectionID])
|
if(YES != [self watchVideo:connectionID])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"failed to watch for video events");
|
logMsg(LOG_DEBUG, @"failed to watch for video events");
|
||||||
|
#endif
|
||||||
|
|
||||||
//set err
|
//set err
|
||||||
wasErrors = YES;
|
wasErrors = YES;
|
||||||
|
@ -322,11 +339,13 @@ bail:
|
||||||
|
|
||||||
//if audio is already active
|
//if audio is already active
|
||||||
// ->tell XPC that it's active
|
// ->tell XPC that it's active
|
||||||
// TODO: monitor for hijacking?
|
// TODO: monitor for piggybacking?
|
||||||
if(YES == self.audioActive)
|
if(YES == self.audioActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"audio already active");//so will start polling for new video procs");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"audio already active");
|
||||||
|
#endif
|
||||||
|
|
||||||
//tell XPC audio is active
|
//tell XPC audio is active
|
||||||
[[xpcConnection remoteObjectProxy] updateAudioStatus:self.audioActive reply:^{
|
[[xpcConnection remoteObjectProxy] updateAudioStatus:self.audioActive reply:^{
|
||||||
|
@ -348,7 +367,9 @@ bail:
|
||||||
if(YES != [self watchAudio:connectionID])
|
if(YES != [self watchAudio:connectionID])
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"failed to watch for audio events");
|
logMsg(LOG_DEBUG, @"failed to watch for audio events");
|
||||||
|
#endif
|
||||||
|
|
||||||
//set err
|
//set err
|
||||||
wasErrors = YES;
|
wasErrors = YES;
|
||||||
|
@ -495,7 +516,9 @@ bail:
|
||||||
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.videoActive];
|
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.videoActive];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got video change notification; is running? %x", self.videoActive]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got video change notification; is running? %x", self.videoActive]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//alloc XPC connection
|
//alloc XPC connection
|
||||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||||
|
@ -518,7 +541,6 @@ bail:
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
//TODO: maybe add timeout here?
|
|
||||||
//wait until XPC is done
|
//wait until XPC is done
|
||||||
// ->XPC reply block will signal semaphore
|
// ->XPC reply block will signal semaphore
|
||||||
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER);
|
||||||
|
@ -528,7 +550,9 @@ bail:
|
||||||
if(YES == self.videoActive)
|
if(YES == self.videoActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"video is active, so querying XPC to get video process(s)");
|
logMsg(LOG_DEBUG, @"video is active, so querying XPC to get video process(s)");
|
||||||
|
#endif
|
||||||
|
|
||||||
//set allowed classes
|
//set allowed classes
|
||||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||||
|
@ -544,7 +568,9 @@ bail:
|
||||||
xpcConnection = nil;
|
xpcConnection = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"video procs from XPC: %@", videoProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"video procs from XPC: %@", videoProcesses]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//generate notification for each process
|
//generate notification for each process
|
||||||
for(NSNumber* processID in videoProcesses)
|
for(NSNumber* processID in videoProcesses)
|
||||||
|
@ -599,7 +625,9 @@ bail:
|
||||||
if(YES != videoMonitorThread.isExecuting)
|
if(YES != videoMonitorThread.isExecuting)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"(re)Starting polling/monitor thread");
|
logMsg(LOG_DEBUG, @"(re)Starting polling/monitor thread");
|
||||||
|
#endif
|
||||||
|
|
||||||
//alloc
|
//alloc
|
||||||
videoMonitorThread = [[NSThread alloc] initWithTarget:self selector:@selector(monitor4Procs) object:nil];
|
videoMonitorThread = [[NSThread alloc] initWithTarget:self selector:@selector(monitor4Procs) object:nil];
|
||||||
|
@ -611,7 +639,9 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"polling/monitor thread still running");
|
logMsg(LOG_DEBUG, @"polling/monitor thread still running");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,7 +681,6 @@ bail:
|
||||||
{
|
{
|
||||||
//invoke helper function
|
//invoke helper function
|
||||||
[self handleVideoNotification:deviceID addresses:addresses];
|
[self handleVideoNotification:deviceID addresses:addresses];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//register (add) property block listener
|
//register (add) property block listener
|
||||||
|
@ -751,7 +780,9 @@ bail:
|
||||||
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.audioActive];
|
event[EVENT_DEVICE_STATUS] = [NSNumber numberWithInt:self.audioActive];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got audio change notification; is running? %x", self.audioActive]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got audio change notification; is running? %x", self.audioActive]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//alloc XPC connection
|
//alloc XPC connection
|
||||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||||
|
@ -783,7 +814,9 @@ bail:
|
||||||
if(YES == self.audioActive)
|
if(YES == self.audioActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"audio is active, so querying XPC to get audio process(s)");
|
logMsg(LOG_DEBUG, @"audio is active, so querying XPC to get audio process(s)");
|
||||||
|
#endif
|
||||||
|
|
||||||
//set allowed classes
|
//set allowed classes
|
||||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||||
|
@ -799,7 +832,9 @@ bail:
|
||||||
xpcConnection = nil;
|
xpcConnection = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"audio procs from XPC: %@", audioProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"audio procs from XPC: %@", audioProcesses]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//generate notification for each process
|
//generate notification for each process
|
||||||
for(NSNumber* processID in audioProcesses)
|
for(NSNumber* processID in audioProcesses)
|
||||||
|
@ -933,6 +968,9 @@ bail:
|
||||||
//preferences
|
//preferences
|
||||||
NSDictionary* preferences = nil;
|
NSDictionary* preferences = nil;
|
||||||
|
|
||||||
|
//flag
|
||||||
|
BOOL matchingActivationAlert = NO;
|
||||||
|
|
||||||
//alloc notificaiton
|
//alloc notificaiton
|
||||||
notification = [[NSUserNotification alloc] init];
|
notification = [[NSUserNotification alloc] init];
|
||||||
|
|
||||||
|
@ -943,7 +981,9 @@ bail:
|
||||||
sysLogMsg = [NSMutableString string];
|
sysLogMsg = [NSMutableString string];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"generating notification for %@", event]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"generating notification for %@", event]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//get process name
|
//get process name
|
||||||
processName = getProcessName([event[EVENT_PROCESS_ID] intValue]);
|
processName = getProcessName([event[EVENT_PROCESS_ID] intValue]);
|
||||||
|
@ -982,7 +1022,9 @@ bail:
|
||||||
(YES == [self.whiteList containsObject:processPath]) )
|
(YES == [self.whiteList containsObject:processPath]) )
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"activation alert for process %@ is whitelisted, so ignoring", processPath]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"activation alert for process %@ is whitelisted, so ignoring", processPath]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -991,30 +1033,33 @@ bail:
|
||||||
// ->for deactivation, ignore when no activation alert was shown (cuz process will have likely died, so no pid/path, etc)
|
// ->for deactivation, ignore when no activation alert was shown (cuz process will have likely died, so no pid/path, etc)
|
||||||
if(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
if(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
||||||
{
|
{
|
||||||
//ignore audio inactive event, if no active event was shown
|
//any active alerts?
|
||||||
if( (SOURCE_AUDIO.intValue == deviceType.intValue) &&
|
// ->note: we make to check if the type matches
|
||||||
(YES != self.showAudioDeactivation) )
|
for(NSUUID* key in self.activationAlerts.allKeys)
|
||||||
|
{
|
||||||
|
//same type?
|
||||||
|
if(event[EVENT_DEVICE] == self.activationAlerts[key][EVENT_DEVICE])
|
||||||
|
{
|
||||||
|
//got match
|
||||||
|
matchingActivationAlert = YES;
|
||||||
|
|
||||||
|
//no need to check more
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//no match?
|
||||||
|
// ->bail, as means process was whitelisted so no activation was shown
|
||||||
|
if(YES != matchingActivationAlert)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"deactivation audio alert doesn't have an activation alert (whitelisted?), so ignoring");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"deactivation alert doesn't have an activation alert (whitelisted?), so ignoring");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ignore video inactive event, if no active event was shown
|
|
||||||
if( (SOURCE_VIDEO.intValue == deviceType.intValue) &&
|
|
||||||
(YES != self.showVideoDeactivation) )
|
|
||||||
{
|
|
||||||
//dbg msg
|
|
||||||
logMsg(LOG_DEBUG, @"deactivation video alert doesn't have an activation alert (whitelisted?), so ignoring");
|
|
||||||
|
|
||||||
//bail
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
//dbg msg
|
|
||||||
logMsg(LOG_DEBUG, @"got deactivation alert, but neither showVideoDeactivation nor showVideoDeactivation is set...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if event is essentially a duplicate (facetime, etc)
|
//check if event is essentially a duplicate (facetime, etc)
|
||||||
|
@ -1029,7 +1074,9 @@ bail:
|
||||||
(YES == [self.lastEvent[EVENT_DEVICE_STATUS] isEqual:event[EVENT_DEVICE_STATUS]]) )
|
(YES == [self.lastEvent[EVENT_DEVICE_STATUS] isEqual:event[EVENT_DEVICE_STATUS]]) )
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"alert for %@ would be same as previous (%@), so ignoring", event, self.lastEvent]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"alert for %@ would be same as previous (%@), so ignoring", event, self.lastEvent]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//update
|
//update
|
||||||
self.lastEvent = event;
|
self.lastEvent = event;
|
||||||
|
@ -1052,7 +1099,9 @@ bail:
|
||||||
(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) )
|
(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) )
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"user has decided to ingore 'inactive' events, so ingoring A/V going to disable state");
|
logMsg(LOG_DEBUG, @"user has decided to ingore 'inactive' events, so ingoring A/V going to disable state");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1077,21 +1126,11 @@ bail:
|
||||||
// ->name of device
|
// ->name of device
|
||||||
details = ((AVCaptureDevice*)event[EVENT_DEVICE]).localizedName;
|
details = ((AVCaptureDevice*)event[EVENT_DEVICE]).localizedName;
|
||||||
|
|
||||||
//customize buttons
|
//ALERT 1:
|
||||||
// ->inactive events, or when consumer proc couldn't be ID'd, just say 'ok'
|
// ->activate alert with lots of info
|
||||||
if( (YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) ||
|
if( (YES == [DEVICE_ACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) &&
|
||||||
(0 == [event[EVENT_PROCESS_ID] intValue]) )
|
(0 != [event[EVENT_PROCESS_ID] intValue]) )
|
||||||
{
|
|
||||||
//set other button title
|
|
||||||
notification.otherButtonTitle = @"ok";
|
|
||||||
|
|
||||||
//remove action button
|
|
||||||
notification.hasActionButton = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
//customize buttons
|
|
||||||
// ->for activated audio/video; allow/block
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
//set other button title
|
//set other button title
|
||||||
notification.otherButtonTitle = @"allow";
|
notification.otherButtonTitle = @"allow";
|
||||||
|
@ -1099,15 +1138,47 @@ bail:
|
||||||
//set action title
|
//set action title
|
||||||
notification.actionButtonTitle = @"block";
|
notification.actionButtonTitle = @"block";
|
||||||
|
|
||||||
|
//remove action button
|
||||||
|
notification.hasActionButton = YES;
|
||||||
|
|
||||||
//set pid/name/device into user info
|
//set pid/name/device into user info
|
||||||
// ->allows code to whitelist proc and/or kill proc (later) if user clicks 'block'
|
// ->allows code to whitelist proc and/or kill proc (later) if user clicks 'block'
|
||||||
notification.userInfo = @{EVENT_PROCESS_ID:event[EVENT_PROCESS_ID], EVENT_PROCESS_PATH:processPath, EVENT_PROCESS_NAME:processName, EVENT_DEVICE:deviceType};
|
notification.userInfo = @{EVENT_PROCESS_ID:event[EVENT_PROCESS_ID], EVENT_PROCESS_PATH:processPath, EVENT_PROCESS_NAME:processName, EVENT_DEVICE:deviceType, EVENT_ALERT_TYPE:ALERT_ACTIVATE};
|
||||||
|
|
||||||
//set details
|
//set details
|
||||||
// ->name of process using it / icon too?
|
// ->name of process using it / icon too?
|
||||||
[notification setInformativeText:[NSString stringWithFormat:@"process: %@ (%@)", processName, event[EVENT_PROCESS_ID]]];
|
[notification setInformativeText:[NSString stringWithFormat:@"process: %@ (%@)", processName, event[EVENT_PROCESS_ID]]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ALERT 2:
|
||||||
|
// ->activate alert, with no process info
|
||||||
|
else if( (YES == [DEVICE_ACTIVE isEqual:event[EVENT_DEVICE_STATUS]]) &&
|
||||||
|
(0 == [event[EVENT_PROCESS_ID] intValue]) )
|
||||||
|
{
|
||||||
|
//set other button title
|
||||||
|
notification.otherButtonTitle = @"ok";
|
||||||
|
|
||||||
|
//remove action button
|
||||||
|
notification.hasActionButton = NO;
|
||||||
|
|
||||||
|
//set type
|
||||||
|
notification.userInfo = @{EVENT_DEVICE:deviceType, EVENT_ALERT_TYPE:ALERT_ACTIVATE};
|
||||||
|
}
|
||||||
|
|
||||||
|
//ALERT 3:
|
||||||
|
// ->inactive alert, with no process info
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//set other button title
|
||||||
|
notification.otherButtonTitle = @"ok";
|
||||||
|
|
||||||
|
//remove action button
|
||||||
|
notification.hasActionButton = NO;
|
||||||
|
|
||||||
|
//set type
|
||||||
|
notification.userInfo = @{EVENT_DEVICE:deviceType, EVENT_ALERT_TYPE:ALERT_INACTIVE};
|
||||||
|
}
|
||||||
|
|
||||||
//log event?
|
//log event?
|
||||||
if(YES == [preferences[PREF_LOG_ACTIVITY] boolValue])
|
if(YES == [preferences[PREF_LOG_ACTIVITY] boolValue])
|
||||||
{
|
{
|
||||||
|
@ -1150,57 +1221,51 @@ bail:
|
||||||
//deliver notification
|
//deliver notification
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||||
|
|
||||||
//set flag saying we showed an 'activated' alert
|
//save displayed activation alerts
|
||||||
// ->allows us to ignore 'inactive' events that had a whitelisted 'activate' event
|
|
||||||
if(YES == [DEVICE_ACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
if(YES == [DEVICE_ACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
||||||
{
|
{
|
||||||
//audio
|
//save
|
||||||
if(SOURCE_AUDIO.intValue == deviceType.intValue)
|
self.activationAlerts[notification.identifier] = event;
|
||||||
{
|
|
||||||
//set
|
|
||||||
self.showAudioDeactivation = YES;
|
|
||||||
}
|
|
||||||
//video
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//set
|
|
||||||
self.showVideoDeactivation = YES;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//inactive alert
|
|
||||||
// ->unset flags
|
//for 'went inactive' notification automatically close
|
||||||
else
|
// ->unless there still is an active alert on the screen
|
||||||
|
if(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
||||||
{
|
{
|
||||||
//audio
|
//any active alerts still visible?
|
||||||
if(SOURCE_AUDIO.intValue == deviceType.intValue)
|
// ->note: we make to check if the type matches
|
||||||
|
for(NSUUID* key in self.activationAlerts.allKeys)
|
||||||
{
|
{
|
||||||
//set
|
//same type?
|
||||||
self.showAudioDeactivation = NO;
|
if(event[EVENT_DEVICE] == self.activationAlerts[key][EVENT_DEVICE])
|
||||||
|
{
|
||||||
|
//got match
|
||||||
|
matchingActivationAlert = YES;
|
||||||
|
|
||||||
|
//no need to check more
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//video
|
|
||||||
else
|
//go match
|
||||||
|
// ->close if not still visible
|
||||||
|
if(YES != matchingActivationAlert)
|
||||||
{
|
{
|
||||||
//set
|
//dbg msg
|
||||||
self.showVideoDeactivation = NO;
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"automatically closing deactivation alert");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//delay, then close
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
//close
|
||||||
|
[NSUserNotificationCenter.defaultUserNotificationCenter removeDeliveredNotification:notification];
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//for 'went inactive' notification
|
|
||||||
// ->automatically close after some time
|
|
||||||
if(YES == [DEVICE_INACTIVE isEqual:event[EVENT_DEVICE_STATUS]])
|
|
||||||
{
|
|
||||||
//dbg msg
|
|
||||||
logMsg(LOG_DEBUG, @"event is 'went inactive', so will automatically close");
|
|
||||||
|
|
||||||
//close after 2 seconds
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
||||||
|
|
||||||
//close
|
|
||||||
[NSUserNotificationCenter.defaultUserNotificationCenter removeDeliveredNotification:notification];
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
|
||||||
|
@ -1223,6 +1288,9 @@ bail:
|
||||||
//process id
|
//process id
|
||||||
NSNumber* processID = nil;
|
NSNumber* processID = nil;
|
||||||
|
|
||||||
|
//device type
|
||||||
|
NSNumber* deviceType = nil;
|
||||||
|
|
||||||
//preferences
|
//preferences
|
||||||
NSDictionary* preferences = nil;
|
NSDictionary* preferences = nil;
|
||||||
|
|
||||||
|
@ -1236,7 +1304,9 @@ bail:
|
||||||
sysLogMsg = [NSMutableString string];
|
sysLogMsg = [NSMutableString string];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"user responded to notification: %@", notification]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"user responded to notification: %@", notification]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//ignore if this notification was already seen
|
//ignore if this notification was already seen
|
||||||
// ->need this logic, since have to determine if 'allow' was invoke indirectly
|
// ->need this logic, since have to determine if 'allow' was invoke indirectly
|
||||||
|
@ -1253,6 +1323,38 @@ bail:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//when it's a deactivation alert
|
||||||
|
// ->remove all activation alerts that match the same type
|
||||||
|
if(ALERT_INACTIVE.intValue == [notification.userInfo[EVENT_ALERT_TYPE] intValue])
|
||||||
|
{
|
||||||
|
//remove any active alerts
|
||||||
|
// ->note: we make to check if the type matches
|
||||||
|
for(NSUUID* key in self.activationAlerts.allKeys)
|
||||||
|
{
|
||||||
|
//check stored activation alert type
|
||||||
|
// ->audio
|
||||||
|
if(YES == [self.activationAlerts[key][EVENT_DEVICE] isKindOfClass:NSClassFromString(@"AVCaptureHALDevice")])
|
||||||
|
{
|
||||||
|
//set device
|
||||||
|
deviceType = SOURCE_AUDIO;
|
||||||
|
}
|
||||||
|
//check stored activation alert type
|
||||||
|
// ->video
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//set device
|
||||||
|
deviceType = SOURCE_VIDEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//same type?
|
||||||
|
if( [notification.userInfo[EVENT_DEVICE] intValue] == deviceType.intValue)
|
||||||
|
{
|
||||||
|
//remove
|
||||||
|
[self.activationAlerts removeObjectForKey:key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//update
|
//update
|
||||||
self.lastNotification = notification.identifier;
|
self.lastNotification = notification.identifier;
|
||||||
|
|
||||||
|
@ -1261,7 +1363,9 @@ bail:
|
||||||
if(YES != notification.hasActionButton)
|
if(YES != notification.hasActionButton)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"popup without an action, no need to do anything");
|
logMsg(LOG_DEBUG, @"popup without an action, no need to do anything");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1291,19 +1395,22 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if user clicked 'allow' via user info (since OS doesn't directly deliver this)
|
//check if user clicked 'allow' via user info (since OS doesn't directly deliver this)
|
||||||
// ->if allow was clicked, show a popup w/ option to rember ('whitelist') the application
|
// ->show a popup w/ option to remember ('whitelist') the application
|
||||||
// don't do this for 'block' since that kills the app, so obv, that'd be bad to always do!
|
// don't do this for 'block' since that kills the app, so obv, that'd be bad to *always* do!
|
||||||
if( (nil != notification.userInfo) &&
|
if(NSUserNotificationActivationTypeAdditionalActionClicked == [notification.userInfo[@"activationType"] integerValue])
|
||||||
(NSUserNotificationActivationTypeAdditionalActionClicked == [notification.userInfo[@"activationType"] integerValue]) )
|
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"user clicked 'allow'");
|
logMsg(LOG_DEBUG, @"user clicked 'allow'");
|
||||||
|
#endif
|
||||||
|
|
||||||
//can't remember process that we didn't find the path for
|
//can't remember process that we didn't find the path for
|
||||||
if(YES == [notification.userInfo[EVENT_PROCESS_PATH] isEqualToString:PROCESS_UNKNOWN])
|
if(YES == [notification.userInfo[EVENT_PROCESS_PATH] isEqualToString:PROCESS_UNKNOWN])
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"don't have a process path, so not displaying whitelisting popup");
|
logMsg(LOG_DEBUG, @"don't have a process path, so not displaying whitelisting popup");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1338,7 +1445,9 @@ bail:
|
||||||
else if(NSUserNotificationActivationTypeActionButtonClicked == notification.activationType)
|
else if(NSUserNotificationActivationTypeActionButtonClicked == notification.activationType)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"user clicked 'block'");
|
logMsg(LOG_DEBUG, @"user clicked 'block'");
|
||||||
|
#endif
|
||||||
|
|
||||||
//extract process id
|
//extract process id
|
||||||
processID = notification.userInfo[EVENT_PROCESS_ID];
|
processID = notification.userInfo[EVENT_PROCESS_ID];
|
||||||
|
@ -1361,7 +1470,9 @@ bail:
|
||||||
[xpcConnection resume];
|
[xpcConnection resume];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"invoking XPC method to kill: %@", processID]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"invoking XPC method to kill: %@", processID]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//invoke XPC method 'killProcess' to terminate
|
//invoke XPC method 'killProcess' to terminate
|
||||||
[[xpcConnection remoteObjectProxy] killProcess:processID reply:^(BOOL wasKilled)
|
[[xpcConnection remoteObjectProxy] killProcess:processID reply:^(BOOL wasKilled)
|
||||||
|
@ -1397,48 +1508,49 @@ bail:
|
||||||
|
|
||||||
//user dictionary
|
//user dictionary
|
||||||
__block NSMutableDictionary* userInfo = nil;
|
__block NSMutableDictionary* userInfo = nil;
|
||||||
|
|
||||||
//only process notifications have 'allow' / 'block'
|
//monitor in background to see if alert was dismissed
|
||||||
if(YES == notification.hasActionButton)
|
// ->invokes normal 'didActivateNotification' callback when alert is dimsissed
|
||||||
{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||||
//monitor in background to see if alert was dismissed
|
^{
|
||||||
// ->invokes normal 'didActivateNotification' callback when alert is dimsissed
|
//monitor all delivered notifications until it goes away
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
do {
|
||||||
^{
|
|
||||||
//monitor all delivered notifications until it goes away
|
//reset
|
||||||
do {
|
notificationStillPresent = NO;
|
||||||
|
|
||||||
//reset
|
//check all delivered notifications
|
||||||
notificationStillPresent = NO;
|
for (NSUserNotification *nox in [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications])
|
||||||
|
{
|
||||||
//check all delivered notifications
|
//check
|
||||||
for (NSUserNotification *nox in [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications])
|
if(YES == [nox.identifier isEqualToString:notification.identifier])
|
||||||
{
|
{
|
||||||
//check
|
//found!
|
||||||
if(YES == [nox.identifier isEqualToString:notification.identifier])
|
notificationStillPresent = YES;
|
||||||
{
|
|
||||||
//found!
|
//exit loop
|
||||||
notificationStillPresent = YES;
|
break;
|
||||||
|
|
||||||
//exit loop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//nap if notification is still there
|
|
||||||
if(YES == notificationStillPresent)
|
//nap if notification is still there
|
||||||
|
if(YES == notificationStillPresent)
|
||||||
|
{
|
||||||
|
//nap
|
||||||
|
[NSThread sleepForTimeInterval:0.25f];
|
||||||
|
}
|
||||||
|
|
||||||
|
//keep monitoring until its gone
|
||||||
|
} while(YES == notificationStillPresent);
|
||||||
|
|
||||||
|
//alert was dismissed
|
||||||
|
// ->invoke 'didActivateNotification' to process if it was an 'allow/block' alert
|
||||||
|
dispatch_async(dispatch_get_main_queue(),
|
||||||
|
^{
|
||||||
|
//add extra info for activation alerts
|
||||||
|
// ->will allow callback to identify we delivered via this mechanism
|
||||||
|
if(YES == notification.hasActionButton)
|
||||||
{
|
{
|
||||||
//nap
|
|
||||||
[NSThread sleepForTimeInterval:0.25f];
|
|
||||||
}
|
|
||||||
|
|
||||||
//keep monitoring until its gone
|
|
||||||
} while(YES == notificationStillPresent);
|
|
||||||
|
|
||||||
//alert was dismissed
|
|
||||||
// ->invoke 'didActivateNotification' to process if it was an 'allow/block' alert
|
|
||||||
dispatch_async(dispatch_get_main_queue(),
|
|
||||||
^{
|
|
||||||
//grab user info dictionary
|
//grab user info dictionary
|
||||||
userInfo = [notification.userInfo mutableCopy];
|
userInfo = [notification.userInfo mutableCopy];
|
||||||
|
|
||||||
|
@ -1447,13 +1559,13 @@ bail:
|
||||||
|
|
||||||
//update
|
//update
|
||||||
notification.userInfo = userInfo;
|
notification.userInfo = userInfo;
|
||||||
|
}
|
||||||
//deliver
|
|
||||||
[self userNotificationCenter:center didActivateNotification:notification];
|
//deliver
|
||||||
});
|
[self userNotificationCenter:center didActivateNotification:notification];
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1468,7 +1580,9 @@ bail:
|
||||||
dispatch_semaphore_t waitSema = nil;
|
dispatch_semaphore_t waitSema = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] video is active, so polling for new procs");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] video is active, so polling for new procs");
|
||||||
|
#endif
|
||||||
|
|
||||||
//alloc XPC connection
|
//alloc XPC connection
|
||||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||||
|
@ -1490,14 +1604,18 @@ bail:
|
||||||
waitSema = dispatch_semaphore_create(0);
|
waitSema = dispatch_semaphore_create(0);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] (re)Asking XPC for (new) video procs");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] (re)Asking XPC for (new) video procs");
|
||||||
|
#endif
|
||||||
|
|
||||||
//invoke XPC service to get (new) video procs
|
//invoke XPC service to get (new) video procs
|
||||||
// ->will generate user notifications for any new processes
|
// ->will generate user notifications for any new processes
|
||||||
[[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses)
|
[[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"[MONITOR THREAD] found %lu new video procs: %@", (unsigned long)videoProcesses.count, videoProcesses]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"[MONITOR THREAD] found %lu new video procs: %@", (unsigned long)videoProcesses.count, videoProcesses]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//generate a notification for each process
|
//generate a notification for each process
|
||||||
// ->double check video is still active though...
|
// ->double check video is still active though...
|
||||||
|
@ -1538,7 +1656,9 @@ bail:
|
||||||
xpcConnection = nil;
|
xpcConnection = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] exiting polling/monitor thread since camera is off");
|
logMsg(LOG_DEBUG, @"[MONITOR THREAD] exiting polling/monitor thread since camera is off");
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
// AppDelegate.m
|
// AppDelegate.m
|
||||||
// Test Application Helper
|
// Login Item, (app helper)
|
||||||
//
|
//
|
||||||
// Created by Patrick Wardle on 9/10/16.
|
// Created by Patrick Wardle on 9/10/16.
|
||||||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||||
|
@ -11,8 +11,6 @@
|
||||||
#import "Utilities.h"
|
#import "Utilities.h"
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
//TODO: "I have a dual monitor setup and just noticed that the alert came up on the other monitor, not the one that Skype was launched on."
|
|
||||||
|
|
||||||
|
|
||||||
@interface AppDelegate ()
|
@interface AppDelegate ()
|
||||||
|
|
||||||
|
@ -33,7 +31,9 @@
|
||||||
NSDictionary* preferences = nil;
|
NSDictionary* preferences = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"starting login item app logic");
|
logMsg(LOG_DEBUG, @"starting login item app logic");
|
||||||
|
#endif
|
||||||
|
|
||||||
//drop group privs
|
//drop group privs
|
||||||
setgid(getgid());
|
setgid(getgid());
|
||||||
|
@ -52,14 +52,18 @@
|
||||||
[self loadStatusBar];
|
[self loadStatusBar];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"initialized/loaded status bar (icon/menu)");
|
logMsg(LOG_DEBUG, @"initialized/loaded status bar (icon/menu)");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
//dbg msg
|
//dbg msg
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"running in headless mode");
|
logMsg(LOG_DEBUG, @"running in headless mode");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//check for updates
|
//check for updates
|
||||||
// ->but only when user has not disabled that feature
|
// ->but only when user has not disabled that feature
|
||||||
|
@ -69,12 +73,13 @@
|
||||||
//->check for updates in background
|
//->check for updates in background
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"checking for update");
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"checking for update");
|
||||||
|
#endif
|
||||||
|
|
||||||
//check
|
//check
|
||||||
[self isThereAnUpdate];
|
[self isThereAnUpdate];
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,14 +87,18 @@
|
||||||
avMonitor = [[AVMonitor alloc] init];
|
avMonitor = [[AVMonitor alloc] init];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"alloc/init'd AV monitor");
|
logMsg(LOG_DEBUG, @"alloc/init'd AV monitor");
|
||||||
|
#endif
|
||||||
|
|
||||||
//start monitoring
|
//start monitoring
|
||||||
// ->sets up audio/video callbacks
|
// ->sets up audio/video callbacks
|
||||||
[avMonitor monitor];
|
[avMonitor monitor];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"AV monitor off and running");
|
logMsg(LOG_DEBUG, @"AV monitor off and running");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
@ -127,7 +136,9 @@ bail:
|
||||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"a new version (%@) is available", versionString]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"a new version (%@) is available", versionString]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//alloc/init about window
|
//alloc/init about window
|
||||||
infoWindowController = [[InfoWindowController alloc] initWithWindowNibName:@"InfoWindow"];
|
infoWindowController = [[InfoWindowController alloc] initWithWindowNibName:@"InfoWindow"];
|
||||||
|
@ -154,11 +165,13 @@ bail:
|
||||||
|
|
||||||
//no new version
|
//no new version
|
||||||
// ->just (debug) log msg
|
// ->just (debug) log msg
|
||||||
|
#ifdef DEBUG
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"no updates available");
|
logMsg(LOG_DEBUG, @"no updates available");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,9 @@
|
||||||
__block NSXPCConnection* xpcConnection = nil;
|
__block NSXPCConnection* xpcConnection = nil;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling user response for 'allow' popup: %ld", (long)((NSButton*)sender).tag]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"handling user response for 'allow' popup: %ld", (long)((NSButton*)sender).tag]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//handle 'always allow' (whitelist) button
|
//handle 'always allow' (whitelist) button
|
||||||
if(BUTTON_ALWAYS_ALLOW == ((NSButton*)sender).tag)
|
if(BUTTON_ALWAYS_ALLOW == ((NSButton*)sender).tag)
|
||||||
|
@ -124,33 +126,37 @@
|
||||||
[xpcConnection resume];
|
[xpcConnection resume];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"sending XPC message to whitelist");
|
logMsg(LOG_DEBUG, @"sending XPC message to whitelist");
|
||||||
|
#endif
|
||||||
|
|
||||||
//invoke XPC method 'whitelistProcess' to add process to white list
|
//invoke XPC method 'whitelistProcess' to add process to white list
|
||||||
[[xpcConnection remoteObjectProxy] whitelistProcess:self.processPath reply:^(BOOL wasWhitelisted)
|
[[xpcConnection remoteObjectProxy] whitelistProcess:self.processPath reply:^(BOOL wasWhitelisted)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got XPC response: %d", wasWhitelisted]);
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got XPC response: %d", wasWhitelisted]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//reload whitelist on success
|
//reload whitelist on success
|
||||||
if(YES == wasWhitelisted)
|
if(YES == wasWhitelisted)
|
||||||
{
|
{
|
||||||
//reload AVMonitor's whitelist
|
//reload AVMonitor's whitelist
|
||||||
[self.avMonitor loadWhitelist];
|
[self.avMonitor loadWhitelist];
|
||||||
}
|
}
|
||||||
//err
|
//err
|
||||||
// ->log msg
|
// ->log msg
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to whitelist: %@", self.processPath]);
|
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to whitelist: %@", self.processPath]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
//nil out
|
||||||
xpcConnection = nil;
|
xpcConnection = nil;
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,9 @@
|
||||||
-(void)quit:(id)sender
|
-(void)quit:(id)sender
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"user clicked 'exit', so goodbye!");
|
logMsg(LOG_DEBUG, @"user clicked 'exit', so goodbye!");
|
||||||
|
#endif
|
||||||
|
|
||||||
//exit
|
//exit
|
||||||
[[NSApplication sharedApplication] terminate:nil];
|
[[NSApplication sharedApplication] terminate:nil];
|
||||||
|
@ -234,7 +236,9 @@
|
||||||
-(void)preferences:(id)sender
|
-(void)preferences:(id)sender
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"launching main app (from /Applications)");
|
logMsg(LOG_DEBUG, @"launching main app (from /Applications)");
|
||||||
|
#endif
|
||||||
|
|
||||||
//launch main app
|
//launch main app
|
||||||
[[NSWorkspace sharedWorkspace] launchApplication:[APPS_FOLDER stringByAppendingPathComponent:APP_NAME]];
|
[[NSWorkspace sharedWorkspace] launchApplication:[APPS_FOLDER stringByAppendingPathComponent:APP_NAME]];
|
||||||
|
|
|
@ -19,8 +19,10 @@ int main(int argc, const char * argv[])
|
||||||
int iReturn = 0;
|
int iReturn = 0;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"starting login item (args: %@/user: %@)", [[NSProcessInfo processInfo] arguments], NSUserName()]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"starting login item (args: %@/user: %@)", [[NSProcessInfo processInfo] arguments], NSUserName()]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//check for uninstall/install flags, and process to remove from whitelist
|
//check for uninstall/install flags, and process to remove from whitelist
|
||||||
if(2 == argc)
|
if(2 == argc)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +30,9 @@ int main(int argc, const char * argv[])
|
||||||
if(0 == strcmp(argv[1], CMD_INSTALL))
|
if(0 == strcmp(argv[1], CMD_INSTALL))
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"running install logic");
|
logMsg(LOG_DEBUG, @"running install logic");
|
||||||
|
#endif
|
||||||
|
|
||||||
//drop user privs
|
//drop user privs
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
|
@ -37,13 +41,17 @@ int main(int argc, const char * argv[])
|
||||||
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_INSTALL_FLAG);
|
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_INSTALL_FLAG);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"installed login item");
|
logMsg(LOG_DEBUG, @"installed login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//create default prefs
|
//create default prefs
|
||||||
[@{PREF_LOG_ACTIVITY:@YES, PREF_START_AT_LOGIN:@YES, PREF_RUN_HEADLESS:@NO, PREF_CHECK_4_UPDATES:@YES} writeToFile:[APP_PREFERENCES stringByExpandingTildeInPath] atomically:NO];
|
[@{PREF_LOG_ACTIVITY:@YES, PREF_START_AT_LOGIN:@YES, PREF_RUN_HEADLESS:@NO, PREF_CHECK_4_UPDATES:@YES} writeToFile:[APP_PREFERENCES stringByExpandingTildeInPath] atomically:NO];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"created preferences at: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"created preferences at: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -52,7 +60,9 @@ int main(int argc, const char * argv[])
|
||||||
else if(0 == strcmp(argv[1], CMD_UNINSTALL))
|
else if(0 == strcmp(argv[1], CMD_UNINSTALL))
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"running uninstall logic");
|
logMsg(LOG_DEBUG, @"running uninstall logic");
|
||||||
|
#endif
|
||||||
|
|
||||||
//drop user privs
|
//drop user privs
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
|
@ -61,13 +71,17 @@ int main(int argc, const char * argv[])
|
||||||
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_UNINSTALL_FLAG);
|
toggleLoginItem([NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]], ACTION_UNINSTALL_FLAG);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"removed login item");
|
logMsg(LOG_DEBUG, @"removed login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//delete prefs
|
//delete prefs
|
||||||
[[NSFileManager defaultManager] removeItemAtPath:[APP_PREFERENCES stringByExpandingTildeInPath] error:nil];
|
[[NSFileManager defaultManager] removeItemAtPath:[APP_PREFERENCES stringByExpandingTildeInPath] error:nil];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"removed preferences from: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"removed preferences from: %@", [APP_PREFERENCES stringByExpandingTildeInPath]]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -77,7 +91,9 @@ int main(int argc, const char * argv[])
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"running 'un-whitelist me' logic");
|
logMsg(LOG_DEBUG, @"running 'un-whitelist me' logic");
|
||||||
|
#endif
|
||||||
|
|
||||||
//remove from whitelist file
|
//remove from whitelist file
|
||||||
unWhiteList([NSString stringWithUTF8String:argv[1]]);
|
unWhiteList([NSString stringWithUTF8String:argv[1]]);
|
||||||
|
@ -112,26 +128,30 @@ void unWhiteList(NSString* process)
|
||||||
[xpcConnection resume];
|
[xpcConnection resume];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"sending XPC message to remove %@ from whitelist file", process]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"sending XPC message to remove %@ from whitelist file", process]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//invoke XPC method 'whitelistProcess' to add process to white list
|
//invoke XPC method 'whitelistProcess' to add process to white list
|
||||||
[[xpcConnection remoteObjectProxy] unWhitelistProcess:process reply:^(BOOL wasRemoved)
|
[[xpcConnection remoteObjectProxy] unWhitelistProcess:process reply:^(BOOL wasRemoved)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got XPC response: %d", wasRemoved]);
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"got XPC response: %d", wasRemoved]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//err msg ono failure
|
//err msg on failure
|
||||||
if(YES != wasRemoved)
|
if(YES != wasRemoved)
|
||||||
{
|
{
|
||||||
//err msg
|
//err msg
|
||||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to remove %@ from whitelist", process]);
|
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to remove %@ from whitelist", process]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//close connection
|
//close connection
|
||||||
[xpcConnection invalidate];
|
[xpcConnection invalidate];
|
||||||
|
|
||||||
//nil out
|
//nil out
|
||||||
xpcConnection = nil;
|
xpcConnection = nil;
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,9 @@
|
||||||
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"OverSight Preferences App Launched");
|
logMsg(LOG_DEBUG, @"OverSight Preferences App Launched");
|
||||||
|
#endif
|
||||||
|
|
||||||
//register for hotkey presses
|
//register for hotkey presses
|
||||||
// ->for now, just cmd+q to quit app
|
// ->for now, just cmd+q to quit app
|
||||||
|
@ -60,7 +62,9 @@
|
||||||
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[APP_PREFERENCES stringByExpandingTildeInPath]])
|
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[APP_PREFERENCES stringByExpandingTildeInPath]])
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"preference file not found; manually creating");
|
logMsg(LOG_DEBUG, @"preference file not found; manually creating");
|
||||||
|
#endif
|
||||||
|
|
||||||
//write em out
|
//write em out
|
||||||
// ->note; set 'start at login' to false, since no prefs here, mean installer wasn't run (user can later toggle)
|
// ->note; set 'start at login' to false, since no prefs here, mean installer wasn't run (user can later toggle)
|
||||||
|
@ -314,14 +318,18 @@ bail:
|
||||||
versionString = [NSMutableString string];
|
versionString = [NSMutableString string];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"checking for new version");
|
logMsg(LOG_DEBUG, @"checking for new version");
|
||||||
|
#endif
|
||||||
|
|
||||||
//check if available version is newer
|
//check if available version is newer
|
||||||
// ->show update popup/window
|
// ->show update popup/window
|
||||||
if(YES == isNewVersion(versionString))
|
if(YES == isNewVersion(versionString))
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"a new version (%@) is available", versionString]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"a new version (%@) is available", versionString]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//hide version message
|
//hide version message
|
||||||
self.versionLabel.hidden = YES;
|
self.versionLabel.hidden = YES;
|
||||||
|
@ -358,7 +366,9 @@ bail:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"no updates available");
|
logMsg(LOG_DEBUG, @"no updates available");
|
||||||
|
#endif
|
||||||
|
|
||||||
//stop/hide spinner
|
//stop/hide spinner
|
||||||
[self.spinner stopAnimation:self];
|
[self.spinner stopAnimation:self];
|
||||||
|
@ -404,7 +414,9 @@ bail:
|
||||||
(YES != shouldRestart) )
|
(YES != shouldRestart) )
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"login item already running and 'shouldRestart' not set, so no need to start it!");
|
logMsg(LOG_DEBUG, @"login item already running and 'shouldRestart' not set, so no need to start it!");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -425,7 +437,9 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"starting login item");
|
logMsg(LOG_DEBUG, @"starting login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//add overlay
|
//add overlay
|
||||||
[self addOverlay:shouldRestart];
|
[self addOverlay:shouldRestart];
|
||||||
|
@ -478,11 +492,17 @@ bail:
|
||||||
[self.overlay setWantsLayer:YES];
|
[self.overlay setWantsLayer:YES];
|
||||||
|
|
||||||
//get main window's frame
|
//get main window's frame
|
||||||
frame = self.window.frame;
|
frame = self.window.contentView.frame;
|
||||||
|
|
||||||
//set origin to 0/0
|
//set origin to 0/0
|
||||||
frame.origin = CGPointZero;
|
frame.origin = CGPointZero;
|
||||||
|
|
||||||
|
//tweak since window is rounded
|
||||||
|
// ->and adding this view doesn't get rounded?
|
||||||
|
frame.origin.y += 1;
|
||||||
|
frame.origin.x += 1;
|
||||||
|
frame.size.width -= 2;
|
||||||
|
|
||||||
//update overlay to take up entire window
|
//update overlay to take up entire window
|
||||||
self.overlay.frame = frame;
|
self.overlay.frame = frame;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#import <sys/sysctl.h>
|
#import <sys/sysctl.h>
|
||||||
|
|
||||||
//ignored mach sender procs
|
//ignored mach sender procs
|
||||||
// TODO: maybe just ignore apple signed daemons/bg procs!?
|
|
||||||
static NSArray* ignoredProcs = nil;
|
static NSArray* ignoredProcs = nil;
|
||||||
|
|
||||||
@implementation Enumerator
|
@implementation Enumerator
|
||||||
|
@ -93,7 +92,9 @@ static NSArray* ignoredProcs = nil;
|
||||||
if(YES != self.videoActive)
|
if(YES != self.videoActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"baselining mach senders for video...");
|
logMsg(LOG_DEBUG, @"baselining mach senders for video...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//find camera assistant
|
//find camera assistant
|
||||||
// ->first look for 'VDCAssistant'
|
// ->first look for 'VDCAssistant'
|
||||||
|
@ -118,29 +119,37 @@ static NSArray* ignoredProcs = nil;
|
||||||
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
|
self.machSendersVideo = [self enumMachSenders:cameraAssistant];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersVideo.count, self.machSendersVideo]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersVideo.count, self.machSendersVideo]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//only baseline if video isn't active
|
//only baseline if audio isn't active
|
||||||
if(YES != self.audioActive)
|
if(YES != self.audioActive)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"baselining mach senders for audio...");
|
logMsg(LOG_DEBUG, @"baselining mach senders for audio...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//enumerate procs that have send mach messages
|
//enumerate procs that have send mach messages
|
||||||
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
|
self.machSendersAudio = [self enumMachSenders:findProcess(CORE_AUDIO)];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersAudio.count, self.machSendersVideo]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSendersAudio.count, self.machSendersVideo]);
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
logMsg(LOG_DEBUG, @"baselining i/o registry entries for audio...");
|
logMsg(LOG_DEBUG, @"baselining i/o registry entries for audio...");
|
||||||
|
#endif
|
||||||
|
|
||||||
//enumerate procs that have i/o registry entries
|
//enumerate procs that have i/o registry entries
|
||||||
self.userClients = [self enumDomainUserClients];
|
self.userClients = [self enumDomainUserClients];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined i/or registry senders: %@", (unsigned long)self.userClients.count, self.userClients]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined i/or registry senders: %@", (unsigned long)self.userClients.count, self.userClients]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +207,9 @@ static NSArray* ignoredProcs = nil;
|
||||||
currentSenders = [self enumMachSenders:cameraAssistant];
|
currentSenders = [self enumMachSenders:cameraAssistant];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current mach senders: %@", (unsigned long)currentSenders.count, currentSenders]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current mach senders: %@", (unsigned long)currentSenders.count, currentSenders]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//remove any known/existing senders
|
//remove any known/existing senders
|
||||||
for(NSNumber* processID in currentSenders.allKeys)
|
for(NSNumber* processID in currentSenders.allKeys)
|
||||||
|
@ -220,7 +231,9 @@ static NSArray* ignoredProcs = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate video procs: %@", (unsigned long)candidateVideoProcs.count, candidateVideoProcs]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate video procs: %@", (unsigned long)candidateVideoProcs.count, candidateVideoProcs]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//update
|
//update
|
||||||
self.machSendersVideo = currentSenders;
|
self.machSendersVideo = currentSenders;
|
||||||
|
@ -294,7 +307,9 @@ bail:
|
||||||
currentSenders = [self enumMachSenders:coreAudio];
|
currentSenders = [self enumMachSenders:coreAudio];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current mach senders: %@", (unsigned long)currentSenders.count, currentSenders]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current mach senders: %@", (unsigned long)currentSenders.count, currentSenders]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//add new senders or those w/ new mach msgs
|
//add new senders or those w/ new mach msgs
|
||||||
for(NSNumber* processID in currentSenders.allKeys)
|
for(NSNumber* processID in currentSenders.allKeys)
|
||||||
|
@ -319,7 +334,9 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new mach senders: %@", newSenders]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new mach senders: %@", newSenders]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//update iVar
|
//update iVar
|
||||||
self.machSendersAudio = currentSenders;
|
self.machSendersAudio = currentSenders;
|
||||||
|
@ -328,7 +345,9 @@ bail:
|
||||||
currentUserClients = [self enumDomainUserClients];
|
currentUserClients = [self enumDomainUserClients];
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current i/o registry user clients: %@", (unsigned long)currentUserClients.count, currentUserClients]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current i/o registry user clients: %@", (unsigned long)currentUserClients.count, currentUserClients]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//add new user clients
|
//add new user clients
|
||||||
for(NSNumber* processID in currentUserClients.allKeys)
|
for(NSNumber* processID in currentUserClients.allKeys)
|
||||||
|
@ -353,29 +372,13 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new user clients: %@", newUserClients]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new user clients: %@", newUserClients]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//update iVar
|
//update iVar
|
||||||
self.userClients = currentUserClients;
|
self.userClients = currentUserClients;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
//parse/check
|
|
||||||
// ->starts at end to find most recent IOUserClientCreator
|
|
||||||
for(NSNumber* domainUserClient in [domainUserClients reverseObjectEnumerator])
|
|
||||||
{
|
|
||||||
//no match?
|
|
||||||
// ->remove from candidate
|
|
||||||
if(YES != [candidateAudioProcs containsObject:domainUserClient])
|
|
||||||
{
|
|
||||||
//remove
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//init set for intersection
|
//init set for intersection
|
||||||
intersection = [NSMutableSet setWithArray:newSenders];
|
intersection = [NSMutableSet setWithArray:newSenders];
|
||||||
|
|
||||||
|
@ -395,14 +398,24 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate audio procs: %@", (unsigned long)candidateAudioProcs.count, candidateAudioProcs]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate audio procs: %@", (unsigned long)candidateAudioProcs.count, candidateAudioProcs]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//TODO: sample?
|
//only once candidate?
|
||||||
//invoke 'sample' to confirm that candidates are using CMIO/video inputs
|
// ->all set, so assign, then bail here
|
||||||
// ->note, will skip FaceTime.app on macOS Sierra, as it doesn't do CMIO stuff directly
|
if(candidateAudioProcs.count <= 1)
|
||||||
//audioProcs = [self sampleCandidates:candidateAudioProcs];
|
{
|
||||||
|
//assign
|
||||||
audioProcs = candidateAudioProcs;
|
audioProcs = candidateAudioProcs;
|
||||||
|
|
||||||
|
//bail
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->invoke 'sample' to determine which candidate is using CMIO/video inputs
|
||||||
|
// note: will skip FaceTime.app on macOS Sierra, as it doesn't do CMIO stuff directly
|
||||||
|
audioProcs = [self sampleCandidates:candidateAudioProcs];
|
||||||
|
|
||||||
}//sync
|
}//sync
|
||||||
|
|
||||||
|
@ -615,11 +628,12 @@ bail:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//invoke 'sample' to confirm candidates are using CMIO/video inputs
|
//invoke 'sample' to confirm candidates are using CMIO/video/av inputs
|
||||||
|
// note: path audio/vide invoke 'CMIOGraph::DoWork'
|
||||||
-(NSMutableArray*)sampleCandidates:(NSArray*)currentSenders
|
-(NSMutableArray*)sampleCandidates:(NSArray*)currentSenders
|
||||||
{
|
{
|
||||||
//current procs
|
//av procs
|
||||||
NSMutableArray* videoProcs = nil;
|
NSMutableArray* avProcs = nil;
|
||||||
|
|
||||||
//results from 'sample' cmd
|
//results from 'sample' cmd
|
||||||
NSString* results = nil;
|
NSString* results = nil;
|
||||||
|
@ -628,14 +642,16 @@ bail:
|
||||||
NSString* processPath = nil;
|
NSString* processPath = nil;
|
||||||
|
|
||||||
//alloc
|
//alloc
|
||||||
videoProcs = [NSMutableArray array];
|
avProcs = [NSMutableArray array];
|
||||||
|
|
||||||
//invoke 'sample' on each
|
//invoke 'sample' on each
|
||||||
// ->skips FaceTime.app though on macOS Sierra
|
// ->skips FaceTime.app though on macOS Sierra
|
||||||
for(NSNumber* processID in currentSenders)
|
for(NSNumber* processID in currentSenders)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"processing %d for sampling", processID.intValue]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"processing %d for sampling", processID.intValue]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//get process path
|
//get process path
|
||||||
// ->skip ones that fail
|
// ->skip ones that fail
|
||||||
|
@ -653,10 +669,12 @@ bail:
|
||||||
([getOSVersion() [@"minorVersion"] intValue] >= 12) )
|
([getOSVersion() [@"minorVersion"] intValue] >= 12) )
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"not sampling as candidate app is FaceTime on macOS Sierra");
|
logMsg(LOG_DEBUG, @"not sampling as candidate app is FaceTime on macOS Sierra");
|
||||||
|
#endif
|
||||||
|
|
||||||
//add
|
//add
|
||||||
[videoProcs addObject:processID];
|
[avProcs addObject:processID];
|
||||||
|
|
||||||
//next
|
//next
|
||||||
continue;
|
continue;
|
||||||
|
@ -664,7 +682,9 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"sampling %d", processID.intValue]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"sampling %d", processID.intValue]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//exec 'sample' to get threads/dylibs
|
//exec 'sample' to get threads/dylibs
|
||||||
// ->uses 1.0 seconds for sampling time
|
// ->uses 1.0 seconds for sampling time
|
||||||
|
@ -681,18 +701,23 @@ bail:
|
||||||
[self deleteSampleFile:processPath];
|
[self deleteSampleFile:processPath];
|
||||||
|
|
||||||
//for now, just check for 'CMIOGraph::DoWork'
|
//for now, just check for 'CMIOGraph::DoWork'
|
||||||
// ->TODO: could look for dylibs, other calls, etc
|
// ->note: both audio/video invoke this, so this method works for both!
|
||||||
if(YES != [results containsString:@"CMIOGraph::DoWork"])
|
if(YES != [results containsString:@"CMIOGraph::DoWork"])
|
||||||
{
|
{
|
||||||
//skip
|
//skip
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//looks like a video proc!
|
//dbg msg
|
||||||
[videoProcs addObject:processID];
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"processing %d for has 'CMIOGraph::DoWork', as adding to list of candidates", processID.intValue]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//looks like a av proc!
|
||||||
|
[avProcs addObject:processID];
|
||||||
}
|
}
|
||||||
|
|
||||||
return videoProcs;
|
return avProcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
//'sample' binary creates a file
|
//'sample' binary creates a file
|
||||||
|
@ -734,7 +759,9 @@ bail:
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"deleting sample file: %@", file]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"deleting sample file: %@", file]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//delete
|
//delete
|
||||||
if(YES != [[NSFileManager defaultManager] removeItemAtPath:[@"/tmp" stringByAppendingPathComponent:file] error:&error])
|
if(YES != [[NSFileManager defaultManager] removeItemAtPath:[@"/tmp" stringByAppendingPathComponent:file] error:&error])
|
||||||
|
|
|
@ -113,7 +113,9 @@
|
||||||
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]])
|
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]])
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"XPC: creating app support directory: %@", [APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"XPC: creating app support directory: %@", [APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath]]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//create
|
//create
|
||||||
if(YES != [[NSFileManager defaultManager] createDirectoryAtPath: [APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath] withIntermediateDirectories:YES attributes:nil error:&error])
|
if(YES != [[NSFileManager defaultManager] createDirectoryAtPath: [APP_SUPPORT_DIRECTORY stringByExpandingTildeInPath] withIntermediateDirectories:YES attributes:nil error:&error])
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="AboutWindowController">
|
<customObject id="-2" userLabel="File's Owner" customClass="AboutWindowController">
|
||||||
|
@ -15,35 +16,50 @@
|
||||||
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="422" height="123"/>
|
<rect key="contentRect" x="196" y="240" width="422" height="123"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1058"/>
|
||||||
<view key="contentView" id="se5-gp-TjO">
|
<view key="contentView" id="se5-gp-TjO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
|
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
|
||||||
<rect key="frame" x="10" y="12" width="110" height="106"/>
|
<rect key="frame" x="10" y="12" width="110" height="106"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="xKf-GK-m0k"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="xKf-GK-m0k"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
|
||||||
<rect key="frame" x="141" y="63" width="180" height="50"/>
|
<rect key="frame" x="138" y="63" width="180" height="50"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="overSight" id="Ws8-bD-j2R"/>
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="overSight" id="Ws8-bD-j2R"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||||
<rect key="frame" x="141" y="51" width="182" height="19"/>
|
<rect key="frame" x="141" y="51" width="182" height="19"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="version:" id="bBK-v0-ypq">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="version:" id="bBK-v0-ypq">
|
||||||
<font key="font" size="13" name="Menlo-Regular"/>
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
<button verticalHuggingPriority="750" fixedFrame="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
||||||
<rect key="frame" x="280" y="11" width="128" height="32"/>
|
<rect key="frame" x="280" y="11" width="128" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
<buttonCell key="cell" type="push" title="more info" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="J9x-sM-h9S">
|
<buttonCell key="cell" type="push" title="more info" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="J9x-sM-h9S">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" size="13" name="Menlo-Regular"/>
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="moreInfo:" target="-2" id="YYW-1b-uJY"/>
|
<action selector="buttonHandler:" target="-2" id="Cgx-f4-Thr"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button verticalHuggingPriority="750" fixedFrame="YES" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="xnd-Gw-0o8">
|
||||||
|
<rect key="frame" x="137" y="11" width="128" height="32"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<buttonCell key="cell" type="push" title="support us!" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6g3-Pg-x3P">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" size="13" name="Menlo-Regular"/>
|
||||||
|
</buttonCell>
|
||||||
|
<connections>
|
||||||
|
<action selector="buttonHandler:" target="-2" id="gP0-s7-o6h"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|
|
@ -20,8 +20,5 @@
|
||||||
|
|
||||||
/* METHODS */
|
/* METHODS */
|
||||||
|
|
||||||
//invoked when user clicks 'more info' button
|
|
||||||
// ->open OverSights webpage
|
|
||||||
- (IBAction)moreInfo:(id)sender;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -48,14 +48,26 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//automatically invoked when user clicks 'more info'
|
//automatically invoked when user clicks any of the buttons
|
||||||
// ->load products webpage view their default browser
|
// ->load patreon or products webpage in user's default browser
|
||||||
-(IBAction)moreInfo:(id)sender
|
-(IBAction)buttonHandler:(id)sender
|
||||||
{
|
{
|
||||||
//open URL
|
//support us button
|
||||||
// ->invokes user's default browser
|
if(((NSButton*)sender).tag == BUTTON_SUPPORT_US)
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PRODUCT_URL]];
|
{
|
||||||
|
//open URL
|
||||||
|
// ->invokes user's default browser
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PATREON_URL]];
|
||||||
|
}
|
||||||
|
|
||||||
|
//more info button
|
||||||
|
else if(((NSButton*)sender).tag == BUTTON_MORE_INFO)
|
||||||
|
{
|
||||||
|
//open URL
|
||||||
|
// ->invokes user's default browser
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PRODUCT_URL]];
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
//product version url
|
//product version url
|
||||||
#define PRODUCT_VERSION_URL @"https://objective-see.com/products.json"
|
#define PRODUCT_VERSION_URL @"https://objective-see.com/products.json"
|
||||||
|
|
||||||
|
//patreon url
|
||||||
|
#define PATREON_URL @"https://www.patreon.com/objective_see"
|
||||||
|
|
||||||
//OS version x
|
//OS version x
|
||||||
#define OS_MAJOR_VERSION_X 10
|
#define OS_MAJOR_VERSION_X 10
|
||||||
|
|
||||||
|
@ -52,7 +55,19 @@
|
||||||
|
|
||||||
//button title
|
//button title
|
||||||
// ->Close
|
// ->Close
|
||||||
#define ACTION_CLOSE @"Close"
|
#define ACTION_CLOSE @"close"
|
||||||
|
|
||||||
|
//button title
|
||||||
|
// ->next
|
||||||
|
#define ACTION_NEXT @"next »"
|
||||||
|
|
||||||
|
//button title
|
||||||
|
// ->no
|
||||||
|
#define ACTION_NO @"no"
|
||||||
|
|
||||||
|
//button title
|
||||||
|
// ->yes
|
||||||
|
#define ACTION_YES @"yes!"
|
||||||
|
|
||||||
//flag to uninstall
|
//flag to uninstall
|
||||||
#define ACTION_UNINSTALL_FLAG 0
|
#define ACTION_UNINSTALL_FLAG 0
|
||||||
|
@ -128,12 +143,19 @@
|
||||||
#define EVENT_TIMESTAMP @"timeStamp"
|
#define EVENT_TIMESTAMP @"timeStamp"
|
||||||
#define EVENT_DEVICE_STATUS @"status"
|
#define EVENT_DEVICE_STATUS @"status"
|
||||||
#define EVENT_PROCESS_ID @"processID"
|
#define EVENT_PROCESS_ID @"processID"
|
||||||
|
#define EVENT_ALERT_TYPE @"alertType"
|
||||||
#define EVENT_PROCESS_NAME @"processName"
|
#define EVENT_PROCESS_NAME @"processName"
|
||||||
#define EVENT_PROCESS_PATH @"processPath"
|
#define EVENT_PROCESS_PATH @"processPath"
|
||||||
|
|
||||||
//unknown process
|
//unknown process
|
||||||
#define PROCESS_UNKNOWN @"<unknown>"
|
#define PROCESS_UNKNOWN @"<unknown>"
|
||||||
|
|
||||||
|
//went inactive
|
||||||
|
#define ALERT_INACTIVE @0x0
|
||||||
|
|
||||||
|
//went active
|
||||||
|
#define ALERT_ACTIVATE @0x1
|
||||||
|
|
||||||
//source audio
|
//source audio
|
||||||
#define SOURCE_AUDIO @0x1
|
#define SOURCE_AUDIO @0x1
|
||||||
|
|
||||||
|
@ -149,5 +171,11 @@
|
||||||
//id (tag) for detailed text in rules table
|
//id (tag) for detailed text in rules table
|
||||||
#define TABLE_ROW_SUB_TEXT_TAG 101
|
#define TABLE_ROW_SUB_TEXT_TAG 101
|
||||||
|
|
||||||
|
//support us button tag
|
||||||
|
#define BUTTON_SUPPORT_US 100
|
||||||
|
|
||||||
|
//more info button tag
|
||||||
|
#define BUTTON_MORE_INFO 101
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -153,7 +153,9 @@ BOOL setFileOwner(NSString* path, NSNumber* groupID, NSNumber* ownerID, BOOL rec
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"set ownership for %@ (%@)", path, fileOwner]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"set ownership for %@ (%@)", path, fileOwner]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//do it recursively
|
//do it recursively
|
||||||
if(YES == recursive)
|
if(YES == recursive)
|
||||||
|
@ -269,35 +271,28 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments)
|
||||||
//output pipe
|
//output pipe
|
||||||
NSPipe *outPipe = nil;
|
NSPipe *outPipe = nil;
|
||||||
|
|
||||||
//read handle
|
|
||||||
NSFileHandle* readHandle = nil;
|
|
||||||
|
|
||||||
//output
|
//output
|
||||||
NSMutableData *output = nil;
|
NSData *output = nil;
|
||||||
|
|
||||||
//init task
|
//init task
|
||||||
task = [NSTask new];
|
task = [NSTask new];
|
||||||
|
|
||||||
//init output pipe
|
//init pipe
|
||||||
outPipe = [NSPipe pipe];
|
outPipe = [NSPipe pipe];
|
||||||
|
|
||||||
//init read handle
|
|
||||||
readHandle = [outPipe fileHandleForReading];
|
|
||||||
|
|
||||||
//init output buffer
|
|
||||||
output = [NSMutableData data];
|
|
||||||
|
|
||||||
//set task's path
|
//set task's path
|
||||||
[task setLaunchPath:binaryPath];
|
task.launchPath = binaryPath;
|
||||||
|
|
||||||
//set task's args
|
//set task's args
|
||||||
[task setArguments:arguments];
|
task.arguments = arguments;
|
||||||
|
|
||||||
//set task's output
|
//set task's output to pipe
|
||||||
[task setStandardOutput:outPipe];
|
task.standardOutput = outPipe;
|
||||||
|
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"@exec'ing %@ (args: %@)", binaryPath, arguments]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"@exec'ing %@ (args: %@)", binaryPath, arguments]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//wrap task launch
|
//wrap task launch
|
||||||
@try
|
@try
|
||||||
|
@ -307,19 +302,33 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments)
|
||||||
}
|
}
|
||||||
@catch(NSException* exception)
|
@catch(NSException* exception)
|
||||||
{
|
{
|
||||||
|
//err msg
|
||||||
|
logMsg(LOG_ERR, [NSString stringWithFormat:@"task failed with %@", exception]);
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
//read in output
|
//dbg msg
|
||||||
while(YES == [task isRunning])
|
#ifdef DEBUG
|
||||||
{
|
logMsg(LOG_DEBUG, @"invoking 'readDataToEndOfFile' to get all data");
|
||||||
//accumulate output
|
#endif
|
||||||
[output appendData:[readHandle readDataToEndOfFile]];
|
|
||||||
}
|
|
||||||
|
|
||||||
//grab any left over data
|
//read until file is closed
|
||||||
[output appendData:[readHandle readDataToEndOfFile]];
|
output = [outPipe.fileHandleForReading readDataToEndOfFile];
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"now waiting for task to exit");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//wait till exit
|
||||||
|
[task waitUntilExit];
|
||||||
|
|
||||||
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
|
logMsg(LOG_DEBUG, @"task to exited");
|
||||||
|
#endif
|
||||||
|
|
||||||
//bail
|
//bail
|
||||||
bail:
|
bail:
|
||||||
|
@ -845,7 +854,9 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
|
||||||
if(ACTION_INSTALL_FLAG == toggleFlag)
|
if(ACTION_INSTALL_FLAG == toggleFlag)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"adding login item");
|
logMsg(LOG_DEBUG, @"adding login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//add
|
//add
|
||||||
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, (__bridge CFURLRef)(loginItem), NULL, NULL);
|
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, (__bridge CFURLRef)(loginItem), NULL, NULL);
|
||||||
|
@ -854,7 +865,9 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
|
||||||
if(NULL != itemRef)
|
if(NULL != itemRef)
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"added %@/%@", loginItem, itemRef]);
|
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"added %@/%@", loginItem, itemRef]);
|
||||||
|
#endif
|
||||||
|
|
||||||
//release
|
//release
|
||||||
CFRelease(itemRef);
|
CFRelease(itemRef);
|
||||||
|
@ -879,7 +892,9 @@ BOOL toggleLoginItem(NSURL* loginItem, int toggleFlag)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//dbg msg
|
//dbg msg
|
||||||
|
#ifdef DEBUG
|
||||||
logMsg(LOG_DEBUG, @"removing login item");
|
logMsg(LOG_DEBUG, @"removing login item");
|
||||||
|
#endif
|
||||||
|
|
||||||
//grab existing login items
|
//grab existing login items
|
||||||
loginItems = LSSharedFileListCopySnapshot(loginItemsRef, nil);
|
loginItems = LSSharedFileListCopySnapshot(loginItemsRef, nil);
|
||||||
|
|
Loading…
Reference in New Issue