root/trunk/lilypad/Sources/LPAccountsController.m @ 251

Revision 251, 40.6 KB (checked in by jppavao, 5 years ago)

Converted the declarations of "Private" categories to class extensions based on anonymous categories for improved compile-time error checking.

Line 
1//
2//  LPAccountsController.m
3//  Lilypad
4//
5//      Copyright (C) 2006-2008 PT.COM,  All rights reserved.
6//      Author: Joao Pavao <jpavao@co.sapo.pt>
7//
8//      For more information on licensing, read the README file.
9//      Para mais informações sobre o licenciamento, leia o ficheiro README.
10//
11
12#import "LPAccountsController.h"
13#import "LPAccount.h"
14#import "LPServerItemsInfo.h"
15#import "LPKeychainManager.h"
16
17
18static NSString *LPAllAccountsDefaultsKey = @"Accounts";
19static NSString *LPSortedAccountUUIDsDefaultsKey = @"Accounts Sort Order";
20
21
22// KVO Contexts
23static void *LPAccountsConfigurationChangeContext       = (void *)1001;
24static void *LPAccountsPasswordsChangeContext           = (void *)1002;
25static void *LPAccountsDynamicStateChangeContext        = (void *)1003;
26
27
28@interface LPAccount ()  // Private Methods
29- (void)p_updateLocationFromChangedComputerName;
30@end
31
32
33static NSString *
34LPAccountsControllerNewUUIDString()
35{
36        CFUUIDRef       uuid = CFUUIDCreate(NULL);
37        NSString        *uuidStr = (NSString *)CFUUIDCreateString(NULL, uuid);
38       
39        if (uuid != NULL) CFRelease(uuid);
40       
41        return [uuidStr autorelease];
42}
43
44
45static void
46LPAccountsControllerSCDynamicStoreCallBack (SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
47{
48        LPAccountsController *accountsCtrl = (LPAccountsController *)info;
49        [[accountsCtrl accounts] makeObjectsPerformSelector:@selector(p_updateLocationFromChangedComputerName)];
50}
51
52
53@interface LPAccountsController ()  // Private Methods
54+ (NSArray *)p_persistentAccountKeys;
55- (void)p_saveAccountsWithTimer:(NSTimer *)timer;
56- (void)p_saveAccountsToDefaults;
57- (void)p_savePasswordsForAccount:(LPAccount *)account;
58- (LPAccount *)p_firstAccountPassingOwnPredicate:(SEL)pred;
59- (id)p_accountsFirstNonNilObjectValueForKey:(NSString *)key;
60- (LPStatus)p_accountsFirstNonOfflineStatusForKey:(NSString *)key;
61- (NSString *)p_computedGlobalAccountName;
62- (LPStatus)p_computedGlobalAccountStatus;
63- (NSString *)p_computedGlobalAccountStatusMessage;
64- (LPStatus)p_computedGlobalAccountTargetStatus;
65- (BOOL)p_computedGlobalAccountOnlineFlag;
66- (BOOL)p_computedGlobalAccountOfflineFlag;
67- (BOOL)p_computedGlobalAccountDebuggerFlag;
68- (BOOL)p_computedGlobalAccountTryingToAutoReconnectFlag;
69- (NSImage *)p_computedGlobalAccountAvatar;
70- (void)p_computedGlobalAccountSMSCredit:(int *)smsCredit
71                                                nrOfFreeMessages:(int *)smsFreeMessages
72                                                   nrOfTotalSent:(int *)smsTotalSent;
73
74- (void)p_updateCachedGlobalAccountValuesForAllKeys;
75- (void)p_updateCachedGlobalAccountValueForKey:(NSString *)key;
76@end
77
78
79@implementation LPAccountsController
80
81+ (void)p_zeroOutSupportFolder:(NSString *)folder ifOlderThanVersion:(int)versionNr
82{
83        NSString *contentsVersionFilePath = [folder stringByAppendingPathComponent:@"version"];
84        NSString *folderContentsVersionStr = [NSString stringWithContentsOfFile:contentsVersionFilePath encoding:NSUTF8StringEncoding error:NULL];
85       
86        if ([folderContentsVersionStr intValue] < versionNr) {
87                NSFileManager *fm = [NSFileManager defaultManager];
88               
89                [fm removeFileAtPath:folder handler:nil];
90                [fm createDirectoryAtPath:folder attributes:nil];
91                [[NSString stringWithFormat:@"%d", versionNr] writeToFile:contentsVersionFilePath
92                                                                                                           atomically:YES
93                                                                                                                 encoding:NSUTF8StringEncoding
94                                                                                                                        error:NULL];
95        }
96}
97
98
99+ (void)initialize
100{
101        if (self == [LPAccountsController class]) {
102                // Start by initializing some stuff on the bridge before adding any accounts
103                NSTimeZone      *tz = [NSTimeZone defaultTimeZone];
104                NSBundle        *appBundle = [NSBundle mainBundle];
105                NSString        *clientName = [NSString stringWithFormat:@"%@ Mac", [appBundle objectForInfoDictionaryKey:@"CFBundleExecutable"]];
106               
107                id                      bundleShortVersionStr = [appBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
108                id                      bundleVersion = [appBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
109               
110                NSString        *versionString = [NSString stringWithFormat:@"%@ (%@)", bundleShortVersionStr, bundleVersion];
111                NSString        *capsVersionString = [NSString stringWithFormat:@"%@_%@", bundleShortVersionStr, bundleVersion];
112               
113                [LFAppController setTimeZoneName:[tz abbreviation] timeZoneOffset:([tz secondsFromGMT] / 3600)];
114                [LFAppController setClientName:clientName
115                                                           version:versionString
116                                                                OSName:@"Mac OS X"
117                                                          capsNode:@"http://messenger.sapo.pt/caps/mac"
118                                                   capsVersion:capsVersionString];
119               
120                // Caches folder
121                NSString *cachesFolder = LPOurApplicationCachesFolderPath();
122               
123                [self p_zeroOutSupportFolder:cachesFolder ifOlderThanVersion:2];
124                [LFAppController setCachesFolder:cachesFolder];
125        }
126}
127
128
129+ (LPAccountsController *)sharedAccountsController
130{
131        static LPAccountsController *sharedController = nil;
132
133        if (sharedController == nil) {
134                sharedController = [[LPAccountsController alloc] init];
135        }
136        return sharedController;
137}
138
139
140+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
141{
142        // Cached computed account attributes
143        NSArray *manualNotificationKeys = [NSArray arrayWithObjects:@"name", @"status", @"statusMessage", @"targetStatus", @"online", @"offline", @"debugger", @"tryingToAutoReconnect", @"avatar", nil];
144       
145        return ([manualNotificationKeys containsObject:key] == NO);
146}
147
148
149- init
150{
151        if (self = [super init]) {
152                m_accountsByUUID = [[NSMutableDictionary alloc] init];
153                m_accounts = [[NSMutableArray alloc] init];
154               
155                m_globalAccountStatus = LPStatusOffline;
156                m_globalAccountTargetStatus = LPStatusOffline;
157                m_globalAccountOfflineFlag = YES;
158               
159                m_isLoadingFromDefaults = NO;
160               
161                // System Configuration change notifications
162                SCDynamicStoreContext ctx = { 0, (void *)self, NULL, NULL, NULL };
163               
164                m_dynamicStore = SCDynamicStoreCreate(NULL,
165                                                                                          (CFStringRef)[[NSBundle mainBundle] bundleIdentifier],
166                                                                                          &LPAccountsControllerSCDynamicStoreCallBack,
167                                                                                          &ctx);
168               
169                CFStringRef computerNameKey = SCDynamicStoreKeyCreateComputerName(NULL);
170                if (computerNameKey) {
171                       
172                        SCDynamicStoreSetNotificationKeys(m_dynamicStore, (CFArrayRef)[NSArray arrayWithObject:(id)computerNameKey], NULL);
173                        CFRelease(computerNameKey);
174                       
175                        m_dynamicStoreNotificationsRunLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, m_dynamicStore, 0);
176                        if (m_dynamicStoreNotificationsRunLoopSource)
177                                CFRunLoopAddSource(CFRunLoopGetCurrent(), m_dynamicStoreNotificationsRunLoopSource, kCFRunLoopCommonModes);
178                }
179               
180               
181                [self loadAccountsFromDefaults];
182               
183                [LFPlatformBridge registerNotificationsObserver:self];
184               
185               
186                [[NSNotificationCenter defaultCenter] addObserver:self
187                                                                                                 selector:@selector(applicationWillTerminate:)
188                                                                                                         name:NSApplicationWillTerminateNotification
189                                                                                                   object:nil];
190        }
191        return self;
192}
193
194
195- (void)dealloc
196{
197        [[NSNotificationCenter defaultCenter] removeObserver:self];
198        [LFPlatformBridge unregisterNotificationsObserver:self];
199       
200        if ([self needsToSaveAccounts]) {
201                [m_accountsSaveTimer fire];
202                [m_accountsSaveTimer release];
203        }
204        [[NSUserDefaults standardUserDefaults] synchronize];
205       
206        [m_accounts release];
207        [m_accountsByUUID release];
208       
209        if (m_dynamicStoreNotificationsRunLoopSource) {
210                CFRunLoopSourceInvalidate(m_dynamicStoreNotificationsRunLoopSource);
211                CFRelease(m_dynamicStoreNotificationsRunLoopSource);
212        }
213        if (m_dynamicStore) {
214                CFRelease(m_dynamicStore);
215        }
216       
217        // Cache of computed account attributes
218        [m_globalAccountName release];
219        [m_globalAccountStatusMessage release];
220        [m_globalAccountAvatar release];
221       
222        [super dealloc];
223}
224
225
226- (void)loadAccountsFromDefaults
227{
228        m_isLoadingFromDefaults = YES;
229       
230        NSUserDefaults  *defaults = [NSUserDefaults standardUserDefaults];
231       
232        NSDictionary    *accountsFromPrefs = [defaults dictionaryForKey:LPAllAccountsDefaultsKey];
233        NSArray                 *sortedAccountUUIDs = [defaults arrayForKey:LPSortedAccountUUIDsDefaultsKey];
234       
235        NSEnumerator    *accountUUIDEnumerator = (sortedAccountUUIDs != nil ?
236                                                                                          [sortedAccountUUIDs objectEnumerator] :
237                                                                                          [accountsFromPrefs keyEnumerator]);
238        NSString                *accountUUID;
239       
240        while (accountUUID = [accountUUIDEnumerator nextObject]) {
241                LPAccount *account = [m_accountsByUUID objectForKey:accountUUID];
242               
243                if (account == nil) {
244                        account = [[LPAccount alloc] initWithUUID:accountUUID];
245                        [self addAccount:account];
246                        [account release];
247                }
248               
249                // Load the persistent account keys
250                NSDictionary *accountDict = [accountsFromPrefs objectForKey:accountUUID];
251                NSEnumerator *keyEnumerator = [accountDict keyEnumerator];
252                NSString *key;
253               
254                while (key = [keyEnumerator nextObject]) {
255                        @try {
256                                [account setValue:[accountDict objectForKey:key] forKey:key];
257                        }
258                        @catch (NSException *exception) {
259                                if ([key isEqualToString:@"shouldAutoLogin"]) {
260                                        // Once a property of the only existing account, this is now a default used by the accounts controller
261                                        [defaults setObject:[accountDict objectForKey:key] forKey:@"AccountAutoLogin"];
262                                }
263                                else if ([[exception name] isEqualToString:NSUndefinedKeyException]) {
264                                        // Do nothing. It's probably a key that was saved by a previous version of leapfrog but that is unknown to this version.
265                                }
266                                else {
267                                        @throw exception;
268                                }
269                        }
270                }
271               
272                // Accounts are assumed enabled by default when the corresponding key isn't found in the defaults
273                if ([accountDict valueForKey:@"enabled"] == nil)
274                        [account setEnabled:YES];
275               
276                // Load the passwords
277                [account setValue:[LPKeychainManager passwordForAccount:[account JID]]
278                                   forKey:@"password"];
279                NSString *username = [account lastRegisteredMSNEmail];
280                [account setValue:[LPKeychainManager passwordForAccount:[NSString stringWithFormat:@"MSN: %@", (username ? username : @"")]]
281                                   forKey:@"lastRegisteredMSNPassword"];
282        }
283
284        m_isLoadingFromDefaults = NO;
285}
286
287
288- (BOOL)needsToSaveAccounts
289{
290        return (m_accountsSaveTimer != nil);
291}
292
293- (void)setNeedsToSaveAccounts:(BOOL)shouldSave
294{
295        if (shouldSave && m_isLoadingFromDefaults == NO && m_accountsSaveTimer == nil) {
296                m_accountsSaveTimer = [[NSTimer scheduledTimerWithTimeInterval:23.0
297                                                                                                                                target:self
298                                                                                                                          selector:@selector(p_saveAccountsWithTimer:)
299                                                                                                                          userInfo:nil
300                                                                                                                           repeats:NO] retain];
301        }
302}
303
304- (LPAccount *)defaultAccount
305{
306        if ([m_accounts count] == 0)
307                [self addNewAccount];
308       
309        LPAccount *account = [m_accounts objectAtIndex:0];
310       
311        if (![account isEnabled]) {
312                // Try to find the first enabled account
313                NSEnumerator *accountEnum = [m_accounts objectEnumerator];
314               
315                // Skip the first one, as we have already tested it
316                [accountEnum nextObject];
317               
318                while (account = [accountEnum nextObject])
319                        if ([account isEnabled])
320                                break;
321               
322                if (account == nil)
323                        account = [m_accounts objectAtIndex:0];
324        }
325       
326        return account;
327}
328
329
330- (NSArray *)accounts
331{
332        return [[m_accounts retain] autorelease];
333}
334
335
336- (id)delegate
337{
338        return m_delegate;
339}
340
341- (void)setDelegate:(id)delegate
342{
343        m_delegate = delegate;
344}
345
346
347- (LPAccount *)addNewAccount
348{
349        LPAccount *newAccount = [[LPAccount alloc] initWithUUID: LPAccountsControllerNewUUIDString() ];
350        [self addAccount:newAccount];
351        return [newAccount autorelease];
352}
353
354
355- (void)addAccount:(LPAccount *)account
356{
357        NSIndexSet *changedIndexes = [NSIndexSet indexSetWithIndex:[m_accounts count]];
358       
359        [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:changedIndexes forKey:@"accounts"];
360        [m_accounts addObject:account];
361        [account setDelegate:self];
362        [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:changedIndexes forKey:@"accounts"];
363       
364        [m_accountsByUUID setObject:account forKey:[account UUID]];
365       
366        // Observe keys that should trigger a save to the defaults
367        NSEnumerator *interestingKeyEnumerator = [[LPAccountsController p_persistentAccountKeys] objectEnumerator];
368        NSString *someKey;
369        while (someKey = [interestingKeyEnumerator nextObject])
370                [account addObserver:self forKeyPath:someKey
371                                         options:0 context:LPAccountsConfigurationChangeContext];
372       
373        // The password is a special case: it is saved to the keychain instead of going to the defaults DB along with the other properties
374        [account addObserver:self forKeyPath:@"password"
375                                 options:0 context:LPAccountsPasswordsChangeContext];
376        [account addObserver:self forKeyPath:@"lastRegisteredMSNPassword"
377                                 options:0 context:LPAccountsPasswordsChangeContext];
378       
379        [self setNeedsToSaveAccounts:YES];
380        [self p_savePasswordsForAccount:account];
381       
382       
383        // Also observe the keys that may change the values of some of our accessors that consider all the accounts to compute their return value
384        // No need to add the "name" key, it is already being observed due to being a "persistent account key"
385        [account addObserver:self forKeyPath:@"status"
386                                 options:0 context:LPAccountsDynamicStateChangeContext];
387        [account addObserver:self forKeyPath:@"statusMessage"
388                                 options:0 context:LPAccountsDynamicStateChangeContext];
389        [account addObserver:self forKeyPath:@"targetStatus"
390                                 options:0 context:LPAccountsDynamicStateChangeContext];
391        [account addObserver:self forKeyPath:@"online"
392                                 options:0 context:LPAccountsDynamicStateChangeContext];
393        [account addObserver:self forKeyPath:@"offline"
394                                 options:0 context:LPAccountsDynamicStateChangeContext];
395        [account addObserver:self forKeyPath:@"debugger"
396                                 options:0 context:LPAccountsDynamicStateChangeContext];
397        [account addObserver:self forKeyPath:@"tryingToAutoReconnect"
398                                 options:0 context:LPAccountsDynamicStateChangeContext];
399        [account addObserver:self forKeyPath:@"avatar"
400                                 options:0 context:LPAccountsDynamicStateChangeContext];
401       
402        [account addObserver:self forKeyPath:@"SMSCreditValues"
403                                 options:0 context:LPAccountsDynamicStateChangeContext];
404       
405        // Make sure the core is aware of it
406        [LFAppController addAccountWithUUID:[account UUID]];
407       
408        [self p_updateCachedGlobalAccountValuesForAllKeys];
409}
410
411
412- (void)removeAccount:(LPAccount *)account
413{
414        [account setTargetStatus:LPStatusOffline];
415       
416        [LFAppController removeAccountWithUUID:[account UUID]];
417       
418        [account removeObserver:self forKeyPath:@"SMSCreditValues"];
419        [account removeObserver:self forKeyPath:@"avatar"];
420        [account removeObserver:self forKeyPath:@"tryingToAutoReconnect"];
421        [account removeObserver:self forKeyPath:@"debugger"];
422        [account removeObserver:self forKeyPath:@"offline"];
423        [account removeObserver:self forKeyPath:@"online"];
424        [account removeObserver:self forKeyPath:@"targetStatus"];
425        [account removeObserver:self forKeyPath:@"statusMessage"];
426        [account removeObserver:self forKeyPath:@"status"];
427       
428       
429        [account removeObserver:self forKeyPath:@"lastRegisteredMSNPassword"];
430        [account removeObserver:self forKeyPath:@"password"];
431       
432        // Remove as observer of keys that should trigger a save to the defaults
433        NSEnumerator *interestingKeyEnumerator = [[LPAccountsController p_persistentAccountKeys] objectEnumerator];
434        NSString *someKey;
435        while (someKey = [interestingKeyEnumerator nextObject])
436                [account removeObserver:self forKeyPath:someKey];
437       
438        [m_accountsByUUID removeObjectForKey:[account UUID]];
439       
440        NSIndexSet *changedIndexes = [NSIndexSet indexSetWithIndex:[m_accounts indexOfObject:account]];
441       
442        [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:changedIndexes forKey:@"accounts"];
443        [m_accounts removeObject:account];
444        [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:changedIndexes forKey:@"accounts"];
445       
446        [self setNeedsToSaveAccounts:YES];
447       
448        [self p_updateCachedGlobalAccountValuesForAllKeys];
449}
450
451
452- (void)moveAccount:(LPAccount *)account toIndex:(int)newIndex
453{
454        NSAssert([m_accounts containsObject:account], @"The account is not a member of this accounts controller!");
455       
456        if ([m_accounts indexOfObject:account] != newIndex) {
457                [account retain];
458                [self willChangeValueForKey:@"accounts"];
459                [m_accounts removeObject:account];
460                [m_accounts insertObject:account atIndex:newIndex];
461                [self didChangeValueForKey:@"accounts"];
462                [account release];
463               
464                [self setNeedsToSaveAccounts:YES];
465        }
466}
467
468
469- (LPAccount *)accountForUUID:(NSString *)theUUID
470{
471        return [m_accountsByUUID objectForKey:theUUID];
472}
473
474
475- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
476{
477        // Do the changes require that we save the current accounts configuration?
478        if (context == LPAccountsConfigurationChangeContext) {
479                [self setNeedsToSaveAccounts:YES];
480               
481                if ([keyPath isEqualToString:@"JID"] || [keyPath isEqualToString:@"lastRegisteredMSNEmail"]) {
482                        // The passwords saved in the keychain reference these values
483                        [self p_savePasswordsForAccount:object];
484                }
485        }
486        else if (context == LPAccountsPasswordsChangeContext) {
487                [self p_savePasswordsForAccount:object];
488        }
489       
490       
491        if ([keyPath isEqualToString:@"enabled"])
492        {
493                [self p_updateCachedGlobalAccountValuesForAllKeys];
494               
495                LPAccount *account = object;
496               
497                if ([account isEnabled] && [account isOffline])
498                        [account setTargetStatus:[self targetStatus] message:[self statusMessage] saveToServer:YES];
499                if (![account isEnabled] && ![account isOffline])
500                        [account setTargetStatus:LPStatusOffline];
501        }
502        else
503        {
504                [self p_updateCachedGlobalAccountValueForKey:keyPath];
505        }
506}
507
508
509#pragma mark -
510#pragma mark NSApplication Notifications
511
512
513- (void)applicationWillTerminate:(NSNotification *)notif
514{
515        if ([self needsToSaveAccounts])
516                [m_accountsSaveTimer fire];
517        [[NSUserDefaults standardUserDefaults] synchronize];
518}
519
520
521#pragma mark -
522#pragma mark Private
523
524
525+ (NSArray *)p_persistentAccountKeys
526{
527        return [NSArray arrayWithObjects:
528                @"description", @"enabled", @"name", @"JID", @"location",
529                @"customServerHost", @"usesCustomServerHost",
530                @"lastSuccessfullyConnectedServerHost",
531                @"usesSSL", @"locationUsesComputerName",
532                @"lastRegisteredMSNEmail", nil];
533}
534
535
536- (void)p_saveAccountsWithTimer:(NSTimer *)timer
537{
538        if (!m_isLoadingFromDefaults) {
539                [self p_saveAccountsToDefaults];
540        }
541        [m_accountsSaveTimer autorelease];
542        m_accountsSaveTimer = nil;
543}
544
545- (void)p_saveAccountsToDefaults
546{
547        NSMutableDictionary     *accountsPropsToSave = [NSMutableDictionary dictionary];
548        NSArray                         *keysToBeSaved = [LPAccountsController p_persistentAccountKeys];
549       
550        NSEnumerator    *accountEnumerator = [m_accounts objectEnumerator];
551        LPAccount               *account;
552       
553        while (account = [accountEnumerator nextObject]) {
554               
555                // Get the values for the persistent keys. We don't use -dictionaryWithValuesForKeys: because the NSNulls returned for nil
556                // values aren't valid plist objects and can't be saved to the defaults.
557                NSMutableDictionary *currentValuesAndKeys = [NSMutableDictionary dictionary];
558                NSEnumerator *keyEnumerator = [keysToBeSaved objectEnumerator];
559                NSString *key;
560               
561                while (key = [keyEnumerator nextObject]) {
562                        id value = [account valueForKey:key];
563                        if (value != nil && value != [NSNull null]) {
564                                [currentValuesAndKeys setValue:value forKey:key];
565                        }
566                }
567               
568                // Save the persistent account keys
569                [accountsPropsToSave setObject:currentValuesAndKeys forKey:[account UUID]];
570        }
571       
572        [[NSUserDefaults standardUserDefaults] setObject:accountsPropsToSave forKey:LPAllAccountsDefaultsKey];
573        [[NSUserDefaults standardUserDefaults] setObject:[m_accounts valueForKey:@"UUID"] forKey:LPSortedAccountUUIDsDefaultsKey];
574}
575
576- (void)p_savePasswordsForAccount:(LPAccount *)account
577{
578        if (!m_isLoadingFromDefaults) {
579                if ([[account JID] length] > 0 && [[account password] length] > 0) {
580                        [LPKeychainManager savePassword:[account password] forAccount:[account JID]];
581                }
582               
583                NSString *username = [account lastRegisteredMSNEmail];
584                if ([username length] > 0 && [[account lastRegisteredMSNPassword] length] > 0) {
585                        [LPKeychainManager savePassword:[account lastRegisteredMSNPassword]
586                                                                 forAccount:[NSString stringWithFormat:@"MSN: %@", (username ? username : @"")]];
587                }
588        }
589}
590
591
592#pragma mark Attributes computed from all the accounts managed by this controller
593
594
595- (LPAccount *)p_firstAccountPassingOwnPredicate:(SEL)pred
596{
597        NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[LPAccount instanceMethodSignatureForSelector:pred]];
598        [inv setSelector:pred];
599       
600        NSAssert([[inv methodSignature] methodReturnLength] <= sizeof(BOOL), @"Return value of the provided predicate takes more space than a BOOL!");
601       
602        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
603        LPAccount *account = nil;
604       
605        BOOL passedPredicate = NO;
606       
607        while (account = [accountEnum nextObject]) {
608                if ([account isEnabled]) {
609                        [inv invokeWithTarget:account];
610                        [inv getReturnValue:&passedPredicate];
611                       
612                        if (passedPredicate) break;
613                }
614        }
615       
616        return account;
617}
618
619- (id)p_accountsFirstNonNilObjectValueForKey:(NSString *)key
620{
621        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
622        LPAccount *account;
623       
624        id value = nil;
625       
626        while (value == nil && (account = [accountEnum nextObject]))
627                if ([account isEnabled])
628                        value = [account valueForKey:key];
629       
630        return value;
631}
632
633- (LPStatus)p_accountsFirstNonOfflineStatusForKey:(NSString *)key
634{
635        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
636        LPAccount *account;
637       
638        LPStatus status = LPStatusOffline;
639       
640        while (status == LPStatusOffline && (account = [accountEnum nextObject]))
641                if ([account isEnabled])
642                        status = (LPStatus)[[account valueForKey:key] intValue];
643       
644        return status;
645}
646
647- (NSString *)p_computedGlobalAccountName
648{
649        NSString *computedName = nil;
650       
651        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
652        LPAccount *account;
653       
654        while (account = [accountEnum nextObject]) {
655                if ([account isEnabled]) {
656                        NSString *accountName = [account name];
657                        if ([accountName length] > 0) {
658                                computedName = accountName;
659                                break;
660                        }
661                }
662        }
663       
664        return computedName;
665}
666
667- (LPStatus)p_computedGlobalAccountStatus
668{
669        return [self p_accountsFirstNonOfflineStatusForKey:@"status"];
670}
671
672- (NSString *)p_computedGlobalAccountStatusMessage
673{
674        // Check whether there is some account trying to get connected. If there is, we want to use this as the prevailing
675        // status message to be displayed to the user.
676        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
677        LPAccount *account;
678       
679        LPStatus status = LPStatusOffline;
680       
681        while (status != LPStatusConnecting && (account = [accountEnum nextObject]))
682                if ([account isEnabled])
683                        status = [account status];
684       
685       
686        if (account != nil)
687                return [account statusMessage];
688        else
689                return [self p_accountsFirstNonNilObjectValueForKey:@"statusMessage"];
690}
691
692- (LPStatus)p_computedGlobalAccountTargetStatus
693{
694        return [self p_accountsFirstNonOfflineStatusForKey:@"targetStatus"];
695}
696
697- (BOOL)p_computedGlobalAccountOnlineFlag
698{
699        return ([self p_firstAccountPassingOwnPredicate:@selector(isOnline)] != nil);
700}
701
702- (BOOL)p_computedGlobalAccountOfflineFlag
703{
704        // We can't use the p_firstAccountPassingOwnPredicate: method because we want the inverse: we want to know if all the accounts are offline
705        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
706        LPAccount *account;
707       
708        BOOL isOffline = YES;
709       
710        while (isOffline == YES && (account = [accountEnum nextObject]))
711                isOffline = [account isOffline];
712       
713        return isOffline;
714}
715
716- (BOOL)p_computedGlobalAccountDebuggerFlag
717{
718        return ([self p_firstAccountPassingOwnPredicate:@selector(isDebugger)] != nil);
719}
720
721- (BOOL)p_computedGlobalAccountTryingToAutoReconnectFlag
722{
723        return ([self p_firstAccountPassingOwnPredicate:@selector(isTryingToAutoReconnect)] != nil);
724}
725
726- (NSImage *)p_computedGlobalAccountAvatar
727{
728        return [self p_accountsFirstNonNilObjectValueForKey:@"avatar"];
729}
730
731- (void)p_computedGlobalAccountSMSCredit:(int *)smsCredit nrOfFreeMessages:(int *)smsFreeMessages nrOfTotalSent:(int *)smsTotalSent
732{
733        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
734        LPAccount *account = nil;
735       
736        *smsCredit = *smsFreeMessages = *smsTotalSent = LPAccountSMSCreditUnknown;
737       
738        while (account = [accountEnum nextObject]) {
739                if ([account isEnabled]) {
740                        if ([account SMSCreditAvailable] != LPAccountSMSCreditUnknown) {
741                                if (*smsCredit == LPAccountSMSCreditUnknown)
742                                        *smsCredit = 0;
743                                *smsCredit += [account SMSCreditAvailable];
744                        }
745                       
746                        if ([account nrOfFreeSMSMessagesAvailable] != LPAccountSMSCreditUnknown) {
747                                if (*smsFreeMessages == LPAccountSMSCreditUnknown)
748                                        *smsFreeMessages = 0;
749                                *smsFreeMessages += [account nrOfFreeSMSMessagesAvailable];
750                        }
751                       
752                        if ([account nrOfSMSMessagesSentThisMonth] != LPAccountSMSCreditUnknown) {
753                                if (*smsTotalSent == LPAccountSMSCreditUnknown)
754                                        *smsTotalSent = 0;
755                                *smsTotalSent += [account nrOfSMSMessagesSentThisMonth];
756                        }
757                }
758        }
759}
760
761#pragma mark -
762
763- (void)p_updateCachedGlobalAccountValuesForAllKeys
764{
765        [self p_updateCachedGlobalAccountValueForKey:nil];
766}
767
768- (void)p_updateCachedGlobalAccountValueForKey:(NSString *)key
769{
770        // Update the cached values of any account attribute that has changed
771        if (key == nil || [key isEqualToString:@"name"]) {
772                [self willChangeValueForKey:@"name"];
773                [m_globalAccountName release];
774                m_globalAccountName = [[self p_computedGlobalAccountName] copy];
775                [self didChangeValueForKey:@"name"];
776        }
777        if (key == nil || [key isEqualToString:@"status"]) {
778                [self willChangeValueForKey:@"status"];
779                m_globalAccountStatus = [self p_computedGlobalAccountStatus];
780                [self didChangeValueForKey:@"status"];
781        }
782        if (key == nil || [key isEqualToString:@"statusMessage"]) {
783                [self willChangeValueForKey:@"statusMessage"];
784                [m_globalAccountStatusMessage release];
785                m_globalAccountStatusMessage = [[self p_computedGlobalAccountStatusMessage] copy];
786                [self didChangeValueForKey:@"statusMessage"];
787        }
788        if (key == nil || [key isEqualToString:@"targetStatus"]) {
789                [self willChangeValueForKey:@"targetStatus"];
790                m_globalAccountTargetStatus = [self p_computedGlobalAccountTargetStatus];
791                [self didChangeValueForKey:@"targetStatus"];
792        }
793        if (key == nil || [key isEqualToString:@"online"]) {
794                [self willChangeValueForKey:@"online"];
795                m_globalAccountOnlineFlag = [self p_computedGlobalAccountOnlineFlag];
796                [self didChangeValueForKey:@"online"];
797        }
798        if (key == nil || [key isEqualToString:@"offline"]) {
799                [self willChangeValueForKey:@"offline"];
800                m_globalAccountOfflineFlag = [self p_computedGlobalAccountOfflineFlag];
801                [self didChangeValueForKey:@"offline"];
802        }
803        if (key == nil || [key isEqualToString:@"debugger"]) {
804                [self willChangeValueForKey:@"debugger"];
805                m_globalAccountDebuggerFlag = [self p_computedGlobalAccountDebuggerFlag];
806                [self didChangeValueForKey:@"debugger"];
807        }
808        if (key == nil || [key isEqualToString:@"tryingToAutoReconnect"]) {
809                [self willChangeValueForKey:@"tryingToAutoReconnect"];
810                m_globalAccountReconnectingFlag = [self p_computedGlobalAccountTryingToAutoReconnectFlag];
811                [self didChangeValueForKey:@"tryingToAutoReconnect"];
812        }
813        if (key == nil || [key isEqualToString:@"avatar"]) {
814                [self willChangeValueForKey:@"avatar"];
815                [m_globalAccountAvatar release];
816                m_globalAccountAvatar = [[self p_computedGlobalAccountAvatar] retain];
817                [self didChangeValueForKey:@"avatar"];
818        }
819        if (key == nil || [key isEqualToString:@"SMSCreditValues"]) {
820                [self willChangeValueForKey:@"SMSCreditValues"];
821                [self p_computedGlobalAccountSMSCredit:&m_globalAccountSMSCredit
822                                                          nrOfFreeMessages:&m_globalAccountSMSFreeMessages
823                                                                 nrOfTotalSent:&m_globalAccountSMSTotalSent];
824                [self didChangeValueForKey:@"SMSCreditValues"];
825        }
826}
827       
828
829
830#pragma mark -
831#pragma mark Actions
832
833
834- (IBAction)connectAllEnabledAccounts:(id)sender
835{
836        [self setTargetStatus:LPStatusAvailable];
837}
838
839
840- (IBAction)disconnectAllAccounts:(id)sender
841{
842        NSEnumerator    *accountEnumerator = [m_accounts objectEnumerator];
843        LPAccount               *account;
844        while (account = [accountEnumerator nextObject]) {
845                [account setTargetStatus:LPStatusOffline];
846        }
847}
848
849
850#pragma mark -
851#pragma mark Attributes computed from all the accounts managed by this controller
852
853
854- (NSString *)name
855{
856        return [[m_globalAccountName copy] autorelease];
857}
858
859- (void)setName:(NSString *)theName
860{
861        [m_accounts setValue:theName forKey:@"name"];
862}
863
864- (LPStatus)status
865{
866        return m_globalAccountStatus;
867}
868
869- (NSString *)statusMessage
870{
871        return [[m_globalAccountStatusMessage copy] autorelease];
872}
873
874- (void)setStatusMessage:(NSString *)theStatusMessage
875{
876        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
877        LPAccount *account;
878        while (account = [accountEnum nextObject])
879                if ([account isEnabled])
880                        [account setStatusMessage:theStatusMessage];
881}
882
883- (void)setStatusMessage:(NSString *)theStatusMessage saveToServer:(BOOL)saveFlag
884{
885        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
886        LPAccount *account;
887        while (account = [accountEnum nextObject])
888                if ([account isEnabled])
889                        [account setStatusMessage:theStatusMessage saveToServer:saveFlag];
890}
891
892- (LPStatus)targetStatus
893{
894        return m_globalAccountTargetStatus;
895}
896
897- (void)setTargetStatus:(LPStatus)theStatus
898{
899        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
900        LPAccount *account;
901        while (account = [accountEnum nextObject])
902                if ([account isEnabled])
903                        [account setTargetStatus:theStatus];
904}
905
906- (void)setTargetStatus:(LPStatus)theStatus saveToServer:(BOOL)saveFlag
907{
908        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
909        LPAccount *account;
910        while (account = [accountEnum nextObject])
911                if ([account isEnabled])
912                        [account setTargetStatus:theStatus saveToServer:saveFlag];
913}
914
915- (void)setTargetStatus:(LPStatus)theStatus message:(NSString *)theMessage saveToServer:(BOOL)saveFlag
916{
917        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
918        LPAccount *account;
919        while (account = [accountEnum nextObject])
920                if ([account isEnabled])
921                        [account setTargetStatus:theStatus message:theMessage saveToServer:saveFlag];
922}
923
924- (void)setTargetStatus:(LPStatus)theStatus message:(NSString *)theMessage saveToServer:(BOOL)saveFlag alsoSaveStatusMessage:(BOOL)saveMsg
925{
926        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
927        LPAccount *account;
928        while (account = [accountEnum nextObject])
929                if ([account isEnabled])
930                        [account setTargetStatus:theStatus message:theMessage saveToServer:saveFlag alsoSaveStatusMessage:saveMsg];
931}
932
933- (BOOL)isOnline
934{
935        return m_globalAccountOnlineFlag;
936}
937
938- (BOOL)isOffline
939{
940        return m_globalAccountOfflineFlag;
941}
942
943- (BOOL)isDebugger
944{
945        return m_globalAccountDebuggerFlag;
946}
947
948- (BOOL)isTryingToAutoReconnect
949{
950        return m_globalAccountReconnectingFlag;
951}
952
953- (NSImage *)avatar
954{
955        return [[m_globalAccountAvatar retain] autorelease];
956}
957
958- (void)setAvatar:(NSImage *)avatar
959{
960        NSEnumerator *accountEnum = [m_accounts objectEnumerator];
961        LPAccount *account;
962        while (account = [accountEnum nextObject])
963                if ([account isEnabled])
964                        [account setAvatar:avatar];
965}
966
967- (LPAccount *)accountForSendingSMS
968{
969        NSEnumerator *accountsEnum = [[self accounts] objectEnumerator];
970        LPAccount *account;
971       
972        while (account = [accountsEnum nextObject]) {
973                NSDictionary    *itemsInfoByFeature = [[account serverItemsInfo] itemsByFeature];
974                NSArray                 *itemForSMS = [itemsInfoByFeature objectForKey:@"sapo:sms"];
975               
976                if (itemForSMS != nil && [itemForSMS count] > 0) {
977                        // This one will do
978                        break;
979                }
980        }
981       
982        return account;
983}
984
985- (int)SMSCreditAvailable
986{
987        return m_globalAccountSMSCredit;
988}
989
990- (int)nrOfFreeSMSMessagesAvailable
991{
992        return m_globalAccountSMSFreeMessages;
993}
994
995- (int)nrOfSMSMessagesSentThisMonth
996{
997        return m_globalAccountSMSTotalSent;
998}
999
1000
1001#pragma mark -
1002#pragma mark LPAccount Delegate Methods
1003
1004
1005- (void)account:(LPAccount *)account didReceiveErrorNamed:(NSString *)errorName errorKind:(int)errorKind errorCode:(int)errorCode
1006{
1007        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveErrorNamed:errorKind:errorCode:)]) {
1008                [m_delegate accountsController:self account:account didReceiveErrorNamed:errorName errorKind:errorKind errorCode:errorCode];
1009        }
1010}
1011
1012
1013- (void)account:(LPAccount *)account didReceiveSavedStatus:(LPStatus)status message:(NSString *)statusMessage
1014{
1015        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveSavedStatus:message:)]) {
1016                [m_delegate accountsController:self account:account didReceiveSavedStatus:status message:statusMessage];
1017        }
1018}
1019
1020
1021- (void)account:(LPAccount *)account didReceiveLiveUpdateURL:(NSString *)URLString
1022{
1023        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveLiveUpdateURL:)]) {
1024                [m_delegate accountsController:self account:account didReceiveLiveUpdateURL:URLString];
1025        }
1026}
1027
1028
1029- (void)account:(LPAccount *)account didReceiveServerVarsDictionary:(NSDictionary *)varsValues
1030{
1031        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveServerVarsDictionary:)]) {
1032                [m_delegate accountsController:self account:account didReceiveServerVarsDictionary:varsValues];
1033        }
1034}
1035
1036
1037- (void)account:(LPAccount *)account didReceiveOfflineMessageFromJID:(NSString *)jid nick:(NSString *)nick timestamp:(NSString *)timestamp subject:(NSString *)subject plainTextVariant:(NSString *)plainTextVariant XHTMLVariant:(NSString *)xhtmlVariant URLs:(NSArray *)urls
1038{
1039        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveOfflineMessageFromJID:nick:timestamp:subject:plainTextVariant:XHTMLVariant:URLs:)]) {
1040                [m_delegate accountsController:self account:account didReceiveOfflineMessageFromJID:jid nick:nick timestamp:timestamp
1041                                                           subject:subject plainTextVariant:plainTextVariant XHTMLVariant:xhtmlVariant URLs:urls];
1042        }
1043}
1044
1045
1046- (void)account:(LPAccount *)account didReceiveHeadlineNotificationMessageFromChannel:(NSString *)channelName subject:(NSString *)subject body:(NSString *)body itemURL:(NSString *)itemURL flashURL:(NSString *)flashURL iconURL:(NSString *)iconURL
1047{
1048        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveHeadlineNotificationMessageFromChannel:subject:body:itemURL:flashURL:iconURL:)]) {
1049                [m_delegate accountsController:self account:account didReceiveHeadlineNotificationMessageFromChannel:channelName subject:subject body:body
1050                                                           itemURL:itemURL flashURL:flashURL iconURL:iconURL];
1051        }
1052}
1053
1054
1055- (void)account:(LPAccount *)account didReceiveChatRoomsList:(NSArray *)chatRoomsList forHost:(NSString *)host
1056{
1057        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveChatRoomsList:forHost:)]) {
1058                [m_delegate accountsController:self account:account didReceiveChatRoomsList:chatRoomsList forHost:host];
1059        }
1060}
1061
1062
1063- (void)account:(LPAccount *)account didReceiveInfo:(NSDictionary *)chatRoomInfo forChatRoomWithJID:(NSString *)roomJID
1064{
1065        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveInfo:forChatRoomWithJID:)]) {
1066                [m_delegate accountsController:self account:account didReceiveInfo:chatRoomInfo forChatRoomWithJID:roomJID];
1067        }
1068}
1069
1070
1071- (void)account:(LPAccount *)account didReceiveInvitationToRoomWithJID:(NSString *)roomJID from:(NSString *)senderJID reason:(NSString *)reason password:(NSString *)password
1072{
1073        if ([m_delegate respondsToSelector:@selector(accountsController:account:didReceiveInvitationToRoomWithJID:from:reason:password:)]) {
1074                [m_delegate accountsController:self account:account didReceiveInvitationToRoomWithJID:roomJID from:senderJID reason:reason password:password];
1075        }
1076}
1077
1078
1079#pragma mark -
1080#pragma mark Bridge Notifications
1081
1082
1083- (void)leapfrogBridge_accountConnectedToServer:(NSString *)accountUUID :(NSString *)localAddress :(NSString *)remoteAddress
1084{
1085        [[self accountForUUID:accountUUID] handleAccountConnectedToServerUsingLocalAddress:localAddress remoteAddress:remoteAddress];
1086}
1087
1088
1089- (void)leapfrogBridge_connectionError:(NSString *)accountUUID :(NSString *)errorName :(int)errorKind :(int)errorCode
1090{
1091        [[self accountForUUID:accountUUID] handleConnectionErrorWithName:errorName kind:errorKind code:errorCode];
1092}
1093
1094
1095- (void)leapfrogBridge_statusUpdated:(NSString *)accountUUID :(NSString *)status :(NSString *)statusMessage
1096{
1097        [[self accountForUUID:accountUUID] handleStatusUpdated:status message:statusMessage];
1098}
1099
1100
1101- (void)leapfrogBridge_savedStatusReceived:(NSString *)accountUUID :(NSString *)status :(NSString *)statusMessage
1102{
1103        [[self accountForUUID:accountUUID] handleSavedStatusReceived:status message:statusMessage];
1104}
1105
1106
1107- (void)leapfrogBridge_selfAvatarChanged:(NSString *)accountUUID :(NSString *)type :(NSData *)avatarData
1108{
1109        [[self accountForUUID:accountUUID] handleSelfAvatarChangedWithType:type data:avatarData];
1110}
1111
1112
1113- (oneway void)leapfrogBridge_accountXmlIO:(NSString *)accountUUID :(BOOL)isInbound :(NSString *)xml
1114{
1115        [[self accountForUUID:accountUUID] handleAccountXmlIO:xml isInbound:isInbound];
1116}
1117
1118
1119
1120
1121- (void)leapfrogBridge_offlineMessageReceived:(NSString *)accountUUID :(NSString *)timestamp :(NSString *)jid :(NSString *)nick :(NSString *)subject :(NSString *)plainTextMessage :(NSString *)XHTMLMessage :(NSArray *)URLs
1122{
1123        [[self accountForUUID:accountUUID] handleReceivedOfflineMessageAt:(NSString *)timestamp
1124                                                                                                                          fromJID:(NSString *)jid nickname:(NSString *)nick
1125                                                                                                                          subject:(NSString *)subject
1126                                                                                                         plainTextMessage:(NSString *)plainTextMessage XHTMLMessaage:(NSString *)XHTMLMessage
1127                                                                                                                                 URLs:(NSArray *)URLs];
1128}
1129
1130
1131- (void)leapfrogBridge_headlineNotificationMessageReceived:(NSString *)accountUUID :(NSString *)channel :(NSString *)item_url :(NSString *)flash_url :(NSString *)icon_url :(NSString *)nick :(NSString *)subject :(NSString *)plainTextMessage :(NSString *)XHTMLMessage
1132{
1133        [[self accountForUUID:accountUUID] handleReceivedHeadlineNotificationMessageFromChannel:channel
1134                                                                                                                                                                        itemURL:item_url flashURL:flash_url iconURL:icon_url
1135                                                                                                                                                                   nickname:nick subject:subject
1136                                                                                                                                                   plainTextMessage:plainTextMessage
1137                                                                                                                                                           XHTMLMessage:XHTMLMessage];
1138}
1139
1140
1141- (void)leapfrogBridge_smsCreditUpdated:(NSString *)accountUUID :(int)credit :(int)free_msgs :(int)total_sent_this_month
1142{
1143        [[self accountForUUID:accountUUID] handleSMSCreditUpdated:credit freeMessages:free_msgs totalSent:total_sent_this_month];
1144}
1145
1146
1147- (void)leapfrogBridge_smsSent:(NSString *)accountUUID
1148                                                          :(int)result :(int)nr_used_msgs :(int)nr_used_chars
1149                                                          :(NSString *)destination_phone_nr :(NSString *)body
1150                                                          :(int)credit :(int)free_msgs :(int)total_sent_this_month
1151{
1152        [[self accountForUUID:accountUUID] handleSMSSentWithResult:result nrUsedMessages:nr_used_msgs nrUsedChars:nr_used_chars
1153                                                                                          destinationPhoneNr:destination_phone_nr body:body
1154                                                                                                                  credit:credit freeMessages:free_msgs totalSent:total_sent_this_month];
1155}
1156
1157
1158- (void)leapfrogBridge_smsReceived:(NSString *)accountUUID
1159                                                                  :(NSString *)date_received
1160                                                                  :(NSString *)source_phone_nr :(NSString *)body
1161                                                                  :(int)credit :(int)free_msgs :(int)total_sent_this_month
1162{
1163        [[self accountForUUID:accountUUID] handleSMSReceivedAt:date_received fromPhoneNr:source_phone_nr body:body
1164                                                                                                          credit:credit freeMessages:free_msgs totalSent:total_sent_this_month];
1165}
1166
1167
1168- (void)leapfrogBridge_serverItemsUpdated:(NSString *)accountUUID :(NSArray *)serverItems
1169{
1170        [[self accountForUUID:accountUUID] handleServerItemsUpdated:serverItems];
1171}
1172
1173
1174- (void)leapfrogBridge_serverItemInfoUpdated:(NSString *)accountUUID :(NSString *)item :(NSString *)name :(NSArray *)identities :(NSArray *)features
1175{
1176        [[self accountForUUID:accountUUID] handleInfoUpdatedForServerItem:item withName:name identities:identities features:features];
1177}
1178
1179
1180- (void)leapfrogBridge_sapoAgentsUpdated:(NSString *)accountUUID :(NSDictionary *)sapoAgentsDescription
1181{
1182        [[self accountForUUID:accountUUID] handleSapoAgentsUpdated:sapoAgentsDescription];
1183}
1184
1185
1186- (void)leapfrogBridge_chatRoomsListReceived:(NSString *)host :(NSArray *)roomsList
1187{
1188        // DEBUG
1189        //NSLog(@"MUC ITEMS UPDATED:\nHost: %@\nRooms: %@\n", host, roomsList);
1190       
1191#warning CHAT ROOMS LIST
1192//      if ([m_delegate respondsToSelector:@selector(account:didReceiveChatRoomsList:forHost:)]) {
1193//              [m_delegate account:self didReceiveChatRoomsList:roomsList forHost:host];
1194//      }
1195}
1196
1197
1198- (void)leapfrogBridge_chatRoomInfoReceived:(NSString *)roomJID :(NSDictionary *)infoDict
1199{
1200        // DEBUG
1201        //NSLog(@"MUC ITEM INFO UPDATED:\nRoom JID: %@\nInfo: %@\n", roomJID, infoDict);
1202       
1203#warning CHAT ROOMS INFO
1204//      if ([m_delegate respondsToSelector:@selector(account:didReceiveInfo:forChatRoomWithJID:)]) {
1205//              [m_delegate account:self didReceiveInfo:infoDict forChatRoomWithJID:roomJID];
1206//      }
1207}
1208
1209
1210- (void)leapfrogBridge_groupChatInvitationReceived:(NSString *)accountUUID :(NSString *)roomJID :(NSString *)sender :(NSString *)reason :(NSString *)password
1211{
1212        [[self accountForUUID:accountUUID] handleReceivedInvitationToGroupChat:roomJID from:sender reason:reason password:password];
1213}
1214
1215
1216- (void)leapfrogBridge_liveUpdateURLReceived:(NSString *)accountUUID :(NSString *)liveUpdateURLStr
1217{
1218        [[self accountForUUID:accountUUID] handleReceivedLiveUpdateURLString:liveUpdateURLStr];
1219}
1220
1221
1222- (void)leapfrogBridge_sapoChatOrderReceived:(NSString *)accountUUID :(NSDictionary *)orderDict
1223{
1224        [[self accountForUUID:accountUUID] handleReceivedSapoChatOrderDictionary:orderDict];
1225}
1226
1227
1228- (void)leapfrogBridge_transportRegistrationStatusUpdated:(NSString *)accountUUID :(NSString *)transportAgent :(BOOL)isRegistered :(NSString *)registeredUsername
1229{
1230        [[self accountForUUID:accountUUID] handleTransportRegistrationStatusUpdatedForAgent:transportAgent
1231                                                                                                                                                         isRegistered:isRegistered
1232                                                                                                                                                                 username:registeredUsername];
1233}
1234
1235- (void)leapfrogBridge_transportLoggedInStatusUpdated:(NSString *)accountUUID :(NSString *)transportAgent :(BOOL)isLoggedIn
1236{
1237        [[self accountForUUID:accountUUID] handleTransportLoggedInStatusUpdatedForAgent:transportAgent isLoggedIn:isLoggedIn];
1238}
1239
1240
1241- (void)leapfrogBridge_serverVarsReceived:(NSString *)accountUUID :(NSDictionary *)varsValues
1242{
1243        [[self accountForUUID:accountUUID] handleReceivedServerVarsDictionary:varsValues];
1244}
1245
1246- (void)leapfrogBridge_selfVCardChanged:(NSString *)accountUUID :(NSDictionary *)vCard
1247{
1248        [[self accountForUUID:accountUUID] handleSelfVCardChanged:vCard];
1249}
1250
1251- (void)leapfrogBridge_debuggerStatusChanged:(NSString *)accountUUID :(BOOL)isDebugger
1252{
1253        [[self accountForUUID:accountUUID] handleDebuggerStatusChanged:isDebugger];
1254}
1255
1256@end
Note: See TracBrowser for help on using the browser.