#define FAIM_INTERNAL
#include <aim.h>
+/*
+ * Takes a msghdr (and a length) and returns a client type
+ * code. Note that this is *only a guess* and has a low likelihood
+ * of actually being accurate.
+ *
+ * Its based on experimental data, with the help of Eric Warmenhoven
+ * who seems to have collected a wide variety of different AIM clients.
+ *
+ *
+ * Heres the current collection:
+ * 0501 0003 0101 0101 01 AOL Mobile Communicator, WinAIM 1.0.414
+ * 0501 0003 0101 0201 01 WinAIM 2.0.847, 2.1.1187, 3.0.1464,
+ * 4.3.2229, 4.4.2286
+ * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here)
+ * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any
+ * TOC client
+ */
+faim_export unsigned short aim_fingerprintclient(unsigned char *msghdr, int len)
+{
+ static const struct {
+ unsigned short clientid;
+ int len;
+ unsigned char data[10];
+ } fingerprints[] = {
+ /* AOL Mobile Communicator, WinAIM 1.0.414 */
+ { AIM_CLIENTTYPE_MC,
+ 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01}},
+
+ /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */
+ { AIM_CLIENTTYPE_WINAIM,
+ 9, {0x05, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01}},
+
+ /* WinAIM 4.1.2010, libfaim */
+ { AIM_CLIENTTYPE_WINAIM41,
+ 10, {0x05, 0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01}},
+
+ /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */
+ { AIM_CLIENTTYPE_AOL_TOC,
+ 7, {0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01}},
+
+ { 0, 0}
+ };
+ int i;
+
+ if (!msghdr || (len <= 0))
+ return 0;
+
+ for (i = 0; fingerprints[i].len; i++) {
+ if (fingerprints[i].len != len)
+ continue;
+ if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0)
+ return fingerprints[i].clientid;
+ }
+
+ return AIM_CLIENTTYPE_UNKNOWN;
+}
+
/*
* Send an ICBM (instant message).
*
/*
* Flag data / ICBM Parameters?
+ *
+ * I don't know what these are...
+ *
*/
curbyte += aimutil_put8(newpacket->data+curbyte, 0x05);
curbyte += aimutil_put8(newpacket->data+curbyte, 0x01);
int channel;
struct aim_tlvlist_t *tlvlist;
struct aim_userinfo_s userinfo;
- u_short wastebits;
memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s));
struct aim_tlv_t *msgblocktlv;
u_char *msgblock;
u_short flag1,flag2;
+ int finlen = 0;
+ unsigned char fingerprint[10];
+ u_short wastebits;
/*
* Check Autoresponse status. If it is an autoresponse,
wastebits = aimutil_get8(msgblock+j++);
wastebits = aimutil_get8(msgblock+j++);
wastebits = aimutil_get8(msgblock+j++);
-
+
+ finlen = j;
+ if (finlen > sizeof(fingerprint))
+ finlen = sizeof(fingerprint);
+ memcpy(fingerprint, msgblocktlv->value, finlen);
+
/*
* Message string length, including flag words.
*/
*/
userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
if (userfunc)
- i = userfunc(sess, command, channel, &userinfo, msg, icbmflags, flag1, flag2);
+ i = userfunc(sess, command, channel, &userinfo, msg, icbmflags, flag1, flag2, finlen, fingerprint);
else
i = 0;
u_int icbmflags = 0;
char *tmpstr = NULL;
unsigned short flag1, flag2;
+ int finlen = 0;
+ unsigned char *fingerprint = NULL;
+ int clienttype = AIM_CLIENTTYPE_UNKNOWN;
userinfo = va_arg(ap, struct aim_userinfo_s *);
msg = va_arg(ap, char *);
icbmflags = va_arg(ap, u_int);
flag1 = va_arg(ap, int);
flag2 = va_arg(ap, int);
+ finlen = va_arg(ap, int);
+ fingerprint = va_arg(ap, unsigned char *);
va_end(ap);
+ clienttype = aim_fingerprintclient(fingerprint, finlen);
+
dvprintf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
+ dvprintf("faimtest: icbm: probable client type: %d\n", clienttype);
dvprintf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
dvprintf("faimtest: icbm: flags = 0x%04x = ", userinfo->flags);
printuserflags(userinfo->flags);