*
*/
-
+#define FAIM_INTERNAL
#include <faim/aim.h>
struct aim_priv_inforeq {
- char sn[MAXSNLEN];
+ char sn[MAXSNLEN+1];
unsigned short infotype;
};
unsigned short infotype)
{
struct command_tx_struct *newpacket;
+ struct aim_priv_inforeq privdata;
int i = 0;
if (!sess || !conn || !sn)
newpacket->lock = 0;
aim_tx_enqueue(sess, newpacket);
- {
- struct aim_snac_t snac;
-
- snac.id = sess->snac_nextid;
- snac.family = 0x0002;
- snac.type = 0x0005;
- snac.flags = 0x0000;
-
- 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;
+ strncpy(privdata.sn, sn, sizeof(privdata.sn));
+ privdata.infotype = infotype;
+ aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq));
- aim_newsnac(sess, &snac);
- }
-
- return (sess->snac_nextid++);
+ return sess->snac_nextid;
}
faim_internal int aim_parse_locateerr(struct aim_session_t *sess,
/*
* Capability blocks.
*/
-u_char aim_caps[6][16] = {
+u_char aim_caps[8][16] = {
/* Buddy icon */
{0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
/* Send file */
{0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Saves stock portfolios */
+ {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Games */
+ {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
};
faim_internal unsigned short aim_getcap(unsigned char *capblock, int buflen)
u_short ret = 0;
int y;
int offset = 0;
+ int identified;
while (offset < buflen) {
+ identified = 0;
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;
+ case 0: ret |= AIM_CAPS_BUDDYICON; identified++; break;
+ case 1: ret |= AIM_CAPS_VOICE; identified++; break;
+ case 2: ret |= AIM_CAPS_IMIMAGE; identified++; break;
+ case 3: ret |= AIM_CAPS_CHAT; identified++; break;
+ case 4: ret |= AIM_CAPS_GETFILE; identified++; break;
+ case 5: ret |= AIM_CAPS_SENDFILE; identified++; break;
+ case 6: ret |= AIM_CAPS_GAMES; identified++; break;
+ case 7: ret |= AIM_CAPS_SAVESTOCKS; identified++; break;
}
}
}
+ if (!identified) {
+ printf("faim: unknown capability!\n");
+ ret |= 0xff00;
+ }
+
offset += 0x10;
}
return ret;
memcpy(capblock+offset, aim_caps[5], sizeof(aim_caps[5]));
offset += sizeof(aim_caps[5]);
}
+ if ((caps & AIM_CAPS_GAMES) && (offset < buflen)) {
+ memcpy(capblock+offset, aim_caps[6], sizeof(aim_caps[6]));
+ offset += sizeof(aim_caps[6]);
+ }
+ if ((caps & AIM_CAPS_SAVESTOCKS) && (offset < buflen)) {
+ memcpy(capblock+offset, aim_caps[7], sizeof(aim_caps[7]));
+ offset += sizeof(aim_caps[7]);
+ }
return offset;
}
break;
/*
- * Type = 0x0001: Member Class.
+ * Type = 0x0001: User flags
*
* Specified as any of the following bitwise ORed together:
* 0x0001 Trial (user less than 60days)
case 0x0001:
if (tlv1) /* use only the first */
break;
- outinfo->class = aimutil_get16(&buf[i+4]);
+ outinfo->flags = aimutil_get16(&buf[i+4]);
tlv1++;
break;
outinfo->idletime = aimutil_get16(&buf[i+4]);
break;
+ /*
+ * Type = 0x0006: ICQ Online Status
+ *
+ * ICQ's Away/DND/etc "enriched" status
+ * Some decoding of values done by Scott <darkagl@pcnet.com>
+ */
+ case 0x0006:
+ outinfo->icqinfo.status = aimutil_get16(buf+i+2+2+2);
+ break;
+
+
+ /*
+ * Type = 0x000a
+ *
+ * ICQ User IP Address.
+ * Ahh, the joy of ICQ security.
+ */
+ case 0x000a:
+ outinfo->icqinfo.ipaddr = aimutil_get32(&buf[i+4]);
+ break;
+
+ /* Type = 0x000c
+ *
+ * random crap containing the IP address,
+ * apparently a port number, and some Other Stuff.
+ *
+ */
+ case 0x000c:
+ memcpy(outinfo->icqinfo.crap, &buf[i+4], 0x25);
+ break;
+
/*
* Type = 0x000d
*
*/
faim_internal int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info)
{
- int i = 0;
+ int i = 0, numtlv = 0;
struct aim_tlvlist_t *tlvlist = NULL;
if (!buf || !info)
i += aimutil_put16(buf+i, info->warnlevel);
- /* XXX: we only put down five */
- i += aimutil_put16(buf+i, 5);
- aim_addtlvtochain16(&tlvlist, 0x0001, info->class);
+
+ aim_addtlvtochain16(&tlvlist, 0x0001, info->flags);
+ numtlv++;
+
aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince);
+ numtlv++;
+
aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince);
+ numtlv++;
+
aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime);
- /* XXX: should put caps here */
- aim_addtlvtochain32(&tlvlist, (unsigned short)((info->class)&AIM_CLASS_AOL?0x0010:0x000f), info->sessionlen);
-
- i += aim_writetlvchain(buf+i, buflen-i, &tlvlist);
+ numtlv++;
+
+#if ICQ_OSCAR_SUPPORT
+ if(atoi(info->sn) != 0) {
+ aim_addtlvtochain16(&tlvlist, 0x0006, info->icqinfo.status);
+ aim_addtlvtochain32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
+ }
+#endif
+
+ aim_addtlvtochain_caps(&tlvlist, 0x000d, info->capabilities);
+ numtlv++;
+
+ aim_addtlvtochain32(&tlvlist, (unsigned short)((info->flags)&AIM_FLAG_AOL?0x0010:0x000f), info->sessionlen);
+ numtlv++;
+
+ i += aimutil_put16(buf+i, numtlv); /* tlvcount */
+ i += aim_writetlvchain(buf+i, buflen-i, &tlvlist); /* tlvs */
aim_freetlvchain(&tlvlist);
-
+
return i;
}