Permalink
Browse files

Boom! First commit.

  • Loading branch information...
0 parents commit 933b5f643257f41afe3dfcff1dcf09b34856b719 future committed Aug 11, 2012
@@ -0,0 +1,15 @@
+build
+doc
+*.xcodeproj/*.pbxuser
+*.xcodeproj/*.perspectivev3
+*.xcodeproj/xcuserdata
+.DS_Store
+.swp
+~.nib
+.pbxuser
+.perspective
+*.perspectivev3
+*.mode1v3
+*.xcworkspacedata
+*.xcuserstate
+*xcuserdata*
Oops, something went wrong.
@@ -0,0 +1,5 @@
+#import <Cocoa/Cocoa.h>
+
+@interface ClickableNSView : NSView
+
+@end
@@ -0,0 +1,20 @@
+#import "ClickableNSView.h"
+
+@implementation ClickableNSView
+
+- (void) mouseDown:(NSEvent*)event {
+ [super mouseDown:event];
+ switch ([event clickCount]) {
+ case 1: [self wasSingleClicked]; break;
+ }
+}
+
+- (void) wasSingleClicked {
+ [self sendNotification:WasSingleClickedNotification];
+}
+
+- (void) sendNotification:(NSString*)notificationName {
+ [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self];
+}
+
+@end
@@ -0,0 +1 @@
+extern NSString* const WasSingleClickedNotification;
@@ -0,0 +1 @@
+NSString* const WasSingleClickedNotification = @"LinkLiarWasSingleClickedNotification";
@@ -0,0 +1,26 @@
+@class MACAddresss;
+
+@interface Interface : NSObject {
+
+ NSString *BSDName;
+ NSString *displayName;
+ NSString *hardMAC;
+ NSString *kind;
+
+}
+
+// Attributes
+@property (nonatomic, assign) NSString *BSDName;
+@property (nonatomic, assign) NSString *displayName;
+@property (nonatomic, assign) NSString *hardMAC;
+@property (nonatomic, assign) NSString *kind;
+
+// Class Methods
++ (Interface*) ethernet;
++ (Interface*) wifi;
+
+// Instance Methods
+- (NSString*) softMAC;
+- (void) applyAddress:(MACAddresss*)address;
+
+@end
@@ -0,0 +1,94 @@
+#import "Interface.h"
+
+#import "MACAddresss.h"
+#import <SystemConfiguration/SystemConfiguration.h>
+
+@implementation Interface
+
+@synthesize BSDName, displayName, hardMAC, kind;
+
+/* Returns info about all available Interfaces.
+ */
++ (NSArray*) all {
+ NSMutableArray *result = [NSMutableArray new];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray *interfaces_ = (NSArray*) SCNetworkInterfaceCopyAll();
+ for (id interface_ in interfaces_) {
+ Interface* interface = [self new];
+ SCNetworkInterfaceRef interfaceRef = (SCNetworkInterfaceRef)interface_;
+ interface.BSDName = (NSString*)SCNetworkInterfaceGetBSDName(interfaceRef);
+ interface.displayName = (NSString*)SCNetworkInterfaceGetLocalizedDisplayName(interfaceRef);
+ interface.hardMAC = (NSString*)SCNetworkInterfaceGetHardwareAddressString(interfaceRef);
+ interface.kind = (NSString*)SCNetworkInterfaceGetInterfaceType(interfaceRef);
+ [result addObject:interface];
+ }
+ [pool drain];
+
+ return (NSArray*)result;
+}
+
++ (Interface*) ethernet {
+ NSArray *interfaces = [self all];
+ for (Interface *interface in interfaces) {
+ if ([interface.kind isEqualToString:@"Ethernet"] && ([interface.BSDName isEqualToString:@"en0"] || [interface.BSDName isEqualToString:@"en1"])) {
+ //DLog(@"Identified Ethernet Interface: %@", interface.BSDName);
+ return interface;
+ }
+
+ }
+ //DLog(@"Hey! You don't have a Ethernet Interface. Weird.");
+ return [self new];
+}
+
++ (Interface*) wifi {
+ NSArray *interfaces = [self all];
+
+ for (Interface *interface in interfaces) {
+ if ([interface.kind isEqualToString:@"IEEE80211"]) {
+ //DLog(@"Identified Wi-Fi Interface: %@", interface.BSDName);
+ return interface;
+ }
+ }
+ //DLog(@"Hey! You don't have a Wi-Fi Interface. Weird.");
+
+ return [self new];
+}
+
+/* This method runs "ifconfig" without superuser privileges to determine
+ * the currently assigned MAC address. It returns it as NSString.
+ */
+- (NSString*) softMAC {
+ // Getting the Task bootstrapped
+ NSTask *ifconfig = [[NSTask alloc] init];
+ NSPipe *pipe = [NSPipe pipe];
+ NSFileHandle *file = [pipe fileHandleForReading];
+
+ // Configuring the ifconfig command
+ [ifconfig setLaunchPath: @"/sbin/ifconfig"];
+ [ifconfig setArguments: [NSArray arrayWithObjects: [self BSDName], nil]];
+ [ifconfig setStandardOutput: pipe];
+ // Starting the Task
+ [ifconfig launch];
+
+ // Reading the result from stdout
+ NSData *data = [file readDataToEndOfFile];
+ NSString *cmdResult = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ // Searching for the MAC address in the result
+ NSString *currentMAC = [[[[cmdResult componentsSeparatedByString:@"ether "] lastObject] componentsSeparatedByString:@" "] objectAtIndex:0];
+ return currentMAC;
+}
+
+- (void) applyAddress:(MACAddresss*)address {
+ NSDictionary *error = [NSDictionary new];
+ NSString *command = [self changeCommandForInterface:self.BSDName usingAddress:address.string];
+ NSString *script = [[NSString new] stringByAppendingFormat:@"do shell script \"%@\" with administrator privileges", command];
+ NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script];
+ [appleScript executeAndReturnError:&error];
+}
+
+- (NSString*) changeCommandForInterface:(NSString*)interfaceBSDName usingAddress:(NSString*)address {
+ return [[NSString new] stringByAppendingFormat:@"ifconfig %@ ether %@", interfaceBSDName, address];
+}
+
+@end
@@ -0,0 +1,29 @@
+#import <PreferencePanes/PreferencePanes.h>
+
+#import "Interface.h"
+
+@interface LinkLiar : NSPreferencePane
+
+@property (assign) Interface *wifi;
+@property (assign) Interface *ethernet;
+@property (assign) NSString *editing;
+
+@property (strong) IBOutlet NSTextField *wifiNameLabel;
+@property (strong) IBOutlet NSTextField *wifiSoftMAC;
+@property (strong) IBOutlet NSTextField *ethernetNameLabel;
+@property (strong) IBOutlet NSTextField *ethernetSoftMAC;
+@property (strong) IBOutlet NSProgressIndicator *wifiSpinner;
+@property (strong) IBOutlet NSProgressIndicator *ethernetSpinner;
+@property (strong) IBOutlet NSPopover *helpPopover;
+
+@property (strong) IBOutlet NSView *wifiClickarea;
+@property (strong) IBOutlet NSView *ethernetClickarea;
+@property (strong) IBOutlet NSPopover *changePopover;
+@property (strong) IBOutlet NSTextField *addressTextField;
+@property (strong) IBOutlet NSButton *applyButton;
+
+- (IBAction) applyAddress:sender;
+- (IBAction) randomizeMACInTextField:sender;
+- (IBAction) showHelp:sender;
+
+@end
@@ -0,0 +1,115 @@
+#import "LinkLiar.h"
+
+#import "Interface.h"
+#import "MACAddresss.h"
+
+@implementation LinkLiar
+@synthesize helpPopover;
+
+@synthesize wifi, wifiNameLabel, wifiSoftMAC, wifiSpinner;
+@synthesize ethernet, ethernetNameLabel, ethernetSoftMAC, ethernetSpinner;
+@synthesize wifiClickarea, ethernetClickarea, changePopover;
+@synthesize editing, addressTextField, applyButton;
+
+- (void) mainViewDidLoad {
+ [self refreshGUI:self];
+ [self setupObservers];
+ [self randomizeMACInTextField:self];
+}
+
+- (void) refreshGUI:sender {
+ wifi = [Interface wifi];
+ ethernet = [Interface ethernet];
+ [wifiNameLabel setStringValue:[wifi.displayName stringByAppendingFormat:@" %@", wifi.BSDName]];
+ [wifiSoftMAC setStringValue:wifi.softMAC];
+ [ethernetNameLabel setStringValue:[ethernet.displayName stringByAppendingFormat:@" %@", ethernet.BSDName]];
+ [ethernetSoftMAC setStringValue:ethernet.softMAC];
+}
+
+- (void) setupObservers {
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wasSingleClickedNotification:) name:WasSingleClickedNotification object:nil];
+ [NSTimer scheduledTimerWithTimeInterval:(4) target:self selector:@selector(refreshGUI:) userInfo:nil repeats:YES];
+}
+
+- (BOOL) control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)command {
+ if (command == @selector(cancelOperation:)) {
+ editing = @"none";
+ [changePopover close];
+ }
+ return NO;
+}
+
+- (void) controlTextDidChange:(NSNotification*)notification {
+ MACAddresss *address = [MACAddresss new];
+ address.string = addressTextField.stringValue;
+ if (address.isValid) {
+ applyButton.enabled = true;
+ } else {
+ applyButton.enabled = false;
+ }
+}
+
+- (void) wasSingleClickedNotification:(NSNotification*)notification {
+ if ([notification object] == wifiClickarea) {
+ if ([changePopover isShown] && [editing isEqualToString:@"wifi"]) {
+ editing = @"none";
+ [changePopover close];
+ } else {
+ editing = @"wifi";
+ [self editWifi];
+ }
+ } else if ([notification object] == ethernetClickarea) {
+ if ([changePopover isShown] && [editing isEqualToString:@"ethernet"]) {
+ editing = @"none";
+ [changePopover close];
+ } else {
+ editing = @"ethernet";
+ [self editEthernet];
+ }
+ }
+}
+
+- (void) editWifi {
+ [changePopover showRelativeToRect:[wifiSoftMAC bounds] ofView:wifiSoftMAC preferredEdge:NSMaxYEdge];
+}
+
+- (void) editEthernet {
+ [changePopover showRelativeToRect:[ethernetSoftMAC bounds] ofView:ethernetSoftMAC preferredEdge:NSMaxYEdge];
+}
+
+- (IBAction) randomizeMACInTextField:sender {
+ [addressTextField setStringValue:[MACAddresss random]];
+}
+
+- (IBAction) showHelp:sender {
+ if ([helpPopover isShown]) {
+ [helpPopover close];
+ } else {
+ [helpPopover showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinXEdge];
+ }
+}
+
+- (IBAction) applyAddress:sender {
+ MACAddresss *address = [MACAddresss new];
+ address.string = addressTextField.stringValue;
+ if (address.isValid) {
+ if ([editing isEqualToString:@"wifi"]) {
+ [[self wifiSpinner] startAnimation:self];
+ [self doApplyAddress:address onInterface:wifi];
+ [[self wifiSpinner] stopAnimation:self];
+ } else if ([editing isEqualToString:@"ethernet"]) {
+ [[self ethernetSpinner] startAnimation:self];
+ [self doApplyAddress:address onInterface:ethernet];
+ [[self ethernetSpinner] stopAnimation:self];
+ }
+ }
+}
+
+- (void) doApplyAddress:(MACAddresss*)address onInterface:(Interface*)interface {
+ [interface applyAddress:address];
+ [changePopover close];
+ addressTextField.stringValue = address.string;
+ [self refreshGUI:self];
+}
+
+@end
@@ -0,0 +1,8 @@
+@interface MACAddresss : NSObject
+
+@property (assign) NSString *string;
+
++ (NSString*) random;
+- (BOOL) isValid;
+
+@end
@@ -0,0 +1,47 @@
+#import "MACAddresss.h"
+
+@implementation MACAddresss
+
+@synthesize string;
+
+/* Some MAC address roulette.
+ * Returns a random, full MAC address, separated by colons.
+ */
++ (NSString*) random {
+ // We will perform this with an Array that holds the HEX values
+ NSMutableArray *components = [[[NSMutableArray alloc] init] autorelease];
+ // Six times we will add something to the Array
+ for (NSInteger i = 0; i < 6; i++) {
+ // Each time we add two random HEX values combined in one NSString. E.g. "AF" or "5C"
+ NSString *component = [[[NSString alloc] initWithFormat:@"%1X%1X", arc4random() % 15, arc4random() % 15] autorelease];
+ // Please in lower case
+ [components addObject:[component lowercaseString]];
+ }
+ // Put it all together by joining the six components with colons
+ return [components componentsJoinedByString:@":"];
+}
+
+/* This method takes some junk string as input and tries to format it as MAC address
+ * separated by colons. Note that it won't check for valid characters, it will only
+ * deal with the colons. The character validity is guaranteed via the MACAddressFormatter.
+ */
+- (MACAddresss*) sanitize {
+ // Stripping all existing colons
+ string = [[self string] stringByReplacingOccurrencesOfString:@":" withString:@""];
+ // Adding fresh colons
+ NSMutableString* formatted = [[string mutableCopy] autorelease];
+ if ([formatted length] > 10) [formatted insertString:@":" atIndex:10];
+ if ([formatted length] > 8) [formatted insertString:@":" atIndex:8];
+ if ([formatted length] > 6) [formatted insertString:@":" atIndex:6];
+ if ([formatted length] > 4) [formatted insertString:@":" atIndex:4];
+ if ([formatted length] > 2) [formatted insertString:@":" atIndex:2];
+ self.string = formatted;
+ return self;
+}
+
+- (BOOL) isValid {
+ [self sanitize];
+ return [string length] == 17;
+}
+
+@end
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+@interface MACAddressFormatter : NSFormatter {}
+
+@end
Oops, something went wrong.

0 comments on commit 933b5f6

Please sign in to comment.