Mercurial > pidgin.yaz
view libfaim/aim_im.c @ 141:f90b022235fe
[gaim-migrate @ 151]
Updates to the FAQ (there's been a few changes since 0.9.5), and found a
new (and presumably the last, since AOL stopped publishing it) copy of the
protocol.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Wed, 19 Apr 2000 22:36:38 +0000 |
parents | 68b230f8da5f |
children | 6ced2f1c8b24 |
line wrap: on
line source
/* * aim_im.c * * The routines for sending/receiving Instant Messages. * */ #include "aim.h" /* * Send an ICBM (instant message). * * * Possible flags: * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse * AIM_IMFLAGS_ACK -- Requests that the server send an ack * when the message is received (of type 0x0004/0x000c) * * * TODO: Update to new standard form * * */ u_long aim_send_im(struct aim_conn_t *conn, char *destsn, int flags, char *msg) { int curbyte; struct command_tx_struct newpacket; newpacket.lock = 1; /* lock struct */ newpacket.type = 0x02; /* IMs are always family 0x02 */ if (conn) newpacket.conn = conn; else newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); newpacket.commandlen = 20+1+strlen(destsn)+1+1+2+7+2+4+strlen(msg)+2; if (flags & AIM_IMFLAGS_ACK) newpacket.commandlen += 4; if (flags & AIM_IMFLAGS_AWAY) newpacket.commandlen += 4; newpacket.data = (char *) calloc(1, newpacket.commandlen); curbyte = 0; curbyte += aim_putsnac(newpacket.data+curbyte, 0x0004, 0x0006, 0x0000, aim_snac_nextid); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); curbyte += aimutil_put8(newpacket.data+curbyte,strlen(destsn)); curbyte += aimutil_putstr(newpacket.data+curbyte, destsn, strlen(destsn)); if (flags & AIM_IMFLAGS_ACK) { curbyte += aimutil_put16(newpacket.data+curbyte,0x0003); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); } if (flags & AIM_IMFLAGS_AWAY) { curbyte += aimutil_put16(newpacket.data+curbyte,0x0004); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); } curbyte += aimutil_put16(newpacket.data+curbyte,0x0002); curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+0xf); curbyte += aimutil_put16(newpacket.data+curbyte,0x0501); curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); curbyte += aimutil_put8(newpacket.data+curbyte,0x01); curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+4); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); curbyte += aimutil_putstr(newpacket.data+curbyte, msg, strlen(msg)); aim_tx_enqueue(&newpacket); #ifdef USE_SNAC_FOR_IMS { struct aim_snac_t snac; snac.id = aim_snac_nextid; snac.family = 0x0004; snac.type = 0x0006; snac.flags = 0x0000; snac.data = malloc(strlen(destsn)+1); memcpy(snac.data, destsn, strlen(destsn)+1); aim_newsnac(&snac); } aim_cleansnacs(60); /* clean out all SNACs over 60sec old */ #endif return (aim_snac_nextid++); } int aim_parse_incoming_im_middle(struct command_rx_struct *command) { int i = 0; char *srcsn = NULL; char *msg = NULL; unsigned int msglen = 0; int warninglevel = 0; int tlvcnt = 0; int class = 0; ulong membersince = 0; ulong onsince = 0; int idletime = 0; int isautoreply = 0; i = 20; srcsn = malloc(command->data[i] + 1); memcpy(srcsn, &(command->data[i+1]), command->data[i]); srcsn[(int)command->data[i]] = '\0'; i += (int) command->data[i] + 1; /* add SN len */ /* warning level */ warninglevel = (command->data[i] << 8); warninglevel += (command->data[i+1]); i += 2; tlvcnt = ((command->data[i++]) << 8) & 0xFF00; tlvcnt += (command->data[i++]) & 0x00FF; /* a mini TLV parser */ { int curtlv = 0; int tlv1 = 0; while (curtlv < tlvcnt) { if ((command->data[i] == 0x00) && (command->data[i+1] == 0x01) ) { if (tlv1) break; /* t(0001) = class */ if (command->data[i+3] != 0x02) printf("faim: userinfo: **warning: strange v(%x) for t(1)\n", command->data[i+3]); class = ((command->data[i+4]) << 8) & 0xFF00; class += (command->data[i+5]) & 0x00FF; i += (2 + 2 + command->data[i+3]); tlv1++; } else if ((command->data[i] == 0x00) && (command->data[i+1] == 0x02)) { /* t(0002) = member since date */ if (command->data[i+3] != 0x04) printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]); membersince = ((command->data[i+4]) << 24) & 0xFF000000; membersince += ((command->data[i+5]) << 16) & 0x00FF0000; membersince += ((command->data[i+6]) << 8) & 0x0000FF00; membersince += ((command->data[i+7]) ) & 0x000000FF; i += (2 + 2 + command->data[i+3]); } else if ((command->data[i] == 0x00) && (command->data[i+1] == 0x03)) { /* t(0003) = on since date */ if (command->data[i+3] != 0x04) printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]); onsince = ((command->data[i+4]) << 24) & 0xFF000000; onsince += ((command->data[i+5]) << 16) & 0x00FF0000; onsince += ((command->data[i+6]) << 8) & 0x0000FF00; onsince += ((command->data[i+7]) ) & 0x000000FF; i += (2 + 2 + command->data[i+3]); } else if ((command->data[i] == 0x00) && (command->data[i+1] == 0x04) ) { /* t(0004) = idle time */ if (command->data[i+3] != 0x02) printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]); idletime = ((command->data[i+4]) << 8) & 0xFF00; idletime += (command->data[i+5]) & 0x00FF; i += (2 + 2 + command->data[i+3]); } else { printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]); i += (2 + 2 + command->data[i+3]); } curtlv++; } } { /* detect if this is an auto-response or not */ /* auto-responses can be detected by the presence of a *second* TLV with t(0004), but of zero length (and therefore no value portion) */ struct aim_tlv_t *tsttlv = NULL; tsttlv = aim_grabtlv((u_char *) &(command->data[i])); if (tsttlv->type == 0x04) isautoreply = 1; aim_freetlv(&tsttlv); } i += 2; i += 2; /* skip first msglen */ i += 7; /* skip garbage */ i -= 4; /* oh boy is this terrible... this comes from a specific of the spec */ while(1) { if ( ( (command->data[i] == 0x00) && (command->data[i+1] == 0x00) && (command->data[i+2] == 0x00) && (command->data[i+3] == 0x00) ) && (i < command->commandlen) ) /* prevent infinity */ break; else i++; } i -= 2; if ( (command->data[i] == 0x00) && (command->data[i+1] == 0x00) ) i += 2; msglen = ( (( (unsigned int) command->data[i]) & 0xFF ) << 8); msglen += ( (unsigned int) command->data[i+1]) & 0xFF; /* mask off garbage */ i += 2; msglen -= 4; /* skip four 0x00s */ i += 4; msg = malloc(msglen +1); memcpy(msg, &(command->data[i]), msglen); msg[msglen] = '\0'; i = (aim_callbacks[AIM_CB_INCOMING_IM])(command, srcsn, msg, warninglevel, class, membersince, onsince, idletime, isautoreply); free(srcsn); free(msg); return i; }