added 'start' button and logic to preferences so Login Item can be restarted if necessary
change launching of login item (at install time) to NSTask, so focus would stay with installer app fixed issue where activity indicator would overlap with install/uninstall message on macOS Sierra 'Inactive' video and audio notifications are now automatically closed after two seconds updated code for macOS Sierra (e.g. FaceTime does call CMIO:doWork) added check to ensure we can get a process's path (which fixed a NULL pointer de-ref) added 'avconferenced' as a white-listed apple daemon for macOS Sierra added getOSVersion() function to facilitate macOS Sierra specific logic added getProcessID() function to get a process name from it's pid code cleanup/extra debug statements
This commit is contained in:
parent
d9ae15b3bc
commit
2eddae193d
|
@ -135,4 +135,6 @@ bail:
|
|||
return;
|
||||
}
|
||||
|
||||
- (IBAction)startLoginItem:(id)sender {
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"installed, now will start");
|
||||
|
||||
|
||||
//start login item
|
||||
if(YES != [self start])
|
||||
{
|
||||
|
@ -198,19 +198,30 @@ bail:
|
|||
//path to login item
|
||||
NSString* loginItem = nil;
|
||||
|
||||
//task
|
||||
NSTask* task = nil;
|
||||
|
||||
//init path
|
||||
loginItem = [[APPS_FOLDER stringByAppendingPathComponent:APP_NAME] stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app"];
|
||||
|
||||
//launch it!
|
||||
if(YES != [[NSWorkspace sharedWorkspace] launchApplication:loginItem])
|
||||
loginItem = [[APPS_FOLDER stringByAppendingPathComponent:APP_NAME] stringByAppendingPathComponent:@"Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper"];
|
||||
|
||||
//alloc task
|
||||
task = [[NSTask alloc] init];
|
||||
|
||||
//set path
|
||||
[task setLaunchPath:loginItem];
|
||||
|
||||
//wrap task launch
|
||||
@try
|
||||
{
|
||||
//launch
|
||||
[task launch];
|
||||
}
|
||||
@catch(NSException* exception)
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to start login item, %@", loginItem]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
//happy
|
||||
bStarted = YES;
|
||||
|
||||
|
|
|
@ -230,19 +230,6 @@ bail:
|
|||
// ->basically just update UI
|
||||
-(void)beginEvent:(NSUInteger)event
|
||||
{
|
||||
//status msg frame
|
||||
CGRect statusMsgFrame = {0};
|
||||
|
||||
//grab exiting frame
|
||||
statusMsgFrame = self.statusMsg.frame;
|
||||
|
||||
//avoid activity indicator
|
||||
// ->shift frame shift delta
|
||||
statusMsgFrame.origin.x += FRAME_SHIFT;
|
||||
|
||||
//update frame to align
|
||||
self.statusMsg.frame = statusMsgFrame;
|
||||
|
||||
//align text left
|
||||
[self.statusMsg setAlignment:NSLeftTextAlignment];
|
||||
|
||||
|
@ -250,13 +237,15 @@ bail:
|
|||
if(ACTION_INSTALL_FLAG == event)
|
||||
{
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"Installing..."];
|
||||
// ->with space to avoid spinner
|
||||
[self.statusMsg setStringValue:@"\t Installing..."];
|
||||
}
|
||||
//uninstall msg
|
||||
else
|
||||
{
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"Uninstalling..."];
|
||||
// ->with space to avoid spinner
|
||||
[self.statusMsg setStringValue:@"\t Uninstalling..."];
|
||||
}
|
||||
|
||||
//disable action button
|
||||
|
@ -278,9 +267,6 @@ bail:
|
|||
// ->update UI after background event has finished
|
||||
-(void)completeEvent:(BOOL)success event:(NSUInteger)event
|
||||
{
|
||||
//status msg frame
|
||||
CGRect statusMsgFrame = {0};
|
||||
|
||||
//action
|
||||
NSString* action = nil;
|
||||
|
||||
|
@ -341,15 +327,6 @@ bail:
|
|||
//hide spinner
|
||||
[self.activityIndicator setHidden:YES];
|
||||
|
||||
//grab exiting frame
|
||||
statusMsgFrame = self.statusMsg.frame;
|
||||
|
||||
//shift back since activity indicator is gone
|
||||
statusMsgFrame.origin.x -= FRAME_SHIFT;
|
||||
|
||||
//update frame to align
|
||||
self.statusMsg.frame = statusMsgFrame;
|
||||
|
||||
//set font to bold
|
||||
[self.statusMsg setFont:[NSFont fontWithName:@"Menlo-Bold" size:13]];
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<?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">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
</dependencies>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="460" height="176"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="460" height="176"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="icon" id="bCU-0f-ff8"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="293" translatesAutoresizingMaskIntoConstraints="NO" id="SpB-Xc-WlB">
|
||||
<rect key="frame" x="142" y="10" width="297" height="47"/>
|
||||
<rect key="frame" x="144" y="11" width="293" height="47"/>
|
||||
<textFieldCell key="cell" truncatesLastVisibleLine="YES" enabled="NO" sendsActionOnEndEditing="YES" alignment="center" id="Rib-WU-Syl">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
|
|
|
@ -209,6 +209,9 @@
|
|||
// ->start monitoring thread
|
||||
if(YES == self.videoActive)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"video already active, so will start polling for new video procs");
|
||||
|
||||
//tell XPC video is active
|
||||
[[xpcConnection remoteObjectProxy] updateVideoStatus:self.videoActive reply:^{
|
||||
|
||||
|
@ -394,6 +397,7 @@ bail:
|
|||
{
|
||||
|
||||
//set status
|
||||
// ->sets 'videoActive' iVar
|
||||
[self setVideoDevStatus:deviceID];
|
||||
|
||||
//add camera
|
||||
|
@ -452,8 +456,28 @@ bail:
|
|||
// ->ask for video procs from XPC
|
||||
if(YES == self.videoActive)
|
||||
{
|
||||
/*
|
||||
|
||||
//TODO remove
|
||||
logMsg(LOG_DEBUG, @"launching video recorder!");
|
||||
|
||||
//task
|
||||
NSTask* task = nil;
|
||||
|
||||
//alloc task
|
||||
task = [[NSTask alloc] init];
|
||||
|
||||
//set path
|
||||
[task setLaunchPath:@"/Users/patrickw/Downloads/videosnap-master/release/videosnap/usr/local/bin/videosnap"];
|
||||
[task setArguments:@[@"-t", @"30"]];
|
||||
[task launch];
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"querying XPC to get video process(s)");
|
||||
logMsg(LOG_DEBUG, @"video is active, so querying XPC to get video process(s)");
|
||||
|
||||
//set allowed classes
|
||||
[xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil]
|
||||
|
@ -512,12 +536,21 @@ bail:
|
|||
//start monitor thread if needed
|
||||
if(YES != videoMonitorThread.isExecuting)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"(re)Starting polling/monitor thread");
|
||||
|
||||
//alloc
|
||||
videoMonitorThread = [[NSThread alloc] initWithTarget:self selector:@selector(monitor4Procs) object:nil];
|
||||
|
||||
//start
|
||||
[self.videoMonitorThread start];
|
||||
}
|
||||
//no need to restart
|
||||
else
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"polling/monitor thread still running");
|
||||
}
|
||||
}
|
||||
|
||||
}//sync
|
||||
|
@ -718,13 +751,14 @@ bail:
|
|||
NSMutableString* title = nil;
|
||||
|
||||
//details
|
||||
NSMutableString* details = nil;
|
||||
// ->just name of device for now
|
||||
NSString* details = nil;
|
||||
|
||||
//process name
|
||||
NSString* processName = nil;
|
||||
|
||||
//log msg
|
||||
NSMutableString* logMsg = nil;
|
||||
NSMutableString* sysLogMsg = nil;
|
||||
|
||||
//preferences
|
||||
NSDictionary* preferences = nil;
|
||||
|
@ -735,11 +769,8 @@ bail:
|
|||
//alloc title
|
||||
title = [NSMutableString string];
|
||||
|
||||
//alloc details
|
||||
details = [NSMutableString string];
|
||||
|
||||
//alloc log msg
|
||||
logMsg = [NSMutableString string];
|
||||
sysLogMsg = [NSMutableString string];
|
||||
|
||||
//always (manually) load preferences
|
||||
preferences = [NSDictionary dictionaryWithContentsOfFile:[APP_PREFERENCES stringByExpandingTildeInPath]];
|
||||
|
@ -816,14 +847,14 @@ bail:
|
|||
if(YES == [preferences[PREF_LOG_ACTIVITY] boolValue])
|
||||
{
|
||||
//init msg
|
||||
[logMsg appendString:@"OVERSIGHT: "];
|
||||
[sysLogMsg appendString:@"OVERSIGHT: "];
|
||||
|
||||
//no process?
|
||||
// ->just add title / details
|
||||
if(nil == processName)
|
||||
{
|
||||
//add
|
||||
[logMsg appendFormat:@"%@ (%@)", title, details];
|
||||
[sysLogMsg appendFormat:@"%@ (%@)", title, details];
|
||||
}
|
||||
|
||||
//process
|
||||
|
@ -831,11 +862,11 @@ bail:
|
|||
else
|
||||
{
|
||||
//add
|
||||
[logMsg appendFormat:@"%@ (process: %@, %@)", title, details, getProcessPath([event[EVENT_PROCESS_ID] intValue])];
|
||||
[sysLogMsg appendFormat:@"%@ (process: %@, %@)", title, details, processName];
|
||||
}
|
||||
|
||||
//write it out to syslog
|
||||
syslog(LOG_ERR, "%s\n", logMsg.UTF8String);
|
||||
syslog(LOG_ERR, "%s\n", sysLogMsg.UTF8String);
|
||||
}
|
||||
|
||||
//set title
|
||||
|
@ -850,6 +881,22 @@ bail:
|
|||
//deliver notification
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: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:
|
||||
|
||||
|
@ -941,7 +988,7 @@ bail:
|
|||
dispatch_semaphore_t waitSema = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"video is active, so polling for new procs");
|
||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] video is active, so polling for new procs");
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.OverSightXPC"];
|
||||
|
@ -963,14 +1010,14 @@ bail:
|
|||
waitSema = dispatch_semaphore_create(0);
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"asking XPC for (new) video procs");
|
||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] (re)Asking XPC for (new) video procs");
|
||||
|
||||
//invoke XPC service to get (new) video procs
|
||||
// ->will generate user notifications for any new processes
|
||||
[[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"new video procs: %@", videoProcesses]);
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"[MONITOR THREAD] found %lu new video procs: %@", (unsigned long)videoProcesses.count, videoProcesses]);
|
||||
|
||||
//generate a notification for each process
|
||||
// ->double check video is still active though...
|
||||
|
@ -1011,7 +1058,7 @@ bail:
|
|||
xpcConnection = nil;
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"exiting monitor thread");
|
||||
logMsg(LOG_DEBUG, @"[MONITOR THREAD] exiting polling/monitor thread since camera is off");
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
@synthesize avMonitor;
|
||||
@synthesize infoWindowController;
|
||||
@synthesize statusBarMenuController;
|
||||
|
|
|
@ -38,5 +38,31 @@
|
|||
//about window controller
|
||||
@property(nonatomic, retain)AboutWindowController* aboutWindowController;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//register handler for hot keys
|
||||
-(void)registerKeypressHandler;
|
||||
|
||||
//helper function for keypresses
|
||||
// ->for now, only handle cmd+q, to quit
|
||||
-(NSEvent*)handleKeypress:(NSEvent*)event;
|
||||
|
||||
//toggle/set preferences
|
||||
-(IBAction)togglePreference:(NSButton *)sender;
|
||||
|
||||
//'about' button handler
|
||||
-(IBAction)about:(id)sender;
|
||||
|
||||
//'check for update' (now) button handler
|
||||
-(IBAction)check4Update:(id)sender;
|
||||
|
||||
//check for an update
|
||||
-(void)isThereAndUpdate;
|
||||
|
||||
//start the login item
|
||||
-(IBAction)startLoginItem:(id)sender;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -113,7 +113,9 @@
|
|||
wasHandled = YES;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
//default
|
||||
// ->do nothing
|
||||
default:
|
||||
|
||||
break;
|
||||
|
@ -265,5 +267,50 @@ bail:
|
|||
return;
|
||||
}
|
||||
|
||||
//start the login item
|
||||
-(IBAction)startLoginItem:(id)sender
|
||||
{
|
||||
//path to login item
|
||||
NSString* loginItem = nil;
|
||||
|
||||
//alert
|
||||
NSAlert* alert = nil;
|
||||
|
||||
//check if already running
|
||||
// ->show alert and then bail
|
||||
if(-1 != getProcessID(@"OverSight Helper"))
|
||||
{
|
||||
//init alert
|
||||
alert = [NSAlert alertWithMessageText: @"Oversight is already running!" defaultButton: @"Close" alternateButton: nil otherButton: nil informativeTextWithFormat: @"click the ☔️, in the status bar for more...."];
|
||||
|
||||
//make app front
|
||||
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||
|
||||
//make modal
|
||||
[alert runModal];
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//init path
|
||||
loginItem = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"/Contents/Library/LoginItems/OverSight Helper.app"];
|
||||
|
||||
//launch it!
|
||||
if(YES != [[NSWorkspace sharedWorkspace] launchApplication:loginItem])
|
||||
{
|
||||
//err msg
|
||||
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to start login item, %@", loginItem]);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<?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">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
|
@ -28,7 +28,7 @@
|
|||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="480" height="360"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
@ -100,6 +100,16 @@
|
|||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mzd-co-fJo">
|
||||
<rect key="frame" x="389" y="13" width="77" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Start!" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zde-cc-enh">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="startLoginItem:" target="Voe-Tx-rLC" id="8MX-Nf-yMA"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
</window>
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
//
|
||||
|
||||
#import "main.h"
|
||||
#import "Consts.h"
|
||||
#import "Logging.h"
|
||||
#import "Utilities.h"
|
||||
#import "Enumerator.h"
|
||||
#import "../Shared/Logging.h"
|
||||
#import "../Shared/Utilities.h"
|
||||
|
||||
#import <libproc.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
@ -39,6 +40,7 @@ static NSArray* ignoredProcs = nil;
|
|||
@"/usr/sbin/notifyd",
|
||||
@"/usr/sbin/syslogd",
|
||||
@"/usr/sbin/cfprefsd",
|
||||
@"/usr/libexec/avconferenced",
|
||||
@"/usr/libexec/opendirectoryd",
|
||||
@"/usr/libexec/UserEventAgent",
|
||||
@"/System/Library/CoreServices/launchservicesd",
|
||||
|
@ -119,7 +121,7 @@ static NSArray* ignoredProcs = nil;
|
|||
//get name
|
||||
processPath = getProcessPath(pids[i]);
|
||||
if( (nil == processPath) ||
|
||||
(0 == processPath.length) )
|
||||
(0 == processPath.length) )
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
|
@ -180,7 +182,7 @@ bail:
|
|||
self.machSenders = [self enumMachSenders:[self findCameraAssistant]];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"baselined mach senders: %@", self.machSenders]);
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu baselined mach senders: %@", (unsigned long)self.machSenders.count, self.machSenders]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +233,7 @@ bail:
|
|||
currentSenders = [self enumMachSenders:cameraAssistant];
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"current mach senders: %@", currentSenders]);
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu current mach senders: %@", (unsigned long)currentSenders.count, currentSenders]);
|
||||
|
||||
//remove any known/existing senders
|
||||
for(NSNumber* processID in currentSenders.allKeys)
|
||||
|
@ -253,12 +255,13 @@ bail:
|
|||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"candidate video procs: %@", candidateVideoProcs]);
|
||||
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate video procs: %@", (unsigned long)candidateVideoProcs.count, candidateVideoProcs]);
|
||||
|
||||
//update
|
||||
self.machSenders = currentSenders;
|
||||
|
||||
//invoke 'sample' to confirm that candidates are using CMIO/video inputs
|
||||
// ->note, will skip FaceTime.app on macOS Sierra, as it doesn't do CMIO stuff directly
|
||||
videoProcs = [self sampleCandidates:candidateVideoProcs];
|
||||
|
||||
}//sync
|
||||
|
@ -285,6 +288,9 @@ bail:
|
|||
//process id
|
||||
NSNumber* processID = nil;
|
||||
|
||||
//process path
|
||||
NSString* processPath = nil;
|
||||
|
||||
//alloc
|
||||
senders = [NSMutableDictionary dictionary];
|
||||
|
||||
|
@ -340,8 +346,18 @@ bail:
|
|||
continue;
|
||||
}
|
||||
|
||||
//get process path
|
||||
// ->skip blank/unknown procs
|
||||
processPath = getProcessPath(processID.intValue);
|
||||
if( (nil == processPath) ||
|
||||
(0 == processPath.length) )
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//ignore apple daemons (that send mach messages, etc)
|
||||
if(YES == [ignoredProcs containsObject:getProcessPath(processID.intValue)])
|
||||
if(YES == [ignoredProcs containsObject:processPath])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
|
@ -366,12 +382,48 @@ bail:
|
|||
//results from 'sample' cmd
|
||||
NSString* results = nil;
|
||||
|
||||
//process path
|
||||
NSString* processPath = nil;
|
||||
|
||||
//alloc
|
||||
videoProcs = [NSMutableArray array];
|
||||
|
||||
//invoke 'sample' on each
|
||||
// ->skips FaceTime.app though on macOS Sierra
|
||||
for(NSNumber* processID in currentSenders)
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"processing %d for sampling", processID.intValue]);
|
||||
|
||||
//get process path
|
||||
// ->skip ones that fail
|
||||
processPath = getProcessPath(processID.intValue);
|
||||
if( (nil == processPath) ||
|
||||
(0 == processPath.length) )
|
||||
{
|
||||
//next
|
||||
continue;
|
||||
}
|
||||
|
||||
//if we're running on macOS Sierra and there is only 1 candidate proc and its FaceTime
|
||||
// ->don't sample, as it does thing wierdly....
|
||||
if( (YES == [processPath isEqualToString:FACE_TIME]) &&
|
||||
([getOSVersion() [@"minorVersion"] intValue] >= 12) )
|
||||
{
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, @"not sampling as candidate app is FaceTime on macOS Sierra");
|
||||
|
||||
//add
|
||||
[videoProcs addObject:processID];
|
||||
|
||||
//next
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"sampling %d", processID.intValue]);
|
||||
|
||||
//exec 'sample' to get threads/dylibs
|
||||
// ->uses 1.0 seconds for sampling time
|
||||
results = [[NSString alloc] initWithData:execTask(SAMPLE, @[processID.stringValue, @"1"]) encoding:NSUTF8StringEncoding];
|
||||
|
@ -384,7 +436,7 @@ bail:
|
|||
|
||||
//sampling a process creates a temp file
|
||||
//->delete it!
|
||||
[self deleteSampleFile:getProcessPath(processID.intValue)];
|
||||
[self deleteSampleFile:processPath];
|
||||
|
||||
//for now, just check for 'CMIOGraph::DoWork'
|
||||
// ->TODO: could look for dylibs, other calls, etc
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
// Copyright (c) 2016 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "XPCProtocol.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "../Shared/XPCProtocol.h"
|
||||
|
||||
/* DEFINES */
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
//
|
||||
|
||||
#import "Logging.h"
|
||||
#import "Utilities.h"
|
||||
#import "Enumerator.h"
|
||||
#import "OverSightXPC.h"
|
||||
#import "../Shared/Utilities.h"
|
||||
|
||||
|
||||
@implementation OverSightXPC
|
||||
|
||||
|
|
|
@ -12,10 +12,9 @@
|
|||
#import <bsm/libbsm.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "../Shared/Exception.h"
|
||||
#import "../Shared/XPCProtocol.h"
|
||||
#import "../Shared/Logging.h"
|
||||
|
||||
#import "Logging.h"
|
||||
#import "Exception.h"
|
||||
#import "XPCProtocol.h"
|
||||
#import "OverSightXPC.h"
|
||||
|
||||
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
//TODO: test final/with page
|
||||
#define PRODUCT_VERSION_URL @"https://objective-see.com/products/versions/oversight.json"
|
||||
|
||||
//frame shift
|
||||
// ->for status msg to avoid activity indicator
|
||||
#define FRAME_SHIFT 45
|
||||
|
||||
//OS version x
|
||||
#define OS_MAJOR_VERSION_X 10
|
||||
|
||||
|
@ -88,4 +84,7 @@
|
|||
//path to pkill
|
||||
#define PKILL @"/usr/bin/pkill"
|
||||
|
||||
//path to facetime
|
||||
#define FACE_TIME @"/Applications/FaceTime.app/Contents/MacOS/FaceTime"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
/* FUNCTIONS */
|
||||
|
||||
//get OS version
|
||||
NSDictionary* getOSVersion();
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion();
|
||||
|
@ -52,6 +55,10 @@ NSString* getProcessPath(pid_t pid);
|
|||
// ->get the name of the process
|
||||
NSString* getProcessName(pid_t pid);
|
||||
|
||||
//given a process name
|
||||
// ->get the (first) instance of that process
|
||||
pid_t getProcessID(NSString* processName);
|
||||
|
||||
//wait until a window is non nil
|
||||
// ->then make it modal
|
||||
void makeModal(NSWindowController* windowController);
|
||||
|
|
|
@ -20,6 +20,55 @@
|
|||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
//get OS version
|
||||
NSDictionary* getOSVersion()
|
||||
{
|
||||
//os version info
|
||||
NSMutableDictionary* osVersionInfo = nil;
|
||||
|
||||
//major v
|
||||
SInt32 majorVersion = 0;
|
||||
|
||||
//minor v
|
||||
SInt32 minorVersion = 0;
|
||||
|
||||
//alloc dictionary
|
||||
osVersionInfo = [NSMutableDictionary dictionary];
|
||||
|
||||
//get major version
|
||||
if(STATUS_SUCCESS != Gestalt(gestaltSystemVersionMajor, &majorVersion))
|
||||
{
|
||||
//reset
|
||||
osVersionInfo = nil;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//get minor version
|
||||
if(STATUS_SUCCESS != Gestalt(gestaltSystemVersionMinor, &minorVersion))
|
||||
{
|
||||
//reset
|
||||
osVersionInfo = nil;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set major version
|
||||
osVersionInfo[@"majorVersion"] = [NSNumber numberWithInteger:majorVersion];
|
||||
|
||||
//set minor version
|
||||
osVersionInfo[@"minorVersion"] = [NSNumber numberWithInteger:minorVersion];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return osVersionInfo;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion()
|
||||
|
@ -178,8 +227,6 @@ BOOL setFilePermissions(NSString* file, int permissions, BOOL recursive)
|
|||
//set file permissions on each
|
||||
for(NSURL* currentFile in enumerator)
|
||||
{
|
||||
NSLog(@"current file: %@", currentFile.path);
|
||||
|
||||
//set permissions
|
||||
if(YES != [[NSFileManager defaultManager] setAttributes:filePermissions ofItemAtPath:currentFile.path error:&error])
|
||||
{
|
||||
|
@ -459,6 +506,81 @@ bail:
|
|||
return processName;
|
||||
}
|
||||
|
||||
//given a process name
|
||||
// ->get the (first) instance of that process
|
||||
pid_t getProcessID(NSString* processName)
|
||||
{
|
||||
//status
|
||||
int status = -1;
|
||||
|
||||
//process id
|
||||
pid_t processID = -1;
|
||||
|
||||
//# of procs
|
||||
int numberOfProcesses = 0;
|
||||
|
||||
//array of pids
|
||||
pid_t* pids = NULL;
|
||||
|
||||
//get # of procs
|
||||
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
|
||||
|
||||
//alloc buffer for pids
|
||||
pids = calloc(numberOfProcesses, sizeof(pid_t));
|
||||
|
||||
//get list of pids
|
||||
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
|
||||
if(status < 0)
|
||||
{
|
||||
//err
|
||||
//syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: proc_listpids() failed with %d", status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//iterate over all pids
|
||||
// ->get name for each
|
||||
for(int i = 0; i < numberOfProcesses; ++i)
|
||||
{
|
||||
//skip blank pids
|
||||
if(0 == pids[i])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//skip if name doesn't match
|
||||
if(YES != [processName isEqualToString:getProcessName(pids[i])])
|
||||
{
|
||||
//next
|
||||
continue;
|
||||
}
|
||||
|
||||
//got match
|
||||
processID = pids[i];
|
||||
|
||||
//exit loop
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free buffer
|
||||
if(NULL != pids)
|
||||
{
|
||||
//free
|
||||
free(pids);
|
||||
|
||||
//reset
|
||||
pids = NULL;
|
||||
}
|
||||
|
||||
return processID;
|
||||
}
|
||||
|
||||
//determine if there is a new version
|
||||
// -1, YES or NO
|
||||
NSInteger isNewVersion(NSMutableString* versionString)
|
||||
|
@ -575,3 +697,4 @@ void makeModal(NSWindowController* windowController)
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue