Index: src/IRCConnection.h ================================================================== --- src/IRCConnection.h +++ src/IRCConnection.h @@ -105,7 +105,8 @@ toChannel: (IRCChannel*)channel; - (void)kickUser: (IRCUser*)user fromChannel: (IRCChannel*)channel withReason: (OFString*)reason; - (void)changeNicknameTo: (OFString*)nickname; +- (void)process; - (void)handleConnection; @end Index: src/IRCConnection.m ================================================================== --- src/IRCConnection.m +++ src/IRCConnection.m @@ -161,292 +161,291 @@ - (void)changeNicknameTo: (OFString*)nickname_ { [self sendLineWithFormat: @"NICK %@", nickname_]; } -- (void)handleConnection +- (void)process { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *line; OFArray *split; - - for (;;) { - OFString *action = nil; - - @try { - line = [sock readLine]; - } @catch (OFInvalidEncodingException *e) { - [e dealloc]; - line = [sock readLineWithEncoding: - OF_STRING_ENCODING_WINDOWS_1252]; - } - - if (line == nil) - break; - - if ([delegate respondsToSelector: - @selector(connection:didReceiveLine:)]) - [delegate connection: self - didReceiveLine: line]; - - split = [line componentsSeparatedByString: @" "]; - - /* PING */ - if (split.count == 2 && [split.firstObject isEqual: @"PING"]) { - OFMutableString *s = [[line mutableCopy] autorelease]; - [s replaceOccurrencesOfString: @"PING" - withString: @"PONG"]; - [self sendLine: s]; - - continue; - } - - action = [[split objectAtIndex: 1] uppercaseString]; - - /* Connected */ - if ([action isEqual: @"001"] && split.count >= 4) { - if ([delegate respondsToSelector: - @selector(connectionWasEstablished:)]) - [delegate connectionWasEstablished: self]; - - continue; - } - - /* JOIN */ - if ([action isEqual: @"JOIN"] && split.count == 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; - IRCUser *user; - IRCChannel *channel; - - who = [who substringWithRange: - of_range(1, who.length - 1)]; - where = [where substringWithRange: - of_range(1, where.length - 1)]; - user = [IRCUser IRCUserWithString: who]; - - if ([who hasPrefix: - [nickname stringByAppendingString: @"!"]]) { - channel = [IRCChannel channelWithName: where]; - [channels setObject: channel - forKey: where]; - } else - channel = [channels objectForKey: where]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:joinChannel:)]) - [delegate connection: self - didSeeUser: user - joinChannel: channel]; - - continue; - } - - /* PART */ - if ([action isEqual: @"PART"] && split.count >= 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; - IRCUser *user; - IRCChannel *channel; - OFString *reason = nil; - size_t pos = who.length + 1 + - [[split objectAtIndex: 1] length] + 1 + - where.length; - - who = [who substringWithRange: - of_range(1, who.length - 1)]; - user = [IRCUser IRCUserWithString: who]; - channel = [channels objectForKey: where]; - - if (split.count > 3) - reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:leaveChannel: - withReason:)]) - [delegate connection: self - didSeeUser: user - leaveChannel: channel - withReason: reason]; - - continue; - } - - /* KICK */ - if ([action isEqual: @"KICK"] && split.count >= 4) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; - OFString *whom = [split objectAtIndex: 3]; - IRCUser *user; - IRCChannel *channel; - OFString *reason = nil; - size_t pos = who.length + 1 + - [[split objectAtIndex: 1] length] + 1 + - where.length + 1 + whom.length; - - who = [who substringWithRange: - of_range(1, who.length - 1)]; - user = [IRCUser IRCUserWithString: who]; - channel = [channels objectForKey: where]; - - if (split.count > 4) - reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:kickUser: - fromChannel:withReason:)]) - [delegate connection: self - didSeeUser: user - kickUser: whom - fromChannel: channel - withReason: reason]; - - continue; - } - - /* QUIT */ - if ([action isEqual: @"QUIT"] && split.count >= 2) { - OFString *who = [split objectAtIndex: 0]; - IRCUser *user; - OFString *reason = nil; - size_t pos = who.length + 1 + - [[split objectAtIndex: 1] length]; - - who = [who substringWithRange: - of_range(1, who.length - 1)]; - user = [IRCUser IRCUserWithString: who]; - - if (split.count > 2) - reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUserQuit:withReason:)]) - [delegate connection: self - didSeeUserQuit: user - withReason: reason]; - - continue; - } - - /* NICK */ - if ([action isEqual: @"NICK"] && split.count == 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *newNickname = [split objectAtIndex: 2]; - IRCUser *user; - - who = [who substringWithRange: - of_range(1, who.length - 1)]; - newNickname = [newNickname substringWithRange: - of_range(1, newNickname.length - 1)]; - - user = [IRCUser IRCUserWithString: who]; - - if ([user.nickname isEqual: nickname]) { - [nickname release]; - nickname = [user.nickname copy]; - } - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:changeNicknameTo:)]) - [delegate connection: self - didSeeUser: user - changeNicknameTo: newNickname]; - } - - /* PRIVMSG */ - if ([action isEqual: @"PRIVMSG"] && split.count >= 4) { - OFString *from = [split objectAtIndex: 0]; - OFString *to = [split objectAtIndex: 2]; - IRCUser *user; - OFString *msg; - size_t pos = from.length + 1 + - [[split objectAtIndex: 1] length] + 1 + - to.length; - - from = [from substringWithRange: - of_range(1, from.length - 1)]; - msg = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - user = [IRCUser IRCUserWithString: from]; - - if (![to isEqual: nickname]) { - IRCChannel *channel; - - channel = [channels objectForKey: to]; - - if ([delegate respondsToSelector: - @selector(connection:didReceiveMessage: - fromUser:inChannel:)]) - [delegate connection: self - didReceiveMessage: msg - fromUser: user - inChannel: channel]; - } else { - if ([delegate respondsToSelector: - @selector(connection: - didReceivePrivateMessage:fromUser:)]) - [delegate - connection: self - didReceivePrivateMessage: msg - fromUser: user]; - } - - continue; - } - - /* NOTICE */ - if ([action isEqual: @"NOTICE"] && split.count >= 4) { - OFString *from = [split objectAtIndex: 0]; - OFString *to = [split objectAtIndex: 2]; - IRCUser *user = nil; - OFString *notice; - size_t pos = from.length + 1 + - [[split objectAtIndex: 1] length] + 1 + - to.length; - - from = [from substringWithRange: - of_range(1, from.length - 1)]; - notice = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - if (![from containsString: @"!"] || [to isEqual: @"*"]) - /* System message - ignore for now */ - continue; - - user = [IRCUser IRCUserWithString: from]; - - if (![to isEqual: nickname]) { - IRCChannel *channel; - - channel = [channels objectForKey: to]; - - if ([delegate respondsToSelector: - @selector(connection:didReceiveNotice: - fromUser:inChannel:)]) - [delegate connection: self - didReceiveNotice: notice - fromUser: user - inChannel: channel]; - } else { - if ([delegate respondsToSelector: - @selector(connection:didReceiveNotice: - fromUser:)]) - [delegate connection: self - didReceiveNotice: notice - fromUser: user]; - } - - continue; - } - - [pool releaseObjects]; - } - - [pool release]; + OFString *action = nil; + + @try { + line = [sock tryReadLine]; + } @catch (OFInvalidEncodingException *e) { + [e dealloc]; + line = [sock tryReadLineWithEncoding: + OF_STRING_ENCODING_WINDOWS_1252]; + } + + if (line == nil) + return; + + if ([delegate respondsToSelector: + @selector(connection:didReceiveLine:)]) + [delegate connection: self + didReceiveLine: line]; + + split = [line componentsSeparatedByString: @" "]; + + /* PING */ + if (split.count == 2 && [split.firstObject isEqual: @"PING"]) { + OFMutableString *s = [[line mutableCopy] autorelease]; + [s replaceOccurrencesOfString: @"PING" + withString: @"PONG"]; + [self sendLine: s]; + + return; + } + + action = [[split objectAtIndex: 1] uppercaseString]; + + /* Connected */ + if ([action isEqual: @"001"] && split.count >= 4) { + if ([delegate respondsToSelector: + @selector(connectionWasEstablished:)]) + [delegate connectionWasEstablished: self]; + + [pool release]; + return; + } + + /* JOIN */ + if ([action isEqual: @"JOIN"] && split.count == 3) { + OFString *who = [split objectAtIndex: 0]; + OFString *where = [split objectAtIndex: 2]; + IRCUser *user; + IRCChannel *channel; + + who = [who substringWithRange: of_range(1, who.length - 1)]; + where = [where substringWithRange: + of_range(1, where.length - 1)]; + user = [IRCUser IRCUserWithString: who]; + + if ([who hasPrefix: [nickname stringByAppendingString: @"!"]]) { + channel = [IRCChannel channelWithName: where]; + [channels setObject: channel + forKey: where]; + } else + channel = [channels objectForKey: where]; + + if ([delegate respondsToSelector: + @selector(connection:didSeeUser:joinChannel:)]) + [delegate connection: self + didSeeUser: user + joinChannel: channel]; + + [pool release]; + return; + } + + /* PART */ + if ([action isEqual: @"PART"] && split.count >= 3) { + OFString *who = [split objectAtIndex: 0]; + OFString *where = [split objectAtIndex: 2]; + IRCUser *user; + IRCChannel *channel; + OFString *reason = nil; + size_t pos = who.length + 1 + + [[split objectAtIndex: 1] length] + 1 + where.length; + + who = [who substringWithRange: of_range(1, who.length - 1)]; + user = [IRCUser IRCUserWithString: who]; + channel = [channels objectForKey: where]; + + if (split.count > 3) + reason = [line substringWithRange: + of_range(pos + 2, line.length - pos - 2)]; + + if ([delegate respondsToSelector: + @selector(connection:didSeeUser:leaveChannel: + withReason:)]) + [delegate connection: self + didSeeUser: user + leaveChannel: channel + withReason: reason]; + + [pool release]; + return; + } + + /* KICK */ + if ([action isEqual: @"KICK"] && split.count >= 4) { + OFString *who = [split objectAtIndex: 0]; + OFString *where = [split objectAtIndex: 2]; + OFString *whom = [split objectAtIndex: 3]; + IRCUser *user; + IRCChannel *channel; + OFString *reason = nil; + size_t pos = who.length + 1 + + [[split objectAtIndex: 1] length] + 1 + where.length + 1 + + whom.length; + + who = [who substringWithRange: of_range(1, who.length - 1)]; + user = [IRCUser IRCUserWithString: who]; + channel = [channels objectForKey: where]; + + if (split.count > 4) + reason = [line substringWithRange: + of_range(pos + 2, line.length - pos - 2)]; + + if ([delegate respondsToSelector: + @selector(connection:didSeeUser:kickUser: + fromChannel:withReason:)]) + [delegate connection: self + didSeeUser: user + kickUser: whom + fromChannel: channel + withReason: reason]; + + [pool release]; + return; + } + + /* QUIT */ + if ([action isEqual: @"QUIT"] && split.count >= 2) { + OFString *who = [split objectAtIndex: 0]; + IRCUser *user; + OFString *reason = nil; + size_t pos = who.length + 1 + [[split objectAtIndex: 1] length]; + + who = [who substringWithRange: of_range(1, who.length - 1)]; + user = [IRCUser IRCUserWithString: who]; + + if (split.count > 2) + reason = [line substringWithRange: + of_range(pos + 2, line.length - pos - 2)]; + + if ([delegate respondsToSelector: + @selector(connection:didSeeUserQuit:withReason:)]) + [delegate connection: self + didSeeUserQuit: user + withReason: reason]; + + [pool release]; + return; + } + + /* NICK */ + if ([action isEqual: @"NICK"] && split.count == 3) { + OFString *who = [split objectAtIndex: 0]; + OFString *newNickname = [split objectAtIndex: 2]; + IRCUser *user; + + who = [who substringWithRange: of_range(1, who.length - 1)]; + newNickname = [newNickname substringWithRange: + of_range(1, newNickname.length - 1)]; + + user = [IRCUser IRCUserWithString: who]; + + if ([user.nickname isEqual: nickname]) { + [nickname release]; + nickname = [user.nickname copy]; + } + + if ([delegate respondsToSelector: + @selector(connection:didSeeUser:changeNicknameTo:)]) + [delegate connection: self + didSeeUser: user + changeNicknameTo: newNickname]; + + [pool release]; + return; + } + + /* PRIVMSG */ + if ([action isEqual: @"PRIVMSG"] && split.count >= 4) { + OFString *from = [split objectAtIndex: 0]; + OFString *to = [split objectAtIndex: 2]; + IRCUser *user; + OFString *msg; + size_t pos = from.length + 1 + + [[split objectAtIndex: 1] length] + 1 + to.length; + + from = [from substringWithRange: of_range(1, from.length - 1)]; + msg = [line substringWithRange: + of_range(pos + 2, line.length - pos - 2)]; + user = [IRCUser IRCUserWithString: from]; + + if (![to isEqual: nickname]) { + IRCChannel *channel; + + channel = [channels objectForKey: to]; + + if ([delegate respondsToSelector: + @selector(connection:didReceiveMessage: + fromUser:inChannel:)]) + [delegate connection: self + didReceiveMessage: msg + fromUser: user + inChannel: channel]; + } else { + if ([delegate respondsToSelector: + @selector(connection: + didReceivePrivateMessage:fromUser:)]) + [delegate + connection: self + didReceivePrivateMessage: msg + fromUser: user]; + } + + [pool release]; + return; + } + + /* NOTICE */ + if ([action isEqual: @"NOTICE"] && split.count >= 4) { + OFString *from = [split objectAtIndex: 0]; + OFString *to = [split objectAtIndex: 2]; + IRCUser *user = nil; + OFString *notice; + size_t pos = from.length + 1 + + [[split objectAtIndex: 1] length] + 1 + to.length; + + from = [from substringWithRange: of_range(1, from.length - 1)]; + notice = [line substringWithRange: + of_range(pos + 2, line.length - pos - 2)]; + + if (![from containsString: @"!"] || [to isEqual: @"*"]) { + /* System message - ignore for now */ + [pool release]; + return; + } + + user = [IRCUser IRCUserWithString: from]; + + if (![to isEqual: nickname]) { + IRCChannel *channel; + + channel = [channels objectForKey: to]; + + if ([delegate respondsToSelector: + @selector(connection:didReceiveNotice: + fromUser:inChannel:)]) + [delegate connection: self + didReceiveNotice: notice + fromUser: user + inChannel: channel]; + } else { + if ([delegate respondsToSelector: + @selector(connection:didReceiveNotice: + fromUser:)]) + [delegate connection: self + didReceiveNotice: notice + fromUser: user]; + } + + [pool release]; + return; + } +} + +- (void)handleConnection +{ + while (![sock isAtEndOfStream]) + [self process]; } - (void)dealloc { [sock release];