@@ -18,10 +18,12 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#define IRC_CONNECTION_M + #include #import #import #import @@ -35,12 +37,10 @@ #import "IRCConnection.h" #import "IRCUser.h" #import "IRCChannel.h" @implementation IRCConnection -@synthesize server, port, nickname, username, realname, delegate, sock; - - init { self = [super init]; @try { @@ -51,10 +51,75 @@ @throw e; } return self; } + +- (void)setServer: (OFString*)server_ +{ + OF_SETTER(server, server_, YES, YES) +} + +- (OFString*)server +{ + OF_GETTER(server, YES) +} + +- (void)setPort: (uint16_t)port_ +{ + port = port_; +} + +- (uint16_t)port +{ + return port; +} + +- (void)setNickname: (OFString*)nickname_ +{ + OF_SETTER(nickname, nickname_, YES, YES) +} + +- (OFString*)nickname +{ + OF_GETTER(nickname, YES) +} + +- (void)setUsername: (OFString*)username_ +{ + OF_SETTER(username, username_, YES, YES) +} + +- (OFString*)username +{ + OF_GETTER(username, YES) +} + +- (void)setRealname: (OFString*)realname_ +{ + OF_SETTER(realname, realname_, YES, YES) +} + +- (OFString*)realname +{ + OF_GETTER(realname, YES) +} + +- (void)setDelegate: (id )delegate_ +{ + delegate = delegate_; +} + +- (id )delegate +{ + return delegate; +} + +- (OFTCPSocket*)socket +{ + OF_GETTER(sock, YES) +} - (void)connect { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -94,22 +159,22 @@ - (void)leaveChannel: (IRCChannel*)channel withReason: (OFString*)reason { if (reason == nil) - [self sendLineWithFormat: @"PART %@", channel.name]; + [self sendLineWithFormat: @"PART %@", [channel name]]; else - [self sendLineWithFormat: @"PART %@ :%@", channel.name, reason]; + [self sendLineWithFormat: @"PART %@ :%@", + [channel name], reason]; - [channels removeObjectForKey: channel.name]; + [channels removeObjectForKey: [channel name]]; } - (void)sendLine: (OFString*)line { - if ([delegate respondsToSelector: @selector(connection:didSendLine:)]) - [delegate connection: self - didSendLine: line]; + [delegate connection: self + didSendLine: line]; [sock writeLine: line]; } - (void)sendLineWithFormat: (OFConstantString*)format, ... @@ -129,11 +194,11 @@ } - (void)sendMessage: (OFString*)msg toChannel: (IRCChannel*)channel { - [self sendLineWithFormat: @"PRIVMSG %@ :%@", channel.name, msg]; + [self sendLineWithFormat: @"PRIVMSG %@ :%@", [channel name], msg]; } - (void)sendMessage: (OFString*)msg toUser: (OFString*)user { @@ -147,315 +212,291 @@ } - (void)sendNotice: (OFString*)notice toChannel: (IRCChannel*)channel { - [self sendLineWithFormat: @"NOTICE %@ :%@", channel.name, notice]; + [self sendLineWithFormat: @"NOTICE %@ :%@", [channel name], notice]; } - (void)kickUser: (OFString*)user fromChannel: (IRCChannel*)channel withReason: (OFString*)reason { [self sendLineWithFormat: @"KICK %@ %@ :%@", - channel.name, user, reason]; + [channel name], user, reason]; } - (void)changeNicknameTo: (OFString*)nickname_ { [self sendLineWithFormat: @"NICK %@", nickname_]; } -- (void)processLine: (OFString*)line +- (void)IRC_processLine: (OFString*)line { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFArray *split; + OFArray *components; OFString *action = nil; - if ([delegate respondsToSelector: - @selector(connection:didReceiveLine:)]) - [delegate connection: self - didReceiveLine: line]; + [delegate connection: self + didReceiveLine: line]; - split = [line componentsSeparatedByString: @" "]; + components = [line componentsSeparatedByString: @" "]; /* PING */ - if (split.count == 2 && [split.firstObject isEqual: @"PING"]) { + if ([components count] == 2 && + [[components firstObject] isEqual: @"PING"]) { OFMutableString *s = [[line mutableCopy] autorelease]; [s replaceOccurrencesOfString: @"PING" withString: @"PONG"]; [self sendLine: s]; return; } - action = [[split objectAtIndex: 1] uppercaseString]; + action = [[components objectAtIndex: 1] uppercaseString]; /* Connected */ - if ([action isEqual: @"001"] && split.count >= 4) { - if ([delegate respondsToSelector: - @selector(connectionWasEstablished:)]) - [delegate connectionWasEstablished: self]; - - [pool release]; + if ([action isEqual: @"001"] && [components count] >= 4) { + [delegate connectionWasEstablished: self]; return; } /* JOIN */ - if ([action isEqual: @"JOIN"] && split.count == 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; + if ([action isEqual: @"JOIN"] && [components count] == 3) { + OFString *who = [components objectAtIndex: 0]; + OFString *where = [components objectAtIndex: 2]; IRCUser *user; IRCChannel *channel; - who = [who substringWithRange: of_range(1, who.length - 1)]; + who = [who substringWithRange: of_range(1, [who 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]; - [channel IRC_addUser: user.nickname]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:joinChannel:)]) - [delegate connection: self - didSeeUser: user - joinChannel: channel]; - - [pool release]; + [channel IRC_addUser: [user nickname]]; + + [delegate connection: self + didSeeUser: user + joinChannel: channel]; + return; } /* NAMES reply */ - if ([action isEqual: @"353"] && split.count >= 6) { + if ([action isEqual: @"353"] && [components count] >= 6) { IRCChannel *channel; OFArray *users; size_t pos; + OFEnumerator *enumerator; + OFString *user; - channel = [channels objectForKey: [split objectAtIndex: 4]]; + channel = [channels + objectForKey: [components objectAtIndex: 4]]; if (channel == nil) { /* We did not request that */ - [pool release]; return; } - pos = [[split objectAtIndex: 0] length] + - [[split objectAtIndex: 1] length] + - [[split objectAtIndex: 2] length] + - [[split objectAtIndex: 3] length] + - [[split objectAtIndex: 4] length] + 6; + pos = [[components objectAtIndex: 0] length] + + [[components objectAtIndex: 1] length] + + [[components objectAtIndex: 2] length] + + [[components objectAtIndex: 3] length] + + [[components objectAtIndex: 4] length] + 6; users = [[line substringWithRange: - of_range(pos, line.length - pos)] + of_range(pos, [line length] - pos)] componentsSeparatedByString: @" "]; - for (OFString *user in users) { + enumerator = [users objectEnumerator]; + while ((user = [enumerator nextObject]) != nil) { if ([user hasPrefix: @"@"] || [user hasPrefix: @"+"] || [user hasPrefix: @"%"] || [user hasPrefix: @"*"]) user = [user substringWithRange: - of_range(1, user.length - 1)]; + of_range(1, [user length] - 1)]; [channel IRC_addUser: user]; } - if ([delegate respondsToSelector: @selector(connection: - didReceiveNamesForChannel:)]) - [delegate connection: self - didReceiveNamesForChannel: channel]; + [delegate connection: self + didReceiveNamesForChannel: channel]; - [pool release]; return; } /* PART */ - if ([action isEqual: @"PART"] && split.count >= 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; + if ([action isEqual: @"PART"] && [components count] >= 3) { + OFString *who = [components objectAtIndex: 0]; + OFString *where = [components objectAtIndex: 2]; IRCUser *user; IRCChannel *channel; OFString *reason = nil; - size_t pos = who.length + 1 + - [[split objectAtIndex: 1] length] + 1 + where.length; + size_t pos = [who length] + 1 + + [[components objectAtIndex: 1] length] + 1 + [where length]; - who = [who substringWithRange: of_range(1, who.length - 1)]; + who = [who substringWithRange: of_range(1, [who length] - 1)]; user = [IRCUser IRCUserWithString: who]; channel = [channels objectForKey: where]; - if (split.count > 3) + if ([components count] > 3) reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - [channel IRC_removeUser: user.nickname]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:leaveChannel: - withReason:)]) - [delegate connection: self - didSeeUser: user - leaveChannel: channel - withReason: reason]; - - [pool release]; + of_range(pos + 2, [line length] - pos - 2)]; + + [channel IRC_removeUser: [user nickname]]; + + [delegate connection: self + didSeeUser: user + leaveChannel: channel + withReason: reason]; + return; } /* KICK */ - if ([action isEqual: @"KICK"] && split.count >= 4) { - OFString *who = [split objectAtIndex: 0]; - OFString *where = [split objectAtIndex: 2]; - OFString *whom = [split objectAtIndex: 3]; + if ([action isEqual: @"KICK"] && [components count] >= 4) { + OFString *who = [components objectAtIndex: 0]; + OFString *where = [components objectAtIndex: 2]; + OFString *whom = [components 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; + size_t pos = [who length] + 1 + + [[components objectAtIndex: 1] length] + 1 + + [where length] + 1 + [whom length]; - who = [who substringWithRange: of_range(1, who.length - 1)]; + who = [who substringWithRange: of_range(1, [who length] - 1)]; user = [IRCUser IRCUserWithString: who]; channel = [channels objectForKey: where]; - if (split.count > 4) + if ([components count] > 4) reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - [channel IRC_removeUser: user.nickname]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:kickUser: - fromChannel:withReason:)]) - [delegate connection: self - didSeeUser: user - kickUser: whom - fromChannel: channel - withReason: reason]; - - [pool release]; + of_range(pos + 2, [line length] - pos - 2)]; + + [channel IRC_removeUser: [user nickname]]; + + [delegate connection: self + didSeeUser: user + kickUser: whom + fromChannel: channel + withReason: reason]; + return; } /* QUIT */ - if ([action isEqual: @"QUIT"] && split.count >= 2) { - OFString *who = [split objectAtIndex: 0]; + if ([action isEqual: @"QUIT"] && [components count] >= 2) { + OFString *who = [components objectAtIndex: 0]; IRCUser *user; OFString *reason = nil; - size_t pos = who.length + 1 + [[split objectAtIndex: 1] length]; + size_t pos = [who length] + 1 + + [[components objectAtIndex: 1] length]; + OFEnumerator *enumerator; + IRCChannel *channel; - who = [who substringWithRange: of_range(1, who.length - 1)]; + who = [who substringWithRange: of_range(1, [who length] - 1)]; user = [IRCUser IRCUserWithString: who]; - if (split.count > 2) + if ([components count] > 2) reason = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; - - for (IRCChannel *channel in channels) - [channel IRC_removeUser: user.nickname]; - - if ([delegate respondsToSelector: - @selector(connection:didSeeUserQuit:withReason:)]) - [delegate connection: self - didSeeUserQuit: user - withReason: reason]; - - [pool release]; + of_range(pos + 2, [line length] - pos - 2)]; + + enumerator = [channels keyEnumerator]; + while ((channel = [enumerator nextObject]) != nil) + [channel IRC_removeUser: [user nickname]]; + + [delegate connection: self + didSeeUserQuit: user + withReason: reason]; + return; } /* NICK */ - if ([action isEqual: @"NICK"] && split.count == 3) { - OFString *who = [split objectAtIndex: 0]; - OFString *newNickname = [split objectAtIndex: 2]; + if ([action isEqual: @"NICK"] && [components count] == 3) { + OFString *who = [components objectAtIndex: 0]; + OFString *newNickname = [components objectAtIndex: 2]; IRCUser *user; + OFEnumerator *enumerator; + IRCChannel *channel; - who = [who substringWithRange: of_range(1, who.length - 1)]; + who = [who substringWithRange: of_range(1, [who length] - 1)]; newNickname = [newNickname substringWithRange: - of_range(1, newNickname.length - 1)]; + of_range(1, [newNickname length] - 1)]; user = [IRCUser IRCUserWithString: who]; - if ([user.nickname isEqual: nickname]) { + if ([[user nickname] isEqual: nickname]) { [nickname release]; - nickname = [user.nickname copy]; + nickname = [[user nickname] copy]; } - for (IRCChannel *channel in channels) { - if ([channel.users containsObject: user.nickname]) { - [channel IRC_removeUser: user.nickname]; + enumerator = [channels keyEnumerator]; + while ((channel = [enumerator nextObject]) != nil) { + if ([[channel users] containsObject: [user nickname]]) { + [channel IRC_removeUser: [user nickname]]; [channel IRC_addUser: newNickname]; } } - if ([delegate respondsToSelector: - @selector(connection:didSeeUser:changeNicknameTo:)]) - [delegate connection: self - didSeeUser: user - changeNicknameTo: newNickname]; + [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]; + if ([action isEqual: @"PRIVMSG"] && [components count] >= 4) { + OFString *from = [components objectAtIndex: 0]; + OFString *to = [components objectAtIndex: 2]; IRCUser *user; OFString *msg; - size_t pos = from.length + 1 + - [[split objectAtIndex: 1] length] + 1 + to.length; + size_t pos = [from length] + 1 + + [[components objectAtIndex: 1] length] + 1 + [to length]; - from = [from substringWithRange: of_range(1, from.length - 1)]; + from = [from substringWithRange: + of_range(1, [from length] - 1)]; msg = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; + 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]; + [delegate connection: self + didReceiveMessage: msg + fromUser: user + inChannel: channel]; + } else + [delegate connection: self + didReceivePrivateMessage: msg + fromUser: user]; + return; } /* NOTICE */ - if ([action isEqual: @"NOTICE"] && split.count >= 4) { - OFString *from = [split objectAtIndex: 0]; - OFString *to = [split objectAtIndex: 2]; + if ([action isEqual: @"NOTICE"] && [components count] >= 4) { + OFString *from = [components objectAtIndex: 0]; + OFString *to = [components objectAtIndex: 2]; IRCUser *user = nil; OFString *notice; - size_t pos = from.length + 1 + - [[split objectAtIndex: 1] length] + 1 + to.length; + size_t pos = [from length] + 1 + + [[components objectAtIndex: 1] length] + 1 + [to length]; - from = [from substringWithRange: of_range(1, from.length - 1)]; + from = [from substringWithRange: + of_range(1, [from length] - 1)]; notice = [line substringWithRange: - of_range(pos + 2, line.length - pos - 2)]; + 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]; @@ -462,38 +503,39 @@ 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]; + [delegate connection: self + didReceiveNotice: notice + fromUser: user + inChannel: channel]; + } else + [delegate connection: self + didReceiveNotice: notice + fromUser: user]; + return; } } + +- (void)processLine: (OFString*)line +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + [self IRC_processLine: line]; + + [pool release]; +} - (BOOL)connection: (OFTCPSocket*)connection didReceiveISO88591Line: (OFString*)line context: (id)context exception: (OFException*)exception { if (line != nil) { - [self processLine: line]; + [self IRC_processLine: line]; [sock asyncReadLineWithTarget: self selector: @selector(connection: didReceiveLine:context: exception:) context: nil]; @@ -506,11 +548,11 @@ didReceiveLine: (OFString*)line context: (id)context exception: (OFException*)exception { if (line != nil) { - [self processLine: line]; + [self IRC_processLine: line]; return YES; } if ([exception isKindOfClass: [OFInvalidEncodingException class]]) [sock asyncReadLineWithEncoding: OF_STRING_ENCODING_ISO_8859_1 @@ -539,7 +581,91 @@ [username release]; [realname release]; [channels release]; [super dealloc]; +} +@end + +@implementation OFObject (IRCConnectionDelegate) +- (void)connection: (IRCConnection*)connection + didReceiveLine: (OFString*)line +{ +} + +- (void)connection: (IRCConnection*)connection + didSendLine: (OFString*)line +{ +} + +- (void)connectionWasEstablished: (IRCConnection*)connection +{ +} + +- (void)connection: (IRCConnection*)connection + didSeeUser: (IRCUser*)user + joinChannel: (IRCChannel*)channel +{ +} + +- (void)connection: (IRCConnection*)connection + didSeeUser: (IRCUser*)user + leaveChannel: (IRCChannel*)channel + withReason: (OFString*)reason +{ +} + +- (void)connection: (IRCConnection*)connection + didSeeUser: (IRCUser*)user + changeNicknameTo: (OFString*)nickname +{ +} + +- (void)connection: (IRCConnection*)connection + didSeeUser: (IRCUser*)user + kickUser: (OFString*)kickedUser + fromChannel: (IRCChannel*)channel + withReason: (OFString*)reason +{ +} + +- (void)connection: (IRCConnection*)connection + didSeeUserQuit: (IRCUser*)user + withReason: (OFString*)reason +{ +} + +- (void)connection: (IRCConnection*)connection + didReceiveMessage: (OFString*)msg + fromUser: (IRCUser*)user + inChannel: (IRCChannel*)channel +{ +} + +- (void)connection: (IRCConnection*)connection + didReceivePrivateMessage: (OFString*)msg + fromUser: (IRCUser*)user +{ +} + +- (void)connection: (IRCConnection*)connection + didReceiveNotice: (OFString*)notice + fromUser: (IRCUser*)user +{ +} + +- (void)connection: (IRCConnection*)connection + didReceiveNotice: (OFString*)notice + fromUser: (IRCUser*)user + inChannel: (IRCChannel*)channel +{ +} + +- (void)connection: (IRCConnection*)connection + didReceiveNamesForChannel: (IRCChannel*)channel +{ +} + +- (void)connectionWasClosed: (IRCConnection*)connection +{ } @end