improved actions, update logic, and uninstaller

Actions now populated by browse pane (ensures path/item is valid)

Update logic now supports OS checking (min supported OS version)

Uninstaller resets/removes preferences file
This commit is contained in:
Patrick Wardle 2022-11-05 13:29:51 -10:00
parent 58c78d24c6
commit aefbf06fd3
7 changed files with 246 additions and 115 deletions

View File

@ -371,21 +371,28 @@ bail:
switch (result)
{
//error
case -1:
case Update_Error:
//err msg
os_log_error(logHandle, "ERROR: update check failed");
break;
//no updates
case 0:
case Update_None:
//dbg msg
os_log_debug(logHandle, "no updates available");
break;
//this version of macOS, not supported
case Update_NotSupported:
//dbg msg
os_log_debug(logHandle, "update available, but not for this version of macOS");
break;
//new version
case 1:
case Update_Available:
//dbg msg
os_log_debug(logHandle, "a new version (%@) is available", newVersion);

View File

@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PrefsWindowController">
<connections>
<outlet property="actionView" destination="Jpg-nC-dWd" id="WHf-rQ-BXU"/>
<outlet property="browseButton" destination="gVP-Ih-dFA" id="j7F-V3-hEq"/>
<outlet property="executeArgsButton" destination="YqA-7j-gYp" id="tbC-AW-etO"/>
<outlet property="executePath" destination="z32-0s-dpb" id="HAL-Mg-ygB"/>
<outlet property="modesView" destination="K6i-xr-27e" id="DOb-L3-eeR"/>
@ -25,7 +26,7 @@
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="196" y="240" width="600" height="365"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="875"/>
<rect key="screenRect" x="0.0" y="0.0" width="3440" height="1415"/>
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="600" height="365"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -41,21 +42,21 @@
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="J66-tT-qAf"/>
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="6nW-4K-zf4"/>
<toolbarItem implicitItemIdentifier="3F78D487-BA4D-4E1B-8FC6-A844D292C69B" explicitItemIdentifier="mode" label="mode" paletteLabel="mode" image="PrefsMode" selectable="YES" id="k0w-Oi-kwd" userLabel="mode">
<toolbarItem implicitItemIdentifier="3F78D487-BA4D-4E1B-8FC6-A844D292C69B" explicitItemIdentifier="mode" label="Mode" paletteLabel="Mode" image="PrefsMode" selectable="YES" id="k0w-Oi-kwd" userLabel="mode">
<size key="minSize" width="22" height="22"/>
<size key="maxSize" width="22" height="22"/>
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="5Bh-RO-nSN"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="F54FFA8D-5F3A-4A92-BCB5-F0200A133E49" explicitItemIdentifier="action" label="action" paletteLabel="action" tag="1" image="PrefsAction" selectable="YES" id="gji-hP-t04">
<toolbarItem implicitItemIdentifier="F54FFA8D-5F3A-4A92-BCB5-F0200A133E49" explicitItemIdentifier="action" label="Action" paletteLabel="Action" tag="1" image="PrefsAction" selectable="YES" id="gji-hP-t04">
<size key="minSize" width="22" height="22"/>
<size key="maxSize" width="22" height="22"/>
<connections>
<action selector="toolbarButtonHandler:" target="-2" id="c6F-yA-Qd8"/>
</connections>
</toolbarItem>
<toolbarItem implicitItemIdentifier="384D69C6-2351-417E-9C93-B14039FE440F" explicitItemIdentifier="update" label="update" paletteLabel="update" tag="2" image="PrefsUpdate" selectable="YES" id="rrF-xj-cXp">
<toolbarItem implicitItemIdentifier="384D69C6-2351-417E-9C93-B14039FE440F" explicitItemIdentifier="update" label="Update" paletteLabel="Update" tag="2" image="PrefsUpdate" selectable="YES" id="rrF-xj-cXp">
<size key="minSize" width="22" height="22"/>
<size key="maxSize" width="22" height="22"/>
<connections>
@ -197,25 +198,16 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="117" translatesAutoresizingMaskIntoConstraints="NO" id="8Tb-Ih-SsC">
<rect key="frame" x="72" y="224" width="114" height="15"/>
<rect key="frame" x="72" y="224" width="59" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Execute Action" id="ncJ-bF-dAA">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Execute" id="ncJ-bF-dAA">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="GyI-og-F35">
<rect key="frame" x="72" y="202" width="318" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Perform an action (script, binary, etc)." id="bky-MW-yBn">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button fixedFrame="YES" tag="5" translatesAutoresizingMaskIntoConstraints="NO" id="YqA-7j-gYp">
<rect key="frame" x="39" y="161" width="29" height="18"/>
<rect key="frame" x="39" y="151" width="29" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="egX-c0-Flf">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -226,7 +218,7 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dH0-Xi-Qnd">
<rect key="frame" x="72" y="162" width="114" height="15"/>
<rect key="frame" x="72" y="152" width="114" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Pass Arguments" id="WL4-fV-4Wq">
<font key="font" size="13" name="Menlo-Bold"/>
@ -235,7 +227,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="GP0-UX-66J">
<rect key="frame" x="72" y="98" width="427" height="60"/>
<rect key="frame" x="72" y="82" width="427" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="7Ah-kZ-gGe">
<font key="font" size="13" name="Menlo-Regular"/>
@ -245,9 +237,9 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="382" translatesAutoresizingMaskIntoConstraints="NO" id="z32-0s-dpb">
<rect key="frame" x="198" y="221" width="382" height="20"/>
<rect key="frame" x="143" y="221" width="437" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="path" drawsBackground="YES" id="Oe0-3Y-Srk">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" state="on" borderStyle="bezel" placeholderString="path" drawsBackground="YES" id="Oe0-3Y-Srk">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -256,7 +248,35 @@
<outlet property="delegate" destination="-2" id="dSg-PZ-Igl"/>
</connections>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gVP-Ih-dFA">
<rect key="frame" x="498" y="187" width="89" height="33"/>
<constraints>
<constraint firstAttribute="width" constant="75" id="0GJ-HY-4cb"/>
<constraint firstAttribute="height" constant="21" id="J0H-v3-Re0"/>
</constraints>
<buttonCell key="cell" type="push" title="Browse" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BTl-QV-9GT">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
</buttonCell>
<connections>
<action selector="browseButtonHandler:" target="-2" id="gXE-0h-DRz"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="GyI-og-F35">
<rect key="frame" x="72" y="181" width="427" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Execute a script or binary when an event is detected." id="bky-MW-yBn">
<font key="font" size="13" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="gVP-Ih-dFA" secondAttribute="trailing" constant="20" symbolic="YES" id="CvO-h8-LQr"/>
<constraint firstItem="gVP-Ih-dFA" firstAttribute="top" secondItem="Jpg-nC-dWd" secondAttribute="top" constant="60" id="nxN-h0-hTd"/>
<constraint firstAttribute="trailing" secondItem="gVP-Ih-dFA" secondAttribute="trailing" constant="20" symbolic="YES" id="wdb-4c-5GF"/>
</constraints>
<point key="canvasLocation" x="-166" y="738.5"/>
</customView>
<customView id="1OV-sl-cSe" userLabel="Update">
@ -303,21 +323,21 @@
<action selector="check4Update:" target="-2" id="GJb-mB-UIz"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Oe2-Ye-1s6">
<rect key="frame" x="201" y="101" width="216" height="34"/>
<progressIndicator wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" bezeled="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="o0T-ra-4H0">
<rect key="frame" x="378" y="145" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="5gt-xh-Ti5">
</progressIndicator>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Oe2-Ye-1s6">
<rect key="frame" x="118" y="60" width="383" height="74"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" id="5gt-xh-Ti5">
<font key="font" size="13" name="Menlo-Bold"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<progressIndicator wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" displayedWhenStopped="NO" bezeled="NO" indeterminate="YES" controlSize="small" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="o0T-ra-4H0">
<rect key="frame" x="378" y="145" width="16" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
</subviews>
<point key="canvasLocation" x="694" y="709"/>
<point key="canvasLocation" x="694" y="708.5"/>
</customView>
</objects>
<resources>

View File

@ -47,6 +47,9 @@
//path to action
@property (weak) IBOutlet NSTextField *executePath;
//browse button
@property (weak) IBOutlet NSButton *browseButton;
//execute args button
@property (weak) IBOutlet NSButton *executeArgsButton;

View File

@ -97,9 +97,9 @@ extern os_log_t logHandle;
break;
//modes
//actions
case TOOLBAR_ACTION:
{
//set view
view = self.actionView;
@ -112,7 +112,7 @@ extern os_log_t logHandle;
//set
self.executePath.stringValue = [NSUserDefaults.standardUserDefaults objectForKey:PREF_EXECUTE_PATH];
}
//set state of 'execute action' to match
self.executePath.enabled = [NSUserDefaults.standardUserDefaults boolForKey:PREF_EXECUTE_ACTION];
@ -121,9 +121,19 @@ extern os_log_t logHandle;
//set state of 'execute action' to match
self.executeArgsButton.enabled = [NSUserDefaults.standardUserDefaults boolForKey:PREF_EXECUTE_ACTION];
break;
//make 'Browse' button first responder
// calling this without a timeout, sometimes fails :/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (100 * NSEC_PER_MSEC)), dispatch_get_main_queue(),
^{
//set first responder
[self.window makeFirstResponder:self.browseButton];
});
break;
}
//update
case TOOLBAR_UPDATE:
@ -153,26 +163,6 @@ bail:
return;
}
//automatically called when 'enter' is hit
// save values that were entered in text field
-(void)controlTextDidEndEditing:(NSNotification *)notification
{
//execute path?
if([notification object] != self.executePath)
{
//bail
goto bail;
}
//save & sync
[NSUserDefaults.standardUserDefaults setObject:self.executePath.stringValue forKey:PREF_EXECUTE_PATH];
[NSUserDefaults.standardUserDefaults synchronize];
bail:
return;
}
//invoked when user toggles button
// update preferences for that button
-(IBAction)togglePreference:(id)sender
@ -237,6 +227,15 @@ bail:
//set path field state to match
self.executeArgsButton.enabled = state;
//enabled, but no path?
// launch 'browse' pane for user to select
if( (NSControlStateValueOn == state) &&
(0 == self.executePath.stringValue.length) )
{
//show 'browse'
[self browseButtonHandler:nil];
}
break;
}
@ -277,6 +276,7 @@ bail:
return;
}
//TODO: supported OS
//'check for update' button handler
-(IBAction)check4Update:(id)sender
{
@ -308,7 +308,7 @@ bail:
}
//process update response
// error, no update, update/new version
// error, no update, update not compatible, update/new version
-(void)updateResponse:(NSInteger)result newVersion:(NSString*)newVersion
{
//re-enable button
@ -320,15 +320,15 @@ bail:
switch(result)
{
//error
case -1:
case Update_Error:
//set label
self.updateLabel.stringValue = @"error: update check failed";
self.updateLabel.stringValue = @"Error: update check failed";
break;
//no updates
case 0:
case Update_None:
//dbg msg
os_log_debug(logHandle, "no updates available");
@ -337,10 +337,20 @@ bail:
self.updateLabel.stringValue = [NSString stringWithFormat:@"Installed version (%@),\r\nis the latest.", getAppVersion()];
break;
//this version of macOS, not supported
case Update_NotSupported:
//dbg msg
os_log_debug(logHandle, "update available, but not for this version of macOS");
//set label
self.updateLabel.stringValue = [NSString stringWithFormat:@"Update available, but isn't supported on macOS %ld.%ld", NSProcessInfo.processInfo.operatingSystemVersion.majorVersion, NSProcessInfo.processInfo.operatingSystemVersion.minorVersion];
break;
//new version
case 1:
case Update_Available:
//dbg msg
os_log_debug(logHandle, "a new version (%@) is available", newVersion);
@ -391,4 +401,54 @@ bail:
return;
}
//'browse' button handler
// open a panel for user to select file
-(IBAction)browseButtonHandler:(id)sender
{
//'browse' panel
NSOpenPanel *panel = nil;
//response to 'browse' panel
NSInteger response = 0;
//init panel
panel = [NSOpenPanel openPanel];
//allow files
panel.canChooseFiles = YES;
//don't allow directories
panel.canChooseDirectories = NO;
//disable multiple selections
panel.allowsMultipleSelection = NO;
//can open app bundles
panel.treatsFilePackagesAsDirectories = YES;
//start in user's home directory
panel.directoryURL = [NSURL fileURLWithPath:NSHomeDirectory()];
//show it
response = [panel runModal];
//ignore cancel
if(NSModalResponseCancel == response)
{
//bail
goto bail;
}
//set path in ui
self.executePath.stringValue = panel.URL.path;
//save path & sync
[NSUserDefaults.standardUserDefaults setObject:self.executePath.stringValue forKey:PREF_EXECUTE_PATH];
[NSUserDefaults.standardUserDefaults synchronize];
bail:
return;
}
@end

View File

@ -25,25 +25,66 @@ extern os_log_t logHandle;
// ->will invoke app delegate method to update UI when check completes
-(void)checkForUpdate:(void (^)(NSUInteger result, NSString* latestVersion))completionHandler
{
//latest version
__block NSString* latestVersion = nil;
//info
__block NSDictionary* productInfo = nil;
//result
__block NSInteger result = -1;
__block NSInteger result = Update_None;
//get latest version in background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//grab latest version
latestVersion = [self getLatestVersion];
if(nil != latestVersion)
//latest version
NSString* latestVersion = nil;
//supported OS
NSOperatingSystemVersion supportedOS = {0};
//get product info
productInfo = [self getProductInfo:PRODUCT_NAME];
if(nil == productInfo)
{
//check
result = (NSOrderedAscending == [getAppVersion() compare:latestVersion options:NSNumericSearch]);
//err msg
os_log_error(logHandle, "ERROR: failed retrieve product info (for update check) from %{public}@", PRODUCT_VERSIONS_URL);
//error
result = Update_Error;
}
//got remote product info
// check supported OS and latest version
else
{
//init supported OS
supportedOS.majorVersion = [productInfo[SUPPORTED_OS_MAJOR] intValue];
supportedOS.minorVersion = [productInfo[SUPPORTED_OS_MINOR] intValue];
//extract latest version
latestVersion = productInfo[LATEST_VERSION];
//supported version of macOS?
if(YES != [NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:supportedOS])
{
//dbg msg
os_log_debug(logHandle, "latest version requires macOS %ld.%ld ...but current macOS is %{public}@", supportedOS.majorVersion, supportedOS.minorVersion, NSProcessInfo.processInfo.operatingSystemVersionString);
//unsupported
result = Update_NotSupported;
}
//latest version is new(er)?
else if(nil != latestVersion)
{
//check app version and latest version
if(NSOrderedAscending == [getAppVersion() compare:latestVersion options:NSNumericSearch])
{
//new update!
result = Update_Available;
}
}
}
//invoke app delegate method
// ->will update UI/show popup if necessart
// will update UI/show popup if necessary
dispatch_async(dispatch_get_main_queue(),
^{
completionHandler(result, latestVersion);
@ -53,53 +94,27 @@ extern os_log_t logHandle;
return;
}
//query interwebz to get latest version
-(NSString*)getLatestVersion
//read JSON file w/ products
// return dictionary w/ info about this product
-(NSDictionary*)getProductInfo:(NSString*)product
{
//product version(s) data
NSData* productsVersionData = nil;
NSDictionary* products = nil;
//version dictionary
NSDictionary* productsVersionDictionary = nil;
//latest version
NSString* latestVersion = nil;
//get version from remote URL
productsVersionData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:PRODUCT_VERSIONS_URL]];
if(nil == productsVersionData)
{
//bail
goto bail;
}
//convert JSON to dictionary
// ->wrap as may throw exception
//get json file (products) from remote URL
@try
{
//convert
productsVersionDictionary = [NSJSONSerialization JSONObjectWithData:productsVersionData options:0 error:nil];
if(nil == productsVersionDictionary)
{
//bail
goto bail;
}
products = [NSJSONSerialization JSONObjectWithData:[[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:PRODUCT_VERSIONS_URL]] options:0 error:nil];
}
@catch(NSException* exception)
{
//bail
goto bail;
;
}
//extract latest version
latestVersion = [[productsVersionDictionary objectForKey:@"OverSight"] objectForKey:@"version"];
//dbg msg
os_log_debug(logHandle, "latest version: %{public}@", latestVersion);
bail:
return latestVersion;
return products[product];
}
@end

View File

@ -441,6 +441,9 @@ bail:
//path to preferences dir
NSString* prefsDirectory = nil;
//preferences file
NSString* preferences = nil;
//path to login item
NSURL* loginItem = nil;
@ -522,14 +525,25 @@ bail:
}
//full?
// delete prefs / allowed items
// delete preferences
if(YES == full)
{
//dbg msg
os_log_debug(logHandle, "removing preferences/allowed items");
//init prefs file
preferences = [NSHomeDirectory() stringByAppendingPathComponent:PREFERENCES];
//delete prefs via defaults
execTask(DEFAULTS, @[@"delete", @BUNDLE_ID], YES, NO);
//dbg msg
os_log_debug(logHandle, "deleting preferences");
//delete preferences file
// and if this fails, reset
if(YES != [NSFileManager.defaultManager removeItemAtPath:preferences error:nil])
{
//dbg msg
os_log_debug(logHandle, "deleting failed, will reset preferences");
//reset
[NSUserDefaults.standardUserDefaults removePersistentDomainForName:@BUNDLE_ID];
}
}
//always remove application

