Mercurial > pidgin.yaz
diff libfaim/aim_im.c @ 2:68b230f8da5f
[gaim-migrate @ 11]
A few more commits :)
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Thu, 23 Mar 2000 03:16:06 +0000 |
parents | |
children | 6ced2f1c8b24 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_im.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,253 @@ +/* + * 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; +}