2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // File: AppController.m
6 // Created: Wed Aug 13 2003
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #import "AppController.h"
13 #include "cheat_shared.h"
15 #import "AboutBoxController.h"
16 #import "PreferenceController.h"
17 #import "NetTrafficController.h"
19 #import "CheatListener.h"
20 #import "CheatServer.h"
22 #import "ServerHolder.h"
24 #import <Chaz/CMUpdateCheck.h>
27 @implementation AppController
31 NSMutableDictionary
*defaults
= [NSMutableDictionary dictionary
];
34 // change the socket path to reside in the home directory of the current user
35 strncpy( temp
, [NSHomeDirectory() lossyCString
], 103 );
36 strncat( temp
, TCDefaultListenPath
, 103 - strlen(TCDefaultListenPath
) );
37 strncpy( TCDefaultListenPath
, temp
, 103 );
39 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalPlaySounds
] forKey
:TCPlaySoundsPref
];
40 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalWindowsOnTop
] forKey
:TCWindowsOnTopPref
];
41 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalUpdateCheck
] forKey
:TCUpdateCheckPref
];
42 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalAllowRemote
] forKey
:TCAllowRemotePref
];
43 [defaults setObject
:[NSNumber numberWithInt
:TCGlobalListenPort
] forKey
:TCListenPortPref
];
44 [defaults setObject
:[NSString stringWithFormat
:@
"%@'s Computer", NSFullUserName()] forKey
:TCBroadcastNamePref
];
45 [defaults setObject
:[NSNumber numberWithInt
:TCGlobalHitsDisplayed
] forKey
:TCHitsDisplayedPref
];
47 [[NSUserDefaults standardUserDefaults
] registerDefaults
:defaults
];
49 TCGlobalPlaySounds
= [[NSUserDefaults standardUserDefaults
] boolForKey
:TCPlaySoundsPref
];
50 TCGlobalWindowsOnTop
= [[NSUserDefaults standardUserDefaults
] boolForKey
:TCWindowsOnTopPref
];
51 TCGlobalUpdateCheck
= [[NSUserDefaults standardUserDefaults
] boolForKey
:TCUpdateCheckPref
];
52 TCGlobalAllowRemote
= [[NSUserDefaults standardUserDefaults
] boolForKey
:TCAllowRemotePref
];
53 TCGlobalListenPort
= [[NSUserDefaults standardUserDefaults
] integerForKey
:TCListenPortPref
];
54 TCGlobalHitsDisplayed
= [[NSUserDefaults standardUserDefaults
] integerForKey
:TCHitsDisplayedPref
];
59 if ( self = [super init
] )
61 servers
= [[NSMutableArray alloc
] init
];
63 // start the server with saved settings
64 [self listenOnPort
:TCGlobalListenPort remote
:TCGlobalAllowRemote
];
65 if ( TCGlobalAllowRemote
) [self broadcastWithName
:TCGlobalBroadcastName
];
67 // set up the network browser
68 browser
= [[NSNetServiceBrowser alloc
] init
];
69 [browser setDelegate
:self];
70 [browser searchForServicesOfType
:@
"_cheat._tcp." inDomain
:@
"local."];
72 serverList
= [[NSMutableArray alloc
] init
];
74 [self setDelegate
:self];
81 - (void)applicationDidFinishLaunching
:(NSNotification
*)aNotification
83 if ( TCGlobalUpdateCheck
)
85 [CMUpdateCheck checkWithURL
:@
"http://www.brokenzipper.com/software.plist" verbose
:NO
];
90 - (void)listenOnPort
:(int)port remote
:(BOOL)remote
96 waitingToListen
= YES
;
97 connectionPort
= port
;
98 connectionRemote
= remote
;
102 connection
= [[CheatListener listenerWithDelegate
:self port
:port remote
:remote
] retain
];
103 connectionPort
= port
;
104 connectionRemote
= remote
;
113 [connection release
], connection
= nil;
118 - (void)broadcastWithName
:(NSString
*)name
120 [self stopBroadcast
];
122 service
= [[NSNetService alloc
] initWithDomain
:@
"local." type
:@
"_cheat._tcp." name
:name port
:TCGlobalListenPort
];
123 [service setDelegate
:self];
127 - (void)stopBroadcast
129 [service stop
], service
= nil;
133 - (IBAction
)showAboutBoxWindow
:(id)sender
135 if ( !aboutBoxController
)
137 aboutBoxController
= [[AboutBoxController alloc
] init
];
140 [aboutBoxController showWindow
:self];
143 - (IBAction
)showPreferenceWindow
:(id)sender
145 if ( !preferenceController
)
147 preferenceController
= [[PreferenceController alloc
] initWithDelegate
:self];
150 [preferenceController showWindow
:self];
153 - (IBAction
)showNetTrafficWindow
:(id)sender
155 if ( !netTrafficController
)
157 netTrafficController
= [[NetTrafficController alloc
] initWithDelegate
:self];
160 [netTrafficController showWindow
:self];
164 - (IBAction
)launchHelpFile
:(id)sender
166 //[[NSWorkspace sharedWorkspace] openFile:[[NSBundle mainBundle] pathForResource:@"Read Me" ofType:@"html"] withApplication:@"Safari"];
167 [[NSWorkspace sharedWorkspace
] openURL
:[NSURL fileURLWithPath
:[[NSBundle mainBundle
] pathForResource
:@
"Read Me" ofType
:@
"rtf"]]];
170 - (IBAction
)launchEmailMenu
:(id)sender
175 - (IBAction
)launchWebsiteMenu
:(id)sender
181 - (IBAction
)checkForUpdate
:(id)sender
183 [CMUpdateCheck checkWithURL
:@
"http://www.brokenzipper.com/software.plist"];
187 - (NSArray
*)serverList
195 [[NSNotificationCenter defaultCenter
] removeObserver
:self];
198 [self stopBroadcast
];
203 [serverList release
];
209 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 %%%%%%%%%%%%%%%%%%%%%% PreferenceControlling
211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
214 - (void)preferenceSetWindowsOnTop
:(BOOL)windowsOnTop
216 if ( TCGlobalWindowsOnTop
!= windowsOnTop
)
218 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCWindowsOnTopChanged" object
:[NSNumber numberWithBool
:windowsOnTop
]];
222 - (void)preferenceSetAllowRemote
:(BOOL)allow listenPort
:(int)port broadcastName
:(NSString
*)name
224 if ( TCGlobalAllowRemote
!= allow || TCGlobalListenPort
!= port
)
226 [self listenOnPort
:port remote
:allow
];
230 if ( !TCGlobalAllowRemote ||
![TCGlobalBroadcastName isEqualToString
:name
] )
232 [self broadcastWithName
:name
];
237 [self stopBroadcast
];
239 [netTrafficController serverSetAllowRemote
:allow listenPort
:port broadcastName
:name
];
240 //[netTrafficController allowRemoteChanged:allow];
241 //[netTrafficController listenPortChanged:port];
242 //[netTrafficController broadcastNameChanged:name];
246 - (void)preferenceAllowRemoteChanged:(BOOL)allow
248 [self listenOnPort:TCGlobalListenPort remote:allow];
252 [self broadcastWithName:TCGlobalBroadcastName];
256 [self stopBroadcast];
259 [netTrafficController allowRemoteChanged:allow];
262 - (void)preferenceListenPortChanged:(int)port
264 [self listenOnPort:port remote:TCGlobalAllowRemote];
265 [self broadcastWithName:TCGlobalBroadcastName];
267 [netTrafficController listenPortChanged:port];
270 - (void)preferenceBroadcastNameChanged:(NSString *)name
272 [self broadcastWithName:name];
274 [netTrafficController broadcastNameChanged:name];
279 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 %%%%%%%%%%%%%%%%%%%%%% NetTrafficControlling
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
284 - (int)netTrafficConnectionCount
286 return [servers count
];
289 - (NSArray
*)netTrafficConnectionList
294 - (void)netTrafficKillConnection
:(int)index
296 NSLog( @
"kill connection" );
298 close( [[servers objectAtIndex
:index
] sockfd
] );
302 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 %%%%%%%%%%%%%%%%%%%%%% ListenerDelegate
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
307 - (void)listenerListeningWithSocket
:(int)sock
311 TCGlobalListening
= YES
;
312 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCListenerStarted" object
:nil];
315 - (void)listenerDisconnected
317 if ( waitingToListen
)
319 waitingToListen
= NO
;
320 connection
= [[CheatListener listenerWithDelegate
:self port
:connectionPort remote
:connectionRemote
] retain
];
327 TCGlobalListening
= NO
;
328 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCListenerStopped" object
:nil];
331 - (void)listenerError
:(NSString
*)error message
:(NSString
*)message
333 NSRunCriticalAlertPanel( error
, message
, @
"OK", nil, nil );
336 - (void)listenerReceivedNewConnection
:(int)sock
338 [servers addObject
:[ServerHolder holderWithConnection
:[CheatServer serverWithDelegate
:self socket
:sock
] socket
:sock
]];
342 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343 %%%%%%%%%%%%%%%%%%%%%% ServerDelegate
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
347 - (void)server
:(CheatServer
*)server connectedWithSocket
:(int)sock
349 int i
, top
= [servers count
];
351 for ( i
= 0; i
< top
; i
++ )
353 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] sockfd
] == sock
)
355 [(ServerHolder
*)[servers objectAtIndex
:i
] setServer
:server
];
360 [netTrafficController connectionListChanged
];
363 - (void)serverDisconnected
:(CheatServer
*)server
365 int i
, top
= [servers count
];
367 for ( i
= 0; i
< top
; i
++ )
369 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
371 [servers removeObjectAtIndex
:i
];
376 [netTrafficController connectionListChanged
];
379 - (void)server
:(CheatServer
*)server changedAddress
:(NSString
*)address
381 int i
, top
= [servers count
];
383 for ( i
= 0; i
< top
; i
++ )
385 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
387 [(ServerHolder
*)[servers objectAtIndex
:i
] setAddress
:address
];
392 [netTrafficController connectionListChanged
];
395 - (void)server
:(CheatServer
*)server changedAction
:(NSString
*)action
397 int i
, top
= [servers count
];
399 for ( i
= 0; i
< top
; i
++ )
401 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
403 [(ServerHolder
*)[servers objectAtIndex
:i
] setAction
:action
];
408 [netTrafficController connectionListChanged
];
411 - (NSArray
*)serverProcessList
413 return [[NSWorkspace sharedWorkspace
] launchedApplications
];
416 - (pid_t
)serverFirstProcess
418 return (pid_t
)[[[[[NSWorkspace sharedWorkspace
] launchedApplications
] objectAtIndex
:0] objectForKey
:@
"NSApplicationProcessIdentifier"] intValue
];
422 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423 %%%%%%%%%%%%%%%%%%%%%% NetService Delegate
424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
427 - (void)netServiceWillPublish
:(NSNetService
*)sender
429 NSLog( @
"service will publish" );
433 - (void)netService
:(NSNetService
*)sender didNotPublish
:(NSDictionary
*)errorDict
435 NSLog( @
"service did not publish" );
437 if ( [[errorDict objectForKey
:@
"NSNetServicesErrorCode"] intValue
] == NSNetServicesCollisionError
)
439 [self broadcastWithName
:[NSString stringWithFormat
:@
"%@ %i", [sender name
], TCGlobalAlternateBroadcastNameCount
++]];
443 NSRunCriticalAlertPanel( @
"Network Error", @
"Server couldn't broadcast. Local can't be cheated by remote computers.", @
"OK", nil, nil );
447 - (void)netServiceDidStop
:(NSNetService
*)sender
449 NSLog( @
"service stopped" );
454 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455 %%%%%%%%%%%%%%%%%%%%%% NSNetServiceBrowser Delegate
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
459 - (void)netServiceBrowser
:(NSNetServiceBrowser
*)browser didFindService
:(NSNetService
*)aService moreComing
:(BOOL)more
461 // a server has broadcast; not much use until it's resolved.
462 [aService setDelegate
:self];
466 - (void)netServiceDidResolveAddress
:(NSNetService
*)aService
468 int i
, top
= [serverList count
];
470 // ignore if this is the local server.
471 if ( TCGlobalAllowRemote
&& [[aService name
] isEqualToString
:TCGlobalBroadcastName
] )
476 // ignore if the server name is already in the list.
477 for ( i
= 0; i
< top
; i
++ )
479 if ( [[aService name
] isEqualToString
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
]] )
485 [serverList addObject
:aService
];
486 NSLog( @
"server added: %i", [serverList count
] );
488 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCServerFound" object
:aService
];
491 - (void)netServiceBrowser
:(NSNetServiceBrowser
*)browser didRemoveService
:(NSNetService
*)aService moreComing
:(BOOL)more
493 int i
, top
= [serverList count
];
495 for ( i
= 0; i
< top
; i
++ )
497 if ( [[aService name
] isEqualToString
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
]] )
499 [serverList removeObjectAtIndex
:i
];
500 NSLog( @
"server deleted: %i", [serverList count
] );
505 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCServerLost" object
:aService
];