From 26af6789798f083551cbc309801819a34e38cda0 Mon Sep 17 00:00:00 2001 From: mid Date: Wed, 29 Dec 1999 09:30:30 +0000 Subject: [PATCH] Added capability block sending and chat invitation parsing. --- CHANGES | 11 +- aim_im.c | 350 ++++++++++++++++++++++++-------------- aim_misc.c | 94 +++++----- utils/faimtest/faimtest.c | 192 +++++++++++++-------- 4 files changed, 411 insertions(+), 236 deletions(-) diff --git a/CHANGES b/CHANGES index d7e4891..20dc779 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,13 @@ No release numbers ------------------ + - Wed Dec 29 09:14:45 UTC 1999 + - Added a capability block to aim_bos_setprofile. Can now get chat invites again. + - Extended ICBM parser to support channel 2 messages (chat invites) + - A channel parameter has been prepended to the varargs -- REQUIRES CLIENT CHANGES. + - Extended faimtest to support chat invites. + - Changed faimtest to get sn/password from environment + - Wed Dec 29 04:17:03 UTC 1999 - Added -g to CFLAGS - Added aim_sendconnack() to aim_login.c (needed for newer login) @@ -12,8 +19,8 @@ No release numbers - Fiddled with version information. Added aim_setversions() - Added table of SNAC names for showing unknown snacs (jbm) - Added a middle handler for MOTD - - Added new authorization SNACs to faim/aim_cbtypes.h - + - Added new authorization SNACs to faim/aim_cbtypes.h + - Sun Dec 26 22:59:10 UTC 1999 - Renamed login_phase1_struct to aim_login_struct - Changed cookie and sn to be static arrays in aim_login_struct diff --git a/aim_im.c b/aim_im.c index 2d038b4..e7ca202 100644 --- a/aim_im.c +++ b/aim_im.c @@ -158,21 +158,14 @@ u_long aim_send_im(struct aim_session_t *sess, int aim_parse_incoming_im_middle(struct aim_session_t *sess, struct command_rx_struct *command) { - struct aim_userinfo_s userinfo; - u_int i = 0, j = 0, y = 0, z = 0; - char *msg = NULL; - u_int icbmflags = 0; + u_int i = 0,z; rxcallback_t userfunc = NULL; u_char cookie[8]; int channel; struct aim_tlvlist_t *tlvlist; - struct aim_tlv_t *msgblocktlv, *tmptlv; - u_char *msgblock; + struct aim_userinfo_s userinfo; u_short wastebits; - u_short flag1,flag2; - memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); - i = 10; /* Skip SNAC header */ /* @@ -187,12 +180,19 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, * Channel 0x0001 is the message channel. There are * other channels for things called "rendevous" * which represent chat and some of the other new - * features of AIM2/3/3.5. We only support - * standard messages; those on channel 0x0001. + * features of AIM2/3/3.5. + * + * Channel 0x0002 is the Rendevous channel, which + * is where Chat Invitiations come from. + * */ channel = aimutil_get16(command->data+i); i += 2; - if (channel != 0x0001) + + /* + * + */ + if ((channel != 0x01) && (channel != 0x02)) { printf("faim: icbm: ICBM received on an unsupported channel. Ignoring.\n (chan = %04x)", channel); return 1; @@ -204,15 +204,19 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, memcpy(userinfo.sn, command->data+i+1, (int)command->data[i]); userinfo.sn[(int)command->data[i]] = '\0'; i += 1 + (int)command->data[i]; - + /* - * Unknown bits. + * Warning Level */ - wastebits = aimutil_get16(command->data+i); + userinfo.warnlevel = aimutil_get16(command->data+i); /* guess */ i += 2; + + /* + * Number of TLVs that follow. Not needed. + */ wastebits = aimutil_get16(command->data+i); i += 2; - + /* * Read block of TLVs. All further data is derived * from what is parsed here. @@ -220,128 +224,220 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess, tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i); /* - * Check Autoresponse status. If it is an autoresponse, - * it will contain a second type 0x0004 TLV, with zero length. - */ - if (aim_gettlv(tlvlist, 0x0004, 2)) - icbmflags |= AIM_IMFLAGS_AWAY; - - /* - * Check Ack Request status. - */ - if (aim_gettlv(tlvlist, 0x0003, 2)) - icbmflags |= AIM_IMFLAGS_ACK; - - /* - * Extract the various pieces of the userinfo struct. + * From here on, its depends on what channel we're on. */ - /* Class. */ - if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1))) - userinfo.class = aimutil_get16(tmptlv->value); - /* Member-since date. */ - if ((tmptlv = aim_gettlv(tlvlist, 0x0002, 1))) + if (channel == 1) { - /* If this is larger than 4, its probably the message block, skip */ - if (tmptlv->length <= 4) - userinfo.membersince = aimutil_get32(tmptlv->value); + u_int j = 0, y = 0, z = 0; + char *msg = NULL; + u_int icbmflags = 0; + struct aim_tlv_t *msgblocktlv, *tmptlv; + u_char *msgblock; + u_short flag1,flag2; + + memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s)); + + /* + * Check Autoresponse status. If it is an autoresponse, + * it will contain a second type 0x0004 TLV, with zero length. + */ + if (aim_gettlv(tlvlist, 0x0004, 2)) + icbmflags |= AIM_IMFLAGS_AWAY; + + /* + * Check Ack Request status. + */ + if (aim_gettlv(tlvlist, 0x0003, 2)) + icbmflags |= AIM_IMFLAGS_ACK; + + /* + * Extract the various pieces of the userinfo struct. + */ + /* Class. */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1))) + userinfo.class = aimutil_get16(tmptlv->value); + /* Member-since date. */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0002, 1))) + { + /* If this is larger than 4, its probably the message block, skip */ + if (tmptlv->length <= 4) + userinfo.membersince = aimutil_get32(tmptlv->value); + } + /* On-since date */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0003, 1))) + userinfo.onlinesince = aimutil_get32(tmptlv->value); + /* Idle-time */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0004, 1))) + userinfo.idletime = aimutil_get16(tmptlv->value); + /* Session Length (AIM) */ + if ((tmptlv = aim_gettlv(tlvlist, 0x000f, 1))) + userinfo.sessionlen = aimutil_get16(tmptlv->value); + /* Session Length (AOL) */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0010, 1))) + userinfo.sessionlen = aimutil_get16(tmptlv->value); + + /* + * Message block. + * + * XXX: Will the msgblock always be the second 0x0002? + */ + msgblocktlv = aim_gettlv(tlvlist, 0x0002, 1); + if (!msgblocktlv) + { + printf("faim: icbm: major error! no message block TLV found!\n"); + aim_freetlvchain(&tlvlist); + } + + /* + * Extracting the message from the unknown cruft. + * + * This is a bit messy, and I'm not really qualified, + * even as the author, to comment on it. At least + * its not as bad as a while loop shooting into infinity. + * + * "Do you believe in magic?" + * + */ + msgblock = msgblocktlv->value; + j = 0; + + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + + y = aimutil_get16(msgblock+j); + j += 2; + for (z = 0; z < y; z++) + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + wastebits = aimutil_get8(msgblock+j++); + + /* + * Message string length, including flag words. + */ + i = aimutil_get16(msgblock+j); + j += 2; + + /* + * Flag words. + * + * Its rumored that these can kick in some funky + * 16bit-wide char stuff that used to really kill + * libfaim. Hopefully the latter is no longer true. + * + * Though someone should investiagte the former. + * + */ + flag1 = aimutil_get16(msgblock+j); + j += 2; + flag2 = aimutil_get16(msgblock+j); + j += 2; + + if (flag1 || flag2) + printf("faim: icbm: **warning: encoding flags are being used! {%04x, %04x}\n", flag1, flag2); + + /* + * Message string. + */ + i -= 4; + msg = (char *)malloc(i+1); + memcpy(msg, msgblock+j, i); + msg[i] = '\0'; + + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); + if (userfunc) + i = userfunc(sess, command, channel, &userinfo, msg, icbmflags, flag1, flag2); + else + i = 0; + + free(msg); } - /* On-since date */ - if ((tmptlv = aim_gettlv(tlvlist, 0x0003, 1))) - userinfo.onlinesince = aimutil_get32(tmptlv->value); - /* Idle-time */ - if ((tmptlv = aim_gettlv(tlvlist, 0x0004, 1))) - userinfo.idletime = aimutil_get16(tmptlv->value); - /* Session Length (AIM) */ - if ((tmptlv = aim_gettlv(tlvlist, 0x000f, 1))) - userinfo.sessionlen = aimutil_get16(tmptlv->value); - /* Session Length (AOL) */ - if ((tmptlv = aim_gettlv(tlvlist, 0x0010, 1))) - userinfo.sessionlen = aimutil_get16(tmptlv->value); - - /* - * Message block. - * - * XXX: Will the msgblock always be the second 0x0002? - */ - msgblocktlv = aim_gettlv(tlvlist, 0x0002, 1); - if (!msgblocktlv) + else if (channel == 0x0002) { - printf("faim: icbm: major error! no message block TLV found!\n"); - aim_freetlvchain(&tlvlist); - } - - /* - * Extracting the message from the unknown cruft. - * - * This is a bit messy, and I'm not really qualified, - * even as the author, to comment on it. At least - * its not as bad as a while loop shooting into infinity. - * - * "Do you believe in magic?" - * - */ - msgblock = msgblocktlv->value; - j = 0; - - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); - - y = aimutil_get16(msgblock+j); - j += 2; - for (z = 0; z < y; z++) - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); - wastebits = aimutil_get8(msgblock+j++); + struct aim_tlv_t *block1; + struct aim_tlvlist_t *list2; + struct aim_tlv_t *tmptlv; + int a; + u_short exchange,instance; + char *roomname,*msg,*encoding,*lang; + + /* Class. */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1))) + userinfo.class = aimutil_get16(tmptlv->value); + /* On-since date */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0003, 1))) + userinfo.onlinesince = aimutil_get32(tmptlv->value); + /* Idle-time */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0004, 1))) + userinfo.idletime = aimutil_get16(tmptlv->value); + /* Session Length (AIM) */ + if ((tmptlv = aim_gettlv(tlvlist, 0x000f, 1))) + userinfo.sessionlen = aimutil_get16(tmptlv->value); + /* Session Length (AOL) */ + if ((tmptlv = aim_gettlv(tlvlist, 0x0010, 1))) + userinfo.sessionlen = aimutil_get16(tmptlv->value); + + /* + * There's another block of TLVs embedded in the type 5 here. + */ + block1 = aim_gettlv(tlvlist, 0x0005, 1); + if (!block1) + return 1; /* major problem */ + + a = 0x1a; /* skip -- not sure what this information is! */ + + list2 = aim_readtlvchain(block1->value+a, block1->length-a); + if (aim_gettlv(list2, 0x2711, 1)) + { + struct aim_tlv_t *name; + int len; + + name = aim_gettlv(list2, 0x2711, 1); + + exchange = aimutil_get16(name->value+0); + + len = aimutil_get16(name->value+2); + roomname = (char *)malloc(len+1); + memcpy(roomname, name->value+3, len); + roomname[len] = '\0'; + + instance = aimutil_get16(name->value+3+len); + } + + if (aim_gettlv(list2, 0x000c, 1)) + msg = aim_gettlv_str(list2, 0x000c, 1); + + if (aim_gettlv(list2, 0x000d, 1)) + encoding = aim_gettlv_str(list2, 0x000d, 1); - /* - * Message string length, including flag words. - */ - i = aimutil_get16(msgblock+j); - j += 2; - - /* - * Flag words. - * - * Its rumored that these can kick in some funky - * 16bit-wide char stuff that used to really kill - * libfaim. Hopefully the latter is no longer true. - * - * Though someone should investiagte the former. - * - */ - flag1 = aimutil_get16(msgblock+j); - j += 2; - flag2 = aimutil_get16(msgblock+j); - j += 2; - - if (flag1 || flag2) - printf("faim: icbm: **warning: encoding flags are being used! {%04x, %04x}\n", flag1, flag2); - - /* - * Message string. - */ - i -= 4; - msg = (char *)malloc(i+1); - memcpy(msg, msgblock+j, i); - msg[i] = '\0'; + if (aim_gettlv(list2, 0x000e, 1)) + lang = aim_gettlv_str(list2, 0x000e, 1); + + /* + * Call client. + */ + userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); + if (userfunc) + i = userfunc(sess, command, channel, &userinfo, roomname, msg, encoding+1, lang+1, exchange, instance); + else + i = 0; + + free(roomname); + free(msg); + free(encoding); + free(lang); + aim_freetlvchain(&list2); + } /* * Free up the TLV chain. */ aim_freetlvchain(&tlvlist); + - /* - * Call client. - */ - userfunc = aim_callhandler(command->conn, 0x0004, 0x0007); - if (userfunc) - i = userfunc(sess, command, &userinfo, msg, icbmflags, flag1, flag2); - else - i = 0; - - free(msg); - - return 1; + return i; } /* diff --git a/aim_misc.c b/aim_misc.c index dae9e9e..b882c80 100644 --- a/aim_misc.c +++ b/aim_misc.c @@ -223,25 +223,44 @@ u_long aim_bos_setbuddylist(struct aim_session_t *sess, * * Gives BOS your profile. * + * + * The large data chunk given here is of unknown decoding. + * What I do know is that each 0x20 byte repetition + * represents a capability. People with only the + * first two reptitions can support normal messaging + * and chat (client version 2.0 or 3.0). People with + * the third as well can also support voice chat (client + * version 3.5 or higher). IOW, if we don't send this, + * we won't get chat invitations (get "software doesn't + * support chat" error). + * + * This data is broadcast along with your oncoming + * buddy command to everyone who has you on their + * buddy list, as a type 0x0002 TLV. + * */ u_long aim_bos_setprofile(struct aim_session_t *sess, struct aim_conn_t *conn, char *profile) { - int packet_profile_len = 0; struct command_tx_struct newpacket; int i = 0; - - /* len: SNAC */ - packet_profile_len = 10; - /* len: T+L (where t(0001)) */ - packet_profile_len += 2 + 2; - /* len: V (where t(0001)) */ - packet_profile_len += strlen("text/x-aolrtf"); - /* len: T+L (where t(0002)) */ - packet_profile_len += 2 + 2; - /* len: V (where t(0002)) */ - packet_profile_len += strlen(profile); + u_char funkydata[] = { + 0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, + 0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, + + 0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, + 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, + + 0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, + 0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 + }; newpacket.type = 0x02; if (conn) @@ -249,32 +268,23 @@ u_long aim_bos_setprofile(struct aim_session_t *sess, else newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); - newpacket.commandlen = packet_profile_len; - newpacket.data = (char *) malloc(packet_profile_len); - - i = 0; + newpacket.commandlen = 1152+strlen(profile)+1; /*arbitrarily large */ + newpacket.data = (char *) malloc(newpacket.commandlen); i += aim_putsnac(newpacket.data, 0x0002, 0x004, 0x0000, sess->snac_nextid); - - /* TLV t(0001) */ - newpacket.data[i++] = 0x00; - newpacket.data[i++] = 0x01; - /* TLV l(000d) */ - newpacket.data[i++] = 0x00; - newpacket.data[i++] = 0x0d; - /* TLV v(text/x-aolrtf) */ - memcpy(&(newpacket.data[i]), "text/x-aolrtf", 0x000d); - i += 0x000d; + i += aim_puttlv_str(newpacket.data+i, 0x0001, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\""); + i += aim_puttlv_str(newpacket.data+i, 0x0002, strlen(profile), profile); + /* why do we send this twice? */ + i += aim_puttlv_str(newpacket.data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\""); - /* TLV t(0002) */ - newpacket.data[i++] = 0x00; - newpacket.data[i++] = 0x02; - /* TLV l() */ - newpacket.data[i++] = (strlen(profile) >> 8) & 0xFF; - newpacket.data[i++] = (strlen(profile) & 0xFF); - /* TLV v(profile) */ - memcpy(&(newpacket.data[i]), profile, strlen(profile)); + /* a blank TLV 0x0004 --- not sure what this is either */ + i += aimutil_put16(newpacket.data+i, 0x0004); + i += aimutil_put16(newpacket.data+i, 0x0000); + /* Capability information. */ + i += aim_puttlv_str(newpacket.data+i, 0x0005, 0x0060, funkydata); + + newpacket.commandlen = i; aim_tx_enqueue(sess, &newpacket); return (sess->snac_nextid++); @@ -481,36 +491,42 @@ u_long aim_setversions(struct aim_session_t *sess, else newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); newpacket.type = 0x02; - newpacket.commandlen = 10 + (4*13); + newpacket.commandlen = 10 + (4*11); newpacket.data = (char *) malloc(newpacket.commandlen); i = aim_putsnac(newpacket.data, 0x0001, 0x0017, 0x0000, sess->snac_nextid); i += aimutil_put16(newpacket.data+i, 0x0001); i += aimutil_put16(newpacket.data+i, 0x0003); + i += aimutil_put16(newpacket.data+i, 0x0002); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0003); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0004); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0006); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0008); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0009); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x000a); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x000b); i += aimutil_put16(newpacket.data+i, 0x0002); + i += aimutil_put16(newpacket.data+i, 0x000c); i += aimutil_put16(newpacket.data+i, 0x0001); + i += aimutil_put16(newpacket.data+i, 0x0015); - i += aimutil_put16(newpacket.data+i, 0x0003); - i += aimutil_put16(newpacket.data+i, 0x000f); - i += aimutil_put16(newpacket.data+i, 0x0001); - i += aimutil_put16(newpacket.data+i, 0x0005); i += aimutil_put16(newpacket.data+i, 0x0001); #if 0 diff --git a/utils/faimtest/faimtest.c b/utils/faimtest/faimtest.c index 00d6311..f54667f 100644 --- a/utils/faimtest/faimtest.c +++ b/utils/faimtest/faimtest.c @@ -44,9 +44,6 @@ */ -#define FAIMTEST_SCREENNAME "SCREENNAME" -#define FAIMTEST_PASSWORD "PASSWORD" - #include int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...); @@ -64,6 +61,8 @@ int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *comm int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...); int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...); +static char *screenname,*password; + int main(void) { struct aim_session_t aimsess; @@ -73,6 +72,13 @@ int main(void) aim_session_init(&aimsess); + if ( !(screenname = getenv("SCREENNAME")) || + !(password = getenv("PASSWORD"))) + { + printf("Must specify SCREENAME and PASSWORD in environment.\n"); + return -1; + } + /* * (I used a goto-based loop here because n wanted quick proof * that reconnecting without restarting was actually possible...) @@ -105,7 +111,7 @@ int main(void) #else aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_parse_authresp, 0); aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0); - aim_send_login(&aimsess, authconn, FAIMTEST_SCREENNAME, FAIMTEST_PASSWORD, &info); + aim_send_login(&aimsess, authconn, screenname, password, &info); #endif } @@ -145,6 +151,7 @@ int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *c switch (command->conn->type) { case AIM_CONN_TYPE_BOS: + aim_bos_reqrate(sess, command->conn); /* request rate info */ aim_bos_ackrateresp(sess, command->conn); /* ack rate info response -- can we say timing? */ aim_bos_setprivacyflags(sess, command->conn, 0x00000003); @@ -428,84 +435,133 @@ int faimtest_parse_userinfo(struct aim_session_t *sess, struct command_rx_struct */ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_struct *command, ...) { - struct aim_userinfo_s *userinfo; - char *msg = NULL; - u_int icbmflags = 0; + int channel; va_list ap; - char *tmpstr = NULL; - u_short flag1, flag2; va_start(ap, command); - userinfo = va_arg(ap, struct aim_userinfo_s *); - msg = va_arg(ap, char *); - icbmflags = va_arg(ap, u_int); - flag1 = va_arg(ap, u_short); - flag2 = va_arg(ap, u_short); - va_end(ap); + channel = va_arg(ap, int); - printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn); - printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel); - printf("faimtest: icbm: class = 0x%04x ", userinfo->class); - if (userinfo->class & 0x0010) - printf("(FREE)\n"); - else if (userinfo->class & 0x0001) - printf("(TRIAL)\n"); - else if (userinfo->class & 0x0004) - printf("(AOL)\n"); - else - printf("(UNKNOWN)\n"); - printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince); - printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince); - printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime); - - printf("faimtest: icbm: icbmflags = "); - if (icbmflags & AIM_IMFLAGS_AWAY) - printf("away "); - if (icbmflags & AIM_IMFLAGS_ACK) - printf("ackrequest "); - printf("\n"); - - printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2); - - printf("faimtest: icbm: message: %s\n", msg); - - if (msg) + /* + * Channel 1: Standard Message + */ + if (channel == 1) { - tmpstr = index(msg, '>'); - if (tmpstr != NULL) - tmpstr+=1; - else - tmpstr = msg; + struct aim_userinfo_s *userinfo; + char *msg = NULL; + u_int icbmflags = 0; + char *tmpstr = NULL; + u_short flag1, flag2; + + userinfo = va_arg(ap, struct aim_userinfo_s *); + msg = va_arg(ap, char *); + icbmflags = va_arg(ap, u_int); + flag1 = va_arg(ap, u_short); + flag2 = va_arg(ap, u_short); + va_end(ap); - if ( (strlen(tmpstr) >= 10) && - (!strncmp(tmpstr, "disconnect", 10)) ) - { - aim_send_im(sess, command->conn, "midendian", 0, "ta ta..."); - aim_logoff(sess); - } - else if (strstr(tmpstr, "goodday")) + printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn); + printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel); + printf("faimtest: icbm: class = 0x%04x ", userinfo->class); + if (userinfo->class & 0x0010) + printf("(FREE) "); + if (userinfo->class & 0x0001) + printf("(TRIAL) "); + if (userinfo->class & 0x0004) + printf("(AOL) "); + printf("\n"); + printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince); + printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince); + printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime); + + printf("faimtest: icbm: icbmflags = "); + if (icbmflags & AIM_IMFLAGS_AWAY) + printf("away "); + if (icbmflags & AIM_IMFLAGS_ACK) + printf("ackrequest "); + printf("\n"); + + printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2); + + printf("faimtest: icbm: message: %s\n", msg); + + if (msg) { - printf("faimtest: icbm: sending response\n"); - aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too."); - } + tmpstr = index(msg, '>'); + if (tmpstr != NULL) + tmpstr+=1; + else + tmpstr = msg; + + if ( (strlen(tmpstr) >= 10) && + (!strncmp(tmpstr, "disconnect", 10)) ) + { + aim_send_im(sess, command->conn, "midendian", 0, "ta ta..."); + aim_logoff(sess); + } + else if (strstr(tmpstr, "goodday")) + { + printf("faimtest: icbm: sending response\n"); + aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too."); + } #if 0 - else if (!strncmp(tmpstr, "joinchat", 8)) - { - aim_chat_join(sess, command->conn, "GoodDay"); - } + else if (!strncmp(tmpstr, "joinchat", 8)) + { + aim_chat_join(sess, command->conn, "GoodDay"); + } #endif - else - { + else + { #if 0 - printf("faimtest: icbm: starting chat...\n"); - aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); + printf("faimtest: icbm: starting chat...\n"); + aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); #else - aim_bos_setidle(sess, command->conn, 0x0ffffffe); + aim_bos_setidle(sess, command->conn, 0x0ffffffe); #endif + } + } - } - + /* + * Channel 2: Chat Invitation + */ + else if (channel == 2) + { + struct aim_userinfo_s *userinfo; + char *roomname,*msg,*encoding,*lang; + u_short exchange, instance; + + userinfo = va_arg(ap, struct aim_userinfo_s *); + roomname = va_arg(ap, char *); + msg = va_arg(ap, char *); + encoding = va_arg(ap, char *); + lang = va_arg(ap, char *); + exchange = va_arg(ap, u_short); + instance = va_arg(ap, u_short); + va_end(ap); + + printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn); + printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel); + printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class); + if (userinfo->class & 0x0010) + printf("(FREE) "); + if (userinfo->class & 0x0001) + printf("(TRIAL) "); + if (userinfo->class & 0x0004) + printf("(AOL) "); + printf("\n"); + /* we dont get membersince on chat invites! */ + printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince); + printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime); + + printf("faimtest: chat invitation: message = %s\n", msg); + printf("faimtest: chat invitation: room name = %s\n", roomname); + printf("faimtest: chat invitation: encoding = %s\n", encoding); + printf("faimtest: chat invitation: language = %s\n", lang); + printf("faimtest: chat invitation: exchange = 0x%04x\n", exchange); + printf("faimtest: chat invitation: instance = 0x%04x\n", instance); + } + else + printf("faimtest does not support channels > 2 (chan = %02x)\n", channel); printf("faimtest: icbm: done with ICBM handling\n"); return 1; -- 2.45.2