View File

@ -70,6 +70,15 @@
//error(s) url
#define ERRORS_URL @"https://objective-see.com/errors.html"
//os major
#define SUPPORTED_OS_MAJOR @"OSMajor"
//os minor
#define SUPPORTED_OS_MINOR @"OSMinor"
//latest version
#define LATEST_VERSION @"version"
//close category
#define CATEGORY_CLOSE @"close"
@ -110,6 +119,9 @@
//add rule, allow
#define BUTTON_ALLOW 1
//preferences file
#define PREFERENCES @"/Library/Preferences/com.objective-see.oversight.plist"
//prefs
// disabled status
#define PREF_IS_DISABLED @"disabled"
@ -198,9 +210,6 @@
//path to launchctl
#define LAUNCHCTL @"/bin/launchctl"
//path to defaults
#define DEFAULTS @"/usr/bin/defaults"
//path to kill all
#define KILL_ALL @"/usr/bin/killall"
@ -237,6 +246,9 @@
//av devices
typedef enum {Device_Camera, Device_Microphone} AVDevice;
//updates
typedef enum {Update_Error, Update_None, Update_NotSupported, Update_Available} UpdateStatus;
//log levels
typedef enum {Log_Level_Default, Log_Level_Info, Log_Level_Debug} LogLevels;