Changeset 3084
- Timestamp:
- 12/26/05 19:29:26 (3 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cocoa-networking/Chat Core/MVIRCChatConnection.h
r3081 r3084 29 29 - (void) _readNextMessageFromServer; 30 30 31 - (void) _handleCTCP:(NSMutableData *) data asRequest:(BOOL) request fromSender:(MVChatUser *) sender forRoom:(MVChatRoom *) room; 32 31 33 + (NSData *) _flattenedIRCDataForMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) enc andChatFormat:(MVChatMessageFormat) format; 32 34 - (void) _sendMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) encoding toTarget:(NSString *) target asAction:(BOOL) action; branches/cocoa-networking/Chat Core/MVIRCChatConnection.m
r3082 r3084 979 979 } 980 980 981 // IRC messages are always lines of characters terminated with a CR-LF 982 // (Carriage Return - Line Feed) pair, and these messages SHALL NOT 983 // exceed 512 characters in length, counting all characters including 984 // the trailing CR-LF. Thus, there are 510 characters maximum allowed 985 // for the command and its parameters. 986 987 if( [data length] > 510 ) [data setLength:510]; 981 988 [data appendBytes:"\x0D\x0A" length:2]; 982 989 … … 1150 1157 - (void) socket:(AsyncSocket *) sock didReadData:(NSData *) data withTag:(long) tag { 1151 1158 NSString *rawString = [[NSString allocWithZone:nil] initWithData:data encoding:[self encoding]]; 1152 c har *line = (char *)[(NSMutableData *)data mutableBytes];1159 const char *line = (const char *)[data bytes]; 1153 1160 unsigned int len = [data length]; 1154 1155 char *sender = NULL; 1156 char *user = NULL; 1157 char *host = NULL; 1158 char *command = NULL; 1159 char *currentParameter = NULL; 1161 const char *end = line + len - 2; // minus the line endings 1162 1163 const char *sender = NULL; 1164 unsigned senderLength = 0; 1165 const char *user = NULL; 1166 unsigned userLength = 0; 1167 const char *host = NULL; 1168 unsigned hostLength = 0; 1169 const char *command = NULL; 1170 unsigned commandLength = 0; 1160 1171 1161 1172 NSMutableArray *parameters = [[NSMutableArray allocWithZone:nil] initWithCapacity:15]; … … 1166 1177 goto end; // bad message 1167 1178 1168 #define checkAndMarkIfDone() if( *line == '\r' || *line == '\f' || *line == '\0') done = YES1169 #define consumeWhitespace() while( *line == ' ' && ! done ) line++1170 #define notEndOfLine() *line != '\r' && *line != '\f' && *line != '\0'&& ! done1179 #define checkAndMarkIfDone() if( line == end ) done = YES 1180 #define consumeWhitespace() while( *line == ' ' && line != end && ! done ) line++ 1181 #define notEndOfLine() line != end && ! done 1171 1182 1172 1183 BOOL done = NO; … … 1176 1187 sender = ++line; 1177 1188 while( notEndOfLine() && *line != ' ' && *line != '!' && *line != '@' ) line++; 1189 senderLength = (line - sender); 1178 1190 checkAndMarkIfDone(); 1179 1191 1180 if( *line == '!' ) { 1181 *line++ = '\0'; 1182 user = line; 1192 if( ! done && *line == '!' ) { 1193 user = ++line; 1183 1194 while( notEndOfLine() && *line != ' ' && *line != '@' ) line++; 1195 userLength = (line - host); 1184 1196 checkAndMarkIfDone(); 1185 if( *line != '@' ) *line = '\0';1186 1197 } 1187 1198 1188 if( *line == '@' ) { 1189 *line++ = '\0'; 1190 host = line; 1199 if( ! done && *line == '@' ) { 1200 host = ++line; 1191 1201 while( notEndOfLine() && *line != ' ' ) line++; 1202 hostLength = (line - host); 1192 1203 checkAndMarkIfDone(); 1193 *line = '\0';1194 1204 } 1195 1205 1196 *line++ = '\0';1206 if( ! done ) line++; 1197 1207 consumeWhitespace(); 1198 1208 } … … 1204 1214 command = line; 1205 1215 while( notEndOfLine() && *line != ' ' ) line++; 1206 *line++ = '\0'; 1216 commandLength = (line - command); 1217 checkAndMarkIfDone(); 1218 1219 if( ! done ) line++; 1207 1220 consumeWhitespace(); 1208 1221 } 1209 1222 1210 id param = nil;1211 1223 while( notEndOfLine() ) { 1212 1224 // params: [ ':' <trailing data> | <letter> { <letter> } ] [ ' ' { ' ' } ] [ <params> ] 1213 c urrentParameter = NULL;1214 param = nil;1225 const char *currentParameter = NULL; 1226 id param = nil; 1215 1227 if( *line == ':' ) { 1216 1228 currentParameter = ++line; 1217 while( notEndOfLine() ) line++; 1218 *line = '\0'; 1229 param = [[NSMutableData allocWithZone:nil] initWithBytes:currentParameter length:(end - currentParameter)]; 1219 1230 done = YES; 1220 param = [[NSData allocWithZone:nil] initWithBytes:currentParameter length:(line - currentParameter)];1221 1231 } else { 1222 1232 currentParameter = line; 1223 1233 while( notEndOfLine() && *line != ' ' ) line++; 1234 param = [[NSString allocWithZone:nil] initWithBytes:currentParameter length:(line - currentParameter) encoding:[self encoding]]; 1224 1235 checkAndMarkIfDone(); 1225 *line++ = '\0'; 1226 param = [[NSString allocWithZone:nil] initWithBytes:currentParameter encoding:[self encoding]]; 1236 if( ! done ) line++; 1227 1237 } 1228 1238 … … 1239 1249 1240 1250 end: 1241 if( command ) {1242 NSString *commandString = [[NSString allocWithZone:nil] initWithBytes:command encoding:[self encoding]];1251 if( command && commandLength ) { 1252 NSString *commandString = [[NSString allocWithZone:nil] initWithBytes:command length:commandLength encoding:[self encoding]]; 1243 1253 NSString *selectorString = [[NSString allocWithZone:nil] initWithFormat:@"_handle%@WithParameters:fromSender:", [commandString capitalizedString]]; 1244 1254 SEL selector = NSSelectorFromString( selectorString ); … … 1248 1258 if( [self respondsToSelector:selector] ) { 1249 1259 NSString *senderString = nil; 1250 if( sender ) senderString = [[NSString allocWithZone:nil] initWithBytes:sender encoding:[self encoding]];1260 if( sender ) senderString = [[NSString allocWithZone:nil] initWithBytes:sender length:senderLength encoding:[self encoding]]; 1251 1261 1252 1262 MVChatUser *chatUser = nil; 1253 if( user ) {1263 if( user && userLength ) { 1254 1264 chatUser = [self chatUserWithUniqueIdentifier:senderString]; 1255 if( ! [chatUser address] && host ) [chatUser _setAddress:[self stringWithEncodedBytes:host]]; 1256 if( ! [chatUser username] ) [chatUser _setUsername:[self stringWithEncodedBytes:user]]; 1265 if( ! [chatUser address] && host && hostLength ) { 1266 NSString *hostString = [[NSString allocWithZone:nil] initWithBytes:host length:hostLength encoding:[self encoding]]; 1267 [chatUser _setAddress:hostString]; 1268 [hostString release]; 1269 } 1270 1271 if( ! [chatUser username] ) { 1272 NSString *userString = [[NSString allocWithZone:nil] initWithBytes:user length:userLength encoding:[self encoding]]; 1273 [chatUser _setUsername:userString]; 1274 [userString release]; 1275 } 1257 1276 } 1258 1277 … … 1442 1461 } 1443 1462 1444 NSData *msgData = [parameters objectAtIndex:1]; 1463 NSMutableData *msgData = [parameters objectAtIndex:1]; 1464 const char *bytes = (const char *)[msgData bytes]; 1465 BOOL ctcp = ( *bytes == '\001' && [msgData length] > 2 ); 1466 1467 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus]; 1468 [sender _setIdleTime:0.]; 1469 1445 1470 if( [[self chatRoomNamePrefixes] characterIsMember:[targetName characterAtIndex:0]] ) { 1446 1471 MVChatRoom *room = [self joinedChatRoomWithName:targetName]; 1447 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus]; 1448 [sender _setIdleTime:0.]; 1449 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", msgData, @"message", [NSString locallyUniqueString], @"identifier", nil]]; 1472 if( ctcp ) [self _handleCTCP:msgData asRequest:YES fromSender:sender forRoom:room]; 1473 else [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", msgData, @"message", [NSString locallyUniqueString], @"identifier", nil]]; 1450 1474 } else { 1451 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus]; 1452 [sender _setIdleTime:0.]; 1453 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:msgData, @"message", [NSString locallyUniqueString], @"identifier", nil]]; 1475 if( ctcp ) [self _handleCTCP:msgData asRequest:YES fromSender:sender forRoom:nil]; 1476 else [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:msgData, @"message", [NSString locallyUniqueString], @"identifier", nil]]; 1454 1477 } 1455 1478 } … … 1466 1489 } 1467 1490 1468 NSData *msgData = [parameters objectAtIndex:1]; 1491 NSMutableData *msgData = [parameters objectAtIndex:1]; 1492 const char *bytes = (const char *)[msgData bytes]; 1493 BOOL ctcp = ( *bytes == '\001' && [msgData length] > 2 ); 1494 1469 1495 if( [[self chatRoomNamePrefixes] characterIsMember:[targetName characterAtIndex:0]] ) { 1470 1496 MVChatRoom *room = [self joinedChatRoomWithName:targetName]; 1471 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus];1472 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", msgData, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"notice", nil]];1497 if( ctcp ) [self _handleCTCP:msgData asRequest:NO fromSender:sender forRoom:room]; 1498 else [[NSNotificationCenter defaultCenter] postNotificationName:MVChatRoomGotMessageNotification object:room userInfo:[NSDictionary dictionaryWithObjectsAndKeys:sender, @"user", msgData, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"notice", nil]]; 1473 1499 } else { 1474 if( [sender status] != MVChatUserAwayStatus ) [sender _setStatus:MVChatUserAvailableStatus]; 1475 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:msgData, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"notice", nil]]; 1476 if( [[sender nickname] isEqualToString:@"NickServ"] ) { 1477 NSString *msg = [[NSString allocWithZone:nil] initWithData:msgData encoding:[self encoding]]; 1478 if( [msg rangeOfString:@"NickServ"].location != NSNotFound && [msg rangeOfString:@"IDENTIFY"].location != NSNotFound ) { 1479 if( ! [self nicknamePassword] ) { 1480 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionNeedNicknamePasswordNotification object:self userInfo:nil]; 1481 } else [self sendRawMessageWithFormat:@"PRIVMSG %@ :IDENTIFY %@", [self nickname], [self nicknamePassword]]; 1482 } else if( [msg rangeOfString:@"Password accepted"].location != NSNotFound ) { 1483 [[self localUser] _setIdentified:YES]; 1484 } else if( [msg rangeOfString:@"authentication required"].location != NSNotFound ) { 1485 [[self localUser] _setIdentified:NO]; 1500 if( ctcp ) [self _handleCTCP:msgData asRequest:NO fromSender:sender forRoom:nil]; 1501 else { 1502 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionGotPrivateMessageNotification object:sender userInfo:[NSDictionary dictionaryWithObjectsAndKeys:msgData, @"message", [NSString locallyUniqueString], @"identifier", [NSNumber numberWithBool:YES], @"notice", nil]]; 1503 if( [[sender nickname] isEqualToString:@"NickServ"] ) { 1504 NSString *msg = [[NSString allocWithZone:nil] initWithData:msgData encoding:[self encoding]]; 1505 if( [msg rangeOfString:@"NickServ"].location != NSNotFound && [msg rangeOfString:@"IDENTIFY"].location != NSNotFound ) { 1506 if( ! [self nicknamePassword] ) { 1507 [[NSNotificationCenter defaultCenter] postNotificationName:MVChatConnectionNeedNicknamePasswordNotification object:self userInfo:nil]; 1508 } else [self sendRawMessageWithFormat:@"PRIVMSG %@ :IDENTIFY %@", [self nickname], [self nicknamePassword]]; 1509 } else if( [msg rangeOfString:@"Password accepted"].location != NSNotFound ) { 1510 [[self localUser] _setIdentified:YES]; 1511 } else if( [msg rangeOfString:@"authentication required"].location != NSNotFound ) { 1512 [[self localUser] _setIdentified:NO]; 1513 } 1514 [msg release]; 1486 1515 } 1487 [msg release];1488 1516 } 1489 1517 } 1490 1518 } 1519 } 1520 1521 - (void) _handleCTCP:(NSMutableData *) data asRequest:(BOOL) request fromSender:(MVChatUser *) sender forRoom:(MVChatRoom *) room { 1522 NSMutableArray *parameters = [[NSMutableArray allocWithZone:nil] initWithCapacity:15]; 1523 const char *line = (const char *)[data bytes] + 1; // skip the \001 char 1524 const char *end = line + [data length] - 2; // minus the first and last \001 char 1525 BOOL done = NO; 1526 1527 while( line != end && ! done ) { 1528 // params: [ ':' <trailing data> | <letter> { <letter> } ] [ ' ' { ' ' } ] [ <params> ] 1529 const char *currentParameter = NULL; 1530 id param = nil; 1531 if( *line == ':' ) { 1532 currentParameter = ++line; 1533 param = [[NSMutableData allocWithZone:nil] initWithBytes:currentParameter length:(end - currentParameter)]; 1534 done = YES; 1535 } else { 1536 currentParameter = line; 1537 while( line != end && *line != ' ' ) line++; 1538 param = [[NSString allocWithZone:nil] initWithBytes:currentParameter length:(line - currentParameter) encoding:[self encoding]]; 1539 if( line == end ) done = YES; 1540 else line++; 1541 } 1542 1543 if( param ) [parameters addObject:param]; 1544 [param release]; 1545 1546 while( *line == ' ' && line != end && ! done ) line++; 1547 } 1548 1549 NSLog(@"ctcp %@ %d %@", sender, request, [parameters description] ); 1491 1550 } 1492 1551
