/* * Grouch.app Copyright (C) 2006 Andy Sveikauskas * ------------------------------------------------------------------------ * This program is free software under the GNU General Public License * -- * When users from your buddy list sign in and out, they end up here. * Think of it like purgatory. */ #import #import #import #import #import struct buddy { NSString *nick; int warning; OscarTlvListIn *props; }; static time_t timeOfMessage; @interface OscarSnac0003Base : NSObject - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap; - (void)handleSnacForClient:(OscarFlap*)flap ofFamily:(int)family andType:(int)type withFlags:(int)flags andTag:tag buffer:(OscarIncomingSnac*)buf; @end @implementation OscarSnac0003Base - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap { } - (void)handleSnacForClient:(OscarFlap*)flap ofFamily:(int)family andType:(int)type withFlags:(int)flags andTag:tag buffer:(OscarIncomingSnac*)buf { time(&timeOfMessage); while( [buf bytesRemaining] ) { struct buddy fool; fool.nick = [buf readPascalString]; fool.warning = [buf readInt16]; fool.props = [buf readTlvList]; [self processBuddy:&fool forClient:flap]; } } @end /* * Buddy sign on */ @interface OscarSnac0003000b : OscarSnac0003Base - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap; @end void oscar_process_buddy( int warn, OscarTlvListIn *tlv, id u ) { BOOL away = NO; OscarIncomingSnac *data; if( ![u online] ) [u online:YES]; [u warn:warn]; if( (data=[tlv getTLV:0x01]) ) { int flags = [data readInt16]; int timeTLV; if( (flags & 0x20) && !(flags & 0x40) ) // away && !icq away = YES; timeTLV = (flags&0x4) ? 0x10 : 0x0f; if( (data=[tlv getTLV:timeTLV]) ) [u onlineSince:[data readInt32]*60 + timeOfMessage]; } if( (data=[tlv getTLV:0x06]) ) { int flags = [data readInt16]; if( flags & 0x17 ) away = YES; } [u away:away]; if( (data=[tlv getTLV:0x04]) ) [u idle:[data readInt32]*60 + timeOfMessage]; else [u idle:0]; [u reloadData]; // TODO: only do this when we need to } @implementation OscarSnac0003000b - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap { OscarClient *oscar = [flap client]; id cli = [oscar getUI]; id u = [cli getUser:bud->nick]; OscarTlvListIn *tlv = bud->props; oscar_process_buddy( bud->warning, tlv, u ); } @end /* * Buddy sign off */ @interface OscarSnac0003000c : OscarSnac0003Base - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap; @end @implementation OscarSnac0003000c - (void)processBuddy:(struct buddy*)bud forClient:(OscarFlap*)flap { OscarClient *oscar = [flap client]; id cli = [oscar getUI]; id u = [cli getUser:bud->nick]; [u online:NO]; [u reloadData]; } @end @implementation OscarListHandler + get { static id r = nil; if( r ) return r; else return r = [OscarListHandler new]; } - init { [super init]; [super initForFamily:0x03 andVersion:0x01 andDLL:0x0629]; [self addHandler:[OscarErrorHandler get] forType:0x01]; [self addHandler:[OscarSnac0003000b new] forType:0x0b]; [self addHandler:[OscarSnac0003000c new] forType:0x0c]; return self; } @end