dylibs and files in bottom pane are now sorted

errSecCSBadResource is ignored when checking for apple-signed files
'show file' fixed in bottom pane
tree view (re)fixed and sorted based on PID
tree view logic combined in single file
This commit is contained in:
Patrick Wardle
2015-06-17 21:47:56 -10:00
parent f19466a8fe
commit ee9b80ddb9
14 changed files with 476 additions and 490 deletions
+3 -2
View File
@@ -36,7 +36,8 @@
- (NSEnumerator *)reverseKeyEnumerator;
-(void)reverse;
//sort, by object key
-(void)sort:(NSString*)sortKey;
//sort
// ->by pid, name, etc
-(void)sort:(NSUInteger)sortBy;
@end
+21 -6
View File
@@ -21,6 +21,7 @@
// distribution.
//
#import "Consts.h"
#import "OrderedDictionary.h"
NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
@@ -133,17 +134,31 @@ NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
array = [[[array reverseObjectEnumerator] allObjects] mutableCopy];
}
//sort, by object key
-(void) :(NSString*)sortKey
//sort
// ->by pid, name, etc
-(void)sort:(NSUInteger)sortBy
{
//task sorted by name
NSArray* sortedTasks = nil;
//sort task by binary name
sortedTasks = [[dictionary allValues] sortedArrayUsingSelector:@selector(compare:)];
//
if(SORT_BY_PID == sortBy)
{
[array sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
}
else if(SORT_BY_NAME == sortBy)
{
//get array of tasks, sorted by binary name
// ->invokes Task class's compare method
sortedTasks = [[dictionary allValues] sortedArrayUsingSelector:@selector(compare:)];
//extract sorted pids into array
array = [[sortedTasks valueForKey:@"pid"] mutableCopy];
}
//extract pids into array
array = [[sortedTasks valueForKey:@"pid"] mutableCopy];
return;
}
+5 -2
View File
@@ -12,7 +12,6 @@
#import "Filter.h"
#import "VirusTotal.h"
#import "TaskTableController.h"
#import "TreeViewController.h"
#import "AboutWindowController.h"
#import "PrefsWindowController.h"
@@ -49,11 +48,15 @@
@property (nonatomic, retain)TaskTableController *taskTableController;
//tree (outline) controller
@property (nonatomic, retain)TreeViewController* treeViewController;
//@property (nonatomic, retain)TreeViewController* treeViewController;
//array to hold binary objects that are in array
//@property (nonatomic, retain)NSMutableArray *tableContents;
//current task view format
// ->flat or tree
@property NSUInteger taskViewFormat;
//drop-down view selector
@property (weak) IBOutlet NSPopUpButton *viewSelector;
+37 -11
View File
@@ -31,7 +31,7 @@
@synthesize bottomViewController;
@synthesize currentTask;
@synthesize requestRootWindowController;
@synthesize taskViewFormat;
@synthesize scannerThread;
@synthesize versionString;
@@ -39,7 +39,7 @@
@synthesize topPane;
@synthesize taskEnumerator;
@synthesize treeViewController;
//@synthesize treeViewController;
@synthesize currentViewController;
@synthesize viewSelector;
@@ -144,10 +144,12 @@
}
*/
//set default top pane view to flat
self.taskViewFormat = FLAT_VIEW;
//set initial view for top pane
// ->default is flat (non-tree) view
[self changeViewController:FLAT_VIEW];
[self changeViewController];
//alloc/init bottom pane controller
self.bottomViewController = [[TaskTableController alloc] initWithNibName:@"FlatView" bundle:nil];
@@ -312,7 +314,7 @@
//change top pane
// ->switch between either flat (default) or tree-based (hierachical) view
-(void)changeViewController:(NSInteger)whichViewTag
-(void)changeViewController
{
//remove old view
if([self.currentViewController view] != nil)
@@ -321,7 +323,7 @@
[[self.currentViewController view] removeFromSuperview];
}
switch (whichViewTag)
switch(self.taskViewFormat)
{
case FLAT_VIEW:
{
@@ -337,11 +339,11 @@
case TREE_VIEW:
{
//alloc/init
treeViewController = [[TreeViewController alloc] initWithNibName:@"TreeView" bundle:nil];
if(self.treeViewController != nil)
taskTableController = [[TaskTableController alloc] initWithNibName:@"TreeView" bundle:nil];
if(self.taskTableController != nil)
{
//update iVar
self.currentViewController = self.treeViewController;
self.currentViewController = self.taskTableController;
}
break;
}
@@ -616,6 +618,22 @@ bail:
// invoke custom refresh method on main thread
-(void)reloadTaskTable
{
//sort tasks
// ->flat view, sort by name
if(FLAT_VIEW == self.taskViewFormat)
{
//sort
[self.taskEnumerator.tasks sort:SORT_BY_NAME];
}
//sort tasks
// ->tree view, sort by pid
else
{
//sort
[self.taskEnumerator.tasks sort:SORT_BY_PID];
}
//when exec'ing on background thread
// ->exec on main thread
if(YES != [NSThread isMainThread])
@@ -634,8 +652,10 @@ bail:
// ->just refresh
else
{
//TODO: currentViewCont?!?
//refresh
[(id)self.taskTableController refresh];
//[(id)self.taskTableController refresh];
[(id)self.currentViewController refresh];
}
return;
@@ -1342,8 +1362,14 @@ bail:
// ->invoke helper function to change view
-(IBAction)switchView:(id)sender
{
//switch (top) view
[self changeViewController: [[sender selectedCell] tag]];
//save selected view
self.taskViewFormat = [[sender selectedCell] tag];
//switch (top) view/pane
[self changeViewController];
//reload top pane
[self reloadTaskTable];
return;
}
+6
View File
@@ -293,6 +293,12 @@
//connected socket
#define SOCKET_ESTABLISHED @"connected"
//sort by pid
#define SORT_BY_PID 0x0
//sort by name
#define SORT_BY_NAME 0x1
+46 -4
View File
@@ -328,6 +328,13 @@ bail:
//alloc array for new dylibs
newDylibs = [NSMutableArray array];
//sync
@synchronized(self.dylibs)
{
//reset existing dylibs
[self.dylibs removeAllObjects];
}
//invoke XPC service (running as r00t)
// ->will enumerate dylibs, then invoke reply block to save into iVar
[[xpcConnection remoteObjectProxy] enumerateDylibs:self.pid withReply:^(NSMutableArray* dylibPaths) {
@@ -393,6 +400,18 @@ bail:
}
}
//sync to sort
@synchronized(self.dylibs)
{
//sort by name
self.dylibs = [[self.dylibs sortedArrayUsingComparator:^NSComparisonResult(id a, id b)
{
//sort
return [[(Binary*)a name] compare:[(Binary*)b name] options:NSCaseInsensitiveSearch];
}] mutableCopy];
}
//reload bottom pane now
// ->this will only reload if new task is the currently selected one, etc
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:DYLIBS_VIEW];
@@ -406,7 +425,7 @@ bail:
}
//any new dylibs?
// ->reload bottom pane
// ->reload bottom pane to update signing info, etc
if(0 != newDylibs.count)
{
//reload
@@ -435,6 +454,13 @@ bail:
//alloc array for new files
newFiles = [NSMutableArray array];
//sync
@synchronized(self.files)
{
//reset existing files
[self.files removeAllObjects];
}
//invoke XPC service (running as r00t)
// ->will enumerate files, then invoke reply block so can save into iVar
[[xpcConnection remoteObjectProxy] enumerateFiles:self.pid withReply:^(NSMutableArray* fileDescriptors) {
@@ -455,9 +481,13 @@ bail:
//next
continue;
}
//add to task's files
[self.files addObject:file];
//sync
@synchronized(self.files)
{
//add to task's files
[self.files addObject:file];
}
//save new files
// ->will be processed below
@@ -468,6 +498,18 @@ bail:
}
}
//sync to sort
@synchronized(self.files)
{
//sort by name
self.files = [[self.files sortedArrayUsingComparator:^NSComparisonResult(id a, id b)
{
//sort
return [[(File*)a name] compare:[(File*)b name] options:NSCaseInsensitiveSearch];
}] mutableCopy];
}
//reload bottom pane
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:FILES_VIEW];
+1 -6
View File
@@ -138,9 +138,7 @@
}//add new tasks
//sort by name!
//reload table
//reload task table
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadTaskTable];
//now generate signing info
@@ -261,9 +259,6 @@
//add kernel task
[allTasks setObject:task forKey:@0];
//sort all tasks alphabetically
[allTasks sort:@"name"];
//bail
bail:
-6
View File
@@ -29,7 +29,6 @@
CD3F4CFF1AF72BC4002A2647 /* TaskInfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD3F4CFE1AF72BC4002A2647 /* TaskInfoWindow.xib */; };
CD3F4D141AF85088002A2647 /* FlatView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD3F4D131AF85088002A2647 /* FlatView.xib */; };
CD3F4D161AF89066002A2647 /* TreeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD3F4D151AF89066002A2647 /* TreeView.xib */; };
CD3F4D1C1AFADD36002A2647 /* TreeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4D1B1AFADD36002A2647 /* TreeViewController.m */; };
CD4D53CA1B20296E00008030 /* unknown.png in Resources */ = {isa = PBXBuildFile; fileRef = CD4D53C91B20296E00008030 /* unknown.png */; };
CD4D53D01B23ED3900008030 /* connectedIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD4D53CF1B23ED3900008030 /* connectedIcon.png */; };
CD4D53D21B23ED4300008030 /* listeningIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD4D53D11B23ED4300008030 /* listeningIcon.png */; };
@@ -164,8 +163,6 @@
CD3F4CFE1AF72BC4002A2647 /* TaskInfoWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TaskInfoWindow.xib; path = UI/TaskInfoWindow.xib; sourceTree = "<group>"; };
CD3F4D131AF85088002A2647 /* FlatView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FlatView.xib; path = UI/FlatView.xib; sourceTree = "<group>"; };
CD3F4D151AF89066002A2647 /* TreeView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TreeView.xib; path = UI/TreeView.xib; sourceTree = "<group>"; };
CD3F4D1A1AFADD36002A2647 /* TreeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TreeViewController.h; sourceTree = "<group>"; };
CD3F4D1B1AFADD36002A2647 /* TreeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TreeViewController.m; sourceTree = "<group>"; };
CD4D53C91B20296E00008030 /* unknown.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = unknown.png; path = images/unknown.png; sourceTree = SOURCE_ROOT; };
CD4D53CF1B23ED3900008030 /* connectedIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = connectedIcon.png; path = images/connectedIcon.png; sourceTree = SOURCE_ROOT; };
CD4D53D11B23ED4300008030 /* listeningIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = listeningIcon.png; path = images/listeningIcon.png; sourceTree = SOURCE_ROOT; };
@@ -465,8 +462,6 @@
children = (
CDA5F6C21B16E20E003CE340 /* RequestRootWindowController.h */,
CDA5F6C31B16E20E003CE340 /* RequestRootWindowController.m */,
CD3F4D1A1AFADD36002A2647 /* TreeViewController.h */,
CD3F4D1B1AFADD36002A2647 /* TreeViewController.m */,
CD6E54FD1B1162B5007953AB /* ItemView.h */,
CD6E54FE1B1162B5007953AB /* ItemView.m */,
CD02195F1AD39A83005148A2 /* ResultsWindowController.h */,
@@ -697,7 +692,6 @@
CDA81D7B1A95D29B009790E2 /* TaskTableController.m in Sources */,
CDF08CCA1AC4C678009B3423 /* PrefsWindowController.m in Sources */,
CDA81DEA1A997BF1009790E2 /* InfoWindowController.m in Sources */,
CD3F4D1C1AFADD36002A2647 /* TreeViewController.m in Sources */,
CD02195C1AD38823005148A2 /* kkRowCell.m in Sources */,
CDF08CE61AC89FE1009B3423 /* HyperlinkTextField.m in Sources */,
CDA81D4F1A95B492009790E2 /* AppDelegate.m in Sources */,
@@ -20,11 +20,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Task.m"
timestampString = "455934659.769831"
timestampString = "456217349.500536"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "509"
endingLineNumber = "509"
startingLineNumber = "551"
endingLineNumber = "551"
landmarkName = "-enumerateNetworking:"
landmarkType = "5">
</BreakpointContent>
@@ -36,27 +36,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Task.m"
timestampString = "455934659.769831"
timestampString = "456217349.500536"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "319"
endingLineNumber = "319"
landmarkName = "-enumerateDylibs:allDylibs:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Task.m"
timestampString = "455934659.769831"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "402"
endingLineNumber = "402"
startingLineNumber = "421"
endingLineNumber = "421"
landmarkName = "-enumerateDylibs:allDylibs:"
landmarkType = "5">
</BreakpointContent>
@@ -68,11 +52,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AppDelegate.m"
timestampString = "455870793.890474"
timestampString = "456302892.352739"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "406"
endingLineNumber = "406"
startingLineNumber = "408"
endingLineNumber = "408"
landmarkName = "-reloadBottomPane:itemView:"
landmarkType = "5">
</BreakpointContent>
@@ -84,11 +68,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AppDelegate.m"
timestampString = "455871607.2373"
timestampString = "456302892.352739"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "413"
endingLineNumber = "413"
startingLineNumber = "415"
endingLineNumber = "415"
landmarkName = "-reloadBottomPane:itemView:"
landmarkType = "5">
</BreakpointContent>
@@ -100,11 +84,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AppDelegate.m"
timestampString = "455913381.256009"
timestampString = "456303370.767322"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "1354"
endingLineNumber = "1354"
startingLineNumber = "1380"
endingLineNumber = "1380"
landmarkName = "-selectBottomPaneContent:"
landmarkType = "5">
</BreakpointContent>
@@ -116,11 +100,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AppDelegate.m"
timestampString = "455927034.93809"
timestampString = "456303370.767322"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "1375"
endingLineNumber = "1375"
startingLineNumber = "1401"
endingLineNumber = "1401"
landmarkName = "-selectBottomPaneContent:"
landmarkType = "5">
</BreakpointContent>
@@ -132,11 +116,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AppDelegate.m"
timestampString = "455927034.93809"
timestampString = "456303370.767322"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "1378"
endingLineNumber = "1378"
startingLineNumber = "1404"
endingLineNumber = "1404"
landmarkName = "-selectBottomPaneContent:"
landmarkType = "5">
</BreakpointContent>
@@ -189,22 +173,6 @@
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "TaskTableController.m"
timestampString = "456129885.389119"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "995"
endingLineNumber = "995"
landmarkName = "-showInfo:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@@ -276,14 +244,78 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Task.m"
timestampString = "456131801.925009"
timestampString = "456217349.500536"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "532"
endingLineNumber = "532"
startingLineNumber = "574"
endingLineNumber = "574"
landmarkName = "-compare:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "TreeViewController.m"
timestampString = "456305223.712479"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "63"
endingLineNumber = "63"
landmarkName = "-outlineView:isItemExpandable:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "TreeViewController.m"
timestampString = "456305223.712479"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "82"
endingLineNumber = "82"
landmarkName = "-outlineView:child:ofItem:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "TaskTableController.m"
timestampString = "456305690.622084"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "40"
endingLineNumber = "40"
landmarkName = "-awakeFromNib"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "TreeViewController.m"
timestampString = "456305705.729474"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "13"
endingLineNumber = "13"
landmarkName = "-awakeFromNib"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
+262 -40
View File
@@ -41,6 +41,18 @@
{
self.selectedRow = -1;
//for outline (tree) view
// ->expand
if(YES == [self.itemView isKindOfClass:[NSOutlineView class]])
{
[(NSOutlineView*)self.itemView expandItem:nil expandChildren:YES];
//TODO: do this in IB?
//[itemView setTarget:self];
}
NSLog(@"item view: %@", self.itemView);
/*
NSString *title = @"[ all tasks ]";
NSTableColumn *yourColumn = self.itemView.tableColumns.lastObject;
@@ -96,40 +108,7 @@
return rows;
/*
//plugin object
PluginBase* selectedPluginObj = nil;
//set selected plugin
selectedPluginObj = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).selectedPlugin;
//invoke helper function to get array
// ->then grab count
rows = [[self getTableItems] count];
//if not items have been found
// ->display 'not found' msg
if( (0 == rows) &&
(nil != selectedPluginObj) )
{
//set string (to include plugin's name)
[self.noItemsLabel setStringValue:[NSString stringWithFormat:@"no %@ found", [selectedPluginObj.name lowercaseString]]];
//show label
self.noItemsLabel.hidden = NO;
}
else
{
//hide label
self.noItemsLabel.hidden = YES;
}
return rows;
*/
}
//automatically invoked when user selects row
// ->only care about for top pane, trigger load bottom view
@@ -958,16 +937,44 @@ bail:
// ->open Finder to show item
-(IBAction)showInFinder:(id)sender
{
//task
Task* task = nil;
//item
// ->task, dylib, file, etc
id item = nil;
//get task
//TODO: this used to be called w/ nil
task = [self taskForRow:sender];
//path to binary
NSString* path = nil;
//for top pane
// ->get task
if(YES != self.isBottomPane)
{
//get task
item = [self taskForRow:sender];
//get path
path = ((Task*)item).binary.path;
}
//bottom pane
else
{
//get item
item = [self itemForRow:sender];
//get path
path = ((Binary*)item).path;
}
//sanity check
if(nil == path)
{
//bail
goto bail;
}
//open Finder
// ->will reveal binary
[[NSWorkspace sharedWorkspace] selectFile:task.binary.path inFileViewerRootedAtPath:nil];
[[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:nil];
//bail
bail:
@@ -976,7 +983,7 @@ bail:
}
//automatically invoked when user clicks the 'info' icon
// ->create/configure/display info window
// ->create/configure/display info window for task/dylib/file/etc
-(IBAction)showInfo:(id)sender
{
//item
@@ -1068,4 +1075,219 @@ bail:
}
//OUTLINE VIEW STUFFZ
-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
//tasks
OrderedDictionary* tasks = nil;
//grab tasks
tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks;
//number of children
NSUInteger numberOfChildren = 0;
//when item is nil
// ->count is number of root items children
if(nil == item)
{
//kids
numberOfChildren = ((Task*)[tasks objectForKey:@0]).children.count;
}
//otherwise
// ->give number of item's kids
else
{
//kids
numberOfChildren = [((Task*)item).children count];
}
return numberOfChildren;
}
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
//only no for leafs
// ->items w/o kids
if( (nil != item) &&
(0 == [[item children] count]) )
{
return NO;
}
else
{
return YES;
}
//return !item ? YES : [[item children] count] != 0;
}
//TODO: sort children!!!
//return child
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
//tasks
OrderedDictionary* tasks = nil;
//task
Task* task = nil;
//grab all tasks
tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks;
//root item
if(nil == item)
{
//root
task = [tasks objectForKey:@0];
}
//non-root items
// ->return *their* child!
else
{
task = [tasks objectForKey:[(Task*)item children][index]];
}
return task;
}
//TODO: combine logic - and make taskForRow method work for flat and tree views :)
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
{
//tasks
__block OrderedDictionary* tasks = nil;
//task
Task* task = nil;
//newly selected row (index)
__block NSInteger newlySelectedRow = -1;
//selected row cell
NSTableCellView* selectedView = nil;
//ignore events for bottom-pane
if(YES == self.isBottomPane)
{
//ignore
goto bail;
}
//get index of newly selected row
newlySelectedRow = [self.itemView selectedRow];
//get row that's about to be selected
selectedView = [self.itemView viewAtColumn:0 row:newlySelectedRow makeIfNecessary:YES];
//grab task
task = [self taskForRow:nil];
//check if task is dead
if(YES != isAlive([task.pid intValue]))
{
//make it red
((kkRowCell*)selectedView).color = [NSColor redColor];
//draw
[selectedView setNeedsDisplay:YES];
//make hide it after 1/4th second
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//reset color
((kkRowCell*)selectedView).color = nil;
//get tasks
tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks;
//remove (now dead) task
[tasks removeObjectForKey:task.pid];
//reload table
[self.itemView reloadData];
//sanity check
// ->make sure removed task wasn't last
if(tasks.count <= newlySelectedRow)
{
//reset to (new) last
newlySelectedRow = tasks.count - 1;
}
//sanity check
// ->reset to first item on other errors
else if(-1 == newlySelectedRow)
{
//set to first
newlySelectedRow = 0;
}
//re-select
[self.itemView selectRowIndexes:[NSIndexSet indexSetWithIndex:newlySelectedRow] byExtendingSelection:NO];
});
//bail
goto bail;
}
//ignore if row selection didn't change
if([self.itemView selectedRow] == self.selectedRow)
{
//ignore
goto bail;
}
//save newly selected row index
self.selectedRow = [self.itemView selectedRow];
//save currently selected task
((AppDelegate*)[[NSApplication sharedApplication] delegate]).currentTask = task;
//reload bottom pane
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) selectBottomPaneContent:nil];
//bail
bail:
return;
}
//table delegate method
// ->return cell for row
-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
return createItemView(outlineView, self, (Task*)item);
}
//automatically invoked
// ->create custom (sub-classed) NSTableRowView
-(NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item
{
//row view
KKRow* rowView = nil;
//row ID
static NSString* const kRowIdentifier = @"RowView";
//try grab existing row view
rowView = [outlineView makeViewWithIdentifier:kRowIdentifier owner:self];
//make new if needed
if(nil == rowView)
{
//create new
// ->size doesn't matter
rowView = [[KKRow alloc] initWithFrame:NSZeroRect];
//set row ID
rowView.identifier = kRowIdentifier;
}
return rowView;
}
@end
-46
View File
@@ -1,46 +0,0 @@
/*-
* Copyright 2009, Mac OS X Internals. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Mac OS X Internals ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Mac OS X Internals OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of Mac OS X Internals.
*/
#import <Cocoa/Cocoa.h>
#import "3rdParty/OrderedDictionary.h"
@interface TreeViewController : NSViewController
{
}
@property (weak) IBOutlet NSOutlineView *itemView;
//tasks
// ->updated by task enumerator
//@property(nonatomic, retain)OrderedDictionary* tasks;
@end
-305
View File
@@ -1,305 +0,0 @@
/*-
* Copyright 2009, Mac OS X Internals. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Mac OS X Internals ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Mac OS X Internals OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of Mac OS X Internals.
*/
#import "Task.h"
#import "AppDelegate.h"
#import "TreeViewController.h"
#import "ItemView.h"
#import "KKRow.h"
@implementation TreeViewController
@synthesize itemView;
-(void)awakeFromNib
{
//auto-expand everything
//
[itemView expandItem:nil expandChildren:YES];
//TODO: do this in IB?
[itemView setTarget:self];
//[outlineView setDoubleAction:@selector(onDoubleAction:)];
}
//reload + row selection intact
-(void)refresh
{
//TODO: add logic to ensure selected row stays selected
[self.itemView reloadData];
return;
}
/*
-(void)showProcessInfo
{
NSArray *processes = [arrayController selectedObjects];
if ([processes count] > 0) {
ProcessInfo *pInfo = [processes objectAtIndex:0];
if (pInfo.processState != -1 ) {
TaskInfoController *taskInfoController = [TaskInfoController taskInfoController:pInfo];
[taskInfoController showInfo];
}
}
}
*/
/*
-(void)onDoubleAction:(NSEvent*)theEvent;
{
[self showProcessInfo];
}
-(NSArray*)sortDescriptors
{
return [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
}
-(IBAction)menuItemAction:(id)sender
{
NSInteger clickedRow = [sender tag];
}
-(TasksInfoManager*)tasksInfoManager
{
return [TasksInfoManager instance];
}
-(NSString*)selectedAppName
{
NSString *result;
NSArray *processes = [arrayController selectedObjects];
if ([processes count] > 0) {
ProcessInfo *pInfo = [processes objectAtIndex:0];
result = pInfo.name;
}
return result;
}
*/
/*
-(void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
//Task* *task = [item representedObject];
Task* task = (Task*)item;
//item cell
NSTableCellView *itemCell = nil;
itemCell = (NSTableCellView*)cell;
//set main text
// ->name
[itemCell.textField setStringValue:task.path];
//[imageAndTextCell setImage:pInfo.icon_small];
/*
if ([[Settings instance] highlightProcesses] == YES) {
if (pInfo.processState == 0) { // process
[(NSTextFieldCell*)cell setTextColor:[NSColor blackColor]];
}
else if (pInfo.processState == 1) { // new process
[(NSTextFieldCell*)cell setTextColor:[NSColor greenColor]];
}
else if (pInfo.processState == -1) { // ended process
[(NSTextFieldCell*)cell setTextColor:[NSColor redColor]];
}
}
return;
}
*/
-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
//tasks
OrderedDictionary* tasks = nil;
//grab tasks
tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks;
//NSLog(@"task: %@", ((Task*)item).path);
//count
NSUInteger children = 0;
//when item is nil
// ->count is all children
if(nil == item)
{
//all
children = ((Task*)[tasks objectForKey:@0]).children.count;
}
//otherwise
// ->give number of item's kids
else
{
//NSLog(@"task: %@", ((Task*)item).path);
//
children = [((Task*)item).children count];
//NSLog(@"..has %lu kids", (unsigned long)children);
}
return children;
}
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
//only no for leafs
// ->items w/o kids
if( (nil != item) &&
(0 == [[item children] count]) )
{
return NO;
}
else
{
return YES;
}
//return !item ? YES : [[item children] count] != 0;
}
//return child
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
//tasks
OrderedDictionary* tasks = nil;
//task
Task* task = nil;
//grab tasks
tasks = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.tasks;
//get task object
// ->by index to get key, then by key
//task = self.tasks[[self.tasks keyAtIndex:index]];
task = [tasks objectForKey:@0];
//NSLog(@"root item: %@", self.tasks[[self.tasks objectForKey:@1]]);
//root item
// ->child at index
if(nil == item)
{
return task;//[self.tasks objectForKey:@1];
}
//other items
// ->return *their* child!
else
{
return [tasks objectForKey:[(Task*)item children][index]];
}
}
//table delegate method
// ->return cell for row
-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
return createItemView(outlineView, self, (Task*)item);
}
//automatically invoked
// ->create custom (sub-classed) NSTableRowView
-(NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item
{
//row view
KKRow* rowView = nil;
//row ID
static NSString* const kRowIdentifier = @"RowView";
//try grab existing row view
rowView = [outlineView makeViewWithIdentifier:kRowIdentifier owner:self];
//make new if needed
if(nil == rowView)
{
//create new
// ->size doesn't matter
rowView = [[KKRow alloc] initWithFrame:NSZeroRect];
//set row ID
rowView.identifier = kRowIdentifier;
}
return rowView;
}
/*
//person object
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
//NSLog(@"column name: %@", [tableColumn identifier]);
// if ([[tableColumn identifier] isEqualToString:@"name"])
return [item path];
// return @"Nobody's Here!";
}
*/
/*
- (NSString *)outlineView:(NSOutlineView *)outlineView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tc item:(id)item mouseLocation:(NSPoint)mouseLocation
{
ProcessInfo *pInfo = [item representedObject];
NSNumber *id_table;
NSString *id_column;
id *cell_data;
NSString *descr = pInfo.description;
return (descr);
}
*/
@end
+3 -3
View File
@@ -6,7 +6,7 @@
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="TreeViewController">
<customObject id="-2" userLabel="File's Owner" customClass="TaskTableController">
<connections>
<outlet property="itemView" destination="Wr1-No-lg2" id="74i-TW-N6D"/>
<outlet property="view" destination="T1P-b9-TzF" id="pja-1o-aue"/>
@@ -25,7 +25,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="40" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" outlineTableColumn="cLW-QZ-CYz" id="Wr1-No-lg2">
<rect key="frame" x="0.0" y="0.0" width="1298" height="0.0"/>
<rect key="frame" x="0.0" y="0.0" width="1304" height="0.0"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -44,7 +44,7 @@
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView identifier="ImageCell" id="7xB-nb-n5O" customClass="kkRowCell">
<tableCellView identifier="TaskCell" id="7xB-nb-n5O" customClass="kkRowCell">
<rect key="frame" x="1" y="1" width="1295" height="40"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
+4 -3
View File
@@ -260,10 +260,11 @@ BOOL isApple(NSString* path)
goto bail;
}
//check if file is signed by apple
// ->i.e. it conforms to req string
//check if file is signed by apple by checking if it conforms to req string
// note: ignore 'errSecCSBadResource' as lots of signed apple files return this issue :/
status = SecStaticCodeCheckValidity(staticCode, kSecCSDefaultFlags, requirementRef);
if(STATUS_SUCCESS != status)
if( (STATUS_SUCCESS != status) &&
(errSecCSBadResource != status) )
{
//bail
// ->just means app isn't signed by apple