view libfaim/aim_im.c @ 133:e277d5f0c1dd

[gaim-migrate @ 143] Let's see if I can remember everything I did: - Fixed a bug I let slip. If you choose the new option to not play login sounds when you log in, and then quit before the timeout is up, it would save that you didn't want login sounds at all. - Added two new plugin events: event_away and event_buddy_away. - Made GtkWidget *imaway in away.c and void play(uchar *, int) in sound.c not static any more (though not referenced in gaim.h). This is so plugins can use those (and not have to worry about writing their own sound code). - Wrote a quick plugin to auto-iconify windows when you go away. I had just been locally patching my own copy, since I figured it wasn't worth including as an option. It also demonstrates some of the issues of deciding between USE_APPLET and not. Perhaps plugins are the way to go with some things that would otherwise have been options (for example, the Lag-O-Meter is one of those things that could possibly have been a plugin instead of hard-coded in). I think that's everything. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 19 Apr 2000 02:04:30 +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;
}