Changeset 3638

Show
Ignore:
Timestamp:
04/17/07 01:39:07 (1 year ago)
Author:
timothy
Message:

Adds the basics for Jabber group chat support. #454

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Chat Core.xcodeproj/project.pbxproj

    r3637 r3638  
    7575                32C46E1B0B3AB37E00B96B27 /* MVICBChatUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C46E190B3AB37E00B96B27 /* MVICBChatUser.m */; }; 
    7676                431261C3072EE37A00720AD1 /* MVSILCFileTransfer.m in Sources */ = {isa = PBXBuildFile; fileRef = 431261C1072EE37A00720AD1 /* MVSILCFileTransfer.m */; }; 
     77                DD4741310BD35A2E00D93AB9 /* MVXMPPChatRoom.m in Sources */ = {isa = PBXBuildFile; fileRef = DD47412F0BD35A2E00D93AB9 /* MVXMPPChatRoom.m */; }; 
    7778                DDF64CE60BD29E41009E8FF6 /* MVXMPPChatConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = DDF64CE40BD29E41009E8FF6 /* MVXMPPChatConnection.m */; }; 
    7879                DDF64D530BD2A4F6009E8FF6 /* Acid.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDF64D520BD2A4F6009E8FF6 /* Acid.framework */; }; 
     
    164165                431261C0072EE37A00720AD1 /* MVSILCFileTransfer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MVSILCFileTransfer.h; path = "Chat Core/MVSILCFileTransfer.h"; sourceTree = "<group>"; }; 
    165166                431261C1072EE37A00720AD1 /* MVSILCFileTransfer.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = MVSILCFileTransfer.m; path = "Chat Core/MVSILCFileTransfer.m"; sourceTree = "<group>"; }; 
     167                DD47412E0BD35A2E00D93AB9 /* MVXMPPChatRoom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MVXMPPChatRoom.h; path = "Chat Core/MVXMPPChatRoom.h"; sourceTree = "<group>"; }; 
     168                DD47412F0BD35A2E00D93AB9 /* MVXMPPChatRoom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MVXMPPChatRoom.m; path = "Chat Core/MVXMPPChatRoom.m"; sourceTree = "<group>"; }; 
    166169                DDF64CE30BD29E41009E8FF6 /* MVXMPPChatConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MVXMPPChatConnection.h; path = "Chat Core/MVXMPPChatConnection.h"; sourceTree = "<group>"; }; 
    167170                DDF64CE40BD29E41009E8FF6 /* MVXMPPChatConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MVXMPPChatConnection.m; path = "Chat Core/MVXMPPChatConnection.m"; sourceTree = "<group>"; }; 
     
    310313                                DDF64CE40BD29E41009E8FF6 /* MVXMPPChatConnection.m */, 
    311314                                DDF64CE30BD29E41009E8FF6 /* MVXMPPChatConnection.h */, 
     315                                DD47412F0BD35A2E00D93AB9 /* MVXMPPChatRoom.m */, 
     316                                DD47412E0BD35A2E00D93AB9 /* MVXMPPChatRoom.h */, 
    312317                                DDF64E180BD2CABE009E8FF6 /* MVXMPPChatUser.m */, 
    313318                                DDF64E170BD2CABE009E8FF6 /* MVXMPPChatUser.h */, 
     
    570575                                DDF64CE60BD29E41009E8FF6 /* MVXMPPChatConnection.m in Sources */, 
    571576                                DDF64E1A0BD2CABE009E8FF6 /* MVXMPPChatUser.m in Sources */, 
     577                                DD4741310BD35A2E00D93AB9 /* MVXMPPChatRoom.m in Sources */, 
    572578                        ); 
    573579                        runOnlyForDeploymentPostprocessing = 0; 
  • trunk/Chat Core/MVChatConnection.h

    r3637 r3638  
    373373#pragma mark - 
    374374 
     375- (MVChatRoom *) joinedChatRoomWithUniqueIdentifier:(id) identifier; 
    375376- (MVChatRoom *) joinedChatRoomWithName:(NSString *) room; 
    376377 
  • trunk/Chat Core/MVChatConnection.m

    r3637 r3638  
    633633} 
    634634 
     635- (MVChatRoom *) joinedChatRoomWithUniqueIdentifier:(id) identifier { 
     636        @synchronized( _joinedRooms ) { 
     637                return [_joinedRooms objectForKey:identifier]; 
     638        } return nil; 
     639} 
     640 
    635641- (MVChatRoom *) joinedChatRoomWithName:(NSString *) name { 
    636642        @synchronized( _joinedRooms ) { 
    637                 return [_joinedRooms objectForKey:[name lowercaseString]]; 
    638         } return nil; 
     643                NSEnumerator *enumerator = [_joinedRooms objectEnumerator]; 
     644                MVChatRoom *room = nil; 
     645 
     646                while( ( room = [enumerator nextObject] ) ) 
     647                        if( [[room name] isEqualToString:name] ) 
     648                                return room; 
     649        } 
     650 
     651        return nil; 
    639652} 
    640653 
     
    899912- (void) _addJoinedRoom:(MVChatRoom *) room { 
    900913        @synchronized( _joinedRooms ) { 
    901                 [_joinedRooms setObject:room forKey:[[room name] lowercaseString]]; 
     914                [_joinedRooms setObject:room forKey:[room uniqueIdentifier]]; 
    902915        } 
    903916} 
     
    905918- (void) _removeJoinedRoom:(MVChatRoom *) room { 
    906919        @synchronized( _joinedRooms ) { 
    907                 [_joinedRooms removeObjectForKey:[[room name] lowercaseString]]; 
     920                [_joinedRooms removeObjectForKey:[room uniqueIdentifier]]; 
    908921        } 
    909922} 
  • trunk/Chat Core/MVChatRoom.h

    r3597 r3638  
    9999@property(readonly, ivar) unsigned long modes; 
    100100 
     101@property(readonly) MVChatUser *localMemberUser; 
    101102@property(readonly) NSSet *memberUsers; 
    102103@property(readonly) NSSet *bannedUsers; 
     
    128129- (unsigned long) modes; 
    129130 
     131- (MVChatUser *) localMemberUser; 
    130132- (NSSet *) memberUsers; 
    131133- (NSSet *) bannedUsers; 
  • trunk/Chat Core/MVChatRoom.m

    r3597 r3638  
    375375#pragma mark - 
    376376 
     377- (MVChatUser *) localMemberUser { 
     378        return [[self connection] localUser]; 
     379} 
     380 
    377381- (NSSet *) memberUsers { 
    378382        @synchronized( _memberUsers ) { 
  • trunk/Chat Core/MVChatUser.m

    r3626 r3638  
    454454 
    455455@implementation MVChatUser (MVChatUserPrivate) 
     456- (void) _setType:(MVChatUserType) type { 
     457        _type = type; 
     458} 
     459 
    456460- (void) _setUniqueIdentifier:(id) identifier { 
    457461        MVSafeAdoptAssign( &_uniqueIdentifier, ( [identifier conformsToProtocol:@protocol( NSCopying )] ? [identifier copyWithZone:nil] : [identifier retain] ) ); 
  • trunk/Chat Core/MVChatUserPrivate.h

    r3498 r3638  
    22 
    33@interface MVChatUser (MVChatUserPrivate) 
     4- (void) _setType:(MVChatUserType) type; 
    45- (void) _setUniqueIdentifier:(id) identifier; 
    56- (void) _setNickname:(NSString *) name; 
  • trunk/Chat Core/MVICBChatConnection.m

    r3599 r3638  
    307307        NSParameterAssert( [identifier isKindOfClass:[NSString class]] ); 
    308308 
    309         MVChatRoom *room; 
    310         @synchronized( _joinedRooms ) { 
    311                 room = [self joinedChatRoomWithName:identifier]; 
    312                 if( !room ) { 
    313                         room = [[MVICBChatRoom alloc] initWithName:identifier 
    314                                                                                   andConnection:self]; 
    315                         [self _addJoinedRoom:room]; 
    316                 } 
    317         } 
     309        MVChatRoom *room = [self joinedChatRoomWithUniqueIdentifier:identifier]; 
     310        if( !room ) { 
     311                room = [[MVICBChatRoom alloc] initWithName:identifier 
     312                                                                          andConnection:self]; 
     313                [self _addJoinedRoom:room]; 
     314        } 
     315 
    318316        return room; 
    319317} 
  • trunk/Chat Core/MVXMPPChatConnection.h

    r3637 r3638  
    44@class JabberSession; 
    55@class JabberID; 
     6@class XMLElement; 
    67 
    78@interface MVXMPPChatConnection : MVChatConnection { 
     
    1213        NSString *_server; 
    1314        NSString *_username; 
     15        NSString *_nickname; 
    1416        NSString *_password; 
    1517        NSMutableDictionary *_knownUsers; 
     
    2123- (JabberSession *) _chatSession; 
    2224- (JabberID *) _localUserID; 
     25- (XMLElement *) _capabilitiesElement; 
     26- (XMLElement *) _multiUserChatExtensionElement; 
    2327@end 
  • trunk/Chat Core/MVXMPPChatConnection.m

    r3637 r3638  
    33#import "MVXMPPChatConnection.h" 
    44#import "MVXMPPChatUser.h" 
     5#import "MVXMPPChatRoom.h" 
    56#import "MVUtilities.h" 
    67#import "MVChatPluginManager.h" 
    78#import "NSMethodSignatureAdditions.h" 
     9#import "NSStringAdditions.h" 
    810 
    911@implementation MVXMPPChatConnection 
     
    1921                _server = @"jabber.org"; 
    2022                _username = [NSUserName() retain]; 
     23                _nickname = [_username retain]; 
    2124                _session = [[JabberSession alloc] init]; 
    2225 
     
    2932                [_session addObserver:self selector:@selector( outgoingPacket: ) name:JSESSION_RAWDATA_OUT]; 
    3033                [_session addObserver:self selector:@selector( incomingPacket: ) name:JSESSION_RAWDATA_IN]; 
    31                 [_session addObserver:self selector:@selector( incomingPrivateMessage: ) xpath:@"/message[@type='chat']"]; 
     34                [_session addObserver:self selector:@selector( incomingMessage: ) xpath:@"/message"]; 
     35                [_session addObserver:self selector:@selector( incomingPresence: ) xpath:@"/presence"]; 
    3236        } 
    3337 
     
    4751        [_server release]; 
    4852        [_username release]; 
     53        [_nickname release]; 
    4954        [_password release]; 
    5055        [_knownUsers release]; 
     
    5459        _server = nil; 
    5560        _username = nil; 
     61        _nickname = nil; 
    5662        _password = nil; 
    5763        _knownUsers = nil; 
     
    106112 
    107113- (void) setNickname:(NSString *) newNickname { 
    108         [self setUsername:newNickname]; 
     114        NSParameterAssert( newNickname != nil ); 
     115        NSParameterAssert( [newNickname length] > 0 ); 
     116        MVSafeCopyAssign( &_nickname, newNickname ); 
    109117} 
    110118 
    111119- (NSString *) nickname { 
    112         return [self username]
     120        return _nickname
    113121} 
    114122 
    115123- (NSString *) preferredNickname { 
    116         return [self username]; 
     124        return [self nickname]; 
    117125} 
    118126 
     
    120128 
    121129- (void) setNicknamePassword:(NSString *) newPassword { 
    122         [self setPassword:newPassword]; 
     130        // not supported 
    123131} 
    124132 
    125133- (NSString *) nicknamePassword { 
    126         return [self password]
     134        return nil
    127135} 
    128136 
     
    186194        NSParameterAssert( [identifier isKindOfClass:[NSString class]] || [identifier isKindOfClass:[JabberID class]] ); 
    187195 
    188         if( [identifier isKindOfClass:[JabberID class]] ) 
    189                 identifier = [identifier completeID]; 
    190         if( [identifier isEqualToString:[[self localUser] uniqueIdentifier]] ) 
     196        if( [identifier isKindOfClass:[NSString class]] ) 
     197                identifier = [[[JabberID allocWithZone:nil] initWithString:identifier] autorelease]; 
     198        if( [identifier isEqual:[[self localUser] uniqueIdentifier]] ) 
    191199                return [self localUser]; 
    192200 
     
    196204        MVChatUser *user = nil; 
    197205        @synchronized( _knownUsers ) { 
    198                 user = [_knownUsers objectForKey:identifier]; 
     206                user = [_knownUsers objectForKey:[identifier completeID]]; 
    199207                if( user ) return user; 
    200208 
    201                 JabberID *jabberID = [[JabberID alloc] initWithString:identifier]; 
    202                 user = [[MVXMPPChatUser allocWithZone:nil] initWithJabberID:jabberID andConnection:self]; 
    203                 if( user ) [_knownUsers setObject:user forKey:identifier]; 
    204                 [jabberID release]; 
     209                user = [[MVXMPPChatUser allocWithZone:nil] initWithJabberID:identifier andConnection:self]; 
     210                if( user ) [_knownUsers setObject:user forKey:[identifier completeID]]; 
    205211        } 
    206212 
    207213        return [user autorelease]; 
     214} 
     215 
     216#pragma mark - 
     217 
     218- (void) joinChatRoomNamed:(NSString *) room withPassphrase:(NSString *) passphrase { 
     219        NSParameterAssert( room != nil ); 
     220        NSParameterAssert( [room length] > 0 ); 
     221 
     222        /* Example: 
     223        <presence from='hag66@shakespeare.lit/pda' to='darkcave@macbeth.shakespeare.lit/thirdwitch'> 
     224          <x xmlns='http://jabber.org/protocol/muc' /> 
     225        </presence> 
     226        */ 
     227 
     228        JabberID *roomId = [[JabberID allocWithZone:nil] initWithString:room]; 
     229        MVXMPPChatRoom *joiningRoom = (MVXMPPChatRoom *)[[self joinedChatRoomWithUniqueIdentifier:roomId] retain]; 
     230        if( joiningRoom && [joiningRoom isJoined] ) { 
     231                // already joined 
     232                [joiningRoom release]; 
     233                [roomId release]; 
     234                return; 
     235        } 
     236 
     237        JabberPresence *presence = [[JabberPresence allocWithZone:nil] initWithQName:JABBER_PRESENCE_QN]; 
     238        [presence putAttribute:@"from" withValue:[_localID escapedCompleteID]]; 
     239 
     240        NSString *localUserStringId = [[NSString allocWithZone:nil] initWithFormat:@"%@/%@", room, [self nickname]]; 
     241        [presence putAttribute:@"to" withValue:localUserStringId]; 
     242 
     243        [presence addElement:[self _capabilitiesElement]]; 
     244        XMLElement *x = [presence addElement:[self _multiUserChatExtensionElement]]; 
     245 
     246        if ([passphrase length]) 
     247                [[x addElementWithName:@"password"] addCData:passphrase]; 
     248 
     249        [_session sendElement:presence]; 
     250        [presence release]; 
     251 
     252        JabberID *localUserJabberId = [[JabberID allocWithZone:nil] initWithString:localUserStringId]; 
     253        MVXMPPChatUser *localUser = (MVXMPPChatUser *)[self chatUserWithUniqueIdentifier:localUserJabberId]; 
     254        [localUser _setRoomMember:YES]; 
     255        [localUser _setType:MVChatLocalUserType]; 
     256 
     257        if( ! joiningRoom ) 
     258                joiningRoom = [[MVXMPPChatRoom allocWithZone:nil] initWithJabberID:roomId andConnection:self]; 
     259        [joiningRoom _setLocalMemberUser:localUser]; 
     260        [joiningRoom _setDateJoined:nil]; 
     261        [joiningRoom _setDateParted:nil]; 
     262        [joiningRoom _clearMemberUsers]; 
     263        [joiningRoom _clearBannedUsers]; 
     264 
     265        [self _addJoinedRoom:joiningRoom]; 
     266 
     267        // joiningRoom will be released in incomingPresence 
     268 
     269        [localUserStringId release]; 
     270        [localUserJabberId release]; 
     271        [roomId release]; 
    208272} 
    209273 
     
    235299 
    236300- (void) outgoingPacket:(NSNotification *) notification { 
    237         NSString *string = [@"send: " stringByAppendingString:[[NSString alloc] initWithData:[notification object] encoding:NSUTF8StringEncoding]]; 
    238         NSLog(@"%@", string); 
     301        NSString *string = [[NSString alloc] initWithData:[notification object] encoding:NSUTF8StringEncoding]; 
     302        [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:string, @"message", [NSNumber numberWithBool:YES], @"outbound", nil]]; 
     303        [string release]; 
    239304} 
    240305 
    241306- (void) incomingPacket:(NSNotification *) notification { 
    242     NSString *string = [@"recv: " stringByAppendingString:[[NSString alloc] initWithData:[notification object] encoding:NSUTF8StringEncoding]]; 
    243         NSLog(@"%@", string); 
    244 
    245  
    246 - (void) incomingPrivateMessage:(NSNotification *) notification { 
     307    NSString *string = [[NSString alloc] initWithData:[notification object] encoding:NSUTF8StringEncoding]; 
     308        [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:string, @"message", [NSNumber numberWithBool:NO], @"outbound", nil]]; 
     309        [string release]; 
     310
     311 
     312- (void) incomingMessage:(NSNotification *) notification { 
    247313    JabberMessage *message = [notification object]; 
    248314 
     
    252318    case JMEVENT_NONE: { 
    253319                MVChatRoom *room = nil; 
    254                 MVChatUser *sender = [self chatUserWithUniqueIdentifier:[message from]]; 
     320                MVChatUser *sender = nil; 
     321 
     322                if( [[message type] isEqualToString:@"groupchat"] ) { 
     323                        room = [self joinedChatRoomWithUniqueIdentifier:[[message from] userhostJID]]; 
     324                        if( ! room ) return; 
     325                        sender = [self chatUserWithUniqueIdentifier:[message from]]; 
     326                        if( [sender isLocalUser] ) return; 
     327                } else { 
     328                        sender = [self chatUserWithUniqueIdentifier:[message from]]; 
     329                } 
     330 
    255331                NSMutableData *msgData = [[[message body] dataUsingEncoding:NSUTF8StringEncoding] mutableCopyWithZone:nil]; 
    256332 
    257333                NSMutableDictionary *msgAttributes = [[NSMutableDictionary allocWithZone:nil] init]; 
    258                 [msgAttributes setObject:sender forKey:@"sender"]; 
     334                [msgAttributes setObject:sender forKey:@"user"]; 
    259335                [msgAttributes setObject:msgData forKey:@"message"]; 
    260336 
     
    270346                if( ! [msgData length] ) return; 
    271347 
    272                 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:msgAttributes]; 
     348                if( room ) { 
     349                        [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:msgAttributes]; 
     350                } else { 
     351                        [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:msgAttributes]; 
     352                } 
    273353 
    274354                [msgData release]; 
    275355                [msgAttributes release]; 
    276  
    277356        break; 
    278357        } 
     
    284363    } 
    285364} 
     365 
     366- (void) incomingPresence:(NSNotification *) notification { 
     367    JabberPresence *presence = [notification object]; 
     368        JabberID *roomID = [[presence from] userhostJID]; 
     369        MVChatRoom *room = [self joinedChatRoomWithUniqueIdentifier:roomID]; 
     370 
     371        if( ! room ) return; 
     372 
     373        if ([[presence getAttribute:@"type"] isCaseInsensitiveEqualToString:@"error"]) { 
     374                [self _removeJoinedRoom:room]; 
     375                [room release]; 
     376                // handle error... 
     377                return; 
     378        } 
     379 
     380        MVXMPPChatUser *user = nil; 
     381        if( [[[room localMemberUser] uniqueIdentifier] isEqual:[presence from]] ) 
     382                user = (MVXMPPChatUser *)[room localMemberUser]; 
     383        else user = (MVXMPPChatUser *)[self chatUserWithUniqueIdentifier:[presence from]]; 
     384 
     385        if ([[presence getAttribute:@"type"] isCaseInsensitiveEqualToString:@"unavailable"]) { 
     386                [room _removeMemberUser:user]; 
     387                [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomUserPartedNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:user, @"user", nil]]; 
     388                return; 
     389        } 
     390 
     391        [room retain]; // retain incase the following release is the last reference 
     392 
     393        if( ! [room isJoined] ) { 
     394                [room _setDateJoined:[NSDate date]]; 
     395                [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomJoinedNotification object:room]; 
     396                [room release]; // balance the alloc or retain in joinChatRoomNamed: 
     397        } 
     398 
     399        if( ! [room hasUser:user] ) { 
     400                [user _setRoomMember:YES]; 
     401                [room _addMemberUser:user]; 
     402                [self _markUserAsOnline:user]; 
     403 
     404                NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:user] forKey:@"added"]; 
     405                [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomMemberUsersSyncedNotification object:room userInfo:userInfo]; 
     406        } 
     407 
     408        [room release]; 
     409} 
    286410@end 
    287  
    288411 
    289412#pragma mark - 
     
    297420        return _localID; 
    298421} 
     422 
     423- (XMLElement *) _capabilitiesElement { 
     424        XMLElement *caps = [[XMLElement allocWithZone:nil] initWithQName:JABBER_CLIENTCAP_QN]; 
     425    [caps putAttribute:@"node" withValue:@"http://colloquy.info/caps"]; 
     426    [caps putAttribute:@"ver" withValue:@"2.1"]; 
     427        return [caps autorelease]; 
     428} 
     429 
     430- (XMLElement *) _multiUserChatExtensionElement { 
     431        XMLQName *xQName = [XMLQName construct:@"x" withURI:@"http://jabber.org/protocol/muc"]; 
     432        return [[[XMLElement allocWithZone:nil] initWithQName:xQName] autorelease]; 
     433} 
    299434@end 
  • trunk/Chat Core/MVXMPPChatUser.h

    r3637 r3638  
    77@interface MVXMPPChatUser : MVChatUser { 
    88@private 
    9         JabberID *_identifier; 
     9        BOOL _roomMember; 
    1010} 
    1111- (id) initLocalUserWithConnection:(MVXMPPChatConnection *) connection; 
    1212- (id) initWithJabberID:(JabberID *) identifier andConnection:(MVXMPPChatConnection *) connection; 
    1313@end 
     14 
     15@interface MVXMPPChatUser (MVXMPPChatUserPrivate) 
     16- (void) _setRoomMember:(BOOL) member; 
     17- (BOOL) _isRoomMember; 
     18@end 
  • trunk/Chat Core/MVXMPPChatUser.m

    r3637 r3638  
    1616                _type = MVChatRemoteUserType; 
    1717                _connection = userConnection; // prevent circular retain 
    18                 MVSafeRetainAssign( &_identifier, identifier ); 
    19                 MVSafeCopyAssign( &_uniqueIdentifier, [identifier completeID] ); 
     18                MVSafeRetainAssign( &_uniqueIdentifier, identifier ); 
    2019        } 
    2120 
     
    3130 
    3231- (NSString *) displayName { 
    33         if( _type == MVChatWildcardUserType ) 
    34                 return [NSString stringWithFormat:@"%@@%@", ( [self username] ? [self username] : @"*" ), ( [self address] ? [self address] : @"*" )]; 
    35         return [self nickname]; 
     32        return [self username]; 
    3633} 
    3734 
    3835- (NSString *) nickname { 
    39         if( _type == MVChatLocalUserType ) 
    40                 return [[self connection] username]; 
    41         return [_identifier username]; 
     36        return [self username]; 
    4237} 
    4338 
     
    4742 
    4843- (NSString *) username { 
     44        if( _roomMember ) 
     45                return [_uniqueIdentifier resource]; 
    4946        if( _type == MVChatLocalUserType ) 
    5047                return [[self connection] username]; 
    51         return [_identifier username]; 
     48        return [_uniqueIdentifier username]; 
    5249} 
    5350 
    5451- (NSString *) address { 
    55         return [_identifier hostname]; 
     52        return [_uniqueIdentifier hostname]; 
    5653} 
    5754 
    5855- (NSString *) serverAddress { 
    59         return [_identifier hostname]; 
     56        return [_uniqueIdentifier hostname]; 
    6057} 
    6158 
     
    7572        NSParameterAssert( message != nil ); 
    7673 
    77         JabberMessage *jabberMsg = [[JabberMessage alloc] initWithRecipient:_identifier andBody:[message string]]; 
     74        JabberMessage *jabberMsg = [[JabberMessage alloc] initWithRecipient:_uniqueIdentifier andBody:[message string]]; 
    7875        [jabberMsg setType:@"chat"]; 
    7976        [jabberMsg addComposingRequest]; 
     
    8279} 
    8380@end 
     81 
     82#pragma mark - 
     83 
     84@implementation MVXMPPChatUser (MVXMPPChatUserPrivate) 
     85- (void) _setRoomMember:(BOOL) member { 
     86        _roomMember = member; 
     87} 
     88 
     89- (BOOL) _isRoomMember { 
     90        return _roomMember; 
     91} 
     92@end 
  • trunk/Models/JVSQLChatTranscript.m

    r3616 r3638  
    656656                senderNickname = [member nickname]; 
    657657                senderIdentifier = [[member user] uniqueIdentifier]; 
    658                 if( [senderIdentifier isKindOfClass:[NSData class]] ) 
    659                         senderIdentifier = [senderIdentifier base64Encoding]; 
    660658                senderHostmask = [member hostmask]; 
    661659                if( [member serverOperator] ) senderClass = @"server operator"; 
     
    673671                senderNickname = [chatUser nickname]; 
    674672                senderIdentifier = [chatUser uniqueIdentifier]; 
    675                 if( [senderIdentifier isKindOfClass:[NSData class]] ) 
    676                         senderIdentifier = [senderIdentifier base64Encoding]; 
    677673                if( [[chatUser username] length] && [[chatUser address] length] ) 
    678674                        senderHostmask = [NSString stringWithFormat:@"%@@%@", [chatUser username], [chatUser address]]; 
    679675                senderLocalUser = [chatUser isLocalUser]; 
    680676        } 
     677 
     678        if( [senderIdentifier isKindOfClass:[NSData class]] ) 
     679                senderIdentifier = [senderIdentifier base64Encoding]; 
     680        else if( ! [senderIdentifier isKindOfClass:[NSString class]] ) 
     681                senderIdentifier = [senderIdentifier description]; 
    681682 
    682683        char userQuery[512] = "";