diff --git a/AppDelegate.m b/AppDelegate.m index 70fc2a5..8bf30dc 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -39,6 +39,10 @@ //TODO: remove task, remove from taskEnum's global list for executables, and dylibs, etc //TODO: also refresh!.... +//TODO: search include network (and improved filtering to include state/proto/type) - DONE! + +//TODO: check all searches that use NSNotFound also check for nil (other != NSNotFound will be true for nil!!) + @implementation AppDelegate @@ -227,18 +231,12 @@ return; } -//invoked for any (and only) key-down events +//invoked for any (but only) key-down events -(NSEvent*)handleKeypress:(NSEvent*)event { //flag indicating event was handled BOOL wasHandled = NO; - //refresh (cmd+r) - //save (cmd+s) - //search (cmd+f) - //close window (cmd+w) - //info for selected task (cmd+i) - //only care about 'cmd' + something if(NSCommandKeyMask != (event.modifierFlags & NSCommandKeyMask)) { @@ -246,9 +244,12 @@ goto bail; } - NSLog(@"key press: %x", [event keyCode]); - //handle key-code + // refresh (cmd+r) + // save (cmd+s) + // search (cmd+f) + // close window (cmd+w) + // info for selected task (cmd+i) switch ([event keyCode]) { //'r' (refresh) diff --git a/Filter.m b/Filter.m index 918f8ce..625e653 100644 --- a/Filter.m +++ b/Filter.m @@ -12,9 +12,6 @@ #import "ItemBase.h" #import "Connection.h" -//file filter keywords -//NSString * const FILE_FILTERS[] = {@"#apple", @"#nonapple", @"#signed", @"#unsigned", @"#flagged"}; - //binary filter keywords NSString * const BINARY_KEYWORDS[] = {@"#apple", @"#nonapple", @"#signed", @"#unsigned", @"#flagged"}; @@ -210,7 +207,6 @@ NSString * const BINARY_KEYWORDS[] = {@"#apple", @"#nonapple", @"#signed", @"#un } //filter network connections -//TODO: match on family/connection type -(void)filterConnections:(NSString*)filterText items:(NSMutableArray*)items results:(NSMutableArray*)results { //first reset filter'd items @@ -220,7 +216,8 @@ NSString * const BINARY_KEYWORDS[] = {@"#apple", @"#nonapple", @"#signed", @"#un for(Connection* item in items) { //check local ip - if(NSNotFound != [item.localIPAddr rangeOfString:filterText options:NSCaseInsensitiveSearch].location) + if( (nil != item.localIPAddr) && + (NSNotFound != [item.localIPAddr rangeOfString:filterText options:NSCaseInsensitiveSearch].location) ) { //save match [results addObject:item]; @@ -230,7 +227,8 @@ NSString * const BINARY_KEYWORDS[] = {@"#apple", @"#nonapple", @"#signed", @"#un } //check local port - if(NSNotFound != [[NSString stringWithFormat:@"%d", [item.localPort unsignedShortValue]] rangeOfString:filterText options:NSCaseInsensitiveSearch].location) + if( (nil != item.localIPAddr) && + (NSNotFound != [[NSString stringWithFormat:@"%d", [item.localPort unsignedShortValue]] rangeOfString:filterText options:NSCaseInsensitiveSearch].location) ) { //save match [results addObject:item]; @@ -261,6 +259,39 @@ NSString * const BINARY_KEYWORDS[] = {@"#apple", @"#nonapple", @"#signed", @"#un continue; } + //check family + if( (nil != item.family) && + (NSNotFound != [item.family rangeOfString:filterText options:NSCaseInsensitiveSearch].location) ) + { + //save match + [results addObject:item]; + + //next + continue; + } + + //check protocol + if( (nil != item.proto) && + (NSNotFound != [item.proto rangeOfString:filterText options:NSCaseInsensitiveSearch].location) ) + { + //save match + [results addObject:item]; + + //next + continue; + } + + //check state + if( (nil != item.state) && + (NSNotFound != [item.state rangeOfString:filterText options:NSCaseInsensitiveSearch].location) ) + { + //save match + [results addObject:item]; + + //next + continue; + } + }//all connections return; diff --git a/ItemView.m b/ItemView.m index c4cb466..50d71a3 100644 --- a/ItemView.m +++ b/ItemView.m @@ -36,9 +36,9 @@ NSTableCellView* createItemView(NSTableView* tableView, id owner, id item) } //handle logic for search results - // ->dylibs and files have the special global 'loaded in' views + // ->dylibs/files/connections have the special global 'loaded in' views else if( (YES == [owner isKindOfClass:[SearchWindowController class]]) && - ( (YES == [item isKindOfClass:[Binary class]]) || (YES == [item isKindOfClass:[File class]]) ) ) + (YES != [item isKindOfClass:[Task class]]) ) { //create & config view itemCell = createLoadedItemView(tableView, owner, item); @@ -164,7 +164,6 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) //get host tasks // ->works with dylibs or files - //TODO: make work w/ network connections tasks = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator loadedIn:item]; //add dylib indicator @@ -181,6 +180,13 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) //init loadedIn = [NSMutableString stringWithFormat:@"(file, loaded in:"]; } + //add connection indicator + //-> '(connection, in: ... ' + else if(YES == [item isKindOfClass:[Connection class]]) + { + //init + loadedIn = [NSMutableString stringWithFormat:@"(connection, in:"]; + } //add all tasks for(Task* task in tasks) @@ -213,6 +219,13 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) //create loadedItemCell = [tableView makeViewWithIdentifier:@"FileCell" owner:owner]; } + //connections + // ->create cell + else if(YES == [item isKindOfClass:[Connection class]]) + { + //create + loadedItemCell = [tableView makeViewWithIdentifier:@"ConnectionCell" owner:owner]; + } //sanity check if(nil == loadedItemCell) @@ -256,9 +269,21 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) // ->(re)set main textfield's color to black loadedItemCell.textField.textColor = [NSColor blackColor]; - //set main text - // ->name - [loadedItemCell.textField setStringValue:[item name]]; + //dylibs/files + // ->main text is name + if( (YES == [item isKindOfClass:[Binary class]]) || + (YES == [item isKindOfClass:[File class]]) ) + { + //set name + [loadedItemCell.textField setStringValue:[item name]]; + } + //connections + // ->main text is endpoints string + else + { + //set endpoints string + [loadedItemCell.textField setStringValue:[item endpoints]]; + } //get name frame nameFrame = loadedItemCell.textField.frame; @@ -273,13 +298,41 @@ NSTableCellView* createLoadedItemView(NSTableView* tableView, id owner, id item) // ->should now be exact size of text loadedItemCell.textField.frame = nameFrame; - //set pid + //set host task(s) string // ->immediately follows name [((NSTextField*)[loadedItemCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:loadedIn]; - //set path - [[loadedItemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:[item path]]; - + //dylibs/files + // ->subtext is path + if( (YES == [item isKindOfClass:[Binary class]]) || + (YES == [item isKindOfClass:[File class]]) ) + { + //set path + [[loadedItemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:[item path]]; + } + //connections + // ->subtext is connection status + else + { + //set details + // ->TCP socket + if(nil != ((Connection*)item).state) + { + //add state + [[loadedItemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:((Connection*)item).state]; + } + //set details + // ->UDP socket + else if(YES == [((Connection*)item).type isEqualToString:@"SOCK_DGRAM"]) + { + //bound + // ->add state + [[loadedItemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:@"bound (UDP) socket"]; + + //TODO: connected UDP socket? + } + } + //only dylibs have VT button if(YES == [item isKindOfClass:[Binary class]]) { @@ -343,7 +396,9 @@ NSTableCellView* createTaskView(NSTableView* tableView, id owner, Task* task) //set code signing icon ((NSImageView*)[taskCell viewWithTag:TABLE_ROW_SIGNATURE_ICON]).image = getCodeSigningIcon(task.binary); - + + //TODO: red for flagged? + //default // ->(re)set main textfield's color to black taskCell.textField.textColor = [NSColor blackColor]; @@ -508,6 +563,7 @@ NSTableCellView* createNetworkView(NSTableView* tableView, id owner, Connection* //item cell NSTableCellView* connectionCell = nil; + //TODO: don't need this to be mutable str? //connection details NSMutableString* details = nil; diff --git a/SearchWindowController.m b/SearchWindowController.m index ec6b3de..2e8770d 100644 --- a/SearchWindowController.m +++ b/SearchWindowController.m @@ -503,6 +503,9 @@ bail: //matching files NSMutableDictionary* matchingFiles = nil; + //matching connections + NSMutableDictionary* matchingConnections = nil; + //task Task* task = nil; @@ -518,6 +521,9 @@ bail: //alloc dictionary for matching files matchingFiles = [NSMutableDictionary dictionary]; + //alloc dictionary for matching connections + matchingConnections = [NSMutableDictionary dictionary]; + //reset search results [self.searchResults removeAllObjects]; @@ -564,6 +570,9 @@ bail: @synchronized(allTasks) { + //reset + [matchingItems removeAllObjects]; + //TODO: B4 RELEASE! SYNC DYLIBS ARRAY!!! //walk all tasks // ->scan each for dylib matches, only processing first match @@ -604,6 +613,9 @@ bail: //sync @synchronized(allTasks) { + //reset + [matchingItems removeAllObjects]; + //walk all tasks // ->scan each for file matches, only processing first match for(NSNumber* taskPid in allTasks) @@ -639,7 +651,48 @@ bail: //refresh table to display dylib [self.searchTable reloadData]; - //TODO: search network conns + //4th: search for all matching network comms + //sync + //TODO: sync network connections + @synchronized(allTasks) + { + //reset + [matchingItems removeAllObjects]; + + //walk all tasks + // ->scan each for file matches, only processing first match + for(NSNumber* taskPid in allTasks) + { + //extract task + task = allTasks[taskPid]; + + //filter + [self.filterObj filterConnections:searchString items:task.connections results:matchingItems]; + + //process all matching connections + // ->but first check if processed due to matching in another task already + for(Connection* connection in matchingItems) + { + //ignore if already seen/processed + if(nil != matchingConnections[connection.endpoints]) + { + //skip + continue; + } + + //process + [self.searchResults addObject:connection]; + + //save + matchingConnections[connection.endpoints] = connection; + } + + }//all tasks + + }//sync + + //refresh table to display dylib + [self.searchTable reloadData]; //bail bail: diff --git a/TaskEnumerator.m b/TaskEnumerator.m index 0f68380..6b4d7eb 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -14,6 +14,7 @@ #import "AppDelegate.h" #import "Utilities.h" #import "TaskEnumerator.h" +#import "Connection.h" #import #import @@ -634,6 +635,9 @@ bail: //file flag BOOL isFile = NO; + //connection flag + BOOL isConnection = NO; + //tasks hostTasks = [NSMutableArray array]; @@ -651,15 +655,24 @@ bail: isFile = YES; } + //check if item is connection + else if(YES == [item isKindOfClass:[Connection class]]) + { + //file + isConnection = YES; + } + //sanity check if( (YES != isDylib) && - (YES != isFile) ) + (YES != isFile) && + (YES != isConnection) ) { //bail goto bail; } //sync + //TODO: B4 RELEASE, sync files/dylibs/connections @synchronized(self.tasks) { //iterate over all tasks @@ -687,7 +700,7 @@ bail: }//dylib check //file check - else + else if(YES == isFile) { //check if file is loaded in task for(File* taskFile in task.files) @@ -704,6 +717,25 @@ bail: } }//file check + + //connection check + else if(YES == isConnection) + { + //check if connection is 'in' task + for(Connection* taskConnection in task.connections) + { + //check for task has connection + // note: ->check via endpoints, as that a good representation of connection(?) + if(YES == [taskConnection.endpoints isEqualToString: ((Connection*)item).endpoints]) + { + //save + [hostTasks addObject:task]; + + //can bail, since match was found + break; + } + } + } }//all tasks diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout index c0c67db..df18232 100644 --- a/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout +++ b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xccheckout @@ -7,14 +7,14 @@ IDESourceControlProjectIdentifier FE4103FE-6F26-4639-8C9F-D8D32C76D6A9 IDESourceControlProjectName - project + TaskExplorer IDESourceControlProjectOriginsDictionary 61F07AFB33748EF0C810BEEF6126283DAC63A899 https://bitbucket.org/objective-see/taskexplorer.git IDESourceControlProjectPath - TaskExplorer.xcodeproj/project.xcworkspace + TaskExplorer.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary 61F07AFB33748EF0C810BEEF6126283DAC63A899 diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate b/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate index 3809cf0..6a8e384 100644 Binary files a/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate and b/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrickw.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 277cd05..b15c66e 100644 --- a/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/TaskExplorer.xcodeproj/xcuserdata/patrickw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -10,43 +10,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "ItemView.m" - timestampString = "461741382.460449" + timestampString = "462956417.143953" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "44" - endingLineNumber = "44" - landmarkName = "createItemView()" - landmarkType = "7"> - - - - - - - - @@ -74,11 +42,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "SearchWindowController.m" - timestampString = "462871273.447907" + timestampString = "462871859.211461" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "196" - endingLineNumber = "196" + startingLineNumber = "192" + endingLineNumber = "192" landmarkName = "-waitTillPau" landmarkType = "5"> @@ -106,11 +74,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "462870109.066579" + timestampString = "462958083.434603" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "1544" - endingLineNumber = "1544" + startingLineNumber = "1545" + endingLineNumber = "1545" landmarkName = "-selectBottomPaneContent:" landmarkType = "5"> @@ -170,47 +138,15 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "AppDelegate.m" - timestampString = "462870109.066579" + timestampString = "462958083.434603" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "214" - endingLineNumber = "214" + startingLineNumber = "218" + endingLineNumber = "218" landmarkName = "-registerKeypressHandler" landmarkType = "5"> - - - - - - - - + + + + + + + + diff --git a/UI/SearchWindow.xib b/UI/SearchWindow.xib index f38089c..792fbc2 100644 --- a/UI/SearchWindow.xib +++ b/UI/SearchWindow.xib @@ -21,7 +21,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -324,8 +324,8 @@ - - + + @@ -358,10 +358,23 @@ + + + + + + + + + + + + +