Changeset 1862

Show
Ignore:
Timestamp:
09/15/04 19:20:41 (4 years ago)
Author:
timothy
Message:

MVChatConnection is now a class cluster, awaiting the SILC subclass. The real IRC connection class is MVIRCChatConnection. We now have a MVChatConnectionType enum, with IRC and SILC. This change will allow for future growth.

Files:

Legend:

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

    r1830 r1862  
    345345                                1C0D8867067D1E7100E851AC, 
    346346                                1CF4E5120698E9E900986498, 
     347                                1C5A1A2506F8F4A000A51F10, 
    347348                        ); 
    348349                        isa = PBXSourcesBuildPhase; 
     
    401402                        refType = 3; 
    402403                        sourceTree = BUILT_PRODUCTS_DIR; 
     404                }; 
     405                1C5A1A2206F8F4A000A51F10 = { 
     406                        fileEncoding = 4; 
     407                        isa = PBXFileReference; 
     408                        lastKnownFileType = sourcecode.c.h; 
     409                        path = MVIRCChatConnection.h; 
     410                        refType = 4; 
     411                        sourceTree = "<group>"; 
     412                }; 
     413                1C5A1A2306F8F4A000A51F10 = { 
     414                        fileEncoding = 4; 
     415                        isa = PBXFileReference; 
     416                        lastKnownFileType = sourcecode.c.objc; 
     417                        path = MVIRCChatConnection.m; 
     418                        refType = 4; 
     419                        sourceTree = "<group>"; 
     420                }; 
     421                1C5A1A2506F8F4A000A51F10 = { 
     422                        fileRef = 1C5A1A2306F8F4A000A51F10; 
     423                        isa = PBXBuildFile; 
     424                        settings = { 
     425                        }; 
    403426                }; 
    404427                1C6C83A00632186900698F55 = { 
     
    32383261                                F52D043001873FC401EE70DE, 
    32393262                                F52D043101873FC401EE70DE, 
     3263                                1C5A1A2306F8F4A000A51F10, 
     3264                                1C5A1A2206F8F4A000A51F10, 
    32403265                                1C943AAA063C260800618CD9, 
    32413266                                1C943AA9063C260800618CD9, 
  • trunk/Colloquy.xcode/project.pbxproj

    r1823 r1862  
    11121112                        settings = { 
    11131113                        }; 
     1114                }; 
     1115                1C5A1A1106F8F42C00A51F10 = { 
     1116                        fileEncoding = 4; 
     1117                        isa = PBXFileReference; 
     1118                        lastKnownFileType = sourcecode.c.h; 
     1119                        path = MVChatConnection.h; 
     1120                        refType = 4; 
     1121                        sourceTree = "<group>"; 
     1122                }; 
     1123                1C5A1A1206F8F42C00A51F10 = { 
     1124                        fileEncoding = 4; 
     1125                        isa = PBXFileReference; 
     1126                        lastKnownFileType = sourcecode.c.objc; 
     1127                        path = MVChatConnection.m; 
     1128                        refType = 4; 
     1129                        sourceTree = "<group>"; 
    11141130                }; 
    11151131                1C6075E005138ED600A8FE6E = { 
     
    44084424                        isa = PBXFileReference; 
    44094425                        lastKnownFileType = sourcecode.c.objc; 
    4410                         path = MVChatConnection.m; 
     4426                        path = MVIRCChatConnection.m; 
    44114427                        refType = 4; 
    44124428                        sourceTree = "<group>"; 
     
    44164432                        isa = PBXFileReference; 
    44174433                        lastKnownFileType = sourcecode.c.h; 
    4418                         path = MVChatConnection.h; 
     4434                        path = MVIRCChatConnection.h; 
    44194435                        refType = 4; 
    44204436                        sourceTree = "<group>"; 
     
    44304446                F5394BBA0378DD7601A35792 = { 
    44314447                        children = ( 
     4448                                1C5A1A1206F8F42C00A51F10, 
     4449                                1C5A1A1106F8F42C00A51F10, 
    44324450                                F52D043001873FC401EE70DE, 
    44334451                                F52D043101873FC401EE70DE, 
  • trunk/JVChatMemberInspector.m

    r1823 r1862  
    162162 
    163163- (void) errorOccurred:(NSNotification *) notification { 
    164       MVChatError error = (MVChatError) [[[notification userInfo] objectForKey:@"error"] intValue]; 
     164/*    MVChatError error = (MVChatError) [[[notification userInfo] objectForKey:@"error"] intValue]; 
    165165        id target = [[notification userInfo] objectForKey:@"target"]; 
    166166        if( ! [target isKindOfClass:[NSString class]] || [target caseInsensitiveCompare:[_member nickname]] != NSOrderedSame ) return; 
     
    169169                [address setObjectValue:NSLocalizedString( @"n/a", "not applicable or not available" )]; 
    170170                [address setToolTip:nil]; 
    171         } 
     171        } */ 
    172172} 
    173173 
  • trunk/MVChatConnection.h

    r1858 r1862  
     1typedef enum { 
     2        MVChatConnectionIRCType = 'ircC', 
     3        MVChatConnectionSILCType = 'silC' 
     4} MVChatConnectionType; 
     5 
    16typedef enum { 
    27        MVChatConnectionDisconnectedStatus = 'disC', 
     
    3237        MVChatMemberVoiceMode = 0x4 
    3338} MVChatMemberMode; 
    34  
    35 typedef enum { 
    36         MVChatNoError, 
    37         MVChatConnectingError, 
    38         MVChatNoMatchError, 
    39         MVChatPacketError, 
    40         MVChatBadUserPasswordError, 
    41         MVChatSequenceError, 
    42         MVChatFrameTypeError, 
    43         MVChatPacketSizeError, 
    44         MVChatServerError, 
    45         MVChatUnknownError, 
    46         MVChatBlockedError, 
    47         MVChatWiredPacketError, 
    48         MVChatCallbackNumberError, 
    49         MVChatBadTargetError, 
    50         MVChatNotFoundError, 
    51         MVChatDisconnectError, 
    52         MVChatSocketError, 
    53         MVChatDNSError, 
    54         MVChatVersionError, 
    55         MVChatUserUnavailableError, 
    56         MVChatUserInfoUnavailableError, 
    57         MVChatTooFastError, 
    58         MVChatRoomUnavailableError, 
    59         MVChatIncomingError, 
    60         MVChatUserDisconnectError, 
    61         MVChatInvalidFormatError, 
    62         MVChatIdleFastError, 
    63         MVChatBadRoomError, 
    64         MVChatBadMessageError, 
    65         MVChatBadPrototypeError, 
    66         MVChatNotConnectedError, 
    67         MVChatBadConnectionError, 
    68         MVChatNoPermissionsError, 
    69         MVChatNoChangePasswordError, 
    70         MVChatDuplicateUserError, 
    71         MVChatDuplicateRoomError, 
    72         MVChatIOError, 
    73         MVChatBadHandleError, 
    74         MVChatTimeoutError, 
    75         MVChatNotDoneError 
    76 } MVChatError; 
    7739 
    7840@class MVUploadFileTransfer; 
     
    13698extern NSString *MVChatConnectionSubcodeReplyNotification; 
    13799 
    138 extern NSRecursiveLock *MVChatConnectionThreadLock; 
    139  
    140 #pragma mark - 
    141  
    142100@interface MVChatConnection : NSObject { 
    143 @private 
     101@protected 
    144102        NSTimer *_reconnectTimer; 
    145103        NSString *_npassword; 
    146         NSString *_proxyUsername; 
    147         NSString *_proxyPassword; 
    148104        MVChatConnectionStatus _status; 
    149105        MVChatConnectionProxy _proxy; 
    150106        NSStringEncoding _encoding; 
    151107 
    152         void *_chatConnection /* SERVER_REC */; 
    153         void *_chatConnectionSettings /* SERVER_CONNECT_REC */; 
    154108        NSMutableDictionary *_roomsCache; 
    155109        NSDate *_lastConnectAttempt; 
     
    162116} 
    163117- (id) initWithURL:(NSURL *) url; 
    164 - (id) initWithServer:(NSString *) server port:(unsigned short) port user:(NSString *) nickname; 
     118- (id) initWithServer:(NSString *) server type:(MVChatConnectionType) type port:(unsigned short) port user:(NSString *) nickname; 
     119 
     120- (MVChatConnectionType) type; 
    165121 
    166122- (void) connect; 
     
    171127#pragma mark - 
    172128 
     129- (NSString *) urlScheme; 
    173130- (NSURL *) url; 
    174131 
     
    230187#pragma mark - 
    231188 
     189- (void) sendMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) encoding toTarget:(NSString *) target asAction:(BOOL) action; 
    232190- (void) sendMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) encoding toUser:(NSString *) user asAction:(BOOL) action; 
    233191- (void) sendMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) encoding toChatRoom:(NSString *) room asAction:(BOOL) action; 
  • trunk/MVChatConnection.m

    r1861 r1862  
    1 #import <unistd.h> 
    2  
    31#import "MVChatConnection.h" 
     2#import "MVIRCChatConnection.h" 
    43#import "MVFileTransfer.h" 
    54#import "MVChatPluginManager.h" 
    65#import "MVChatScriptPlugin.h" 
     6#import "NSURLAdditions.h" 
    77#import "NSStringAdditions.h" 
    88#import "NSAttributedStringAdditions.h" 
    9 #import "NSColorAdditions.h" 
    109#import "NSMethodSignatureAdditions.h" 
    11 #import "NSNotificationAdditions.h" 
    12 #import "NSURLAdditions.h" 
    13 #import "NSDataAdditions.h" 
    14  
    15 #define MODULE_NAME "MVChatConnection" 
    16  
    17 #import "common.h" 
    18 #import "core.h" 
    19 #import "irc.h" 
    20 #import "signals.h" 
    21 #import "servers.h" 
    22 #import "servers-setup.h" 
    23 #import "servers-reconnect.h" 
    24 #import "chat-protocols.h" 
    25 #import "net-sendbuffer.h" 
    26 #import "channels.h" 
    27 #import "nicklist.h" 
    28 #import "notifylist.h" 
    29 #import "mode-lists.h" 
    30 #import "settings.h" 
    31  
    32 #import "config.h" 
    33 #import "dcc.h" 
    34 #import "dcc-file.h" 
    35 #import "dcc-get.h" 
    3610 
    3711NSString *MVChatConnectionGotRawMessageNotification = @"MVChatConnectionGotRawMessageNotification"; 
     
    9266NSString *MVChatConnectionSubcodeReplyNotification = @"MVChatConnectionSubcodeReplyNotification"; 
    9367 
    94 void irc_init( void ); 
    95 void irc_deinit( void ); 
    96  
    97 #pragma mark - 
    98  
    99 NSRecursiveLock *MVChatConnectionThreadLock = nil; 
    100 static BOOL applicationQuitting = NO; 
    101 static unsigned int connectionCount = 0; 
    102 static GMainLoop *glibMainLoop = NULL; 
    103  
    104 typedef struct { 
    105         MVChatConnection *connection; 
    106 } MVChatConnectionModuleData; 
     68BOOL MVChatApplicationQuitting = NO; 
    10769 
    10870@interface MVChatConnection (MVChatConnectionPrivate) 
    109 + (MVChatConnection *) _connectionForServer:(SERVER_REC *) server; 
    110 + (void) _registerCallbacks; 
    111 + (void) _deregisterCallbacks; 
    112 + (const char *) _flattenedIRCStringForMessage:(NSAttributedString *) message withEncoding:(NSStringEncoding) enc; 
    113 - (SERVER_REC *) _irssiConnection; 
    114 - (void) _setIrssiConnection:(SERVER_REC *) server; 
    115 - (SERVER_CONNECT_REC *) _irssiConnectSettings; 
    116 - (void) _setIrssiConnectSettings:(SERVER_CONNECT_REC *) settings; 
    117 - (void) _addRoomToCache:(NSMutableDictionary *) info; 
    118 - (NSString *) _roomWithProperPrefix:(NSString *) room; 
    119 - (void) _nicknameIdentified:(BOOL) identified; 
    12071- (void) _willConnect; 
    12172- (void) _didConnect; 
     
    12374- (void) _willDisconnect; 
    12475- (void) _didDisconnect; 
    125 - (void) _forceDisconnect; 
    12676- (void) _scheduleReconnectAttemptEvery:(NSTimeInterval) seconds; 
    12777- (void) _cancelReconnectAttempts; 
     
    13080#pragma mark - 
    13181 
    132 #define ERR_NOSUCHNICK       401 // <nickname> :No such nick/channel 
    133 #define ERR_NOSUCHSERVER     402 // <server name> :No such server 
    134 #define ERR_NOSUCHCHANNEL    403 // <channel name> :No such channel 
    135 #define ERR_CANNOTSENDTOCHAN 404 // <channel name> :Cannot send to channel 
    136 #define ERR_TOOMANYCHANNELS  405 // <channel name> :You have joined too many channels 
    137 #define ERR_WASNOSUCHNICK    406 // <nickname> :There was no such nickname 
    138 #define ERR_TOOMANYTARGETS   407 // <target> :Duplicate recipients. No message delivered 
    139 #define ERR_NOSUCHSERVICE    408  
    140 #define ERR_NOORIGIN         409 // :No origin specified 
    141 #define ERR_CANNOTKNOCK      410  
    142 #define ERR_NORECIPIENT      411 // :No recipient given (<command>) 
    143 #define ERR_NOTEXTTOSEND     412 // :No text to send 
    144 #define ERR_NOTOPLEVEL       413 // <mask> :No toplevel domain specified 
    145 #define ERR_WILDTOPLEVEL     414 // <mask> :Wildcard in toplevel domain 
    146 #define ERR_SERVICESUP       415 
    147  
    148 #define ERR_UNKNOWNCOMMAND   421 // <command> :Unknown command 
    149 #define ERR_NOMOTD           422 // :MOTD File is missing 
    150 #define ERR_NOADMININFO      423 // <server> :No administrative info available 
    151 #define ERR_FILEERROR        424 // :File error doing <file op> on <file> 
    152  
    153 #define ERR_NONICKNAMEGIVEN  431 // :No nickname given 
    154 #define ERR_ERRONEUSNICKNAME 432 // <nick> :Erroneus nickname 
    155 #define ERR_NICKNAMEINUSE    433 // <nick> :Nickname is already in use 
    156 #define ERR_SERVICENAMEINUSE 434  
    157 #define ERR_SERVICECONFUSED  435 
    158 #define ERR_NICKCOLLISION    436 // <nick> :Nickname collision KILL 
    159 #define ERR_BANNICKCHANGE    437 
    160 #define ERR_NCHANGETOOFAST   438 
    161 #define ERR_TARGETTOOFAST    439 
    162 #define ERR_SERVICESDOWN     440 
    163  
    164 #define ERR_USERNOTINCHANNEL 441 // <nick> <channel> :They aren't on that channel 
    165 #define ERR_NOTONCHANNEL     442 // <channel> :You're not on that channel 
    166 #define ERR_USERONCHANNEL    443 // <user> <channel> :is already on channel 
    167 #define ERR_NOLOGIN          444 // <user> :User not logged in 
    168 #define ERR_SUMMONDISABLED   445 // :SUMMON has been disabled 
    169 #define ERR_USERSDISABLED    446 // :USERS has been disabled 
    170  
    171 #define ERR_NOTREGISTERED    451 // :You have not registered 
    172  
    173 #define ERR_HOSTILENAME      455 
    174  
    175 #define ERR_NEEDMOREPARAMS   461 // <command> :Not enough parameters 
    176 #define ERR_ALREADYREGISTRED 462 // :You may not reregister 
    177 #define ERR_NOPERMFORHOST    463 // :Your host isn't among the privileged 
    178 #define ERR_PASSWDMISMATCH   464 // :Password incorrect 
    179 #define ERR_YOUREBANNEDCREEP 465 // :You are banned from this server 
    180 #define ERR_YOUWILLBEBANNED  466 
    181 #define ERR_KEYSET           467 // <channel> :Channel key already set 
    182 #define ERR_ONLYSERVERSCANCHANGE 468 
    183  
    184 #define ERR_CHANNELISFULL    471 // <channel> :Cannot join channel (+l) 
    185 #define ERR_UNKNOWNMODE      472 // <char> :is unknown mode char to me 
    186 #define ERR_INVITEONLYCHAN   473 // <channel> :Cannot join channel (+i) 
    187 #define ERR_BANNEDFROMCHAN   474 // <channel> :Cannot join channel (+b) 
    188 #define ERR_BADCHANNELKEY    475 // <channel> :Cannot join channel (+k) 
    189 #define ERR_BADCHANMASK      476 
    190 #define ERR_NEEDREGGEDNICK   477 
    191 #define ERR_BANLISTFULL      478 
    192 #define ERR_NOPRIVILEGES     481 // :Permission Denied- You're not an IRC operator 
    193 #define ERR_CHANOPRIVSNEEDED 482 // <channel> :You're not channel operator 
    194 #define ERR_CANTKILLSERVER   483 // :You cant kill a server! 
    195 #define ERR_CANTKICKOPER     484 // Undernet extension was ERR_ISCHANSERVICE 
    196 #define ERR_CANTKICKADMIN        485 
    197  
    198 #define ERR_NOOPERHOST       491 // :No O-lines for your host 
    199 #define ERR_NOSERVICEHOST    492 
    200  
    201 #define ERR_UMODEUNKNOWNFLAG 501 // :Unknown MODE flag 
    202 #define ERR_USERSDONTMATCH   502 // :Cant change mode for other users 
    203  
    204 #define ERR_SILELISTFULL     511 
    205 #define ERR_TOOMANYWATCH     512 
    206 #define ERR_NEEDPONG         513 
    207  
    208 #define ERR_LISTSYNTAX       521 
    209  
    210 static void MVChatConnecting( SERVER_REC *server ) { 
    211         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    212         [self performSelectorOnMainThread:@selector( _willConnect ) withObject:nil waitUntilDone:NO]; 
    213 } 
    214  
    215 static void MVChatConnected( SERVER_REC *server ) { 
    216         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    217         [self performSelectorOnMainThread:@selector( _didConnect ) withObject:nil waitUntilDone:NO]; 
    218 } 
    219  
    220 static void MVChatDisconnect( SERVER_REC *server ) { 
    221         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    222         [self performSelectorOnMainThread:@selector( _didDisconnect ) withObject:nil waitUntilDone:NO]; 
    223 } 
    224  
    225 static void MVChatConnectFailed( SERVER_REC *server ) { 
    226         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    227         if( ! self ) return; 
    228  
    229         server_ref( server ); 
    230         [self performSelectorOnMainThread:@selector( _didNotConnect ) withObject:nil waitUntilDone:NO]; 
    231 } 
    232  
    233 static void MVChatRawIncomingMessage( SERVER_REC *server, char *data ) { 
    234         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    235         if( ! self ) return; 
    236  
    237         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:data], @"message", [NSNumber numberWithBool:NO], @"outbound", nil]]; 
    238         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    239 } 
    240  
    241 static void MVChatRawOutgoingMessage( SERVER_REC *server, char *data ) { 
    242         MVChatConnection *self = [MVChatConnection _connectionForServer:server]; 
    243         if( ! self ) return; 
    244  
    245         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotRawMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:data], @"message", [NSNumber numberWithBool:YES], @"outbound", nil]]; 
    246         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    247 } 
    248  
    249 #pragma mark - 
    250  
    251 static void MVChatNickTaken( IRC_SERVER_REC *server, const char *data, const char *by, const char *address ) { 
    252         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    253         if( ! self ) return; 
    254  
    255         if( ((SERVER_REC *)server) -> connected ) { 
    256                 // error 
    257                 return; 
    258         } else { 
    259                 NSString *nick = [self nextAlternateNickname]; 
    260                 if( nick ) { 
    261                         [self sendRawMessage:[NSString stringWithFormat:@"NICK %@", nick] immediately:YES]; 
    262                         signal_stop(); 
    263                 } 
    264         } 
    265 } 
    266  
    267 #pragma mark - 
    268  
    269 static void MVChatJoinedRoom( CHANNEL_REC *channel ) { 
    270         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    271         if( ! self ) return; 
    272  
    273         GSList *nicks = nicklist_getnicks( channel ); 
    274         GSList *nickItem = NULL; 
    275         NSMutableArray *nickArray = [NSMutableArray arrayWithCapacity:g_slist_length( nicks )]; 
    276  
    277         for( nickItem = nicks; nickItem != NULL; nickItem = g_slist_next( nickItem ) ) { 
    278                 NICK_REC *nick = nickItem -> data; 
    279                 NSMutableDictionary *info = [NSMutableDictionary dictionary]; 
    280  
    281                 [info setObject:[self stringWithEncodedBytes:nick -> nick] forKey:@"nickname"]; 
    282                 [info setObject:[NSNumber numberWithBool:nick -> serverop] forKey:@"serverOperator"]; 
    283                 [info setObject:[NSNumber numberWithBool:nick -> op] forKey:@"operator"]; 
    284                 [info setObject:[NSNumber numberWithBool:nick -> halfop] forKey:@"halfOperator"]; 
    285                 [info setObject:[NSNumber numberWithBool:nick -> voice] forKey:@"voice"]; 
    286  
    287                 NSString *host = ( nick -> host ? [self stringWithEncodedBytes:nick -> host] : nil ); 
    288                 if( host ) [info setObject:host forKey:@"address"]; 
    289  
    290                 NSString *realName = ( nick -> realname ? [self stringWithEncodedBytes:nick -> realname] : nil ); 
    291                 if( realName ) [info setObject:realName forKey:@"realName"]; 
    292  
    293                 [nickArray addObject:info]; 
    294         } 
    295  
    296         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionRoomExistingMemberListNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", nickArray, @"members", nil]]; 
    297         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    298 } 
    299  
    300 static void MVChatJoinedWhoList( CHANNEL_REC *channel ) { 
    301         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    302         if( ! self ) return; 
    303  
    304         GSList *nicks = nicklist_getnicks( channel ); 
    305         GSList *nickItem = NULL; 
    306         NSMutableArray *nickArray = [NSMutableArray arrayWithCapacity:g_slist_length( nicks )]; 
    307  
    308         for( nickItem = nicks; nickItem != NULL; nickItem = g_slist_next( nickItem ) ) { 
    309                 NICK_REC *nick = nickItem -> data; 
    310  
    311                 NSMutableDictionary *info = [NSMutableDictionary dictionary]; 
    312                 [info setObject:[self stringWithEncodedBytes:nick -> nick] forKey:@"nickname"]; 
    313  
    314                 NSString *host = ( nick -> host ? [self stringWithEncodedBytes:nick -> host] : nil ); 
    315                 if( host ) [info setObject:host forKey:@"address"]; 
    316  
    317                 NSString *realName = ( nick -> realname ? [self stringWithEncodedBytes:nick -> realname] : nil ); 
    318                 if( realName ) [info setObject:realName forKey:@"realName"]; 
    319  
    320                 [nickArray addObject:info]; 
    321         } 
    322  
    323         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotJoinWhoListNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", nickArray, @"list", nil]]; 
    324         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    325 } 
    326  
    327 static void MVChatLeftRoom( CHANNEL_REC *channel ) { 
    328         if( channel -> kicked || channel -> server -> disconnected ) return; 
    329  
    330         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    331         if( ! self ) return; 
    332  
    333         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionLeftRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", nil]]; 
    334         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    335 } 
    336  
    337 static void MVChatRoomTopicChanged( CHANNEL_REC *channel ) { 
    338         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    339         if( ! self ) return; 
    340         if( ! channel -> topic ) return; 
    341  
    342         NSData *msgData = [NSData dataWithBytes:channel -> topic length:strlen( channel -> topic )]; 
    343         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotRoomTopicNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", ( channel -> topic_by ? (id) [self stringWithEncodedBytes:channel -> topic_by] : (id) [NSNull null] ), @"author", ( msgData ? (id) msgData : (id) [NSNull null] ), @"topic", [NSDate dateWithTimeIntervalSince1970:channel -> topic_time], @"time", [NSNumber numberWithBool:( ! channel -> synced )], @"justJoined", nil]]; 
    344         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    345 } 
    346  
    347 #pragma mark - 
    348  
    349 static void MVChatUserJoinedRoom( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address ) { 
    350         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    351         if( ! self ) return; 
    352  
    353         char *channel = NULL; 
    354         char *params = event_get_params( data, 1, &channel ); 
    355  
    356         CHANNEL_REC *room = channel_find( (SERVER_REC *) server, channel ); 
    357         NICK_REC *nickname = nicklist_find( room, nick ); 
    358  
    359         if( [[self nickname] isEqualToString:[self stringWithEncodedBytes:nick]] ) { 
    360                 NSNotification *note = [NSNotification notificationWithName:MVChatConnectionJoinedRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", nil]]; 
    361                 [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    362                 return; 
    363         } 
    364  
    365         if( ! nickname ) return; 
    366  
    367         NSMutableDictionary *info = [NSMutableDictionary dictionary]; 
    368         [info setObject:[self stringWithEncodedBytes:nickname -> nick] forKey:@"nickname"]; 
    369         [info setObject:[NSNumber numberWithBool:nickname -> serverop] forKey:@"serverOperator"]; 
    370         [info setObject:[NSNumber numberWithBool:nickname -> op] forKey:@"operator"]; 
    371         [info setObject:[NSNumber numberWithBool:nickname -> halfop] forKey:@"halfOperator"]; 
    372         [info setObject:[NSNumber numberWithBool:nickname -> voice] forKey:@"voice"]; 
    373         if( nickname -> host ) [info setObject:[self stringWithEncodedBytes:nickname -> host] forKey:@"address"]; 
    374         if( nickname -> realname ) [info setObject:[self stringWithEncodedBytes:nickname -> realname] forKey:@"realName"]; 
    375  
    376         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionUserJoinedRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", [self stringWithEncodedBytes:nick], @"who", info, @"info", nil]]; 
    377         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    378  
    379         g_free( params ); 
    380 } 
    381  
    382 static void MVChatUserLeftRoom( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address ) { 
    383         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    384         if( ! self ) return; 
    385  
    386         if( [[self nickname] isEqualToString:[self stringWithEncodedBytes:nick]] ) return; 
    387  
    388         char *channel = NULL; 
    389         char *reason = NULL; 
    390         char *params = event_get_params( data, 2 | PARAM_FLAG_GETREST, &channel, &reason ); 
    391  
    392         NSData *reasonData = [NSData dataWithBytes:reason length:strlen( reason )]; 
    393         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionUserLeftRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", [self stringWithEncodedBytes:nick], @"who", [self stringWithEncodedBytes:address], @"address", ( reasonData ? (id) reasonData : (id) [NSNull null] ), @"reason", nil]]; 
    394         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    395  
    396         g_free( params ); 
    397 } 
    398  
    399 static void MVChatUserQuit( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address ) { 
    400         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    401         if( ! self ) return; 
    402  
    403         if( [[self nickname] isEqualToString:[self stringWithEncodedBytes:nick]] ) return; 
    404  
    405         if( *data == ':' ) data++; 
    406  
    407         NSData *msgData = [NSData dataWithBytes:data length:strlen( data )]; 
    408         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionUserQuitNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", [self stringWithEncodedBytes:address], @"address", ( msgData ? (id) msgData : (id) [NSNull null] ), @"reason", nil]]; 
    409         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    410 } 
    411  
    412 static void MVChatUserKicked( IRC_SERVER_REC *server, const char *data, const char *by, const char *address ) { 
    413         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    414         if( ! self ) return; 
    415  
    416         char *channel = NULL, *nick = NULL, *reason = NULL; 
    417         char *params = event_get_params( data, 3 | PARAM_FLAG_GETREST, &channel, &nick, &reason ); 
    418  
    419         NSData *msgData = [NSData dataWithBytes:reason length:strlen( reason )]; 
    420         NSNotification *note = nil; 
    421  
    422         if( [[self nickname] isEqualToString:[self stringWithEncodedBytes:nick]] ) { 
    423                 note = [NSNotification notificationWithName:MVChatConnectionKickedFromRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", ( by ? (id)[self stringWithEncodedBytes:by] : (id)[NSNull null] ), @"by", ( msgData ? (id) msgData : (id) [NSNull null] ), @"reason", nil]];              
    424         } else { 
    425                 note = [NSNotification notificationWithName:MVChatConnectionUserKickedFromRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", [self stringWithEncodedBytes:nick], @"who", ( by ? (id)[self stringWithEncodedBytes:by] : (id)[NSNull null] ), @"by", ( msgData ? (id) msgData : (id) [NSNull null] ), @"reason", nil]]; 
    426         } 
    427  
    428         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    429  
    430         g_free( params );        
    431 } 
    432  
    433 static void MVChatInvited( IRC_SERVER_REC *server, const char *data, const char *by, const char *address ) { 
    434         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    435         if( ! self ) return; 
    436  
    437         char *channel = NULL; 
    438         char *params = event_get_params( data, 2, NULL, &channel ); 
    439  
    440         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionInvitedToRoomNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", [self stringWithEncodedBytes:by], @"from", nil]];          
    441         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    442  
    443         g_free( params );        
    444 } 
    445  
    446 static void MVChatUserAway( IRC_SERVER_REC *server, const char *data ) { 
    447         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    448         if( ! self ) return; 
    449  
    450         char *nick = NULL, *message = NULL; 
    451         char *params = event_get_params( data, 3 | PARAM_FLAG_GETREST, NULL, &nick, &message ); 
    452  
    453         NSData *msgData = [NSData dataWithBytes:message length:strlen( message )]; 
    454  
    455         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionUserAwayStatusNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", msgData, @"message", nil]];           
    456         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    457  
    458         g_free( params );        
    459 } 
    460  
    461 #pragma mark - 
    462  
    463 static void MVChatSelfAwayChanged( IRC_SERVER_REC *server ) { 
    464         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    465         if( ! self ) return; 
    466  
    467         NSNumber *away = [NSNumber numberWithBool:( ((SERVER_REC *)server) -> usermode_away == TRUE )]; 
    468  
    469         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionSelfAwayStatusNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:away, @"away", nil]]; 
    470         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    471 } 
    472  
    473 #pragma mark - 
    474  
    475 static void MVChatGetMessage( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address ) { 
    476         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    477         if( ! self ) return; 
    478         if( ! nick ) return; 
    479  
    480         char *target = NULL, *message = NULL; 
    481         char *params = event_get_params( data, 2 | PARAM_FLAG_GETREST, &target, &message ); 
    482         if( ! address ) address = ""; 
    483  
    484         if( *target == '@' && ischannel( target[1] ) ) target = target + 1; 
    485  
    486         NSData *msgData = [NSData dataWithBytes:message length:strlen( message )]; 
    487         NSNotification *note = nil; 
    488  
    489         if( ischannel( *target ) ) { 
    490                 note = [NSNotification notificationWithName:MVChatConnectionGotRoomMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:target], @"room", [self stringWithEncodedBytes:nick], @"from", msgData, @"message", nil]]; 
    491         } else { 
    492                 note = [NSNotification notificationWithName:MVChatConnectionGotPrivateMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"from", msgData, @"message", nil]]; 
    493         } 
    494  
    495         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    496  
    497         g_free( params ); 
    498 } 
    499  
    500 static void MVChatGetAutoMessage( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address ) { 
    501         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    502         if( ! self ) return; 
    503         if( ! nick ) return; 
    504  
    505         char *target = NULL, *message = NULL; 
    506         char *params = event_get_params( data, 2 | PARAM_FLAG_GETREST, &target, &message ); 
    507         if( ! address ) address = ""; 
    508  
    509         NSNotification *note = nil; 
    510         NSData *msgData = [NSData dataWithBytes:message length:strlen( message )]; 
    511  
    512         if( ischannel( *target ) ) { 
    513                 note = [NSNotification notificationWithName:MVChatConnectionGotRoomMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:target], @"room", [self stringWithEncodedBytes:nick], @"from", [NSNumber numberWithBool:YES], @"auto", msgData, @"message", nil]]; 
    514         } else { 
    515                 note = [NSNotification notificationWithName:MVChatConnectionGotPrivateMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"from", [NSNumber numberWithBool:YES], @"auto", msgData, @"message", nil]]; 
    516                 if( ! strncasecmp( nick, "NickServ", 8 ) && message ) { 
    517                         if( strstr( message, nick ) && strstr( message, "IDENTIFY" ) ) { 
    518                                 if( ! [self nicknamePassword] ) { 
    519                                         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionNeedNicknamePasswordNotification object:self userInfo:nil]; 
    520                                         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    521                                 } else irc_send_cmdv( server, "PRIVMSG %s :IDENTIFY %s", nick, [self encodedBytesWithString:[self nicknamePassword]] ); 
    522                         } else if( strstr( message, "Password accepted" ) ) { 
    523                                 [self _nicknameIdentified:YES]; 
    524                         } else if( strstr( message, "authentication required" ) ) { 
    525                                 [self _nicknameIdentified:NO]; 
    526                         } 
    527                 } 
    528         } 
    529  
    530         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    531  
    532         g_free( params ); 
    533 } 
    534  
    535 static void MVChatGetActionMessage( IRC_SERVER_REC *server, const char *data, const char *nick, const char *address, const char *target ) { 
    536         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    537         if( ! self ) return; 
    538         if( ! nick ) return; 
    539         if( ! address ) address = ""; 
    540  
    541         NSData *msgData = [NSData dataWithBytes:data length:strlen( data )]; 
    542         NSNotification *note = nil; 
    543  
    544         if( ischannel( *target ) ) { 
    545                 note = [NSNotification notificationWithName:MVChatConnectionGotRoomMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:target], @"room", [self stringWithEncodedBytes:nick], @"from", [NSNumber numberWithBool:YES], @"action", msgData, @"message", nil]]; 
    546         } else { 
    547                 note = [NSNotification notificationWithName:MVChatConnectionGotPrivateMessageNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"from", [NSNumber numberWithBool:YES], @"action", msgData, @"message", nil]]; 
    548         } 
    549  
    550         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    551 } 
    552  
    553 #pragma mark - 
    554  
    555 static void MVChatUserNicknameChanged( CHANNEL_REC *channel, NICK_REC *nick, const char *oldnick ) { 
    556         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    557         if( ! self ) return; 
    558  
    559         NSNotification *note = nil; 
    560         if( [[self nickname] isEqualToString:[self stringWithEncodedBytes:oldnick]] ) { 
    561                 note = [NSNotification notificationWithName:MVChatConnectionNicknameAcceptedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick -> nick], @"nickname", nil]]; 
    562         } else { 
    563                 note = [NSNotification notificationWithName:MVChatConnectionUserNicknameChangedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", [self stringWithEncodedBytes:oldnick], @"oldNickname", [self stringWithEncodedBytes:nick -> nick], @"newNickname", nil]]; 
    564         } 
    565  
    566         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    567 } 
    568  
    569 static void MVChatGotUserMode( CHANNEL_REC *channel, NICK_REC *nick, char *by, char *mode, char *type ) { 
    570         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    571         if( ! self ) return; 
    572  
    573         unsigned int m = MVChatMemberNoModes; 
    574         if( *mode == '@' ) m = MVChatMemberOperatorMode; 
    575         else if( *mode == '%' ) m = MVChatMemberHalfOperatorMode; 
    576         else if( *mode == '+' ) m = MVChatMemberVoiceMode; 
    577  
    578         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotMemberModeNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", [self stringWithEncodedBytes:nick -> nick], @"who", ( by ? (id)[self stringWithEncodedBytes:by] : (id)[NSNull null] ), @"by", [NSNumber numberWithBool:( *type == '+' ? YES : NO )], @"enabled", [NSNumber numberWithUnsignedInt:m], @"mode", nil]]; 
    579         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    580 } 
    581  
    582 static void MVChatGotRoomMode( CHANNEL_REC *channel, const char *setby ) { 
    583         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    584         if( ! self ) return; 
    585  
    586         unsigned int currentModes = 0; 
    587         if( strchr( channel -> mode, 'p' ) ) 
    588                 currentModes |= MVChatRoomPrivateMode; 
    589         if( strchr( channel -> mode, 's' ) ) 
    590                 currentModes |= MVChatRoomSecretMode; 
    591         if( strchr( channel -> mode, 'i' ) ) 
    592                 currentModes |= MVChatRoomInviteOnlyMode; 
    593         if( strchr( channel -> mode, 'm' ) ) 
    594                 currentModes |= MVChatRoomModeratedMode; 
    595         if( strchr( channel -> mode, 'n' ) ) 
    596                 currentModes |= MVChatRoomNoOutsideMessagesMode; 
    597         if( strchr( channel -> mode, 't' ) ) 
    598                 currentModes |= MVChatRoomSetTopicOperatorOnlyMode; 
    599         if( strchr( channel -> mode, 'k' ) ) 
    600                 currentModes |= MVChatRoomPasswordRequiredMode; 
    601         if( strchr( channel -> mode, 'l' ) ) 
    602                 currentModes |= MVChatRoomMemberLimitMode; 
    603  
    604         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionGotRoomModeNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", [NSNumber numberWithUnsignedInt:currentModes], @"mode", [NSNumber numberWithUnsignedInt:channel -> limit], @"limit", ( channel -> key ? [self stringWithEncodedBytes:channel -> key] : @"" ), @"key", ( setby ? (id)[self stringWithEncodedBytes:setby] : (id)[NSNull null] ), @"by", nil]]; 
    605         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    606 } 
    607  
    608 #pragma mark - 
    609  
    610 static void MVChatBanNew( CHANNEL_REC *channel, BAN_REC *ban ) { 
    611         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    612         if( ! self ) return; 
    613          
    614         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionNewBanNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", [self stringWithEncodedBytes:ban -> ban], @"ban", ( ban -> setby ? (id)[self stringWithEncodedBytes:ban -> setby] : (id)[NSNull null] ), @"by", nil]]; 
    615         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    616 } 
    617  
    618 static void MVChatBanRemove( CHANNEL_REC *channel, BAN_REC *ban ) { 
    619         MVChatConnection *self = [MVChatConnection _connectionForServer:channel -> server]; 
    620         if( ! self ) return; 
    621          
    622         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionRemovedBanNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel -> name], @"room", [self stringWithEncodedBytes:ban -> ban], @"ban", ( ban -> setby ? (id)[self stringWithEncodedBytes:ban -> setby] : (id)[NSNull null] ), @"by", nil]]; 
    623         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    624 } 
    625  
    626 static void MVChatBanlistReceived( IRC_SERVER_REC *server, const char *data ) { 
    627         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    628         if( ! self ) return; 
    629          
    630         char *channel = NULL; 
    631         char *params = event_get_params( data, 2, NULL, &channel ); 
    632          
    633         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionBanlistReceivedNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:channel], @"room", nil]]; 
    634         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    635          
    636         g_free( params ); 
    637 } 
    638  
    639 #pragma mark - 
    640  
    641 static void MVChatBuddyOnline( IRC_SERVER_REC *server, const char *nick, const char *username, const char *host, const char *realname, const char *awaymsg ) { 
    642         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    643         if( ! self ) return; 
    644  
    645         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionBuddyIsOnlineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", nil]]; 
    646         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    647  
    648         if( awaymsg ) { // Mark the buddy as away 
    649                 note = [NSNotification notificationWithName:MVChatConnectionBuddyIsAwayNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", [self stringWithEncodedBytes:awaymsg], @"msg", nil]]; 
    650                 [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    651         } 
    652 } 
    653  
    654 static void MVChatBuddyOffline( IRC_SERVER_REC *server, const char *nick, const char *username, const char *host, const char *realname, const char *awaymsg ) { 
    655         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    656         if( ! self ) return; 
    657  
    658         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionBuddyIsOfflineNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", nil]]; 
    659         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    660 } 
    661  
    662 static void MVChatBuddyAway( IRC_SERVER_REC *server, const char *nick, const char *username, const char *host, const char *realname, const char *awaymsg ) { 
    663         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    664         if( ! self ) return; 
    665  
    666         NSNotification *note = nil; 
    667         if( awaymsg ) note = [NSNotification notificationWithName:MVChatConnectionBuddyIsAwayNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", [self stringWithEncodedBytes:awaymsg], @"msg", nil]]; 
    668         else note = [NSNotification notificationWithName:MVChatConnectionBuddyIsUnawayNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", nil]]; 
    669         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    670 } 
    671  
    672 static void MVChatBuddyUnidle( IRC_SERVER_REC *server, const char *nick, const char *username, const char *host, const char *realname, const char *awaymsg ) { 
    673         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    674         if( ! self ) return; 
    675  
    676         NSNotification *note = [NSNotification notificationWithName:MVChatConnectionBuddyIsIdleNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self stringWithEncodedBytes:nick], @"who", [NSNumber numberWithLong:0], @"idle", nil]]; 
    677         [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:note]; 
    678 } 
    679  
    680 #pragma mark - 
    681  
    682 static void MVChatUserWhois( IRC_SERVER_REC *server, const char *data ) { 
    683         MVChatConnection *self = [MVChatConnection _connectionForServer:(SERVER_REC *)server]; 
    684         if( ! self ) return; 
    685  
    686         char *nick = NULL, *user = NULL, *host = NULL, *realname = NULL; 
    687         char *params = event_