X-Git-Url: http://andersk.mit.edu/gitweb/libfaim.git/blobdiff_plain/5b79dc938f4e84b913b53d35aa229e54f041252d..f0a7908e6ac789e81e591519d5554ea84ba8feb9:/aim_info.c diff --git a/aim_info.c b/aim_info.c index 7a70321..88f07fc 100644 --- a/aim_info.c +++ b/aim_info.c @@ -9,9 +9,15 @@ #include +struct aim_priv_inforeq { + char sn[MAXSNLEN]; + unsigned short infotype; +}; + u_long aim_getinfo(struct aim_session_t *sess, struct aim_conn_t *conn, - const char *sn) + const char *sn, + unsigned short infotype) { struct command_tx_struct *newpacket; int i = 0; @@ -19,14 +25,14 @@ u_long aim_getinfo(struct aim_session_t *sess, if (!sess || !conn || !sn) return 0; - if (!(newpacket = aim_tx_new(0x0002, conn, 12+1+strlen(sn)))) + if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 12+1+strlen(sn)))) return -1; newpacket->lock = 1; i = aim_putsnac(newpacket->data, 0x0002, 0x0005, 0x0000, sess->snac_nextid); - i += aimutil_put16(newpacket->data+i, 0x0001); + i += aimutil_put16(newpacket->data+i, infotype); i += aimutil_put8(newpacket->data+i, strlen(sn)); i += aimutil_putstr(newpacket->data+i, sn, strlen(sn)); @@ -41,8 +47,9 @@ u_long aim_getinfo(struct aim_session_t *sess, snac.type = 0x0005; snac.flags = 0x0000; - snac.data = malloc(strlen(sn)+1); - strcpy(snac.data, sn); + snac.data = malloc(sizeof(struct aim_priv_inforeq)); + strcpy(((struct aim_priv_inforeq *)snac.data)->sn, sn); + ((struct aim_priv_inforeq *)snac.data)->infotype = infotype; aim_newsnac(sess, &snac); } @@ -81,6 +88,66 @@ u_char aim_caps[6][16] = { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }; +u_short aim_getcap(unsigned char *capblock, int buflen) +{ + u_short ret = 0; + int y; + int offset = 0; + + while (offset < buflen) { + for(y=0; y < (sizeof(aim_caps)/0x10); y++) { + if (memcmp(&aim_caps[y], capblock+offset, 0x10) == 0) { + switch(y) { + case 0: ret |= AIM_CAPS_BUDDYICON; break; + case 1: ret |= AIM_CAPS_VOICE; break; + case 2: ret |= AIM_CAPS_IMIMAGE; break; + case 3: ret |= AIM_CAPS_CHAT; break; + case 4: ret |= AIM_CAPS_GETFILE; break; + case 5: ret |= AIM_CAPS_SENDFILE; break; + default: ret |= 0xff00; break; + } + } + } + offset += 0x10; + } + return ret; +} + +int aim_putcap(unsigned char *capblock, int buflen, u_short caps) +{ + int offset = 0; + + if (!capblock) + return -1; + + if ((caps & AIM_CAPS_BUDDYICON) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[0], sizeof(aim_caps[0])); + offset += sizeof(aim_caps[1]); + } + if ((caps & AIM_CAPS_VOICE) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[1], sizeof(aim_caps[1])); + offset += sizeof(aim_caps[1]); + } + if ((caps & AIM_CAPS_IMIMAGE) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[2], sizeof(aim_caps[2])); + offset += sizeof(aim_caps[2]); + } + if ((caps & AIM_CAPS_CHAT) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[3], sizeof(aim_caps[3])); + offset += sizeof(aim_caps[3]); + } + if ((caps & AIM_CAPS_GETFILE) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[4], sizeof(aim_caps[4])); + offset += sizeof(aim_caps[4]); + } + if ((caps & AIM_CAPS_SENDFILE) && (offset < buflen)) { + memcpy(capblock+offset, aim_caps[5], sizeof(aim_caps[5])); + offset += sizeof(aim_caps[5]); + } + + return offset; +} + /* * AIM is fairly regular about providing user info. This * is a generic routine to extract it in its standard form. @@ -191,32 +258,15 @@ int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo) * actual decoding. See comment on aim_bos_setprofile() * in aim_misc.c about the capability block, its the same. * - * Ignore. - * */ case 0x000d: { - int z,y; int len; len = aimutil_get16(buf+i+2); if (!len) break; - - for (z = 0; z < len; z+=0x10) { - for(y=0; y < 6; y++) { - if (memcmp(&aim_caps[y], buf+i+4+z, 0x10) == 0) { - switch(y) { - case 0: outinfo->capabilities |= AIM_CAPS_BUDDYICON; break; - case 1: outinfo->capabilities |= AIM_CAPS_VOICE; break; - case 2: outinfo->capabilities |= AIM_CAPS_IMIMAGE; break; - case 3: outinfo->capabilities |= AIM_CAPS_CHAT; break; - case 4: outinfo->capabilities |= AIM_CAPS_GETFILE; break; - case 5: outinfo->capabilities |= AIM_CAPS_SENDFILE; break; - default: outinfo->capabilities |= 0xff00; break; - } - } - } - } + + outinfo->capabilities = aim_getcap(buf+i+4, len); } break; @@ -356,59 +406,78 @@ int aim_parse_userinfo_middle(struct aim_session_t *sess, struct command_rx_struct *command) { struct aim_userinfo_s userinfo; - char *prof_encoding = NULL; - char *prof = NULL; + char *text_encoding = NULL; + char *text = NULL; u_int i = 0; rxcallback_t userfunc=NULL; struct aim_tlvlist_t *tlvlist; + struct aim_snac_t *origsnac = NULL; + u_long snacid; + struct aim_priv_inforeq *inforeq; + + snacid = aimutil_get32(&command->data[6]); + origsnac = aim_remsnac(sess, snacid); - { - u_long snacid = 0x000000000; - struct aim_snac_t *snac = NULL; - - snacid = aimutil_get32(&command->data[6]); - snac = aim_remsnac(sess, snacid); - - if (snac) - { - if (snac->data) - free(snac->data); - else - printf("faim: parse_userinfo_middle: warning: no ->data in cached SNAC\n"); - free(snac); - } - else - printf("faim: parseuserinfo_middle: warning: no SNAC cached with for this response (%08lx)\n", snacid); - + if (!origsnac || !origsnac->data) { + printf("faim: parse_userinfo_middle: major problem: no snac stored!\n"); + return 1; } - - i = 10; - /* - * extractuserinfo will give us the basic metaTLV information - */ - i += aim_extractuserinfo(command->data+i, &userinfo); + inforeq = (struct aim_priv_inforeq *)origsnac->data; + + switch (inforeq->infotype) { + case AIM_GETINFO_GENERALINFO: + case AIM_GETINFO_AWAYMESSAGE: + i = 10; + + /* + * extractuserinfo will give us the basic metaTLV information + */ + i += aim_extractuserinfo(command->data+i, &userinfo); - /* - * However, in this command, there's usually more TLVs following... - */ - tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i); - prof_encoding = aim_gettlv_str(tlvlist, 0x0001, 1); - prof = aim_gettlv_str(tlvlist, 0x0002, 1); + /* + * However, in this command, there's usually more TLVs following... + */ + tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i); + + /* + * Depending on what informational text was requested, different + * TLVs will appear here. + * + * Profile will be 1 and 2, away message will be 3 and 4. + */ + if (aim_gettlv(tlvlist, 0x0001, 1)) { + text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1); + text = aim_gettlv_str(tlvlist, 0x0002, 1); + } else if (aim_gettlv(tlvlist, 0x0003, 1)) { + text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1); + text = aim_gettlv_str(tlvlist, 0x0004, 1); + } - userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO); - if (userfunc) - { + userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO); + if (userfunc) { i = userfunc(sess, command, &userinfo, - prof_encoding, - prof); + text_encoding, + text, + inforeq->infotype); } - free(prof_encoding); - free(prof); - aim_freetlvchain(&tlvlist); + free(text_encoding); + free(text); + aim_freetlvchain(&tlvlist); + break; + default: + printf("faim: parse_userinfo_middle: unknown infotype in request! (0x%04x)\n", inforeq->infotype); + break; + } + + if (origsnac) { + if (origsnac->data) + free(origsnac->data); + free(origsnac); + } return 1; } @@ -452,7 +521,7 @@ int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, s if (!sess || !conn || !info) return 0; - if (!(tx = aim_tx_new(0x0002, conn, 1152))) + if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152))) return -1; tx->lock = 1; @@ -480,7 +549,7 @@ int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, c if (!sess || !conn || !sn) return 0; - if (!(tx = aim_tx_new(0x0002, conn, 10+1+strlen(sn)))) + if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+1+strlen(sn)))) return -1; tx->lock = 1; @@ -499,3 +568,4 @@ int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, c return 0; } +