+faim_internal int aim_parse_locateerr(struct aim_session_t *sess,
+ struct command_rx_struct *command)
+{
+ u_long snacid = 0x000000000;
+ struct aim_snac_t *snac = NULL;
+ int ret = 0;
+ rxcallback_t userfunc = NULL;
+ char *dest;
+ unsigned short reason = 0;
+
+ /*
+ * Get SNAC from packet and look it up
+ * the list of unrepliedto/outstanding
+ * SNACs.
+ *
+ */
+ snacid = aimutil_get32(command->data+6);
+ snac = aim_remsnac(sess, snacid);
+
+ if (!snac) {
+ printf("faim: locerr: got an locate-failed error on an unknown SNAC ID! (%08lx)\n", snacid);
+ dest = NULL;
+ } else
+ dest = snac->data;
+
+ reason = aimutil_get16(command->data+10);
+
+ /*
+ * Call client.
+ */
+ userfunc = aim_callhandler(command->conn, 0x0002, 0x0001);
+ if (userfunc)
+ ret = userfunc(sess, command, dest, reason);
+ else
+ ret = 0;
+
+ if (snac) {
+ free(snac->data);
+ free(snac);
+ }
+
+ return ret;
+}
+
+/*
+ * Capability blocks.
+ */
+u_char aim_caps[6][16] = {
+
+ /* Buddy icon */
+ {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Voice */
+ {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* IM image */
+ {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Chat */
+ {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Get file */
+ {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
+
+ /* Send file */
+ {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
+ 0x82, 0x22, 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;
+
+ 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;
+}
+
+faim_internal 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;
+}
+