Changeset 3086
- Timestamp:
- 12/26/05 22:12:16 (3 years ago)
- Files:
-
- branches/cocoa-networking/Chat Core/MVChatConnection.h (modified) (2 diffs)
- branches/cocoa-networking/Chat Core/MVChatConnection.m (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVChatRoom.h (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVChatRoom.m (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVChatUser.h (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVChatUser.m (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVIRCChatConnection.m (modified) (3 diffs)
- branches/cocoa-networking/Chat Core/MVIRCChatRoom.m (modified) (1 diff)
- branches/cocoa-networking/Chat Core/MVIRCChatUser.m (modified) (2 diffs)
- branches/cocoa-networking/Chat Core/MVSILCChatConnection.m (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cocoa-networking/Chat Core/MVChatConnection.h
r3082 r3086 145 145 - (void) setEncoding:(NSStringEncoding) encoding; 146 146 - (NSStringEncoding) encoding; 147 - (NSString *) stringWithEncodedBytes:(const char *) bytes;148 - (NSString *) stringWithEncodedBytesNoCopy:(char *) bytes freeWhenDone:(BOOL) free;149 - (const char *) encodedBytesWithString:(NSString *) string;150 147 151 148 #pragma mark - … … 279 276 280 277 @interface NSObject (MVChatPluginConnectionSupport) 281 - (BOOL) processSubcodeRequest:(NSString *) command withArguments:(NS String*) arguments fromUser:(MVChatUser *) user;282 - (BOOL) processSubcodeReply:(NSString *) command withArguments:(NS String*) arguments fromUser:(MVChatUser *) user;278 - (BOOL) processSubcodeRequest:(NSString *) command withArguments:(NSData *) arguments fromUser:(MVChatUser *) user; 279 - (BOOL) processSubcodeReply:(NSString *) command withArguments:(NSData *) arguments fromUser:(MVChatUser *) user; 283 280 284 281 - (void) connected:(MVChatConnection *) connection; branches/cocoa-networking/Chat Core/MVChatConnection.m
r3082 r3086 259 259 - (NSStringEncoding) encoding { 260 260 return _encoding; 261 }262 263 - (NSString *) stringWithEncodedBytes:(const char *) bytes {264 return [[[NSString allocWithZone:nil] initWithBytes:bytes encoding:_encoding] autorelease];265 }266 267 - (NSString *) stringWithEncodedBytesNoCopy:(char *) bytes freeWhenDone:(BOOL) free {268 return [[[NSString allocWithZone:nil] initWithBytesNoCopy:bytes encoding:_encoding freeWhenDone:free] autorelease];269 }270 271 - (const char *) encodedBytesWithString:(NSString *) string {272 return [string bytesUsingEncoding:_encoding allowLossyConversion:YES];273 261 } 274 262 branches/cocoa-networking/Chat Core/MVChatRoom.h
r3072 r3086 90 90 - (void) sendMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) encoding asAction:(BOOL) action; 91 91 92 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments;93 - (void) sendSubcodeReply:(NSString *) command withArguments:( NSString *) arguments;92 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments; 93 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments; 94 94 95 95 - (NSData *) topic; branches/cocoa-networking/Chat Core/MVChatRoom.m
r3081 r3086 213 213 #pragma mark - 214 214 215 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments {215 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments { 216 216 // subclass this method, if needed 217 217 } 218 218 219 - (void) sendSubcodeReply:(NSString *) command withArguments:( NSString *) arguments {219 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments { 220 220 // subclass this method, if needed 221 221 } branches/cocoa-networking/Chat Core/MVChatUser.h
r3072 r3086 139 139 - (MVUploadFileTransfer *) sendFile:(NSString *) path passively:(BOOL) passive; 140 140 141 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments;142 - (void) sendSubcodeReply:(NSString *) command withArguments:( NSString *) arguments;141 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments; 142 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments; 143 143 @end 144 144 branches/cocoa-networking/Chat Core/MVChatUser.m
r3072 r3086 444 444 #pragma mark - 445 445 446 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments {446 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments { 447 447 // subclass this method, if needed 448 448 } 449 449 450 - (void) sendSubcodeReply:(NSString *) command withArguments:( NSString *) arguments {450 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments { 451 451 // subclass this method, if needed 452 452 } branches/cocoa-networking/Chat Core/MVIRCChatConnection.m
r3085 r3086 1249 1249 1250 1250 end: 1251 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:rawString, @"message", [NSNumber numberWithBool:NO], @"outbound", nil]]; 1252 1251 1253 if( command && commandLength ) { 1252 1254 NSString *commandString = [[NSString allocWithZone:nil] initWithBytes:command length:commandLength encoding:[self encoding]]; … … 1280 1282 } 1281 1283 } 1282 1283 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:rawString, @"message", [NSNumber numberWithBool:NO], @"outbound", nil]];1284 1284 1285 1285 [rawString release]; … … 1520 1520 1521 1521 - (void) _handleCTCP:(NSMutableData *) data asRequest:(BOOL) request fromSender:(MVChatUser *) sender forRoom:(MVChatRoom *) room { 1522 NSMutableArray *parameters = [[NSMutableArray allocWithZone:nil] initWithCapacity:15];1523 1522 const char *line = (const char *)[data bytes] + 1; // skip the \001 char 1524 1523 const char *end = line + [data length] - 2; // minus the first and last \001 char 1525 BOOL done = NO; 1526 BOOL restAsData = NO; 1527 1528 while( line != end && ! done ) { 1529 // params: [ ':' <trailing data> | <letter> { <letter> } ] [ ' ' { ' ' } ] [ <params> ] 1530 const char *currentParameter = NULL; 1531 id param = nil; 1532 if( *line == ':' || restAsData ) { 1533 currentParameter = ( ! restAsData ? ++line : line ); 1534 param = [[NSMutableData allocWithZone:nil] initWithBytes:currentParameter length:(end - currentParameter)]; 1535 done = YES; 1536 } else { 1537 currentParameter = line; 1538 while( line != end && *line != ' ' ) line++; 1539 param = [[NSString allocWithZone:nil] initWithBytes:currentParameter length:(line - currentParameter) encoding:[self encoding]]; 1540 if( line == end ) done = YES; 1541 else line++; 1524 const char *current = line; 1525 1526 while( line != end && *line != ' ' ) line++; 1527 NSString *command = [[NSString allocWithZone:nil] initWithBytes:current length:(line - current) encoding:[self encoding]]; 1528 NSMutableData *arguments = nil; 1529 if( line != end ) arguments = [[NSMutableData allocWithZone:nil] initWithBytes:++line length:(end - line)]; 1530 1531 if( [command caseInsensitiveCompare:@"ACTION"] == NSOrderedSame && arguments ) { 1532 // special case ACTION and send it out like a message with the action flag 1533 if( room ) [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", arguments, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"action", nil]]; 1534 else [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:arguments, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"action", nil]]; 1535 [command release]; 1536 [arguments release]; 1537 return; 1538 } 1539 1540 [[NSNotificationCenter defaultCenter] postNotificationName:( request ? MVChatConnectionSubcodeRequestNotification : MVChatConnectionSubcodeReplyNotification ) object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:command, @"command", arguments, @"arguments", nil]]; 1541 1542 NSMethodSignature *signature = [NSMethodSignature methodSignatureWithReturnAndArgumentTypes:@encode( BOOL ), @encode( NSString * ), @encode( NSString * ), @encode( MVChatUser * ), nil]; 1543 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 1544 if( request ) [invocation setSelector:@selector( processSubcodeRequest:withArguments:fromUser: )]; 1545 else [invocation setSelector:@selector( processSubcodeReply:withArguments:fromUser: )]; 1546 [invocation setArgument:&command atIndex:2]; 1547 [invocation setArgument:&arguments atIndex:3]; 1548 [invocation setArgument:&sender atIndex:4]; 1549 1550 NSArray *results = [[MVChatPluginManager defaultManager] makePluginsPerformInvocation:invocation stoppingOnFirstSuccessfulReturn:YES]; 1551 if( [[results lastObject] boolValue] ) { 1552 [command release]; 1553 [arguments release]; 1554 return; 1555 } 1556 1557 if( request ) { 1558 if( [command caseInsensitiveCompare:@"VERSION"] == NSOrderedSame ) { 1559 NSDictionary *systemVersion = [[NSDictionary allocWithZone:nil] initWithContentsOfFile:@"/System/Library/CoreServices/ServerVersion.plist"]; 1560 if( ! [systemVersion count] ) systemVersion = [[NSDictionary allocWithZone:nil] initWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; 1561 NSDictionary *clientVersion = [[NSBundle mainBundle] infoDictionary]; 1562 1563 #if __ppc__ 1564 NSString *processor = @"PowerPC"; 1565 #elif __i386__ 1566 NSString *processor = @"Intel"; 1567 #else 1568 NSString *processor = @"Unknown Architecture"; 1569 #endif 1570 1571 NSString *reply = [[NSString allocWithZone:nil] initWithFormat:@"%@ %@ (%@) - %@ %@ (%@) - %@", [clientVersion objectForKey:@"CFBundleName"], [clientVersion objectForKey:@"CFBundleShortVersionString"], [clientVersion objectForKey:@"CFBundleVersion"], [systemVersion objectForKey:@"ProductName"], [systemVersion objectForKey:@"ProductUserVisibleVersion"], processor, [clientVersion objectForKey:@"MVChatCoreCTCPVersionReplyInfo"]]; 1572 [sender sendSubcodeReply:command withArguments:reply]; 1573 1574 [reply release]; 1575 [systemVersion release]; 1576 } else if( [command caseInsensitiveCompare:@"TIME"] == NSOrderedSame ) { 1577 [sender sendSubcodeReply:command withArguments:[[NSDate date] description]]; 1578 } else if( [command caseInsensitiveCompare:@"PING"] == NSOrderedSame ) { 1579 // only reply with packets less than 100 bytes, anything over that is bad karma 1580 if( [arguments length] < 100 ) [sender sendSubcodeReply:command withArguments:arguments]; 1581 } else if( [command caseInsensitiveCompare:@"CLIENTINFO"] == NSOrderedSame ) { 1582 // make this extnesible later with a plugin registration method 1583 [sender sendSubcodeReply:command withArguments:@"VERSION TIME PING DCC CLIENTINFO"]; 1542 1584 } 1543 1544 if( param ) { 1545 [parameters addObject:param]; 1546 if( [parameters count] == 1 && [param isKindOfClass:[NSString class]] ) 1547 restAsData = ( [param caseInsensitiveCompare:@"ACTION"] == NSOrderedSame ); 1548 [param release]; 1549 } 1550 1551 while( *line == ' ' && line != end && ! done ) line++; 1552 } 1553 1554 if( [parameters count] == 2 && [[parameters objectAtIndex:0] caseInsensitiveCompare:@"ACTION"] == NSOrderedSame ) { 1555 // special case ACTION and send it out like a message with the action flag 1556 if( room ) [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", [parameters objectAtIndex:1], @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"action", nil]]; 1557 else [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[parameters objectAtIndex:1], @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"action", nil]]; 1558 [parameters release]; 1559 return; 1560 } 1561 1562 NSLog(@"ctcp %@ %d %@", sender, request, [parameters description] ); 1563 [parameters release]; 1585 } 1586 1587 [command release]; 1588 [arguments release]; 1564 1589 } 1565 1590 branches/cocoa-networking/Chat Core/MVIRCChatRoom.m
r3081 r3086 59 59 #pragma mark - 60 60 61 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments {61 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments { 62 62 NSParameterAssert( command != nil ); 63 NSString *request = ( [arguments length] ? [NSString stringWithFormat:@"%@ %@", command, arguments] : command ); 64 [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@\001", [self name], request]; 65 } 66 67 - (void) sendSubcodeReply:(NSString *) command withArguments:(NSString *) arguments { 63 if( arguments && [arguments isKindOfClass:[NSData class]] && [arguments length] ) { 64 NSString *prefix = [[NSString allocWithZone:nil] initWithFormat:@"PRIVMSG %@ :\001%@ ", [self name], command]; 65 [[self connection] sendRawMessageWithComponents:prefix, arguments, @"\001", nil]; 66 [prefix release]; 67 } else if( arguments && [arguments isKindOfClass:[NSString class]] && [arguments length] ) { 68 [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@ %@\001", [self name], command, arguments]; 69 } else [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@\001", [self name], command]; 70 } 71 72 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments { 68 73 NSParameterAssert( command != nil ); 69 NSString *request = ( [arguments length] ? [NSString stringWithFormat:@"%@ %@", command, arguments] : command ); 70 [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@\001", [self name], request]; 74 if( arguments && [arguments isKindOfClass:[NSData class]] && [arguments length] ) { 75 NSString *prefix = [[NSString allocWithZone:nil] initWithFormat:@"NOTICE %@ :\001%@ ", [self name], command]; 76 [[self connection] sendRawMessageWithComponents:prefix, arguments, @"\001", nil]; 77 [prefix release]; 78 } else if( arguments && [arguments isKindOfClass:[NSString class]] && [arguments length] ) { 79 [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@ %@\001", [self name], command, arguments]; 80 } else [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@\001", [self name], command]; 71 81 } 72 82 branches/cocoa-networking/Chat Core/MVIRCChatUser.m
r3080 r3086 47 47 } 48 48 49 - (void) sendSubcodeRequest:(NSString *) command withArguments:( NSString *) arguments {49 - (void) sendSubcodeRequest:(NSString *) command withArguments:(id) arguments { 50 50 NSParameterAssert( command != nil ); 51 NSString *request = ( [arguments length] ? [NSString stringWithFormat:@"%@ %@", command, arguments] : command ); 52 [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@\001", [self nickname], request]; 51 if( arguments && [arguments isKindOfClass:[NSData class]] && [arguments length] ) { 52 NSString *prefix = [[NSString allocWithZone:nil] initWithFormat:@"PRIVMSG %@ :\001%@ ", [self nickname], command]; 53 [[self connection] sendRawMessageWithComponents:prefix, arguments, @"\001", nil]; 54 [prefix release]; 55 } else if( arguments && [arguments isKindOfClass:[NSString class]] && [arguments length] ) { 56 [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@ %@\001", [self nickname], command, arguments]; 57 } else [[self connection] sendRawMessageWithFormat:@"PRIVMSG %@ :\001%@\001", [self nickname], command]; 53 58 } 54 59 55 - (void) sendSubcodeReply:(NSString *) command withArguments:( NSString *) arguments {60 - (void) sendSubcodeReply:(NSString *) command withArguments:(id) arguments { 56 61 NSParameterAssert( command != nil ); 57 NSString *request = ( [arguments length] ? [NSString stringWithFormat:@"%@ %@", command, arguments] : command ); 58 [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@\001", [self nickname], request]; 62 if( arguments && [arguments isKindOfClass:[NSData class]] && [arguments length] ) { 63 NSString *prefix = [[NSString allocWithZone:nil] initWithFormat:@"NOTICE %@ :\001%@ ", [self nickname], command]; 64 [[self connection] sendRawMessageWithComponents:prefix, arguments, @"\001", nil]; 65 [prefix release]; 66 } else if( arguments && [arguments isKindOfClass:[NSString class]] && [arguments length] ) { 67 [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@ %@\001", [self nickname], command, arguments]; 68 } else [[self connection] sendRawMessageWithFormat:@"NOTICE %@ :\001%@\001", [self nickname], command]; 59 69 } 60 70 … … 80 90 - (void) ctcpReplyNotification:(NSNotification *) notification { 81 91 NSString *command = [[notification userInfo] objectForKey:@"command"]; 82 NS String*arguments = [[notification userInfo] objectForKey:@"arguments"];83 if( ! [command caseInsensitiveCompare:@"version"]) {92 NSData *arguments = [[notification userInfo] objectForKey:@"arguments"]; 93 if( [command caseInsensitiveCompare:@"VERSION"] == NSOrderedSame ) { 84 94 [self setAttribute:arguments forKey:MVChatUserClientInfoAttribute]; 85 } else if( ! [command caseInsensitiveCompare:@"time"] ) { 86 NSDate *localThere = [NSDate dateWithNaturalLanguageString:arguments]; 95 } else if( [command caseInsensitiveCompare:@"TIME"] == NSOrderedSame ) { 96 NSString *date = [[NSString allocWithZone:nil] initWithData:arguments encoding:[[self connection] encoding]]; 97 NSDate *localThere = [NSDate dateWithNaturalLanguageString:date]; 87 98 if( localThere ) { 88 99 NSTimeInterval diff = [localThere timeIntervalSinceDate:[NSDate date]]; 89 100 [self setAttribute:[NSNumber numberWithDouble:diff] forKey:MVChatUserLocalTimeDifferenceAttribute]; 90 101 } else [self setAttribute:nil forKey:MVChatUserLocalTimeDifferenceAttribute]; 102 [date release]; 91 103 } 92 104 } branches/cocoa-networking/Chat Core/MVSILCChatConnection.m
r3072 r3086 78 78 if( flags & SILC_MESSAGE_FLAG_ACTION ) action = YES; 79 79 80 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];80 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 81 81 MVChatUser *user = [self _chatUserWithClientEntry:sender]; 82 82 NSString *mimeType = @"text/plain"; … … 252 252 if( joining_client == conn -> local_entry ) break; 253 253 254 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];254 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 255 255 MVChatUser *member = [self _chatUserWithClientEntry:joining_client]; 256 256 … … 280 280 if( ! leaving_client || ! channel ) break; 281 281 282 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];282 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 283 283 MVChatUser *member = [self _chatUserWithClientEntry:leaving_client]; 284 284 … … 300 300 authorUser = [self _chatUserWithClientEntry:(SilcClientEntry)setter_entry]; 301 301 302 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];302 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 303 303 NSData *msgData = ( topic ? [[NSData allocWithZone:nil] initWithBytes:topic length:strlen( topic )] : nil ); 304 304 [room _setTopic:msgData byAuthor:authorUser withDate:[NSDate date]]; … … 320 320 changerUser = [self _chatUserWithClientEntry:(SilcClientEntry)changer_entry]; 321 321 322 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];322 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 323 323 MVChatUser *member = [self _chatUserWithClientEntry:target_client]; 324 324 … … 394 394 NSNotification *note = nil; 395 395 396 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];396 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 397 397 MVChatUser *member = [self _chatUserWithClientEntry:kicked]; 398 398 MVChatUser *byMember = [self _chatUserWithClientEntry:kicker]; … … 632 632 /* SilcUInt32 user_limit = */ va_arg( list, SilcUInt32 ); 633 633 634 MVSILCChatRoom *room = (MVSILCChatRoom *)[self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];634 MVSILCChatRoom *room = (MVSILCChatRoom *)[self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 635 635 if( ! room ) { 636 636 room = [[[MVSILCChatRoom allocWithZone:nil] initWithChannelEntry:channel andConnection:self] autorelease]; … … 673 673 case SILC_COMMAND_LEAVE: { 674 674 SilcChannelEntry channel = va_arg( list, SilcChannelEntry ); 675 MVChatRoom *room = [self joinedChatRoomWithName:[ self stringWithEncodedBytes:channel -> channel_name]];675 MVChatRoom *room = [self joinedChatRoomWithName:[NSString stringWithUTF8String:channel -> channel_name]]; 676 676 [room _setDateParted:[NSDate date]]; 677 677 NSNotification *note = [NSNotification notificationWithName:MVChatRoomPartedNotification object:room userInfo:nil];
