From ee9b80ddb90ca2e6e12e0bee42d3297b79ca2df4 Mon Sep 17 00:00:00 2001 From: Patrick Wardle Date: Wed, 17 Jun 2015 21:47:56 -1000 Subject: [PATCH] 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 --- 3rdParty/OrderedDictionary.h | 5 +- 3rdParty/OrderedDictionary.m | 27 +- AppDelegate.h | 7 +- AppDelegate.m | 48 ++- Consts.h | 6 + Task.m | 50 ++- TaskEnumerator.m | 7 +- TaskExplorer.xcodeproj/project.pbxproj | 6 - .../xcdebugger/Breakpoints_v2.xcbkptlist | 144 +++++---- TaskTableController.m | 302 ++++++++++++++--- TreeViewController.h | 46 --- TreeViewController.m | 305 ------------------ UI/TreeView.xib | 6 +- Utilities.m | 7 +- 14 files changed, 476 insertions(+), 490 deletions(-) delete mode 100755 TreeViewController.h delete mode 100755 TreeViewController.m diff --git a/3rdParty/OrderedDictionary.h b/3rdParty/OrderedDictionary.h index aac2e73..506d17d 100644 --- a/3rdParty/OrderedDictionary.h +++ b/3rdParty/OrderedDictionary.h @@ -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 diff --git a/3rdParty/OrderedDictionary.m b/3rdParty/OrderedDictionary.m index c6b208c..df700b4 100644 --- a/3rdParty/OrderedDictionary.m +++ b/3rdParty/OrderedDictionary.m @@ -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; } diff --git a/AppDelegate.h b/AppDelegate.h index 9af6aa8..e015e38 100755 --- a/AppDelegate.h +++ b/AppDelegate.h @@ -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; diff --git a/AppDelegate.m b/AppDelegate.m index a6a86fa..4baf3a5 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -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; } diff --git a/Consts.h b/Consts.h index c34fd0e..4d2488b 100644 --- a/Consts.h +++ b/Consts.h @@ -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 + diff --git a/Task.m b/Task.m index e194140..cad6381 100644 --- a/Task.m +++ b/Task.m @@ -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]; diff --git a/TaskEnumerator.m b/TaskEnumerator.m index 50b16bf..0516a57 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -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: diff --git a/TaskExplorer.xcodeproj/project.pbxproj b/TaskExplorer.xcodeproj/project.pbxproj index a85edde..a715a96 100755 --- a/TaskExplorer.xcodeproj/project.pbxproj +++ b/TaskExplorer.xcodeproj/project.pbxproj @@ -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 = ""; }; CD3F4D131AF85088002A2647 /* FlatView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FlatView.xib; path = UI/FlatView.xib; sourceTree = ""; }; CD3F4D151AF89066002A2647 /* TreeView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TreeView.xib; path = UI/TreeView.xib; sourceTree = ""; }; - CD3F4D1A1AFADD36002A2647 /* TreeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TreeViewController.h; sourceTree = ""; }; - CD3F4D1B1AFADD36002A2647 /* TreeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TreeViewController.m; sourceTree = ""; }; 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 */, diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 4d881fa..b0bb648 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/TaskExplorer.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -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"> @@ -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"> - - - - @@ -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"> @@ -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"> @@ -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"> @@ -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"> @@ -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"> @@ -189,22 +173,6 @@ landmarkType = "5"> - - - - + + + + + + + + + + + + + + + + diff --git a/TaskTableController.m b/TaskTableController.m index a3a7481..38e59c3 100644 --- a/TaskTableController.m +++ b/TaskTableController.m @@ -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 diff --git a/TreeViewController.h b/TreeViewController.h deleted file mode 100755 index a9368dc..0000000 --- a/TreeViewController.h +++ /dev/null @@ -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 - -#import "3rdParty/OrderedDictionary.h" - -@interface TreeViewController : NSViewController -{ - -} -@property (weak) IBOutlet NSOutlineView *itemView; - - - -//tasks -// ->updated by task enumerator -//@property(nonatomic, retain)OrderedDictionary* tasks; - - -@end diff --git a/TreeViewController.m b/TreeViewController.m deleted file mode 100755 index 40f491b..0000000 --- a/TreeViewController.m +++ /dev/null @@ -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 diff --git a/UI/TreeView.xib b/UI/TreeView.xib index 0290e94..529f55b 100755 --- a/UI/TreeView.xib +++ b/UI/TreeView.xib @@ -6,7 +6,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -44,7 +44,7 @@ - + diff --git a/Utilities.m b/Utilities.m index 977df34..18fcde4 100644 --- a/Utilities.m +++ b/Utilities.m @@ -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