added password checking. Added checking for servers that quit and reopen.
Added more UI stuff. Added more more more more more. It's gonna be
HUUUUUUGEEEE!!!!
hotKeysTableView = NSTableView;
launchAtLoginCheckbox = NSButton;
launchPlayerAtLaunchCheckbox = NSButton;
+ locationTextField = NSTextField;
manualView = NSView;
menuTableView = CustomMenuTableView;
nameCheckbox = NSButton;
selectPlayerBox = NSBox;
selectPlayerSheet = NSPanel;
selectSharedPlayerButton = NSButton;
+ selectedPlayerTextField = NSTextField;
shareMenuTunesCheckbox = NSButton;
sharingTableView = NSTableView;
showOnChangeCheckbox = NSButton;
</array>
<key>IBOpenObjects</key>
<array>
- <integer>639</integer>
- <integer>634</integer>
<integer>6</integer>
</array>
<key>IBSystem Version</key>
*/
- (NSImage *)remoteIcon;
+/*!
+ * @method sharedRemoteName
+ * @abstract Returns the shared remote's name.
+ * @discussion This title is shown while the user is selecting which shared remote to use. This is for informational purposes only, should not be overridden.
+ * @result An NSString containing the name of the shared remote.
+ */
+- (NSString *)sharedRemoteName;
+
/*!
* @method begin
* @abstract Sent when the remote should begin operation.
return nil;
}
+- (NSString *)sharedRemoteName
+{
+ NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@"sharedPlayerName"];
+ if (!name)
+ name = @"MenuTunes Shared Player";
+ return name;
+}
+
- (BOOL)begin
{
return NO;
networkController = [[NetworkController alloc] init];
if ([df boolForKey:@"enableSharing"]) {
[self setServerStatus:YES];
- } else if ([df boolForKey:@"useSharedPlayer"] && [df boolForKey:@"alwaysUseSharedPlayer"]) {
- [self connectToServer];
+ } else if ([df boolForKey:@"useSharedPlayer"]) {
+ if (![self connectToServer]) {
+ [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES];
+ }
}
//Setup for notification of the remote player launching or quitting
- (BOOL)connectToServer
{
+ ITDebugLog(@"Attempting to connect to shared remote.");
//Connect
if ([networkController connectToHost:[df stringForKey:@"sharedPlayerHost"]]) {
currentRemote = [networkController sharedRemote];
[refreshTimer invalidate];
+ ITDebugLog(@"Connection successful.");
return YES;
} else {
+ ITDebugLog(@"Connection failed.");
currentRemote = [remoteArray objectAtIndex:0];
return NO;
}
- (BOOL)disconnectFromServer
{
+ ITDebugLog(@"Disconnecting from shared remote.");
//Disconnect
currentRemote = [remoteArray objectAtIndex:0];
[networkController disconnect];
return YES;
}
+- (void)checkForRemoteServer:(NSTimer *)timer
+{
+ ITDebugLog(@"Checking for remote server.");
+ if ([networkController checkForServerAtHost:[df stringForKey:@"sharedPlayerHost"]]) {
+ ITDebugLog(@"Remote server found.");
+ [timer invalidate];
+ [[StatusWindowController sharedController] showReconnectQueryWindow];
+ } else {
+ ITDebugLog(@"Remote server not found.");
+ }
+}
+
- (void)networkError:(NSException *)exception
{
ITDebugLog(@"Remote exception thrown: %@: %@", [exception name], [exception reason]);
- NSRunAlertPanel(@"Remote MenuTunes Disconnected", @"The MenuTunes server you were connected to stopped responding or quit. MenuTunes will revert back to the local player.", @"OK", nil, nil);
+ NSLog(@"Remote exception thrown: %@: %@", [exception name], [exception reason]);
+ NSRunCriticalAlertPanel(@"Remote MenuTunes Disconnected", @"The MenuTunes server you were connected to stopped responding or quit. MenuTunes will revert back to the local player.", @"OK", nil, nil);
if ([networkController isConnectedToServer] && [self disconnectFromServer]) {
+ if ([[exception name] isEqualToString:NSPortTimeoutException]) {
+ [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES];
+ }
} else {
- ITDebugLog(@"CRITICAL ERROR DISCONNECTING!");
+ ITDebugLog(@"CRITICAL ERROR, DISCONNECTING!");
+ }
+}
+
+- (void)reconnect
+{
+ if (![self connectToServer]) {
+ [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES];
}
+ [[StatusWindow sharedWindow] setLocked:NO];
+ [[StatusWindow sharedWindow] vanish:self];
+ [[StatusWindow sharedWindow] setIgnoresMouseEvents:YES];
+}
+
+- (void)cancelReconnect
+{
+ [[StatusWindow sharedWindow] setLocked:NO];
+ [[StatusWindow sharedWindow] vanish:self];
+ [[StatusWindow sharedWindow] setIgnoresMouseEvents:YES];
}
/*************************************************************************/
NSConnection *serverConnection, *clientConnection;
NSSocketPort *serverPort, *clientPort;
+ NSString *remoteHost;
BOOL serverOn, clientConnected, connectedToServer;
+ NSData *serverPass, *clientPass;
ITMTRemote *clientProxy;
}
+ (NetworkController *)sharedController;
- (void)setServerStatus:(BOOL)status;
- (BOOL)connectToHost:(NSString *)host;
+- (BOOL)checkForServerAtHost:(NSString *)host;
- (BOOL)disconnect;
- (BOOL)isServerOn;
- (BOOL)isClientConnected;
- (BOOL)isConnectedToServer;
+- (NSString *)remoteHost;
- (ITMTRemote *)sharedRemote;
- (NSArray *)remoteServices;
[serverConnection invalidate];
[serverConnection release];
}
+ [serverPass release];
+ [clientPass release];
[clientProxy release];
[remoteServices release];
[browser release];
{
if (!serverOn && status) {
NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@"sharedPlayerName"];
+ unsigned char buffer;
+ NSData *fullPass;
//Turn on
NS_DURING
serverPort = [[NSSocketPort alloc] initWithTCPPort:SERVER_PORT];
[serverConnection registerName:@"ITMTPlayerHost"];
[serverConnection setDelegate:self];
NS_HANDLER
+ [serverConnection release];
+ [serverPort release];
ITDebugLog(@"Error starting server!");
NS_ENDHANDLER
ITDebugLog(@"Started server.");
type:@"_mttp._tcp."
name:name
port:SERVER_PORT];
+ fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"sharedPlayerPassword"];
+ if (fullPass) {
+ [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
+ [serverPass release];
+ serverPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
+ } else {
+ serverPass = nil;
+ }
[service publish];
serverOn = YES;
} else if (serverOn && !status && [serverConnection isValid]) {
- (BOOL)connectToHost:(NSString *)host
{
+ NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
+ unsigned char buffer;
ITDebugLog(@"Connecting to host: %@", host);
+ remoteHost = [host copy];
+ if (fullPass) {
+ [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
+ [clientPass release];
+ clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
+ } else {
+ clientPass = nil;
+ }
NS_DURING
clientPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
host:host];
clientConnection = [[NSConnection connectionWithReceivePort:nil sendPort:clientPort] retain];
+ [clientConnection setDelegate:self];
+ [clientConnection setReplyTimeout:5];
clientProxy = [[clientConnection rootProxy] retain];
NS_HANDLER
+ [clientConnection release];
+ [clientPort release];
ITDebugLog(@"Connection to host failed: %@", host);
return NO;
NS_ENDHANDLER
- [clientConnection setReplyTimeout:5];
ITDebugLog(@"Connected to host: %@", host);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(disconnect) name:NSConnectionDidDieNotification object:clientConnection];
connectedToServer = YES;
{
ITDebugLog(@"Disconnecting from host.");
connectedToServer = NO;
+ [remoteHost release];
+ remoteHost = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[clientProxy release];
[clientConnection invalidate];
return YES;
}
+- (BOOL)checkForServerAtHost:(NSString *)host
+{
+ NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
+ unsigned char buffer;
+ NSConnection *testConnection;
+ NSSocketPort *testPort;
+ NSDistantObject *tempProxy;
+ ITDebugLog(@"Checking for shared remote at %@.", host);
+ if (fullPass) {
+ [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
+ [clientPass release];
+ clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
+ } else {
+ clientPass = nil;
+ }
+
+ NS_DURING
+ testPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
+ host:host];
+ testConnection = [[NSConnection connectionWithReceivePort:nil sendPort:testPort] retain];
+ [testConnection setReplyTimeout:2];
+ tempProxy = [testConnection rootProxy];
+ [testConnection setDelegate:self];
+ [tempProxy sharedRemoteName];
+ NS_HANDLER
+ ITDebugLog(@"Connection to host failed: %@", host);
+ [testConnection invalidate];
+ [testConnection release];
+ [testPort release];
+ return NO;
+ NS_ENDHANDLER
+ [testConnection invalidate];
+ [testConnection release];
+ [testPort release];
+ return YES;
+}
+
- (BOOL)isServerOn
{
return serverOn;
return connectedToServer;
}
+- (NSString *)remoteHost
+{
+ return remoteHost;
+}
+
- (ITMTRemote *)sharedRemote
{
return (ITMTRemote *)clientProxy;
return remoteServices;
}
+/*- (BOOL)authenticateComponents:(NSArray*)components withData:(NSData *)authenticationData
+{
+ return YES;
+ if (![[NSUserDefaults standardUserDefaults] boolForKey:@"enableSharingPassword"] || [authenticationData isEqualToData:serverPass]) {
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
+- (NSData *)authenticationDataForComponents:(NSArray *)components
+{
+ return clientPass;
+}*/
+
- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
{
ITDebugLog(@"Found service named %@.", [aNetService name]);
ITDebugLog(@"Resolved service named %@.", [sender name]);
NSLog(@"Resolved service named %@.", [sender name]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
+ [sender stop];
}
- (void)netServiceWillResolve:(NSNetService *)sender
IBOutlet NSTableView *hotKeysTableView;
IBOutlet NSButton *launchAtLoginCheckbox;
IBOutlet NSButton *launchPlayerAtLaunchCheckbox;
+ IBOutlet NSTextField *locationTextField;
IBOutlet NSView *manualView;
IBOutlet CustomMenuTableView *menuTableView;
IBOutlet NSButton *nameCheckbox;
IBOutlet NSTextField *nameTextField;
IBOutlet NSTextField *passwordTextField;
IBOutlet NSButton *ratingCheckbox;
+ IBOutlet NSTextField *selectedPlayerTextField;
IBOutlet NSBox *selectPlayerBox;
IBOutlet NSPanel *selectPlayerSheet;
IBOutlet NSButton *selectSharedPlayerButton;
#import "StatusWindow.h"
#import "StatusWindowController.h"
#import "CustomMenuTableView.h"
-#import "netinet/in.h"
-#import "arpa/inet.h"
+
+#import <netinet/in.h>
+#import <arpa/inet.h>
+#import <openssl/sha.h>
#import <ITKit/ITHotKeyCenter.h>
#import <ITKit/ITKeyCombo.h>
} else if ( [sender tag] == 5020 ) {
[df setBool:SENDER_STATE forKey:@"enableSharingPassword"];
} else if ( [sender tag] == 5030 ) {
- [df setObject:[sender stringValue] forKey:@"sharedPlayerPassword"];
+ //Set the server password
+ const char *instring = [[sender stringValue] UTF8String];
+ const char *password = "password";
+ unsigned char result;
+ NSData *hashedPass, *passwordStringHash;
+ SHA1(instring, strlen(instring), &result);
+ hashedPass = [NSData dataWithBytes:&result length:strlen(&result)];
+ SHA1(password, strlen(password), &result);
+ passwordStringHash = [NSData dataWithBytes:&result length:strlen(&result)];
+ if (![hashedPass isEqualToData:passwordStringHash]) {
+ [df setObject:hashedPass forKey:@"sharedPlayerPassword"];
+ }
} else if ( [sender tag] == 5040 ) {
BOOL state = SENDER_STATE;
[df setBool:state forKey:@"useSharedPlayer"];
[controller disconnectFromServer];
}
} else if ( [sender tag] == 5050 ) {
- if ([sender clickedRow] > -1) {
- //Set sharedPlayerHost
- //[df setObject:[[[[NetworkController sharedController] remoteServices] objectAtIndex:[sender clickedRow]] objectForKey:@"ip"] forKey:@"sharedPlayerHost"];
- }
+ //Do nothing on table view click
+ } else if ( [sender tag] == 5051 ) {
+ [df setObject:[sender stringValue] forKey:@"sharedPlayerHost"];
} else if ( [sender tag] == 5060 ) {
//Show selection sheet
[NSApp beginSheet:selectPlayerSheet modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil];
frame.size.height = 273;
[selectPlayerBox setContentView:zeroConfView];
[selectPlayerSheet setFrame:frame display:YES animate:YES];
- } else if ([selectPlayerBox contentView] != manualView) {
+ } else if ( ([sender indexOfItem:[sender selectedItem]] == 1) && ([selectPlayerBox contentView] != manualView) ){
NSRect frame = [selectPlayerSheet frame];
frame.origin.y += 58;
frame.size.height = 215;
+ //[window makeFirstResponder:hostTextField];
[selectPlayerBox setContentView:manualView];
[selectPlayerSheet setFrame:frame display:YES animate:YES];
+ [hostTextField selectText:nil];
}
+ } else if ( [sender tag] == 5150 ) {
+ const char *instring = [[sender stringValue] UTF8String];
+ unsigned char result;
+ SHA1(instring, strlen(instring), &result);
+ [df setObject:[NSData dataWithBytes:&result length:strlen(&result)] forKey:@"connectPassword"];
} else if ( [sender tag] == 5110 ) {
//Cancel
[NSApp endSheet:selectPlayerSheet];
}
}
- if (![controller connectToServer]) {
- NSRunAlertPanel(@"Connection error.", @"The MenuTunes server you attempted to connect to was not responding. MenuTunes will revert back to the local player.", @"OK", nil, nil);
- } else {
+ if ([controller connectToServer]) {
[useSharedMenuTunesCheckbox setState:NSOnState];
+ [selectedPlayerTextField setStringValue:[[[MainController sharedController] currentRemote] sharedRemoteName]];
+ [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]];
+ } else {
+ NSRunAlertPanel(@"Connection error.", @"The MenuTunes server you attempted to connect to was not responding. MenuTunes will revert back to the local player.", @"OK", nil, nil);
}
}
[df synchronize];
} else if ([df boolForKey:@"useSharedPlayer"]) {
[useSharedMenuTunesCheckbox setState:NSOnState];
[shareMenuTunesCheckbox setEnabled:NO];
+ [selectSharedPlayerButton setEnabled:YES];
}
[[NSNotificationCenter defaultCenter] addObserver:sharingTableView selector:@selector(reloadData) name:@"ITMTFoundNetService" object:nil];
[selectPlayerBox setContentView:zeroConfView];
[usePasswordCheckbox setState:([df boolForKey:@"enableSharingPassword"] ? NSOnState : NSOffState)];
- if ([df stringForKey:@"sharedPlayerPassword"]) {
- [passwordTextField setStringValue:@"*************"];
+ if ([df dataForKey:@"sharedPlayerPassword"]) {
+ [passwordTextField setStringValue:@"password"];
}
if ([df stringForKey:@"sharedPlayerHost"]) {
[hostTextField setStringValue:[df stringForKey:@"sharedPlayerHost"]];
}
+
+ if ([[NetworkController sharedController] isConnectedToServer]) {
+ [selectedPlayerTextField setStringValue:[[[MainController sharedController] currentRemote] sharedRemoteName]];
+ [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]];
+ } else {
+ [selectedPlayerTextField setStringValue:@"No shared player selected."];
+ [locationTextField setStringValue:@"-"];
+ }
}
- (IBAction)changeMenus:(id)sender
- (void)showRepeatWindowWithMode:(StatusWindowRepeatMode)mode;
- (void)showSetupQueryWindow;
- (void)showRegistrationQueryWindow;
+- (void)showReconnectQueryWindow;
- (void)showSongInfoWindowWithSource:(ITMTRemotePlayerSource)source
title: (NSString *)title
[_window setLocked:YES];
}
+- (void)showReconnectQueryWindow
+{
+ NSString *message = @"The selected shared player is available again.\nWould you like to reconnect to it?.";
+
+ [_window setImage:[NSImage imageNamed:@"Register"]];
+ [_window buildDialogWindowWithMessage:message
+ defaultButton:@"Reconnect"
+ alternateButton:@"Ignore"
+ target:[MainController sharedController]
+ defaultAction:@selector(reconnect)
+ alternateAction:@selector(cancelReconnect)];
+
+ [_window appear:self];
+ [_window setLocked:YES];
+}
@end
\ No newline at end of file