-try/catch around JSON output
 -switched to 'UUIDString' for <10.10 compatibility
 -update check!
This commit is contained in:
Patrick Wardle
2018-11-23 12:04:24 -10:00
parent 56ef862118
commit be45161024
17 changed files with 589 additions and 185 deletions
+4
View File
@@ -15,6 +15,7 @@
#import "ItemTableController.h"
#import "AboutWindowController.h"
#import "PrefsWindowController.h"
#import "UpdateWindowController.h"
#import "CategoryTableController.h"
#import "ResultsWindowController.h"
@@ -107,6 +108,9 @@ extern Filter* itemFilter;
//constraint for status text
@property (weak) IBOutlet NSLayoutConstraint *statusTextConstraint;
//update window controller
@property(nonatomic, retain)UpdateWindowController* updateWindowController;
/* METHODS */
+85 -5
View File
@@ -4,6 +4,7 @@
//
#import "Consts.h"
#import "Update.h"
#import "Utilities.h"
#import "PluginBase.h"
#import "AppDelegate.h"
@@ -30,6 +31,7 @@
@synthesize aboutWindowController;
@synthesize prefsWindowController;
@synthesize showPreferencesButton;
@synthesize updateWindowController;
@synthesize categoryTableController;
@synthesize resultsWindowController;
@@ -83,13 +85,9 @@
exit(0);
}
//kick off thread to begin enumerating shared objects
// ->this takes awhile, so do it now/first!
[sharedItemEnumerator start];
//load defaults
defaults = [NSUserDefaults standardUserDefaults];
//first time run?
// show thanks to friends window!
if(YES != [defaults boolForKey:NOT_FIRST_TIME])
@@ -107,7 +105,19 @@
[self.friends close];
});
}
//check for update
// unless user has turn off via prefs
if(YES != [defaults boolForKey:PREF_DISABLE_UPDATE_CHECK])
{
//check
[self check4Update];
}
//kick off thread to begin enumerating shared objects
// ->this takes awhile, so do it now/first!
[sharedItemEnumerator start];
//instantiate all plugins objects
self.plugins = [self instantiatePlugins];
@@ -1291,4 +1301,74 @@
return bEnabled;
}
//call into Update obj
// check to see if there an update?
-(void)check4Update
{
//update obj
Update* update = nil;
//init update obj
update = [[Update alloc] init];
//check for update
// ->'updateResponse newVersion:' method will be called when check is done
[update checkForUpdate:^(NSUInteger result, NSString* newVersion) {
//process response
[self updateResponse:result newVersion:newVersion];
}];
return;
}
//process update response
// error, no update, update/new version
-(void)updateResponse:(NSInteger)result newVersion:(NSString*)newVersion
{
//handle response
// new version, show popup
switch (result)
{
//error
case -1:
break;
//no updates
case 0:
break;
//new version
case 1:
//alloc update window
updateWindowController = [[UpdateWindowController alloc] initWithWindowNibName:@"UpdateWindow"];
//configure
[self.updateWindowController configure:[NSString stringWithFormat:@"a new version (%@) is available!", newVersion] buttonTitle:@"Update"];
//center window
[[self.updateWindowController window] center];
//show it
[self.updateWindowController showWindow:self];
//invoke function in background that will make window modal
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//make modal
makeModal(self.updateWindowController);
});
break;
}
return;
}
@end
+7
View File
@@ -42,6 +42,10 @@ static NSString * const SUPPORTED_PLUGINS[] = {@"AuthorizationPlugins", @"Browse
// ->save output
#define PREF_SAVE_OUTPUT @"saveOutput"
//prefs
// ->no updates
#define PREF_DISABLE_UPDATE_CHECK @"noUpdateCheck"
//disabled state
#define STATE_DISABLED 0
@@ -279,4 +283,7 @@ enum Signer{None, Apple, AppStore, DevID, AdHoc};
//product url
#define PRODUCT_URL @"https://objective-see.com/products/knockknock.html"
//product version url
#define PRODUCT_VERSIONS_URL @"https://objective-see.com/products.json"
#endif
+25
View File
@@ -30,6 +30,9 @@
CD24F077219DF3DB0081B0E5 /* Signing.m in Sources */ = {isa = PBXBuildFile; fileRef = CD24F075219DF3DA0081B0E5 /* Signing.m */; };
CD2B613320675EEC00BF72E9 /* EventRules.m in Sources */ = {isa = PBXBuildFile; fileRef = CD2B611220675EEB00BF72E9 /* EventRules.m */; };
CD2B61442067656200BF72E9 /* eventRulesIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD2B61432067656200BF72E9 /* eventRulesIcon.png */; };
CD2F219F21A8A73100F67A83 /* Update.m in Sources */ = {isa = PBXBuildFile; fileRef = CD2F219E21A8A73100F67A83 /* Update.m */; };
CD2F21A121A8A7D100F67A83 /* UpdateWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD2F21A021A8A7D000F67A83 /* UpdateWindow.xib */; };
CD2F21A421A8A7E300F67A83 /* UpdateWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD2F21A321A8A7E300F67A83 /* UpdateWindowController.m */; };
CD585494219FE61D00A438B0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD585493219FE61D00A438B0 /* Assets.xcassets */; };
CD5854D321A5FADD00A438B0 /* patrons.txt in Resources */ = {isa = PBXBuildFile; fileRef = CD5854D221A5FADD00A438B0 /* patrons.txt */; };
CD5854D521A60B1000A438B0 /* PlistWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD5854D421A60B0F00A438B0 /* PlistWindow.xib */; };
@@ -172,6 +175,11 @@
CD2B611220675EEB00BF72E9 /* EventRules.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EventRules.m; path = Plugins/EventRules.m; sourceTree = "<group>"; };
CD2B611320675EEB00BF72E9 /* EventRules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EventRules.h; path = Plugins/EventRules.h; sourceTree = "<group>"; };
CD2B61432067656200BF72E9 /* eventRulesIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = eventRulesIcon.png; path = images/eventRulesIcon.png; sourceTree = SOURCE_ROOT; };
CD2F219D21A8A73000F67A83 /* Update.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Update.h; sourceTree = SOURCE_ROOT; };
CD2F219E21A8A73100F67A83 /* Update.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Update.m; sourceTree = SOURCE_ROOT; };
CD2F21A021A8A7D000F67A83 /* UpdateWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = UpdateWindow.xib; path = UI/UpdateWindow.xib; sourceTree = "<group>"; };
CD2F21A221A8A7E300F67A83 /* UpdateWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateWindowController.h; sourceTree = "<group>"; };
CD2F21A321A8A7E300F67A83 /* UpdateWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UpdateWindowController.m; sourceTree = "<group>"; };
CD585493219FE61D00A438B0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = SOURCE_ROOT; };
CD5854D221A5FADD00A438B0 /* patrons.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = patrons.txt; sourceTree = SOURCE_ROOT; };
CD5854D421A60B0F00A438B0 /* PlistWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = PlistWindow.xib; path = UI/PlistWindow.xib; sourceTree = "<group>"; };
@@ -376,6 +384,8 @@
1D21BC54172AF43D009D1CFD /* KnockKnock */ = {
isa = PBXGroup;
children = (
CD2F219D21A8A73000F67A83 /* Update.h */,
CD2F219E21A8A73100F67A83 /* Update.m */,
CDF08CC71AC4C678009B3423 /* PrefsWindowController.h */,
CDF08CC81AC4C678009B3423 /* PrefsWindowController.m */,
CD5854D621A60B2000A438B0 /* PlistWindowController.h */,
@@ -469,6 +479,8 @@
isa = PBXGroup;
children = (
CD02195F1AD39A83005148A2 /* ResultsWindowController.h */,
CD2F21A221A8A7E300F67A83 /* UpdateWindowController.h */,
CD2F21A321A8A7E300F67A83 /* UpdateWindowController.m */,
CD0219601AD39A83005148A2 /* ResultsWindowController.m */,
CD0219511AD34D9A005148A2 /* AboutWindowController.h */,
CD0219521AD34D9A005148A2 /* AboutWindowController.m */,
@@ -550,6 +562,7 @@
CDA81E621AA020E8009790E2 /* UI */ = {
isa = PBXGroup;
children = (
CD2F21A021A8A7D000F67A83 /* UpdateWindow.xib */,
CD5854D421A60B0F00A438B0 /* PlistWindow.xib */,
CD02195D1AD39A74005148A2 /* ResultsWindow.xib */,
CD02194D1AD34D8B005148A2 /* AboutWindow.xib */,
@@ -616,6 +629,11 @@
1D21BC4A172AF43D009D1CFD = {
DevelopmentTeam = VBG97UB4TA;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.HardenedRuntime = {
enabled = 1;
};
};
};
};
};
@@ -695,6 +713,7 @@
CDBE491F1B5B46040031FC22 /* logInOutIcon.png in Resources */,
CDA81D721A95B4E9009790E2 /* virus.png in Resources */,
CDA81DC91A9960A3009790E2 /* info.png in Resources */,
CD2F21A121A8A7D100F67A83 /* UpdateWindow.xib in Resources */,
CDA81D6E1A95B4E9009790E2 /* startScan.png in Resources */,
CD02194F1AD34D8B005148A2 /* AboutWindow.xib in Resources */,
CDA81DCA1A9960A3009790E2 /* infoBG.png in Resources */,
@@ -732,8 +751,10 @@
CDA81E001A9A7D26009790E2 /* File.m in Sources */,
CD6BBBF01B52032D00506D0D /* NSApplicationKeyEvents.m in Sources */,
CDA81D4F1A95B492009790E2 /* AppDelegate.m in Sources */,
CD2F219F21A8A73100F67A83 /* Update.m in Sources */,
CDA81D5E1A95B4B4009790E2 /* main.m in Sources */,
CD5854D821A60B2100A438B0 /* PlistWindowController.m in Sources */,
CD2F21A421A8A7E300F67A83 /* UpdateWindowController.m in Sources */,
7DE2FE2E1D3F30BE006C1438 /* Extensions.m in Sources */,
7DE29CA41CA7BC5600DFA6A6 /* StartupScripts.m in Sources */,
CD6975061B02F60400CE819B /* RFOverlayScroller.m in Sources */,
@@ -879,6 +900,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = VBG97UB4TA;
ENABLE_HARDENED_RUNTIME = YES;
@@ -892,6 +914,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = KnockKnock;
PROVISIONING_PROFILE_SPECIFIER = "";
WRAPPER_EXTENSION = app;
};
name = Debug;
@@ -902,6 +925,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = VBG97UB4TA;
ENABLE_HARDENED_RUNTIME = YES;
@@ -915,6 +939,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = KnockKnock;
PROVISIONING_PROFILE_SPECIFIER = "";
WRAPPER_EXTENSION = app;
};
name = Release;
@@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
scope = "0"
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Plugins/DylibProxies.m"
timestampString = "564556800.5881079"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "189"
endingLineNumber = "189"
landmarkName = "-enumLoadedDylibs"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ItemTableController.m"
timestampString = "564556800.588191"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "136"
endingLineNumber = "136"
landmarkName = "-tableView:viewForTableColumn:row:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ItemTableController.m"
timestampString = "564556800.588248"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "251"
endingLineNumber = "251"
landmarkName = "-tableView:viewForTableColumn:row:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ItemTableController.m"
timestampString = "564556800.588299"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "254"
endingLineNumber = "254"
landmarkName = "-tableView:viewForTableColumn:row:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ItemTableController.m"
timestampString = "564556800.5883451"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "886"
endingLineNumber = "886"
landmarkName = "getCodeSigningIcon"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "kkRowCell.m"
timestampString = "564208966.188289"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "22"
endingLineNumber = "22"
landmarkName = "-setBackgroundStyle:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ResultsWindowController.m"
timestampString = "564298058.888056"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "32"
endingLineNumber = "32"
landmarkName = "-windowDidLoad"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "main.m"
timestampString = "564556800.588663"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "222"
endingLineNumber = "222"
landmarkName = "cmdlineScan"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
@@ -66,10 +66,6 @@
argument = "-whosthere"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-pretty"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
+6
View File
@@ -27,6 +27,9 @@
//button for filtering out OS componets
@property (weak) IBOutlet NSButton* showTrustedItemsBtn;
//button disabling update check
@property (weak) IBOutlet NSButton *disableUpdateCheckBtn;
//button for disabling talking to VT
@property (weak) IBOutlet NSButton* disableVTQueriesBtn;
@@ -39,6 +42,9 @@
//filter out OS/known items
@property BOOL showTrustedItems;
//no update checks
@property BOOL disableUpdateCheck;
//disable talking to VT
@property BOOL disableVTQueries;
+27 -2
View File
@@ -19,6 +19,7 @@
@synthesize shouldSaveNow;
@synthesize disableVTQueries;
@synthesize showTrustedItems;
@synthesize disableUpdateCheck;
//automatically called when nib is loaded
@@ -54,6 +55,13 @@
self.showTrustedItemsBtn.state = STATE_ENABLED;
}
//check if 'disable update check' button should be selected
if(YES == self.disableUpdateCheck)
{
//set
self.disableUpdateCheckBtn.state = STATE_ENABLED;
}
//check if 'disable vt queries' button should be selected
if(YES == self.disableVTQueries)
{
@@ -76,11 +84,11 @@
}
//register default prefs
// ->only used if user hasn't set any
// only used if user hasn't set any
-(void)registerDefaults
{
//set defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:@{PREF_SHOW_TRUSTED_ITEMS:@NO, PREF_DISABLE_VT_QUERIRES:@NO, PREF_SAVE_OUTPUT:@NO}];
[[NSUserDefaults standardUserDefaults] registerDefaults:@{PREF_SHOW_TRUSTED_ITEMS:@NO, PREF_DISABLE_UPDATE_CHECK:@NO, PREF_DISABLE_VT_QUERIRES:@NO, PREF_SAVE_OUTPUT:@NO}];
return;
}
@@ -105,6 +113,13 @@
self.showTrustedItems = [defaults boolForKey:PREF_SHOW_TRUSTED_ITEMS];
}
//load 'disable update check'
if(nil != [defaults objectForKey:PREF_DISABLE_UPDATE_CHECK])
{
//save
self.disableUpdateCheck = [defaults boolForKey:PREF_DISABLE_UPDATE_CHECK];
}
//load 'disable vt queries'
if(nil != [defaults objectForKey:PREF_DISABLE_VT_QUERIRES])
{
@@ -129,6 +144,9 @@
//save current state of 'include os/trusted' components
self.showTrustedItems = self.showTrustedItemsBtn.state;
//save current state of 'disable update checks'
self.disableUpdateCheck = self.disableUpdateCheckBtn.state;
//save current state of 'disable VT'
self.disableVTQueries = self.disableVTQueriesBtn.state;
@@ -163,6 +181,7 @@
//first, any prefs changed, a 'save' set
// ->set 'save now' flag
if( ((self.showTrustedItems != self.showTrustedItemsBtn.state) ||
(self.disableUpdateCheck != self.disableUpdateCheckBtn.state) ||
(self.disableVTQueries != self.disableVTQueriesBtn.state) ||
(self.saveOutput != self.saveOutputBtn.state) ) &&
(YES == self.saveOutputBtn.state) )
@@ -180,6 +199,9 @@
//save hiding OS components flag
self.showTrustedItems = self.showTrustedItemsBtn.state;
//save current state of 'disable update checks'
self.disableUpdateCheck = self.disableUpdateCheckBtn.state;
//save disabling VT flag
self.disableVTQueries = self.disableVTQueriesBtn.state;
@@ -189,6 +211,9 @@
//save 'show trusted items'
[defaults setBool:self.showTrustedItems forKey:PREF_SHOW_TRUSTED_ITEMS];
//save 'disable update checks'
[defaults setBool:self.disableUpdateCheck forKey:PREF_DISABLE_UPDATE_CHECK];
//save 'disable vt queries'
[defaults setBool:self.disableVTQueries forKey:PREF_DISABLE_VT_QUERIRES];
+3 -3
View File
@@ -30,7 +30,7 @@
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkIcon" id="xKf-GK-m0k"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
<rect key="frame" x="153" y="330" width="180" height="50"/>
<rect key="frame" x="153" y="351" width="180" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkText" id="Ws8-bD-j2R"/>
</imageView>
@@ -71,7 +71,7 @@
</scroller>
</scrollView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fZJ-sG-ZuJ">
<rect key="frame" x="20" y="265" width="153" height="19"/>
<rect key="frame" x="20" y="250" width="153" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Supporters/Patrons:" id="fJg-qw-wDf">
<font key="font" size="13" name="Menlo-Regular"/>
@@ -80,7 +80,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
<rect key="frame" x="153" y="309" width="182" height="19"/>
<rect key="frame" x="153" y="334" 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">
<font key="font" size="13" name="Menlo-Regular"/>
+33 -18
View File
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15B42" 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="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<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="disableUpdateCheckBtn" destination="dJU-Ok-N6U" id="Q9b-gF-V3d"/>
<outlet property="disableVTQueriesBtn" destination="d54-mZ-jqy" id="Xx6-E1-yv0"/>
<outlet property="okButton" destination="HZZ-Es-mpy" id="GKU-Jc-ENB"/>
<outlet property="saveOutputBtn" destination="6la-v6-zBD" id="m3d-J9-MZg"/>
@@ -16,41 +18,49 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Preferences" 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"/>
<rect key="contentRect" x="196" y="240" width="422" height="123"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
<window title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES"/>
<rect key="contentRect" x="196" y="240" width="422" height="177"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
<rect key="frame" x="0.0" y="0.0" width="422" height="177"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
<rect key="frame" x="25" y="37" width="48" height="48"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="settings" id="xKf-GK-m0k"/>
</imageView>
<button focusRingType="none" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4xV-kQ-iaT">
<rect key="frame" x="101" y="85" width="264" height="18"/>
<rect key="frame" x="101" y="139" width="264" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="include os/known items" bezelStyle="regularSquare" imagePosition="left" focusRingType="none" inset="2" id="WN8-cQ-8xh">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
</buttonCell>
</button>
<button focusRingType="none" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d54-mZ-jqy">
<rect key="frame" x="101" y="52" width="303" height="19"/>
<rect key="frame" x="101" y="81" width="303" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="disable virustotal integration" bezelStyle="regularSquare" imagePosition="left" focusRingType="none" inset="2" id="gXW-vY-Aj1">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
</buttonCell>
</button>
<button focusRingType="none" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dJU-Ok-N6U">
<rect key="frame" x="101" y="110" width="303" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="disable update check" bezelStyle="regularSquare" imagePosition="left" focusRingType="none" inset="2" id="idJ-pd-k6U">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
</buttonCell>
</button>
<button focusRingType="none" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6la-v6-zBD">
<rect key="frame" x="101" y="19" width="160" height="18"/>
<buttonCell key="cell" type="check" title="save results" bezelStyle="regularSquare" imagePosition="left" focusRingType="none" inset="2" id="8A7-6z-flS">
<rect key="frame" x="101" y="51" width="160" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="save scan results" bezelStyle="regularSquare" imagePosition="left" focusRingType="none" inset="2" id="8A7-6z-flS">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
<rect key="frame" x="326" y="10" width="82" height="32"/>
<rect key="frame" x="326" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="J9x-sM-h9S">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" size="13" name="Menlo-Regular"/>
@@ -59,12 +69,17 @@
<action selector="closeWindow:" target="-2" id="eFa-k0-zTM"/>
</connections>
</button>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
<rect key="frame" x="20" y="79" width="48" height="48"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="settings" id="xKf-GK-m0k"/>
</imageView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="318" y="246.5"/>
<point key="canvasLocation" x="318" y="273.5"/>
</window>
</objects>
<resources>
+80
View File
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="InfoWindowController">
<connections>
<outlet property="actionButton" destination="tDD-5C-L8e" id="VA6-H5-ZZO"/>
<outlet property="infoLabel" destination="OSm-xS-Dmd" id="Ffv-9q-5a6"/>
<outlet property="overlayView" destination="afp-ji-No6" id="qDV-BW-3l3"/>
<outlet property="progressIndicator" destination="1oq-WT-B5T" id="f6G-ch-c3m"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" texturedBackground="YES"/>
<rect key="contentRect" x="196" y="240" width="422" height="123"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
<rect key="frame" x="10" y="8" width="110" height="106"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkIcon" id="xKf-GK-m0k"/>
</imageView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
<rect key="frame" x="122" y="69" width="198" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkText" id="Ws8-bD-j2R"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
<rect key="frame" x="124" y="48" width="279" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" id="bBK-v0-ypq">
<font key="font" size="12" name="Menlo-Regular"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button wantsLayer="YES" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tDD-5C-L8e">
<rect key="frame" x="272" y="13" width="136" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="nMV-1f-RyK">
<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="tap-If-b45"/>
</connections>
</button>
<customView hidden="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="afp-ji-No6">
<rect key="frame" x="0.0" y="0.0" width="422" height="123"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<progressIndicator hidden="YES" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="1oq-WT-B5T">
<rect key="frame" x="195" y="45" width="32" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
</subviews>
</customView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="318" y="246.5"/>
</window>
</objects>
<resources>
<image name="kkIcon" width="512" height="512"/>
<image name="kkText" width="426.48001098632812" height="85.919998168945312"/>
</resources>
</document>
+26
View File
@@ -0,0 +1,26 @@
//
// file: Update.h
// project: lulu (shared)
// description: checks for new versions of LuLu (header)
//
// created by Patrick Wardle
// copyright (c) 2017 Objective-See. All rights reserved.
//
#ifndef Update_h
#define Update_h
@import Cocoa;
@import Foundation;
@interface Update : NSObject
//check for an update
// will invoke app delegate method to update UI when check completes
-(void)checkForUpdate:(void (^)(NSUInteger result, NSString* latestVersion))completionHandler;
@end
#endif /* Update_h */
+97
View File
@@ -0,0 +1,97 @@
//
// file: Update.m
// project: lulu (shared)
// description: checks for new versions of LuLu
//
// created by Patrick Wardle
// copyright (c) 2017 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "Update.h"
#import "Utilities.h"
#import "AppDelegate.h"
@implementation Update
//check for an update
// ->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;
//result
__block NSInteger result = -1;
//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)
{
//check
result = (NSOrderedAscending == [getAppVersion() compare:latestVersion options:NSNumericSearch]);
}
//invoke app delegate method
// ->will update UI/show popup if necessart
dispatch_async(dispatch_get_main_queue(),
^{
completionHandler(result, latestVersion);
});
});
return;
}
//query interwebz to get latest version
-(NSString*)getLatestVersion
{
//product version(s) data
NSData* productsVersionData = 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
@try
{
//convert
productsVersionDictionary = [NSJSONSerialization JSONObjectWithData:productsVersionData options:0 error:nil];
if(nil == productsVersionDictionary)
{
//bail
goto bail;
}
}
@catch(NSException* exception)
{
//bail
goto bail;
}
//extract latest version
latestVersion = [[productsVersionDictionary objectForKey:@"KnockKnock"] objectForKey:@"version"];
bail:
return latestVersion;
}
@end
+49
View File
@@ -0,0 +1,49 @@
//
// file: UpdateWindowController.m
// project: KnockKnock
// description: window handler for update window/popup (header)
//
// created by Patrick Wardle
// copyright (c) 2017 Objective-See. All rights reserved.
//
@import Cocoa;
@interface UpdateWindowController : NSWindowController <NSWindowDelegate>
{
}
/* PROPERTIES */
//version label/string
@property(weak)IBOutlet NSTextField *infoLabel;
//action button
@property(weak)IBOutlet NSButton *actionButton;
//label string
@property(nonatomic, retain)NSString* infoLabelString;
//first button ('update check')
@property(weak)IBOutlet NSView *firstButton;
//button title
@property(nonatomic, retain)NSString* actionButtonTitle;
//overlay view
@property(weak)IBOutlet NSView *overlayView;
//spinner
@property(weak)IBOutlet NSProgressIndicator *progressIndicator;
/* METHODS */
//save the main label's & button title's text
-(void)configure:(NSString*)label buttonTitle:(NSString*)buttonTitle;
//invoked when user clicks button
// ->trigger action such as opening product website, updating, etc
-(IBAction)buttonHandler:(id)sender;
@end
+121
View File
@@ -0,0 +1,121 @@
//
// file: UpdateWindowController.m
// project: KnockKnock
// description: window handler for update window/popup
//
// created by Patrick Wardle
// copyright (c) 2017 Objective-See. All rights reserved.
//
#import "Consts.h"
#import "Utilities.h"
#import "AppDelegate.h"
#import "UpdateWindowController.h"
@implementation UpdateWindowController
@synthesize infoLabel;
@synthesize overlayView;
@synthesize firstButton;
@synthesize actionButton;
@synthesize infoLabelString;
@synthesize actionButtonTitle;
@synthesize progressIndicator;
//automatically called when nib is loaded
// ->center window
-(void)awakeFromNib
{
//center
[self.window center];
return;
}
//automatically invoked when window is loaded
// ->set to white
-(void)windowDidLoad
{
//super
[super windowDidLoad];
//not in dark mode?
// make window white
if(YES != isDarkMode())
{
//make white
self.window.backgroundColor = NSColor.whiteColor;
}
//indicated title bar is tranparent (too)
self.window.titlebarAppearsTransparent = YES;
//set main label
[self.infoLabel setStringValue:self.infoLabelString];
//set button text
self.actionButton.title = self.actionButtonTitle;
//hide first button when action is 'update'
// ->don't need update check button ;)
if(YES == [self.actionButton.title isEqualToString:@"Update"])
{
//hide
self.firstButton.hidden = YES;
//then make action button first responder
[self.window makeFirstResponder:self.actionButton];
}
//make it key window
[self.window makeKeyAndOrderFront:self];
//make window front
[NSApp activateIgnoringOtherApps:YES];
return;
}
//automatically invoked when window is closing
// ->make ourselves unmodal
-(void)windowWillClose:(NSNotification *)notification
{
//make un-modal
[[NSApplication sharedApplication] stopModal];
return;
}
//save the main label's & button title's text
// ->invoked before window is loaded (and thus buttons, etc are nil)
-(void)configure:(NSString*)label buttonTitle:(NSString*)buttonTitle
{
//save label's string
self.infoLabelString = label;
//save button's title
self.actionButtonTitle = buttonTitle;
return;
}
//invoked when user clicks button
// trigger action such as opening product website, updating, etc
-(IBAction)buttonHandler:(id)sender
{
//handle 'update' / 'more info', etc
// ->open LuLu's webpage, if they *didn't* click 'close'
if(YES != [((NSButton*)sender).title isEqualToString:@"close"])
{
//open URL
// ->invokes user's default browser
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:PRODUCT_URL]];
}
//always close window
[[self window] close];
return;
}
@end
+2 -2
View File
@@ -108,9 +108,9 @@ NSMutableDictionary* allUsers()
{
//grab identity
identity = [CBIdentity identityWithCSIdentity:(CSIdentityRef)CFArrayGetValueAtIndex(results, i)];
//add user
users[identity.uniqueIdentifier] = @{USER_NAME:identity.posixName, USER_DIRECTORY:NSHomeDirectoryForUser(identity.posixName)};
users[identity.UUIDString] = @{USER_NAME:identity.posixName, USER_DIRECTORY:NSHomeDirectoryForUser(identity.posixName)};
}
bail:
+24 -6
View File
@@ -251,14 +251,32 @@ void prettyPrintJSON(NSString* output)
//covert to data
data = [output dataUsingEncoding:NSUTF8StringEncoding];
//serialize
object = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//covert to pretty data
prettyData = [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:nil];
//convert to JSON
// wrap since we are serializing JSON
@try
{
//serialize
object = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//covert to pretty data
prettyData = [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:nil];
}
@catch(NSException *exception)
{
;
}
//covert to pretty string
prettyString = [[NSString alloc] initWithData:prettyData encoding:NSUTF8StringEncoding];
if(nil != prettyData)
{
//convert to string
prettyString = [[NSString alloc] initWithData:prettyData encoding:NSUTF8StringEncoding];
}
else
{
//error
prettyString = @"{\"ERROR\" : \"failed to covert output to JSON\"}";
}
//output
printf("%s\n", prettyString.UTF8String);