1434 lines
33 KiB
C
1434 lines
33 KiB
C
|
/** _
|
||
|
** (_)_ __ __ ___ _ __ _ __
|
||
|
** | | ' \/ _/ _ \ ' \| ' \
|
||
|
** |_|_|_|_\__\___/_|_|_|_|_|_|
|
||
|
**
|
||
|
** Copyright (C) 2003-2005, Claudio Leite
|
||
|
** All rights reserved.
|
||
|
**
|
||
|
** Please see the file 'COPYING' for licensing information.
|
||
|
**/
|
||
|
|
||
|
#include "imcomm.h"
|
||
|
|
||
|
/*
|
||
|
* OK, by a little cleaning up, I mean a lot of cleaning up.
|
||
|
*
|
||
|
* I need to split this into several files and comment it. If anyone is brave
|
||
|
* enough to try to figure out this mess, go for it, but you've been warned.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* This file could use a little cleaning up.
|
||
|
*
|
||
|
* A lot of this was hurried in an attempt to get a working client, but I never
|
||
|
* bothered to fix it since it worked.
|
||
|
*/
|
||
|
|
||
|
extern int endianness;
|
||
|
extern int nodes_to_delete;
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_decode(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
uint16_t family, subfamily, flags;
|
||
|
TLVLIST *tlvlist;
|
||
|
|
||
|
if (len <= 4)
|
||
|
return IMCOMM_RET_OK;
|
||
|
|
||
|
family = two_to_16(data);
|
||
|
subfamily = two_to_16(data + 2);
|
||
|
flags = two_to_16(data + 4);
|
||
|
|
||
|
if (((IMCOMM *) handle)->ischild == 1) {
|
||
|
family = two_to_16(data);
|
||
|
subfamily = two_to_16(data + 2);
|
||
|
|
||
|
if (family == 0x0001 && subfamily == 0x0003) {
|
||
|
if (data[12] == 0x00 && data[13] == 0x10) {
|
||
|
snac_finish_buddy_icon(handle);
|
||
|
#ifdef DEBUG
|
||
|
printf("sent buddy icon\n");
|
||
|
#endif
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
} else if (family == 0x0010 && subfamily == 0x0003) {
|
||
|
/* ack from buddy icon upload */
|
||
|
((IMCOMM *) handle)->to_delete = 1;
|
||
|
nodes_to_delete = 1;
|
||
|
#ifdef DEBUG
|
||
|
printf
|
||
|
("Received ACK for buddy icon upload, marking handle for deletion.\n");
|
||
|
#endif
|
||
|
return IMCOMM_RET_OK;
|
||
|
} else {
|
||
|
printf("not really parsing child.\n");
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
#ifdef MD5_LOGIN
|
||
|
if (family == 0x0017) {
|
||
|
bos_md5snac(handle, data, len);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (family == 0x0001) {
|
||
|
char *sn;
|
||
|
uint8_t sn_len;
|
||
|
|
||
|
switch (subfamily) {
|
||
|
/*
|
||
|
* supported families list respond with (01,17)
|
||
|
*/
|
||
|
case 0x0003:
|
||
|
snac_get_srv_families(handle, data + 10, len - 10);
|
||
|
return snac_send_versions(handle);
|
||
|
break;
|
||
|
/*
|
||
|
* we're not really worried about versions right now.
|
||
|
*/
|
||
|
case 0x0005:
|
||
|
snac_new_subconnection(handle, data + 18, len - 18);
|
||
|
return IMCOMM_RET_OK;
|
||
|
break;
|
||
|
case 0x0018:
|
||
|
return snac_request_limits(handle);
|
||
|
break;
|
||
|
case 0x0007:
|
||
|
return snac_ack_limits(handle, data + 10, len - 10);
|
||
|
break;
|
||
|
case 0x000a:
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR]) {
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_RATE_LIMIT_WARN,
|
||
|
data[19]);
|
||
|
}
|
||
|
break;
|
||
|
#if 0
|
||
|
case 0x000b:
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR]) {
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_WARN_PAUSE);
|
||
|
}
|
||
|
return snac_ack_srv_pause(handle, data + 10, len - 10);
|
||
|
break;
|
||
|
case 0x000d:
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR]) {
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_WARN_UNPAUSE);
|
||
|
}
|
||
|
if (((IMCOMM *) handle)->srv_pause)
|
||
|
((IMCOMM *) handle)->srv_pause = 0;
|
||
|
|
||
|
break;
|
||
|
#endif
|
||
|
case 0x000f:
|
||
|
if (flags == 0x8000)
|
||
|
break;
|
||
|
|
||
|
sn_len = data[10];
|
||
|
sn = malloc(sn_len + 1);
|
||
|
memcpy(sn, data + 11, sn_len);
|
||
|
sn[sn_len] = 0;
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_FORMATTED_SN])
|
||
|
((IMCOMM *) handle)->
|
||
|
callbacks[IMCOMM_FORMATTED_SN] (handle, sn);
|
||
|
|
||
|
free(sn);
|
||
|
break;
|
||
|
#if 0
|
||
|
case 0x0012:
|
||
|
handle_srv_migration(handle, data, len);
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
} else if (family == 0x0002) {
|
||
|
switch (subfamily) {
|
||
|
case 0x0003:
|
||
|
((IMCOMM *) handle)->max_profile_len = two_to_16(data + 14);
|
||
|
((IMCOMM *) handle)->max_capabilities = two_to_16(data + 20);
|
||
|
if (snac_set_location_info(handle) == IMCOMM_RET_ERROR)
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
else
|
||
|
return IMCOMM_RET_OK;
|
||
|
case 0x0006:
|
||
|
snac_get_user_info(handle, data + 10, len - 10);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
} else if (family == 0x0003) {
|
||
|
switch (subfamily) {
|
||
|
case 0x0003:
|
||
|
tlvlist = tlv_split(data + 10, len - 10, 3);
|
||
|
{
|
||
|
TLVLIST *trav;
|
||
|
for (trav = tlvlist; trav != NULL; trav = trav->next) {
|
||
|
switch (trav->type) {
|
||
|
case 0x01:
|
||
|
if (trav->len >= 2)
|
||
|
((IMCOMM *) handle)->max_buddylist_size =
|
||
|
two_to_16(trav->value);
|
||
|
break;
|
||
|
case 0x02:
|
||
|
if (trav->len >= 2)
|
||
|
((IMCOMM *) handle)->max_num_watchers =
|
||
|
two_to_16(trav->value);
|
||
|
break;
|
||
|
case 0x03:
|
||
|
if (trav->len >= 2)
|
||
|
((IMCOMM *) handle)->max_online_notifications =
|
||
|
two_to_16(trav->value);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
clear_tlv_list(tlvlist);
|
||
|
return IMCOMM_RET_OK;
|
||
|
case 0x0C:
|
||
|
return snac_get_signoff(handle, data, len);
|
||
|
case 0x0B:
|
||
|
return snac_get_signon(handle, data, len);
|
||
|
}
|
||
|
} else if (family == 0x0004) {
|
||
|
switch (subfamily) {
|
||
|
case 0x0001:
|
||
|
if (data[11] == 0x04) {
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_ERROR_USER_OFFLINE);
|
||
|
}
|
||
|
return IMCOMM_RET_OK;
|
||
|
case 0x0005:
|
||
|
((IMCOMM *) handle)->max_message_size = two_to_16(data + 16);
|
||
|
((IMCOMM *) handle)->max_sender_warning = two_to_16(data + 18);
|
||
|
((IMCOMM *) handle)->max_receiver_warning =
|
||
|
two_to_16(data + 20);
|
||
|
((IMCOMM *) handle)->max_message_interval =
|
||
|
two_to_16(data + 22);
|
||
|
return snac_send_icbm_params(handle, two_to_16(data + 10),
|
||
|
1024);
|
||
|
case 0x0007:
|
||
|
return snac_get_incoming_im(handle, data, len);
|
||
|
}
|
||
|
} else if (family == 0x0009) {
|
||
|
switch (subfamily) {
|
||
|
case 0x0003:
|
||
|
return snac_get_privacy_rights(handle, data, len);
|
||
|
}
|
||
|
} else if (family == 0x0013) {
|
||
|
switch (subfamily) {
|
||
|
case 0x0006:
|
||
|
snac_ssi_get_list(handle, data, len);
|
||
|
return snac_ssi_activate(handle);
|
||
|
}
|
||
|
}
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
snac_addToMulti(void *handle, struct MultiPacket * mpkt, uint16_t family, uint16_t subtype, unsigned char *data, uint16_t len, int updateidle)
|
||
|
{
|
||
|
pkt_t *snac_packet;
|
||
|
|
||
|
snac_packet = pkt_init(len + 10);
|
||
|
pkt_add16(snac_packet, family);
|
||
|
pkt_add16(snac_packet, subtype);
|
||
|
pkt_add16(snac_packet, 0);
|
||
|
pkt_add32(snac_packet, ((IMCOMM *) handle)->snacreq);
|
||
|
pkt_addraw(snac_packet, (uint8_t *) data, len);
|
||
|
((IMCOMM *) handle)->snacreq++;
|
||
|
|
||
|
flap_addToMulti(mpkt, 0x02, snac_packet->data, snac_packet->len,
|
||
|
updateidle);
|
||
|
pkt_free(snac_packet);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_send(void *handle, uint16_t family, uint16_t subtype, unsigned char *data, uint16_t len, int updateidle)
|
||
|
{
|
||
|
pkt_t *snac_packet;
|
||
|
IMCOMM_RET ret;
|
||
|
|
||
|
if (((IMCOMM *) handle)->srv_pause)
|
||
|
return IMCOMM_RET_OK;
|
||
|
|
||
|
snac_packet = pkt_init(len + 10);
|
||
|
pkt_add16(snac_packet, family);
|
||
|
pkt_add16(snac_packet, subtype);
|
||
|
pkt_add16(snac_packet, 0);
|
||
|
pkt_add32(snac_packet, ((IMCOMM *) handle)->snacreq);
|
||
|
pkt_addraw(snac_packet, (uint8_t *) data, len);
|
||
|
((IMCOMM *) handle)->snacreq++;
|
||
|
|
||
|
ret = flap_sendpkt(handle, 0x02, snac_packet, updateidle);
|
||
|
pkt_free(snac_packet);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_sendpkt(void *handle, uint8_t family, uint8_t subtype, pkt_t * pkt, int updateidle)
|
||
|
{
|
||
|
return snac_send(handle, family, subtype, pkt->data,
|
||
|
(uint16_t) pkt->len, updateidle);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_send_versions(void *handle)
|
||
|
{
|
||
|
/*
|
||
|
* I love it when I get really lazy...
|
||
|
*
|
||
|
* This works...
|
||
|
*/
|
||
|
unsigned char packet[] =
|
||
|
{0x00, 0x13, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00,
|
||
|
0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||
|
0x09, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x0C, 0x00,
|
||
|
0x01, 0x00, 0x01, 0x00, 0x04};
|
||
|
|
||
|
return snac_send(handle, 0x01, 0x17, packet, (uint16_t) sizeof(packet),
|
||
|
0);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_request_limits(void *handle)
|
||
|
{
|
||
|
return snac_send(handle, 0x01, 0x06, NULL, 0, 0);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_ack_srv_pause(void *handle, uint8_t * data, size_t len)
|
||
|
{
|
||
|
pkt_t *ackpkt;
|
||
|
struct IMComm_Families *tr;
|
||
|
int count;
|
||
|
|
||
|
for (count = 0, tr = ((IMCOMM *) handle)->families; tr; tr = tr->next)
|
||
|
count++;
|
||
|
|
||
|
ackpkt = pkt_init(count * 2); /* each family is 16 bits */
|
||
|
|
||
|
for (tr = ((IMCOMM *) handle)->families; tr; tr = tr->next) {
|
||
|
pkt_add16(ackpkt, tr->family);
|
||
|
printf("adding family %d (total %d).\n", tr->family, count);
|
||
|
}
|
||
|
|
||
|
((IMCOMM *) handle)->srv_pause = 1;
|
||
|
|
||
|
/* return snac_send(handle, 0x01, 0x0c, data, len, 0); */
|
||
|
snac_sendpkt(handle, 0x01, 0x0c, ackpkt, 0);
|
||
|
|
||
|
pkt_free(ackpkt);
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_get_srv_families(void *handle, uint8_t * data, size_t len)
|
||
|
{
|
||
|
struct IMComm_Families *lastptr;
|
||
|
pkt_t *inpkt = pkt_initP(data, len);
|
||
|
int num_families = 0;
|
||
|
|
||
|
if (pkt_end(inpkt))
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
|
||
|
((IMCOMM *) handle)->families = malloc(sizeof(struct IMComm_Families));
|
||
|
((IMCOMM *) handle)->families->family = pkt_get16(inpkt);
|
||
|
num_families++;
|
||
|
|
||
|
lastptr = ((IMCOMM *) handle)->families;
|
||
|
lastptr->next = NULL;
|
||
|
|
||
|
while (!pkt_end(inpkt)) {
|
||
|
lastptr->next = malloc(sizeof(struct IMComm_Families));
|
||
|
lastptr->next->family = pkt_get16(inpkt);
|
||
|
lastptr->next->next = NULL;
|
||
|
lastptr = lastptr->next;
|
||
|
num_families++;
|
||
|
}
|
||
|
|
||
|
pkt_freeP(inpkt);
|
||
|
|
||
|
((IMCOMM *) handle)->num_families = num_families;
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_ack_limits(void *handle, unsigned char *data, size_t len)
|
||
|
{
|
||
|
pkt_t *pkt;
|
||
|
uint16_t x, y, num_classes, *ids;
|
||
|
|
||
|
num_classes = two_to_16(data);
|
||
|
ids = malloc(num_classes * 2); /* it's a 16 bit type, so we need
|
||
|
* twice the bytes. Thanks to djgpp
|
||
|
* for catching this bug! UNIX/win32
|
||
|
* let it go. */
|
||
|
|
||
|
|
||
|
for (x = 2, y = 0; y < num_classes; y++) {
|
||
|
ids[y] = two_to_16(data + x);
|
||
|
x += 35;
|
||
|
}
|
||
|
|
||
|
pkt = pkt_init(num_classes * 2);
|
||
|
|
||
|
for (y = 0; y < num_classes; y++)
|
||
|
pkt_add16(pkt, ids[y]);
|
||
|
|
||
|
if (snac_sendpkt(handle, 0x01, 0x08, pkt, 0) != IMCOMM_RET_OK) {
|
||
|
pkt_free(pkt);
|
||
|
free(ids);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
pkt_free(pkt);
|
||
|
free(ids);
|
||
|
|
||
|
return snac_multireq(handle);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_multireq(void *handle)
|
||
|
{
|
||
|
struct MultiPacket *mpkt;
|
||
|
|
||
|
mpkt = MultiPktInit();
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x01, 0x0e, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x02, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x04, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x02, 0x02, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x03, 0x02, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x04, 0x04, NULL, 0, 0);
|
||
|
snac_addToMulti(handle, mpkt, 0x09, 0x02, NULL, 0, 0);
|
||
|
|
||
|
flap_sendMulti(handle, mpkt);
|
||
|
|
||
|
MultiPktFree(mpkt);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_get_privacy_rights(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
TLVLIST *tlvlist, *trav;
|
||
|
|
||
|
tlvlist = tlv_split(data + 10, len - 10, 2);
|
||
|
|
||
|
for (trav = tlvlist; trav != NULL; trav = trav->next) {
|
||
|
if (trav->type == 0x0001) {
|
||
|
((IMCOMM *) handle)->max_visible_list_size =
|
||
|
two_to_16(trav->value);
|
||
|
} else if (trav->type == 0x0002) {
|
||
|
((IMCOMM *) handle)->max_invisible_list_size =
|
||
|
two_to_16(trav->value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clear_tlv_list(tlvlist);
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_set_location_info(void *handle)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
char *idstr = "text/aolrtf; charset=\"iso-8859-1\"";
|
||
|
int pktlen = 0;
|
||
|
uint8_t capabilities[] =
|
||
|
{0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44,
|
||
|
0x45, 0x53, 0x54,
|
||
|
0x00, 0x00,
|
||
|
0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44,
|
||
|
0x45, 0x53, 0x54, 0x00, 0x00,
|
||
|
0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22, 0x44,
|
||
|
0x45, 0x53, 0x54, 0x00, 0x00
|
||
|
};
|
||
|
|
||
|
snac_send_cli_update(handle);
|
||
|
|
||
|
if (((IMCOMM *) handle)->profile_str != NULL)
|
||
|
pktlen +=
|
||
|
8 + strlen(idstr) +
|
||
|
strlen((char *) ((IMCOMM *) handle)->profile_str);
|
||
|
if (((IMCOMM *) handle)->away_msg != NULL)
|
||
|
pktlen += strlen((char *) ((IMCOMM *) handle)->away_msg);
|
||
|
|
||
|
packet =
|
||
|
pkt_init(pktlen + 10 + 8 + 4 + strlen(idstr) +
|
||
|
sizeof(capabilities));
|
||
|
|
||
|
pkt_add16(packet, 0x0001);
|
||
|
pkt_add16(packet, (uint16_t) strlen(idstr));
|
||
|
pkt_addraw(packet, (uint8_t *) idstr, strlen(idstr));
|
||
|
|
||
|
if (((IMCOMM *) handle)->profile_str != NULL) {
|
||
|
pkt_add16(packet, 0x0002);
|
||
|
pkt_add16(packet,
|
||
|
(uint16_t) strlen((char *) ((IMCOMM *) handle)->
|
||
|
profile_str));
|
||
|
pkt_addraw(packet, ((IMCOMM *) handle)->profile_str,
|
||
|
strlen((char *) ((IMCOMM *) handle)->profile_str));
|
||
|
}
|
||
|
pkt_add16(packet, 0x0003);
|
||
|
pkt_add16(packet, (uint16_t) strlen(idstr));
|
||
|
pkt_addraw(packet, (uint8_t *) idstr, strlen(idstr));
|
||
|
pkt_add16(packet, 0x0004);
|
||
|
|
||
|
if (((IMCOMM *) handle)->away_msg != NULL) {
|
||
|
pkt_add16(packet,
|
||
|
(uint16_t) strlen((char *) ((IMCOMM *) handle)->
|
||
|
away_msg));
|
||
|
pkt_addraw(packet, ((IMCOMM *) handle)->away_msg,
|
||
|
(uint16_t) strlen((char *) ((IMCOMM *) handle)->
|
||
|
away_msg));
|
||
|
} else {
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
}
|
||
|
|
||
|
pkt_add16(packet, 0x0005);
|
||
|
pkt_add16(packet, (uint16_t) sizeof(capabilities));
|
||
|
pkt_addraw(packet, capabilities, sizeof(capabilities));
|
||
|
pkt_add16(packet, 0x0006);
|
||
|
pkt_add16(packet, 0x0006);
|
||
|
pkt_add16(packet, 0x0004);
|
||
|
pkt_add32(packet, 0x00020002);
|
||
|
|
||
|
snac_sendpkt(handle, 0x02, 0x04, packet, 0);
|
||
|
pkt_free(packet);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_send_icbm_params(void *handle, uint16_t channel, uint16_t max_msg_size)
|
||
|
{
|
||
|
IMCOMM_RET ret;
|
||
|
pkt_t *packet;
|
||
|
|
||
|
packet = pkt_init(16);
|
||
|
pkt_add32(packet, 0x00000000);
|
||
|
pkt_add16(packet, 0x000b);
|
||
|
pkt_add16(packet, 0x1f40);
|
||
|
pkt_add16(packet, ((IMCOMM *) handle)->max_sender_warning);
|
||
|
pkt_add16(packet, ((IMCOMM *) handle)->max_receiver_warning);
|
||
|
pkt_add32(packet, 0x00000000);
|
||
|
|
||
|
ret = snac_sendpkt(handle, 0x04, 0x02, packet, 0);
|
||
|
pkt_free(packet);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_ssi_activate(void *handle)
|
||
|
{
|
||
|
if (!((IMCOMM *) handle)->connected) {
|
||
|
((IMCOMM *) handle)->connected = 1;
|
||
|
return multi_ssiact_cliready(handle);
|
||
|
} else {
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_ssi_get_list(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
uint8_t version, *name;
|
||
|
uint16_t x, count, length, group_id, id, type, tlvlen;
|
||
|
pkt_t *pkt;
|
||
|
|
||
|
pkt = pkt_initP(data + 10, len - 10);
|
||
|
|
||
|
version = pkt_get8(pkt);
|
||
|
count = pkt_get16(pkt);
|
||
|
|
||
|
for (x = 0; x < count; x++) {
|
||
|
length = pkt_get16(pkt);
|
||
|
if (length > 0) {
|
||
|
name = pkt_getstr(pkt, length);
|
||
|
} else {
|
||
|
name = NULL;
|
||
|
}
|
||
|
|
||
|
group_id = pkt_get16(pkt);
|
||
|
id = pkt_get16(pkt);
|
||
|
type = pkt_get16(pkt);
|
||
|
tlvlen = pkt_get16(pkt);
|
||
|
pkt_skip(pkt, tlvlen);
|
||
|
|
||
|
if (type == 0x0000 && name != NULL) {
|
||
|
imcomm_addtobuddylist(handle, (char *) name, id, group_id);
|
||
|
}
|
||
|
free(name);
|
||
|
}
|
||
|
|
||
|
pkt_freeP(pkt);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_send_cli_update(void *handle)
|
||
|
{
|
||
|
IMCOMM_RET ret;
|
||
|
pkt_t *pkt;
|
||
|
|
||
|
/*
|
||
|
* This makes the server send us extended status information
|
||
|
*/
|
||
|
#if 0
|
||
|
pkt = pkt_init(12);
|
||
|
pkt_add16(pkt, 0x001d);
|
||
|
pkt_add16(pkt, 0x0008);
|
||
|
pkt_add32(pkt, 0x00020404);
|
||
|
pkt_add32(pkt, 0x00000000);
|
||
|
#endif
|
||
|
|
||
|
pkt = pkt_init(8);
|
||
|
pkt_add16(pkt, 0x0006);
|
||
|
pkt_add16(pkt, 0x0004);
|
||
|
if (((IMCOMM *) handle)->isinvisible)
|
||
|
pkt_add32(pkt, 0x00000100);
|
||
|
else
|
||
|
pkt_add32(pkt, 0x00000000);
|
||
|
|
||
|
ret = snac_sendpkt(handle, 0x01, 0x1e, pkt, 0);
|
||
|
pkt_free(pkt);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
multi_ssiact_cliready(void *handle)
|
||
|
{
|
||
|
struct MultiPacket *multipkt;
|
||
|
pkt_t *cliupdpkt;
|
||
|
unsigned char cli_ready_packet[] = {0x00,
|
||
|
0x13, 0x00, 0x03, 0x01, 0x10, 0x08, 0xE5, 0x00, 0x0b, 0x00, 0x01,
|
||
|
0x01, 0x10, 0x08, 0xe5, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x10,
|
||
|
0x08, 0xe5, 0x00, 0x09, 0x00, 0x01, 0x01, 0x10, 0x08, 0xe5,
|
||
|
0x00, 0x08, 0x00, 0x01, 0x01, 0x04, 0x00, 0x01, 0x00, 0x06,
|
||
|
0x00, 0x01, 0x01, 0x10, 0x08, 0xe5, 0x00, 0x04, 0x00, 0x01,
|
||
|
0x01, 0x10, 0x08, 0xe5, 0x00, 0x03, 0x00, 0x01, 0x01, 0x10,
|
||
|
0x08, 0xe5, 0x00, 0x02, 0x00, 0x01, 0x01, 0x10, 0x08, 0xe5,
|
||
|
0x00, 0x01, 0x00, 0x04, 0x01, 0x10, 0x08, 0xe5
|
||
|
};
|
||
|
|
||
|
multipkt = MultiPktInit();
|
||
|
|
||
|
cliupdpkt = pkt_init(12);
|
||
|
pkt_add16(cliupdpkt, 0x001d);
|
||
|
pkt_add16(cliupdpkt, 0x0008);
|
||
|
pkt_add32(cliupdpkt, 0x00020404);
|
||
|
pkt_add32(cliupdpkt, 0x00000000);
|
||
|
|
||
|
snac_addToMulti(handle, multipkt, 0x01, 0x1e, cliupdpkt->data,
|
||
|
cliupdpkt->len, 0);
|
||
|
snac_addToMulti(handle, multipkt, 0x01, 0x02, cli_ready_packet,
|
||
|
sizeof(cli_ready_packet), 0);
|
||
|
snac_addToMulti(handle, multipkt, 0x13, 0x07, NULL, 0, 0);
|
||
|
|
||
|
flap_sendMulti(handle, multipkt);
|
||
|
MultiPktFree(multipkt);
|
||
|
pkt_free(cliupdpkt);
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_STATUS_CONNECTED);
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_send_cli_ready(void *handle)
|
||
|
{
|
||
|
unsigned char packet[] =
|
||
|
{0x00, 0x01, 0x00, 0x04, 0x01, 0x10, 0x08, 0xf1, 0x00, 0x13, 0x00,
|
||
|
0x03,
|
||
|
0x01, 0x10, 0x08, 0xf1,
|
||
|
0x00, 0x02, 0x00, 0x01, 0x01, 0x10, 0x08, 0xf1, 0x00, 0x03, 0x00,
|
||
|
0x01,
|
||
|
0x01, 0x10, 0x08, 0xf1,
|
||
|
0x00, 0x08, 0x00, 0x01, 0x01, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00,
|
||
|
0x01,
|
||
|
0x01, 0x10, 0x08, 0xf1,
|
||
|
0x00, 0x06, 0x00, 0x01, 0x01, 0x10, 0x08, 0xf1, 0x00, 0x09, 0x00,
|
||
|
0x01,
|
||
|
0x01, 0x10, 0x08, 0xf1,
|
||
|
0x00, 0x0A, 0x00, 0x01, 0x01, 0x10, 0x08, 0xf1, 0x00, 0x0B, 0x00,
|
||
|
0x01,
|
||
|
0x01, 0x10, 0x08, 0xf1
|
||
|
};
|
||
|
snac_send(handle, 0x01, 0x02, packet, sizeof(packet), 0);
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_STATUS_CONNECTED);
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
size_t
|
||
|
count_tlv(unsigned char *data, size_t len)
|
||
|
{
|
||
|
pkt_t *tp;
|
||
|
size_t num;
|
||
|
|
||
|
tp = pkt_initP(data, len);
|
||
|
|
||
|
num = count_tlv_pkt(tp);
|
||
|
pkt_freeP(tp);
|
||
|
|
||
|
return num;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
size_t
|
||
|
count_tlv_pkt(pkt_t * tp)
|
||
|
{
|
||
|
size_t num = 0;
|
||
|
|
||
|
while (tp->offset < tp->len) {
|
||
|
pkt_get16(tp);
|
||
|
pkt_skip(tp, pkt_get16(tp));
|
||
|
num++;
|
||
|
}
|
||
|
|
||
|
return num;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
TLVLIST *
|
||
|
tlv_split(unsigned char *data, size_t len, size_t numtlv)
|
||
|
{
|
||
|
TLVLIST *newtlv = 0, *tlvlist = 0, *firsttlv = 0;
|
||
|
uint16_t x = 0, counter = 0;
|
||
|
int firstTime = 1;
|
||
|
|
||
|
while (x < len) {
|
||
|
newtlv = malloc(sizeof(TLVLIST));
|
||
|
newtlv->type = two_to_16(data + x);
|
||
|
newtlv->len = two_to_16(data + x + 2);
|
||
|
|
||
|
x += 4;
|
||
|
if (newtlv->len != 0) {
|
||
|
newtlv->value = malloc(newtlv->len);
|
||
|
memcpy(newtlv->value, data + x, newtlv->len);
|
||
|
}
|
||
|
newtlv->next = NULL;
|
||
|
if (firstTime) {
|
||
|
tlvlist = newtlv;
|
||
|
firsttlv = newtlv;
|
||
|
firstTime = 0;
|
||
|
} else {
|
||
|
tlvlist->next = newtlv;
|
||
|
tlvlist = tlvlist->next;
|
||
|
}
|
||
|
|
||
|
if (newtlv->len != 0) {
|
||
|
x += newtlv->len;
|
||
|
counter++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
for (tlvlist = firsttlv; tlvlist != NULL; tlvlist = tlvlist->next)
|
||
|
printf("TLV type: %04X length: %04X\n", tlvlist->type,
|
||
|
tlvlist->len);
|
||
|
#endif
|
||
|
|
||
|
return firsttlv;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
clear_tlv_list(TLVLIST * tlvlist)
|
||
|
{
|
||
|
TLVLIST *temp, *trav = tlvlist;
|
||
|
|
||
|
while (trav != NULL) {
|
||
|
temp = trav;
|
||
|
trav = trav->next;
|
||
|
if (temp->len > 0)
|
||
|
free(temp->value);
|
||
|
free(temp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
uint32_t
|
||
|
four_to_32(unsigned char *value)
|
||
|
{
|
||
|
uint32_t temp;
|
||
|
|
||
|
memcpy(&temp, value, 4);
|
||
|
|
||
|
if (endianness == HOST_LITTLE_ENDIAN)
|
||
|
temp = BYTE_SWAP_32(temp);
|
||
|
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
uint16_t
|
||
|
two_to_16(unsigned char *value)
|
||
|
{
|
||
|
uint16_t temp;
|
||
|
|
||
|
memcpy(&temp, value, 2);
|
||
|
|
||
|
if (endianness == HOST_LITTLE_ENDIAN)
|
||
|
temp = BYTE_SWAP_16(temp);
|
||
|
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_get_incoming_im(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
char *sn;
|
||
|
uint8_t sn_len = data[20];
|
||
|
char *msg;
|
||
|
TLVLIST *tlvlist, *trav, *trav2, *subtlv;
|
||
|
int auto_resp = 0;
|
||
|
int numtlv;
|
||
|
|
||
|
|
||
|
numtlv = two_to_16(data + sn_len + 23);
|
||
|
sn = malloc(sn_len + 1);
|
||
|
memcpy(sn, data + 21, sn_len);
|
||
|
sn[sn_len] = 0;
|
||
|
|
||
|
tlvlist = tlv_split(data + 25 + sn_len, len - 25 - sn_len, numtlv + 1);
|
||
|
for (trav = tlvlist; trav != NULL; trav = trav->next) {
|
||
|
if (trav->type == 0x0004 && trav->len == 0)
|
||
|
auto_resp = 1;
|
||
|
|
||
|
if (trav->type == 0x0003) {
|
||
|
imcomm_update_buddy_times(handle, sn, 2,
|
||
|
four_to_32(trav->value));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!auto_resp)
|
||
|
imcomm_update_buddy_times(handle, sn, 1, 0);
|
||
|
|
||
|
for (trav = tlvlist; trav != NULL; trav = trav->next)
|
||
|
if (trav->type == 0x0002)
|
||
|
break;
|
||
|
|
||
|
if (trav == NULL) {
|
||
|
clear_tlv_list(tlvlist);
|
||
|
free(sn);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
subtlv = tlv_split(trav->value, trav->len, 2);
|
||
|
for (trav2 = subtlv; trav2 != NULL; trav2 = trav2->next)
|
||
|
if (trav2->type == 0x0101)
|
||
|
break;
|
||
|
|
||
|
if (trav2 == NULL) {
|
||
|
clear_tlv_list(subtlv);
|
||
|
clear_tlv_list(tlvlist);
|
||
|
free(sn);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
msg = malloc(trav2->len - 3);
|
||
|
memcpy(msg, trav2->value + 4, trav2->len - 4);
|
||
|
msg[trav2->len - 4] = 0;
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_INCOMING])
|
||
|
(((IMCOMM *) handle)->callbacks[IMCOMM_IM_INCOMING]) (handle, sn,
|
||
|
auto_resp,
|
||
|
msg);
|
||
|
|
||
|
free(msg);
|
||
|
clear_tlv_list(subtlv);
|
||
|
clear_tlv_list(tlvlist);
|
||
|
free(sn);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_get_signoff(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
char *sn;
|
||
|
int sn_len = (int) data[10];
|
||
|
|
||
|
sn = malloc(sn_len + 1);
|
||
|
memcpy(sn, data + 11, sn_len);
|
||
|
sn[sn_len] = 0;
|
||
|
imcomm_internal_delete_buddy(handle, sn);
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_SIGNOFF])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_IM_SIGNOFF] (handle, sn);
|
||
|
|
||
|
free(sn);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
snac_get_signon(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
char *sn;
|
||
|
int sn_len = (int) data[10];
|
||
|
int numtlv = two_to_16(data + 13 + sn_len);
|
||
|
unsigned long idletime = 0;
|
||
|
unsigned long onlinetime = 0;
|
||
|
int isaway = 0;
|
||
|
TLVLIST *temp, *tlvlist;
|
||
|
|
||
|
sn = malloc(sn_len + 1);
|
||
|
memcpy(sn, data + 11, sn_len);
|
||
|
sn[sn_len] = 0;
|
||
|
tlvlist =
|
||
|
tlv_split(data + 11 + sn_len + 4, len - 11 - sn_len - 4, numtlv);
|
||
|
|
||
|
for (temp = tlvlist; temp != NULL; temp = temp->next) {
|
||
|
if (temp->type == 0x0004) {
|
||
|
idletime = two_to_16(temp->value);
|
||
|
}
|
||
|
if (temp->type == 0x0001) {
|
||
|
if (temp->value[1] == 0x30 || temp->value[1] == 0x31
|
||
|
|| temp->value[1] == 0x24)
|
||
|
isaway = 1;
|
||
|
}
|
||
|
if (temp->type == 0x0003) {
|
||
|
onlinetime = four_to_32(temp->value);
|
||
|
imcomm_update_buddy_times(handle, sn, 2, onlinetime);
|
||
|
}
|
||
|
}
|
||
|
if (imcomm_internal_add_buddy(handle, sn, idletime, onlinetime, isaway)
|
||
|
== 0) {
|
||
|
imcomm_update_buddy_times(handle, sn, 1, idletime);
|
||
|
imcomm_update_buddy_away(handle, sn, isaway);
|
||
|
} else {
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_SIGNON])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_IM_SIGNON] (handle, sn);
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_IDLEINFO])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_IM_IDLEINFO] (handle, sn,
|
||
|
idletime);
|
||
|
if (isaway)
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_BUDDYAWAY])
|
||
|
((IMCOMM *) handle)->
|
||
|
callbacks[IMCOMM_IM_BUDDYAWAY] (handle, sn);
|
||
|
}
|
||
|
clear_tlv_list(tlvlist);
|
||
|
|
||
|
free(sn);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
snac_get_user_info(void *handle, uint8_t * data, uint16_t len)
|
||
|
{
|
||
|
int sn_len = (int) data[0];
|
||
|
char *sn;
|
||
|
char *profilestr = NULL;
|
||
|
char *awaymsg = NULL;
|
||
|
TLVLIST *tlvlist, *trav;
|
||
|
|
||
|
sn = malloc(sn_len + 1);
|
||
|
memcpy(sn, data + 1, sn_len);
|
||
|
sn[sn_len] = 0;
|
||
|
|
||
|
tlvlist =
|
||
|
tlv_split(data + 5 + sn_len, len - 5 - sn_len,
|
||
|
data[sn_len + 4] + 2);
|
||
|
|
||
|
if (tlvlist == NULL) {
|
||
|
free(sn);
|
||
|
return;
|
||
|
}
|
||
|
if (tlvlist->next == NULL) {
|
||
|
free(sn);
|
||
|
clear_tlv_list(tlvlist);
|
||
|
return;
|
||
|
}
|
||
|
for (trav = tlvlist->next->next; trav != NULL; trav = trav->next) {
|
||
|
switch (trav->type) {
|
||
|
case 0x02:
|
||
|
profilestr = malloc(trav->len + 1);
|
||
|
strncpy(profilestr, (char *) trav->value, trav->len);
|
||
|
profilestr[trav->len] = 0;
|
||
|
break;
|
||
|
case 0x04:
|
||
|
if (trav->len == 2) /* idle time? */
|
||
|
break;
|
||
|
|
||
|
awaymsg = malloc(trav->len + 1);
|
||
|
strncpy(awaymsg, (char *) trav->value, trav->len);
|
||
|
awaymsg[trav->len] = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (profilestr != NULL) {
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_PROFILE]) {
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_IM_PROFILE] (handle, sn,
|
||
|
profilestr);
|
||
|
free(profilestr);
|
||
|
}
|
||
|
} else if (awaymsg != NULL) {
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_IM_AWAYMSG]) {
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_IM_AWAYMSG] (handle, sn,
|
||
|
awaymsg);
|
||
|
free(awaymsg);
|
||
|
}
|
||
|
}
|
||
|
free(sn);
|
||
|
clear_tlv_list(tlvlist);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_im_send_message(void *handle, const char *whom, const char *msg, int automsg)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
|
||
|
packet = pkt_init(28 + strlen(whom) + strlen(msg) + (4 * automsg));
|
||
|
|
||
|
/*
|
||
|
* Message cookie?
|
||
|
*
|
||
|
* Putting something random seems to work.
|
||
|
*/
|
||
|
pkt_add32(packet, 0x01020304);
|
||
|
pkt_add32(packet, 0x05060708);
|
||
|
|
||
|
pkt_add16(packet, 0x0001);
|
||
|
pkt_add8(packet, (uint8_t) strlen(whom));
|
||
|
pkt_addraw(packet, (uint8_t *) whom, strlen(whom));
|
||
|
pkt_add16(packet, 0x0002);
|
||
|
pkt_add16(packet, (uint16_t) (uint16_t) (strlen(msg) + 13));
|
||
|
pkt_add32(packet, 0x05010001);
|
||
|
pkt_add8(packet, 0x01);
|
||
|
pkt_add16(packet, 0x0101);
|
||
|
pkt_add16(packet, (uint16_t) (uint16_t) (strlen(msg) + 4));
|
||
|
pkt_add32(packet, 0x00000000);
|
||
|
pkt_addraw(packet, (uint8_t *) msg, strlen(msg));
|
||
|
|
||
|
if (automsg) {
|
||
|
pkt_add16(packet, 0x0004);
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
}
|
||
|
snac_sendpkt(handle, 0x04, 0x06, packet, (automsg ? 0 : 1));
|
||
|
pkt_free(packet);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_request_awayprofile(void *handle, char *sn)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
struct MultiPacket *mpkt;
|
||
|
|
||
|
mpkt = MultiPktInit();
|
||
|
|
||
|
packet = pkt_init(3 + (uint8_t) strlen(sn));
|
||
|
|
||
|
pkt_add16(packet, 0x0003);
|
||
|
pkt_add8(packet, (uint8_t) strlen(sn));
|
||
|
pkt_addraw(packet, (uint8_t *) sn, strlen(sn));
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x02, 0x05, packet->data, packet->len,
|
||
|
0);
|
||
|
|
||
|
pkt_free(packet);
|
||
|
|
||
|
packet = pkt_init(3 + (uint8_t) strlen(sn));
|
||
|
|
||
|
pkt_add16(packet, 0x0001);
|
||
|
pkt_add8(packet, (uint8_t) strlen(sn));
|
||
|
pkt_addraw(packet, (uint8_t *) sn, strlen(sn));
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x02, 0x05, packet->data, packet->len,
|
||
|
0);
|
||
|
pkt_free(packet);
|
||
|
|
||
|
flap_sendMulti(handle, mpkt);
|
||
|
MultiPktFree(mpkt);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_request_profile(void *handle, char *sn)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
|
||
|
packet = pkt_init(3 + (uint8_t) strlen(sn));
|
||
|
|
||
|
pkt_add16(packet, 0x0001);
|
||
|
pkt_add8(packet, (uint8_t) strlen(sn));
|
||
|
pkt_addraw(packet, (uint8_t *) sn, strlen(sn));
|
||
|
|
||
|
snac_sendpkt(handle, 0x02, 0x05, packet, 0);
|
||
|
pkt_free(packet);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_request_awaymsg(void *handle, char *sn)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
|
||
|
packet = pkt_init(3 + (uint8_t) strlen(sn));
|
||
|
|
||
|
pkt_add16(packet, 0x0003);
|
||
|
pkt_add8(packet, (uint8_t) strlen(sn));
|
||
|
pkt_addraw(packet, (uint8_t *) sn, strlen(sn));
|
||
|
|
||
|
snac_sendpkt(handle, 0x02, 0x05, packet, 0);
|
||
|
pkt_free(packet);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_request_massawaymsg(void *handle, char **sns, int num)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
int x;
|
||
|
struct MultiPacket *multipkt;
|
||
|
|
||
|
multipkt = MultiPktInit();
|
||
|
|
||
|
for (x = 0; x < num; x++) {
|
||
|
packet = pkt_init(3 + (uint8_t) strlen(sns[x]));
|
||
|
|
||
|
pkt_add16(packet, 0x0003);
|
||
|
pkt_add8(packet, (uint8_t) strlen(sns[x]));
|
||
|
pkt_addraw(packet, (uint8_t *) sns[x], strlen(sns[x]));
|
||
|
|
||
|
snac_addToMulti(handle, multipkt, 0x02, 0x05, packet->data,
|
||
|
(uint16_t) packet->len, 0);
|
||
|
pkt_free(packet);
|
||
|
}
|
||
|
|
||
|
flap_sendMulti(handle, multipkt);
|
||
|
MultiPktFree(multipkt);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_addtobuddylist(void *handle, char *sn, uint16_t id, uint16_t group_id)
|
||
|
{
|
||
|
IMCOMM_BUDDYLIST *temp, *trav;
|
||
|
char *sname;
|
||
|
|
||
|
sname = imcomm_simplify_sn(sn);
|
||
|
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav != NULL;
|
||
|
trav = trav->next) {
|
||
|
if (strcmp(sname, trav->sn) == 0) {
|
||
|
free(sname);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
temp = malloc(sizeof(IMCOMM_BUDDYLIST));
|
||
|
temp->sn = sname;
|
||
|
temp->formattedsn = strdup(sn);
|
||
|
temp->ssi_id = id;
|
||
|
temp->group_id = group_id;
|
||
|
temp->next = NULL;
|
||
|
|
||
|
if (((IMCOMM *) handle)->buddylist == NULL)
|
||
|
((IMCOMM *) handle)->buddylist = temp;
|
||
|
else {
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav->next != NULL;
|
||
|
trav = trav->next);
|
||
|
|
||
|
trav->next = temp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
uint16_t
|
||
|
imcomm_get_next_id(void *handle)
|
||
|
{
|
||
|
IMCOMM_BUDDYLIST *trav;
|
||
|
uint16_t firstid = 0x0001;
|
||
|
uint8_t found;
|
||
|
|
||
|
/* this is supremely gross */
|
||
|
|
||
|
while (1) {
|
||
|
found = 0;
|
||
|
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav != NULL;
|
||
|
trav = trav->next) {
|
||
|
if (trav->ssi_id == firstid) {
|
||
|
found = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (found == 1) {
|
||
|
firstid++;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return firstid;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_im_add_buddy(void *handle, char *sn)
|
||
|
{
|
||
|
IMCOMM_BUDDYLIST *temp, *trav;
|
||
|
struct MultiPacket *mpkt;
|
||
|
pkt_t *packet;
|
||
|
char *sname;
|
||
|
uint16_t nextid;
|
||
|
|
||
|
sname = imcomm_simplify_sn(sn);
|
||
|
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav != NULL;
|
||
|
trav = trav->next) {
|
||
|
if (strcmp(sname, trav->sn) == 0) {
|
||
|
free(sname);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nextid = imcomm_get_next_id(handle);
|
||
|
|
||
|
temp = malloc(sizeof(IMCOMM_BUDDYLIST));
|
||
|
temp->sn = sname;
|
||
|
temp->formattedsn = strdup(sname);
|
||
|
temp->ssi_id = nextid;
|
||
|
temp->next = NULL;
|
||
|
|
||
|
if (((IMCOMM *) handle)->buddylist == NULL)
|
||
|
((IMCOMM *) handle)->buddylist = temp;
|
||
|
else {
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav->next != NULL;
|
||
|
trav = trav->next);
|
||
|
|
||
|
trav->next = temp;
|
||
|
}
|
||
|
|
||
|
mpkt = MultiPktInit();
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x11, NULL, 0, 0);
|
||
|
packet = pkt_init(10 + strlen(sname));
|
||
|
pkt_add16(packet, (uint16_t) strlen(sname));
|
||
|
pkt_addraw(packet, (unsigned char *) sname, strlen(sname));
|
||
|
pkt_add16(packet, 0x0001);
|
||
|
pkt_add16(packet, nextid);
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x08, packet->data, packet->len,
|
||
|
0);
|
||
|
pkt_free(packet);
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x012, NULL, 0, 0);
|
||
|
|
||
|
flap_sendMulti(handle, mpkt);
|
||
|
MultiPktFree(mpkt);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_im_remove_buddy(void *handle, const char *sn)
|
||
|
{
|
||
|
char *sname, *snsend = NULL;
|
||
|
pkt_t *packet;
|
||
|
IMCOMM_BUDDYLIST *temp, *trav;
|
||
|
struct MultiPacket *mpkt;
|
||
|
uint16_t buddy_id = 0x00, buddy_group_id = 0x00;
|
||
|
|
||
|
sname = imcomm_simplify_sn(sn);
|
||
|
|
||
|
if (((IMCOMM *) handle)->buddylist != NULL) {
|
||
|
if (strcmp(((IMCOMM *) handle)->buddylist->sn, sname) == 0) {
|
||
|
temp = ((IMCOMM *) handle)->buddylist;
|
||
|
((IMCOMM *) handle)->buddylist =
|
||
|
((IMCOMM *) handle)->buddylist->next;
|
||
|
|
||
|
buddy_id = temp->ssi_id;
|
||
|
buddy_group_id = temp->group_id;
|
||
|
snsend = temp->formattedsn;
|
||
|
free(temp->sn);
|
||
|
free(temp);
|
||
|
} else {
|
||
|
for (trav = ((IMCOMM *) handle)->buddylist; trav->next != NULL;
|
||
|
trav = trav->next) {
|
||
|
if (strcmp(trav->next->sn, sname) == 0) {
|
||
|
temp = trav->next;
|
||
|
trav->next = trav->next->next;
|
||
|
|
||
|
buddy_id = temp->ssi_id;
|
||
|
buddy_group_id = temp->group_id;
|
||
|
snsend = temp->formattedsn;
|
||
|
free(temp->sn);
|
||
|
free(temp);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
imcomm_internal_delete_buddy(handle, sn);
|
||
|
|
||
|
if (snsend == NULL) {
|
||
|
free(sname);
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
* packet = malloc(strlen(sname) + 1); packet[0] = strlen(sname);
|
||
|
* memcpy(packet + 1, sname, strlen(sname));
|
||
|
*
|
||
|
* snac_send(handle, 0x03, 0x05, packet, (uint16_t) (strlen(sname) + 1),
|
||
|
* 0); free(packet);
|
||
|
*/
|
||
|
|
||
|
mpkt = MultiPktInit();
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x11, NULL, 0, 0);
|
||
|
packet = pkt_init(10 + strlen(snsend));
|
||
|
pkt_add16(packet, (uint16_t) strlen(snsend));
|
||
|
pkt_addraw(packet, (unsigned char *) snsend, strlen(snsend));
|
||
|
pkt_add16(packet, buddy_group_id);
|
||
|
pkt_add16(packet, buddy_id);
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
pkt_add16(packet, 0x0000);
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x0a, packet->data, packet->len,
|
||
|
0);
|
||
|
pkt_free(packet);
|
||
|
|
||
|
snac_addToMulti(handle, mpkt, 0x13, 0x012, NULL, 0, 0);
|
||
|
|
||
|
flap_sendMulti(handle, mpkt);
|
||
|
MultiPktFree(mpkt);
|
||
|
free(sname);
|
||
|
free(snsend);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
snac_request_new_service(void *handle, uint16_t service)
|
||
|
{
|
||
|
pkt_t *pkt;
|
||
|
|
||
|
pkt = pkt_init(2);
|
||
|
pkt_add16(pkt, service);
|
||
|
snac_sendpkt(handle, 0x01, 0x04, pkt, 0);
|
||
|
pkt_free(pkt);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
snac_new_subconnection(void *handle, unsigned char *data, uint16_t len)
|
||
|
{
|
||
|
TLVLIST *tv, *trav;
|
||
|
uint16_t subtype = 0, cookie_len = 0;
|
||
|
void *h;
|
||
|
unsigned char *cookie = 0, *server = 0, *serverport;
|
||
|
|
||
|
tv = tlv_split(data, len, 3);
|
||
|
|
||
|
for (trav = tv; trav != NULL; trav = trav->next) {
|
||
|
if (trav->type == 0x000D) {
|
||
|
subtype = two_to_16(trav->value);
|
||
|
} else if (trav->type == 0x0005) {
|
||
|
server = malloc((trav->len) + 1);
|
||
|
memcpy(server, trav->value, trav->len);
|
||
|
server[trav->len] = 0;
|
||
|
} else if (trav->type == 0x0006) {
|
||
|
cookie = malloc(trav->len);
|
||
|
memcpy(cookie, trav->value, trav->len);
|
||
|
cookie_len = trav->len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clear_tlv_list(tv);
|
||
|
|
||
|
if (strchr((char *) server, ':') == NULL) {
|
||
|
serverport = malloc(strlen((char *) server) + 7);
|
||
|
snprintf((char *) serverport, strlen((char *) server) + 7, "%s:%d",
|
||
|
(char *) server, ((IMCOMM *) handle)->oscarport);
|
||
|
free(server);
|
||
|
server = serverport;
|
||
|
}
|
||
|
#ifdef DEBUG
|
||
|
printf
|
||
|
("New connection info: Type %02X, server %s. Cookie len %d bytes.\n",
|
||
|
subtype, server, cookie_len);
|
||
|
#endif
|
||
|
|
||
|
h = imcomm_create_child_handle(handle);
|
||
|
bos_signon_phase2(h, server, cookie, cookie_len);
|
||
|
|
||
|
free(server);
|
||
|
free(cookie);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
imcomm_upload_icon(void *handle, uint8_t * data, uint16_t icon_len)
|
||
|
{
|
||
|
/* this is really badly broken */
|
||
|
/* I'm disabling it for now */
|
||
|
|
||
|
/*
|
||
|
* snac_request_new_service(handle, 0x10); ((IMCOMM *)
|
||
|
* handle)->icondata = malloc(icon_len); memcpy(((IMCOMM *)
|
||
|
* handle)->icondata, data, icon_len); ((IMCOMM *) handle)->iconlen =
|
||
|
* icon_len;
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
snac_finish_buddy_icon(void *handle)
|
||
|
{
|
||
|
/*
|
||
|
* The icon data is contained in the parent's node
|
||
|
*/
|
||
|
|
||
|
pkt_t *newpkt;
|
||
|
void *pptr = ((IMCOMM *) handle)->parent;
|
||
|
|
||
|
newpkt = pkt_init(4 + ((IMCOMM *) pptr)->iconlen);
|
||
|
pkt_add16(newpkt, 0x0001);
|
||
|
pkt_add16(newpkt, ((IMCOMM *) pptr)->iconlen);
|
||
|
pkt_addraw(newpkt, ((IMCOMM *) pptr)->icondata,
|
||
|
((IMCOMM *) pptr)->iconlen);
|
||
|
|
||
|
snac_sendpkt(handle, 0x10, 0x02, newpkt, 0);
|
||
|
pkt_free(newpkt);
|
||
|
}
|