--- a/src/protocols/oscar/info.c Wed Jun 11 22:46:38 2003 +0000 +++ b/src/protocols/oscar/info.c Thu Jun 12 03:27:58 2003 +0000 @@ -443,11 +443,17 @@ return; } +faim_internal void aim_info_free(aim_userinfo_t *info) +{ + free(info->iconcsum); + free(info->availablemsg); +} + /* * AIM is fairly regular about providing user info. This is a generic * routine to extract it in its standard form. */ -faim_internal int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo) +faim_internal int aim_info_extract(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo) { int curtlv, tlvcnt; fu8_t snlen; @@ -636,24 +642,54 @@ /* * Type = 0x001d * - * Buddy icon information. This contains the info - * about the buddy icon that the user has stored on - * the server. + * Buddy icon information and available messages. + * + * This almost seems like the AIM protocol guys gave + * the iChat guys a Type, and the iChat guys tried to + * cram as much cool shit into it as possible. Then + * the Windows AIM guys were like, "hey, that's + * pretty neat, let's copy those prawns." + * + * In that spirit, this can contain a custom message, + * kind of like an away message, but you're not away + * (it's called an "available" message). Or it can + * contain information about the buddy icon the user + * has stored on the server. */ - int flags, number, len; - fu8_t *csum; + int type2, number, length2; while (aim_bstream_curpos(bs) < endpos) { - flags = aimbs_get16(bs); + type2 = aimbs_get16(bs); number = aimbs_get8(bs); - len = aimbs_get8(bs); - if ((flags & 0x0001) && (number == 0x01) && (len < 30)) { - csum = aimbs_getraw(bs, len); - memcpy(outinfo->iconcsum, csum, len); - outinfo->iconcsumlen = len; - free(csum); - } else - aim_bstream_advance(bs, len); + length2 = aimbs_get8(bs); + + switch (type2) { + case 0x0000: { /* This is an official buddy icon? */ + /* This is always 5 bytes? */ + aim_bstream_advance(bs, length2); + } break; + + case 0x0001: { /* A buddy icon checksum */ + if ((length2 > 0) && (number == 0x01)) { + free(outinfo->iconcsum); + outinfo->iconcsum = aimbs_getraw(bs, length2); + outinfo->iconcsumlen = length2; + } else + aim_bstream_advance(bs, length2); + } break; + + case 0x0002: { /* An available message */ + if (length2 > 4) { + free(outinfo->availablemsg); + outinfo->availablemsg = aimbs_getstr(bs, aimbs_get16(bs)); + } else + aim_bstream_advance(bs, length2); + } break; + + default: { + aim_bstream_advance(bs, length2); + } break; + } } } else if (type == 0x001e) { @@ -686,7 +722,7 @@ } /* - * Inverse of aim_extractuserinfo() + * Inverse of aim_info_extract() */ faim_internal int aim_putuserinfo(aim_bstream_t *bs, aim_userinfo_t *info) { @@ -816,7 +852,7 @@ return 0; } - aim_extractuserinfo(sess, bs, &userinfo); + aim_info_extract(sess, bs, &userinfo); tlvlist = aim_readtlvchain(bs); @@ -854,10 +890,9 @@ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo, inforeq->infotype, text_encoding, text, textlen); + aim_info_free(&userinfo); free(text_encoding); - aim_freetlvchain(&tlvlist); - if (origsnac) free(origsnac->data); free(origsnac);