diff -r fd30caf1a296 -r 29004a3d21a0 src/protocols/oscar/icq.c --- a/src/protocols/oscar/icq.c Sat Dec 28 05:15:43 2002 +0000 +++ b/src/protocols/oscar/icq.c Sun Dec 29 17:12:05 2002 +0000 @@ -145,6 +145,43 @@ return 0; } +faim_export int aim_icq_getallinfo(aim_session_t *sess, const char *uin) +{ + aim_conn_t *conn; + aim_frame_t *fr; + aim_snacid_t snacid; + int bslen; + + if (!uin || uin[0] < '0' || uin[0] > '9') + return -EINVAL; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + return -EINVAL; + + bslen = 2 + 4 + 2 + 2 + 2 + 4; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) + return -ENOMEM; + + snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + + /* For simplicity, don't bother using a tlvlist */ + aimbs_put16(&fr->data, 0x0001); + aimbs_put16(&fr->data, bslen); + + aimbs_putle16(&fr->data, bslen - 2); + aimbs_putle32(&fr->data, atoi(sess->sn)); + aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ + aimbs_putle16(&fr->data, snacid); /* eh. */ + aimbs_putle16(&fr->data, 0x04b2); /* shrug. */ + aimbs_putle32(&fr->data, atoi(uin)); + + aim_tx_enqueue(sess, fr); + + return 0; +} + /* * Response to 15/2, contains an ICQ packet. */ @@ -198,40 +235,108 @@ if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE))) ret = userfunc(sess, rx); - } else if (cmd == 0x07da) { + + } else if (cmd == 0x07da) { /* information */ fu16_t subtype; + struct aim_icq_info *info; + aim_rxcallback_t userfunc; subtype = aimbs_getle16(&qbs); + info = (struct aim_icq_info *)malloc(sizeof(struct aim_icq_info)); + memset(info, 0, sizeof(struct aim_icq_info)); + aim_bstream_advance(&qbs, 1); /* 0x0a */ + + switch (subtype) { + case 0x00c8: { /* info summary (useful stuff) */ + info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homecountry = aimbs_getle16(&qbs); + } break; + + case 0x00dc: { /* personal web page */ + aim_bstream_advance(&qbs, 3); + info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + + case 0x00eb: { /* email address(es) */ + aim_bstream_advance(&qbs, 2); /* Number of email addresses? */ + info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + + case 0x00d2: { /* work information */ + info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workcountry = aimbs_getle16(&qbs); + info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, 2); /* Number of webpage addresses? */ + info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + + case 0x00e6: { /* additional personal information */ + info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + + case 0x00f0: { /* personal interests */ + } break; + + case 0x00fa: { /* past background and current organizations */ + } break; + + case 0x010e: { /* unknown */ + } break; + + case 0x019a: { /* simple info */ + aim_bstream_advance(&qbs, 2); + info->uin = aimbs_getle32(&qbs); + info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + } /* End switch statement */ if (subtype == 0x019a) { - fu16_t tlen; - struct aim_icq_simpleinfo info; - aim_rxcallback_t userfunc; - - memset(&info, 0, sizeof(info)); - - aimbs_getle8(&qbs); /* no clue */ - aimbs_getle16(&qbs); /* no clue */ - info.uin = aimbs_getle32(&qbs); - tlen = aimbs_getle16(&qbs); - info.nick = aimbs_getstr(&qbs, tlen); - tlen = aimbs_getle16(&qbs); - info.first = aimbs_getstr(&qbs, tlen); - tlen = aimbs_getle16(&qbs); - info.last = aimbs_getstr(&qbs, tlen); - tlen = aimbs_getle16(&qbs); - info.email = aimbs_getstr(&qbs, tlen); - /* no clue what the rest of it is */ - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_SIMPLEINFO))) - ret = userfunc(sess, rx, &info); - - free(info.nick); - free(info.first); - free(info.last); - free(info.email); + ret = userfunc(sess, rx, info); + } else { + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALLINFO))) + ret = userfunc(sess, rx, info); } + free(info->nick); + free(info->first); + free(info->last); + free(info->email); + free(info->personalwebpage); + free(info->info); + free(info->homecity); + free(info->homestate); + free(info->homeaddr); + free(info->homezip); + free(info->workcity); + free(info->workstate); + free(info->workaddr); + free(info->workzip); + free(info->workcompany); + free(info->workdivision); + free(info->workposition); + free(info->workwebpage); + free(info); } aim_freetlvchain(&tl);