initial commit
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// HyperlinkTextField.h
|
||||
// NSTextFieldHyperlinks
|
||||
//
|
||||
// Created by Toomas Vahter on 25.12.12.
|
||||
// Copyright (c) 2012 Toomas Vahter. All rights reserved.
|
||||
//
|
||||
// This content is released under the MIT License (http://www.opensource.org/licenses/mit-license.php).
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface HyperlinkTextField : NSTextField
|
||||
@end
|
||||
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// HyperlinkTextField.m
|
||||
// NSTextFieldHyperlinks
|
||||
//
|
||||
// Created by Toomas Vahter on 25.12.12.
|
||||
// Copyright (c) 2012 Toomas Vahter. All rights reserved.
|
||||
//
|
||||
// This content is released under the MIT License (http://www.opensource.org/licenses/mit-license.php).
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import "HyperlinkTextField.h"
|
||||
|
||||
@interface HyperlinkTextField ()
|
||||
@property (nonatomic, readonly) NSArray *hyperlinkInfos;
|
||||
@property (nonatomic, readonly) NSTextView *textView;
|
||||
|
||||
- (void)_resetHyperlinkCursorRects;
|
||||
@end
|
||||
|
||||
#define kHyperlinkInfoCharacterRangeKey @"range"
|
||||
#define kHyperlinkInfoURLKey @"url"
|
||||
#define kHyperlinkInfoRectKey @"rect"
|
||||
|
||||
@implementation HyperlinkTextField
|
||||
|
||||
- (void)_hyperlinkTextFieldInit
|
||||
{
|
||||
[self setEditable:NO];
|
||||
[self setSelectable:NO];
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame]))
|
||||
{
|
||||
[self _hyperlinkTextFieldInit];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
if ((self = [super initWithCoder:coder]))
|
||||
{
|
||||
[self _hyperlinkTextFieldInit];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void)resetCursorRects
|
||||
{
|
||||
[super resetCursorRects];
|
||||
[self _resetHyperlinkCursorRects];
|
||||
}
|
||||
|
||||
|
||||
- (void)_resetHyperlinkCursorRects
|
||||
{
|
||||
for (NSDictionary *info in self.hyperlinkInfos)
|
||||
{
|
||||
[self addCursorRect:[[info objectForKey:kHyperlinkInfoRectKey] rectValue] cursor:[NSCursor pointingHandCursor]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (NSArray *)hyperlinkInfos
|
||||
{
|
||||
NSMutableArray *hyperlinkInfos = [[NSMutableArray alloc] init];
|
||||
NSRange stringRange = NSMakeRange(0, [self.attributedStringValue length]);
|
||||
__block NSTextView *textView = self.textView;
|
||||
[self.attributedStringValue enumerateAttribute:NSLinkAttributeName inRange:stringRange options:0 usingBlock:^(id value, NSRange range, BOOL *stop)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
NSUInteger rectCount = 0;
|
||||
NSRectArray rectArray = [textView.layoutManager rectArrayForCharacterRange:range withinSelectedCharacterRange:range inTextContainer:textView.textContainer rectCount:&rectCount];
|
||||
for (NSUInteger i = 0; i < rectCount; i++)
|
||||
{
|
||||
[hyperlinkInfos addObject:@{kHyperlinkInfoCharacterRangeKey : [NSValue valueWithRange:range], kHyperlinkInfoURLKey : value, kHyperlinkInfoRectKey : [NSValue valueWithRect:rectArray[i]]}];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
return [hyperlinkInfos count] ? hyperlinkInfos : nil;
|
||||
}
|
||||
|
||||
|
||||
- (NSTextView *)textView
|
||||
{
|
||||
// Font used for displaying and frame calculations must match
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedStringValue];
|
||||
NSFont *font = [attributedString attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL];
|
||||
|
||||
if (!font)
|
||||
[attributedString addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, [attributedString length])];
|
||||
|
||||
NSRect textViewFrame = [self.cell titleRectForBounds:self.bounds];
|
||||
NSTextView *textView = [[NSTextView alloc] initWithFrame:textViewFrame];
|
||||
[textView.textStorage setAttributedString:attributedString];
|
||||
|
||||
return textView;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Mouse Events
|
||||
|
||||
- (void)mouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
NSTextView *textView = self.textView;
|
||||
NSPoint localPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
|
||||
NSUInteger index = [textView.layoutManager characterIndexForPoint:localPoint inTextContainer:textView.textContainer fractionOfDistanceBetweenInsertionPoints:NULL];
|
||||
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
for (NSDictionary *info in self.hyperlinkInfos)
|
||||
{
|
||||
NSRange range = [[info objectForKey:kHyperlinkInfoCharacterRangeKey] rangeValue];
|
||||
if (NSLocationInRange(index, range))
|
||||
{
|
||||
NSURL *url = [info objectForKey:kHyperlinkInfoURLKey];
|
||||
[[NSWorkspace sharedWorkspace] openURL:url];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// OrderedDictionary.h
|
||||
// OrderedDictionary
|
||||
//
|
||||
// Created by Matt Gallagher on 19/12/08.
|
||||
// Copyright 2008 Matt Gallagher. All rights reserved.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software. Permission is granted to anyone to
|
||||
// use this software for any purpose, including commercial applications, and to
|
||||
// alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface OrderedDictionary : NSMutableDictionary
|
||||
{
|
||||
NSMutableDictionary *dictionary;
|
||||
NSMutableArray *array;
|
||||
}
|
||||
|
||||
|
||||
- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex;
|
||||
- (id)keyAtIndex:(NSUInteger)anIndex;
|
||||
- (NSUInteger)indexOfKey:(id)aKey;
|
||||
- (NSEnumerator *)reverseKeyEnumerator;
|
||||
-(void)reverse;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// OrderedDictionary.m
|
||||
// OrderedDictionary
|
||||
//
|
||||
// Created by Matt Gallagher on 19/12/08.
|
||||
// Copyright 2008 Matt Gallagher. All rights reserved.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software. Permission is granted to anyone to
|
||||
// use this software for any purpose, including commercial applications, and to
|
||||
// alter it and redistribute it freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#import "OrderedDictionary.h"
|
||||
|
||||
NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
|
||||
{
|
||||
NSString *objectString;
|
||||
if ([object isKindOfClass:[NSString class]])
|
||||
{
|
||||
objectString = (NSString *)object;
|
||||
}
|
||||
else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
|
||||
{
|
||||
objectString = [(NSDictionary *)object descriptionWithLocale:locale indent:indent];
|
||||
}
|
||||
else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
|
||||
{
|
||||
objectString = [(NSSet *)object descriptionWithLocale:locale];
|
||||
}
|
||||
else
|
||||
{
|
||||
objectString = [object description];
|
||||
}
|
||||
return objectString;
|
||||
}
|
||||
|
||||
@implementation OrderedDictionary
|
||||
|
||||
-(id)init
|
||||
{
|
||||
return [self initWithCapacity:0];
|
||||
}
|
||||
|
||||
- (id)initWithCapacity:(NSUInteger)capacity
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
|
||||
array = [[NSMutableArray alloc] initWithCapacity:capacity];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
return [self mutableCopy];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)anObject forKey:(id)aKey
|
||||
{
|
||||
if(![dictionary objectForKey:aKey])
|
||||
{
|
||||
//
|
||||
[array addObject:aKey];
|
||||
}
|
||||
[dictionary setObject:anObject forKey:aKey];
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(id)aKey
|
||||
{
|
||||
[dictionary removeObjectForKey:aKey];
|
||||
[array removeObject:aKey];
|
||||
}
|
||||
|
||||
- (NSUInteger)count
|
||||
{
|
||||
return [dictionary count];
|
||||
}
|
||||
|
||||
- (id)objectForKey:(id)aKey
|
||||
{
|
||||
return [dictionary objectForKey:aKey];
|
||||
}
|
||||
|
||||
- (NSEnumerator *)keyEnumerator
|
||||
{
|
||||
return [array objectEnumerator];
|
||||
}
|
||||
|
||||
/*
|
||||
- (NSEnumerator *)reverseKeyEnumerator
|
||||
{
|
||||
return [array reverseObjectEnumerator];
|
||||
}
|
||||
*/
|
||||
|
||||
-(void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex
|
||||
{
|
||||
if([dictionary objectForKey:aKey])
|
||||
{
|
||||
[self removeObjectForKey:aKey];
|
||||
}
|
||||
[array insertObject:aKey atIndex:anIndex];
|
||||
[dictionary setObject:anObject forKey:aKey];
|
||||
}
|
||||
|
||||
-(id)keyAtIndex:(NSUInteger)anIndex
|
||||
{
|
||||
return [array objectAtIndex:anIndex];
|
||||
}
|
||||
|
||||
//given an key
|
||||
// ->return its index
|
||||
-(NSUInteger)indexOfKey:(id)aKey
|
||||
{
|
||||
return [array indexOfObject:aKey];
|
||||
}
|
||||
|
||||
-(void)reverse
|
||||
{
|
||||
array = [[[array reverseObjectEnumerator] allObjects] mutableCopy];
|
||||
}
|
||||
|
||||
/*
|
||||
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
|
||||
{
|
||||
NSMutableString *indentString = [NSMutableString string];
|
||||
NSUInteger i, count = level;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
[indentString appendFormat:@" "];
|
||||
}
|
||||
|
||||
NSMutableString *description = [NSMutableString string];
|
||||
[description appendFormat:@"%@{\n", indentString];
|
||||
for (NSObject *key in self)
|
||||
{
|
||||
[description appendFormat:@"%@ %@ = %@;\n",
|
||||
indentString,
|
||||
DescriptionForObject(key, locale, level),
|
||||
DescriptionForObject([self objectForKey:key], locale, level)];
|
||||
}
|
||||
[description appendFormat:@"%@}\n", indentString];
|
||||
return description;
|
||||
}
|
||||
*/
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// TAAdaptiveSpaceItem.h
|
||||
// TAAdaptiveSpaceItem
|
||||
//
|
||||
// Created by Timothy Armes on 17/02/2014.
|
||||
// Copyright (c) 2014 Timothy Armes. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface TAAdaptiveSpaceItem : NSToolbarItem
|
||||
|
||||
- (void)updateWidth;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// TAAdaptiveSpaceItem.m
|
||||
// TAAdaptiveSpaceItem
|
||||
//
|
||||
// Created by Timothy Armes on 17/02/2014.
|
||||
// Copyright (c) 2014 Timothy Armes. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TAAdaptiveSpaceItem.h"
|
||||
#import "TAAdaptiveSpaceItemView.h"
|
||||
|
||||
@implementation TAAdaptiveSpaceItem
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
TAAdaptiveSpaceItemView *adaptiveSpaceItemView = [[TAAdaptiveSpaceItemView alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)];
|
||||
adaptiveSpaceItemView.adaptiveSpaceItem = self;
|
||||
self.view = adaptiveSpaceItemView;
|
||||
}
|
||||
|
||||
- (NSString *)label
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString *)paletteLabel
|
||||
{
|
||||
return NSLocalizedString(@"Adaptive Space Item", @"Palette name when customising toolbar");
|
||||
}
|
||||
|
||||
- (NSSize)minSize
|
||||
{
|
||||
NSArray *items = [self.toolbar items];
|
||||
NSInteger index = [items indexOfObject:self];
|
||||
|
||||
if (index != NSNotFound) {
|
||||
NSRect thisFrame = self.view.superview.frame;
|
||||
if (thisFrame.origin.x > 0) {
|
||||
|
||||
CGFloat space = 0;
|
||||
if (items.count > index + 1) {
|
||||
|
||||
NSToolbarItem *nextItem = [items objectAtIndex:index + 1];
|
||||
NSRect nextFrame = nextItem.view.superview.frame;
|
||||
NSRect toolbarFrame = nextItem.view.superview.superview.frame;
|
||||
|
||||
space = (toolbarFrame.size.width - nextFrame.size.width) / 2 - thisFrame.origin.x - 6;
|
||||
if (space < 0)
|
||||
space = 0;
|
||||
}
|
||||
|
||||
NSSize size = [super minSize];
|
||||
return NSMakeSize(space, size.height);
|
||||
}
|
||||
}
|
||||
|
||||
return [super minSize];
|
||||
}
|
||||
|
||||
- (NSSize)maxSize
|
||||
{
|
||||
NSSize size = [super maxSize];
|
||||
return NSMakeSize([self minSize].width, size.height);
|
||||
}
|
||||
|
||||
- (void)updateWidth
|
||||
{
|
||||
[self setMinSize:[self minSize]];
|
||||
[self setMaxSize:[self maxSize]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// TAAdaptiveSpaceItemView.h
|
||||
// TAAdaptiveSpaceItem
|
||||
//
|
||||
// Created by Timothy Armes on 17/02/2014.
|
||||
// Copyright (c) 2014 Timothy Armes. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class TAAdaptiveSpaceItem;
|
||||
@interface TAAdaptiveSpaceItemView : NSView
|
||||
|
||||
@property (weak) TAAdaptiveSpaceItem *adaptiveSpaceItem;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// TAAdaptiveSpaceItemView.m
|
||||
// TAAdaptiveSpaceItem
|
||||
//
|
||||
// Created by Timothy Armes on 17/02/2014.
|
||||
// Copyright (c) 2014 Timothy Armes. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TAAdaptiveSpaceItemView.h"
|
||||
#import "TAAdaptiveSpaceItem.h"
|
||||
|
||||
@implementation TAAdaptiveSpaceItemView
|
||||
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResized:) name:NSWindowDidResizeNotification object:[self window]];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)windowResized:(NSNotification *)notification;
|
||||
{
|
||||
[_adaptiveSpaceItem updateWidth];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// PrefsWindowController.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AboutWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//version label/string
|
||||
@property (weak) IBOutlet NSTextField *versionLabel;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//invoked when user clicks 'more info' button
|
||||
// ->open KK's webpage
|
||||
- (IBAction)moreInfo:(id)sender;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// PrefsWindowController.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "AboutWindowController.h"
|
||||
|
||||
|
||||
@implementation AboutWindowController
|
||||
|
||||
@synthesize versionLabel;
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
//automatically invoked when window is loaded
|
||||
// ->set to white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//set version sting
|
||||
[self.versionLabel setStringValue:[NSString stringWithFormat:@"version: %@", getAppVersion()]];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'more info'
|
||||
// ->load knockknock's html page
|
||||
- (IBAction)moreInfo:(id)sender
|
||||
{
|
||||
//open URL
|
||||
// ->invokes user's default browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://objective-see.com/products/knockknock.html"]];
|
||||
|
||||
return;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Binary.h"
|
||||
#import "ItemBase.h"
|
||||
|
||||
#import "Filter.h"
|
||||
#import "VirusTotal.h"
|
||||
#import "TaskTableController.h"
|
||||
#import "TreeViewController.h"
|
||||
|
||||
#import "AboutWindowController.h"
|
||||
#import "PrefsWindowController.h"
|
||||
#import "ResultsWindowController.h"
|
||||
#import "RequestRootWindowController.h"
|
||||
|
||||
|
||||
#import "Task.h"
|
||||
#import "TaskEnumerator.h"
|
||||
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate, NSTableViewDataSource, NSTableViewDelegate, NSMenuDelegate>
|
||||
{
|
||||
//NSViewController *bottomViewController;
|
||||
|
||||
}
|
||||
|
||||
//@property (readonly) NSViewController *currentViewController;
|
||||
@property(nonatomic, retain)NSViewController *currentViewController;
|
||||
|
||||
//(current) bottom view controller
|
||||
@property(nonatomic, retain)TaskTableController *bottomViewController;
|
||||
|
||||
@property (weak) IBOutlet NSView *topPane;
|
||||
|
||||
//@property (weak) IBOutlet NSScrollView *taskScrollView;
|
||||
|
||||
//task enumerator object
|
||||
@property(nonatomic, retain)TaskEnumerator* taskEnumerator;
|
||||
|
||||
//task table controller object
|
||||
@property (nonatomic, retain)TaskTableController *taskTableController;
|
||||
|
||||
//tree (outline) controller
|
||||
@property (nonatomic, retain)TreeViewController* treeViewController;
|
||||
|
||||
//array to hold binary objects that are in array
|
||||
//@property (nonatomic, retain)NSMutableArray *tableContents;
|
||||
|
||||
//drop-down view selector
|
||||
|
||||
@property (weak) IBOutlet NSPopUpButton *viewSelector;
|
||||
|
||||
//segmented button for button pane
|
||||
// ->select to view dylib, files, network, etc
|
||||
@property (weak) IBOutlet NSSegmentedControl *bottomPaneBtn;
|
||||
|
||||
//action when segmented button is clicked
|
||||
-(IBAction)selectBottomPaneContent:(id)sender;
|
||||
|
||||
//bottom pane view
|
||||
@property (weak) IBOutlet NSView *bottomPane;
|
||||
|
||||
|
||||
@property (assign) IBOutlet NSWindow *window;
|
||||
|
||||
@property (weak) IBOutlet NSButton *logoButton;
|
||||
|
||||
|
||||
@property (weak) IBOutlet NSButton *showPreferencesButton;
|
||||
|
||||
//spinner
|
||||
@property (weak) IBOutlet NSProgressIndicator *progressIndicator;
|
||||
|
||||
//status msg
|
||||
@property (weak) IBOutlet NSTextField *statusText;
|
||||
|
||||
//non-UI thread that performs actual scan
|
||||
@property(nonatomic, strong)NSThread *scannerThread;
|
||||
|
||||
//filter object
|
||||
@property(nonatomic, retain)Filter* filterObj;
|
||||
|
||||
//virus total object
|
||||
@property(nonatomic, retain)VirusTotal* virusTotalObj;
|
||||
|
||||
//array for all virus total threads
|
||||
@property(nonatomic, retain)NSMutableArray* vtThreads;
|
||||
|
||||
//request root window controller
|
||||
@property(nonatomic, retain)RequestRootWindowController* requestRootWindowController;
|
||||
|
||||
//preferences window controller
|
||||
@property(nonatomic, retain)PrefsWindowController* prefsWindowController;
|
||||
|
||||
//about window controller
|
||||
@property(nonatomic, retain)AboutWindowController* aboutWindowController;
|
||||
|
||||
//results window controller
|
||||
@property(nonatomic, retain)ResultsWindowController* resultsWindowController;
|
||||
|
||||
//currently selected task
|
||||
@property(nonatomic, retain)Task* currentTask;
|
||||
|
||||
//activity indicator for bottom pane
|
||||
@property (weak) IBOutlet NSProgressIndicator *bottomPaneSpinner;
|
||||
|
||||
//'no items' found label for bottom pane
|
||||
@property (weak) IBOutlet NSTextField *noItemsLabel;
|
||||
|
||||
/* METHODS */
|
||||
- (IBAction)switchView:(id)sender;
|
||||
|
||||
//init tracking areas for buttons
|
||||
// ->provide mouse over effects
|
||||
-(void)initTrackingAreas;
|
||||
|
||||
//create instances of all registered plugins
|
||||
//-(NSMutableArray*)instantiatePlugins;
|
||||
|
||||
//callback method, invoked by plugin(s) when item is found
|
||||
// ->update the 'total' count and the item table (if active plugin is selected in UI)
|
||||
-(void)itemFound:(Task*)task;
|
||||
|
||||
//callback method, invoked by virus total when plugin's items have been processed
|
||||
// ->reload table if plugin matches active plugin
|
||||
//-(void)itemsProcessed:(PluginBase*)plugin;
|
||||
|
||||
//callback method, invoked by category table controller when user selects category
|
||||
// ->save the selected plugin & reload the item table
|
||||
-(void)categorySelected:(NSUInteger)rowIndex;
|
||||
|
||||
//callback when user has updated prefs
|
||||
// ->reload table, etc
|
||||
-(void)applyPreferences;
|
||||
|
||||
//update a single row
|
||||
-(void)itemProcessed:(Binary*)fileObj rowIndex:(NSUInteger)rowIndex;
|
||||
|
||||
//action
|
||||
// ->invoked when user clicks 'About/Info' or Objective-See logo in main UI
|
||||
-(void)displayScanStats;
|
||||
|
||||
-(IBAction)scanButtonHandler:(id)sender;
|
||||
|
||||
//button handler for when settings icon (gear) is clicked
|
||||
-(IBAction)showPreferences:(id)sender;
|
||||
|
||||
//kickoff a thread to query VT
|
||||
//-(void)queryVT:(PluginBase*)plugin;
|
||||
|
||||
//button handler for logo
|
||||
-(IBAction)logoButtonHandler:(id)sender;
|
||||
|
||||
//action for 'about' in menu/logo in UI
|
||||
-(IBAction)about:(id)sender;
|
||||
|
||||
//TODO add this, and move into properties
|
||||
//version string
|
||||
@property (weak) IBOutlet NSTextField *versionString;
|
||||
|
||||
//reload (to re-draw) a specific row in table
|
||||
-(void)reloadRow:(Task*)task item:(ItemBase*)item pane:(NSUInteger)pane;
|
||||
|
||||
//reload task table
|
||||
-(void)reloadTaskTable;
|
||||
|
||||
//smartly, reload bottom pane
|
||||
// ->checks if task & item type (e.g. files) are both selected
|
||||
-(void)reloadBottomPane:(Task*)task itemView:(NSUInteger)itemView;
|
||||
|
||||
//begin task enumeration
|
||||
-(void)exploreTasks;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,299 @@
|
||||
//
|
||||
// Consts.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/4/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KK_Consts_h
|
||||
#define KK_Consts_h
|
||||
|
||||
//button text, start scan
|
||||
#define START_SCAN @"Start Scan"
|
||||
|
||||
//button text, stop scan
|
||||
#define STOP_SCAN @"Stop Scan"
|
||||
|
||||
//status msg
|
||||
#define SCAN_MSG_STARTED @"scanning started"
|
||||
|
||||
//status msg
|
||||
#define SCAN_MSG_STOPPED @"scan stopped"
|
||||
|
||||
//status msg
|
||||
#define SCAN_MSG_COMPLETE @"scan complete"
|
||||
|
||||
//success
|
||||
#define STATUS_SUCCESS 0
|
||||
|
||||
//keys for signing stuff
|
||||
#define KEY_SIGNATURE_STATUS @"signatureStatus"
|
||||
#define KEY_SIGNING_AUTHORITIES @"signingAuthorities"
|
||||
|
||||
//OS version x
|
||||
#define OS_MAJOR_VERSION_X 10
|
||||
|
||||
//OS version lion
|
||||
#define OS_MINOR_VERSION_LION 8
|
||||
|
||||
//OS version yosemite
|
||||
#define OS_MINOR_VERSION_YOSEMITE 10
|
||||
|
||||
|
||||
//executable path
|
||||
#define EXECUTABLE_PATH @"@executable_path"
|
||||
|
||||
//loader path
|
||||
#define LOADER_PATH @"@loader_path"
|
||||
|
||||
//rpath
|
||||
#define RUN_SEARCH_PATH @"@rpath"
|
||||
|
||||
//path to LSOF
|
||||
#define LSOF @"/usr/sbin/lsof"
|
||||
|
||||
//hash key, SHA1
|
||||
#define KEY_HASH_SHA1 @"sha1"
|
||||
|
||||
//hash key, MD5
|
||||
#define KEY_HASH_MD5 @"md5"
|
||||
|
||||
//path to system profiler
|
||||
#define SYSTEM_PROFILER @"/usr/sbin/system_profiler"
|
||||
|
||||
//dyld_ key for launch items
|
||||
#define LAUNCH_ITEM_DYLD_KEY @"EnvironmentVariables"
|
||||
|
||||
//dyld_ key for applications
|
||||
#define APPLICATION_DYLD_KEY @"LSEnvironment"
|
||||
|
||||
//menu
|
||||
|
||||
//tag for prefs menu item
|
||||
#define PREF_MENU_ITEM_TAG 1
|
||||
|
||||
//main window
|
||||
|
||||
//space for File's button in time table (w/ VT info)
|
||||
#define TABLE_BUTTONS_FILE 225
|
||||
|
||||
//space for Extension's button in time table
|
||||
#define TABLE_BUTTONS_EXTENTION 135
|
||||
|
||||
|
||||
//scan button
|
||||
#define SCAN_BUTTON_TAG 1000
|
||||
|
||||
//pref button
|
||||
#define PREF_BUTTON_TAG 1001
|
||||
|
||||
//logo button
|
||||
#define LOGO_BUTTON_TAG 1002
|
||||
|
||||
//category table
|
||||
|
||||
|
||||
//id (tag) for detailed text in category table
|
||||
#define TABLE_ROW_NAME_TAG 100
|
||||
|
||||
//id (tag) for detailed text in category table
|
||||
#define TABLE_ROW_SUB_TEXT_TAG 101
|
||||
|
||||
//id (tag) for total's msg
|
||||
#define TABLE_ROW_TOTAL_TAG 102
|
||||
|
||||
|
||||
//item table
|
||||
|
||||
//id (tag) for signed icon
|
||||
#define TABLE_ROW_SIGNATURE_ICON 100
|
||||
|
||||
//id (tag) for path
|
||||
#define TABLE_ROW_PATH_LABEL 101
|
||||
|
||||
//id (tag) for plist
|
||||
#define TABLE_ROW_PID_LABEL 102
|
||||
|
||||
//id (tag) for 'virus total' button
|
||||
#define TABLE_ROW_VT_BUTTON 103
|
||||
|
||||
//id (tag) for 'info' button
|
||||
#define TABLE_ROW_INFO_BUTTON 105
|
||||
|
||||
//id (tag) for 'show' button
|
||||
#define TABLE_ROW_SHOW_BUTTON 107
|
||||
|
||||
//ellipis
|
||||
// ->for long paths...
|
||||
#define ELLIPIS @"..."
|
||||
|
||||
//known file hashes
|
||||
#define WHITE_LISTED_FILES @"whitelistedFiles"
|
||||
|
||||
//known commands
|
||||
#define WHITE_LISTED_COMMANDS @"whitelistedCommands"
|
||||
|
||||
//known extension hashes
|
||||
#define WHITE_LISTED_EXTENSIONS @"whitelistedExtensions"
|
||||
|
||||
//scanner option key
|
||||
// ->filter apple signed/known items
|
||||
#define KEY_SCANNER_FILTER @"filterItems"
|
||||
|
||||
//plugin key
|
||||
//#define KEY_RESULT_PLUGIN @"plugin"
|
||||
|
||||
//XPC Service name
|
||||
#define XPC_SERVICE @"remoteTaskService.xpc"
|
||||
|
||||
//location of kernel in pre-Yosemite
|
||||
#define KERNEL_PRE_YOSEMITE @"/System/Library/Kernels/kernel"
|
||||
|
||||
//location of kernel in Yosemite
|
||||
#define KERNEL_YOSEMITE @"/System/Library/Kernels/kernel"
|
||||
|
||||
//top pane
|
||||
|
||||
//top
|
||||
#define PANE_TOP 0x0
|
||||
|
||||
|
||||
//for prefs
|
||||
//#define PREF_FIRST_RUN @"isFirstRun"
|
||||
|
||||
//flat view
|
||||
#define FLAT_VIEW 100
|
||||
|
||||
//tree view
|
||||
#define TREE_VIEW 101
|
||||
|
||||
//bottom pane
|
||||
|
||||
//top
|
||||
#define PANE_BOTTOM 0x1
|
||||
|
||||
//any view
|
||||
// ->not in UI
|
||||
#define CURRENT_VIEW -1
|
||||
|
||||
//dylib view
|
||||
#define DYLIBS_VIEW 0
|
||||
|
||||
//file view
|
||||
#define FILES_VIEW 1
|
||||
|
||||
//networking view
|
||||
#define NETWORKING_VIEW 2
|
||||
|
||||
//pid
|
||||
#define KEY_RESULT_PID @"pid"
|
||||
|
||||
//name key
|
||||
#define KEY_RESULT_NAME @"name"
|
||||
|
||||
//path key
|
||||
#define KEY_RESULT_PATH @"path"
|
||||
|
||||
//plist key
|
||||
#define KEY_RESULT_PLIST @"plist"
|
||||
|
||||
//extension id key
|
||||
#define KEY_EXTENSION_ID @"id"
|
||||
|
||||
//extension description key
|
||||
#define KEY_EXTENSION_DETAILS @"details"
|
||||
|
||||
//extension (host) browser key
|
||||
#define KEY_EXTENSION_BROWSER @"browser"
|
||||
|
||||
/* VIRUS TOTAL */
|
||||
|
||||
//query url
|
||||
#define VT_QUERY_URL @"https://www.virustotal.com/partners/sysinternals/file-reports?apikey="
|
||||
|
||||
//requery url
|
||||
#define VT_REQUERY_URL @"https://www.virustotal.com/vtapi/v2/file/report"
|
||||
|
||||
//rescan url
|
||||
#define VT_RESCAN_URL @"https://www.virustotal.com/vtapi/v2/file/rescan"
|
||||
|
||||
//submit url
|
||||
#define VT_SUBMIT_URL @"https://www.virustotal.com/vtapi/v2/file/scan"
|
||||
|
||||
//api key
|
||||
#define VT_API_KEY @"233f22e200ca5822bd91103043ccac138b910db79f29af5616a9afe8b6f215ad"
|
||||
|
||||
//user agent
|
||||
#define VT_USER_AGENT @"VirusTotal"
|
||||
|
||||
//query count
|
||||
#define VT_MAX_QUERY_COUNT 25
|
||||
|
||||
//results
|
||||
#define VT_RESULTS @"data"
|
||||
|
||||
//results response code
|
||||
#define VT_RESULTS_RESPONSE @"response_code"
|
||||
|
||||
//result url
|
||||
#define VT_RESULTS_URL @"permalink"
|
||||
|
||||
//result hash
|
||||
#define VT_RESULT_HASH @"hash"
|
||||
|
||||
//results positives
|
||||
#define VT_RESULTS_POSITIVES @"positives"
|
||||
|
||||
//results total
|
||||
#define VT_RESULTS_TOTAL @"total"
|
||||
|
||||
//results scan id
|
||||
#define VT_RESULTS_SCANID @"scan_id"
|
||||
|
||||
//output file
|
||||
#define OUTPUT_FILE @"kkFindings.txt"
|
||||
|
||||
//keys/types for XPC dictionaries
|
||||
|
||||
//descriptor type
|
||||
#define KEY_DESCRIPTOR_TYPE @"descriptorType"
|
||||
|
||||
//file path
|
||||
#define KEY_FILE_PATH @"filePath"
|
||||
|
||||
//socket local ip addr
|
||||
#define KEY_LOCAL_ADDR @"localIPAddr"
|
||||
|
||||
//socket local port
|
||||
#define KEY_LOCAL_PORT @"localPort"
|
||||
|
||||
//socket remote ip addr
|
||||
#define KEY_REMOTE_ADDR @"remoteIPAddr"
|
||||
|
||||
//socket remote port
|
||||
#define KEY_REMOTE_PORT @"remotePort"
|
||||
|
||||
//socket state
|
||||
#define KEY_SOCKET_STATE @"socketState"
|
||||
|
||||
//socket type
|
||||
#define KEY_SOCKET_TYPE @"socketType"
|
||||
|
||||
//socket family
|
||||
#define KEY_SOCKET_FAMILY @"socketFamily"
|
||||
|
||||
//socket protocol
|
||||
#define KEY_SOCKET_PROTO @"socketProto"
|
||||
|
||||
//listening socket
|
||||
#define SOCKET_LISTENING @"listening"
|
||||
|
||||
//connected socket
|
||||
#define SOCKET_ESTABLISHED @"connected"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
|
||||
#import <syslog.h>
|
||||
#import <signal.h>
|
||||
|
||||
|
||||
//install exception/signal handlers
|
||||
void installExceptionHandlers();
|
||||
|
||||
//exception handler for Obj-C exceptions
|
||||
void exceptionHandler(NSException *exception);
|
||||
|
||||
//signal handler for *nix style exceptions
|
||||
void signalHandler(int signal, siginfo_t *info, void *context);
|
||||
|
||||
//display an alert
|
||||
void showAlert();
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Exception.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
|
||||
//install exception/signal handlers
|
||||
void installExceptionHandlers()
|
||||
{
|
||||
//sigaction struct
|
||||
struct sigaction sa = {0};
|
||||
|
||||
//init struct
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = signalHandler;
|
||||
|
||||
//exception handler
|
||||
NSSetUncaughtExceptionHandler(&exceptionHandler);
|
||||
|
||||
//install signal handlers
|
||||
sigaction(SIGILL, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
sigaction(SIGBUS, &sa, NULL);
|
||||
sigaction(SIGABRT, &sa, NULL);
|
||||
sigaction(SIGTRAP, &sa, NULL);
|
||||
sigaction(SIGFPE, &sa, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//display error alert
|
||||
void showAlert()
|
||||
{
|
||||
//response
|
||||
// ->index of button click
|
||||
NSModalResponse response = 0;
|
||||
|
||||
//alert box
|
||||
NSAlert* fullScanAlert = nil;
|
||||
|
||||
//alloc/init alert
|
||||
fullScanAlert = [NSAlert alertWithMessageText:@"ERROR: detected unrecoverable fault" defaultButton:@"Exit" alternateButton:@"Info" otherButton:nil informativeTextWithFormat:@"click 'Info' to help fix the issue!"];
|
||||
|
||||
//and show it
|
||||
response = [fullScanAlert runModal];
|
||||
|
||||
//handle case where user clicks 'Info'
|
||||
// ->take 'em to error page
|
||||
if(0 == response)
|
||||
{
|
||||
//open page in browser
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://objective-see.com/errors.html"]];
|
||||
}
|
||||
|
||||
//kill app
|
||||
exit(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//exception handler
|
||||
// will be invoked for Obj-C exceptions
|
||||
void exceptionHandler(NSException *exception)
|
||||
{
|
||||
//error msg
|
||||
NSString* errMsg = nil;
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: OS version: %s /App version: %s", [[[NSProcessInfo processInfo] operatingSystemVersionString] UTF8String], [getAppVersion() UTF8String]);
|
||||
|
||||
//create error msg
|
||||
errMsg = [NSString stringWithFormat:@"unhandled obj-c exception caught [name: %@ / reason: %@]", [exception name], [exception reason]];
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s", [errMsg UTF8String]);
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s", [[[NSThread callStackSymbols] description] UTF8String]);
|
||||
|
||||
//main thread
|
||||
// ->just show UI alert
|
||||
if(YES == [NSThread isMainThread])
|
||||
{
|
||||
//show
|
||||
showAlert();
|
||||
}
|
||||
//back thread
|
||||
// ->have to show it on main thread
|
||||
else
|
||||
{
|
||||
//show alert
|
||||
// ->in main UI thread
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//show
|
||||
showAlert();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//handler for signals
|
||||
// will be invoked for BSD/*nix signals
|
||||
void signalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
//error msg
|
||||
NSString* errMsg = nil;
|
||||
|
||||
//context
|
||||
ucontext_t *uContext = NULL;
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: OS version: %s /App version: %s", [[[NSProcessInfo processInfo] operatingSystemVersionString] UTF8String], [getAppVersion() UTF8String]);
|
||||
|
||||
//typecast context
|
||||
uContext = (ucontext_t *)context;
|
||||
|
||||
//create error msg
|
||||
errMsg = [NSString stringWithFormat:@"unhandled exception caught, si_signo: %d /si_code: %s /si_addr: %p /rip: %p",
|
||||
info->si_signo, (info->si_code == SEGV_MAPERR) ? "SEGV_MAPERR" : "SEGV_ACCERR", info->si_addr, (unsigned long*)uContext->uc_mcontext->__ss.__rip];
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s", [errMsg UTF8String]);
|
||||
|
||||
//err msg
|
||||
syslog(LOG_ERR, "OBJECTIVE-SEE ERROR: %s", [[[NSThread callStackSymbols] description] UTF8String]);
|
||||
|
||||
//main thread
|
||||
// ->just show UI alert
|
||||
if(YES == [NSThread isMainThread])
|
||||
{
|
||||
//show
|
||||
showAlert();
|
||||
}
|
||||
//back thread
|
||||
// ->have to show it on main thread
|
||||
else
|
||||
{
|
||||
//show alert
|
||||
// ->in main UI thread
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//show
|
||||
showAlert();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Filter.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/21/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
#import "File.h"
|
||||
#import "Binary.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Filter : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//white listed file hashes
|
||||
@property(nonatomic, retain)NSDictionary* trustedFiles;
|
||||
|
||||
//white listed commands
|
||||
@property(nonatomic, retain)NSDictionary* knownCommands;
|
||||
|
||||
//white listed extensions
|
||||
@property(nonatomic, retain)NSDictionary* trustedExtensions;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//load a (JSON) white list
|
||||
// ->file hashes, known commands, etc
|
||||
-(NSDictionary*)loadWhitelist:(NSString*)fileName;
|
||||
|
||||
//check if a File obj is whitelisted
|
||||
-(BOOL)isTrustedFile:(Binary*)fileObj;
|
||||
|
||||
//check if a Command obj is whitelisted
|
||||
//-(BOOL)isKnownCommand:(Command*)commandObj;
|
||||
|
||||
//check if a Extension obj is whitelisted
|
||||
//-(BOOL)isTrustedExtension:(Extension*)extensionObj;
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// Filter.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/21/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
#import "Consts.h"
|
||||
#import "Filter.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
@implementation Filter
|
||||
|
||||
@synthesize trustedFiles;
|
||||
@synthesize knownCommands;
|
||||
@synthesize trustedExtensions;
|
||||
|
||||
#define SOFTWARE_SIGNING @"Software Signing"
|
||||
#define APPLE_SIGNING_AUTH @"Apple Code Signing Certification Authority"
|
||||
#define APPLE_ROOT_CA @"Apple Root CA"
|
||||
|
||||
//init
|
||||
-(id)init
|
||||
{
|
||||
//super
|
||||
self = [super init];
|
||||
if(self)
|
||||
{
|
||||
//load known file hashes
|
||||
self.trustedFiles = [self loadWhitelist:WHITE_LISTED_FILES];
|
||||
|
||||
//load known commands
|
||||
self.knownCommands = [self loadWhitelist:WHITE_LISTED_COMMANDS];
|
||||
|
||||
//load known extensions
|
||||
self.trustedExtensions = [self loadWhitelist:WHITE_LISTED_EXTENSIONS];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//load a (JSON) white list
|
||||
// ->file hashes, known commands, etc
|
||||
-(NSDictionary*)loadWhitelist:(NSString*)fileName
|
||||
{
|
||||
//whitelisted data
|
||||
NSDictionary* whiteList = nil;
|
||||
|
||||
//path
|
||||
NSString* path = nil;
|
||||
|
||||
//error var
|
||||
NSError *error = nil;
|
||||
|
||||
//json data
|
||||
NSData* whiteListJSON = nil;
|
||||
|
||||
//init path
|
||||
path = [[NSBundle mainBundle] pathForResource:fileName ofType: @"json"];
|
||||
|
||||
//load whitelist file data
|
||||
whiteListJSON = [NSData dataWithContentsOfFile:path];
|
||||
|
||||
//convert JSON into dictionary
|
||||
whiteList = [NSJSONSerialization JSONObjectWithData:whiteListJSON options:kNilOptions error:&error];
|
||||
|
||||
return whiteList;
|
||||
}
|
||||
|
||||
|
||||
//check if a File obj is known
|
||||
// ->whitelisted *or* signed by apple
|
||||
-(BOOL)isTrustedFile:(Binary*)fileObj
|
||||
{
|
||||
//flag
|
||||
BOOL isTrusted = NO;
|
||||
|
||||
//known hashes for file name
|
||||
NSArray* knownHashes = nil;
|
||||
|
||||
//lookup based on name
|
||||
knownHashes = self.trustedFiles[fileObj.path];
|
||||
|
||||
//first check if hash is known
|
||||
if( (nil != knownHashes) &&
|
||||
(YES == [knownHashes containsObject:[fileObj.hashes[KEY_HASH_MD5] lowercaseString]]) )
|
||||
{
|
||||
//got match
|
||||
isTrusted = YES;
|
||||
}
|
||||
//then check if its signed by apple
|
||||
// ->apple-signed files are always trusted
|
||||
else
|
||||
{
|
||||
//check for apple signature
|
||||
isTrusted = isApple(fileObj.path);
|
||||
}
|
||||
|
||||
return isTrusted;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// InfoWindowController.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/21/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class ItemBase;
|
||||
|
||||
@interface InfoWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//properties in window
|
||||
// ->attributes about the item
|
||||
@property(weak)IBOutlet NSImageView *icon;
|
||||
@property(weak)IBOutlet NSTextField *name;
|
||||
@property(weak)IBOutlet NSTextField *path;
|
||||
@property(weak)IBOutlet NSTextField *date;
|
||||
|
||||
|
||||
//task-specific outlets
|
||||
@property (weak) IBOutlet NSTextField *arguments;
|
||||
|
||||
|
||||
//file window specific outlets
|
||||
@property(weak)IBOutlet NSTextField *hashes;
|
||||
@property(weak)IBOutlet NSTextField *size;
|
||||
@property(weak)IBOutlet NSTextField *sign;
|
||||
|
||||
|
||||
@property (weak) IBOutlet NSTextField *plist;
|
||||
|
||||
//extension window specific outlets
|
||||
@property (weak) IBOutlet NSTextField *details;
|
||||
@property (weak) IBOutlet NSTextField *identifier;
|
||||
|
||||
//window controller
|
||||
@property(nonatomic, strong)InfoWindowController *windowController;
|
||||
|
||||
//item
|
||||
@property(nonatomic, retain)ItemBase* itemObj;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init method
|
||||
// ->save item and load nib
|
||||
-(id)initWithItem:(id)selectedItem;
|
||||
|
||||
//configure window
|
||||
// ->add item's attributes (name, path, etc.)
|
||||
-(void)configure;
|
||||
|
||||
//check if something is nil
|
||||
// ->if so, return the default
|
||||
-(NSString*)valueForStringItem:(NSString*)item default:(NSString*)defaultValue;
|
||||
|
||||
//close button handler
|
||||
-(IBAction)closeWindow:(id)sender;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,315 @@
|
||||
//
|
||||
// InfoWindowController.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/21/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Task.h"
|
||||
#import "File.h"
|
||||
#import "Binary.h"
|
||||
#import "Connection.h"
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "InfoWindowController.h"
|
||||
|
||||
@interface InfoWindowController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation InfoWindowController
|
||||
|
||||
@synthesize itemObj;
|
||||
|
||||
//automatically invoked when window is loaded
|
||||
// ->set to white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//init method
|
||||
// ->save item and load nib
|
||||
-(id)initWithItem:(id)selectedItem
|
||||
{
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//load task info window
|
||||
if(YES == [selectedItem isKindOfClass:[Task class]])
|
||||
{
|
||||
//load nib
|
||||
self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"TaskInfoWindow"];
|
||||
}
|
||||
//load binary info window
|
||||
else if(YES == [selectedItem isKindOfClass:[Binary class]])
|
||||
{
|
||||
//load nib
|
||||
self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"DylibInfoWindow"];
|
||||
}
|
||||
|
||||
/*TODO: delete this and xibs?
|
||||
|
||||
//load file info window
|
||||
else if(YES == [selectedItem isKindOfClass:[File class]])
|
||||
{
|
||||
//load nib
|
||||
self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"FileInfoWindow"];
|
||||
}
|
||||
//load extension info window
|
||||
else if(YES == [selectedItem isKindOfClass:[Connection class]])
|
||||
{
|
||||
//load nib
|
||||
self.windowController = [[InfoWindowController alloc] initWithWindowNibName:@"ConnectionInfoWindow"];
|
||||
}
|
||||
*/
|
||||
|
||||
//save item
|
||||
self.windowController.itemObj = selectedItem;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->save self into iVar, and center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//configure UI
|
||||
[self configure];
|
||||
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
//configure window
|
||||
// ->add item's attributes (name, path, etc.)
|
||||
-(void)configure
|
||||
{
|
||||
//task
|
||||
// ->when showing info about a task
|
||||
Task* task = nil;
|
||||
|
||||
//binary
|
||||
// ->when showing info about a dylib
|
||||
Binary* dylib = nil;
|
||||
|
||||
//handle tasks
|
||||
if(YES == [self.itemObj isKindOfClass:[Task class]])
|
||||
{
|
||||
//cast as task
|
||||
task = (Task*)self.itemObj;
|
||||
|
||||
//set icon
|
||||
self.icon.image = task.binary.icon;
|
||||
|
||||
//set name
|
||||
[self.name setStringValue:[self valueForStringItem:task.binary.name default:@"unknown"]];
|
||||
|
||||
//set command line
|
||||
// ->done just in time (first time)
|
||||
if(nil == task.arguments)
|
||||
{
|
||||
//get args
|
||||
[((Task*)self.itemObj) getArguments];
|
||||
}
|
||||
|
||||
//set args
|
||||
[self.arguments setStringValue:[self valueForStringItem:[task.arguments componentsJoinedByString:@""] default:@"no arguments"]];
|
||||
|
||||
/*
|
||||
//flagged files
|
||||
// ->make name red!
|
||||
if( (nil != ((File*)self.itemObj).vtInfo) &&
|
||||
(0 != [((File*)self.itemObj).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
self.name.textColor = [NSColor redColor];
|
||||
}
|
||||
*/
|
||||
|
||||
//set path
|
||||
[self.path setStringValue:[self valueForStringItem:task.binary.path default:@"unknown"]];
|
||||
|
||||
|
||||
//set hash
|
||||
[self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", task.binary.hashes[KEY_HASH_MD5], task.binary.hashes[KEY_HASH_SHA1]]];
|
||||
|
||||
//set size
|
||||
[self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", task.binary.attributes.fileSize]];
|
||||
|
||||
//set date
|
||||
[self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", task.binary.attributes.fileCreationDate, task.binary.attributes.fileModificationDate]];
|
||||
|
||||
//set signing info
|
||||
[self.sign setStringValue:[self valueForStringItem:[task.binary formatSigningInfo] default:@"not signed"]];
|
||||
}
|
||||
|
||||
//handle tasks
|
||||
else if(YES == [self.itemObj isKindOfClass:[Binary class]])
|
||||
{
|
||||
//type cast
|
||||
dylib = (Binary*)self.itemObj;
|
||||
|
||||
//set icon
|
||||
self.icon.image = dylib.icon;
|
||||
|
||||
//set name
|
||||
[self.name setStringValue:[self valueForStringItem:dylib.name default:@"unknown"]];
|
||||
|
||||
|
||||
/*
|
||||
//flagged files
|
||||
// ->make name red!
|
||||
if( (nil != ((File*)self.itemObj).vtInfo) &&
|
||||
(0 != [((File*)self.itemObj).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
self.name.textColor = [NSColor redColor];
|
||||
}
|
||||
*/
|
||||
|
||||
//set path
|
||||
[self.path setStringValue:[self valueForStringItem:dylib.path default:@"unknown"]];
|
||||
|
||||
|
||||
//set hash
|
||||
[self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", dylib.hashes[KEY_HASH_MD5], task.binary.hashes[KEY_HASH_SHA1]]];
|
||||
|
||||
//set size
|
||||
[self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", dylib.attributes.fileSize]];
|
||||
|
||||
//set date
|
||||
[self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", dylib.attributes.fileCreationDate, task.binary.attributes.fileModificationDate]];
|
||||
|
||||
//set signing info
|
||||
[self.sign setStringValue:[self valueForStringItem:[dylib formatSigningInfo] default:@"not signed"]];
|
||||
}
|
||||
|
||||
|
||||
//handle File class
|
||||
else if(YES == [self.itemObj isKindOfClass:[File class]])
|
||||
{
|
||||
//set icon
|
||||
self.icon.image = getIconForBinary(self.itemObj.path, ((File*)itemObj).bundle);
|
||||
|
||||
//set name
|
||||
[self.name setStringValue:self.itemObj.name];
|
||||
|
||||
/*
|
||||
|
||||
//flagged files
|
||||
// ->make name red!
|
||||
if( (nil != ((Binary*)self.itemObj).vtInfo) &&
|
||||
(0 != [((File*)self.itemObj).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
self.name.textColor = [NSColor redColor];
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//set path
|
||||
[self.path setStringValue:self.itemObj.path];
|
||||
|
||||
//set hash
|
||||
[self.hashes setStringValue:[NSString stringWithFormat:@"%@ / %@", ((File*)self.itemObj).hashes[KEY_HASH_MD5], ((File*)self.itemObj).hashes[KEY_HASH_SHA1]]];
|
||||
|
||||
//set size
|
||||
[self.size setStringValue:[NSString stringWithFormat:@"%llu bytes", ((File*)self.itemObj).attributes.fileSize]];
|
||||
|
||||
//set date
|
||||
[self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", ((File*)self.itemObj).attributes.fileCreationDate, ((File*)self.itemObj).attributes.fileModificationDate]];
|
||||
|
||||
//set plist
|
||||
if(nil != ((File*)self.itemObj).plist)
|
||||
{
|
||||
//set
|
||||
[self.plist setStringValue:((File*)self.itemObj).plist];
|
||||
}
|
||||
//no plist
|
||||
else
|
||||
{
|
||||
//set
|
||||
[self.plist setStringValue:@"no plist for item"];
|
||||
}
|
||||
|
||||
//set signing info
|
||||
[self.sign setStringValue:[(File*)self.itemObj formatSigningInfo]];
|
||||
}
|
||||
|
||||
/*
|
||||
//handle Extension class
|
||||
if(YES == [self.itemObj isKindOfClass:[Extension class]])
|
||||
{
|
||||
//set icon
|
||||
self.icon.image = getIconForBinary(((Extension*)itemObj).browser, nil);
|
||||
|
||||
//set name
|
||||
[self.name setStringValue:self.itemObj.name];
|
||||
|
||||
//set path
|
||||
[self.path setStringValue:self.itemObj.path];
|
||||
|
||||
//set description
|
||||
// ->optional
|
||||
if(nil != ((Extension*)self.itemObj).details)
|
||||
{
|
||||
//set
|
||||
[self.details setStringValue:[NSString stringWithFormat:@"%@", ((Extension*)self.itemObj).details]];
|
||||
}
|
||||
|
||||
//set id
|
||||
[self.identifier setStringValue:[NSString stringWithFormat:@"%@", ((Extension*)self.itemObj).identifier]];
|
||||
|
||||
//set date
|
||||
[self.date setStringValue:[NSString stringWithFormat:@"%@ (created) / %@ (modified)", ((File*)self.itemObj).attributes.fileCreationDate, ((File*)self.itemObj).attributes.fileModificationDate]];
|
||||
|
||||
//set signing info
|
||||
//[self.sign setStringValue:[(File*)self.itemObj formatSigningInfo]];
|
||||
}
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//check if something is nil
|
||||
// ->if so, return the default
|
||||
-(NSString*)valueForStringItem:(NSString*)item default:(NSString*)defaultValue
|
||||
{
|
||||
//return value
|
||||
NSString* value = nil;
|
||||
|
||||
//check if item is nil/blank
|
||||
if( (nil != item) &&
|
||||
(item.length != 0))
|
||||
{
|
||||
//just set to item
|
||||
value = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
//set to default
|
||||
value = defaultValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'close'
|
||||
// ->just close window
|
||||
-(IBAction)closeWindow:(id)sender
|
||||
{
|
||||
//close
|
||||
[self.window close];
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// ItemView.h
|
||||
// TaskExplorer
|
||||
//
|
||||
// Created by Patrick Wardle on 5/23/15.
|
||||
// Copyright (c) 2015 Lucas Derraugh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "File.h"
|
||||
#import "Task.h"
|
||||
#import "Binary.h"
|
||||
#import "Connection.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//create customize item view
|
||||
NSTableCellView* createItemView(NSTableView* tableView, id owner, id item);
|
||||
|
||||
//create & customize task view
|
||||
NSTableCellView* createTaskView(NSTableView* tableView, id owner, id item);
|
||||
|
||||
//create & customize dylib view
|
||||
NSTableCellView* createDylibView(NSTableView* tableView, id owner, Binary* dylib);
|
||||
|
||||
//create & customize file view
|
||||
NSTableCellView* createFileView(NSTableView* tableView, id owner, File* file);
|
||||
|
||||
//create & customize networking view
|
||||
NSTableCellView* createNetworkView(NSTableView* tableView, id owner, Connection* connection);
|
||||
|
||||
//add a tracking area to a view within the item view
|
||||
void addTrackingArea(NSTableCellView* itemView, NSUInteger subviewTag, id owner);
|
||||
|
||||
//set code signing image
|
||||
// ->either signed, unsigned, or unknown
|
||||
NSImage* getCodeSigningIcon(Binary* binary);
|
||||
@@ -0,0 +1,737 @@
|
||||
//
|
||||
// ItemView.m
|
||||
// TaskExplorer
|
||||
//
|
||||
// Created by Patrick Wardle on 5/23/15.
|
||||
// Copyright (c) 2015 Lucas Derraugh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "ItemView.h"
|
||||
#import "VTButton.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "3rdParty/OrderedDictionary.h"
|
||||
|
||||
//create customize item view
|
||||
NSTableCellView* createItemView(NSTableView* tableView, id owner, id item)
|
||||
{
|
||||
//item cell
|
||||
NSTableCellView *itemCell = nil;
|
||||
|
||||
//signature icon
|
||||
NSImageView* signatureImageView = nil;
|
||||
|
||||
//VT detection ratio
|
||||
NSString* vtDetectionRatio = nil;
|
||||
|
||||
//virus total button
|
||||
// ->for File objects only...
|
||||
VTButton* vtButton;
|
||||
|
||||
//(for files) signed/unsigned icon
|
||||
NSImage* signatureStatus = nil;
|
||||
|
||||
//task's name frame
|
||||
CGRect nameFrame = {0};
|
||||
|
||||
//attribute dictionary
|
||||
NSMutableDictionary *stringAttributes = nil;
|
||||
|
||||
//paragraph style
|
||||
NSMutableParagraphStyle *paragraphStyle = nil;
|
||||
|
||||
//binary obj
|
||||
ItemBase* baseItem = nil;
|
||||
|
||||
//truncated path
|
||||
//NSString* truncatedPath = nil;
|
||||
|
||||
//truncated plist
|
||||
//NSString* truncatedPlist = nil;
|
||||
|
||||
//tracking area
|
||||
NSTrackingArea* trackingArea = nil;
|
||||
|
||||
//flag indicating row has tracking area
|
||||
// ->ensures we don't add 2x
|
||||
BOOL hasTrackingArea = NO;
|
||||
|
||||
//sanity chec
|
||||
if(nil == item)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//logic to create task view
|
||||
if(YES == [item isKindOfClass:[Task class]])
|
||||
{
|
||||
//create & config view
|
||||
itemCell = createTaskView(tableView, owner, item);
|
||||
}
|
||||
|
||||
//logic to create dylib view
|
||||
else if(YES == [item isKindOfClass:[Binary class]])
|
||||
{
|
||||
//create & config view
|
||||
itemCell = createDylibView(tableView, owner, item);
|
||||
}
|
||||
|
||||
//logic to create file view
|
||||
else if(YES == [item isKindOfClass:[File class]])
|
||||
{
|
||||
//create & config view
|
||||
itemCell = createFileView(tableView, owner, item);
|
||||
}
|
||||
|
||||
//logic to create network view
|
||||
else if(YES == [item isKindOfClass:[Connection class]])
|
||||
{
|
||||
//create & config view
|
||||
itemCell = createNetworkView(tableView, owner, item);
|
||||
}
|
||||
|
||||
return itemCell;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//set
|
||||
baseItem = ((Task*)item).binary;
|
||||
}
|
||||
//otherwise just assign
|
||||
else
|
||||
{
|
||||
//set
|
||||
baseItem = item;
|
||||
}
|
||||
|
||||
//bail if base item is nil
|
||||
// ->e.g. task doesn't have any dylibs, etc
|
||||
if(nil == baseItem)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//make table cell
|
||||
itemCell = [tableView makeViewWithIdentifier:@"TaskCell" owner:owner];
|
||||
if(nil == itemCell)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//check if cell was previously used (by checking the item name)
|
||||
// ->if so, set flag to indicated tracking area does not need to be added
|
||||
if(YES != [itemCell.textField.stringValue isEqualToString:@"Item Name"])
|
||||
{
|
||||
//set flag
|
||||
hasTrackingArea = YES;
|
||||
}
|
||||
|
||||
//default
|
||||
// ->set main textfield's color to black
|
||||
itemCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//set main text
|
||||
// ->name
|
||||
[itemCell.textField setStringValue:baseItem.name];
|
||||
|
||||
//get name frame
|
||||
nameFrame = itemCell.textField.frame;
|
||||
|
||||
//adjust width to fit text
|
||||
nameFrame.size.width = [itemCell.textField.stringValue sizeWithAttributes: @{NSFontAttributeName: itemCell.textField.font}].width + 5;
|
||||
|
||||
//disable autolayout
|
||||
itemCell.textField.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
|
||||
//update frame
|
||||
// ->should now be exact size of text
|
||||
itemCell.textField.frame = nameFrame;
|
||||
|
||||
//[itemCell.textField setDrawsBackground:YES];
|
||||
|
||||
//NSLog(@"size after: %f", itemCell.textField.frame.size.width);
|
||||
|
||||
//itemCell.textField.backgroundColor = [NSColor redColor];
|
||||
|
||||
*/
|
||||
|
||||
//set pid for tasks
|
||||
if(YES == [item isKindOfClass:[Task class]])
|
||||
{
|
||||
//set pid
|
||||
[((NSTextField*)[itemCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:[NSString stringWithFormat:@"(%@)", ((Task*)item).pid]];
|
||||
}
|
||||
//otherwise nil out pid
|
||||
else
|
||||
{
|
||||
//set to nil to hide
|
||||
[((NSTextField*)[itemCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:@""];
|
||||
}
|
||||
|
||||
//only have to add tracking area once
|
||||
// ->add it the first time
|
||||
if(NO == hasTrackingArea)
|
||||
{
|
||||
//init tracking area
|
||||
// ->for 'show' button
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:[[itemCell viewWithTag:TABLE_ROW_SHOW_BUTTON] bounds]
|
||||
options:(NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
|
||||
owner:owner userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:TABLE_ROW_SHOW_BUTTON]}];
|
||||
|
||||
//add tracking area to 'show' button
|
||||
[[itemCell viewWithTag:TABLE_ROW_SHOW_BUTTON] addTrackingArea:trackingArea];
|
||||
|
||||
//init tracking area
|
||||
// ->for 'info' button
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:[[itemCell viewWithTag:TABLE_ROW_INFO_BUTTON] bounds]
|
||||
options:(NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
|
||||
owner:owner userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:TABLE_ROW_INFO_BUTTON]}];
|
||||
|
||||
//add tracking area to 'info' button
|
||||
[[itemCell viewWithTag:TABLE_ROW_INFO_BUTTON] addTrackingArea:trackingArea];
|
||||
}
|
||||
|
||||
//set detailed text
|
||||
// ->path
|
||||
//if(YES == [item isKindOfClass:[File class]])
|
||||
//{
|
||||
//grab virus total button
|
||||
// ->need it for frame computations, etc
|
||||
vtButton = [itemCell viewWithTag:TABLE_ROW_VT_BUTTON];
|
||||
|
||||
//set image
|
||||
// ->app's icon
|
||||
itemCell.imageView.image = [baseItem icon];
|
||||
|
||||
//Tasks and Dylibs
|
||||
// ->set signature icon
|
||||
if( (YES == [item isKindOfClass:[Task class]]) ||
|
||||
(YES == [item isKindOfClass:[Binary class]]) )
|
||||
{
|
||||
//get signature image view
|
||||
signatureImageView = [itemCell viewWithTag:TABLE_ROW_SIGNATURE_ICON];
|
||||
|
||||
//set signature status icon
|
||||
// note: if binary doesn't have signing info, default ('?') is shown...
|
||||
if(nil != ((Binary*)baseItem).signingInfo)
|
||||
{
|
||||
if(STATUS_SUCCESS == [((Binary*)baseItem).signingInfo[KEY_SIGNATURE_STATUS] integerValue])
|
||||
{
|
||||
//signed
|
||||
signatureImageView.image = [NSImage imageNamed:@"signed"];
|
||||
}
|
||||
else
|
||||
{
|
||||
//unsigned
|
||||
signatureImageView.image = [NSImage imageNamed:@"unsigned"];
|
||||
}
|
||||
}
|
||||
|
||||
//show signature icon
|
||||
signatureImageView.hidden = NO;
|
||||
}
|
||||
//non-executable files
|
||||
// ->hide signature icon
|
||||
else
|
||||
{
|
||||
//hide
|
||||
signatureImageView.hidden = YES;
|
||||
}
|
||||
|
||||
//set detailed text
|
||||
// ->always item's path
|
||||
[[itemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:baseItem.path];
|
||||
|
||||
/*
|
||||
//for files w/ plist
|
||||
// ->set/show
|
||||
if(nil != task.plist)
|
||||
{
|
||||
//shift up frame
|
||||
pathFrame.origin.y = 20;
|
||||
|
||||
//set new frame
|
||||
((NSTextField*)[itemCell viewWithTag:TABLE_ROW_PATH_LABEL]).frame = pathFrame;
|
||||
|
||||
//truncate plist
|
||||
truncatedPlist = stringByTruncatingString([itemCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG], ((File*)item).plist, itemCell.frame.size.width-TABLE_BUTTONS_FILE);
|
||||
|
||||
//set plist
|
||||
[((NSTextField*)[itemCell viewWithTag:TABLE_ROW_PLIST_LABEL]) setStringValue:truncatedPlist];
|
||||
|
||||
//show
|
||||
[((NSTextField*)[itemCell viewWithTag:TABLE_ROW_PLIST_LABEL]) setHidden:NO];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//configure/show VT info
|
||||
// ->only if 'disable' preference not set
|
||||
if(YES != ((AppDelegate*)[[NSApplication sharedApplication] delegate]).prefsWindowController.disableVTQueries)
|
||||
{
|
||||
//set button delegate
|
||||
vtButton.delegate = self;
|
||||
|
||||
//save file obj
|
||||
vtButton.fileObj = task
|
||||
|
||||
//check if have vt results
|
||||
if(nil != ((File*)item).vtInfo)
|
||||
{
|
||||
//set font
|
||||
[vtButton setFont:[NSFont fontWithName:@"Menlo-Bold" size:25]];
|
||||
|
||||
//enable
|
||||
vtButton.enabled = YES;
|
||||
|
||||
//got VT results
|
||||
// ->check 'permalink' to determine if file is known to VT
|
||||
// then, show ratio and set to red if file is flagged
|
||||
if(nil != ((File*)item).vtInfo[VT_RESULTS_URL])
|
||||
{
|
||||
//alloc paragraph style
|
||||
paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
|
||||
//center the text
|
||||
[paragraphStyle setAlignment:NSCenterTextAlignment];
|
||||
|
||||
//alloc attributes dictionary
|
||||
stringAttributes = [NSMutableDictionary dictionary];
|
||||
|
||||
//set underlined attribute
|
||||
stringAttributes[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
|
||||
|
||||
//set alignment (center)
|
||||
stringAttributes[NSParagraphStyleAttributeName] = paragraphStyle;
|
||||
|
||||
//set font
|
||||
stringAttributes[NSFontAttributeName] = [NSFont fontWithName:@"Menlo-Bold" size:15];
|
||||
|
||||
//compute detection ratio
|
||||
vtDetectionRatio = [NSString stringWithFormat:@"%lu/%lu", (unsigned long)[((File*)item).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue], (unsigned long)[((File*)item).vtInfo[VT_RESULTS_TOTAL] unsignedIntegerValue]];
|
||||
|
||||
//known 'good' files (0 positivies)
|
||||
if(0 == [((File*)item).vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue])
|
||||
{
|
||||
//(re)set title black
|
||||
itemCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//set color (black)
|
||||
stringAttributes[NSForegroundColorAttributeName] = [NSColor blackColor];
|
||||
|
||||
//set string (vt ratio), with attributes
|
||||
[vtButton setAttributedTitle:[[NSAttributedString alloc] initWithString:vtDetectionRatio attributes:stringAttributes]];
|
||||
|
||||
//set color (gray)
|
||||
stringAttributes[NSForegroundColorAttributeName] = [NSColor grayColor];
|
||||
|
||||
//set selected text color
|
||||
[vtButton setAttributedAlternateTitle:[[NSAttributedString alloc] initWithString:vtDetectionRatio attributes:stringAttributes]];
|
||||
}
|
||||
//files flagged by VT
|
||||
// ->set name and detection to red
|
||||
else
|
||||
{
|
||||
//set title red
|
||||
itemCell.textField.textColor = [NSColor redColor];
|
||||
|
||||
//set color (red)
|
||||
stringAttributes[NSForegroundColorAttributeName] = [NSColor redColor];
|
||||
|
||||
//set string (vt ratio), with attributes
|
||||
[vtButton setAttributedTitle:[[NSAttributedString alloc] initWithString:vtDetectionRatio attributes:stringAttributes]];
|
||||
|
||||
//set selected text color
|
||||
[vtButton setAttributedAlternateTitle:[[NSAttributedString alloc] initWithString:vtDetectionRatio attributes:stringAttributes]];
|
||||
|
||||
}
|
||||
|
||||
//enable
|
||||
[vtButton setEnabled:YES];
|
||||
}
|
||||
|
||||
//file is not known
|
||||
// ->reset title to '?'
|
||||
else
|
||||
{
|
||||
//set title
|
||||
[vtButton setTitle:@"?"];
|
||||
}
|
||||
}
|
||||
|
||||
//no VT results (e.g. unknown file)
|
||||
else
|
||||
{
|
||||
//set font
|
||||
[vtButton setFont:[NSFont fontWithName:@"Menlo-Bold" size:8]];
|
||||
|
||||
//set title
|
||||
[vtButton setTitle:@"▪ ▪ ▪"];
|
||||
|
||||
//disable
|
||||
vtButton.enabled = NO;
|
||||
}
|
||||
|
||||
//show virus total button
|
||||
vtButton.hidden = NO;
|
||||
|
||||
//show virus total label
|
||||
[[itemCell viewWithTag:TABLE_ROW_VT_BUTTON+1] setHidden:NO];
|
||||
|
||||
}//show VT info (pref not disabled)
|
||||
|
||||
//hide VT info
|
||||
else
|
||||
{
|
||||
//hide virus total button
|
||||
vtButton.hidden = YES;
|
||||
|
||||
//hide virus total button label
|
||||
[[itemCell viewWithTag:TABLE_ROW_VT_BUTTON+1] setHidden:YES];
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return itemCell;
|
||||
}
|
||||
|
||||
//add a tracking area to a view within the item view
|
||||
void addTrackingArea(NSTableCellView* itemView, NSUInteger subviewTag, id owner)
|
||||
{
|
||||
//tracking area
|
||||
NSTrackingArea* trackingArea = nil;
|
||||
|
||||
//alloc/init tracking area
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:[[itemView viewWithTag:subviewTag] bounds] options:(NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:owner userInfo:@{@"tag":[NSNumber numberWithUnsignedInteger:subviewTag]}];
|
||||
|
||||
//add tracking area to subview
|
||||
[[itemView viewWithTag:subviewTag] addTrackingArea:trackingArea];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//set code signing image
|
||||
// ->either signed, unsigned, or unknown
|
||||
NSImage* getCodeSigningIcon(Binary* binary)
|
||||
{
|
||||
//signature image
|
||||
NSImage* codeSignIcon = nil;
|
||||
|
||||
//set signature status icon
|
||||
if(nil != binary.signingInfo)
|
||||
{
|
||||
//binary is signed
|
||||
if(STATUS_SUCCESS == [binary.signingInfo[KEY_SIGNATURE_STATUS] integerValue])
|
||||
{
|
||||
//set
|
||||
codeSignIcon = [NSImage imageNamed:@"signed"];
|
||||
}
|
||||
|
||||
//binary not signed
|
||||
else if(errSecCSUnsigned == [binary.signingInfo[KEY_SIGNATURE_STATUS] integerValue])
|
||||
{
|
||||
//set
|
||||
codeSignIcon = [NSImage imageNamed:@"unsigned"];
|
||||
}
|
||||
|
||||
//unknown
|
||||
else
|
||||
{
|
||||
//set
|
||||
codeSignIcon = [NSImage imageNamed:@"unknown"];
|
||||
}
|
||||
}
|
||||
//signing info is nil
|
||||
// ->just to unknown
|
||||
else
|
||||
{
|
||||
//set
|
||||
codeSignIcon = [NSImage imageNamed:@"unknown"];
|
||||
}
|
||||
|
||||
return codeSignIcon;
|
||||
|
||||
}
|
||||
|
||||
//create & customize Task view
|
||||
NSTableCellView* createTaskView(NSTableView* tableView, id owner, Task* task)
|
||||
{
|
||||
//item cell
|
||||
NSTableCellView* taskCell = nil;
|
||||
|
||||
//task's name frame
|
||||
CGRect nameFrame = {0};
|
||||
|
||||
//sanity check
|
||||
if(nil == task.binary)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//create cell
|
||||
taskCell = [tableView makeViewWithIdentifier:@"TaskCell" owner:owner];
|
||||
if(nil == taskCell)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//brand new cells need tracking areas
|
||||
// ->determine if new, by checking default (.xib/IB) value
|
||||
if(YES == [taskCell.textField.stringValue isEqualToString:@"Task Name"])
|
||||
{
|
||||
//add tracking area
|
||||
// ->'vt' button
|
||||
addTrackingArea(taskCell, TABLE_ROW_VT_BUTTON, owner);
|
||||
|
||||
//add tracking area
|
||||
// ->'info' button
|
||||
addTrackingArea(taskCell, TABLE_ROW_INFO_BUTTON, owner);
|
||||
|
||||
//add tracking area
|
||||
// ->'show' button
|
||||
addTrackingArea(taskCell, TABLE_ROW_SHOW_BUTTON, owner);
|
||||
}
|
||||
|
||||
//set icon
|
||||
taskCell.imageView.image = [task.binary icon];
|
||||
|
||||
//set code signing icon
|
||||
((NSImageView*)[taskCell viewWithTag:TABLE_ROW_SIGNATURE_ICON]).image = getCodeSigningIcon(task.binary);
|
||||
|
||||
//default
|
||||
// ->(re)set main textfield's color to black
|
||||
taskCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//set main text
|
||||
// ->name
|
||||
[taskCell.textField setStringValue:task.binary.name];
|
||||
|
||||
//get name frame
|
||||
nameFrame = taskCell.textField.frame;
|
||||
|
||||
//adjust width to fit text
|
||||
nameFrame.size.width = [taskCell.textField.stringValue sizeWithAttributes: @{NSFontAttributeName: taskCell.textField.font}].width + 5;
|
||||
|
||||
//disable autolayout for name
|
||||
taskCell.textField.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
|
||||
//update name frame
|
||||
// ->should now be exact size of text
|
||||
taskCell.textField.frame = nameFrame;
|
||||
|
||||
//set pid
|
||||
// ->immediately follows name
|
||||
[((NSTextField*)[taskCell viewWithTag:TABLE_ROW_PID_LABEL]) setStringValue:[NSString stringWithFormat:@"(%@)", task.pid]];
|
||||
|
||||
//set path
|
||||
[[taskCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:task.binary.path];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return taskCell;
|
||||
}
|
||||
|
||||
//create & customize dylib view
|
||||
NSTableCellView* createDylibView(NSTableView* tableView, id owner, Binary* dylib)
|
||||
{
|
||||
//item cell
|
||||
NSTableCellView* dylibCell = nil;
|
||||
|
||||
//create cell
|
||||
dylibCell = [tableView makeViewWithIdentifier:@"DylibCell" owner:owner];
|
||||
if(nil == dylibCell)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//brand new cells need tracking areas
|
||||
// ->determine if new, by checking default (.xib/IB) value
|
||||
if(YES == [dylibCell.textField.stringValue isEqualToString:@"Dylib Name"])
|
||||
{
|
||||
//add tracking area
|
||||
// ->'vt' button
|
||||
addTrackingArea(dylibCell, TABLE_ROW_VT_BUTTON, owner);
|
||||
|
||||
//add tracking area
|
||||
// ->'info' button
|
||||
addTrackingArea(dylibCell, TABLE_ROW_INFO_BUTTON, owner);
|
||||
|
||||
//add tracking area
|
||||
// ->'show' button
|
||||
addTrackingArea(dylibCell, TABLE_ROW_SHOW_BUTTON, owner);
|
||||
}
|
||||
|
||||
//set code signing icon
|
||||
((NSImageView*)[dylibCell viewWithTag:TABLE_ROW_SIGNATURE_ICON]).image = getCodeSigningIcon(dylib);
|
||||
|
||||
//default
|
||||
// ->(re)set main textfield's color to black
|
||||
dylibCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//set main text
|
||||
// ->name
|
||||
[dylibCell.textField setStringValue:dylib.name];
|
||||
|
||||
//set path
|
||||
[[dylibCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:dylib.path];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return dylibCell;
|
||||
}
|
||||
|
||||
|
||||
//create & customize file view
|
||||
NSTableCellView* createFileView(NSTableView* tableView, id owner, File* file)
|
||||
{
|
||||
//item cell
|
||||
NSTableCellView* fileCell = nil;
|
||||
|
||||
//sanity check
|
||||
if(nil == file)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//create cell
|
||||
fileCell = [tableView makeViewWithIdentifier:@"FileCell" owner:owner];
|
||||
if(nil == fileCell)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//brand new cells need tracking areas
|
||||
// ->determine if new, by checking default (.xib/IB) value
|
||||
if(YES == [fileCell.textField.stringValue isEqualToString:@"Dylib Name"])
|
||||
{
|
||||
//add tracking area
|
||||
// ->'info' button
|
||||
addTrackingArea(fileCell, TABLE_ROW_INFO_BUTTON, owner);
|
||||
|
||||
//add tracking area
|
||||
// ->'show' button
|
||||
addTrackingArea(fileCell, TABLE_ROW_SHOW_BUTTON, owner);
|
||||
}
|
||||
|
||||
//default
|
||||
// ->(re)set main textfield's color to black
|
||||
fileCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//set main text
|
||||
// ->name
|
||||
[fileCell.textField setStringValue:file.name];
|
||||
|
||||
//set path
|
||||
[[fileCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:file.path];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return fileCell;
|
||||
}
|
||||
|
||||
//create & customize networking view
|
||||
NSTableCellView* createNetworkView(NSTableView* tableView, id owner, Connection* connection)
|
||||
{
|
||||
//item cell
|
||||
NSTableCellView* connectionCell = nil;
|
||||
|
||||
//connection endpoint
|
||||
NSMutableString* endpoints = nil;
|
||||
|
||||
//connection details
|
||||
NSMutableString* details = nil;
|
||||
|
||||
//alloc string for endpoints
|
||||
endpoints = [NSMutableString string];
|
||||
|
||||
//alloc string for details
|
||||
details = [NSMutableString string];
|
||||
|
||||
//create cell
|
||||
connectionCell = [tableView makeViewWithIdentifier:@"NetworkCell" owner:owner];
|
||||
if(nil == connectionCell)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set icon
|
||||
//TODO: (re)set default icon!?
|
||||
if(nil != connection.state)
|
||||
{
|
||||
//listening
|
||||
if(YES == [connection.state isEqualToString:SOCKET_LISTENING])
|
||||
{
|
||||
//set
|
||||
connectionCell.imageView.image = [NSImage imageNamed:@"listeningIcon"];
|
||||
}
|
||||
//connected
|
||||
else if(YES == [connection.state isEqualToString:SOCKET_ESTABLISHED])
|
||||
{
|
||||
//set
|
||||
connectionCell.imageView.image = [NSImage imageNamed:@"connectedIcon"];
|
||||
}
|
||||
}
|
||||
|
||||
//default
|
||||
// ->(re)set main textfield's color to black
|
||||
connectionCell.textField.textColor = [NSColor blackColor];
|
||||
|
||||
//add local addr/port to endpoint string
|
||||
[endpoints appendString:[NSString stringWithFormat:@"%@:%d", connection.localIPAddr, [connection.localPort unsignedShortValue]]];
|
||||
|
||||
//for remote connections
|
||||
// ->add remote endpoint
|
||||
if( (nil != connection.remoteIPAddr) &&
|
||||
(nil != connection.remotePort) )
|
||||
{
|
||||
//add remote endpoint
|
||||
[endpoints appendString:[NSString stringWithFormat:@" -> %@:%d", connection.remoteIPAddr, [connection.remotePort unsignedShortValue]]];
|
||||
}
|
||||
|
||||
//set main text
|
||||
// ->connection endpoints
|
||||
[connectionCell.textField setStringValue:endpoints];
|
||||
|
||||
//set details
|
||||
if(nil != connection.state)
|
||||
{
|
||||
//add state
|
||||
[details appendString:connection.state];
|
||||
}
|
||||
|
||||
//set details
|
||||
[[connectionCell viewWithTag:TABLE_ROW_SUB_TEXT_TAG] setStringValue:details];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return connectionCell;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// File.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ItemBase.h"
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
@interface Binary : ItemBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//name
|
||||
@property(nonatomic, retain)NSString* name;
|
||||
|
||||
//path
|
||||
@property(nonatomic, retain)NSString* path;
|
||||
|
||||
//bundle
|
||||
@property(nonatomic, retain)NSBundle* bundle;
|
||||
|
||||
//TODO: no needed?
|
||||
//flag for task (main) executable
|
||||
@property BOOL isTaskBinary;
|
||||
|
||||
|
||||
//hashes (md5, sha1)
|
||||
@property(nonatomic, retain)NSDictionary* hashes;
|
||||
|
||||
//signing info
|
||||
@property(nonatomic, retain)NSDictionary* signingInfo;
|
||||
|
||||
/* VIRUS TOTAL INFO */
|
||||
|
||||
//dictionary returned by VT
|
||||
@property (nonatomic, retain)NSDictionary* vtInfo;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params;
|
||||
|
||||
//get task's name
|
||||
// ->either from bundle or path's last component
|
||||
-(NSString*)getName;
|
||||
|
||||
//get an icon for a process
|
||||
-(NSImage*)getIcon;
|
||||
|
||||
//get signing info (which takes a while to generate)
|
||||
// ->this method should be called in the background
|
||||
-(void)generatedSigningInfo;
|
||||
|
||||
//get detailed info (which takes a while to generate)
|
||||
// ->only shown to user if they click 'info' so this method should be called in the background
|
||||
-(void)generateDetailedInfo;
|
||||
|
||||
//format the signing info dictionary
|
||||
-(NSString*)formatSigningInfo;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,358 @@
|
||||
//
|
||||
// File.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Binary.h"
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation Binary
|
||||
|
||||
@synthesize path;
|
||||
@synthesize name;
|
||||
@synthesize icon;
|
||||
@synthesize bundle;
|
||||
@synthesize hashes;
|
||||
@synthesize signingInfo;
|
||||
@synthesize isTaskBinary;
|
||||
|
||||
@synthesize vtInfo;
|
||||
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params
|
||||
{
|
||||
//super
|
||||
// ->saves path, etc
|
||||
self = [super initWithParams:params];
|
||||
if(self)
|
||||
{
|
||||
//since path is always full path to binary
|
||||
// ->manaully try to find & load bundle (for .apps)
|
||||
self.bundle = findAppBundle(self.path);
|
||||
|
||||
/* now we have bundle (maybe), try get name and icon */
|
||||
|
||||
//get task's name
|
||||
// ->either from bundle or path's last component
|
||||
self.name = [self getName];
|
||||
|
||||
//get task's icon
|
||||
// ->either from bundle or just use system icon
|
||||
self.icon = [self getIcon];
|
||||
|
||||
//grab attributes
|
||||
//self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil];
|
||||
|
||||
|
||||
//do this in bg!
|
||||
//set signing info
|
||||
//self.signingInfo = extractSigningInfo(self.path);
|
||||
|
||||
//computes hashes
|
||||
// ->set 'md5' and 'sha1' iVars
|
||||
//self.hashes = hashFile(self.path);
|
||||
|
||||
|
||||
|
||||
//call into filter object to check if file is known
|
||||
// ->apple-signed or whitelisted
|
||||
//self.isTrusted = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).filterObj isTrustedFile:self];
|
||||
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//get task's name
|
||||
// ->either from bundle or path's last component
|
||||
-(NSString*)getName
|
||||
{
|
||||
//name
|
||||
NSString* taskName = nil;
|
||||
|
||||
//try to get name from bundle
|
||||
// ->key 'CFBundleName'
|
||||
if(nil != self.bundle)
|
||||
{
|
||||
//extract name
|
||||
taskName = [self.bundle infoDictionary][@"CFBundleName"];
|
||||
}
|
||||
|
||||
//no bundle/ or bundle lookup failed
|
||||
// ->just use last component of path
|
||||
if(nil == taskName)
|
||||
{
|
||||
//special case
|
||||
// ->kernel -> 'kernel_task'
|
||||
if(YES == [self.path isEqualToString:path2Kernel()])
|
||||
{
|
||||
//set kernel
|
||||
taskName = @"kernel_task";
|
||||
}
|
||||
//default
|
||||
// ->name is just last component of path
|
||||
else
|
||||
{
|
||||
//extract name
|
||||
taskName = [self.path lastPathComponent];
|
||||
}
|
||||
}
|
||||
|
||||
return taskName;
|
||||
}
|
||||
|
||||
//TODO: fix: "Path kernel_task given to -[NSWorkspace iconForFile:] is not a full path."
|
||||
//get an icon for a process
|
||||
// ->for apps, this will be app's icon, otherwise just a standard system one
|
||||
-(NSImage*)getIcon
|
||||
{
|
||||
//icon's file name
|
||||
NSString* iconFile = nil;
|
||||
|
||||
//icon's path
|
||||
NSString* iconPath = nil;
|
||||
|
||||
//icon's path extension
|
||||
NSString* iconExtension = nil;
|
||||
|
||||
//icon
|
||||
NSImage* taskIcon = nil;
|
||||
|
||||
//for app's
|
||||
// ->extract their icon
|
||||
if(nil != self.bundle)
|
||||
{
|
||||
//get file
|
||||
iconFile = self.bundle.infoDictionary[@"CFBundleIconFile"];
|
||||
|
||||
//get path extension
|
||||
iconExtension = [iconFile pathExtension];
|
||||
|
||||
//if its blank (i.e. not specified)
|
||||
// ->go with 'icns'
|
||||
if(YES == [iconExtension isEqualTo:@""])
|
||||
{
|
||||
//set type
|
||||
iconExtension = @"icns";
|
||||
}
|
||||
|
||||
//set full path
|
||||
iconPath = [self.bundle pathForResource:[iconFile stringByDeletingPathExtension] ofType:iconExtension];
|
||||
|
||||
//load it
|
||||
taskIcon = [[NSImage alloc] initWithContentsOfFile:iconPath];
|
||||
}
|
||||
|
||||
//process is not an app or couldn't get icon
|
||||
// ->try to get it via shared workspace
|
||||
if( (nil == self.bundle) ||
|
||||
(nil == taskIcon) )
|
||||
{
|
||||
//extract icon
|
||||
taskIcon = [[NSWorkspace sharedWorkspace] iconForFile:self.path];
|
||||
}
|
||||
|
||||
return taskIcon;
|
||||
}
|
||||
|
||||
//TODO: green signing for apple!!!
|
||||
//get signing info (which takes a while to generate)
|
||||
// ->this method should be called in the background
|
||||
-(void)generatedSigningInfo
|
||||
{
|
||||
//set signing info
|
||||
self.signingInfo = extractSigningInfo(self.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//get detailed info (which takes a while to generate)
|
||||
// ->only shown to user if they click 'info' so this method should be called in the background
|
||||
-(void)generateDetailedInfo
|
||||
{
|
||||
//grab file attributes
|
||||
self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil];
|
||||
|
||||
//computes hashes
|
||||
// ->set 'md5' and 'sha1' iVars
|
||||
self.hashes = hashFile(self.path);
|
||||
|
||||
//call into filter object to check if file is known
|
||||
// ->apple-signed or whitelisted
|
||||
self.isTrusted = [((AppDelegate*)[[NSApplication sharedApplication] delegate]).filterObj isTrustedFile:self];
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//format the signing info dictionary
|
||||
-(NSString*)formatSigningInfo
|
||||
{
|
||||
//pretty print
|
||||
NSMutableString* prettyPrint = nil;
|
||||
|
||||
//sanity check
|
||||
if(nil == self.signingInfo)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//switch on signing status
|
||||
switch([self.signingInfo[KEY_SIGNATURE_STATUS] integerValue])
|
||||
{
|
||||
//unsigned
|
||||
case errSecCSUnsigned:
|
||||
{
|
||||
//set string
|
||||
prettyPrint = [NSMutableString stringWithString:@"unsigned"];
|
||||
|
||||
//brk
|
||||
break;
|
||||
}
|
||||
|
||||
//errSecCSSignatureFailed
|
||||
case errSecCSSignatureFailed:
|
||||
{
|
||||
//set string
|
||||
prettyPrint = [NSMutableString stringWithString:@"invalid signature"];
|
||||
|
||||
//brk
|
||||
break;
|
||||
}
|
||||
|
||||
//happily signed
|
||||
case STATUS_SUCCESS:
|
||||
{
|
||||
//init
|
||||
prettyPrint = [NSMutableString string];//stringWithString:@"signed by:"];
|
||||
|
||||
//add each signing auth
|
||||
for(NSString* signingAuthority in self.signingInfo[KEY_SIGNING_AUTHORITIES])
|
||||
{
|
||||
//append
|
||||
[prettyPrint appendString:[NSString stringWithFormat:@"%@, ", signingAuthority]];
|
||||
}
|
||||
|
||||
//remove last comma & space
|
||||
if(YES == [prettyPrint hasSuffix:@", "])
|
||||
{
|
||||
//remove
|
||||
[prettyPrint deleteCharactersInRange:NSMakeRange([prettyPrint length]-2, 2)];
|
||||
}
|
||||
|
||||
//brk
|
||||
break;
|
||||
}
|
||||
|
||||
//unknown
|
||||
default:
|
||||
|
||||
//set string
|
||||
prettyPrint = [NSMutableString stringWithFormat:@"unknown (status/error: %ld)", (long)[self.signingInfo[KEY_SIGNATURE_STATUS] integerValue]];
|
||||
|
||||
//brk
|
||||
break;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return prettyPrint;
|
||||
}
|
||||
|
||||
//convert object to JSON string
|
||||
-(NSString*)toJSON
|
||||
{
|
||||
//json string
|
||||
NSString *json = nil;
|
||||
|
||||
//json data
|
||||
// ->for intermediate conversions
|
||||
NSData *jsonData = nil;
|
||||
|
||||
//hashes
|
||||
NSString* fileHashes = nil;
|
||||
|
||||
//signing info
|
||||
NSString* fileSigs = nil;
|
||||
|
||||
//VT detection ratio
|
||||
NSString* vtDetectionRatio = nil;
|
||||
|
||||
//init file hash to default string
|
||||
// ->used when hashes are nil, or serialization fails
|
||||
fileHashes = @"\"unknown\"";
|
||||
|
||||
//init file signature to default string
|
||||
// ->used when signatures are nil, or serialization fails
|
||||
fileSigs = @"\"unknown\"";
|
||||
|
||||
//convert hashes to JSON
|
||||
if(nil != self.hashes)
|
||||
{
|
||||
//convert hash dictionary
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//convert
|
||||
jsonData = [NSJSONSerialization dataWithJSONObject:self.hashes options:kNilOptions error:NULL];
|
||||
if(nil != jsonData)
|
||||
{
|
||||
//convert data to string
|
||||
fileHashes = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
//ignore exceptions
|
||||
// ->file hashes will just be 'unknown'
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//convert signing dictionary to JSON
|
||||
if(nil != self.signingInfo)
|
||||
{
|
||||
//convert signing dictionary
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//convert
|
||||
jsonData = [NSJSONSerialization dataWithJSONObject:self.signingInfo options:kNilOptions error:NULL];
|
||||
if(nil != jsonData)
|
||||
{
|
||||
//convert data to string
|
||||
fileSigs = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
//ignore exceptions
|
||||
// ->file sigs will just be 'unknown'
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//init VT detection ratio
|
||||
vtDetectionRatio = [NSString stringWithFormat:@"%lu/%lu", (unsigned long)[self.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue], (unsigned long)[self.vtInfo[VT_RESULTS_TOTAL] unsignedIntegerValue]];
|
||||
|
||||
//init json
|
||||
json = [NSString stringWithFormat:@"\"name\": \"%@\", \"path\": \"%@\", \"hashes\": %@, \"signature(s)\": %@, \"VT detection\": \"%@\"", self.name, self.path, fileHashes, fileSigs, vtDetectionRatio];
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Extension.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ItemBase.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Connection : ItemBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//local ip addr
|
||||
@property(nonatomic, retain)NSString* localIPAddr;
|
||||
|
||||
//local port
|
||||
@property(nonatomic, retain)NSNumber* localPort;
|
||||
|
||||
//remote ip addr
|
||||
@property(nonatomic, retain)NSString* remoteIPAddr;
|
||||
|
||||
//remote port
|
||||
@property(nonatomic, retain)NSNumber* remotePort;
|
||||
|
||||
//socket type
|
||||
@property(nonatomic, retain)NSString* type;
|
||||
|
||||
//socket family
|
||||
@property(nonatomic, retain)NSString* family;
|
||||
|
||||
//socket proto
|
||||
@property(nonatomic, retain)NSString* proto;
|
||||
|
||||
//socket state
|
||||
@property(nonatomic, retain)NSString* state;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// Extension.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Connection.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation Connection
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params
|
||||
{
|
||||
//super
|
||||
//self = [super initWithParams:params];
|
||||
//TODO: think about this - Connection doesn't share any baseItem stuffz
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//extract/save local addr
|
||||
self.localIPAddr = params[KEY_LOCAL_ADDR];
|
||||
|
||||
//extract/save local port
|
||||
self.localPort = params[KEY_LOCAL_PORT];
|
||||
|
||||
//extract/save remote addr
|
||||
self.remoteIPAddr = params[KEY_REMOTE_ADDR];
|
||||
|
||||
//extract/save remote port
|
||||
self.remotePort = params[KEY_REMOTE_PORT];
|
||||
|
||||
//extract/save type
|
||||
self.type = params[KEY_SOCKET_TYPE];
|
||||
|
||||
//extract/save family
|
||||
self.family = params[KEY_SOCKET_FAMILY];
|
||||
|
||||
//extract/save proto
|
||||
self.proto = params[KEY_SOCKET_PROTO];
|
||||
|
||||
//extract/save state
|
||||
self.state = params[KEY_SOCKET_STATE];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
//convert object to JSON string
|
||||
-(NSString*)toJSON
|
||||
{
|
||||
//json string
|
||||
NSString *json = nil;
|
||||
|
||||
//init json
|
||||
json = [NSString stringWithFormat:@"\"name\": \"%@\", \"path\": \"%@\", \"identifier\": \"%@\", \"details\": \"%@\", \"browser\": \"%@\"", self.name, self.path, self.identifier, self.details, self.browser];
|
||||
|
||||
return json;
|
||||
}
|
||||
*/
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// File.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ItemBase.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
@interface File : ItemBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//name
|
||||
@property(nonatomic, retain)NSString* name;
|
||||
|
||||
//path
|
||||
@property(nonatomic, retain)NSString* path;
|
||||
|
||||
//plist
|
||||
@property(nonatomic, retain)NSString* plist;
|
||||
|
||||
//bundle
|
||||
@property(nonatomic, retain)NSBundle* bundle;
|
||||
|
||||
//hashes (md5, sha1)
|
||||
@property(nonatomic, retain)NSDictionary* hashes;
|
||||
|
||||
//signing info
|
||||
@property(nonatomic, retain)NSDictionary* signingInfo;
|
||||
|
||||
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params;
|
||||
|
||||
//get detailed info (which takes a while to generate)
|
||||
// ->only shown to user if they click 'info' so this method is called in the background
|
||||
-(void)generateDetailedInfo;
|
||||
|
||||
//format the signing info dictionary
|
||||
-(NSString*)formatSigningInfo;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// File.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/19/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "File.h"
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation File
|
||||
|
||||
@synthesize path;
|
||||
@synthesize name;
|
||||
@synthesize plist;
|
||||
@synthesize bundle;
|
||||
@synthesize hashes;
|
||||
@synthesize signingInfo;
|
||||
|
||||
//@synthesize vtInfo;
|
||||
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params
|
||||
{
|
||||
//flag for directories
|
||||
BOOL isDirectory = NO;
|
||||
|
||||
//super
|
||||
// ->saves path, etc
|
||||
self = [super initWithParams:params];
|
||||
if(self)
|
||||
{
|
||||
//always skip not-existent paths
|
||||
// ->also get set a directory flag at the same time ;)
|
||||
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:params[KEY_RESULT_PATH] isDirectory:&isDirectory])
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: %@ not found", params[KEY_RESULT_PATH]);
|
||||
|
||||
//set self to nil
|
||||
self = nil;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//if path is directory
|
||||
// ->treat is as a bundle
|
||||
if(YES == isDirectory)
|
||||
{
|
||||
//load bundle
|
||||
// ->save this into 'bundle' iVar
|
||||
if(nil == (bundle = [NSBundle bundleWithPath:params[KEY_RESULT_PATH]]))
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: couldn't create bundle for %@", params[KEY_RESULT_PATH]);
|
||||
|
||||
//set self to nil
|
||||
self = nil;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//extract executable from bundle
|
||||
// ->save this into 'path' iVar
|
||||
if(nil == (self.path = self.bundle.executablePath))
|
||||
{
|
||||
//err msg
|
||||
//NSLog(@"OBJECTIVE-SEE ERROR: couldn't find executable in bundle %@", itemPath);
|
||||
|
||||
//set self to nil
|
||||
self = nil;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
//save (optional) plist
|
||||
// ->ok if this is nil
|
||||
self.plist = params[KEY_RESULT_PLIST];
|
||||
|
||||
//extract name
|
||||
self.name = [[self.path lastPathComponent] stringByDeletingPathExtension];
|
||||
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//get detailed info (which takes a while to generate)
|
||||
// ->only shown to user if they click 'info' so this method is called in the background
|
||||
-(void)generateDetailedInfo
|
||||
{
|
||||
//grab attributes
|
||||
//TODO: done elsewhere?
|
||||
self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil];
|
||||
|
||||
//computes hashes
|
||||
// ->set 'md5' and 'sha1' iVars
|
||||
self.hashes = hashFile(self.path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//convert object to JSON string
|
||||
-(NSString*)toJSON
|
||||
{
|
||||
//json string
|
||||
NSString *json = nil;
|
||||
|
||||
//json data
|
||||
// ->for intermediate conversions
|
||||
NSData *jsonData = nil;
|
||||
|
||||
//plist
|
||||
NSString* filePlist = nil;
|
||||
|
||||
//hashes
|
||||
NSString* fileHashes = nil;
|
||||
|
||||
//signing info
|
||||
NSString* fileSigs = nil;
|
||||
|
||||
//init file hash to default string
|
||||
// ->used when hashes are nil, or serialization fails
|
||||
fileHashes = @"\"unknown\"";
|
||||
|
||||
//init file signature to default string
|
||||
// ->used when signatures are nil, or serialization fails
|
||||
fileSigs = @"\"unknown\"";
|
||||
|
||||
//convert hashes to JSON
|
||||
if(nil != self.hashes)
|
||||
{
|
||||
//convert hash dictionary
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//convert
|
||||
jsonData = [NSJSONSerialization dataWithJSONObject:self.hashes options:kNilOptions error:NULL];
|
||||
if(nil != jsonData)
|
||||
{
|
||||
//convert data to string
|
||||
fileHashes = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
//ignore exceptions
|
||||
// ->file hashes will just be 'unknown'
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//convert signing dictionary to JSON
|
||||
if(nil != self.signingInfo)
|
||||
{
|
||||
//convert signing dictionary
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//convert
|
||||
jsonData = [NSJSONSerialization dataWithJSONObject:self.signingInfo options:kNilOptions error:NULL];
|
||||
if(nil != jsonData)
|
||||
{
|
||||
//convert data to string
|
||||
fileSigs = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
//ignore exceptions
|
||||
// ->file sigs will just be 'unknown'
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//provide a default string if the file doesn't have a plist
|
||||
if(nil == self.plist)
|
||||
{
|
||||
//set
|
||||
filePlist = @"n/a";
|
||||
}
|
||||
//use plist as is
|
||||
else
|
||||
{
|
||||
//set
|
||||
filePlist = self.plist;
|
||||
}
|
||||
|
||||
//init VT detection ratio
|
||||
//vtDetectionRatio = [NSString stringWithFormat:@"%lu/%lu", (unsigned long)[self.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue], (unsigned long)[self.vtInfo[VT_RESULTS_TOTAL] unsignedIntegerValue]];
|
||||
|
||||
//init json
|
||||
json = [NSString stringWithFormat:@"\"name\": \"%@\", \"path\": \"%@\", \"plist\": \"%@\", \"hashes\": %@, \"signature(s)\": %@", self.name, self.path, filePlist, fileHashes, fileSigs];
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// ItemBase.h
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 9/25/14.
|
||||
// Copyright (c) 2014 Synack. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface ItemBase : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//name
|
||||
@property(retain, nonatomic)NSString* name;
|
||||
|
||||
//path
|
||||
@property(retain, nonatomic)NSString* path;
|
||||
|
||||
//icon
|
||||
@property(nonatomic, retain)NSImage* icon;
|
||||
|
||||
//file attributes
|
||||
@property(nonatomic, retain)NSDictionary* attributes;
|
||||
|
||||
//flag if known
|
||||
// ->signed by apple and/or whitelisted
|
||||
@property BOOL isTrusted;
|
||||
|
||||
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params;
|
||||
|
||||
//return a path that can be opened in Finder.app
|
||||
-(NSString*)pathForFinder;
|
||||
|
||||
//convert object to JSON string
|
||||
-(NSString*)toJSON;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// ItemBase.m
|
||||
// TaskExplorer
|
||||
|
||||
#import "Consts.h"
|
||||
#import "ItemBase.h"
|
||||
|
||||
#define kErrFormat @"%@ not implemented in subclass %@"
|
||||
#define kExceptName @"KK Item"
|
||||
|
||||
|
||||
|
||||
@implementation ItemBase
|
||||
|
||||
@synthesize name;
|
||||
@synthesize path;
|
||||
@synthesize isTrusted;
|
||||
@synthesize attributes;
|
||||
|
||||
//init method
|
||||
-(id)initWithParams:(NSDictionary*)params
|
||||
{
|
||||
//super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//save plugin
|
||||
//self.plugin = params[KEY_RESULT_PLUGIN];
|
||||
|
||||
//extract/save name
|
||||
self.name = params[KEY_RESULT_NAME];
|
||||
|
||||
//extract/save path
|
||||
self.path = params[KEY_RESULT_PATH];
|
||||
|
||||
//get attributes
|
||||
// ->based off path
|
||||
self.attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//return a path that can be opened in Finder.app
|
||||
-(NSString*)pathForFinder
|
||||
{
|
||||
return self.path;
|
||||
}
|
||||
|
||||
//return
|
||||
|
||||
|
||||
/* OPTIONAL METHODS */
|
||||
|
||||
|
||||
|
||||
/* REQUIRED METHODS */
|
||||
|
||||
//stubs for inherited methods
|
||||
// ->all just throw exceptions as they should be implemented in sub-classes
|
||||
|
||||
//scan
|
||||
-(void)scan:(NSDictionary*)scanOptions
|
||||
{
|
||||
@throw [NSException exceptionWithName:kExceptName
|
||||
reason:[NSString stringWithFormat:kErrFormat, NSStringFromSelector(_cmd), [self class]]
|
||||
userInfo:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
//convert object to JSON string
|
||||
-(NSString*)toJSON
|
||||
{
|
||||
@throw [NSException exceptionWithName:kExceptName
|
||||
reason:[NSString stringWithFormat:kErrFormat, NSStringFromSelector(_cmd), [self class]]
|
||||
userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// CategoryRow.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 4/4/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface KKRow : NSTableRowView
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// CategoryRow.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 4/4/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KKRow.h"
|
||||
|
||||
@implementation KKRow
|
||||
|
||||
//custom row selection
|
||||
-(void)drawSelectionInRect:(NSRect)dirtyRect
|
||||
{
|
||||
//selection rect
|
||||
NSRect selectionRect = {0};
|
||||
|
||||
//selection path
|
||||
NSBezierPath *selectionPath = nil;
|
||||
|
||||
//highlight selected rows
|
||||
if(self.selectionHighlightStyle != NSTableViewSelectionHighlightStyleNone)
|
||||
{
|
||||
//make selection rect
|
||||
selectionRect = NSInsetRect(self.bounds, 2.5, 2.5);
|
||||
|
||||
//set stroke
|
||||
[[NSColor colorWithCalibratedWhite:.65 alpha:1.0] setStroke];
|
||||
|
||||
//set fill
|
||||
[[NSColor colorWithCalibratedWhite:.82 alpha:1.0] setFill];
|
||||
|
||||
//create selection path
|
||||
// ->with rounded corners
|
||||
selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:5 yRadius:5];
|
||||
|
||||
//fill
|
||||
[selectionPath fill];
|
||||
|
||||
//stroke
|
||||
[selectionPath stroke];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// NSMutableArray+QueueAdditions.h
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 9/26/14.
|
||||
// Copyright (c) 2014 Synack. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSMutableArray (QueueAdditions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//METHODS
|
||||
|
||||
//remove first object
|
||||
-(id)dequeue;
|
||||
|
||||
//add to end
|
||||
-(void)enqueue:(id)obj;
|
||||
|
||||
//check if empty
|
||||
-(BOOL)empty;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// NSMutableArray+QueueAdditions.m
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 9/26/14.
|
||||
// Copyright (c) 2014 Synack. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSMutableArray+QueueAdditions.h"
|
||||
|
||||
@implementation NSMutableArray (QueueAdditions)
|
||||
|
||||
//add object to tail (end) of queue
|
||||
-(void)enqueue:(id)anObject
|
||||
{
|
||||
//sync
|
||||
@synchronized(self)
|
||||
{
|
||||
//add object
|
||||
[self addObject: anObject];
|
||||
}
|
||||
}
|
||||
|
||||
//grab next item in queue
|
||||
-(id)dequeue
|
||||
{
|
||||
//extract object
|
||||
id queueObject = nil;
|
||||
|
||||
//sync
|
||||
@synchronized(self)
|
||||
{
|
||||
//check to make sure there are some items
|
||||
if(YES != [self empty])
|
||||
{
|
||||
//extract first one
|
||||
queueObject = [self objectAtIndex: 0];
|
||||
|
||||
//delete it from queue
|
||||
[self removeObjectAtIndex: 0];
|
||||
}
|
||||
|
||||
}//sync
|
||||
|
||||
return queueObject;
|
||||
}
|
||||
|
||||
// Checks if the queue is empty
|
||||
-(BOOL)empty
|
||||
{
|
||||
return ([self lastObject] == nil);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// PrefsWindowController.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface PrefsWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//buttons
|
||||
|
||||
//button for filtering out OS componets
|
||||
@property (weak) IBOutlet NSButton* showTrustedItemsBtn;
|
||||
|
||||
//button for disabling talking to VT
|
||||
@property (weak) IBOutlet NSButton* disableVTQueriesBtn;
|
||||
|
||||
//button for saving output
|
||||
@property (weak) IBOutlet NSButton* saveOutputBtn;
|
||||
|
||||
//button for ok/close
|
||||
@property (weak) IBOutlet NSButton *okButton;
|
||||
|
||||
//filter out OS/known items
|
||||
@property BOOL showTrustedItems;
|
||||
|
||||
//disable talking to VT
|
||||
@property BOOL disableVTQueries;
|
||||
|
||||
//save results (at end of scan)
|
||||
@property BOOL saveOutput;
|
||||
|
||||
//save results now
|
||||
@property BOOL shouldSaveNow;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//save existing prefs
|
||||
-(void)captureExistingPrefs;
|
||||
|
||||
//'OK' button handler
|
||||
// ->save prefs and close window
|
||||
-(IBAction)closeWindow:(id)sender;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// PrefsWindowController.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "PrefsWindowController.h"
|
||||
|
||||
|
||||
@implementation PrefsWindowController
|
||||
|
||||
@synthesize okButton;
|
||||
@synthesize saveOutput;
|
||||
@synthesize shouldSaveNow;
|
||||
@synthesize disableVTQueries;
|
||||
@synthesize showTrustedItems;
|
||||
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
|
||||
//automatically invoked when window is loaded
|
||||
// ->set to white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//make button selected
|
||||
[self.window makeFirstResponder:self.okButton];
|
||||
|
||||
//capture existing prefs
|
||||
// ->needed to trigger re-saves
|
||||
[self captureExistingPrefs];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//save existing prefs
|
||||
-(void)captureExistingPrefs
|
||||
{
|
||||
//save current state of 'include os/trusted' components
|
||||
self.showTrustedItems = self.showTrustedItemsBtn.state;
|
||||
|
||||
//save current state of 'disable VT'
|
||||
self.disableVTQueries = self.disableVTQueriesBtn.state;
|
||||
|
||||
//save current state of 'save' button
|
||||
self.saveOutput = self.saveOutputBtn.state;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->make ourselves unmodal
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//save prefs
|
||||
[self savePrefs];
|
||||
|
||||
//make un-modal
|
||||
[[NSApplication sharedApplication] stopModal];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//save prefs
|
||||
-(void)savePrefs
|
||||
{
|
||||
//first, any prefs changed, a 'save' set
|
||||
// ->set 'save now' flag
|
||||
if( ((self.showTrustedItems != self.showTrustedItemsBtn.state) ||
|
||||
(self.disableVTQueries != self.disableVTQueriesBtn.state) ||
|
||||
(self.saveOutput != self.saveOutputBtn.state) ) &&
|
||||
(YES == self.saveOutputBtn.state) )
|
||||
{
|
||||
//set
|
||||
self.shouldSaveNow = YES;
|
||||
}
|
||||
//don't save
|
||||
else
|
||||
{
|
||||
//unset
|
||||
self.shouldSaveNow = NO;
|
||||
}
|
||||
|
||||
//save hiding OS components flag
|
||||
self.showTrustedItems = self.showTrustedItemsBtn.state;
|
||||
|
||||
//save disabling VT flag
|
||||
self.disableVTQueries = self.disableVTQueriesBtn.state;
|
||||
|
||||
//save save output flag
|
||||
self.saveOutput = self.saveOutputBtn.state;
|
||||
|
||||
//call back up into app delegate for filtering/hiding OS components
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) applyPreferences];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//'OK' button handler
|
||||
// ->save prefs and close window
|
||||
-(IBAction)closeWindow:(id)sender
|
||||
{
|
||||
//close
|
||||
[self.window close];
|
||||
|
||||
return;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Queue.h
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 9/26/14.
|
||||
// Copyright (c) 2014 Synack. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
//from: https://github.com/esromneb/ios-queue-object/blob/master/NSMutableArray%2BQueueAdditions.h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "NSMutableArray+QueueAdditions.h"
|
||||
|
||||
@interface Queue : NSObject
|
||||
{
|
||||
//the queue
|
||||
NSMutableArray* eventQueue;
|
||||
|
||||
//queue processor thread
|
||||
NSThread* qProcessorThread;
|
||||
|
||||
//condition for queue's status
|
||||
NSCondition* queueCondition;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//event queue
|
||||
@property(retain, atomic)NSMutableArray* eventQueue;
|
||||
|
||||
|
||||
@property (nonatomic, retain)NSThread* qProcessorThread;
|
||||
@property (nonatomic, retain)NSCondition* queueCondition;
|
||||
|
||||
|
||||
//METHODS
|
||||
|
||||
//add an object to the queue
|
||||
-(void)enqueue:(id)anObject;
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Queue.m
|
||||
// BlockBlock
|
||||
//
|
||||
// Created by Patrick Wardle on 9/26/14.
|
||||
// Copyright (c) 2014 Synack. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Queue.h"
|
||||
#import "Consts.h"
|
||||
#import "Binary.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation Queue
|
||||
|
||||
@synthesize eventQueue;
|
||||
@synthesize queueCondition;
|
||||
@synthesize qProcessorThread;
|
||||
|
||||
-(id)init
|
||||
{
|
||||
//init super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//init queue
|
||||
eventQueue = [NSMutableArray array];
|
||||
|
||||
//init empty condition
|
||||
queueCondition = [[NSCondition alloc] init];
|
||||
|
||||
//spin up thread to watch/process queue
|
||||
self.qProcessorThread = [[NSThread alloc] initWithTarget:self selector:@selector(processQueue:) object:nil];
|
||||
|
||||
//start it
|
||||
[self.qProcessorThread start];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//process events from Q
|
||||
-(void)processQueue:(id)threadParam
|
||||
{
|
||||
//Binary obj
|
||||
Binary* binary = nil;
|
||||
|
||||
//nap for a bit
|
||||
// ->don't want UI thread, etc to suffer
|
||||
[NSThread sleepForTimeInterval:5.0f];
|
||||
|
||||
//for ever
|
||||
while(YES)
|
||||
{
|
||||
//pool
|
||||
@autoreleasepool {
|
||||
|
||||
//lock
|
||||
[self.queueCondition lock];
|
||||
|
||||
//wait while queue is empty
|
||||
while(YES == [self.eventQueue empty])
|
||||
{
|
||||
//wait
|
||||
[self.queueCondition wait];
|
||||
}
|
||||
|
||||
//get item off queue
|
||||
binary = [eventQueue dequeue];
|
||||
|
||||
//process binary
|
||||
// ->hash, etc
|
||||
if(YES == [binary isKindOfClass:[Binary class]])
|
||||
{
|
||||
//process
|
||||
//->for now, just hash, etc
|
||||
[binary generateDetailedInfo];
|
||||
}
|
||||
|
||||
//unlock
|
||||
[self.queueCondition unlock];
|
||||
|
||||
//pool
|
||||
}
|
||||
|
||||
}//foreverz process queue
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//add an object to the queue
|
||||
-(void)enqueue:(id)anObject
|
||||
{
|
||||
//lock
|
||||
[self.queueCondition lock];
|
||||
|
||||
//add to queue
|
||||
[self.eventQueue enqueue:anObject];
|
||||
|
||||
//signal
|
||||
[self.queueCondition signal];
|
||||
|
||||
//unlock
|
||||
[self.queueCondition unlock];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//process binary
|
||||
-(void)processBinary:(Binary*)binary
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// PrefsWindowController.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface RequestRootWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//status msg
|
||||
@property (weak) IBOutlet NSTextField *statusMsg;
|
||||
|
||||
//flag indicating app should exit
|
||||
@property BOOL shouldExit;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//invoked when user clicks 'auth' button
|
||||
// ->auths user!
|
||||
-(IBAction)authenticate:(id)sender;
|
||||
|
||||
//invoked when user clicks 'cancel' button
|
||||
// ->exits app
|
||||
-(IBAction)close:(id)sender;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,226 @@
|
||||
//
|
||||
// PrefsWindowController.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RequestRootWindowController.h"
|
||||
|
||||
|
||||
@implementation RequestRootWindowController
|
||||
|
||||
@synthesize statusMsg;
|
||||
@synthesize shouldExit;
|
||||
|
||||
//TODO: add 'why' / info button :)
|
||||
|
||||
|
||||
//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];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//set version sting
|
||||
//[self.versionLabel setStringValue:[NSString stringWithFormat:@"version: %@", getAppVersion()]];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->make ourselves unmodal and possibly exit app
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//save prefs
|
||||
//[self savePrefs];
|
||||
|
||||
//make un-modal
|
||||
[[NSApplication sharedApplication] stopModal];
|
||||
|
||||
//on errors, cancels
|
||||
// ->exit app
|
||||
if(YES == self.shouldExit)
|
||||
{
|
||||
//exit
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//invoked when user clicks 'auth' button
|
||||
// ->auth user, then set XPC service as root/setuid
|
||||
-(IBAction)authenticate:(id)sender
|
||||
{
|
||||
//status var
|
||||
BOOL authdOK = NO;
|
||||
|
||||
//authorization ref
|
||||
AuthorizationRef authorizationRef = {0};
|
||||
|
||||
//args
|
||||
const char* installArgs[0x10] = {0};
|
||||
|
||||
//status code
|
||||
OSStatus osStatus = -1;
|
||||
|
||||
//path to XPC service
|
||||
NSString* xpcService = nil;
|
||||
|
||||
//get path to XPC service
|
||||
xpcService = getPath2XPC();
|
||||
if(nil == xpcService)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* first chown as root */
|
||||
|
||||
//1st arg: recursive flag
|
||||
installArgs[0] = "-R";
|
||||
|
||||
//2nd arg: group/owner
|
||||
installArgs[1] = "root:wheel";
|
||||
|
||||
//3rd arg: XPC service
|
||||
installArgs[2] = [xpcService UTF8String];
|
||||
|
||||
//end w/ NULL
|
||||
installArgs[3] = NULL;
|
||||
|
||||
//create authorization ref
|
||||
osStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
|
||||
if(errAuthorizationSuccess != osStatus)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"ERROR: AuthorizationCreate() failed with %d", osStatus);
|
||||
|
||||
//set exit flag
|
||||
self.shouldExit = YES;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//chown XPC service as r00t
|
||||
osStatus = AuthorizationExecuteWithPrivileges(authorizationRef, "/usr/sbin/chown", 0, (char* const*)installArgs, NULL);
|
||||
if(errAuthorizationSuccess != osStatus)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"ERROR: AuthorizationExecuteWithPrivileges() failed with %d", osStatus);
|
||||
|
||||
//set result msg
|
||||
[self.statusMsg setStringValue: [NSString stringWithFormat:@"error: failed with %d", osStatus]];
|
||||
|
||||
//set font to red
|
||||
self.statusMsg.textColor = [NSColor redColor];
|
||||
|
||||
//set exit flag
|
||||
self.shouldExit = YES;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* then setuid */
|
||||
|
||||
//1st arg: recursive flag
|
||||
installArgs[0] = "-R";
|
||||
|
||||
//2nd arg: permissions
|
||||
// ->4 at front is setuid
|
||||
//TODO: make 4755
|
||||
installArgs[1] = "4777";
|
||||
|
||||
//3rd arg: XPC service
|
||||
installArgs[2] = [xpcService UTF8String];
|
||||
|
||||
//end w/ NULL
|
||||
installArgs[3] = NULL;
|
||||
|
||||
//chmod XPC service w/ setuid
|
||||
osStatus = AuthorizationExecuteWithPrivileges(authorizationRef, "/bin/chmod", 0, (char* const*)installArgs, NULL);
|
||||
|
||||
//check
|
||||
if(errAuthorizationSuccess != osStatus)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"ERROR: AuthorizationExecuteWithPrivileges() failed with %d", osStatus);
|
||||
|
||||
//set result msg
|
||||
[self.statusMsg setStringValue: [NSString stringWithFormat:@"error: failed with %d", osStatus]];
|
||||
|
||||
//set font to red
|
||||
self.statusMsg.textColor = [NSColor redColor];
|
||||
|
||||
//set exit flag
|
||||
self.shouldExit = YES;
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//no errors
|
||||
authdOK = YES;
|
||||
|
||||
//no exit
|
||||
self.shouldExit = NO;
|
||||
|
||||
//start enumerating tasks
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) exploreTasks];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free auth ref
|
||||
if(0 != authorizationRef)
|
||||
{
|
||||
//free
|
||||
AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
|
||||
}
|
||||
|
||||
//on auth/'install' success
|
||||
// ->close window
|
||||
if(YES == authdOK)
|
||||
{
|
||||
//close window
|
||||
[self.window close];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//invoked when user clicks 'cancel' button
|
||||
// ->set exit flag and close window
|
||||
-(IBAction)close:(id)sender
|
||||
{
|
||||
//set flag to exit
|
||||
self.shouldExit = YES;
|
||||
|
||||
//exit
|
||||
[self.window close];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// PrefsWindowController.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface ResultsWindowController : NSWindowController <NSWindowDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//details
|
||||
@property(nonatomic, retain)NSString* details;
|
||||
|
||||
//details of results label/string
|
||||
@property(weak) IBOutlet NSTextField *detailsLabel;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//invoked when user clicks 'more info' button
|
||||
// ->open KK's webpage
|
||||
- (IBAction)close:(id)sender;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// PrefsWindowController.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/6/15.
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "Utilities.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "ResultsWindowController.h"
|
||||
|
||||
|
||||
@implementation ResultsWindowController
|
||||
|
||||
@synthesize details;
|
||||
@synthesize detailsLabel;
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
//automatically invoked when window is loaded
|
||||
// ->set to white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//set details
|
||||
self.detailsLabel.stringValue = self.details;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'OK'
|
||||
// ->close window
|
||||
-(IBAction)close:(id)sender
|
||||
{
|
||||
//close
|
||||
[[self window] close];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->make ourselves unmodal
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//make un-modal
|
||||
[[NSApplication sharedApplication] stopModal];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// Task.h
|
||||
// TaskExplorer
|
||||
//
|
||||
// Created by Patrick Wardle on 5/2/15.
|
||||
// Copyright (c) 2015 Lucas Derraugh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Binary.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
/*
|
||||
|
||||
//32bit
|
||||
struct dyld_image_info_32 {
|
||||
int imageLoadAddress;
|
||||
int imageFilePath;
|
||||
int imageFileModDate;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
@interface Task : NSObject
|
||||
{
|
||||
//pid
|
||||
NSNumber* pid;
|
||||
|
||||
//uid
|
||||
uid_t uid;
|
||||
|
||||
//main binary
|
||||
Binary* binary;
|
||||
|
||||
//app bundle
|
||||
// ->only for apps of course...
|
||||
//NSBundle* bundle;
|
||||
|
||||
//process's full path
|
||||
// ->e.g. /Applications/Calculator.app/Contents/MacOS/Calculator
|
||||
//NSString* path;
|
||||
|
||||
//process's name
|
||||
// ->e.g Calculator
|
||||
//NSString* name;
|
||||
|
||||
//icon
|
||||
//NSImage* icon;
|
||||
|
||||
//parent id
|
||||
NSNumber* ppid;
|
||||
|
||||
//children (for tree view)
|
||||
NSMutableArray* children;
|
||||
}
|
||||
|
||||
|
||||
@property (nonatomic, retain)NSNumber* pid;
|
||||
|
||||
//main binary
|
||||
@property(nonatomic, retain)Binary* binary;
|
||||
|
||||
//process args
|
||||
@property(nonatomic, retain)NSMutableArray* arguments;
|
||||
|
||||
//loaded dylibs
|
||||
@property(nonatomic, retain)NSMutableArray* dylibs;
|
||||
|
||||
//open files
|
||||
@property(nonatomic, retain)NSMutableArray* files;
|
||||
|
||||
//connections
|
||||
@property(nonatomic, retain)NSMutableArray* connections;
|
||||
|
||||
@property uid_t uid;
|
||||
@property (nonatomic, retain)NSNumber* ppid;
|
||||
|
||||
|
||||
//signing info
|
||||
@property(nonatomic, retain)NSDictionary* signingInfo;
|
||||
|
||||
//children
|
||||
@property (nonatomic, retain)NSMutableArray* children;
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init w/ a pid + path
|
||||
// note: icons are dynamically determined only when process is shown in alert
|
||||
-(id)initWithPID:(NSNumber*)taskPID andPath:(NSString*)taskPath;
|
||||
|
||||
//get command-line args
|
||||
-(void)getArguments;
|
||||
|
||||
-(void)generateBinaryInfo;
|
||||
|
||||
//enumerate all dylibs
|
||||
// ->new ones are added to 'existingDylibs' (global) dictionary
|
||||
-(void)enumerateDylibs:(NSXPCConnection*)xpcConnection allDylibs:(NSMutableDictionary*)allDylibs;
|
||||
|
||||
//enumerate all open files
|
||||
-(void)enumerateFiles:(NSXPCConnection*)xpcConnection;
|
||||
|
||||
//enumerate network sockets/connections
|
||||
-(void)enumerateNetworking:(NSXPCConnection*)xpcConnection;
|
||||
|
||||
|
||||
|
||||
//get UID for process (by pid)
|
||||
//-(void)determineUID;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,536 @@
|
||||
//
|
||||
// Task.m
|
||||
// TaskExplorer
|
||||
//
|
||||
// Created by Patrick Wardle on 5/2/15.
|
||||
// Copyright (c) 2015 Lucas Derraugh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Task.h"
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "File.h"
|
||||
#import "Connection.h"
|
||||
#import "remoteTaskService.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import <mach-o/dyld_images.h>
|
||||
#import <mach/mach_init.h>
|
||||
#import <mach/mach_vm.h>
|
||||
#import <sys/types.h>
|
||||
#import <mach/mach.h>
|
||||
#import <sys/ptrace.h>
|
||||
#import <sys/wait.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/proc_info.h>
|
||||
#import <libproc.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <netinet/tcp_fsm.h>
|
||||
|
||||
|
||||
@implementation Task
|
||||
|
||||
@synthesize pid;
|
||||
@synthesize uid;
|
||||
//@synthesize icon;
|
||||
//@synthesize name;
|
||||
//@synthesize path;
|
||||
@synthesize ppid;
|
||||
@synthesize files;
|
||||
@synthesize binary;
|
||||
//@synthesize bundle;
|
||||
@synthesize dylibs;
|
||||
@synthesize children;
|
||||
@synthesize arguments;
|
||||
@synthesize connections;
|
||||
|
||||
//init w/ a pid + path
|
||||
// note: time consuming init's are done in '' method
|
||||
-(id)initWithPID:(NSNumber*)taskPID andPath:(NSString*)taskPath
|
||||
{
|
||||
//existing binaries
|
||||
NSMutableDictionary* existingBinaries = nil;
|
||||
|
||||
//existing binary
|
||||
// ->can re-use for tasks w/ same binary
|
||||
Binary* existingBinary = nil;
|
||||
|
||||
//init super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//grab existings binaries
|
||||
existingBinaries = ((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.executables;
|
||||
|
||||
//since root UID is zero
|
||||
// ->init UID to -1
|
||||
//self.uid = -1;
|
||||
|
||||
//save pid
|
||||
self.pid = taskPID;
|
||||
|
||||
//alloc array for children
|
||||
children = [NSMutableArray array];
|
||||
|
||||
//alloc array for dylibs
|
||||
dylibs = [NSMutableArray array];
|
||||
|
||||
//alloc array for open files
|
||||
files = [NSMutableArray array];
|
||||
|
||||
//alloc array for network connections
|
||||
connections = [NSMutableArray array];
|
||||
|
||||
//get parent id
|
||||
self.ppid = [NSNumber numberWithInteger:getParentID([taskPID intValue])];
|
||||
|
||||
//try extract existing binary
|
||||
// ->will succeed for multiple instances of the same task (process)
|
||||
existingBinary = existingBinaries[taskPath];
|
||||
|
||||
//re-use existing binaries
|
||||
if(nil != existingBinary)
|
||||
{
|
||||
//re-use
|
||||
self.binary = existingBinary;
|
||||
}
|
||||
//generate new binary
|
||||
else
|
||||
{
|
||||
//generate binary obj
|
||||
// ->time-consuming tasks are preformed in background block
|
||||
self.binary = [[Binary alloc] initWithParams:@{KEY_RESULT_PATH:taskPath}];
|
||||
|
||||
//skip those that error out
|
||||
if(nil == self.binary)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//add to queue
|
||||
// ->this will processing
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.binaryQueue enqueue:self.binary];
|
||||
|
||||
//add it to 'global' list
|
||||
existingBinaries[taskPath] = self.binary;
|
||||
|
||||
}
|
||||
|
||||
//indicate that binary is a task (main) executable
|
||||
//self.binary.isTaskBinary = YES;
|
||||
|
||||
}//init self
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//
|
||||
-(void)generateBinaryInfo
|
||||
{
|
||||
//create main binary
|
||||
//self.binary = [[Binary alloc] initWithParams:@{KEY_RESULT_PATH:self.path}];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//get command-line args
|
||||
-(void)getArguments
|
||||
{
|
||||
//'management info base' array
|
||||
int mib[3] = {0};
|
||||
|
||||
//system's size for max args
|
||||
int systemMaxArgs = 0;
|
||||
|
||||
//process's args
|
||||
char* processArgs = NULL;
|
||||
|
||||
//# of args
|
||||
int numberOfArgs = 0;
|
||||
|
||||
//start of (each) arg
|
||||
char* argStart = NULL;
|
||||
|
||||
//size of buffers, etc
|
||||
size_t size = 0;
|
||||
|
||||
//parser pointer
|
||||
char *parser;
|
||||
|
||||
//init mib
|
||||
// ->want system's size for max args
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARGMAX;
|
||||
|
||||
//first time
|
||||
// ->alloc array for args
|
||||
if(nil == self.arguments)
|
||||
{
|
||||
//alloc
|
||||
arguments = [NSMutableArray array];
|
||||
}
|
||||
|
||||
//set size
|
||||
size = sizeof(systemMaxArgs);
|
||||
|
||||
//get system's size for max args
|
||||
if(-1 == sysctl(mib, 2, &systemMaxArgs, &size, NULL, 0))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//alloc space for args
|
||||
processArgs = malloc(systemMaxArgs);
|
||||
if(NULL == processArgs)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//init mib
|
||||
// ->want process args
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROCARGS2;
|
||||
mib[2] = [self.pid intValue];
|
||||
|
||||
//set size
|
||||
size = (size_t)systemMaxArgs;
|
||||
|
||||
//get process's args
|
||||
if(-1 == sysctl(mib, 3, processArgs, &size, NULL, 0))
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//extract number of args
|
||||
// ->at start of buffer
|
||||
memcpy(&numberOfArgs, processArgs, sizeof(numberOfArgs));
|
||||
|
||||
//skip procs w/ no args
|
||||
// ->note: don't care about arg[0]
|
||||
if(numberOfArgs < 2)
|
||||
{
|
||||
//no args
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//init point to start of args
|
||||
// ->they start right after # of args
|
||||
parser = processArgs + sizeof(numberOfArgs);
|
||||
|
||||
//skip over exe name
|
||||
// ->always at front, yes, even before arg[0] (which is also exe name)
|
||||
while(parser < &processArgs[size])
|
||||
{
|
||||
//scan till NULL-terminator
|
||||
if(0x0 == *parser)
|
||||
{
|
||||
//end of exe name
|
||||
break;
|
||||
}
|
||||
|
||||
//next char
|
||||
parser++;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
// ->make sure end-of-buffer wasn't reached
|
||||
if(parser == &processArgs[size])
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//skip all trailing NULLs
|
||||
// ->scan will non-NULL is found
|
||||
while(parser < &processArgs[size])
|
||||
{
|
||||
//scan till NULL-terminator
|
||||
if(0x0 != *parser)
|
||||
{
|
||||
//ok, got to argv[0]
|
||||
break;
|
||||
}
|
||||
|
||||
//next char
|
||||
parser++;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
// ->(again), make sure end-of-buffer wasn't reached
|
||||
if(parser == &processArgs[size])
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//keep scanning until all args are found
|
||||
// ->each is NULL-terminated
|
||||
while(parser < &processArgs[size])
|
||||
{
|
||||
//bail if we've hit arg cnt
|
||||
// ->note: don't save arg[0], so add 1
|
||||
if(self.arguments.count + 1 == numberOfArgs)
|
||||
{
|
||||
//bail
|
||||
break;
|
||||
}
|
||||
|
||||
//each arg is NULL-terminated
|
||||
if(*parser == '\0')
|
||||
{
|
||||
//save arg
|
||||
// ->'argStart' is purposely NULL for argv[0]
|
||||
if(NULL != argStart)
|
||||
{
|
||||
[self.arguments addObject:[NSString stringWithUTF8String:argStart]];
|
||||
}
|
||||
|
||||
//init string pointer to (possibly) next arg
|
||||
argStart = ++parser;
|
||||
}
|
||||
|
||||
//next char
|
||||
parser++;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free process args
|
||||
if(NULL != processArgs)
|
||||
{
|
||||
//free
|
||||
free(processArgs);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//enumerate all dylibs
|
||||
// ->new ones are added to 'existingDylibs' (global) dictionary
|
||||
-(void)enumerateDylibs:(NSXPCConnection*)xpcConnection allDylibs:(NSMutableDictionary*)allDylibs
|
||||
{
|
||||
//dylib instance (as Binary) obj
|
||||
__block Binary* dylib = nil;
|
||||
|
||||
//new dylibs
|
||||
// ->ones that should be hashed/processed
|
||||
__block NSMutableArray* newDylibs = nil;
|
||||
|
||||
//alloc array for new dylibs
|
||||
newDylibs = [NSMutableArray array];
|
||||
|
||||
//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) {
|
||||
|
||||
//add all dylibs
|
||||
for(NSString* dylibPath in dylibPaths)
|
||||
{
|
||||
//skip main image
|
||||
if(YES == [dylibPath isEqualToString:self.binary.path])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//skip 'cl_kernels'
|
||||
// ->not an on-disk/'real' dylib
|
||||
if(YES == [dylibPath isEqualToString:@"cl_kernels"])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//first try grab from 'global' list of all dylibs
|
||||
// ->will be non-nil if its already been processed
|
||||
dylib = allDylibs[dylibPath];
|
||||
|
||||
//first time seen?
|
||||
// ->create Binary obj & save into 'global' list
|
||||
if(nil == dylib)
|
||||
{
|
||||
//create Binary obj
|
||||
dylib = [[Binary alloc] initWithParams:@{KEY_RESULT_PATH:dylibPath}];
|
||||
|
||||
//skip any that error out
|
||||
if(nil == dylib)
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//add to queue
|
||||
// ->this will processing
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.binaryQueue enqueue:dylib];
|
||||
|
||||
//add to list of new dylibs
|
||||
// ->will allow for post processing
|
||||
[newDylibs addObject:dylib];
|
||||
|
||||
//sync
|
||||
// ->add to global list
|
||||
@synchronized(allDylibs)
|
||||
{
|
||||
//add
|
||||
allDylibs[dylib.path] = dylib;
|
||||
}
|
||||
}
|
||||
|
||||
//sync
|
||||
@synchronized(self.dylibs)
|
||||
{
|
||||
//add to task's dylibs
|
||||
[self.dylibs addObject:dylib];
|
||||
}
|
||||
}
|
||||
|
||||
//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];
|
||||
|
||||
//complete dylib processing
|
||||
// ->get signing info, hash, etc, & save into global list
|
||||
for(Binary* newDylib in newDylibs)
|
||||
{
|
||||
//generate signing info
|
||||
[newDylib generatedSigningInfo];
|
||||
}
|
||||
|
||||
//any new dylibs?
|
||||
// ->reload bottom pane
|
||||
if(0 != newDylibs.count)
|
||||
{
|
||||
//reload
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:DYLIBS_VIEW];
|
||||
}
|
||||
|
||||
}];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//enumerate all file descriptors
|
||||
-(void)enumerateFiles:(NSXPCConnection*)xpcConnection
|
||||
{
|
||||
//File object
|
||||
__block File* file = nil;
|
||||
|
||||
//new files
|
||||
NSMutableArray* newFiles = nil;
|
||||
|
||||
//file path
|
||||
__block NSString* filePath = nil;
|
||||
|
||||
//alloc array for new files
|
||||
newFiles = [NSMutableArray array];
|
||||
|
||||
//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) {
|
||||
|
||||
//create/add all files
|
||||
for(NSMutableDictionary* fileDescriptor in fileDescriptors)
|
||||
{
|
||||
//extract file path
|
||||
filePath = fileDescriptor[KEY_FILE_PATH];
|
||||
|
||||
//alloc/init File obj
|
||||
file = [[File alloc] initWithParams:@{KEY_RESULT_PATH:filePath}];
|
||||
|
||||
//skip nil files
|
||||
//TODO: look into what files err out!!
|
||||
if(nil == file)
|
||||
{
|
||||
//next
|
||||
continue;
|
||||
}
|
||||
|
||||
//add to task's files
|
||||
[self.files addObject:file];
|
||||
|
||||
//save new files
|
||||
// ->will be processed below
|
||||
if(nil == [((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.files objectForKey:filePath])
|
||||
{
|
||||
//save as new
|
||||
[newFiles addObject:file];
|
||||
}
|
||||
}
|
||||
|
||||
//reload bottom pane
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:FILES_VIEW];
|
||||
|
||||
//process all new files
|
||||
// ->calculate hash, etc & save into global list
|
||||
for(File* newFile in newFiles)
|
||||
{
|
||||
//generate detailed info
|
||||
[newFile generateDetailedInfo];
|
||||
|
||||
//TODO: sync!
|
||||
//save into global list
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]).taskEnumerator.files setObject:newFile forKey:filePath];
|
||||
}
|
||||
}];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//enumerate network sockets/connections
|
||||
-(void)enumerateNetworking:(NSXPCConnection*)xpcConnection
|
||||
{
|
||||
//File object
|
||||
__block Connection* connection = nil;
|
||||
|
||||
//remove any existing enum'd networking sockets/connections
|
||||
[self.connections removeAllObjects];
|
||||
|
||||
NSLog(@"invoking XPC to enumer networking");
|
||||
|
||||
//invoke XPC service (running as r00t)
|
||||
// ->will enumerate network sockets/connections, then invoke reply block so can save into iVar
|
||||
[[xpcConnection remoteObjectProxy] enumerateNetwork:self.pid withReply:^(NSMutableArray* networkItems) {
|
||||
|
||||
//
|
||||
//NSLog(@"found %d connections", networkItems.count);
|
||||
|
||||
//create/add all network sockets/connection
|
||||
for(NSMutableDictionary* networkItem in networkItems)
|
||||
{
|
||||
//alloc/init File obj
|
||||
connection = [[Connection alloc] initWithParams:networkItem];
|
||||
|
||||
//add File obj
|
||||
if(nil != connection)
|
||||
{
|
||||
//add
|
||||
[self.connections addObject:connection];
|
||||
}
|
||||
}
|
||||
|
||||
////TODO: on main thead?
|
||||
//reload bottom pane
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:self itemView:NETWORKING_VIEW];
|
||||
|
||||
}];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// TaskEnumerator.h
|
||||
//
|
||||
//
|
||||
// Created by Patrick Wardle on 5/2/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import "Queue.h"
|
||||
#import "3rdParty/OrderedDictionary.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface TaskEnumerator : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//flag indicating first scan is complete
|
||||
//@property BOOL firstScanComplete;
|
||||
|
||||
//all tasks objects
|
||||
@property(nonatomic, retain)OrderedDictionary* tasks;
|
||||
|
||||
//all task binaries (main executables)
|
||||
@property(nonatomic, retain)NSMutableDictionary* executables;
|
||||
|
||||
//all (opened) files
|
||||
@property(nonatomic, retain)NSMutableDictionary* files;
|
||||
|
||||
//all dylibs
|
||||
@property(nonatomic, retain)NSMutableDictionary* dylibs;
|
||||
|
||||
//remote XPC interface
|
||||
//TODO: weak OK?
|
||||
@property (nonatomic, retain) NSXPCConnection* xpcConnection;
|
||||
|
||||
//queue object
|
||||
// ->contains watch items that should be processed
|
||||
@property (nonatomic, retain) Queue* binaryQueue;
|
||||
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//enumerate all tasks
|
||||
// ->call back into app delegate to update task (top) table
|
||||
-(void)enumerateTasks;
|
||||
|
||||
//get list of all pids
|
||||
-(OrderedDictionary*)getAllTasks;
|
||||
|
||||
//insert tasks into appropriate parent
|
||||
// ->ensures order of parent's (by pid), is preserved
|
||||
-(void)generateAncestries:(OrderedDictionary*)newTasks;
|
||||
|
||||
//determine if dylibs should be (re)enumerated
|
||||
// ->generally yes, unless the first enumeration (of all tasks) is not complete
|
||||
-(BOOL)shouldEnumDylibs;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,411 @@
|
||||
//
|
||||
// TaskEnumerator.m
|
||||
//
|
||||
//
|
||||
// Created by Patrick Wardle on 5/2/15.
|
||||
//
|
||||
//
|
||||
|
||||
#import <libproc.h>
|
||||
#import <sys/proc_info.h>
|
||||
|
||||
#import "Task.h"
|
||||
#import "Consts.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "Utilities.h"
|
||||
#import "TaskEnumerator.h"
|
||||
#import "serviceInterface.h"
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation TaskEnumerator
|
||||
|
||||
|
||||
@synthesize files;
|
||||
@synthesize tasks;
|
||||
@synthesize dylibs;
|
||||
@synthesize binaryQueue;
|
||||
@synthesize executables;
|
||||
@synthesize xpcConnection;
|
||||
|
||||
//@synthesize firstScanComplete;
|
||||
|
||||
//init
|
||||
-(id)init
|
||||
{
|
||||
//init super
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//init tasks dictionary
|
||||
tasks = [[OrderedDictionary alloc] init];
|
||||
|
||||
//alloc executables dictionary
|
||||
executables = [NSMutableDictionary dictionary];
|
||||
|
||||
//alloc dylibs dictionary
|
||||
dylibs = [NSMutableDictionary dictionary];
|
||||
|
||||
//alloc XPC connection
|
||||
xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.remoteTaskService"];
|
||||
|
||||
//set remote object interface
|
||||
self.xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(remoteTaskProto)];
|
||||
|
||||
//set classes
|
||||
// ->arrays & strings are what is ok to vend
|
||||
[self.xpcConnection.remoteObjectInterface
|
||||
setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSMutableDictionary class], [NSString class], nil]
|
||||
forSelector: @selector(enumerateDylibs:withReply:)
|
||||
argumentIndex: 0 // the first parameter
|
||||
ofReply: YES // in the method itself.
|
||||
];
|
||||
|
||||
//set classes
|
||||
// ->arrays & strings are what is ok to vend
|
||||
[self.xpcConnection.remoteObjectInterface
|
||||
setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSMutableDictionary class], [NSString class], nil]
|
||||
forSelector: @selector(enumerateFiles:withReply:)
|
||||
argumentIndex: 0 // the first parameter
|
||||
ofReply: YES // in the method itself.
|
||||
];
|
||||
|
||||
//set classes
|
||||
// ->arrays & strings are what is ok to vend
|
||||
[self.xpcConnection.remoteObjectInterface
|
||||
setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSMutableDictionary class], [NSString class], [NSNumber class], nil]
|
||||
forSelector: @selector(enumerateNetwork:withReply:)
|
||||
argumentIndex: 0 // the first parameter
|
||||
ofReply: YES // in the method itself.
|
||||
];
|
||||
|
||||
//resume
|
||||
[self.xpcConnection resume];
|
||||
|
||||
//init binary processing queue
|
||||
binaryQueue = [[Queue alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//enumerate all tasks
|
||||
// ->call back into app delegate to update task (top) table
|
||||
// call every x # of seconds~
|
||||
|
||||
//TODO: re-enumerate dylibs for everytime!
|
||||
// only need to update task.dylibs list (not global one, unless its new!)
|
||||
|
||||
-(void)enumerateTasks
|
||||
{
|
||||
//(new) task item
|
||||
Task* newTask = nil;
|
||||
|
||||
//new tasks
|
||||
OrderedDictionary* newTasks = nil;
|
||||
|
||||
//get all tasks
|
||||
// ->pids and binary obj with just path/name
|
||||
newTasks = [self getAllTasks];
|
||||
|
||||
//build ancestries
|
||||
[self generateAncestries:newTasks];
|
||||
|
||||
//add all tasks that are really new to 'tasks' iVar
|
||||
// ->ensures existing task and their info are reused
|
||||
for(NSNumber* key in newTasks.allKeys)
|
||||
{
|
||||
//get task
|
||||
newTask = newTasks[key];
|
||||
|
||||
//remove any non-new (i.e. existing) tasks
|
||||
if(nil != self.tasks[newTask.pid])
|
||||
{
|
||||
//not new
|
||||
// ->remove
|
||||
[newTasks removeObjectForKey:key];
|
||||
|
||||
//next
|
||||
continue;
|
||||
}
|
||||
|
||||
//enumerate task's dylibs
|
||||
//[newTask enumerateDylibs:self.xpcConnection allDylibs:self.dylibs];
|
||||
|
||||
//add new task
|
||||
// TODO: ordering!?
|
||||
[self.tasks setObject:newTask forKey:newTask.pid];
|
||||
|
||||
}
|
||||
|
||||
//reload table
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadTaskTable];
|
||||
|
||||
//now generate signing info
|
||||
// ->for (new) tasks & their dylibs
|
||||
for(NSNumber* key in newTasks)
|
||||
{
|
||||
//get task
|
||||
newTask = newTasks[key];
|
||||
|
||||
//generate signing info
|
||||
[newTask.binary generatedSigningInfo];
|
||||
|
||||
//reload task (row) in table
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadRow:newTask item:newTask.binary pane:PANE_TOP];
|
||||
|
||||
//reload bottom pane
|
||||
// ->this will only reload if new task is the currently selected one, etc
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) reloadBottomPane:newTask itemView:CURRENT_VIEW];
|
||||
|
||||
}//signing info for all tasks and dylibs
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
//determine if dylibs should be (re)enumerated
|
||||
// ->generally yes, unless the first enumeration (of all tasks) is not complete
|
||||
-(BOOL)shouldEnumDylibs
|
||||
{
|
||||
//flag
|
||||
BOOL shouldEnum = NO;
|
||||
|
||||
//task key
|
||||
NSNumber* taskKey = nil;
|
||||
|
||||
//Task
|
||||
Task* task = nil;
|
||||
|
||||
for(NSInteger i = self.tasks.count-1; i>=0; i--)
|
||||
{
|
||||
taskKey = [self.tasks keyAtIndex:i];
|
||||
|
||||
task = self.tasks[taskKey];
|
||||
|
||||
//skip dead procs
|
||||
if(YES != isAlive([task.pid unsignedIntValue]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//alive
|
||||
// ->does it have dylibs?
|
||||
if(0 != task.dylibs.count)
|
||||
{
|
||||
//a end task has dylibs
|
||||
// ->indicates all done?
|
||||
shouldEnum = YES;
|
||||
|
||||
//bail
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldEnum = NO;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return shouldEnum;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//TODO: only do this once!
|
||||
// ->otherwise done JIT (on click)
|
||||
//TODO: sync!!
|
||||
//iterate over all tasks
|
||||
// ->invoke task's emun method to get all files/network (via XPC)
|
||||
-(void)enumerateFiles
|
||||
{
|
||||
//Task
|
||||
Task* task = nil;
|
||||
|
||||
//iterate over all tasks
|
||||
// ->invoke method to enumerate files
|
||||
for(NSNumber* key in self.tasks)
|
||||
{
|
||||
//get task
|
||||
task = self.tasks[key];
|
||||
|
||||
//enumerate files
|
||||
[task enumerateFiles:self.xpcConnection];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//get list of all pids
|
||||
-(OrderedDictionary*)getAllTasks
|
||||
{
|
||||
//tasks
|
||||
// ->pid/name
|
||||
OrderedDictionary* allTasks = nil;
|
||||
|
||||
//task
|
||||
Task* task = nil;
|
||||
|
||||
//alloc/init list
|
||||
allTasks = [[OrderedDictionary alloc] init];
|
||||
|
||||
//# of procs
|
||||
int numberOfProcesses = 0;
|
||||
|
||||
//array of pids
|
||||
pid_t* pids = NULL;
|
||||
|
||||
//buffer for process path
|
||||
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE] = {0};
|
||||
|
||||
//status
|
||||
int status = -1;
|
||||
|
||||
//process ID
|
||||
NSNumber* processID = nil;
|
||||
|
||||
//process name
|
||||
NSString* processName = nil;
|
||||
|
||||
//get # of procs
|
||||
numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
|
||||
|
||||
//alloc buffer for pids
|
||||
pids = calloc(numberOfProcesses, sizeof(pid_t));
|
||||
|
||||
//get list of pids
|
||||
status = proc_listpids(PROC_ALL_PIDS, 0, pids, numberOfProcesses * sizeof(pid_t));
|
||||
if(status < 0)
|
||||
{
|
||||
//err
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: proc_listpids() failed with %d", status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//iterate over all pids
|
||||
// ->get name for each
|
||||
for(int i = 0; i < numberOfProcesses; ++i)
|
||||
{
|
||||
//skip blank pids
|
||||
if(0 == pids[i])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//reset buffer
|
||||
bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
|
||||
|
||||
//init process ID
|
||||
processID = [NSNumber numberWithInt:pids[i]];
|
||||
|
||||
//get path
|
||||
status = proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
|
||||
|
||||
//sanity check
|
||||
// ->this generally just fails if process has exited....
|
||||
if( (status < 0) ||
|
||||
(0 == strlen(pathBuffer)) )
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//init process name
|
||||
processName = [NSString stringWithUTF8String:pathBuffer];
|
||||
|
||||
//init task
|
||||
// ->pass in pid and name
|
||||
task = [[Task alloc] initWithPID:processID andPath:processName];
|
||||
|
||||
//add task to list
|
||||
// ->order by pid for now
|
||||
[allTasks setObject:task forKey:processID];
|
||||
}
|
||||
|
||||
//always add kernel's task
|
||||
// ->hardcoded pid (0) and path to kernel
|
||||
task = [[Task alloc] initWithPID:@0 andPath:path2Kernel()];
|
||||
|
||||
//add kernel task
|
||||
[allTasks setObject:task forKey:@0];
|
||||
|
||||
//reverse array
|
||||
// ->want order to go from 0 -> ...
|
||||
[allTasks reverse];
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free buffer
|
||||
if(NULL != pids)
|
||||
{
|
||||
//free
|
||||
free(pids);
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
//NSLog(@"OBJECTIVE-SEE INFO: done scanning running processes");
|
||||
|
||||
return allTasks;
|
||||
}
|
||||
|
||||
//insert tasks into appropriate parent
|
||||
// ->ensures order of parent's (by pid), is preserved
|
||||
//TODO: what about parentless procs!? (e.g. malware?)
|
||||
-(void)generateAncestries:(OrderedDictionary*)newTasks
|
||||
{
|
||||
//task
|
||||
Task* task = nil;
|
||||
|
||||
//parent
|
||||
Task* parent = nil;
|
||||
|
||||
//comparator
|
||||
NSComparator comparator = nil;
|
||||
|
||||
//index
|
||||
// ->where task should be inserted into parent's child array
|
||||
NSUInteger childIndex = 0;
|
||||
|
||||
//init comparator
|
||||
comparator = ^(id obj1, id obj2) { return NSOrderedSame; };
|
||||
|
||||
//interate over all task
|
||||
// ->insert task into parent's *ordered* child array
|
||||
for(NSNumber* key in newTasks.allKeys)
|
||||
{
|
||||
//get task
|
||||
task = newTasks[key];
|
||||
|
||||
//get parent
|
||||
parent = newTasks[task.ppid];
|
||||
|
||||
//ignore tasks that are their own parent
|
||||
// ->i.e. kernel_task
|
||||
if(YES == [task.pid isEqualToNumber:task.ppid])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//get index where child should be inserted
|
||||
childIndex = [parent.children indexOfObject:task.pid
|
||||
inSortedRange:(NSRange){0, [parent.children count]}
|
||||
options:NSBinarySearchingInsertionIndex usingComparator:comparator];
|
||||
|
||||
//insert child
|
||||
[parent.children insertObject:task.pid atIndex:childIndex];
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icon</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.objective-see.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.2.3</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015 Objective-See, LLC. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'KnockKnock' target in the 'KnockKnock' project
|
||||
//
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
@@ -0,0 +1,916 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1D21BC4F172AF43D009D1CFD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D21BC4E172AF43D009D1CFD /* Cocoa.framework */; };
|
||||
CD001B371AB903040089014A /* kkText.png in Resources */ = {isa = PBXBuildFile; fileRef = CD001B341AB903040089014A /* kkText.png */; };
|
||||
CD001B381AB903040089014A /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = CD001B351AB903040089014A /* logo.png */; };
|
||||
CD001B391AB903040089014A /* logoApple.png in Resources */ = {isa = PBXBuildFile; fileRef = CD001B361AB903040089014A /* logoApple.png */; };
|
||||
CD02194F1AD34D8B005148A2 /* AboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD02194D1AD34D8B005148A2 /* AboutWindow.xib */; };
|
||||
CD0219501AD34D8B005148A2 /* PrefsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD02194E1AD34D8B005148A2 /* PrefsWindow.xib */; };
|
||||
CD0219531AD34D9A005148A2 /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD0219521AD34D9A005148A2 /* AboutWindowController.m */; };
|
||||
CD0219551AD34E4C005148A2 /* kkIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD0219541AD34E4C005148A2 /* kkIcon.png */; };
|
||||
CD0219581AD37748005148A2 /* signed2.png in Resources */ = {isa = PBXBuildFile; fileRef = CD0219561AD37748005148A2 /* signed2.png */; };
|
||||
CD0219591AD37748005148A2 /* unsigned2.png in Resources */ = {isa = PBXBuildFile; fileRef = CD0219571AD37748005148A2 /* unsigned2.png */; };
|
||||
CD02195C1AD38823005148A2 /* kkRowCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD02195B1AD38823005148A2 /* kkRowCell.m */; };
|
||||
CD02195E1AD39A74005148A2 /* ResultsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD02195D1AD39A74005148A2 /* ResultsWindow.xib */; };
|
||||
CD0219611AD39A83005148A2 /* ResultsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD0219601AD39A83005148A2 /* ResultsWindowController.m */; };
|
||||
CD3F4CE81AF5CF68002A2647 /* TaskEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CE61AF5CF68002A2647 /* TaskEnumerator.m */; };
|
||||
CD3F4CEB1AF6D948002A2647 /* OrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CEA1AF6D948002A2647 /* OrderedDictionary.m */; };
|
||||
CD3F4CFA1AF71B58002A2647 /* Binary.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CF31AF71B58002A2647 /* Binary.m */; };
|
||||
CD3F4CFB1AF71B58002A2647 /* Connection.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CF51AF71B58002A2647 /* Connection.m */; };
|
||||
CD3F4CFC1AF71B58002A2647 /* File.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CF71AF71B58002A2647 /* File.m */; };
|
||||
CD3F4CFD1AF71B58002A2647 /* ItemBase.m in Sources */ = {isa = PBXBuildFile; fileRef = CD3F4CF91AF71B58002A2647 /* ItemBase.m */; };
|
||||
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 */; };
|
||||
CD4D541F1B2CE6C400008030 /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = CD4D541E1B2CE6C400008030 /* Queue.m */; };
|
||||
CD4D54221B2CE6F200008030 /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD4D54211B2CE6F200008030 /* NSMutableArray+QueueAdditions.m */; };
|
||||
CD4D54241B2D082300008030 /* DylibInfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD4D54231B2D082300008030 /* DylibInfoWindow.xib */; };
|
||||
CD6095731A87067D00E091CD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD6095721A87067D00E091CD /* Security.framework */; };
|
||||
CD6E54FF1B1162B5007953AB /* ItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6E54FE1B1162B5007953AB /* ItemView.m */; };
|
||||
CD7B9F4D1ACB959200DF3C71 /* logoAppleOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9F4C1ACB959200DF3C71 /* logoAppleOver.png */; };
|
||||
CD7B9F501ACB9A8400DF3C71 /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = CD7B9F4F1ACB9A8400DF3C71 /* Exception.m */; };
|
||||
CD7B9FA41ACBCFAD00DF3C71 /* spotlightIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9FA31ACBCFAD00DF3C71 /* spotlightIcon.png */; };
|
||||
CD7B9FA71ACCAE5E00DF3C71 /* startScanOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9FA51ACCAE5E00DF3C71 /* startScanOver.png */; };
|
||||
CD7B9FA81ACCAE5E00DF3C71 /* stopScanOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CD7B9FA61ACCAE5E00DF3C71 /* stopScanOver.png */; };
|
||||
CD7B9FAB1AD08FA100DF3C71 /* KKRow.m in Sources */ = {isa = PBXBuildFile; fileRef = CD7B9FAA1AD08FA100DF3C71 /* KKRow.m */; };
|
||||
CD83887F1AACCEDF000EB098 /* VirusTotal.m in Sources */ = {isa = PBXBuildFile; fileRef = CD83887E1AACCEDF000EB098 /* VirusTotal.m */; };
|
||||
CDA5F6B41B16D805003CE340 /* remoteTaskService.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA5F6B31B16D805003CE340 /* remoteTaskService.m */; };
|
||||
CDA5F6B61B16D805003CE340 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA5F6B51B16D805003CE340 /* main.m */; };
|
||||
CDA5F6BA1B16D805003CE340 /* remoteTaskService.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = CDA5F6AD1B16D805003CE340 /* remoteTaskService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
CDA5F6C11B16E1D6003CE340 /* RequestRootWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDA5F6C01B16E1D6003CE340 /* RequestRootWindow.xib */; };
|
||||
CDA5F6C41B16E20E003CE340 /* RequestRootWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA5F6C31B16E20E003CE340 /* RequestRootWindowController.m */; };
|
||||
CDA5F6C61B16E8D4003CE340 /* lockIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA5F6C51B16E8D4003CE340 /* lockIcon.png */; };
|
||||
CDA81D4F1A95B492009790E2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81D451A95B492009790E2 /* AppDelegate.m */; };
|
||||
CDA81D531A95B492009790E2 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81D4E1A95B492009790E2 /* Utilities.m */; };
|
||||
CDA81D5B1A95B4B4009790E2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D541A95B4B4009790E2 /* InfoPlist.strings */; };
|
||||
CDA81D5C1A95B4B4009790E2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D561A95B4B4009790E2 /* MainMenu.xib */; };
|
||||
CDA81D5E1A95B4B4009790E2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81D5A1A95B4B4009790E2 /* main.m */; };
|
||||
CDA81D691A95B4E9009790E2 /* bug.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D5F1A95B4E9009790E2 /* bug.png */; };
|
||||
CDA81D6A1A95B4E9009790E2 /* mainIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D601A95B4E9009790E2 /* mainIcon.png */; };
|
||||
CDA81D6B1A95B4E9009790E2 /* show.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D611A95B4E9009790E2 /* show.png */; };
|
||||
CDA81D6C1A95B4E9009790E2 /* showBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D621A95B4E9009790E2 /* showBG.png */; };
|
||||
CDA81D6D1A95B4E9009790E2 /* scanIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D631A95B4E9009790E2 /* scanIcon.png */; };
|
||||
CDA81D6E1A95B4E9009790E2 /* startScan.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D641A95B4E9009790E2 /* startScan.png */; };
|
||||
CDA81D6F1A95B4E9009790E2 /* startScanBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D651A95B4E9009790E2 /* startScanBG.png */; };
|
||||
CDA81D701A95B4E9009790E2 /* stopScan.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D661A95B4E9009790E2 /* stopScan.png */; };
|
||||
CDA81D711A95B4E9009790E2 /* stopScanBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D671A95B4E9009790E2 /* stopScanBG.png */; };
|
||||
CDA81D721A95B4E9009790E2 /* virus.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D681A95B4E9009790E2 /* virus.png */; };
|
||||
CDA81D741A95B4FB009790E2 /* icon.iconset in Resources */ = {isa = PBXBuildFile; fileRef = CDA81D731A95B4FB009790E2 /* icon.iconset */; };
|
||||
CDA81D7B1A95D29B009790E2 /* TaskTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81D7A1A95D29B009790E2 /* TaskTableController.m */; };
|
||||
CDA81DC91A9960A3009790E2 /* info.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DC51A9960A3009790E2 /* info.png */; };
|
||||
CDA81DCA1A9960A3009790E2 /* infoBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DC61A9960A3009790E2 /* infoBG.png */; };
|
||||
CDA81DCB1A9960A3009790E2 /* virusTotal.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DC71A9960A3009790E2 /* virusTotal.png */; };
|
||||
CDA81DCC1A9960A3009790E2 /* virusTotalBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DC81A9960A3009790E2 /* virusTotalBG.png */; };
|
||||
CDA81DD31A9970A0009790E2 /* signed.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DD11A9970A0009790E2 /* signed.png */; };
|
||||
CDA81DD41A9970A0009790E2 /* unsigned.png in Resources */ = {isa = PBXBuildFile; fileRef = CDA81DD21A9970A0009790E2 /* unsigned.png */; };
|
||||
CDA81DEA1A997BF1009790E2 /* InfoWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81DE81A997BF1009790E2 /* InfoWindowController.m */; };
|
||||
CDA81DEE1A99B5F8009790E2 /* Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA81DED1A99B5F8009790E2 /* Filter.m */; };
|
||||
CDA81E661AA020FD009790E2 /* FileInfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDA81E641AA020FD009790E2 /* FileInfoWindow.xib */; };
|
||||
CDAB98A11AEAFAFA00C75B4B /* authorizationIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAB98A01AEAFAFA00C75B4B /* authorizationIcon.png */; };
|
||||
CDAB98A31AEB413C00C75B4B /* dylibIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDAB98A21AEB413C00C75B4B /* dylibIcon.png */; };
|
||||
CDD248341AF5947300232422 /* TAAdaptiveSpaceItem.m in Sources */ = {isa = PBXBuildFile; fileRef = CDD248311AF5947300232422 /* TAAdaptiveSpaceItem.m */; };
|
||||
CDD248351AF5947300232422 /* TAAdaptiveSpaceItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = CDD248331AF5947300232422 /* TAAdaptiveSpaceItemView.m */; };
|
||||
CDD2483B1AF5CC4D00232422 /* Task.m in Sources */ = {isa = PBXBuildFile; fileRef = CDD2483A1AF5CC4D00232422 /* Task.m */; };
|
||||
CDF08CBF1AC3DE25009B3423 /* logoAppleBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CBE1AC3DE25009B3423 /* logoAppleBG.png */; };
|
||||
CDF08CC11AC3E8B0009B3423 /* showOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CC01AC3E8B0009B3423 /* showOver.png */; };
|
||||
CDF08CC31AC3E98D009B3423 /* infoOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CC21AC3E98D009B3423 /* infoOver.png */; };
|
||||
CDF08CC61AC46E75009B3423 /* VTButton.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF08CC51AC46E75009B3423 /* VTButton.m */; };
|
||||
CDF08CCA1AC4C678009B3423 /* PrefsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF08CC81AC4C678009B3423 /* PrefsWindowController.m */; };
|
||||
CDF08CCF1AC4C6E8009B3423 /* settingsOver.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CCC1AC4C6E8009B3423 /* settingsOver.png */; };
|
||||
CDF08CD01AC4C6E8009B3423 /* settingsBG.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CCD1AC4C6E8009B3423 /* settingsBG.png */; };
|
||||
CDF08CD11AC4C6E8009B3423 /* settings.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CCE1AC4C6E8009B3423 /* settings.png */; };
|
||||
CDF08CDF1AC886F2009B3423 /* VTInfoWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF08CDD1AC886F2009B3423 /* VTInfoWindowController.m */; };
|
||||
CDF08CE21AC88E0F009B3423 /* VTInfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CE11AC88E0F009B3423 /* VTInfoWindow.xib */; };
|
||||
CDF08CE61AC89FE1009B3423 /* HyperlinkTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF08CE51AC89FE1009B3423 /* HyperlinkTextField.m */; };
|
||||
CDF08CE81AC8A35C009B3423 /* vtLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CE71AC8A35C009B3423 /* vtLogo.png */; };
|
||||
CDF08CEA1AC8D97B009B3423 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF08CE91AC8D97B009B3423 /* Quartz.framework */; };
|
||||
CDF08CEF1ACA677B009B3423 /* launchIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CED1ACA677B009B3423 /* launchIcon.png */; };
|
||||
CDF08CF01ACA677B009B3423 /* kernelIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CEE1ACA677B009B3423 /* kernelIcon.png */; };
|
||||
CDF08CF31ACA6864009B3423 /* browserIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CF11ACA6864009B3423 /* browserIcon.png */; };
|
||||
CDF08CF41ACA6864009B3423 /* loginIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = CDF08CF21ACA6864009B3423 /* loginIcon.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
CDA5F6B71B16D805003CE340 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 1D21BC43172AF43D009D1CFD /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = CDA5F6AC1B16D805003CE340;
|
||||
remoteInfo = remoteTaskService;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
CDA5F6B91B16D805003CE340 /* Embed XPC Services */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
CDA5F6BA1B16D805003CE340 /* remoteTaskService.xpc in Embed XPC Services */,
|
||||
);
|
||||
name = "Embed XPC Services";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1D21BC4B172AF43D009D1CFD /* TaskExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TaskExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1D21BC4E172AF43D009D1CFD /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
1D21BC51172AF43D009D1CFD /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
1D21BC52172AF43D009D1CFD /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
1D21BC53172AF43D009D1CFD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
CD001B341AB903040089014A /* kkText.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = kkText.png; path = images/kkText.png; sourceTree = SOURCE_ROOT; };
|
||||
CD001B351AB903040089014A /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo.png; path = images/logo.png; sourceTree = SOURCE_ROOT; };
|
||||
CD001B361AB903040089014A /* logoApple.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logoApple.png; path = images/logoApple.png; sourceTree = SOURCE_ROOT; };
|
||||
CD02194D1AD34D8B005148A2 /* AboutWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = AboutWindow.xib; path = UI/AboutWindow.xib; sourceTree = "<group>"; };
|
||||
CD02194E1AD34D8B005148A2 /* PrefsWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = PrefsWindow.xib; path = UI/PrefsWindow.xib; sourceTree = "<group>"; };
|
||||
CD0219511AD34D9A005148A2 /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutWindowController.h; sourceTree = "<group>"; };
|
||||
CD0219521AD34D9A005148A2 /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AboutWindowController.m; sourceTree = "<group>"; };
|
||||
CD0219541AD34E4C005148A2 /* kkIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = kkIcon.png; path = images/kkIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CD0219561AD37748005148A2 /* signed2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = signed2.png; path = images/signed2.png; sourceTree = SOURCE_ROOT; };
|
||||
CD0219571AD37748005148A2 /* unsigned2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = unsigned2.png; path = images/unsigned2.png; sourceTree = SOURCE_ROOT; };
|
||||
CD02195A1AD38823005148A2 /* kkRowCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kkRowCell.h; sourceTree = "<group>"; };
|
||||
CD02195B1AD38823005148A2 /* kkRowCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kkRowCell.m; sourceTree = "<group>"; };
|
||||
CD02195D1AD39A74005148A2 /* ResultsWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ResultsWindow.xib; path = UI/ResultsWindow.xib; sourceTree = "<group>"; };
|
||||
CD02195F1AD39A83005148A2 /* ResultsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultsWindowController.h; sourceTree = "<group>"; };
|
||||
CD0219601AD39A83005148A2 /* ResultsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ResultsWindowController.m; sourceTree = "<group>"; };
|
||||
CD3F4CE61AF5CF68002A2647 /* TaskEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TaskEnumerator.m; sourceTree = SOURCE_ROOT; };
|
||||
CD3F4CE71AF5CF68002A2647 /* TaskEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TaskEnumerator.h; sourceTree = SOURCE_ROOT; };
|
||||
CD3F4CE91AF6D948002A2647 /* OrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OrderedDictionary.h; path = 3rdParty/OrderedDictionary.h; sourceTree = "<group>"; };
|
||||
CD3F4CEA1AF6D948002A2647 /* OrderedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OrderedDictionary.m; path = 3rdParty/OrderedDictionary.m; sourceTree = "<group>"; };
|
||||
CD3F4CF21AF71B58002A2647 /* Binary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Binary.h; path = Items/Binary.h; sourceTree = "<group>"; };
|
||||
CD3F4CF31AF71B58002A2647 /* Binary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Binary.m; path = Items/Binary.m; sourceTree = "<group>"; };
|
||||
CD3F4CF41AF71B58002A2647 /* Connection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Connection.h; path = Items/Connection.h; sourceTree = "<group>"; };
|
||||
CD3F4CF51AF71B58002A2647 /* Connection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Connection.m; path = Items/Connection.m; sourceTree = "<group>"; };
|
||||
CD3F4CF61AF71B58002A2647 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = File.h; path = Items/File.h; sourceTree = "<group>"; };
|
||||
CD3F4CF71AF71B58002A2647 /* File.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = File.m; path = Items/File.m; sourceTree = "<group>"; };
|
||||
CD3F4CF81AF71B58002A2647 /* ItemBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ItemBase.h; path = Items/ItemBase.h; sourceTree = "<group>"; };
|
||||
CD3F4CF91AF71B58002A2647 /* ItemBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ItemBase.m; path = Items/ItemBase.m; sourceTree = "<group>"; };
|
||||
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; };
|
||||
CD4D541D1B2CE6C400008030 /* Queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Queue.h; sourceTree = "<group>"; };
|
||||
CD4D541E1B2CE6C400008030 /* Queue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Queue.m; sourceTree = "<group>"; };
|
||||
CD4D54201B2CE6F200008030 /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
|
||||
CD4D54211B2CE6F200008030 /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
|
||||
CD4D54231B2D082300008030 /* DylibInfoWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = DylibInfoWindow.xib; path = UI/DylibInfoWindow.xib; sourceTree = "<group>"; };
|
||||
CD6095721A87067D00E091CD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
CD6E54FD1B1162B5007953AB /* ItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ItemView.h; sourceTree = "<group>"; };
|
||||
CD6E54FE1B1162B5007953AB /* ItemView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ItemView.m; sourceTree = "<group>"; };
|
||||
CD7B9F4C1ACB959200DF3C71 /* logoAppleOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logoAppleOver.png; path = images/logoAppleOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9F4E1ACB9A8400DF3C71 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9F4F1ACB9A8400DF3C71 /* Exception.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Exception.m; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9FA31ACBCFAD00DF3C71 /* spotlightIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = spotlightIcon.png; path = images/spotlightIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9FA51ACCAE5E00DF3C71 /* startScanOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = startScanOver.png; path = images/startScanOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9FA61ACCAE5E00DF3C71 /* stopScanOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopScanOver.png; path = images/stopScanOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CD7B9FA91AD08FA100DF3C71 /* KKRow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KKRow.h; sourceTree = "<group>"; };
|
||||
CD7B9FAA1AD08FA100DF3C71 /* KKRow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KKRow.m; sourceTree = "<group>"; };
|
||||
CD83887D1AACCEDF000EB098 /* VirusTotal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirusTotal.h; sourceTree = "<group>"; };
|
||||
CD83887E1AACCEDF000EB098 /* VirusTotal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VirusTotal.m; sourceTree = "<group>"; };
|
||||
CDA5F6AD1B16D805003CE340 /* remoteTaskService.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = remoteTaskService.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CDA5F6B01B16D805003CE340 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
CDA5F6B21B16D805003CE340 /* remoteTaskService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = remoteTaskService.h; sourceTree = "<group>"; };
|
||||
CDA5F6B31B16D805003CE340 /* remoteTaskService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = remoteTaskService.m; sourceTree = "<group>"; };
|
||||
CDA5F6B51B16D805003CE340 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
CDA5F6BF1B16DBC9003CE340 /* serviceInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = serviceInterface.h; sourceTree = "<group>"; };
|
||||
CDA5F6C01B16E1D6003CE340 /* RequestRootWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RequestRootWindow.xib; path = UI/RequestRootWindow.xib; sourceTree = "<group>"; };
|
||||
CDA5F6C21B16E20E003CE340 /* RequestRootWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RequestRootWindowController.h; sourceTree = "<group>"; };
|
||||
CDA5F6C31B16E20E003CE340 /* RequestRootWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RequestRootWindowController.m; sourceTree = "<group>"; };
|
||||
CDA5F6C51B16E8D4003CE340 /* lockIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = lockIcon.png; path = images/lockIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D441A95B492009790E2 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D451A95B492009790E2 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D481A95B492009790E2 /* Consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Consts.h; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D4D1A95B492009790E2 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D4E1A95B492009790E2 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D551A95B4B4009790E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D571A95B4B4009790E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D581A95B4B4009790E2 /* TaskExplorer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TaskExplorer-Info.plist"; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D591A95B4B4009790E2 /* TaskExplorer-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskExplorer-Prefix.pch"; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D5A1A95B4B4009790E2 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D5F1A95B4E9009790E2 /* bug.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = bug.png; path = images/bug.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D601A95B4E9009790E2 /* mainIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = mainIcon.png; path = images/mainIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D611A95B4E9009790E2 /* show.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = show.png; path = images/show.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D621A95B4E9009790E2 /* showBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = showBG.png; path = images/showBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D631A95B4E9009790E2 /* scanIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = scanIcon.png; path = images/scanIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D641A95B4E9009790E2 /* startScan.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = startScan.png; path = images/startScan.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D651A95B4E9009790E2 /* startScanBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = startScanBG.png; path = images/startScanBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D661A95B4E9009790E2 /* stopScan.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopScan.png; path = images/stopScan.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D671A95B4E9009790E2 /* stopScanBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopScanBG.png; path = images/stopScanBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D681A95B4E9009790E2 /* virus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = virus.png; path = images/virus.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D731A95B4FB009790E2 /* icon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = icon.iconset; path = images/icon.iconset; sourceTree = SOURCE_ROOT; };
|
||||
CDA81D791A95D29B009790E2 /* TaskTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TaskTableController.h; sourceTree = "<group>"; };
|
||||
CDA81D7A1A95D29B009790E2 /* TaskTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TaskTableController.m; sourceTree = "<group>"; };
|
||||
CDA81DC51A9960A3009790E2 /* info.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = info.png; path = images/info.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DC61A9960A3009790E2 /* infoBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoBG.png; path = images/infoBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DC71A9960A3009790E2 /* virusTotal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = virusTotal.png; path = images/virusTotal.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DC81A9960A3009790E2 /* virusTotalBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = virusTotalBG.png; path = images/virusTotalBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DD11A9970A0009790E2 /* signed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = signed.png; path = images/signed.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DD21A9970A0009790E2 /* unsigned.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = unsigned.png; path = images/unsigned.png; sourceTree = SOURCE_ROOT; };
|
||||
CDA81DE71A997BF1009790E2 /* InfoWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoWindowController.h; sourceTree = "<group>"; };
|
||||
CDA81DE81A997BF1009790E2 /* InfoWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InfoWindowController.m; sourceTree = "<group>"; };
|
||||
CDA81DEC1A99B5F8009790E2 /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
|
||||
CDA81DED1A99B5F8009790E2 /* Filter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Filter.m; sourceTree = "<group>"; };
|
||||
CDA81E641AA020FD009790E2 /* FileInfoWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FileInfoWindow.xib; path = UI/FileInfoWindow.xib; sourceTree = "<group>"; };
|
||||
CDAB98A01AEAFAFA00C75B4B /* authorizationIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = authorizationIcon.png; path = images/authorizationIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDAB98A21AEB413C00C75B4B /* dylibIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dylibIcon.png; path = images/dylibIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDD248301AF5947300232422 /* TAAdaptiveSpaceItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TAAdaptiveSpaceItem.h; path = 3rdParty/TAAdaptiveSpaceItem.h; sourceTree = "<group>"; };
|
||||
CDD248311AF5947300232422 /* TAAdaptiveSpaceItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TAAdaptiveSpaceItem.m; path = 3rdParty/TAAdaptiveSpaceItem.m; sourceTree = "<group>"; };
|
||||
CDD248321AF5947300232422 /* TAAdaptiveSpaceItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TAAdaptiveSpaceItemView.h; path = 3rdParty/TAAdaptiveSpaceItemView.h; sourceTree = "<group>"; };
|
||||
CDD248331AF5947300232422 /* TAAdaptiveSpaceItemView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TAAdaptiveSpaceItemView.m; path = 3rdParty/TAAdaptiveSpaceItemView.m; sourceTree = "<group>"; };
|
||||
CDD248391AF5CC4D00232422 /* Task.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Task.h; sourceTree = SOURCE_ROOT; };
|
||||
CDD2483A1AF5CC4D00232422 /* Task.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Task.m; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CBE1AC3DE25009B3423 /* logoAppleBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logoAppleBG.png; path = images/logoAppleBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC01AC3E8B0009B3423 /* showOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = showOver.png; path = images/showOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC21AC3E98D009B3423 /* infoOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = infoOver.png; path = images/infoOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC41AC46E75009B3423 /* VTButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTButton.h; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC51AC46E75009B3423 /* VTButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTButton.m; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC71AC4C678009B3423 /* PrefsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrefsWindowController.h; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CC81AC4C678009B3423 /* PrefsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrefsWindowController.m; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CCC1AC4C6E8009B3423 /* settingsOver.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = settingsOver.png; path = images/settingsOver.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CCD1AC4C6E8009B3423 /* settingsBG.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = settingsBG.png; path = images/settingsBG.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CCE1AC4C6E8009B3423 /* settings.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = settings.png; path = images/settings.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CDC1AC886F2009B3423 /* VTInfoWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTInfoWindowController.h; sourceTree = "<group>"; };
|
||||
CDF08CDD1AC886F2009B3423 /* VTInfoWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTInfoWindowController.m; sourceTree = "<group>"; };
|
||||
CDF08CE11AC88E0F009B3423 /* VTInfoWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VTInfoWindow.xib; path = UI/VTInfoWindow.xib; sourceTree = "<group>"; };
|
||||
CDF08CE41AC89FE1009B3423 /* HyperlinkTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HyperlinkTextField.h; path = 3rdParty/HyperlinkTextField.h; sourceTree = "<group>"; };
|
||||
CDF08CE51AC89FE1009B3423 /* HyperlinkTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HyperlinkTextField.m; path = 3rdParty/HyperlinkTextField.m; sourceTree = "<group>"; };
|
||||
CDF08CE71AC8A35C009B3423 /* vtLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = vtLogo.png; path = images/vtLogo.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CE91AC8D97B009B3423 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
|
||||
CDF08CED1ACA677B009B3423 /* launchIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = launchIcon.png; path = images/launchIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CEE1ACA677B009B3423 /* kernelIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = kernelIcon.png; path = images/kernelIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CF11ACA6864009B3423 /* browserIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = browserIcon.png; path = images/browserIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
CDF08CF21ACA6864009B3423 /* loginIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = loginIcon.png; path = images/loginIcon.png; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
1D21BC48172AF43D009D1CFD /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CDF08CEA1AC8D97B009B3423 /* Quartz.framework in Frameworks */,
|
||||
CD6095731A87067D00E091CD /* Security.framework in Frameworks */,
|
||||
1D21BC4F172AF43D009D1CFD /* Cocoa.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CDA5F6AA1B16D805003CE340 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1D21BC42172AF43D009D1CFD = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD4D54201B2CE6F200008030 /* NSMutableArray+QueueAdditions.h */,
|
||||
CD4D54211B2CE6F200008030 /* NSMutableArray+QueueAdditions.m */,
|
||||
CD4D541D1B2CE6C400008030 /* Queue.h */,
|
||||
CD4D541E1B2CE6C400008030 /* Queue.m */,
|
||||
CDA5F6BE1B16DBAA003CE340 /* Interface */,
|
||||
CD02195A1AD38823005148A2 /* kkRowCell.h */,
|
||||
CD02195B1AD38823005148A2 /* kkRowCell.m */,
|
||||
CD7B9FA91AD08FA100DF3C71 /* KKRow.h */,
|
||||
CD7B9FAA1AD08FA100DF3C71 /* KKRow.m */,
|
||||
CDF08CE31AC89FD4009B3423 /* 3rdParty */,
|
||||
CD83887D1AACCEDF000EB098 /* VirusTotal.h */,
|
||||
CD83887E1AACCEDF000EB098 /* VirusTotal.m */,
|
||||
CDA81E621AA020E8009790E2 /* UI */,
|
||||
CDA81DEC1A99B5F8009790E2 /* Filter.h */,
|
||||
CDA81DED1A99B5F8009790E2 /* Filter.m */,
|
||||
CDA81D7C1A96EFFF009790E2 /* Items */,
|
||||
CDA81D781A95B939009790E2 /* UIControllers */,
|
||||
1D21BC54172AF43D009D1CFD /* TaskExplorer */,
|
||||
CDA5F6AE1B16D805003CE340 /* remoteTaskService */,
|
||||
1D21BC4D172AF43D009D1CFD /* Frameworks */,
|
||||
1D21BC4C172AF43D009D1CFD /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1D21BC4C172AF43D009D1CFD /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D21BC4B172AF43D009D1CFD /* TaskExplorer.app */,
|
||||
CDA5F6AD1B16D805003CE340 /* remoteTaskService.xpc */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1D21BC4D172AF43D009D1CFD /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDF08CE91AC8D97B009B3423 /* Quartz.framework */,
|
||||
CD6095721A87067D00E091CD /* Security.framework */,
|
||||
1D21BC4E172AF43D009D1CFD /* Cocoa.framework */,
|
||||
1D21BC50172AF43D009D1CFD /* Other Frameworks */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1D21BC50172AF43D009D1CFD /* Other Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1D21BC51172AF43D009D1CFD /* AppKit.framework */,
|
||||
1D21BC52172AF43D009D1CFD /* CoreData.framework */,
|
||||
1D21BC53172AF43D009D1CFD /* Foundation.framework */,
|
||||
);
|
||||
name = "Other Frameworks";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1D21BC54172AF43D009D1CFD /* TaskExplorer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD3F4CE61AF5CF68002A2647 /* TaskEnumerator.m */,
|
||||
CD3F4CE71AF5CF68002A2647 /* TaskEnumerator.h */,
|
||||
CDD248391AF5CC4D00232422 /* Task.h */,
|
||||
CDD2483A1AF5CC4D00232422 /* Task.m */,
|
||||
CD7B9F4E1ACB9A8400DF3C71 /* Exception.h */,
|
||||
CD7B9F4F1ACB9A8400DF3C71 /* Exception.m */,
|
||||
CDF08CC71AC4C678009B3423 /* PrefsWindowController.h */,
|
||||
CDF08CC81AC4C678009B3423 /* PrefsWindowController.m */,
|
||||
CDA81D731A95B4FB009790E2 /* icon.iconset */,
|
||||
CDA81D561A95B4B4009790E2 /* MainMenu.xib */,
|
||||
CDF08CC41AC46E75009B3423 /* VTButton.h */,
|
||||
CDF08CC51AC46E75009B3423 /* VTButton.m */,
|
||||
CDA81D441A95B492009790E2 /* AppDelegate.h */,
|
||||
CDA81D451A95B492009790E2 /* AppDelegate.m */,
|
||||
CDA81D481A95B492009790E2 /* Consts.h */,
|
||||
CDA81D4D1A95B492009790E2 /* Utilities.h */,
|
||||
CDA81D4E1A95B492009790E2 /* Utilities.m */,
|
||||
CD6095501A8329FA00E091CD /* images */,
|
||||
1D21BC55172AF43D009D1CFD /* Supporting Files */,
|
||||
);
|
||||
name = TaskExplorer;
|
||||
path = "Lesson 53";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1D21BC55172AF43D009D1CFD /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA81D541A95B4B4009790E2 /* InfoPlist.strings */,
|
||||
CDA81D581A95B4B4009790E2 /* TaskExplorer-Info.plist */,
|
||||
CDA81D591A95B4B4009790E2 /* TaskExplorer-Prefix.pch */,
|
||||
CDA81D5A1A95B4B4009790E2 /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CD6095501A8329FA00E091CD /* images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD4D53D11B23ED4300008030 /* listeningIcon.png */,
|
||||
CD4D53CF1B23ED3900008030 /* connectedIcon.png */,
|
||||
CD4D53C91B20296E00008030 /* unknown.png */,
|
||||
CDA5F6C51B16E8D4003CE340 /* lockIcon.png */,
|
||||
CDAB98A21AEB413C00C75B4B /* dylibIcon.png */,
|
||||
CDAB98A01AEAFAFA00C75B4B /* authorizationIcon.png */,
|
||||
CD0219561AD37748005148A2 /* signed2.png */,
|
||||
CD0219571AD37748005148A2 /* unsigned2.png */,
|
||||
CD0219541AD34E4C005148A2 /* kkIcon.png */,
|
||||
CD7B9FA51ACCAE5E00DF3C71 /* startScanOver.png */,
|
||||
CD7B9FA61ACCAE5E00DF3C71 /* stopScanOver.png */,
|
||||
CD7B9FA31ACBCFAD00DF3C71 /* spotlightIcon.png */,
|
||||
CD7B9F4C1ACB959200DF3C71 /* logoAppleOver.png */,
|
||||
CDF08CF11ACA6864009B3423 /* browserIcon.png */,
|
||||
CDF08CF21ACA6864009B3423 /* loginIcon.png */,
|
||||
CDF08CED1ACA677B009B3423 /* launchIcon.png */,
|
||||
CDF08CEE1ACA677B009B3423 /* kernelIcon.png */,
|
||||
CDF08CE71AC8A35C009B3423 /* vtLogo.png */,
|
||||
CDF08CCC1AC4C6E8009B3423 /* settingsOver.png */,
|
||||
CDF08CCD1AC4C6E8009B3423 /* settingsBG.png */,
|
||||
CDF08CCE1AC4C6E8009B3423 /* settings.png */,
|
||||
CDF08CC21AC3E98D009B3423 /* infoOver.png */,
|
||||
CDF08CC01AC3E8B0009B3423 /* showOver.png */,
|
||||
CDF08CBE1AC3DE25009B3423 /* logoAppleBG.png */,
|
||||
CD001B341AB903040089014A /* kkText.png */,
|
||||
CD001B351AB903040089014A /* logo.png */,
|
||||
CD001B361AB903040089014A /* logoApple.png */,
|
||||
CDA81DD11A9970A0009790E2 /* signed.png */,
|
||||
CDA81DD21A9970A0009790E2 /* unsigned.png */,
|
||||
CDA81DC51A9960A3009790E2 /* info.png */,
|
||||
CDA81DC61A9960A3009790E2 /* infoBG.png */,
|
||||
CDA81DC71A9960A3009790E2 /* virusTotal.png */,
|
||||
CDA81DC81A9960A3009790E2 /* virusTotalBG.png */,
|
||||
CDA81D5F1A95B4E9009790E2 /* bug.png */,
|
||||
CDA81D601A95B4E9009790E2 /* mainIcon.png */,
|
||||
CDA81D611A95B4E9009790E2 /* show.png */,
|
||||
CDA81D621A95B4E9009790E2 /* showBG.png */,
|
||||
CDA81D631A95B4E9009790E2 /* scanIcon.png */,
|
||||
CDA81D641A95B4E9009790E2 /* startScan.png */,
|
||||
CDA81D651A95B4E9009790E2 /* startScanBG.png */,
|
||||
CDA81D661A95B4E9009790E2 /* stopScan.png */,
|
||||
CDA81D671A95B4E9009790E2 /* stopScanBG.png */,
|
||||
CDA81D681A95B4E9009790E2 /* virus.png */,
|
||||
);
|
||||
name = images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA5F6AE1B16D805003CE340 /* remoteTaskService */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA5F6B21B16D805003CE340 /* remoteTaskService.h */,
|
||||
CDA5F6B31B16D805003CE340 /* remoteTaskService.m */,
|
||||
CDA5F6B51B16D805003CE340 /* main.m */,
|
||||
CDA5F6AF1B16D805003CE340 /* Supporting Files */,
|
||||
);
|
||||
path = remoteTaskService;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA5F6AF1B16D805003CE340 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA5F6B01B16D805003CE340 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA5F6BE1B16DBAA003CE340 /* Interface */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA5F6BF1B16DBC9003CE340 /* serviceInterface.h */,
|
||||
);
|
||||
name = Interface;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA81D781A95B939009790E2 /* UIControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDA5F6C21B16E20E003CE340 /* RequestRootWindowController.h */,
|
||||
CDA5F6C31B16E20E003CE340 /* RequestRootWindowController.m */,
|
||||
CD3F4D1A1AFADD36002A2647 /* TreeViewController.h */,
|
||||
CD3F4D1B1AFADD36002A2647 /* TreeViewController.m */,
|
||||
CD6E54FD1B1162B5007953AB /* ItemView.h */,
|
||||
CD6E54FE1B1162B5007953AB /* ItemView.m */,
|
||||
CD02195F1AD39A83005148A2 /* ResultsWindowController.h */,
|
||||
CD0219601AD39A83005148A2 /* ResultsWindowController.m */,
|
||||
CD0219511AD34D9A005148A2 /* AboutWindowController.h */,
|
||||
CD0219521AD34D9A005148A2 /* AboutWindowController.m */,
|
||||
CDF08CDC1AC886F2009B3423 /* VTInfoWindowController.h */,
|
||||
CDF08CDD1AC886F2009B3423 /* VTInfoWindowController.m */,
|
||||
CDA81DE71A997BF1009790E2 /* InfoWindowController.h */,
|
||||
CDA81DE81A997BF1009790E2 /* InfoWindowController.m */,
|
||||
CDA81D791A95D29B009790E2 /* TaskTableController.h */,
|
||||
CDA81D7A1A95D29B009790E2 /* TaskTableController.m */,
|
||||
);
|
||||
name = UIControllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA81D7C1A96EFFF009790E2 /* Items */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD3F4CF21AF71B58002A2647 /* Binary.h */,
|
||||
CD3F4CF31AF71B58002A2647 /* Binary.m */,
|
||||
CD3F4CF41AF71B58002A2647 /* Connection.h */,
|
||||
CD3F4CF51AF71B58002A2647 /* Connection.m */,
|
||||
CD3F4CF61AF71B58002A2647 /* File.h */,
|
||||
CD3F4CF71AF71B58002A2647 /* File.m */,
|
||||
CD3F4CF81AF71B58002A2647 /* ItemBase.h */,
|
||||
CD3F4CF91AF71B58002A2647 /* ItemBase.m */,
|
||||
);
|
||||
name = Items;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA81E621AA020E8009790E2 /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD4D54231B2D082300008030 /* DylibInfoWindow.xib */,
|
||||
CDA5F6C01B16E1D6003CE340 /* RequestRootWindow.xib */,
|
||||
CD3F4D151AF89066002A2647 /* TreeView.xib */,
|
||||
CD3F4D131AF85088002A2647 /* FlatView.xib */,
|
||||
CD3F4CFE1AF72BC4002A2647 /* TaskInfoWindow.xib */,
|
||||
CD02195D1AD39A74005148A2 /* ResultsWindow.xib */,
|
||||
CD02194D1AD34D8B005148A2 /* AboutWindow.xib */,
|
||||
CD02194E1AD34D8B005148A2 /* PrefsWindow.xib */,
|
||||
CDF08CE11AC88E0F009B3423 /* VTInfoWindow.xib */,
|
||||
CDA81E641AA020FD009790E2 /* FileInfoWindow.xib */,
|
||||
);
|
||||
name = UI;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDF08CE31AC89FD4009B3423 /* 3rdParty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD3F4CE91AF6D948002A2647 /* OrderedDictionary.h */,
|
||||
CD3F4CEA1AF6D948002A2647 /* OrderedDictionary.m */,
|
||||
CDD248301AF5947300232422 /* TAAdaptiveSpaceItem.h */,
|
||||
CDD248311AF5947300232422 /* TAAdaptiveSpaceItem.m */,
|
||||
CDD248321AF5947300232422 /* TAAdaptiveSpaceItemView.h */,
|
||||
CDD248331AF5947300232422 /* TAAdaptiveSpaceItemView.m */,
|
||||
CDF08CE41AC89FE1009B3423 /* HyperlinkTextField.h */,
|
||||
CDF08CE51AC89FE1009B3423 /* HyperlinkTextField.m */,
|
||||
);
|
||||
name = 3rdParty;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
1D21BC4A172AF43D009D1CFD /* TaskExplorer */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1D21BC68172AF43D009D1CFD /* Build configuration list for PBXNativeTarget "TaskExplorer" */;
|
||||
buildPhases = (
|
||||
1D21BC47172AF43D009D1CFD /* Sources */,
|
||||
1D21BC48172AF43D009D1CFD /* Frameworks */,
|
||||
1D21BC49172AF43D009D1CFD /* Resources */,
|
||||
CDA5F6B91B16D805003CE340 /* Embed XPC Services */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
CDA5F6B81B16D805003CE340 /* PBXTargetDependency */,
|
||||
);
|
||||
name = TaskExplorer;
|
||||
productName = "Lesson 53";
|
||||
productReference = 1D21BC4B172AF43D009D1CFD /* TaskExplorer.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
CDA5F6AC1B16D805003CE340 /* remoteTaskService */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CDA5F6BD1B16D805003CE340 /* Build configuration list for PBXNativeTarget "remoteTaskService" */;
|
||||
buildPhases = (
|
||||
CDA5F6A91B16D805003CE340 /* Sources */,
|
||||
CDA5F6AA1B16D805003CE340 /* Frameworks */,
|
||||
CDA5F6AB1B16D805003CE340 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = remoteTaskService;
|
||||
productName = remoteTaskService;
|
||||
productReference = CDA5F6AD1B16D805003CE340 /* remoteTaskService.xpc */;
|
||||
productType = "com.apple.product-type.xpc-service";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
1D21BC43172AF43D009D1CFD /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0620;
|
||||
ORGANIZATIONNAME = "Lucas Derraugh";
|
||||
TargetAttributes = {
|
||||
CDA5F6AC1B16D805003CE340 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 1D21BC46172AF43D009D1CFD /* Build configuration list for PBXProject "TaskExplorer" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 1D21BC42172AF43D009D1CFD;
|
||||
productRefGroup = 1D21BC4C172AF43D009D1CFD /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
1D21BC4A172AF43D009D1CFD /* TaskExplorer */,
|
||||
CDA5F6AC1B16D805003CE340 /* remoteTaskService */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
1D21BC49172AF43D009D1CFD /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CD4D53D01B23ED3900008030 /* connectedIcon.png in Resources */,
|
||||
CDF08CE81AC8A35C009B3423 /* vtLogo.png in Resources */,
|
||||
CDA81D691A95B4E9009790E2 /* bug.png in Resources */,
|
||||
CD02195E1AD39A74005148A2 /* ResultsWindow.xib in Resources */,
|
||||
CD3F4D141AF85088002A2647 /* FlatView.xib in Resources */,
|
||||
CDA81D5B1A95B4B4009790E2 /* InfoPlist.strings in Resources */,
|
||||
CD4D53CA1B20296E00008030 /* unknown.png in Resources */,
|
||||
CDA81D6B1A95B4E9009790E2 /* show.png in Resources */,
|
||||
CDF08CF31ACA6864009B3423 /* browserIcon.png in Resources */,
|
||||
CDAB98A11AEAFAFA00C75B4B /* authorizationIcon.png in Resources */,
|
||||
CD001B391AB903040089014A /* logoApple.png in Resources */,
|
||||
CDF08CEF1ACA677B009B3423 /* launchIcon.png in Resources */,
|
||||
CD7B9FA41ACBCFAD00DF3C71 /* spotlightIcon.png in Resources */,
|
||||
CD7B9FA81ACCAE5E00DF3C71 /* stopScanOver.png in Resources */,
|
||||
CDA81D701A95B4E9009790E2 /* stopScan.png in Resources */,
|
||||
CDF08CF01ACA677B009B3423 /* kernelIcon.png in Resources */,
|
||||
CDF08CD01AC4C6E8009B3423 /* settingsBG.png in Resources */,
|
||||
CD0219551AD34E4C005148A2 /* kkIcon.png in Resources */,
|
||||
CD0219591AD37748005148A2 /* unsigned2.png in Resources */,
|
||||
CDA81D5C1A95B4B4009790E2 /* MainMenu.xib in Resources */,
|
||||
CD7B9F4D1ACB959200DF3C71 /* logoAppleOver.png in Resources */,
|
||||
CD0219581AD37748005148A2 /* signed2.png in Resources */,
|
||||
CDA81DCB1A9960A3009790E2 /* virusTotal.png in Resources */,
|
||||
CDA5F6C61B16E8D4003CE340 /* lockIcon.png in Resources */,
|
||||
CDA81DD41A9970A0009790E2 /* unsigned.png in Resources */,
|
||||
CD7B9FA71ACCAE5E00DF3C71 /* startScanOver.png in Resources */,
|
||||
CD001B371AB903040089014A /* kkText.png in Resources */,
|
||||
CDF08CC11AC3E8B0009B3423 /* showOver.png in Resources */,
|
||||
CD4D54241B2D082300008030 /* DylibInfoWindow.xib in Resources */,
|
||||
CDA81DCC1A9960A3009790E2 /* virusTotalBG.png in Resources */,
|
||||
CD001B381AB903040089014A /* logo.png in Resources */,
|
||||
CDA81D6D1A95B4E9009790E2 /* scanIcon.png in Resources */,
|
||||
CDF08CCF1AC4C6E8009B3423 /* settingsOver.png in Resources */,
|
||||
CDAB98A31AEB413C00C75B4B /* dylibIcon.png in Resources */,
|
||||
CDF08CC31AC3E98D009B3423 /* infoOver.png in Resources */,
|
||||
CDF08CF41ACA6864009B3423 /* loginIcon.png in Resources */,
|
||||
CD3F4D161AF89066002A2647 /* TreeView.xib in Resources */,
|
||||
CD0219501AD34D8B005148A2 /* PrefsWindow.xib in Resources */,
|
||||
CDA81D6C1A95B4E9009790E2 /* showBG.png in Resources */,
|
||||
CD3F4CFF1AF72BC4002A2647 /* TaskInfoWindow.xib in Resources */,
|
||||
CDA81D6A1A95B4E9009790E2 /* mainIcon.png in Resources */,
|
||||
CDA81D711A95B4E9009790E2 /* stopScanBG.png in Resources */,
|
||||
CDF08CBF1AC3DE25009B3423 /* logoAppleBG.png in Resources */,
|
||||
CDF08CE21AC88E0F009B3423 /* VTInfoWindow.xib in Resources */,
|
||||
CD4D53D21B23ED4300008030 /* listeningIcon.png in Resources */,
|
||||
CDA81D6F1A95B4E9009790E2 /* startScanBG.png in Resources */,
|
||||
CDA5F6C11B16E1D6003CE340 /* RequestRootWindow.xib in Resources */,
|
||||
CDA81D721A95B4E9009790E2 /* virus.png in Resources */,
|
||||
CDA81DC91A9960A3009790E2 /* info.png in Resources */,
|
||||
CDA81D741A95B4FB009790E2 /* icon.iconset in Resources */,
|
||||
CDA81D6E1A95B4E9009790E2 /* startScan.png in Resources */,
|
||||
CD02194F1AD34D8B005148A2 /* AboutWindow.xib in Resources */,
|
||||
CDA81DCA1A9960A3009790E2 /* infoBG.png in Resources */,
|
||||
CDF08CD11AC4C6E8009B3423 /* settings.png in Resources */,
|
||||
CDA81DD31A9970A0009790E2 /* signed.png in Resources */,
|
||||
CDA81E661AA020FD009790E2 /* FileInfoWindow.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CDA5F6AB1B16D805003CE340 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
1D21BC47172AF43D009D1CFD /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CD3F4CE81AF5CF68002A2647 /* TaskEnumerator.m in Sources */,
|
||||
CD4D54221B2CE6F200008030 /* NSMutableArray+QueueAdditions.m in Sources */,
|
||||
CDA5F6C41B16E20E003CE340 /* RequestRootWindowController.m in Sources */,
|
||||
CDD2483B1AF5CC4D00232422 /* Task.m in Sources */,
|
||||
CD83887F1AACCEDF000EB098 /* VirusTotal.m in Sources */,
|
||||
CDF08CDF1AC886F2009B3423 /* VTInfoWindowController.m in Sources */,
|
||||
CD3F4CEB1AF6D948002A2647 /* OrderedDictionary.m in Sources */,
|
||||
CD0219611AD39A83005148A2 /* ResultsWindowController.m in Sources */,
|
||||
CD4D541F1B2CE6C400008030 /* Queue.m in Sources */,
|
||||
CD6E54FF1B1162B5007953AB /* ItemView.m in Sources */,
|
||||
CDA81DEE1A99B5F8009790E2 /* Filter.m in Sources */,
|
||||
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 */,
|
||||
CD3F4CFA1AF71B58002A2647 /* Binary.m in Sources */,
|
||||
CD3F4CFC1AF71B58002A2647 /* File.m in Sources */,
|
||||
CDA81D5E1A95B4B4009790E2 /* main.m in Sources */,
|
||||
CD7B9F501ACB9A8400DF3C71 /* Exception.m in Sources */,
|
||||
CDD248341AF5947300232422 /* TAAdaptiveSpaceItem.m in Sources */,
|
||||
CD0219531AD34D9A005148A2 /* AboutWindowController.m in Sources */,
|
||||
CDF08CC61AC46E75009B3423 /* VTButton.m in Sources */,
|
||||
CD3F4CFB1AF71B58002A2647 /* Connection.m in Sources */,
|
||||
CDD248351AF5947300232422 /* TAAdaptiveSpaceItemView.m in Sources */,
|
||||
CDA81D531A95B492009790E2 /* Utilities.m in Sources */,
|
||||
CD7B9FAB1AD08FA100DF3C71 /* KKRow.m in Sources */,
|
||||
CD3F4CFD1AF71B58002A2647 /* ItemBase.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CDA5F6A91B16D805003CE340 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CDA5F6B61B16D805003CE340 /* main.m in Sources */,
|
||||
CDA5F6B41B16D805003CE340 /* remoteTaskService.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
CDA5F6B81B16D805003CE340 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = CDA5F6AC1B16D805003CE340 /* remoteTaskService */;
|
||||
targetProxy = CDA5F6B71B16D805003CE340 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
CDA81D541A95B4B4009790E2 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
CDA81D551A95B4B4009790E2 /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDA81D561A95B4B4009790E2 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
CDA81D571A95B4B4009790E2 /* en */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1D21BC66172AF43D009D1CFD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1D21BC67172AF43D009D1CFD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1D21BC69172AF43D009D1CFD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "TaskExplorer-Prefix.pch";
|
||||
INFOPLIST_FILE = "TaskExplorer-Info.plist";
|
||||
PRODUCT_NAME = TaskExplorer;
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1D21BC6A172AF43D009D1CFD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "TaskExplorer-Prefix.pch";
|
||||
INFOPLIST_FILE = "TaskExplorer-Info.plist";
|
||||
PRODUCT_NAME = TaskExplorer;
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CDA5F6BB1B16D805003CE340 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = remoteTaskService/Info.plist;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CDA5F6BC1B16D805003CE340 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = remoteTaskService/Info.plist;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1D21BC46172AF43D009D1CFD /* Build configuration list for PBXProject "TaskExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1D21BC66172AF43D009D1CFD /* Debug */,
|
||||
1D21BC67172AF43D009D1CFD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
1D21BC68172AF43D009D1CFD /* Build configuration list for PBXNativeTarget "TaskExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1D21BC69172AF43D009D1CFD /* Debug */,
|
||||
1D21BC6A172AF43D009D1CFD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CDA5F6BD1B16D805003CE340 /* Build configuration list for PBXNativeTarget "remoteTaskService" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CDA5F6BB1B16D805003CE340 /* Debug */,
|
||||
CDA5F6BC1B16D805003CE340 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 1D21BC43172AF43D009D1CFD /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:../TaskEnumerator.h">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:../TaskEnumerator.m">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "self:TaskExplorer.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>1ECDBF86-1DFC-4002-A5BE-41FC31ACB68B</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>project</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</key>
|
||||
<string>https://bitbucket.org/objective-see/knockknock.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>KnockKnock.xcodeproj/project.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>https://bitbucket.org/objective-see/knockknock.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>KnockKnock</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>FE4103FE-6F26-4639-8C9F-D8D32C76D6A9</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>TaskExplorer</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</key>
|
||||
<string>https://bitbucket.org/objective-see/knockknock.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>TaskExplorer.xcodeproj</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>https://bitbucket.org/objective-see/knockknock.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>A9FFC1B124E25027A0E10FB456DBA9E2803FAE9D</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>TaskExplorer</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,241 @@
|
||||
<?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 = "Task.m"
|
||||
timestampString = "455934659.769831"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "509"
|
||||
endingLineNumber = "509"
|
||||
landmarkName = "-enumerateNetworking:"
|
||||
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 = "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"
|
||||
landmarkName = "-enumerateDylibs:allDylibs:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AppDelegate.m"
|
||||
timestampString = "455870793.890474"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "406"
|
||||
endingLineNumber = "406"
|
||||
landmarkName = "-reloadBottomPane:itemView:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AppDelegate.m"
|
||||
timestampString = "455871607.2373"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "413"
|
||||
endingLineNumber = "413"
|
||||
landmarkName = "-reloadBottomPane:itemView:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AppDelegate.m"
|
||||
timestampString = "455913381.256009"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "1354"
|
||||
endingLineNumber = "1354"
|
||||
landmarkName = "-selectBottomPaneContent:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AppDelegate.m"
|
||||
timestampString = "455927034.93809"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "1375"
|
||||
endingLineNumber = "1375"
|
||||
landmarkName = "-selectBottomPaneContent:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "AppDelegate.m"
|
||||
timestampString = "455927034.93809"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "1378"
|
||||
endingLineNumber = "1378"
|
||||
landmarkName = "-selectBottomPaneContent:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "kkRowCell.m"
|
||||
timestampString = "455918972.792996"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "15"
|
||||
endingLineNumber = "15"
|
||||
landmarkName = "-drawRect:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Task.m"
|
||||
timestampString = "455933492.971073"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "95"
|
||||
endingLineNumber = "95"
|
||||
landmarkName = "-initWithPID:andPath:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Queue.m"
|
||||
timestampString = "455934198.853999"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "94"
|
||||
endingLineNumber = "94"
|
||||
landmarkName = "-enqueue:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "TaskTableController.m"
|
||||
timestampString = "455935914.851075"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "985"
|
||||
endingLineNumber = "985"
|
||||
landmarkName = "-showInfo:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "InfoWindowController.m"
|
||||
timestampString = "455936252.706327"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "40"
|
||||
endingLineNumber = "40"
|
||||
landmarkName = "-initWithItem:"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "InfoWindowController.m"
|
||||
timestampString = "455936279.739463"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "95"
|
||||
endingLineNumber = "95"
|
||||
landmarkName = "-configure"
|
||||
landmarkType = "5">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0620"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1D21BC4A172AF43D009D1CFD"
|
||||
BuildableName = "TaskExplorer.app"
|
||||
BlueprintName = "TaskExplorer"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1D21BC4A172AF43D009D1CFD"
|
||||
BuildableName = "TaskExplorer.app"
|
||||
BlueprintName = "TaskExplorer"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1D21BC4A172AF43D009D1CFD"
|
||||
BuildableName = "TaskExplorer.app"
|
||||
BlueprintName = "TaskExplorer"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0630"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "CDA5F6AC1B16D805003CE340"
|
||||
BuildableName = "remoteTaskService.xpc"
|
||||
BlueprintName = "remoteTaskService"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1D21BC4A172AF43D009D1CFD"
|
||||
BuildableName = "TaskExplorer.app"
|
||||
BlueprintName = "TaskExplorer"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1D21BC4A172AF43D009D1CFD"
|
||||
BuildableName = "TaskExplorer.app"
|
||||
BlueprintName = "TaskExplorer"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "CDA5F6AC1B16D805003CE340"
|
||||
BuildableName = "remoteTaskService.xpc"
|
||||
BlueprintName = "remoteTaskService"
|
||||
ReferencedContainer = "container:TaskExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>TaskExplorer.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>remoteTaskService.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>1D21BC4A172AF43D009D1CFD</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>CDA5F6AC1B16D805003CE340</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// ItemTableController.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 2/18/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Task.h"
|
||||
#import "InfoWindowController.h"
|
||||
#import "VTInfoWindowController.h"
|
||||
#import "3rdParty/OrderedDictionary.h"
|
||||
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface TaskTableController : NSViewController <NSTableViewDataSource, NSTableViewDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//tasks
|
||||
// ->updated by task enumerator
|
||||
//@property(nonatomic, retain)OrderedDictionary* tasks;
|
||||
|
||||
@property(nonatomic, retain)NSMutableArray* tableItems;
|
||||
|
||||
//category table view
|
||||
@property(weak) IBOutlet NSTableView *itemView;
|
||||
|
||||
//info window
|
||||
@property(retain, nonatomic)InfoWindowController* infoWindowController;
|
||||
|
||||
//preferences window controller
|
||||
@property (nonatomic, retain)VTInfoWindowController* vtWindowController;
|
||||
|
||||
//currently selected row
|
||||
// ->can help determine if newly selected row is really new
|
||||
@property NSUInteger selectedRow;
|
||||
|
||||
//flag to differentiate between top/bottom view
|
||||
@property BOOL isBottomPane;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//reload table
|
||||
-(void)reloadTable;
|
||||
|
||||
//custom reload
|
||||
// ->ensures selected row remains selected
|
||||
-(void)refresh;
|
||||
|
||||
//grab a task at a row
|
||||
-(Task*)taskForRow:(id)sender;
|
||||
|
||||
//button handler
|
||||
// ->show item in finder
|
||||
- (IBAction)showInFinder:(id)sender;
|
||||
|
||||
//button handler
|
||||
// ->show info window
|
||||
- (IBAction)showInfo:(id)sender;
|
||||
|
||||
//button handler
|
||||
// ->show virus total info window
|
||||
-(void)showVTInfo:(NSView*)button;
|
||||
|
||||
//scroll back up to top of table
|
||||
-(void)scrollToTop;
|
||||
|
||||
//helper function
|
||||
// ->get items array (either all or just unknown)
|
||||
-(NSArray*)getTableItems;
|
||||
|
||||
//determine if instance is rendering top pane
|
||||
// ->for now, just looks at 'tableItems' iVar
|
||||
-(BOOL)isTopPane;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* 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
|
||||
@@ -0,0 +1,305 @@
|
||||
/*-
|
||||
* 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
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="AboutWindowController">
|
||||
<connections>
|
||||
<outlet property="versionLabel" destination="OSm-xS-Dmd" id="luW-4O-fYe"/>
|
||||
<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" 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="1440" height="877"/>
|
||||
<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="12" width="110" height="106"/>
|
||||
<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="141" y="63" width="180" height="50"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkText" id="Ws8-bD-j2R"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||
<rect key="frame" x="141" y="51" width="182" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="version:" id="bBK-v0-ypq">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
||||
<rect key="frame" x="280" y="11" width="128" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="more info" 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"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="moreInfo:" target="-2" id="YYW-1b-uJY"/>
|
||||
</connections>
|
||||
</button>
|
||||
</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>
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="InfoWindowController">
|
||||
<connections>
|
||||
<outlet property="arguments" destination="1eL-b7-I94" id="6GM-Ne-rgf"/>
|
||||
<outlet property="date" destination="Wbv-SK-w53" id="Li5-qD-Hxq"/>
|
||||
<outlet property="hashes" destination="GQc-va-MLN" id="ta6-6g-dzh"/>
|
||||
<outlet property="icon" destination="l8H-S3-g8O" id="P7o-8z-MjY"/>
|
||||
<outlet property="name" destination="NA2-2e-4hN" id="0Lg-xP-m03"/>
|
||||
<outlet property="path" destination="dY9-WD-WAf" id="7Lg-cs-t0f"/>
|
||||
<outlet property="sign" destination="5Rx-Vm-7gm" id="3g2-Ay-zQ4"/>
|
||||
<outlet property="size" destination="hLU-fi-qXH" id="wZf-h4-BKf"/>
|
||||
<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 title="Task File Information" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="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="646" height="220"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="-1" width="646" height="220"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NA2-2e-4hN">
|
||||
<rect key="frame" x="73" y="186" width="553" height="29"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Item Name" id="pYD-IR-Vtv">
|
||||
<font key="font" size="20" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dY9-WD-WAf">
|
||||
<rect key="frame" x="75" y="151" width="553" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" title="Item Path" id="MfU-Jb-agl">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GMp-1g-TFI">
|
||||
<rect key="frame" x="8" y="84" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="hash:" id="fYa-Av-reX">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GQc-va-MLN">
|
||||
<rect key="frame" x="75" y="84" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item hash" id="yYo-KQ-DMm">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hLU-fi-qXH">
|
||||
<rect key="frame" x="75" y="64" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item size" id="XJ7-Go-bkG">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wbv-SK-w53">
|
||||
<rect key="frame" x="75" y="43" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item creation/modified" id="hR8-Wz-esN">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Rx-Vm-7gm">
|
||||
<rect key="frame" x="75" y="6" width="554" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="signing status" id="00d-h4-SPW">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DFa-vc-wFY">
|
||||
<rect key="frame" x="8" y="64" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="size:" id="iBS-9J-ok9">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tM6-Nq-1Rh">
|
||||
<rect key="frame" x="8" y="43" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="time:" id="U3V-A7-jO8">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hel-J4-4Qt">
|
||||
<rect key="frame" x="8" y="23" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="sign:" id="ezp-TW-Xky">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<box verticalHuggingPriority="750" fixedFrame="YES" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Oh7-Ag-bHc">
|
||||
<rect key="frame" x="22" y="141" width="604" height="5"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l8H-S3-g8O">
|
||||
<rect key="frame" x="13" y="162" width="48" height="48"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="bug" id="w3z-uu-XKS"/>
|
||||
</imageView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uJq-Bw-lDQ">
|
||||
<rect key="frame" x="552" y="9" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="RwO-yA-Xwk">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="closeWindow:" target="-2" id="SSo-9s-xQz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="i1i-Er-lQW">
|
||||
<rect key="frame" x="8" y="110" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="args:" id="fZY-li-gtz">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1eL-b7-I94">
|
||||
<rect key="frame" x="74" y="110" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item args" id="qTP-D2-QN6">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="430" y="250"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bug" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="InfoWindowController">
|
||||
<connections>
|
||||
<outlet property="date" destination="Wbv-SK-w53" id="Li5-qD-Hxq"/>
|
||||
<outlet property="hashes" destination="GQc-va-MLN" id="ta6-6g-dzh"/>
|
||||
<outlet property="icon" destination="l8H-S3-g8O" id="P7o-8z-MjY"/>
|
||||
<outlet property="name" destination="NA2-2e-4hN" id="0Lg-xP-m03"/>
|
||||
<outlet property="path" destination="dY9-WD-WAf" id="7Lg-cs-t0f"/>
|
||||
<outlet property="plist" destination="vm8-PU-Bu0" id="9mC-ha-tfK"/>
|
||||
<outlet property="sign" destination="5Rx-Vm-7gm" id="3g2-Ay-zQ4"/>
|
||||
<outlet property="size" destination="hLU-fi-qXH" id="wZf-h4-BKf"/>
|
||||
<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 title="File Information" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="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="646" height="260"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="646" height="260"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NA2-2e-4hN">
|
||||
<rect key="frame" x="73" y="226" width="553" height="29"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Item Name" id="pYD-IR-Vtv">
|
||||
<font key="font" size="20" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dY9-WD-WAf">
|
||||
<rect key="frame" x="75" y="191" width="553" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" title="Item Path" id="MfU-Jb-agl">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GMp-1g-TFI">
|
||||
<rect key="frame" x="8" y="149" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="hash:" id="fYa-Av-reX">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GQc-va-MLN">
|
||||
<rect key="frame" x="75" y="149" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item hash" id="yYo-KQ-DMm">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hLU-fi-qXH">
|
||||
<rect key="frame" x="75" y="129" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item size" id="XJ7-Go-bkG">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wbv-SK-w53">
|
||||
<rect key="frame" x="75" y="108" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item creation/modified" id="hR8-Wz-esN">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Rx-Vm-7gm">
|
||||
<rect key="frame" x="75" y="51" width="554" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="signing status" id="00d-h4-SPW">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vm8-PU-Bu0">
|
||||
<rect key="frame" x="76" y="88" width="554" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="plist" id="23w-N2-C5Z">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DFa-vc-wFY">
|
||||
<rect key="frame" x="8" y="129" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="size:" id="iBS-9J-ok9">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tM6-Nq-1Rh">
|
||||
<rect key="frame" x="8" y="108" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="time:" id="U3V-A7-jO8">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hel-J4-4Qt">
|
||||
<rect key="frame" x="8" y="68" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="sign:" id="ezp-TW-Xky">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fAH-dm-SJe">
|
||||
<rect key="frame" x="8" y="88" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="list:" id="oqF-UL-ydq">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<box verticalHuggingPriority="750" fixedFrame="YES" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Oh7-Ag-bHc">
|
||||
<rect key="frame" x="22" y="181" width="604" height="5"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l8H-S3-g8O">
|
||||
<rect key="frame" x="13" y="202" width="48" height="48"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="bug" id="w3z-uu-XKS"/>
|
||||
</imageView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uJq-Bw-lDQ">
|
||||
<rect key="frame" x="552" y="12" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="RwO-yA-Xwk">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="closeWindow:" target="-2" id="SSo-9s-xQz"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="430" y="270"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bug" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,461 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<development version="5000" identifier="xcode"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="TaskTableController">
|
||||
<connections>
|
||||
<outlet property="itemView" destination="fb0-7X-Sm6" id="sWQ-Jv-UTG"/>
|
||||
<outlet property="view" destination="T1P-b9-TzF" id="pja-1o-aue"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<view id="T1P-b9-TzF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1306" height="294"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView ambiguous="YES" misplaced="YES" autohidesScrollers="YES" horizontalLineScroll="42" horizontalPageScroll="10" verticalLineScroll="42" verticalPageScroll="10" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="QDh-31-mfl">
|
||||
<rect key="frame" x="-3" y="20" width="1300" height="274"/>
|
||||
<clipView key="contentView" ambiguous="YES" misplaced="YES" drawsBackground="NO" id="t1U-m3-CeJ">
|
||||
<rect key="frame" x="1" y="1" width="1204" height="437"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="40" rowSizeStyle="automatic" viewBased="YES" id="fb0-7X-Sm6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1298" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="MainCell" editable="NO" width="1295" minWidth="40" maxWidth="2000" id="sUM-Cl-ag5">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="XYM-bm-ie0">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="TaskCell" id="sdY-t5-tbW" customClass="kkRowCell">
|
||||
<rect key="frame" x="1" y="1" width="1295" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cG6-PF-La2">
|
||||
<rect key="frame" x="5" y="9" width="26" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="9B3-Dt-CCW"/>
|
||||
<constraint firstAttribute="width" constant="20" id="XhL-Yo-1xA"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="0cD-OF-kgr"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="M2y-fe-Zb7">
|
||||
<rect key="frame" x="33" y="23" width="11" height="11"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="11" id="RPq-FT-sWw"/>
|
||||
<constraint firstAttribute="height" constant="11" id="erK-aR-d7L"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="unknown" id="2ru-B9-6b1"/>
|
||||
</imageView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ryD-lC-8IR">
|
||||
<rect key="frame" x="46" y="20" width="225" height="19"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Task Name" id="fEY-SM-ufc">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show in finder" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="107" translatesAutoresizingMaskIntoConstraints="NO" id="Y4J-KD-8iy">
|
||||
<rect key="frame" x="1263" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="15" id="Nro-9M-6Xg"/>
|
||||
<constraint firstAttribute="width" constant="15" id="rEk-W0-lvD"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="show" imagePosition="only" alignment="center" alternateImage="showBG" state="on" imageScaling="proportionallyDown" inset="2" id="Xle-cK-MOQ">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInFinder:" target="-2" id="7nB-GA-ZiB"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="108" translatesAutoresizingMaskIntoConstraints="NO" id="gpF-bM-EQR">
|
||||
<rect key="frame" x="1259" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="25" id="F3C-cT-yKu"/>
|
||||
<constraint firstAttribute="height" constant="12" id="k1Q-YJ-vSj"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="show" id="B5F-50-OCm">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="miW-QO-gna">
|
||||
<rect key="frame" x="31" y="2" width="1093" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="item path" id="7xA-XP-LK6">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show virustotal info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="103" translatesAutoresizingMaskIntoConstraints="NO" id="Dtg-ac-EVZ" customClass="VTButton">
|
||||
<rect key="frame" x="1155" y="17" width="49" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="29" id="0ZR-hE-oUJ"/>
|
||||
<constraint firstAttribute="width" constant="49" id="i1N-eU-GWT"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" title="▪ ▪ ▪" bezelStyle="regularSquare" imagePosition="overlaps" alignment="center" enabled="NO" refusesFirstResponder="YES" state="on" imageScaling="proportionallyDown" inset="2" id="WMp-cU-Uct">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" size="8" name="Menlo-Bold"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="104" translatesAutoresizingMaskIntoConstraints="NO" id="aPz-9H-xyy">
|
||||
<rect key="frame" x="1148" y="4" width="65" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="Mn9-1j-NeM"/>
|
||||
<constraint firstAttribute="height" constant="12" id="pgg-Gc-7aV"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="virustotal" id="WbN-3u-Ihr">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show file info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="105" translatesAutoresizingMaskIntoConstraints="NO" id="eBe-7K-OiH">
|
||||
<rect key="frame" x="1226" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="15" id="3YM-AG-8um"/>
|
||||
<constraint firstAttribute="width" constant="15" id="iZ2-6y-WKB"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="info" imagePosition="only" alignment="center" alternateImage="infoBG" state="on" imageScaling="proportionallyDown" inset="2" id="TCH-R3-DzT">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInfo:" target="-2" id="1Jl-sO-iDL"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="106" translatesAutoresizingMaskIntoConstraints="NO" id="MqO-G8-w9L">
|
||||
<rect key="frame" x="1220" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="xID-bs-CI7"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="info" id="ljw-jb-ljM">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="102" translatesAutoresizingMaskIntoConstraints="NO" id="Nky-Qb-S7Z">
|
||||
<rect key="frame" x="295" y="20" width="79" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="ecq-WO-Xtq"/>
|
||||
<constraint firstAttribute="width" constant="75" id="qxm-8e-ma2"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="pid" id="BVj-TR-eR2">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.49295236009999999" alpha="0.84999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Nky-Qb-S7Z" firstAttribute="leading" secondItem="ryD-lC-8IR" secondAttribute="trailing" constant="8" id="7Og-f1-rQH"/>
|
||||
<constraint firstItem="cG6-PF-La2" firstAttribute="leading" secondItem="sdY-t5-tbW" secondAttribute="leading" constant="5" id="7ms-dD-as0"/>
|
||||
<constraint firstItem="eBe-7K-OiH" firstAttribute="leading" secondItem="Dtg-ac-EVZ" secondAttribute="trailing" constant="18" id="Dd1-7F-oi4"/>
|
||||
<constraint firstItem="miW-QO-gna" firstAttribute="leading" secondItem="cG6-PF-La2" secondAttribute="trailing" constant="8" id="J3y-8b-F3q"/>
|
||||
<constraint firstItem="MqO-G8-w9L" firstAttribute="leading" secondItem="aPz-9H-xyy" secondAttribute="trailing" constant="9" id="Rfl-hR-rxD"/>
|
||||
<constraint firstItem="Y4J-KD-8iy" firstAttribute="leading" secondItem="eBe-7K-OiH" secondAttribute="trailing" constant="20" id="TAx-KS-R7a"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Y4J-KD-8iy" secondAttribute="trailing" constant="10" id="iMf-M4-bv0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="gpF-bM-EQR" secondAttribute="trailing" constant="4" id="myW-Ol-OIp"/>
|
||||
<constraint firstItem="Dtg-ac-EVZ" firstAttribute="leading" secondItem="miW-QO-gna" secondAttribute="trailing" constant="8" id="rxd-Fp-O3o"/>
|
||||
<constraint firstItem="gpF-bM-EQR" firstAttribute="leading" secondItem="MqO-G8-w9L" secondAttribute="trailing" constant="10" id="tLu-Y9-F4d"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="cG6-PF-La2" id="v1M-Zn-U5X"/>
|
||||
<outlet property="textField" destination="ryD-lC-8IR" id="ias-DX-8EL"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="DylibCell" id="AMp-Sl-IUz" customClass="kkRowCell">
|
||||
<rect key="frame" x="1" y="1" width="1295" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="bgG-DR-RMT">
|
||||
<rect key="frame" x="13" y="23" width="11" height="11"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="11" id="SRW-ea-jvI"/>
|
||||
<constraint firstAttribute="height" constant="11" id="boT-hW-24p"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="unknown" id="tuX-G4-1az"/>
|
||||
</imageView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kE0-h4-XoU">
|
||||
<rect key="frame" x="26" y="20" width="1000" height="19"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Dylib Name" id="BA3-2m-roK">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show in finder" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="107" translatesAutoresizingMaskIntoConstraints="NO" id="bau-Td-7ST">
|
||||
<rect key="frame" x="1263" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="15" id="DPj-gb-dIB"/>
|
||||
<constraint firstAttribute="width" constant="15" id="oNg-zE-nJv"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="show" imagePosition="only" alignment="center" alternateImage="showBG" state="on" imageScaling="proportionallyDown" inset="2" id="PQ1-ho-YTb">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInFinder:" target="-2" id="iqe-Av-pL0"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="108" translatesAutoresizingMaskIntoConstraints="NO" id="DCt-ke-ecy">
|
||||
<rect key="frame" x="1259" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="25" id="SHJ-Pm-wjU"/>
|
||||
<constraint firstAttribute="height" constant="12" id="dsu-l8-dLe"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="show" id="SbY-jh-Hwi">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="s79-UC-kl8">
|
||||
<rect key="frame" x="11" y="2" width="1093" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="item path" id="efL-9x-1ue">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show virustotal info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="103" translatesAutoresizingMaskIntoConstraints="NO" id="FC1-IO-3xs" customClass="VTButton">
|
||||
<rect key="frame" x="1155" y="17" width="49" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="29" id="M7k-0n-E2g"/>
|
||||
<constraint firstAttribute="width" constant="49" id="e6T-3k-tEd"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" title="▪ ▪ ▪" bezelStyle="regularSquare" imagePosition="overlaps" alignment="center" enabled="NO" refusesFirstResponder="YES" state="on" imageScaling="proportionallyDown" inset="2" id="nJM-0x-661">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" size="8" name="Menlo-Bold"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="104" translatesAutoresizingMaskIntoConstraints="NO" id="mKM-Ea-CdX">
|
||||
<rect key="frame" x="1148" y="4" width="65" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="L1s-UF-cDG"/>
|
||||
<constraint firstAttribute="width" constant="61" id="Yai-jE-Ag4"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="virustotal" id="6Bu-O1-DgW">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show file info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="105" translatesAutoresizingMaskIntoConstraints="NO" id="Nvb-5R-deG">
|
||||
<rect key="frame" x="1226" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="15" id="CAs-CP-Cfn"/>
|
||||
<constraint firstAttribute="height" constant="15" id="Nyk-SH-8p6"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="info" imagePosition="only" alignment="center" alternateImage="infoBG" state="on" imageScaling="proportionallyDown" inset="2" id="7oW-jB-dbZ">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInfo:" target="-2" id="6cF-vs-qfi"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="106" translatesAutoresizingMaskIntoConstraints="NO" id="d6d-We-r4h">
|
||||
<rect key="frame" x="1220" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="x00-pi-4zx"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="info" id="mzh-KR-osn">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Nvb-5R-deG" firstAttribute="leading" secondItem="FC1-IO-3xs" secondAttribute="trailing" constant="18" id="B3b-K8-iKu"/>
|
||||
<constraint firstItem="d6d-We-r4h" firstAttribute="leading" secondItem="mKM-Ea-CdX" secondAttribute="trailing" constant="9" id="Geb-Pj-PW9"/>
|
||||
<constraint firstItem="FC1-IO-3xs" firstAttribute="leading" secondItem="s79-UC-kl8" secondAttribute="trailing" constant="8" id="Rb2-Pf-nT9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bau-Td-7ST" secondAttribute="trailing" constant="10" id="YV7-dd-VnF"/>
|
||||
<constraint firstItem="s79-UC-kl8" firstAttribute="leading" secondItem="AMp-Sl-IUz" secondAttribute="leading" constant="13" id="jUo-Cu-hm3"/>
|
||||
<constraint firstItem="DCt-ke-ecy" firstAttribute="leading" secondItem="d6d-We-r4h" secondAttribute="trailing" constant="10" id="mQm-zs-mcQ"/>
|
||||
<constraint firstItem="bau-Td-7ST" firstAttribute="leading" secondItem="Nvb-5R-deG" secondAttribute="trailing" constant="20" id="p6O-3z-4Kx"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DCt-ke-ecy" secondAttribute="trailing" constant="4" id="paK-cH-SPa"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="kE0-h4-XoU" id="ngK-iU-Wtk"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="FileCell" id="zC6-7V-PKY" customClass="kkRowCell">
|
||||
<rect key="frame" x="1" y="1" width="1295" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LkX-uS-hKH">
|
||||
<rect key="frame" x="11" y="20" width="1000" height="19"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="File Name" id="fg8-Ix-mHR">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show in finder" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="107" translatesAutoresizingMaskIntoConstraints="NO" id="yDq-tI-YQJ">
|
||||
<rect key="frame" x="1263" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="15" id="weN-ut-xDd"/>
|
||||
<constraint firstAttribute="width" constant="15" id="zwd-5o-XMf"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="show" imagePosition="only" alignment="center" alternateImage="showBG" state="on" imageScaling="proportionallyDown" inset="2" id="i29-A9-Sv1">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInFinder:" target="-2" id="wBh-1s-Jgt"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="108" translatesAutoresizingMaskIntoConstraints="NO" id="27e-wh-BEp">
|
||||
<rect key="frame" x="1259" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="M8u-tp-mKC"/>
|
||||
<constraint firstAttribute="width" constant="25" id="nMd-Wy-wvB"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="show" id="VHL-k9-JxN">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="gwn-Wz-bDY">
|
||||
<rect key="frame" x="11" y="2" width="1093" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="item path" id="1WZ-C2-VvW">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show file info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="105" translatesAutoresizingMaskIntoConstraints="NO" id="8Vk-bl-kjr">
|
||||
<rect key="frame" x="1226" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="15" id="FLn-RP-zYu"/>
|
||||
<constraint firstAttribute="height" constant="15" id="dM6-uC-lks"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="info" imagePosition="only" alignment="center" alternateImage="infoBG" state="on" imageScaling="proportionallyDown" inset="2" id="UDk-8x-xVs">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showInfo:" target="-2" id="eaC-mP-eoj"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="106" translatesAutoresizingMaskIntoConstraints="NO" id="tIY-Ij-plN">
|
||||
<rect key="frame" x="1220" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="VXj-Yu-ucw"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="info" id="Jha-96-Egc">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="27e-wh-BEp" secondAttribute="trailing" constant="4" id="Ft1-LY-Scf"/>
|
||||
<constraint firstItem="gwn-Wz-bDY" firstAttribute="leading" secondItem="zC6-7V-PKY" secondAttribute="leading" constant="13" id="GEK-N3-wIC"/>
|
||||
<constraint firstItem="yDq-tI-YQJ" firstAttribute="leading" secondItem="8Vk-bl-kjr" secondAttribute="trailing" constant="20" id="aV6-Hu-Y5b"/>
|
||||
<constraint firstAttribute="trailing" secondItem="yDq-tI-YQJ" secondAttribute="trailing" constant="10" id="fqn-su-UYW"/>
|
||||
<constraint firstItem="27e-wh-BEp" firstAttribute="leading" secondItem="tIY-Ij-plN" secondAttribute="trailing" constant="10" id="w6k-vz-Q6U"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="LkX-uS-hKH" id="XKi-AB-R3o"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<tableCellView identifier="NetworkCell" id="vkh-K9-CiP" customClass="kkRowCell">
|
||||
<rect key="frame" x="1" y="1" width="1295" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="n84-aN-dS4">
|
||||
<rect key="frame" x="5" y="9" width="26" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="20" id="S0W-eP-sJY"/>
|
||||
<constraint firstAttribute="height" constant="20" id="beQ-3n-m5v"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="5ar-gc-DMu"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="clK-51-yQN">
|
||||
<rect key="frame" x="31" y="2" width="1093" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="item path" id="DlS-aR-tJt">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="t4A-WM-KWO">
|
||||
<rect key="frame" x="31" y="20" width="1000" height="19"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Network Info" id="Boe-bK-y2E">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="n84-aN-dS4" firstAttribute="leading" secondItem="vkh-K9-CiP" secondAttribute="leading" constant="5" id="iJH-Aa-QGY"/>
|
||||
<constraint firstItem="clK-51-yQN" firstAttribute="leading" secondItem="n84-aN-dS4" secondAttribute="trailing" constant="8" id="zd5-Ae-yYB"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="n84-aN-dS4" id="dGH-6T-93g"/>
|
||||
<outlet property="textField" destination="t4A-WM-KWO" id="gOS-IJ-Hvb"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-2" id="SEP-G5-Rr5"/>
|
||||
<outlet property="delegate" destination="-2" id="iWU-v0-A4g"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" controlSize="mini" horizontal="YES" id="gmJ-1g-Tah">
|
||||
<rect key="frame" x="1" y="298" width="480" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" controlSize="mini" horizontal="NO" id="cwi-rA-cqP">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="QDh-31-mfl" firstAttribute="leading" secondItem="T1P-b9-TzF" secondAttribute="leading" id="XxZ-TH-o2t"/>
|
||||
<constraint firstAttribute="trailing" secondItem="QDh-31-mfl" secondAttribute="trailing" id="Z3y-5B-K5h"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="638" y="-658"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="14" height="14"/>
|
||||
<image name="info" width="256" height="256"/>
|
||||
<image name="infoBG" width="256" height="256"/>
|
||||
<image name="show" width="256" height="256"/>
|
||||
<image name="showBG" width="256" height="256"/>
|
||||
<image name="unknown" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="PrefsWindowController">
|
||||
<connections>
|
||||
<outlet property="disableVTQueries" destination="d54-mZ-jqy" id="gCe-BP-bct"/>
|
||||
<outlet property="disableVTQueriesBtn" destination="d54-mZ-jqy" id="Xx6-E1-yv0"/>
|
||||
<outlet property="okButton" destination="HZZ-Es-mpy" id="GKU-Jc-ENB"/>
|
||||
<outlet property="saveOutput" destination="6la-v6-zBD" id="iif-cF-w6y"/>
|
||||
<outlet property="saveOutputBtn" destination="6la-v6-zBD" id="m3d-J9-MZg"/>
|
||||
<outlet property="showTrustedItems" destination="4xV-kQ-iaT" id="3wm-5q-ib3"/>
|
||||
<outlet property="showTrustedItemsBtn" destination="4xV-kQ-iaT" id="aEg-d4-Orl"/>
|
||||
<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 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="1440" height="877"/>
|
||||
<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="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="189" height="18"/>
|
||||
<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"/>
|
||||
<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="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">
|
||||
<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"/>
|
||||
<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"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="closeWindow:" target="-2" id="eFa-k0-zTM"/>
|
||||
</connections>
|
||||
</button>
|
||||
</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="settings" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="RequestRootWindowController">
|
||||
<connections>
|
||||
<outlet property="statusMsg" destination="OSm-xS-Dmd" id="mh0-TD-SLI"/>
|
||||
<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" 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="148"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="-2" width="422" height="148"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Eaf-yA-bbe">
|
||||
<rect key="frame" x="141" y="88" width="180" height="50"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkText" id="Ws8-bD-j2R"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||
<rect key="frame" x="141" y="49" width="271" height="41"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="please authenticate TaskExplorer" id="bBK-v0-ypq">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sNs-lK-0YZ">
|
||||
<rect key="frame" x="190" y="13" width="128" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="authenticate" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="9IW-5U-ukA">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="authenticate:" target="-2" id="not-EQ-mpp"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
||||
<rect key="frame" x="328" y="13" width="80" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="cancel" 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"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="close:" target="-2" id="Ege-pO-ZGg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
|
||||
<rect key="frame" x="11" y="22" width="110" height="106"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="lockIcon" id="xKf-GK-m0k"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="318" y="259"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="kkText" width="426.48001098632812" height="85.919998168945312"/>
|
||||
<image name="lockIcon" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="ResultsWindowController">
|
||||
<connections>
|
||||
<outlet property="detailsLabel" destination="OSm-xS-Dmd" id="fAP-nb-hfk"/>
|
||||
<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" 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="138"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="-1" width="422" height="138"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lEv-Wj-6S5">
|
||||
<rect key="frame" x="10" y="4" width="121" height="133"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkIcon" id="xKf-GK-m0k"/>
|
||||
</imageView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OSm-xS-Dmd">
|
||||
<rect key="frame" x="138" y="45" width="261" height="60"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="results..." id="bBK-v0-ypq">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="h9d-xm-5lM">
|
||||
<rect key="frame" x="138" y="106" width="182" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="scan complete" id="viG-9e-1Nj">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZZ-Es-mpy">
|
||||
<rect key="frame" x="309" y="13" width="94" height="32"/>
|
||||
<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"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="close:" target="-2" id="uMS-EM-Wl2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="318" y="253"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="kkIcon" width="512" height="512"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="InfoWindowController">
|
||||
<connections>
|
||||
<outlet property="arguments" destination="1eL-b7-I94" id="6GM-Ne-rgf"/>
|
||||
<outlet property="date" destination="Wbv-SK-w53" id="Li5-qD-Hxq"/>
|
||||
<outlet property="hashes" destination="GQc-va-MLN" id="ta6-6g-dzh"/>
|
||||
<outlet property="icon" destination="l8H-S3-g8O" id="P7o-8z-MjY"/>
|
||||
<outlet property="name" destination="NA2-2e-4hN" id="0Lg-xP-m03"/>
|
||||
<outlet property="path" destination="dY9-WD-WAf" id="7Lg-cs-t0f"/>
|
||||
<outlet property="sign" destination="5Rx-Vm-7gm" id="3g2-Ay-zQ4"/>
|
||||
<outlet property="size" destination="hLU-fi-qXH" id="wZf-h4-BKf"/>
|
||||
<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 title="Task File Information" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="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="646" height="220"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="-1" width="646" height="220"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NA2-2e-4hN">
|
||||
<rect key="frame" x="73" y="186" width="553" height="29"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" title="Item Name" id="pYD-IR-Vtv">
|
||||
<font key="font" size="20" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dY9-WD-WAf">
|
||||
<rect key="frame" x="75" y="151" width="553" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" title="Item Path" id="MfU-Jb-agl">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GMp-1g-TFI">
|
||||
<rect key="frame" x="8" y="84" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="hash:" id="fYa-Av-reX">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GQc-va-MLN">
|
||||
<rect key="frame" x="75" y="84" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item hash" id="yYo-KQ-DMm">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hLU-fi-qXH">
|
||||
<rect key="frame" x="75" y="64" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item size" id="XJ7-Go-bkG">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wbv-SK-w53">
|
||||
<rect key="frame" x="75" y="43" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item creation/modified" id="hR8-Wz-esN">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Rx-Vm-7gm">
|
||||
<rect key="frame" x="75" y="6" width="554" height="34"/>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="signing status" id="00d-h4-SPW">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DFa-vc-wFY">
|
||||
<rect key="frame" x="8" y="64" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="size:" id="iBS-9J-ok9">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tM6-Nq-1Rh">
|
||||
<rect key="frame" x="8" y="43" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="time:" id="U3V-A7-jO8">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hel-J4-4Qt">
|
||||
<rect key="frame" x="8" y="23" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="sign:" id="ezp-TW-Xky">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<box verticalHuggingPriority="750" fixedFrame="YES" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Oh7-Ag-bHc">
|
||||
<rect key="frame" x="22" y="141" width="604" height="5"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l8H-S3-g8O">
|
||||
<rect key="frame" x="13" y="162" width="48" height="48"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="bug" id="w3z-uu-XKS"/>
|
||||
</imageView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uJq-Bw-lDQ">
|
||||
<rect key="frame" x="552" y="9" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="RwO-yA-Xwk">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="closeWindow:" target="-2" id="SSo-9s-xQz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="i1i-Er-lQW">
|
||||
<rect key="frame" x="8" y="110" width="59" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="args:" id="fZY-li-gtz">
|
||||
<font key="font" size="11" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1eL-b7-I94">
|
||||
<rect key="frame" x="74" y="110" width="555" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="item args" id="qTP-D2-QN6">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="430" y="250"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bug" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,213 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<development version="5000" identifier="xcode"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="TreeViewController">
|
||||
<connections>
|
||||
<outlet property="itemView" destination="Wr1-No-lg2" id="74i-TW-N6D"/>
|
||||
<outlet property="view" destination="T1P-b9-TzF" id="pja-1o-aue"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<view id="T1P-b9-TzF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1306" height="294"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" borderType="line" autohidesScrollers="YES" horizontalLineScroll="42" horizontalPageScroll="10" verticalLineScroll="42" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mTr-W0-MgJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1306" height="294"/>
|
||||
<clipView key="contentView" misplaced="YES" id="Sbm-Z7-NmT">
|
||||
<rect key="frame" x="1" y="17" width="238" height="117"/>
|
||||
<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"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="MainCell" editable="NO" width="1301" minWidth="40" maxWidth="2000" id="cLW-QZ-CYz">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="r1l-iI-5S2">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="ImageCell" 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>
|
||||
<imageView ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DMw-xR-BeB">
|
||||
<rect key="frame" x="5" y="9" width="26" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="N3v-eG-0fM"/>
|
||||
<constraint firstAttribute="width" constant="20" id="ZmE-rN-Aa2"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="I2b-0v-y6D"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="839-dJ-gQp">
|
||||
<rect key="frame" x="33" y="23" width="11" height="11"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="11" id="1Kh-hp-YgV"/>
|
||||
<constraint firstAttribute="width" constant="11" id="WKY-rc-A7v"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="unknown" id="cl5-Gt-HMs"/>
|
||||
</imageView>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oWx-jq-02H">
|
||||
<rect key="frame" x="46" y="20" width="225" height="18"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Item Name" id="Z6I-g2-cup">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show in finder" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="107" translatesAutoresizingMaskIntoConstraints="NO" id="6f3-ri-fbE">
|
||||
<rect key="frame" x="1263" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="15" id="Mza-vw-e2F"/>
|
||||
<constraint firstAttribute="height" constant="15" id="qqU-cb-eBX"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="show" imagePosition="only" alignment="center" alternateImage="showBG" state="on" imageScaling="proportionallyDown" inset="2" id="cy3-S9-iUc">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="108" translatesAutoresizingMaskIntoConstraints="NO" id="Wjv-b4-LpE">
|
||||
<rect key="frame" x="1259" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="25" id="IdA-gX-1SJ"/>
|
||||
<constraint firstAttribute="height" constant="12" id="mEP-zn-5P5"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="show" id="Ypq-tG-G2w">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="101" translatesAutoresizingMaskIntoConstraints="NO" id="vl6-B3-YnP">
|
||||
<rect key="frame" x="31" y="2" width="1093" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" title="item path" id="IxF-8j-bl0">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show virustotal info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="103" translatesAutoresizingMaskIntoConstraints="NO" id="4A1-v1-fqF" customClass="VTButton">
|
||||
<rect key="frame" x="1155" y="17" width="49" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="29" id="81l-Vw-eYi"/>
|
||||
<constraint firstAttribute="width" constant="49" id="Tsp-mH-sb0"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" title="▪ ▪ ▪" bezelStyle="regularSquare" imagePosition="overlaps" alignment="center" enabled="NO" refusesFirstResponder="YES" state="on" imageScaling="proportionallyDown" inset="2" id="7Ff-Cs-4HN">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" size="8" name="Menlo-Bold"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="104" translatesAutoresizingMaskIntoConstraints="NO" id="NKv-qJ-K0K">
|
||||
<rect key="frame" x="1148" y="4" width="65" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="61" id="BhB-I3-B9j"/>
|
||||
<constraint firstAttribute="height" constant="12" id="Lvp-ST-Nn4"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="virustotal" id="6oc-VM-LLN">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button toolTip="show file info" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="105" translatesAutoresizingMaskIntoConstraints="NO" id="DJD-ri-L1B">
|
||||
<rect key="frame" x="1226" y="17" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="15" id="OjK-9U-ZN2"/>
|
||||
<constraint firstAttribute="width" constant="15" id="VnG-o4-pT8"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="info" imagePosition="only" alignment="center" alternateImage="infoBG" state="on" imageScaling="proportionallyDown" inset="2" id="Pt4-bk-dHy">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="106" translatesAutoresizingMaskIntoConstraints="NO" id="66d-28-HRc">
|
||||
<rect key="frame" x="1220" y="4" width="25" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="12" id="U1Q-a7-1C4"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="info" id="D2L-sc-I1J">
|
||||
<font key="font" size="9" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" tag="102" translatesAutoresizingMaskIntoConstraints="NO" id="bxk-nY-Ojx">
|
||||
<rect key="frame" x="295" y="20" width="79" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="75" id="QKJ-lc-9uH"/>
|
||||
<constraint firstAttribute="height" constant="18" id="lqD-mH-tWl"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="pid" id="yDx-Lo-cYE">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.49295236009999999" alpha="0.84999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="6f3-ri-fbE" firstAttribute="leading" secondItem="DJD-ri-L1B" secondAttribute="trailing" constant="20" id="62I-6i-bdJ"/>
|
||||
<constraint firstItem="66d-28-HRc" firstAttribute="leading" secondItem="NKv-qJ-K0K" secondAttribute="trailing" constant="9" id="D01-9Y-AMk"/>
|
||||
<constraint firstItem="DMw-xR-BeB" firstAttribute="leading" secondItem="7xB-nb-n5O" secondAttribute="leading" constant="5" id="EEt-PD-0zF"/>
|
||||
<constraint firstItem="bxk-nY-Ojx" firstAttribute="leading" secondItem="oWx-jq-02H" secondAttribute="trailing" constant="8" id="IP5-Ta-1Bu"/>
|
||||
<constraint firstItem="4A1-v1-fqF" firstAttribute="leading" secondItem="vl6-B3-YnP" secondAttribute="trailing" constant="8" id="VbZ-DW-ip1"/>
|
||||
<constraint firstItem="vl6-B3-YnP" firstAttribute="leading" secondItem="DMw-xR-BeB" secondAttribute="trailing" constant="8" id="gVM-E6-C5n"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Wjv-b4-LpE" secondAttribute="trailing" constant="4" id="nBr-zQ-aVu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="6f3-ri-fbE" secondAttribute="trailing" constant="10" id="nNS-um-ew2"/>
|
||||
<constraint firstItem="Wjv-b4-LpE" firstAttribute="leading" secondItem="66d-28-HRc" secondAttribute="trailing" constant="10" id="qg8-JA-AGc"/>
|
||||
<constraint firstItem="DJD-ri-L1B" firstAttribute="leading" secondItem="4A1-v1-fqF" secondAttribute="trailing" constant="18" id="qrS-aQ-C2c"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="imageView" destination="DMw-xR-BeB" id="m01-aR-tqa"/>
|
||||
<outlet property="textField" destination="oWx-jq-02H" id="hC6-7m-qaL"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-2" id="AI8-10-Pvd"/>
|
||||
<outlet property="delegate" destination="-2" id="Edd-Bv-VRx"/>
|
||||
</connections>
|
||||
</outlineView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="7QY-ke-KIc">
|
||||
<rect key="frame" x="1" y="109.73348331451416" width="220" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="ifK-Bg-0Ke">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="638" y="-658"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="14" height="14"/>
|
||||
<image name="info" width="256" height="256"/>
|
||||
<image name="infoBG" width="256" height="256"/>
|
||||
<image name="show" width="256" height="256"/>
|
||||
<image name="showBG" width="256" height="256"/>
|
||||
<image name="unknown" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6751" systemVersion="14C1514" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6751"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="VTInfoWindowController">
|
||||
<connections>
|
||||
<outlet property="analysisURL" destination="Wbv-SK-w53" id="vRG-LY-sA2"/>
|
||||
<outlet property="analysisURLLabel" destination="tM6-Nq-1Rh" id="tVS-Z8-QoN"/>
|
||||
<outlet property="closeButton" destination="uJq-Bw-lDQ" id="RWs-cM-R4U"/>
|
||||
<outlet property="detectionRatio" destination="hLU-fi-qXH" id="HMI-2q-F37"/>
|
||||
<outlet property="detectionRatioLabel" destination="DFa-vc-wFY" id="KeB-h4-vI3"/>
|
||||
<outlet property="fileName" destination="hcM-hb-3Lz" id="uSy-od-y3n"/>
|
||||
<outlet property="fileNameLabel" destination="Plg-lF-OEE" id="KeM-nK-KQA"/>
|
||||
<outlet property="overlayView" destination="S16-Le-yTU" id="8Ye-PE-A3D"/>
|
||||
<outlet property="progressIndicator" destination="egv-M2-RqY" id="zgU-Hu-k7Z"/>
|
||||
<outlet property="statusMsg" destination="Hew-Ee-HGX" id="BFR-Pr-u6h"/>
|
||||
<outlet property="submitButton" destination="Sxd-Ob-1Af" id="jB1-QN-Af2"/>
|
||||
<outlet property="unknownFile" destination="eEi-hA-pdx" id="tY3-qL-05e"/>
|
||||
<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 title="VirusTotal Information" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="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="534" height="144"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="se5-gp-TjO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="534" height="144"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uJq-Bw-lDQ">
|
||||
<rect key="frame" x="430" y="13" width="90" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="RwO-yA-Xwk">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="closeButtonHandler:" target="-2" id="h73-fH-gDU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hLU-fi-qXH">
|
||||
<rect key="frame" x="189" y="81" width="650" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="ratio" id="XJ7-Go-bkG">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wbv-SK-w53" customClass="HyperlinkTextField">
|
||||
<rect key="frame" x="189" y="53" width="650" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="report url" id="hR8-Wz-esN">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DFa-vc-wFY">
|
||||
<rect key="frame" x="99" y="81" width="83" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="detection:" id="iBS-9J-ok9">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tM6-Nq-1Rh">
|
||||
<rect key="frame" x="57" y="53" width="125" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="more info:" id="U3V-A7-jO8">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hcM-hb-3Lz" customClass="HyperlinkTextField">
|
||||
<rect key="frame" x="189" y="106" width="650" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" title="file name" id="3TS-NZ-XYE">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Plg-lF-OEE">
|
||||
<rect key="frame" x="99" y="107" width="83" height="19"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="file name:" id="HO9-t1-yCi">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vO5-mf-hOM">
|
||||
<rect key="frame" x="20" y="56" width="68" height="68"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="vtLogo" id="qFc-P8-Wm8"/>
|
||||
</imageView>
|
||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eEi-hA-pdx">
|
||||
<rect key="frame" x="18" y="81" width="498" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="unknown file" id="2nj-QY-6ot">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Sxd-Ob-1Af">
|
||||
<rect key="frame" x="340" y="13" width="90" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="submit?" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JAW-nH-eRf">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="vtButtonHandler:" target="-2" id="YtT-aa-xM1"/>
|
||||
</connections>
|
||||
</button>
|
||||
<customView hidden="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="S16-Le-yTU">
|
||||
<rect key="frame" x="0.0" y="-12" width="534" height="156"/>
|
||||
<subviews>
|
||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hew-Ee-HGX">
|
||||
<rect key="frame" x="18" y="52" width="498" height="20"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="status msg" id="lxM-ES-i7K">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<progressIndicator hidden="YES" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="egv-M2-RqY">
|
||||
<rect key="frame" x="251" y="74" width="32" height="32"/>
|
||||
</progressIndicator>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="374" y="212"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="vtLogo" width="300" height="300"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Utilities.h
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/7/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef DHS_Utilities_h
|
||||
#define DHS_Utilities_h
|
||||
|
||||
|
||||
//get the signing info of a file
|
||||
NSDictionary* extractSigningInfo(NSString* path);
|
||||
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//check if OS is supported
|
||||
BOOL isSupportedOS();
|
||||
|
||||
//get OS's major or minor version
|
||||
SInt32 getVersion(OSType selector);
|
||||
|
||||
//if string is too long to fit into a the text field
|
||||
// ->truncate and insert ellipises before /file
|
||||
NSString* stringByTruncatingString(NSTextField* textField, NSString* string, float width);
|
||||
|
||||
//get an icon for a process
|
||||
// ->for apps, this will be app's icon, otherwise just a standard system one
|
||||
NSImage* getIconForBinary(NSString* binary, NSBundle* bundle);
|
||||
|
||||
//given a path to binary
|
||||
// parse it back up to find app's bundle
|
||||
NSBundle* findAppBundle(NSString* binaryPath);
|
||||
|
||||
//given a directory and a filter predicate
|
||||
// ->return all matches
|
||||
NSArray* directoryContents(NSString* directory, NSString* predicate);
|
||||
|
||||
//hash (sha1/md5) a file
|
||||
NSDictionary* hashFile(NSString* filePath);
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion();
|
||||
|
||||
//determine if a file is signed by Apple proper
|
||||
BOOL isApple(NSString* path);
|
||||
|
||||
//convert a textview to a clickable hyperlink
|
||||
void makeTextViewHyperlink(NSTextField* textField, NSURL* url);
|
||||
|
||||
//determine if a file is signed by Apple proper
|
||||
BOOL isApple(NSString* path);
|
||||
|
||||
//set the color of an attributed string
|
||||
NSMutableAttributedString* setStringColor(NSAttributedString* string, NSColor* color);
|
||||
|
||||
//exec a process and grab it's output
|
||||
NSData* execTask(NSString* binaryPath, NSArray* arguments);
|
||||
|
||||
//wait until a window is non nil
|
||||
// ->then make it modal
|
||||
void makeModal(NSWindowController* windowController);
|
||||
|
||||
//given a pid, get its parent (ppid)
|
||||
pid_t getParentID(int pid);
|
||||
|
||||
//get path to XPC service
|
||||
NSString* getPath2XPC();
|
||||
|
||||
//get path to kernel
|
||||
NSString* path2Kernel();
|
||||
|
||||
//determine if process is (still) alive
|
||||
BOOL isAlive(pid_t targetPID);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,831 @@
|
||||
//
|
||||
// Utilities.m
|
||||
// DHS
|
||||
//
|
||||
// Created by Patrick Wardle on 2/7/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
#import <signal.h>
|
||||
#import <unistd.h>
|
||||
#import <libproc.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <Security/Security.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
//check if OS is supported
|
||||
BOOL isSupportedOS()
|
||||
{
|
||||
//return
|
||||
BOOL isSupported = NO;
|
||||
|
||||
//major version
|
||||
SInt32 versionMajor = 0;
|
||||
|
||||
//minor version
|
||||
SInt32 versionMinor = 0;
|
||||
|
||||
//get major version
|
||||
versionMajor = getVersion(gestaltSystemVersionMajor);
|
||||
|
||||
//get minor version
|
||||
versionMinor = getVersion(gestaltSystemVersionMinor);
|
||||
|
||||
//sanity check
|
||||
if( (-1 == versionMajor) ||
|
||||
(-1 == versionMinor) )
|
||||
{
|
||||
//err
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//check that OS is supported
|
||||
// ->10.8+ ?
|
||||
if( (versionMajor == OS_MAJOR_VERSION_X) &&
|
||||
(versionMinor >= OS_MINOR_VERSION_LION) )
|
||||
{
|
||||
//set flag
|
||||
isSupported = YES;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
//get OS's major or minor version
|
||||
SInt32 getVersion(OSType selector)
|
||||
{
|
||||
//version
|
||||
// ->major or minor
|
||||
SInt32 version = -1;
|
||||
|
||||
//get version info
|
||||
if(noErr != Gestalt(selector, &version))
|
||||
{
|
||||
//reset version
|
||||
version = -1;
|
||||
|
||||
//err
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
//get the signing info of a file
|
||||
NSDictionary* extractSigningInfo(NSString* path)
|
||||
{
|
||||
//info dictionary
|
||||
NSMutableDictionary* signingStatus = nil;
|
||||
|
||||
//code
|
||||
SecStaticCodeRef staticCode = NULL;
|
||||
|
||||
//status
|
||||
OSStatus status = !STATUS_SUCCESS;
|
||||
|
||||
//signing information
|
||||
CFDictionaryRef signingInformation = NULL;
|
||||
|
||||
//cert chain
|
||||
NSArray* certificateChain = nil;
|
||||
|
||||
//index
|
||||
NSUInteger index = 0;
|
||||
|
||||
//cert
|
||||
SecCertificateRef certificate = NULL;
|
||||
|
||||
//common name on chert
|
||||
CFStringRef commonName = NULL;
|
||||
|
||||
//init signing status
|
||||
signingStatus = [NSMutableDictionary dictionary];
|
||||
|
||||
//create static code
|
||||
status = SecStaticCodeCreateWithPath((__bridge CFURLRef)([NSURL fileURLWithPath:path]), kSecCSDefaultFlags, &staticCode);
|
||||
|
||||
//save signature status
|
||||
signingStatus[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status];
|
||||
|
||||
//sanity check
|
||||
if(STATUS_SUCCESS != status)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: SecStaticCodeCreateWithPath() failed on %@ with %d", path, status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//check signature
|
||||
status = SecStaticCodeCheckValidityWithErrors(staticCode, kSecCSDoNotValidateResources, NULL, NULL);
|
||||
|
||||
//(re)save signature status
|
||||
signingStatus[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status];
|
||||
|
||||
//if file is signed
|
||||
// ->grab signing authorities
|
||||
if(STATUS_SUCCESS == status)
|
||||
{
|
||||
//grab signing authorities
|
||||
status = SecCodeCopySigningInformation(staticCode, kSecCSSigningInformation, &signingInformation);
|
||||
|
||||
//sanity check
|
||||
if(STATUS_SUCCESS != status)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: SecCodeCopySigningInformation() failed on %@ with %d", path, status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
//init array for certificate names
|
||||
signingStatus[KEY_SIGNING_AUTHORITIES] = [NSMutableArray array];
|
||||
|
||||
//get cert chain
|
||||
certificateChain = [(__bridge NSDictionary*)signingInformation objectForKey:(__bridge NSString*)kSecCodeInfoCertificates];
|
||||
|
||||
//handle case there is no cert chain
|
||||
// ->adhoc? (/Library/Frameworks/OpenVPN.framework/Versions/Current/bin/openvpn-service)
|
||||
if(0 == certificateChain.count)
|
||||
{
|
||||
//set
|
||||
[signingStatus[KEY_SIGNING_AUTHORITIES] addObject:@"signed, but no signing authorities (adhoc?)"];
|
||||
}
|
||||
|
||||
//got cert chain
|
||||
// ->add each to list
|
||||
else
|
||||
{
|
||||
//get name of all certs
|
||||
for(index = 0; index < certificateChain.count; index++)
|
||||
{
|
||||
//extract cert
|
||||
certificate = (__bridge SecCertificateRef)([certificateChain objectAtIndex:index]);
|
||||
|
||||
//get common name
|
||||
status = SecCertificateCopyCommonName(certificate, &commonName);
|
||||
|
||||
//skip ones that error out
|
||||
if( (STATUS_SUCCESS != status) ||
|
||||
(NULL == commonName))
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//save
|
||||
[signingStatus[KEY_SIGNING_AUTHORITIES] addObject:(__bridge NSString*)commonName];
|
||||
|
||||
//release name
|
||||
CFRelease(commonName);
|
||||
}
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free signing info
|
||||
if(NULL != signingInformation)
|
||||
{
|
||||
//free
|
||||
CFRelease(signingInformation);
|
||||
}
|
||||
|
||||
//free static code
|
||||
if(NULL != staticCode)
|
||||
{
|
||||
//free
|
||||
CFRelease(staticCode);
|
||||
}
|
||||
|
||||
return signingStatus;
|
||||
}
|
||||
|
||||
//determine if a file is signed by Apple proper
|
||||
BOOL isApple(NSString* path)
|
||||
{
|
||||
//flag
|
||||
BOOL isApple = NO;
|
||||
|
||||
//code
|
||||
SecStaticCodeRef staticCode = NULL;
|
||||
|
||||
//signing reqs
|
||||
SecRequirementRef requirementRef = NULL;
|
||||
|
||||
//status
|
||||
OSStatus status = -1;
|
||||
|
||||
//create static code
|
||||
status = SecStaticCodeCreateWithPath((__bridge CFURLRef)([NSURL fileURLWithPath:path]), kSecCSDefaultFlags, &staticCode);
|
||||
if(STATUS_SUCCESS != status)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: SecStaticCodeCreateWithPath() failed on %@ with %d", path, status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//create req string w/ 'anchor apple'
|
||||
// (3rd party: 'anchor apple generic')
|
||||
status = SecRequirementCreateWithString(CFSTR("anchor apple"), kSecCSDefaultFlags, &requirementRef);
|
||||
if( (STATUS_SUCCESS != status) ||
|
||||
(requirementRef == NULL) )
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: SecRequirementCreateWithString() failed on %@ with %d", path, status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//check if file is signed by apple
|
||||
// ->i.e. it conforms to req string
|
||||
status = SecStaticCodeCheckValidity(staticCode, kSecCSDefaultFlags, requirementRef);
|
||||
if(STATUS_SUCCESS != status)
|
||||
{
|
||||
//bail
|
||||
// ->just means app isn't signed by apple
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//ok, happy (SecStaticCodeCheckValidity() didn't fail)
|
||||
// ->file is signed by Apple
|
||||
isApple = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
//free req reference
|
||||
if(NULL != requirementRef)
|
||||
{
|
||||
//free
|
||||
CFRelease(requirementRef);
|
||||
}
|
||||
|
||||
//free static code
|
||||
if(NULL != staticCode)
|
||||
{
|
||||
//free
|
||||
CFRelease(staticCode);
|
||||
}
|
||||
|
||||
|
||||
return isApple;
|
||||
}
|
||||
|
||||
|
||||
//get an icon for a process
|
||||
// ->for apps, this will be app's icon, otherwise just a standard system one
|
||||
NSImage* getIconForBinary(NSString* binary, NSBundle* bundle)
|
||||
{
|
||||
//icon's file name
|
||||
NSString* iconFile = nil;
|
||||
|
||||
//icon's path
|
||||
NSString* iconPath = nil;
|
||||
|
||||
//icon's path extension
|
||||
NSString* iconExtension = nil;
|
||||
|
||||
//system's document icon
|
||||
NSData* documentIcon = nil;
|
||||
|
||||
//icon
|
||||
NSImage* icon = nil;
|
||||
|
||||
//since path is always full path to binary
|
||||
// ->manaully try to find & load bundle (for .apps)
|
||||
if(nil == bundle)
|
||||
{
|
||||
//load bundle
|
||||
bundle = findAppBundle(binary);
|
||||
}
|
||||
|
||||
//for app's
|
||||
// ->extract their icon
|
||||
if(nil != bundle)
|
||||
{
|
||||
//get file
|
||||
iconFile = bundle.infoDictionary[@"CFBundleIconFile"];
|
||||
|
||||
//get path extension
|
||||
iconExtension = [iconFile pathExtension];
|
||||
|
||||
//if its blank (i.e. not specified)
|
||||
// ->go with 'icns'
|
||||
if(YES == [iconExtension isEqualTo:@""])
|
||||
{
|
||||
//set type
|
||||
iconExtension = @"icns";
|
||||
}
|
||||
|
||||
//set full path
|
||||
iconPath = [bundle pathForResource:[iconFile stringByDeletingPathExtension] ofType:iconExtension];
|
||||
|
||||
//load it
|
||||
icon = [[NSImage alloc] initWithContentsOfFile:iconPath];
|
||||
}
|
||||
|
||||
//process is not an app or couldn't get icon
|
||||
// ->try to get it via shared workspace
|
||||
if( (nil == bundle) ||
|
||||
(nil == icon) )
|
||||
{
|
||||
//extract icon
|
||||
icon = [[NSWorkspace sharedWorkspace] iconForFile:binary];
|
||||
|
||||
//load system document icon
|
||||
documentIcon = [[[NSWorkspace sharedWorkspace] iconForFileType:
|
||||
NSFileTypeForHFSTypeCode(kGenericDocumentIcon)] TIFFRepresentation];
|
||||
|
||||
//if 'iconForFile' method doesn't find and icon, it returns the system 'document' icon
|
||||
// ->the system 'applicaiton' icon seems more applicable, so use that here...
|
||||
if(YES == [[icon TIFFRepresentation] isEqual:documentIcon])
|
||||
{
|
||||
//set icon to system 'applicaiton' icon
|
||||
icon = [[NSWorkspace sharedWorkspace]
|
||||
iconForFileType: NSFileTypeForHFSTypeCode(kGenericApplicationIcon)];
|
||||
}
|
||||
|
||||
//'iconForFileType' returns small icons
|
||||
// ->so set size to 64
|
||||
[icon setSize:NSMakeSize(64, 64)];
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
//if string is too long to fit into a the text field
|
||||
// ->truncate and insert ellipises before /file
|
||||
NSString* stringByTruncatingString(NSTextField* textField, NSString* string, float width)
|
||||
{
|
||||
//trucated string (with ellipis)
|
||||
NSMutableString *truncatedString = nil;
|
||||
|
||||
//offset of last '/'
|
||||
NSRange lastSlash = {};
|
||||
|
||||
//make copy of string
|
||||
truncatedString = [string mutableCopy];
|
||||
|
||||
//sanity check
|
||||
// ->make sure string needs truncating
|
||||
if([string sizeWithAttributes: @{NSFontAttributeName: textField.font}].width < width)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//find instance of last '/
|
||||
lastSlash = [string rangeOfString:@"/" options:NSBackwardsSearch];
|
||||
|
||||
//sanity check
|
||||
// ->make sure found a '/'
|
||||
if(NSNotFound == lastSlash.location)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//account for added ellipsis
|
||||
width -= [ELLIPIS sizeWithAttributes: @{NSFontAttributeName: textField.font}].width;
|
||||
|
||||
//delete characters until string will fit into specified size
|
||||
while([truncatedString sizeWithAttributes: @{NSFontAttributeName: textField.font}].width > width)
|
||||
{
|
||||
//sanity check
|
||||
// ->make sure we don't run off the front
|
||||
if(0 == lastSlash.location)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//skip back
|
||||
lastSlash.location--;
|
||||
|
||||
//delete char
|
||||
[truncatedString deleteCharactersInRange:lastSlash];
|
||||
}
|
||||
|
||||
//set length of range
|
||||
lastSlash.length = ELLIPIS.length;
|
||||
|
||||
//back up location
|
||||
lastSlash.location -= ELLIPIS.length;
|
||||
|
||||
//add in ellipis
|
||||
[truncatedString replaceCharactersInRange:lastSlash withString:ELLIPIS];
|
||||
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return truncatedString;
|
||||
}
|
||||
|
||||
//given a directory and a filter predicate
|
||||
// ->return all matches
|
||||
NSArray* directoryContents(NSString* directory, NSString* predicate)
|
||||
{
|
||||
//(unfiltered) directory contents
|
||||
NSArray* directoryContents = nil;
|
||||
|
||||
//matches
|
||||
NSArray* matches = nil;
|
||||
|
||||
//get (unfiltered) directory contents
|
||||
directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:nil];
|
||||
|
||||
//filter out matches
|
||||
if(nil != predicate)
|
||||
{
|
||||
//filter
|
||||
matches = [directoryContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:predicate]];
|
||||
}
|
||||
//no need to filter
|
||||
else
|
||||
{
|
||||
//no filter
|
||||
matches = directoryContents;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
//given a path to binary
|
||||
// parse it back up to find app's bundle
|
||||
NSBundle* findAppBundle(NSString* binaryPath)
|
||||
{
|
||||
//app's bundle
|
||||
NSBundle* appBundle = nil;
|
||||
|
||||
//app's path
|
||||
NSString* appPath = nil;
|
||||
|
||||
//first just try full path
|
||||
appPath = binaryPath;
|
||||
|
||||
//try to find the app's bundle/info dictionary
|
||||
do
|
||||
{
|
||||
//try to load app's bundle
|
||||
appBundle = [NSBundle bundleWithPath:appPath];
|
||||
|
||||
//check for match
|
||||
// ->binary path's match
|
||||
if( (nil != appBundle) &&
|
||||
(YES == [appBundle.executablePath isEqualToString:binaryPath]))
|
||||
{
|
||||
//all done
|
||||
break;
|
||||
}
|
||||
|
||||
//always unset bundle var since it's being returned
|
||||
// ->and at this point, its not a match
|
||||
appBundle = nil;
|
||||
|
||||
//remove last part
|
||||
// ->will try this next
|
||||
appPath = [appPath stringByDeletingLastPathComponent];
|
||||
|
||||
//scan until we get to root
|
||||
// ->of course, loop will be exited if app info dictionary is found/loaded
|
||||
} while( (nil != appPath) &&
|
||||
(YES != [appPath isEqualToString:@"/"]) &&
|
||||
(YES != [appPath isEqualToString:@""]) );
|
||||
|
||||
return appBundle;
|
||||
}
|
||||
|
||||
//hash a file
|
||||
// ->md5 and sha1
|
||||
NSDictionary* hashFile(NSString* filePath)
|
||||
{
|
||||
//file hashes
|
||||
NSDictionary* hashes = nil;
|
||||
|
||||
//file's contents
|
||||
NSData* fileContents = nil;
|
||||
|
||||
//hash digest (md5)
|
||||
uint8_t digestMD5[CC_MD5_DIGEST_LENGTH] = {0};
|
||||
|
||||
//md5 hash as string
|
||||
NSMutableString* md5 = nil;
|
||||
|
||||
//hash digest (sha1)
|
||||
uint8_t digestSHA1[CC_SHA1_DIGEST_LENGTH] = {0};
|
||||
|
||||
//sha1 hash as string
|
||||
NSMutableString* sha1 = nil;
|
||||
|
||||
//index var
|
||||
NSUInteger index = 0;
|
||||
|
||||
//init md5 hash string
|
||||
md5 = [NSMutableString string];
|
||||
|
||||
//init sha1 hash string
|
||||
sha1 = [NSMutableString string];
|
||||
|
||||
//load file
|
||||
if(nil == (fileContents = [NSData dataWithContentsOfFile:filePath]))
|
||||
{
|
||||
//err msg
|
||||
//TODO: re-enable
|
||||
//NSLog(@"OBJECTIVE-SEE ERROR: couldn't load %@ to hash", filePath);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//md5 it
|
||||
CC_MD5(fileContents.bytes, (unsigned int)fileContents.length, digestMD5);
|
||||
|
||||
//convert to NSString
|
||||
// ->iterate over each bytes in computed digest and format
|
||||
for(index=0; index < CC_MD5_DIGEST_LENGTH; index++)
|
||||
{
|
||||
//format/append
|
||||
[md5 appendFormat:@"%02lX", (unsigned long)digestMD5[index]];
|
||||
}
|
||||
|
||||
//sha1 it
|
||||
CC_SHA1(fileContents.bytes, (unsigned int)fileContents.length, digestSHA1);
|
||||
|
||||
//convert to NSString
|
||||
// ->iterate over each bytes in computed digest and format
|
||||
for(index=0; index < CC_SHA1_DIGEST_LENGTH; index++)
|
||||
{
|
||||
//format/append
|
||||
[sha1 appendFormat:@"%02lX", (unsigned long)digestSHA1[index]];
|
||||
}
|
||||
|
||||
//init hash dictionary
|
||||
hashes = @{KEY_HASH_MD5: md5, KEY_HASH_SHA1: sha1};
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
||||
//get app's version
|
||||
// ->extracted from Info.plist
|
||||
NSString* getAppVersion()
|
||||
{
|
||||
//read and return 'CFBundleVersion' from bundle
|
||||
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
|
||||
}
|
||||
|
||||
//convert a textview to a clickable hyperlink
|
||||
void makeTextViewHyperlink(NSTextField* textField, NSURL* url)
|
||||
{
|
||||
//hyperlink
|
||||
NSMutableAttributedString *hyperlinkString = nil;
|
||||
|
||||
//range
|
||||
NSRange range = {0};
|
||||
|
||||
//init hyper link
|
||||
hyperlinkString = [[NSMutableAttributedString alloc] initWithString:textField.stringValue];
|
||||
|
||||
//init range
|
||||
range = NSMakeRange(0, [hyperlinkString length]);
|
||||
|
||||
//start editing
|
||||
[hyperlinkString beginEditing];
|
||||
|
||||
//add url
|
||||
[hyperlinkString addAttribute:NSLinkAttributeName value:url range:range];
|
||||
|
||||
//make it blue
|
||||
[hyperlinkString addAttribute:NSForegroundColorAttributeName value:[NSColor blueColor] range:NSMakeRange(0, [hyperlinkString length])];
|
||||
|
||||
//underline
|
||||
[hyperlinkString addAttribute:
|
||||
NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:NSMakeRange(0, [hyperlinkString length])];
|
||||
|
||||
//done editing
|
||||
[hyperlinkString endEditing];
|
||||
|
||||
//set text
|
||||
[textField setAttributedStringValue:hyperlinkString];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//set the color of an attributed string
|
||||
NSMutableAttributedString* setStringColor(NSAttributedString* string, NSColor* color)
|
||||
{
|
||||
//colored string
|
||||
NSMutableAttributedString *coloredString = nil;
|
||||
|
||||
//alloc/init colored string from existing one
|
||||
coloredString = [[NSMutableAttributedString alloc] initWithAttributedString:string];
|
||||
|
||||
//set color
|
||||
[coloredString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [coloredString length])];
|
||||
|
||||
return coloredString;
|
||||
}
|
||||
|
||||
//exec a process and grab it's output
|
||||
NSData* execTask(NSString* binaryPath, NSArray* arguments)
|
||||
{
|
||||
//task
|
||||
NSTask *task = nil;
|
||||
|
||||
//output pipe
|
||||
NSPipe *outPipe = nil;
|
||||
|
||||
//read handle
|
||||
NSFileHandle* readHandle = nil;
|
||||
|
||||
//output
|
||||
NSMutableData *output = nil;
|
||||
|
||||
//init task
|
||||
task = [NSTask new];
|
||||
|
||||
//init output pipe
|
||||
outPipe = [NSPipe pipe];
|
||||
|
||||
//init read handle
|
||||
readHandle = [outPipe fileHandleForReading];
|
||||
|
||||
//init output buffer
|
||||
output = [NSMutableData data];
|
||||
|
||||
//set task's path
|
||||
[task setLaunchPath:binaryPath];
|
||||
|
||||
//set task's args
|
||||
[task setArguments:arguments];
|
||||
|
||||
//set task's output
|
||||
[task setStandardOutput:outPipe];
|
||||
|
||||
//launch the task
|
||||
[task launch];
|
||||
|
||||
//read in output
|
||||
while(YES == [task isRunning])
|
||||
{
|
||||
//accumulate output
|
||||
[output appendData:[readHandle readDataToEndOfFile]];
|
||||
}
|
||||
|
||||
//grab any left over data
|
||||
[output appendData:[readHandle readDataToEndOfFile]];
|
||||
|
||||
//return output as string
|
||||
return output;
|
||||
}
|
||||
|
||||
//wait until a window is non nil
|
||||
// ->then make it modal
|
||||
void makeModal(NSWindowController* windowController)
|
||||
{
|
||||
//wait up to 1 second window to be non-nil
|
||||
// ->then make modal
|
||||
for(int i=0; i<20; i++)
|
||||
{
|
||||
//can make it modal once we have a window
|
||||
if(nil != windowController.window)
|
||||
{
|
||||
//make modal on main thread
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//modal
|
||||
[[NSApplication sharedApplication] runModalForWindow:windowController.window];
|
||||
|
||||
});
|
||||
|
||||
//all done
|
||||
break;
|
||||
}
|
||||
|
||||
//nap
|
||||
[NSThread sleepForTimeInterval:0.05f];
|
||||
|
||||
}//until 1 second
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//given a pid, get its parent (ppid)
|
||||
pid_t getParentID(int pid)
|
||||
{
|
||||
//parent id
|
||||
pid_t parentID = -1;
|
||||
|
||||
//kinfo_proc struct
|
||||
struct kinfo_proc processStruct = {0};
|
||||
|
||||
//size
|
||||
size_t procBufferSize = sizeof(processStruct);
|
||||
|
||||
//mib
|
||||
const u_int mibLength = 4;
|
||||
|
||||
//syscall result
|
||||
int sysctlResult = -1;
|
||||
|
||||
//init mib
|
||||
int mib[mibLength] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
|
||||
|
||||
//make syscall
|
||||
sysctlResult = sysctl(mib, mibLength, &processStruct, &procBufferSize, NULL, 0);
|
||||
|
||||
//check if got ppid
|
||||
if( (STATUS_SUCCESS == sysctlResult) &&
|
||||
(0 != procBufferSize) )
|
||||
{
|
||||
//save ppid
|
||||
parentID = processStruct.kp_eproc.e_ppid;
|
||||
}
|
||||
|
||||
return parentID;
|
||||
}
|
||||
|
||||
//get path to XPC service
|
||||
NSString* getPath2XPC()
|
||||
{
|
||||
//path to XPC service
|
||||
NSString* xpcService = nil;
|
||||
|
||||
//build path
|
||||
xpcService = [NSString stringWithFormat:@"%@/Contents/XPCServices/%@", [[NSBundle mainBundle] bundlePath], XPC_SERVICE];
|
||||
|
||||
//make sure its there
|
||||
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:xpcService])
|
||||
{
|
||||
//nope
|
||||
// ->nil out
|
||||
xpcService = nil;
|
||||
}
|
||||
|
||||
return xpcService;
|
||||
}
|
||||
|
||||
//get path to kernel
|
||||
NSString* path2Kernel()
|
||||
{
|
||||
//kernel path
|
||||
NSString* kernel;
|
||||
|
||||
//check Yosemite's location first
|
||||
if(YES == [[NSFileManager defaultManager] fileExistsAtPath:KERNEL_YOSEMITE])
|
||||
{
|
||||
//set
|
||||
kernel = KERNEL_YOSEMITE;
|
||||
}
|
||||
//go w/ older location
|
||||
else
|
||||
{
|
||||
//set
|
||||
kernel = KERNEL_PRE_YOSEMITE;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
//determine if process is (still) alive
|
||||
BOOL isAlive(pid_t targetPID)
|
||||
{
|
||||
//flag
|
||||
BOOL isAlive = YES;
|
||||
|
||||
//try 'kill' with 0
|
||||
// ->no harm done, but will fail with 'ESRCH' if process is dead!
|
||||
if( (0 != kill(targetPID, 0)) &&
|
||||
(ESRCH == errno) )
|
||||
{
|
||||
isAlive = NO;
|
||||
|
||||
}
|
||||
|
||||
//NSLog(@"killing %d: %d/%d", targetPID, result, errno);
|
||||
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// vtButton.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/26/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Binary.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
//#import "ItemTableController.h"
|
||||
|
||||
@class TaskTableController;
|
||||
|
||||
@interface VTButton : NSButton
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//properties
|
||||
|
||||
//parent object
|
||||
@property(assign)TaskTableController *delegate;
|
||||
|
||||
//File object
|
||||
@property(nonatomic, retain)Binary* fileObj;
|
||||
|
||||
//button's row index
|
||||
|
||||
//flag indicating press
|
||||
@property BOOL mouseDown;
|
||||
|
||||
//flag indicating exit
|
||||
@property BOOL mouseExit;
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// vtButton.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/26/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Consts.h"
|
||||
#import "VTButton.h"
|
||||
#import "Utilities.h"
|
||||
#import "TaskTableController.h"
|
||||
|
||||
@implementation VTButton
|
||||
|
||||
@synthesize fileObj;
|
||||
@synthesize delegate;
|
||||
@synthesize mouseDown;
|
||||
@synthesize mouseExit;
|
||||
|
||||
//automatically invoked
|
||||
// ->create tracking area for mouse events
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//create the mouse-over tracking area
|
||||
[self createTrackingArea];
|
||||
}
|
||||
|
||||
//create the mouse-over tracking area
|
||||
-(void)createTrackingArea
|
||||
{
|
||||
//tracking area
|
||||
NSTrackingArea *trackingArea = nil;
|
||||
|
||||
//alloc/init tracking area
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
|
||||
|
||||
//add tracking area
|
||||
[self addTrackingArea:trackingArea];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when mouse-down occurs
|
||||
// ->set color to light gray or light red
|
||||
-(void)mouseDown:(NSEvent *)theEvent;
|
||||
{
|
||||
//mouse down/over color
|
||||
NSColor* color = nil;
|
||||
|
||||
//set flag
|
||||
self.mouseDown = YES;
|
||||
|
||||
//flagged files
|
||||
// ->make em red!
|
||||
if( (nil != self.fileObj.vtInfo) &&
|
||||
(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
color = [NSColor colorWithCalibratedRed:(255/255.0f) green:(1.0/255.0f) blue:(1.0/255.0f) alpha:0.5];
|
||||
}
|
||||
//non-flagged files
|
||||
// ->just gray
|
||||
else
|
||||
{
|
||||
//gray
|
||||
color = [NSColor lightGrayColor];
|
||||
}
|
||||
|
||||
//set string
|
||||
[self setAttributedTitle:setStringColor(self.attributedTitle, color)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when mouse-up occurs
|
||||
// ->reset color to gray or red and trigger mouse click logic (if necessary)
|
||||
-(void)mouseUp:(NSEvent *)theEvent;
|
||||
{
|
||||
//mouse up color
|
||||
NSColor* color = nil;
|
||||
|
||||
//shoud treat at click?
|
||||
// ->mouse up inside in non-disabled button
|
||||
if( (YES == self.isEnabled) &&
|
||||
(YES != self.mouseExit) )
|
||||
{
|
||||
//show virus total window
|
||||
[self.delegate performSelector:@selector(showVTInfo:) withObject:self];
|
||||
}
|
||||
|
||||
//reset flag
|
||||
self.mouseDown = NO;
|
||||
|
||||
//flagged files
|
||||
// ->make em red!
|
||||
if( (nil != self.fileObj.vtInfo) &&
|
||||
(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
color = [NSColor redColor];
|
||||
}
|
||||
//non-flagged files
|
||||
// ->just black
|
||||
else
|
||||
{
|
||||
//gray
|
||||
color = [NSColor blackColor];
|
||||
}
|
||||
|
||||
//set string
|
||||
[self setAttributedTitle:setStringColor(self.attributedTitle, color)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when mouse enters
|
||||
// ->set mouse over color
|
||||
-(void)mouseEntered:(NSEvent*)theEvent
|
||||
{
|
||||
//mouse entered color
|
||||
NSColor* color = nil;
|
||||
|
||||
//set flag
|
||||
self.mouseExit = NO;
|
||||
|
||||
//flagged files
|
||||
// ->make em red!
|
||||
if( (nil != self.fileObj.vtInfo) &&
|
||||
(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (lightish red)
|
||||
color = [NSColor colorWithCalibratedRed:(255/255.0f) green:(1.0/255.0f) blue:(1.0/255.0f) alpha:0.66];
|
||||
}
|
||||
//non-flagged files
|
||||
// ->just black
|
||||
else
|
||||
{
|
||||
//gray
|
||||
color = [NSColor grayColor];
|
||||
}
|
||||
|
||||
//set string
|
||||
[self setAttributedTitle:setStringColor(self.attributedTitle, color)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when mouse exits
|
||||
// ->reset color to black or red
|
||||
-(void)mouseExited:(NSEvent*)theEvent
|
||||
{
|
||||
//mouse exit color
|
||||
NSColor* color = nil;
|
||||
|
||||
//set flag
|
||||
self.mouseExit = YES;
|
||||
|
||||
//check if mouse is down
|
||||
// ->set color to gray/lightish red
|
||||
if(YES == self.mouseDown)
|
||||
{
|
||||
//flagged files
|
||||
// ->make em red!
|
||||
if( (nil != self.fileObj.vtInfo) &&
|
||||
(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (lightish red)
|
||||
color = [NSColor colorWithCalibratedRed:(255/255.0f) green:(1.0/255.0f) blue:(1.0/255.0f) alpha:0.66];
|
||||
}
|
||||
//non-flagged files
|
||||
// ->just black
|
||||
else
|
||||
{
|
||||
//gray
|
||||
color = [NSColor grayColor];
|
||||
}
|
||||
}
|
||||
//mouse is up
|
||||
// ->reset color to black/red
|
||||
else
|
||||
{
|
||||
//flagged files
|
||||
// ->make em red!
|
||||
if( (nil != self.fileObj.vtInfo) &&
|
||||
(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue]) )
|
||||
{
|
||||
//set color (light red)
|
||||
color = [NSColor redColor];
|
||||
}
|
||||
//non-flagged files
|
||||
// ->just black
|
||||
else
|
||||
{
|
||||
//gray
|
||||
color = [NSColor blackColor];
|
||||
}
|
||||
}
|
||||
|
||||
//set string
|
||||
[self setAttributedTitle:setStringColor(self.attributedTitle, color)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// VTInfoWindow.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/29/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
@class File;
|
||||
@class HyperlinkTextField;
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface VTInfoWindowController : NSWindowController
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* PROPERTIES */
|
||||
|
||||
//window controller
|
||||
@property(nonatomic, strong)VTInfoWindowController *windowController;
|
||||
|
||||
//file object
|
||||
@property(nonatomic, retain)Binary* fileObj;
|
||||
|
||||
//row index
|
||||
@property NSUInteger rowIndex;
|
||||
|
||||
//properties in window
|
||||
@property (weak) IBOutlet NSTextField *unknownFile;
|
||||
|
||||
@property (weak) IBOutlet NSTextField *fileNameLabel;
|
||||
@property (weak) IBOutlet HyperlinkTextField *fileName;
|
||||
|
||||
@property (weak) IBOutlet NSTextField *detectionRatioLabel;
|
||||
@property (weak) IBOutlet NSTextField *detectionRatio;
|
||||
|
||||
@property (weak) IBOutlet NSTextField *analysisURLLabel;
|
||||
@property (weak) IBOutlet NSTextField *analysisURL;
|
||||
|
||||
@property (weak) IBOutlet NSButton *closeButton;
|
||||
|
||||
@property (weak) IBOutlet NSButton *submitButton;
|
||||
@property (weak) IBOutlet NSProgressIndicator *progressIndicator;
|
||||
@property (strong) IBOutlet NSView *overlayView;
|
||||
@property (weak) IBOutlet NSTextField *statusMsg;
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//init method
|
||||
// ->save item and load nib
|
||||
-(id)initWithItem:(File*)selectedItem rowIndex:(NSUInteger)itemRowIndex;
|
||||
|
||||
//'submit' button handler
|
||||
-(IBAction)vtButtonHandler:(id)sender;
|
||||
|
||||
//'close' button handler
|
||||
-(IBAction)closeButtonHandler:(id)sender;
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,444 @@
|
||||
//
|
||||
// VTInfoWindow.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/29/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "File.h"
|
||||
#import "Consts.h"
|
||||
#import "Utilities.h"
|
||||
#import "VirusTotal.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "VTInfoWindowController.h"
|
||||
#import "3rdParty/HyperlinkTextField.h"
|
||||
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@interface VTInfoWindowController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation VTInfoWindowController
|
||||
|
||||
@synthesize rowIndex;
|
||||
@synthesize windowController;
|
||||
|
||||
|
||||
//init method
|
||||
// ->save item and load nib
|
||||
-(id)initWithItem:(File*)selectedItem rowIndex:(NSUInteger)itemRowIndex
|
||||
{
|
||||
self = [super init];
|
||||
if(nil != self)
|
||||
{
|
||||
//load nib
|
||||
self.windowController = [[VTInfoWindowController alloc] initWithWindowNibName:@"VTInfoWindow"];
|
||||
|
||||
//save item
|
||||
self.windowController.fileObj = selectedItem;
|
||||
|
||||
//save row index
|
||||
self.windowController.rowIndex = itemRowIndex;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//automatically invoked
|
||||
// ->make it white
|
||||
-(void)windowDidLoad
|
||||
{
|
||||
//super
|
||||
[super windowDidLoad];
|
||||
|
||||
//make it modal
|
||||
//[[NSApplication sharedApplication] runModalForWindow:self.window];
|
||||
|
||||
//make white
|
||||
[self.window setBackgroundColor: NSColor.whiteColor];
|
||||
|
||||
//make close button selected
|
||||
[self.window makeFirstResponder:self.closeButton];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically called when nib is loaded
|
||||
// ->save self into iVar, and center window
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
//configure UI
|
||||
[self configure];
|
||||
|
||||
//center
|
||||
[self.window center];
|
||||
}
|
||||
|
||||
//configure window
|
||||
// ->add item's attributes (name, path, etc.)
|
||||
-(void)configure
|
||||
{
|
||||
//flag
|
||||
BOOL isKnown = NO;
|
||||
|
||||
//detection ratio
|
||||
NSString* vtDetectionRatio = nil;
|
||||
|
||||
//color
|
||||
NSColor* textColor = nil;
|
||||
|
||||
//get status
|
||||
if(nil != self.fileObj.vtInfo[VT_RESULTS_URL])
|
||||
{
|
||||
//known
|
||||
isKnown = YES;
|
||||
}
|
||||
|
||||
//file status (known/unknown)
|
||||
if(YES == isKnown)
|
||||
{
|
||||
//default color to black
|
||||
textColor = [NSColor blackColor];
|
||||
|
||||
//set color to red if its flagged
|
||||
if(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue])
|
||||
{
|
||||
//red
|
||||
textColor = [NSColor redColor];
|
||||
}
|
||||
|
||||
//generate detection ratio
|
||||
vtDetectionRatio = [NSString stringWithFormat:@"%lu/%lu", (unsigned long)[self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue], (unsigned long)[self.fileObj.vtInfo[VT_RESULTS_TOTAL] unsignedIntegerValue]];
|
||||
|
||||
//set name
|
||||
[self.fileName setStringValue:self.fileObj.name];
|
||||
|
||||
//set color
|
||||
self.fileName.textColor = textColor;
|
||||
|
||||
//detection ratio
|
||||
[self.detectionRatio setStringValue:vtDetectionRatio];
|
||||
|
||||
//set color
|
||||
self.detectionRatio.textColor = textColor;
|
||||
|
||||
//analysis url
|
||||
[self.analysisURL setStringValue:@"VirusTotal report"];
|
||||
|
||||
//make analyis url a hyperlink
|
||||
makeTextViewHyperlink(self.analysisURL, [NSURL URLWithString:self.fileObj.vtInfo[VT_RESULTS_URL]]);
|
||||
|
||||
//set 'submit' button text to 'rescan'
|
||||
self.submitButton.title = @"rescan?";
|
||||
}
|
||||
//unknown file
|
||||
else
|
||||
{
|
||||
//hide file name label
|
||||
self.fileNameLabel.hidden = YES;
|
||||
|
||||
//hide file name
|
||||
self.fileName.hidden = YES;
|
||||
|
||||
//hide detection ratio label
|
||||
self.detectionRatioLabel.hidden = YES;
|
||||
|
||||
//hide detection ratio
|
||||
self.detectionRatio.hidden = YES;
|
||||
|
||||
//hide analysis url label
|
||||
self.analysisURLLabel.hidden = YES;
|
||||
|
||||
//hide analysis url
|
||||
self.analysisURL.hidden = YES;
|
||||
|
||||
//set unknown file msg
|
||||
[self.unknownFile setStringValue:[NSString stringWithFormat:@"no results found for '%@'", self.fileObj.name]];
|
||||
|
||||
//show 'unknown file' msg
|
||||
self.unknownFile.hidden = NO;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'close'
|
||||
// ->just close window
|
||||
-(IBAction)closeButtonHandler:(id)sender
|
||||
{
|
||||
//close
|
||||
[self.window close];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when window is closing
|
||||
// ->tell OS that we are done with window so it can (now) be freed
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
//make un-modal
|
||||
//[[NSApplication sharedApplication] stopModal];
|
||||
|
||||
//stop spinner
|
||||
// ->will hide too
|
||||
[self.progressIndicator stopAnimation:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//automatically invoked when user clicks 'rescan'/'submit'
|
||||
// ->rescan or upload to VT!
|
||||
-(IBAction)vtButtonHandler:(id)sender
|
||||
{
|
||||
//VT object
|
||||
VirusTotal* vtObj = nil;
|
||||
|
||||
//result(s) from VT
|
||||
__block NSDictionary* result = nil;
|
||||
|
||||
//analyis URL
|
||||
NSMutableAttributedString* hyperlinkString = nil;
|
||||
|
||||
//VT scan ID
|
||||
__block NSString* scanID = nil;
|
||||
|
||||
//alloc/init VT obj
|
||||
vtObj = [[VirusTotal alloc] init];
|
||||
|
||||
//disable button
|
||||
((NSButton*)sender).enabled = NO;
|
||||
|
||||
//disable close button
|
||||
self.closeButton.enabled = NO;
|
||||
|
||||
//get current string
|
||||
hyperlinkString = [self.analysisURL.attributedStringValue mutableCopy];
|
||||
|
||||
//start editing
|
||||
[hyperlinkString beginEditing];
|
||||
|
||||
//remove url/link
|
||||
[hyperlinkString removeAttribute:NSLinkAttributeName range:NSMakeRange(0, [hyperlinkString length])];
|
||||
|
||||
//done editing
|
||||
[hyperlinkString endEditing];
|
||||
|
||||
//set text
|
||||
// ->will look the same, but the URL will be disabled!
|
||||
[self.analysisURL setAttributedStringValue:hyperlinkString];
|
||||
|
||||
//pre-req
|
||||
[self.overlayView setWantsLayer:YES];
|
||||
|
||||
//set overlay's view color to black
|
||||
self.overlayView.layer.backgroundColor = [NSColor whiteColor].CGColor;
|
||||
|
||||
//make it semi-transparent
|
||||
self.overlayView.alphaValue = 0.85;
|
||||
|
||||
//show it
|
||||
self.overlayView.hidden = NO;
|
||||
|
||||
//show spinner
|
||||
self.progressIndicator.hidden = NO;
|
||||
|
||||
//animate it
|
||||
[self.progressIndicator startAnimation:nil];
|
||||
|
||||
//rescan file?
|
||||
if(YES == [((NSButton*)sender).title isEqualToString:@"rescan?"])
|
||||
{
|
||||
//set status msg
|
||||
[self.statusMsg setStringValue:[NSString stringWithFormat:@"submitting re-scan request for %@", self.fileObj.name]];
|
||||
|
||||
//show status msg
|
||||
self.statusMsg.hidden = NO;
|
||||
|
||||
//submit rescan request in background
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
//make request to VT
|
||||
result = [vtObj reScan:self.fileObj];
|
||||
|
||||
//got result
|
||||
// ->update UI and launch browswer to show report
|
||||
if(nil != result)
|
||||
{
|
||||
//grab scan ID
|
||||
// ->need this for (re)queries
|
||||
scanID = result[VT_RESULTS_SCANID];
|
||||
|
||||
/*
|
||||
|
||||
//if file was flagged
|
||||
// ->remove it from list of plugin's flagged
|
||||
if(0 != [self.fileObj.vtInfo[VT_RESULTS_POSITIVES] unsignedIntegerValue])
|
||||
{
|
||||
//sync
|
||||
// ->since array will be reset if user clicks 'stop' scan
|
||||
@synchronized(self.fileObj.plugin.flaggedItems)
|
||||
{
|
||||
//remove
|
||||
[self.fileObj.plugin.flaggedItems removeObject:self.fileObj];
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//remove file's VT info (since it'd now out of date)
|
||||
self.fileObj.vtInfo = nil;
|
||||
|
||||
//with a scan id can re-query VT
|
||||
// ->will update VT button in UI once results are retrieved
|
||||
if(nil != scanID)
|
||||
{
|
||||
//kick off task to re-query VT
|
||||
// ->wait 60 seconds though to give VT servers some time to process
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[vtObj getInfoForItem:self.fileObj scanID:scanID rowIndex:self.rowIndex];
|
||||
});
|
||||
}
|
||||
|
||||
//ask app delegate to update item in table
|
||||
// ->will change the item's VT status to ... (pending)
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) itemProcessed:self.fileObj rowIndex:self.rowIndex];
|
||||
|
||||
//nap so user can see msg 'submitting' msg
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//update status msg
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//update
|
||||
[self.statusMsg setStringValue:@"request submitted"];
|
||||
|
||||
});
|
||||
|
||||
//nap so user can see msg
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//launch browser to show rew report
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:result[@"permalink"]]];
|
||||
|
||||
//wait to browser is up and happy
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//close window
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//close
|
||||
[self.window close];
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//error
|
||||
else
|
||||
{
|
||||
//show error msg
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"failed to submit request :("];
|
||||
|
||||
//stop activity indicator
|
||||
[self.progressIndicator stopAnimation:nil];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//submit file
|
||||
else
|
||||
{
|
||||
//set status msg
|
||||
[self.statusMsg setStringValue:[NSString stringWithFormat:@"submitting %@", self.fileObj.name]];
|
||||
|
||||
//show status msg
|
||||
self.statusMsg.hidden = NO;
|
||||
|
||||
//submit rescan request in background
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
//submit file to VT
|
||||
result = [vtObj submit:self.fileObj];
|
||||
|
||||
// ->need this for (re)queries
|
||||
scanID = result[VT_RESULTS_SCANID];
|
||||
|
||||
//reset file's VT info
|
||||
self.fileObj.vtInfo = nil;
|
||||
|
||||
//with a scan id can query VT
|
||||
// ->will update VT button in UI once results are retrieved
|
||||
if(nil != scanID)
|
||||
{
|
||||
//kick off task to re-query VT
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[vtObj getInfoForItem:self.fileObj scanID:scanID rowIndex:self.rowIndex];
|
||||
});
|
||||
}
|
||||
|
||||
//got response
|
||||
// ->update UI and launch browswer to show report
|
||||
if(nil != result)
|
||||
{
|
||||
//ask app delegate to update item in table
|
||||
// ->will change the item's VT status to ... (pending)
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) itemProcessed:self.fileObj rowIndex:self.rowIndex];
|
||||
|
||||
//update status msg
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//update
|
||||
[self.statusMsg setStringValue:@"file submitted"];
|
||||
|
||||
});
|
||||
|
||||
//nap so user can see msg
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//launch browser to show rew report
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:result[@"permalink"]]];
|
||||
|
||||
//wait to browser is up and happy
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
|
||||
//close window
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//close
|
||||
[self.window close];
|
||||
|
||||
});
|
||||
|
||||
}//got result
|
||||
|
||||
//error
|
||||
else
|
||||
{
|
||||
//show error msg
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
|
||||
//update status msg
|
||||
[self.statusMsg setStringValue:@"failed to submit request :("];
|
||||
|
||||
//stop activity indicator
|
||||
[self.progressIndicator stopAnimation:nil];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// VirusTotal.h
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/8/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface VirusTotal : NSObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
//thread function
|
||||
// ->runs in the background to get virus total info about a plugin's items
|
||||
//-(void)getInfo:(PluginBase*)plugin;
|
||||
|
||||
//make the (POST)query to VT
|
||||
-(NSDictionary*)postRequest:(NSURL*)url parameters:(id)params;
|
||||
|
||||
//submit a file to VT
|
||||
-(NSDictionary*)submit:(File*)fileObj;
|
||||
|
||||
//submit a rescan request
|
||||
-(NSDictionary*)reScan:(File*)fileObj;
|
||||
|
||||
//process results
|
||||
// ->updates items (found, detection ratio, etc)
|
||||
-(void)processResults:(NSArray*)items results:(NSDictionary*)results;
|
||||
|
||||
//get info for a single item
|
||||
// ->will callback into AppDelegate to reload plugin
|
||||
-(void)getInfoForItem:(File*)fileObj scanID:(NSString*)scanID rowIndex:(NSUInteger)rowIndex;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,541 @@
|
||||
//
|
||||
// VirusTotal.m
|
||||
// KnockKnock
|
||||
//
|
||||
// Created by Patrick Wardle on 3/8/15.
|
||||
// Copyright (c) 2015 Objective-See. All rights reserved.
|
||||
//
|
||||
|
||||
#import "File.h"
|
||||
#import "Consts.h"
|
||||
#import "ItemBase.h"
|
||||
#import "VirusTotal.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation VirusTotal
|
||||
|
||||
/*
|
||||
//thread function
|
||||
// ->runs in the background to get virus total info about a plugin's items
|
||||
-(void)getInfo:(PluginBase*)plugin
|
||||
{
|
||||
//plugin file items
|
||||
// ->in dictionary w/ SHA1 hash as key
|
||||
NSMutableDictionary* uniqueItems = nil;
|
||||
|
||||
//File object
|
||||
File* item = nil;
|
||||
|
||||
//item data
|
||||
NSMutableDictionary* itemData = nil;
|
||||
|
||||
//items
|
||||
NSMutableArray* items = nil;
|
||||
|
||||
//VT query URL
|
||||
NSURL* queryURL = nil;
|
||||
|
||||
//results
|
||||
NSDictionary* results = nil;
|
||||
|
||||
//alloc dictionary for plugin file items
|
||||
uniqueItems = [NSMutableDictionary dictionary];
|
||||
|
||||
//alloc list for items
|
||||
items = [NSMutableArray array];
|
||||
|
||||
//init query URL
|
||||
queryURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", VT_QUERY_URL, VT_API_KEY]];
|
||||
|
||||
//sync
|
||||
// ->since array will be reset if user clicks 'stop' scan
|
||||
@synchronized(plugin.allItems)
|
||||
{
|
||||
|
||||
//place all plugin file items into dictionary
|
||||
// ->key: hash, filter's out dups for queries
|
||||
for(ItemBase* item in plugin.allItems)
|
||||
{
|
||||
//skip non-file items
|
||||
if(YES != [item isKindOfClass:[File class]])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//skip item's without hashes
|
||||
// ...not sure how this could ever happen
|
||||
if(nil == ((File*)item).hashes[KEY_HASH_SHA1])
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
}
|
||||
|
||||
//add item
|
||||
uniqueItems[((File*)item).hashes[KEY_HASH_SHA1]] = item;
|
||||
}
|
||||
|
||||
}//sync
|
||||
|
||||
//iterate over all hashes
|
||||
// ->create item dictionary (JSON), and add it to list
|
||||
for(NSString* itemKey in uniqueItems)
|
||||
{
|
||||
//alloc item data
|
||||
itemData = [NSMutableDictionary dictionary];
|
||||
|
||||
//exit if thread was cancelled
|
||||
// ->i.e. user pressed 'stop' scan
|
||||
if(YES == [[NSThread currentThread] isCancelled])
|
||||
{
|
||||
//exit
|
||||
[NSThread exit];
|
||||
}
|
||||
|
||||
//extract item
|
||||
item = uniqueItems[itemKey];
|
||||
|
||||
//auto start location
|
||||
itemData[@"autostart_location"] = plugin.name;
|
||||
|
||||
//set item name
|
||||
itemData[@"autostart_entry"] = item.name;
|
||||
|
||||
//set item path
|
||||
itemData[@"image_path"] = item.path;
|
||||
|
||||
//set hash
|
||||
itemData[@"hash"] = item.hashes[KEY_HASH_SHA1];
|
||||
|
||||
//set creation times
|
||||
itemData[@"creation_datetime"] = [item.attributes.fileCreationDate description];
|
||||
|
||||
//add item info to list
|
||||
[items addObject:itemData];
|
||||
|
||||
//less then 25 items
|
||||
// ->just keep collecting items
|
||||
if(VT_MAX_QUERY_COUNT != items.count)
|
||||
{
|
||||
//next
|
||||
continue;
|
||||
}
|
||||
|
||||
//make query to VT
|
||||
results = [self postRequest:queryURL parameters:items];
|
||||
if(nil != results)
|
||||
{
|
||||
//process results
|
||||
[self processResults:plugin.allItems results:results];
|
||||
}
|
||||
|
||||
//remove all items
|
||||
// ->since they've been processed
|
||||
[items removeAllObjects];
|
||||
}
|
||||
|
||||
//process any remaining items
|
||||
if(0 != items.count)
|
||||
{
|
||||
//query virus total
|
||||
results = [self postRequest:queryURL parameters:items];
|
||||
if(nil != results)
|
||||
{
|
||||
//process results
|
||||
[self processResults:plugin.allItems results:results];
|
||||
}
|
||||
}
|
||||
|
||||
//exit if thread was cancelled
|
||||
// ->i.e. user pressed 'stop' scan
|
||||
if(YES == [[NSThread currentThread] isCancelled])
|
||||
{
|
||||
//exit
|
||||
[NSThread exit];
|
||||
}
|
||||
|
||||
//tell UI all plugin's items have all be processed
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) itemsProcessed:plugin];
|
||||
|
||||
return;
|
||||
}
|
||||
*/
|
||||
//get VT info for a single item
|
||||
// ->will then callback into AppDelegate to reload item in UI
|
||||
-(void)getInfoForItem:(Binary*)fileObj scanID:(NSString*)scanID rowIndex:(NSUInteger)rowIndex
|
||||
{
|
||||
//VT query URL
|
||||
NSURL* queryURL = nil;
|
||||
|
||||
//results
|
||||
NSDictionary* results = nil;
|
||||
|
||||
//init query URL
|
||||
queryURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?apikey=%@&resource=%@", VT_REQUERY_URL, VT_API_KEY, scanID]];
|
||||
|
||||
//make queries until response is recieved
|
||||
while(YES)
|
||||
{
|
||||
//make query to VT
|
||||
results = [self postRequest:queryURL parameters:nil];
|
||||
|
||||
//check if scan is complete
|
||||
if( (nil != results) &&
|
||||
(1 == [results[VT_RESULTS_RESPONSE] integerValue]) )
|
||||
{
|
||||
//save result
|
||||
fileObj.vtInfo = results;
|
||||
|
||||
//if its flagged save in File's plugin
|
||||
if(0 != [results[VT_RESULTS_POSITIVES] unsignedIntegerValue])
|
||||
{
|
||||
/*
|
||||
//sync
|
||||
// ->since array will be reset if user clicks 'stop' scan
|
||||
@synchronized(fileObj.plugin.flaggedItems)
|
||||
{
|
||||
//save
|
||||
[fileObj.plugin.flaggedItems addObject:fileObj];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//callback up into UI to reload item
|
||||
[((AppDelegate*)[[NSApplication sharedApplication] delegate]) itemProcessed:fileObj rowIndex:rowIndex];
|
||||
|
||||
//exit loop
|
||||
break;
|
||||
}
|
||||
|
||||
//nap
|
||||
[NSThread sleepForTimeInterval:60.0f];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//make the (POST)query to VT
|
||||
-(NSDictionary*)postRequest:(NSURL*)url parameters:(id)params
|
||||
{
|
||||
//results
|
||||
NSDictionary* results = nil;
|
||||
|
||||
//request
|
||||
NSMutableURLRequest *request = nil;
|
||||
|
||||
//post data
|
||||
// ->JSON'd items
|
||||
NSData* postData = nil;
|
||||
|
||||
//error var
|
||||
NSError* error = nil;
|
||||
|
||||
//data from VT
|
||||
NSData* vtData = nil;
|
||||
|
||||
//response (HTTP) from VT
|
||||
NSURLResponse* httpResponse = nil;
|
||||
|
||||
//alloc/init request
|
||||
request = [[NSMutableURLRequest alloc] initWithURL:url];
|
||||
|
||||
//set user agent
|
||||
[request setValue:VT_USER_AGENT forHTTPHeaderField:@"User-Agent"];
|
||||
|
||||
//serialize JSON
|
||||
if(nil != params)
|
||||
{
|
||||
//convert items to JSON'd data for POST request
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//convert items
|
||||
postData = [NSJSONSerialization dataWithJSONObject:params options:kNilOptions error:nil];
|
||||
if(nil == postData)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to convert request %@ to JSON", postData);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
//bail on exceptions
|
||||
@catch(NSException *exception)
|
||||
{
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//set content type
|
||||
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
|
||||
|
||||
//set content length
|
||||
[request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[postData length]] forHTTPHeaderField:@"Content-length"];
|
||||
|
||||
//add POST data
|
||||
[request setHTTPBody:postData];
|
||||
}
|
||||
|
||||
//set method type
|
||||
[request setHTTPMethod:@"POST"];
|
||||
|
||||
//send request
|
||||
// ->synchronous, so will block
|
||||
vtData = [NSURLConnection sendSynchronousRequest:request returningResponse:&httpResponse error:&error];
|
||||
|
||||
//sanity check(s)
|
||||
if( (nil == vtData) ||
|
||||
(nil != error) ||
|
||||
(200 != (long)[(NSHTTPURLResponse *)httpResponse statusCode]) )
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to query VirusTotal (%@, %@)", error, httpResponse);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//serialize response into NSData obj
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//serialized
|
||||
results = [NSJSONSerialization JSONObjectWithData:vtData options:kNilOptions error:nil];
|
||||
}
|
||||
//bail on any exceptions
|
||||
@catch (NSException *exception)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: converting response %@ to JSON threw %@", vtData, exception);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
if(nil == results)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to convert response %@ to JSON", vtData);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
//submit a file to VT
|
||||
-(NSDictionary*)submit:(File*)fileObj
|
||||
{
|
||||
//results
|
||||
NSDictionary* results = nil;
|
||||
|
||||
//submit URL
|
||||
NSURL* submitURL = nil;
|
||||
|
||||
//request
|
||||
NSMutableURLRequest *request = nil;
|
||||
|
||||
//body of request
|
||||
NSMutableData* body = nil;
|
||||
|
||||
//file data
|
||||
NSData* fileContents = nil;
|
||||
|
||||
//error var
|
||||
NSError* error = nil;
|
||||
|
||||
//data from Vt
|
||||
NSData* vtData = nil;
|
||||
|
||||
//response (HTTP) from VT
|
||||
NSURLResponse* httpResponse = nil;
|
||||
|
||||
//init submit URL
|
||||
submitURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?apikey=%@&resource=%@", VT_SUBMIT_URL, VT_API_KEY, fileObj.hashes[KEY_HASH_MD5]]];
|
||||
|
||||
//init request
|
||||
request = [[NSMutableURLRequest alloc] initWithURL:submitURL];
|
||||
|
||||
//set boundary string
|
||||
NSString *boundary = @"qqqq___knockknock___qqqq";
|
||||
|
||||
//set HTTP method (POST)
|
||||
[request setHTTPMethod:@"POST"];
|
||||
|
||||
//set the HTTP header 'Content-type' to the boundary
|
||||
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField: @"Content-Type"];
|
||||
|
||||
//set HTTP header, 'User-Agent'
|
||||
[request setValue:VT_USER_AGENT forHTTPHeaderField:@"User-Agent"];
|
||||
|
||||
//init body
|
||||
body = [NSMutableData data];
|
||||
|
||||
//load file into memory
|
||||
fileContents = [NSData dataWithContentsOfFile:fileObj.pathForFinder];
|
||||
|
||||
//sanity check
|
||||
if(nil == fileContents)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to load %@ into memory for submission", fileObj.path);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//append boundary
|
||||
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
//append 'Content-Disposition' file name, etc
|
||||
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileObj.name] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
//append 'Content-Type'
|
||||
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
//append file's contents
|
||||
[body appendData:fileContents];
|
||||
|
||||
//append '\r\n'
|
||||
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
//append final boundary
|
||||
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
//set body
|
||||
[request setHTTPBody:body];
|
||||
|
||||
//set content length
|
||||
[request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[body length]] forHTTPHeaderField:@"Content-length"];
|
||||
|
||||
//send request
|
||||
// ->synchronous, so will block
|
||||
vtData = [NSURLConnection sendSynchronousRequest:request returningResponse:&httpResponse error:&error];
|
||||
|
||||
//sanity check(s)
|
||||
if( (nil == vtData) ||
|
||||
(nil != error) ||
|
||||
(200 != (long)[(NSHTTPURLResponse *)httpResponse statusCode]) )
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to query VirusTotal (%@, %@)", error, httpResponse);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//serialize response into NSData obj
|
||||
// ->wrap since we are serializing JSON
|
||||
@try
|
||||
{
|
||||
//serialize
|
||||
results = [NSJSONSerialization JSONObjectWithData:vtData options:kNilOptions error:nil];
|
||||
}
|
||||
//bail on any exceptions
|
||||
@catch (NSException *exception)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: converting response %@ to JSON threw %@", vtData, exception);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//sanity check
|
||||
if(nil == results)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to convert response %@ to JSON", vtData);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
//submit a rescan request
|
||||
-(NSDictionary*)reScan:(File*)fileObj
|
||||
{
|
||||
//result data
|
||||
NSDictionary* result = nil;
|
||||
|
||||
//scan url
|
||||
NSURL* reScanURL = nil;
|
||||
|
||||
//init scan url
|
||||
reScanURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?apikey=%@&resource=%@", VT_RESCAN_URL, VT_API_KEY, fileObj.hashes[KEY_HASH_MD5]]];
|
||||
|
||||
//make request to VT
|
||||
result = [self postRequest:reScanURL parameters:nil];
|
||||
if(nil == result)
|
||||
{
|
||||
//err msg
|
||||
NSLog(@"OBJECTIVE-SEE ERROR: failed to re-scan %@", fileObj.name);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//process results
|
||||
// ->save VT info into each File obj and all flagged files
|
||||
-(void)processResults:(NSArray*)items results:(NSDictionary*)results
|
||||
{
|
||||
//process all results
|
||||
// ->save VT result dictionary into File obj
|
||||
for(NSDictionary* result in results[VT_RESULTS])
|
||||
{
|
||||
//sync
|
||||
// ->since array will be reset if user clicks 'stop' scan
|
||||
@synchronized(items)
|
||||
{
|
||||
|
||||
//find all items that match
|
||||
// ->might be dupes, which is fine
|
||||
for(Binary* item in items)
|
||||
{
|
||||
//for matches, save vt info
|
||||
if(YES == [result[@"hash"] isEqualToString:item.hashes[KEY_HASH_SHA1]])
|
||||
{
|
||||
//save
|
||||
item.vtInfo = result;
|
||||
|
||||
//if its flagged save in File's plugin
|
||||
if(0 != [result[VT_RESULTS_POSITIVES] unsignedIntegerValue])
|
||||
{
|
||||
/*
|
||||
//sync
|
||||
// ->since array will be reset if user clicks 'stop' scan
|
||||
@synchronized(item.plugin.flaggedItems)
|
||||
{
|
||||
//save
|
||||
[item.plugin.flaggedItems addObject:item];
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}//sync
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
KNOCKKNOCK CHANGELOG
|
||||
|
||||
VERSION 1.0.0 (4/23/2015)
|
||||
initial release
|
||||
|
||||
|
||||
VERSION 1.1.0 (4/24/2015)
|
||||
added plugin to scan for Authorization Plugins
|
||||
fixed NSJSONSerialization bug (parsing Google Chrome plugins)
|
||||
|
||||
|
||||
VERSION 1.2.0 (4/25/2015)
|
||||
added DYLD_INSERT_LIBRARIES plugin
|
||||
browser extensions plugin now supports enumerating Opera plugins
|
||||
browser extensions plugin improved to enumerate Google Chrome with multiple profiles
|
||||
increased timeouts for making a popups modal (to avoid NSInternalInconsistencyException issues)
|
||||
fixed nil dictionary insertion when processing Safari extensions with missin 'Bundle Identifier'
|
||||
|
||||
|
||||
VERSION 1.2.1 (4/25/2015)
|
||||
improved DYLD_INSERT_LIBRARIES plugin to report path to applications' Info.plist as string (instead of URL)
|
||||
fixed issue in DYLD_INSERT_LIBRARIES plugin, where NSInvalidArgumentException would result if enviro var was string
|
||||
|
||||
|
||||
VERSION 1.2.2 (4/28/2015)
|
||||
browser extensions plugin now supports enumerating extensions in older versions of Safari
|
||||
improved JSON output & fixed bug when saving JSON when file hash or signature was nil
|
||||
recompiled with updated/improved (shared) MachO parser
|
||||
fixed issue where on multiple scans, result popup was not properly updated
|
||||
improved UI to display item's plist (when applicable) into the item's row
|
||||
listed items in item table are now selectable
|
||||
|
||||
VERSION 1.2.3 (4/30/2015)
|
||||
improved VirusTotal logic (e.g. when an signed OS file was flagged)
|
||||
tweaked UI to be more compatible with OS X 10.9
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<development version="5000" identifier="xcode"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="494" id="495"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<menu title="AMainMenu" systemMenu="main" id="29">
|
||||
<items>
|
||||
<menuItem title="KnockKnock" id="56">
|
||||
<menu key="submenu" title="KnockKnock" systemMenu="apple" id="57">
|
||||
<items>
|
||||
<menuItem title="About" id="134">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="about:" target="494" id="1Av-a0-4RW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Preferences" tag="1" id="Cd7-Xq-jnw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="showPreferences:" target="494" id="h1a-NR-0PY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="149">
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</menuItem>
|
||||
<menuItem title="Quit" tag="2" keyEquivalent="q" id="136">
|
||||
<connections>
|
||||
<action selector="terminate:" target="-3" id="449"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES"/>
|
||||
<rect key="contentRect" x="0.0" y="0.0" width="1353" height="650"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<value key="minSize" type="size" width="1000" height="650"/>
|
||||
<value key="maxSize" type="size" width="2000" height="650"/>
|
||||
<view key="contentView" id="372">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1353" height="650"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<progressIndicator hidden="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="839">
|
||||
<rect key="frame" x="1157" y="-146" width="32" height="32"/>
|
||||
</progressIndicator>
|
||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="745">
|
||||
<rect key="frame" x="869" y="-137" width="268" height="18"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="status..." id="748">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" red="0.20000000000000001" green="0.67450980392156867" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button ambiguous="YES" misplaced="YES" tag="1002" translatesAutoresizingMaskIntoConstraints="NO" id="HoI-FQ-vTI">
|
||||
<rect key="frame" x="640" y="4" width="29" height="32"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" image="logoApple" imagePosition="only" alignment="center" alternateImage="logoAppleBG" imageScaling="proportionallyDown" inset="2" id="3g8-vm-R7Z">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="logoButtonHandler:" target="494" id="H4C-BT-arE"/>
|
||||
</connections>
|
||||
</button>
|
||||
<segmentedControl verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gtq-gn-VPL">
|
||||
<rect key="frame" x="465" y="329" width="223" height="24"/>
|
||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="rounded" trackingMode="selectOne" id="DHY-0u-YD7">
|
||||
<font key="font" metaFont="system"/>
|
||||
<segments>
|
||||
<segment label="dylibs" width="73" selected="YES"/>
|
||||
<segment label="files" width="72" tag="1"/>
|
||||
<segment label="network" tag="2"/>
|
||||
</segments>
|
||||
</segmentedCell>
|
||||
<connections>
|
||||
<action selector="selectBottomPaneContent:" target="494" id="CQa-nn-jVf"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<searchField wantsLayer="YES" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bNA-gy-9Ta">
|
||||
<rect key="frame" x="1161" y="330" width="148" height="22"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="22" id="1yR-lY-9om"/>
|
||||
<constraint firstAttribute="width" constant="148" id="XYi-Db-Iyc"/>
|
||||
</constraints>
|
||||
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Filter" usesSingleLineMode="YES" bezelStyle="round" id="bct-8m-iWd">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
</searchField>
|
||||
<button fixedFrame="YES" tag="1001" translatesAutoresizingMaskIntoConstraints="NO" id="gSG-Nq-plb">
|
||||
<rect key="frame" x="9" y="4" width="35" height="32"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="settings" imagePosition="overlaps" alignment="center" alternateImage="settingsBG" imageScaling="proportionallyDown" inset="2" id="1TF-i7-mBn">
|
||||
<behavior key="behavior" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="showPreferences:" target="494" id="U3q-gH-jC6"/>
|
||||
</connections>
|
||||
</button>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TNF-7q-Loy" userLabel="Top Pane">
|
||||
<rect key="frame" x="0.0" y="369" width="1353" height="281"/>
|
||||
</customView>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="E4M-PF-VD0" userLabel="Bottom Pane">
|
||||
<rect key="frame" x="0.0" y="35" width="1353" height="281"/>
|
||||
<subviews>
|
||||
<progressIndicator horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" maxValue="100" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="LMT-Bu-FAk">
|
||||
<rect key="frame" x="660" y="124" width="32" height="32"/>
|
||||
</progressIndicator>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kIC-ZZ-ldy">
|
||||
<rect key="frame" x="584" y="106" width="184" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="center" title="no items found" id="LO4-i6-1es">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="centerX" secondItem="gtq-gn-VPL" secondAttribute="centerX" id="2Nh-NZ-P5p"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bNA-gy-9Ta" secondAttribute="trailing" constant="12" id="5N8-Ye-mhe"/>
|
||||
<constraint firstAttribute="centerX" secondItem="HoI-FQ-vTI" secondAttribute="centerX" constant="1" id="EcI-vS-3LG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<toolbar key="toolbar" implicitIdentifier="EAE4838B-30FD-4B21-8BE5-8564B213BE96" autosavesConfiguration="NO" displayMode="iconAndLabel" sizeMode="regular" id="qEm-Os-zrh">
|
||||
<allowedToolbarItems>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarShowColorsItem" id="RP7-Aw-wsx"/>
|
||||
<toolbarItem implicitItemIdentifier="33BA6F3A-71D3-476F-B1FA-72F899CFDCA2" label="Toolbar Item" paletteLabel="Toolbar Item" tag="-1" id="1xB-mk-PMD" customClass="TAAdaptiveSpaceItem"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarShowFontsItem" id="NU8-Nm-T2R"/>
|
||||
<toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="eEO-jq-TLG"/>
|
||||
<toolbarItem implicitItemIdentifier="146A46B5-DE4B-42D4-98E4-7C3A803AC963" label="" paletteLabel="" id="7ph-jg-soj">
|
||||
<nil key="toolTip"/>
|
||||
<size key="minSize" width="100" height="28"/>
|
||||
<size key="maxSize" width="100" height="28"/>
|
||||
<popUpButton key="view" verticalHuggingPriority="750" id="nRz-eH-T6D">
|
||||
<rect key="frame" x="0.0" y="0.0" width="100" height="28"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="l3Y-M3-yM2">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="IeP-xT-MKw">
|
||||
<items>
|
||||
<menuItem title="Flat View" tag="100" id="p1h-kw-5aA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Tree View" tag="101" id="uuF-ak-b7S">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<connections>
|
||||
<action selector="switchView:" target="494" id="1DR-jI-8ah"/>
|
||||
</connections>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="CF826839-BC2B-4FEF-898A-77DC4D2486F1" label="" paletteLabel="" id="y4u-t8-Acq">
|
||||
<nil key="toolTip"/>
|
||||
<size key="minSize" width="96" height="22"/>
|
||||
<size key="maxSize" width="119" height="22"/>
|
||||
<searchField key="view" wantsLayer="YES" verticalHuggingPriority="750" id="4Kr-b9-X6j">
|
||||
<rect key="frame" x="11" y="14" width="117" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Filter Tasks" usesSingleLineMode="YES" bezelStyle="round" id="WXx-nE-N2S">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
</searchField>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="A5784C30-D7FC-4958-875B-487768A4E610" label="" paletteLabel="" id="O1y-1z-g0u">
|
||||
<nil key="toolTip"/>
|
||||
<size key="minSize" width="38" height="17"/>
|
||||
<size key="maxSize" width="38" height="17"/>
|
||||
<textField key="view" horizontalHuggingPriority="251" verticalHuggingPriority="750" id="Pc9-qO-K4R">
|
||||
<rect key="frame" x="6" y="15" width="38" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Tasks" id="jaa-xq-WqA">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</toolbarItem>
|
||||
<toolbarItem implicitItemIdentifier="F54A1AEB-291E-4556-8B7E-D1C677012ABF" label="" paletteLabel="" image="kkText" id="UwA-pW-Mg8">
|
||||
<nil key="toolTip"/>
|
||||
<size key="minSize" width="48" height="48"/>
|
||||
<size key="maxSize" width="330" height="48"/>
|
||||
<imageView key="view" horizontalHuggingPriority="251" verticalHuggingPriority="251" id="aNo-Uq-I0N">
|
||||
<rect key="frame" x="116" y="14" width="330" height="48"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="kkText" id="hwQ-Gs-JPJ"/>
|
||||
</imageView>
|
||||
</toolbarItem>
|
||||
</allowedToolbarItems>
|
||||
<defaultToolbarItems>
|
||||
<toolbarItem reference="eEO-jq-TLG"/>
|
||||
<toolbarItem reference="1xB-mk-PMD"/>
|
||||
<toolbarItem reference="UwA-pW-Mg8"/>
|
||||
<toolbarItem reference="eEO-jq-TLG"/>
|
||||
<toolbarItem reference="7ph-jg-soj"/>
|
||||
<toolbarItem reference="y4u-t8-Acq"/>
|
||||
</defaultToolbarItems>
|
||||
</toolbar>
|
||||
<point key="canvasLocation" x="662.5" y="335"/>
|
||||
</window>
|
||||
<customObject id="494" customClass="AppDelegate">
|
||||
<connections>
|
||||
<outlet property="bottomPane" destination="E4M-PF-VD0" id="Au5-EH-OKZ"/>
|
||||
<outlet property="bottomPaneBtn" destination="gtq-gn-VPL" id="Uxg-Ab-QzA"/>
|
||||
<outlet property="bottomPaneSpinner" destination="LMT-Bu-FAk" id="a1H-Ag-GT8"/>
|
||||
<outlet property="logoButton" destination="HoI-FQ-vTI" id="bzc-wu-4Hv"/>
|
||||
<outlet property="noItemsLabel" destination="kIC-ZZ-ldy" id="nOm-8E-tZA"/>
|
||||
<outlet property="progressIndicator" destination="839" id="870"/>
|
||||
<outlet property="showPreferencesButton" destination="gSG-Nq-plb" id="MsG-Ve-uHw"/>
|
||||
<outlet property="statusText" destination="745" id="871"/>
|
||||
<outlet property="topPane" destination="TNF-7q-Loy" id="KZl-fO-P4O"/>
|
||||
<outlet property="viewSelector" destination="nRz-eH-T6D" id="1YT-Nb-K3a"/>
|
||||
<outlet property="window" destination="371" id="532"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="420" customClass="NSFontManager"/>
|
||||
<customObject id="8VH-uv-w4O" customClass="TaskTableController"/>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="85d-Tb-wMk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="38" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Label" id="TbI-kK-19h">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="kkText" width="426.48001098632812" height="85.919998168945312"/>
|
||||
<image name="logoApple" width="194" height="236"/>
|
||||
<image name="logoAppleBG" width="194" height="236"/>
|
||||
<image name="settings" width="256" height="256"/>
|
||||
<image name="settingsBG" width="256" height="256"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 3.1 KiB |