]> andersk Git - libfaim.git/commitdiff
Implemented chat and some chatnav. Nearly a 2000line diff.
authormid <mid>
Sun, 2 Jan 2000 10:40:26 +0000 (10:40 +0000)
committermid <mid>
Sun, 2 Jan 2000 10:40:26 +0000 (10:40 +0000)
15 files changed:
CHANGES
aim_chat.c
aim_chatnav.c
aim_conn.c
aim_im.c
aim_info.c
aim_misc.c
aim_rxhandlers.c
aim_tlv.c
aim_txqueue.c
faim/aim.h
faim/aim_cbtypes.h
faim/faimconfig.h
tcpdumps/randombits.txt [new file with mode: 0644]
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 2f79562f84ae40343aea26a85b3974f149fd1108..e1bd75dcf72159f4c65a0996a9ae82f871b0aeda 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,14 +1,31 @@
 
 No release numbers
 ------------------
+ - Sun Jan  2 10:31:19 UTC 2000
+   - Cleanups in aim_info.c
+   - Can compile with -Ddebug=100 again
+   - Implemented chat: Joining/Leaving, info parsing, IM parsing/sending
+   - Implemented some chatnav: rights req/parsing, room creation
+
+ - Thu Dec 30 10:08:42 UTC 1999
+   - Fixed bug in aim_im.c when (encoding == NULL) || (lang == NULL)
+   - Added detection of voice chat requests
+   - Added AIM_CLASS_* defines, including new Away flag
+   - Added awaymsg parameter to bos_setprofile.
+     - If awaymsg is nonnull, you will be advertised as being away (your
+         class will be ORed with AIM_CLASS_AWAY), otherwise you'll show 
+         up normal.
+
  - Wed Dec 29 10:06:35 UTC 1999
    - Fixed small bug in IM parser
    - Added stubs for the capability TLVs in userinfo.
 
  - Wed Dec 29 09:14:45 UTC 1999
-   - Added a capability block to aim_bos_setprofile.  Can now get chat invites again.
+   - Added a capability block to aim_bos_setprofile.  Can now get chat 
+       invites again.
    - Extended ICBM parser to support channel 2 messages (chat invites)
-     - A channel parameter has been prepended to the varargs -- REQUIRES CLIENT CHANGES.
+     - A channel parameter has been prepended to the varargs -- REQUIRES 
+         CLIENT CHANGES.
      - Extended faimtest to support chat invites.
    - Changed faimtest to get sn/password from environment
 
index a7af3447ba9409206e517e290a29899e870b1f77..6ce4b69d608f866bd01179ad13aae807b1eb0541 100644 (file)
 
 #include <faim/aim.h> 
 
+char *aim_chat_getname(struct aim_conn_t *conn)
+{
+  if (!conn)
+    return NULL;
+  if (conn->type != AIM_CONN_TYPE_CHAT)
+    return NULL;
+
+  return (char *)conn->priv; /* yuck ! */
+}
+
+struct aim_conn_t *aim_chat_getconn(struct aim_session_t *sess, char *name)
+{
+  int i;
+
+  for (i=0;i<AIM_CONN_MAX;i++)
+    {
+      if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
+       {
+         if (sess->conns[i].priv)
+           if (!strcmp((char *)sess->conns[i].priv, name))
+             {
+               return &sess->conns[i];
+             }
+       }
+    }
+  return NULL;
+}
+
+int aim_chat_attachname(struct aim_conn_t *conn, char *roomname)
+{
+  if (!conn || !roomname)
+    return -1;
+
+  conn->priv = malloc(strlen(roomname)+1);
+  strcpy(conn->priv, roomname);
+
+  return 0;
+}
+
+u_long aim_chat_send_im(struct aim_session_t *sess,
+                       struct aim_conn_t *conn, 
+                       char *msg)
+{   
+
+  int curbyte,i;
+  struct command_tx_struct newpacket;
+
+  if (!sess || !conn || !msg)
+    return 0;
+  
+  newpacket.lock = 1; /* lock struct */
+  newpacket.type = 0x02; /* IMs are always family 0x02 */
+
+  /* 
+   * Since we must have a specific connection, then theres 
+   * no use in going on if we don't have one... 
+   */
+  if (!conn)
+    return sess->snac_nextid;
+  newpacket.conn = conn;
+
+  /*
+   * Its simplest to set this arbitrarily large and waste
+   * space.  Precalculating is costly here.
+   */
+  newpacket.commandlen = 1152;
+
+  newpacket.data = (u_char *) calloc(1, newpacket.commandlen);
+
+  curbyte  = 0;
+  curbyte += aim_putsnac(newpacket.data+curbyte, 
+                        0x000e, 0x0005, 0x0000, sess->snac_nextid);
+
+  /* 
+   * Generate a random message cookie 
+   *
+   */
+  for (i=0;i<8;i++)
+    curbyte += aimutil_put8(newpacket.data+curbyte, (u_char) random());
+
+  /*
+   * metaTLV start.  -- i assume this is a metaTLV.  it could be the
+   *                    channel ID though.
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0003);
+
+  /*
+   * Type 1: Unknown.  Blank.
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  
+  /*
+   * Type 6: Unknown.  Blank.
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0006);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+
+  /*
+   * Type 5: Message block.  Contains more TLVs.
+   *
+   * This could include other information... We just
+   * put in a message TLV however.  
+   * 
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0005);
+  curbyte += aimutil_put16(newpacket.data+curbyte, strlen(msg)+4);
+
+  /*
+   * SubTLV: Type 1: Message
+   */
+  curbyte += aim_puttlv_str(newpacket.data+curbyte, 0x0001, strlen(msg), msg);
+  
+  newpacket.commandlen = curbyte;
+
+  newpacket.lock = 0;
+  aim_tx_enqueue(sess, &newpacket);
+
+  return (sess->snac_nextid++);
+}
+
 /*
- * FIXME: Doesn't work.
+ * Join a room of name roomname.  This is the first
+ * step to joining an already created room.  It's 
+ * basically a Service Request for family 0x000e, 
+ * with a little added on to specify the exchange
+ * and room name.
  *
  */
 u_long aim_chat_join(struct aim_session_t *sess,
                     struct aim_conn_t *conn, 
+                    u_short exchange,
                     const char *roomname)
 {
   struct command_tx_struct newpacket;
+  int i;
+
+  if (!sess || !conn || !roomname)
+    return 0;
   
   newpacket.lock = 1;
   if (conn)
@@ -23,35 +153,45 @@ u_long aim_chat_join(struct aim_session_t *sess,
   else
     newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
 
-  newpacket.type = 0x0002;
+  newpacket.type = 0x02;
   
-  newpacket.commandlen = 12+7+strlen(roomname)+6;
+  newpacket.commandlen = 10 + 9 + strlen(roomname) + 2;
   newpacket.data = (char *) malloc(newpacket.commandlen);
   memset(newpacket.data, 0x00, newpacket.commandlen);
   
-  aim_putsnac(newpacket.data, 0x0001, 0x0004, 0x0000, sess->snac_nextid);
+  i = aim_putsnac(newpacket.data, 0x0001, 0x0004, 0x0000, sess->snac_nextid);
 
-  newpacket.data[10] = 0x00;
-  newpacket.data[11] = 0x0e;
-  newpacket.data[12] = 0x00;
-  newpacket.data[13] = 0x01;
-  newpacket.data[14] = 0x00;
-  newpacket.data[15] = 0x0c;
-  newpacket.data[16] = 0x00;
-  newpacket.data[17] = 0x04;
-  newpacket.data[18] = strlen(roomname) & 0x00ff;
-  memcpy(&(newpacket.data[19]), roomname, strlen(roomname));
-  
-  {
-    u_int i = 0;
-    printf("\n\n\n");
-    for (i = 0;i < newpacket.commandlen; i++)
-      printf("0x%02x ", newpacket.data[i]);
-    printf("\n\n\n");
-  }
+  i+= aimutil_put16(newpacket.data+i, 0x000e);
+
+  /* 
+   * this is techinally a TLV, but we can't use normal functions
+   * because we need the extraneous nulls and other weird things.
+   */
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+  i+= aimutil_put16(newpacket.data+i, 2+1+strlen(roomname)+2);
+  i+= aimutil_put16(newpacket.data+i, exchange);
+  i+= aimutil_put8(newpacket.data+i, strlen(roomname));
+  memcpy(newpacket.data+i, roomname, strlen(roomname));
+  i+= strlen(roomname);
+  //i+= aimutil_putstr(newpacket.data+i, roomname, strlen(roomname));
+  i+= aimutil_put16(newpacket.data+i, 0x0000);
 
+  /*
+   * Chat hack.
+   *
+   * XXX: A problem occurs here if we request a channel
+   *      join but it fails....pendingjoin will be nonnull
+   *      even though the channel is never going to get a
+   *      redirect!
+   *
+   */
+  sess->pendingjoin = (char *)malloc(strlen(roomname)+1);
+  strcpy(sess->pendingjoin, roomname);
+
+  newpacket.lock = 0;
   aim_tx_enqueue(sess, &newpacket);
 
+#if 0
   {
     struct aim_snac_t snac;
     
@@ -60,11 +200,480 @@ u_long aim_chat_join(struct aim_session_t *sess,
     snac.type = 0x0004;
     snac.flags = 0x0000;
 
-    snac.data = malloc(strlen(roomname));
-    memcpy(snac.data, roomname, strlen(roomname));
+    snac.data = malloc(strlen(roomname)+1);
+    strcpy(snac.data, roomname);
 
     aim_newsnac(sess, &snac);
   }
 
+#endif
+  return (sess->snac_nextid++);
+}
+
+int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo)
+{
+  int namelen = 0;
+  int i = 0;
+
+  if (!buf || !outinfo)
+    return 0;
+
+  outinfo->exchange = aimutil_get16(buf+i);
+  i += 2;
+
+  namelen = aimutil_get8(buf+i);
+  i += 1;
+
+  outinfo->name = (char *)malloc(namelen+1);
+  memcpy(outinfo->name, buf+i, namelen);
+  outinfo->name[namelen] = '\0';
+  i += namelen;
+
+  outinfo->instance = aimutil_get16(buf+i);
+  i += 2;
+  
+  return i;
+};
+
+
+/*
+ * General room information.  Lots of stuff.
+ *
+ * Values I know are in here but I havent attached
+ * them to any of the 'Unknown's:
+ *     - Language (English)
+ *
+ */
+int aim_chat_parse_infoupdate(struct aim_session_t *sess,
+                             struct command_rx_struct *command)
+{
+  struct aim_userinfo_s *userinfo;
+  rxcallback_t userfunc=NULL;  
+  int ret = 1, i = 0;
+  int usercount = 0;
+  u_char detaillevel = 0;
+  char *roomname;
+  struct aim_chat_roominfo roominfo;
+  u_short tlvcount = 0;
+  struct aim_tlvlist_t *tlvlist;
+  char *roomdesc;
+
+  i = 10;
+  i += aim_chat_readroominfo(command->data+i, &roominfo);
+  
+  detaillevel = aimutil_get8(command->data+i);
+  i++;
+  
+  tlvcount = aimutil_get16(command->data+i);
+  i += 2;
+
+  /*
+   * Everything else are TLVs.
+   */ 
+  tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+  
+  /*
+   * TLV type 0x006a is the room name in Human Readable Form.
+   */
+  if (aim_gettlv(tlvlist, 0x006a, 1))
+      roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
+
+  /*
+   * Type 0x006f: Number of occupants.
+   */
+  if (aim_gettlv(tlvlist, 0x006f, 1))
+    {
+      struct aim_tlv_t *tmptlv;
+      tmptlv = aim_gettlv(tlvlist, 0x006f, 1);
+
+      usercount = aimutil_get16(tmptlv->value);
+    }
+
+  /*
+   * Type 0x0073:  Occupant list.
+   */
+  if (aim_gettlv(tlvlist, 0x0073, 1))
+    {  
+      int curoccupant = 0;
+      struct aim_tlv_t *tmptlv;
+
+      tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
+
+      /* Allocate enough userinfo structs for all occupants */
+      userinfo = calloc(usercount, sizeof(struct aim_userinfo_s));
+
+      i = 0;
+      while (curoccupant < usercount)
+       i += aim_extractuserinfo(tmptlv->value+i, &userinfo[curoccupant++]);
+    }
+  
+  /* 
+   * Type 0x00c9: Unknown.
+   */
+  if (aim_gettlv(tlvlist, 0x00c9, 1))
+    ;
+  
+  /* 
+   * Type 0x00ca: Creation date
+   */
+  if (aim_gettlv(tlvlist, 0x00ca, 1))
+    ;
+
+  /* 
+   * Type 0x00d1: Maximum Message Length
+   */
+  if (aim_gettlv(tlvlist, 0x00d1, 1))
+    ;
+
+  /* 
+   * Type 0x00d2: Unknown.
+   */
+  if (aim_gettlv(tlvlist, 0x00d2, 1))
+    ;
+
+  /* 
+   * Type 0x00d3: Room Description
+   */
+  if (aim_gettlv(tlvlist, 0x00d3, 1))
+    roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
+
+  /* 
+   * Type 0x00d5: Unknown.
+   */
+  if (aim_gettlv(tlvlist, 0x00d5, 1))
+    ;
+
+
+  userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE);
+  if (userfunc)
+    {
+      ret = userfunc(sess,
+                    command, 
+                    &roominfo,
+                    roomname,
+                    usercount,
+                    userinfo,  
+                    roomdesc);
+    }
+  free(roominfo.name);
+  free(userinfo);
+  free(roomname);
+  free(roomdesc);
+  aim_freetlvchain(&tlvlist);
+  return ret;
+}
+
+int aim_chat_parse_joined(struct aim_session_t *sess,
+                             struct command_rx_struct *command)
+{
+  struct aim_userinfo_s *userinfo = NULL;
+  rxcallback_t userfunc=NULL;  
+  int i = 10, curcount = 0, ret = 1;
+
+  while (i < command->commandlen)
+    {
+      curcount++;
+      userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s));
+      i += aim_extractuserinfo(command->data+i, &userinfo[curcount-1]);
+    }
+
+  userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN);
+  if (userfunc)
+    {
+      ret = userfunc(sess,
+                    command, 
+                    curcount,
+                    userinfo);
+    }
+
+  free(userinfo);
+
+  return ret;
+}            
+
+int aim_chat_parse_leave(struct aim_session_t *sess,
+                             struct command_rx_struct *command)
+{
+
+  struct aim_userinfo_s *userinfo = NULL;
+  rxcallback_t userfunc=NULL;  
+  int i = 10, curcount = 0, ret = 1;
+
+  while (i < command->commandlen)
+    {
+      curcount++;
+      userinfo = realloc(userinfo, curcount * sizeof(struct aim_userinfo_s));
+      i += aim_extractuserinfo(command->data+i, &userinfo[curcount-1]);
+    }
+
+  userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE);
+  if (userfunc)
+    {
+      ret = userfunc(sess,
+                    command, 
+                    curcount,
+                    userinfo);
+    }
+
+  free(userinfo);
+
+  return ret;
+}         
+
+/*
+ * We could probably include this in the normal ICBM parsing 
+ * code as channel 0x0003, however, since only the start
+ * would be the same, we might as well do it here.
+ */
+int aim_chat_parse_incoming(struct aim_session_t *sess,
+                             struct command_rx_struct *command)
+{
+  struct aim_userinfo_s userinfo;
+  rxcallback_t userfunc=NULL;  
+  int ret = 1, i = 0, z = 0;
+  u_char cookie[8];
+  int channel;
+  struct aim_tlvlist_t *outerlist;
+  char *msg = NULL;
+
+  memset(&userinfo, 0x00, sizeof(struct aim_userinfo_s));
+
+  i = 10; /* skip snac */
+
+  /*
+   * ICBM Cookie.  Ignore it.
+   */ 
+  for (z=0; z<8; z++,i++)
+    cookie[z] = command->data[i];
+
+  /*
+   * Channel ID
+   *
+   * Channels 1 and 2 are implemented in the normal ICBM
+   * parser.
+   *
+   * We only do channel 3 here.
+   *
+   */
+  channel = aimutil_get16(command->data+i);
+  i += 2;
+
+  if (channel != 0x0003)
+    {
+      printf("faim: chat_incoming: unknown channel! (0x%04x)\n", channel);
+      return 1;
+    }
+
+  /*
+   * Start parsing TLVs right away. 
+   */
+  outerlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+  
+  /*
+   * Type 0x0003: Source User Information
+   */
+  if (aim_gettlv(outerlist, 0x0003, 1))
+    {
+      struct aim_tlv_t *userinfotlv;
+      
+      userinfotlv = aim_gettlv(outerlist, 0x0003, 1);
+      aim_extractuserinfo(userinfotlv->value, &userinfo);
+    }
+
+  /*
+   * Type 0x0001: Unknown.
+   */
+  if (aim_gettlv(outerlist, 0x0001, 1))
+    ;
+
+  /*
+   * Type 0x0005: Message Block.  Conains more TLVs.
+   */
+  if (aim_gettlv(outerlist, 0x0005, 1))
+    {
+      struct aim_tlvlist_t *innerlist;
+      struct aim_tlv_t *msgblock;
+
+      msgblock = aim_gettlv(outerlist, 0x0005, 1);
+      innerlist = aim_readtlvchain(msgblock->value, msgblock->length);
+      
+      /* 
+       * Type 0x0001: Message.
+       */      
+      if (aim_gettlv(innerlist, 0x0001, 1))
+         msg = aim_gettlv_str(innerlist, 0x0001, 1);
+
+      aim_freetlvchain(&innerlist); 
+    }
+
+  userfunc = aim_callhandler(command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG);
+  if (userfunc)
+    {
+      ret = userfunc(sess,
+                    command, 
+                    &userinfo,
+                    msg);
+    }
+  free(msg);
+  aim_freetlvchain(&outerlist);
+
+  return ret;
+}            
+
+u_long aim_chat_clientready(struct aim_session_t *sess,
+                           struct aim_conn_t *conn)
+{
+  struct command_tx_struct newpacket;
+  int i;
+
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHAT);
+  newpacket.type = 0x02;
+  newpacket.commandlen = 0x20;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  i = aim_putsnac(newpacket.data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
+
+  i+= aimutil_put16(newpacket.data+i, 0x000e);
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0004);
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+  i+= aimutil_put16(newpacket.data+i, 0x0003);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0004);
+  i+= aimutil_put16(newpacket.data+i, 0x0686);
+
+  newpacket.lock = 0;
+  aim_tx_enqueue(sess, &newpacket);
+
+  return (sess->snac_nextid++);
+}
+
+int aim_chat_leaveroom(struct aim_session_t *sess, char *name)
+{
+  int i;
+
+  for (i=0;i<AIM_CONN_MAX;i++)
+    {
+      if (sess->conns[i].type == AIM_CONN_TYPE_CHAT)
+       {
+         if (sess->conns[i].priv)
+           if (!strcmp((char *)sess->conns[i].priv, name))
+             {
+               aim_conn_close(&sess->conns[i]);
+               return 0;
+             }
+       }
+    }
+  return -1;
+}
+
+/*
+ * conn must be a BOS connection!
+ */
+u_long aim_chat_invite(struct aim_session_t *sess,
+                      struct aim_conn_t *conn,
+                      char *sn,
+                      char *msg,
+                      u_short exchange,
+                      char *roomname,
+                      u_short instance)
+{
+  struct command_tx_struct newpacket;
+  int i,curbyte=0;
+
+  if (!sess || !conn || !sn || !msg || !roomname)
+    return 0;
+
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
+  newpacket.type = 0x02;
+  newpacket.commandlen = 1152+strlen(sn)+strlen(roomname)+strlen(msg);
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  curbyte = aim_putsnac(newpacket.data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
+
+  /*
+   * Cookie
+   */
+  for (i=0;i<8;i++)
+    curbyte += aimutil_put8(newpacket.data+curbyte, (u_char)rand());
+
+  /*
+   * Channel (2)
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002);
+
+  /*
+   * Dest sn
+   */
+  curbyte += aimutil_put8(newpacket.data+curbyte, strlen(sn));
+  curbyte += aimutil_putstr(newpacket.data+curbyte, sn, strlen(sn));
+
+  /*
+   * TLV t(0005)
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0005);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x28+strlen(msg)+0x04+0x03+strlen(roomname)+0x02);
+  
+  /* 
+   * Unknown info
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x3131);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x3538);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x3446);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x4100);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x748f);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x2420);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x6287);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x11d1);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x8222);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x4445);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x5354);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  
+  /*
+   * TLV t(000a) -- Unknown
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x000a);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001);
+  
+  /*
+   * TLV t(000f) -- Unknown
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x000f);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000);
+  
+  /*
+   * TLV t(000c) -- Invitation message
+   */
+  curbyte += aim_puttlv_str(newpacket.data+curbyte, 0x000c, strlen(msg), msg);
+
+  /*
+   * TLV t(2711) -- Container for room information 
+   */
+  curbyte += aimutil_put16(newpacket.data+curbyte, 0x2711);
+  curbyte += aimutil_put16(newpacket.data+curbyte, 3+strlen(roomname)+2);
+  curbyte += aimutil_put16(newpacket.data+curbyte, exchange);
+  curbyte += aimutil_put8(newpacket.data+curbyte, strlen(roomname));
+  curbyte += aimutil_putstr(newpacket.data+curbyte, roomname, strlen(roomname));
+  curbyte += aimutil_put16(newpacket.data+curbyte, instance);
+
+  newpacket.commandlen = curbyte;
+  newpacket.lock = 0;
+  aim_tx_enqueue(sess, &newpacket);
+
   return (sess->snac_nextid++);
 }
index be99cfdfe2853a4e0bbed510c7fbd5f5633a5205..b6764e1c152dfe827d787b428540ae716edb61f0 100644 (file)
@@ -7,3 +7,326 @@
 
 #include <faim/aim.h>
 
+
+/*
+ * conn must be a chatnav connection!
+ */
+u_long aim_chatnav_reqrights(struct aim_session_t *sess,
+                         struct aim_conn_t *conn)
+{
+  struct aim_snac_t snac;
+
+  snac.id = aim_genericreq_n(sess, conn, 0x000d, 0x0002);
+
+  snac.family = 0x000d;
+  snac.type = 0x0002;
+  snac.flags = 0x0000;
+  snac.data = NULL;
+  
+  aim_newsnac(sess, &snac);
+
+  return (sess->snac_nextid); /* already incremented */
+}
+
+u_long aim_chatnav_clientready(struct aim_session_t *sess,
+                              struct aim_conn_t *conn)
+{
+  struct command_tx_struct newpacket; 
+  int i;
+
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+  newpacket.type = 0x02;
+  newpacket.commandlen = 0x20;
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  i = aim_putsnac(newpacket.data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
+
+  i+= aimutil_put16(newpacket.data+i, 0x000d);
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0004);
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+  i+= aimutil_put16(newpacket.data+i, 0x0003);
+
+  i+= aimutil_put16(newpacket.data+i, 0x0004);
+  i+= aimutil_put16(newpacket.data+i, 0x0686);
+
+  aim_tx_enqueue(sess, &newpacket);
+
+  return (sess->snac_nextid++);
+}
+
+/*
+ * Since multiple things can trigger this callback,
+ * we must lookup the snacid to determine the original
+ * snac subtype that was called.
+ */
+int aim_chatnav_parse_info(struct aim_session_t *sess, struct command_rx_struct *command)
+{
+  struct aim_snac_t *snac;
+  u_long snacid;
+  rxcallback_t userfunc;
+  
+  snacid = aimutil_get32(command->data+6);
+  snac = aim_remsnac(sess, snacid);
+
+  if (!snac)
+    {
+      printf("faim: chatnav_parse_info: received response to unknown request! (%08lx)\n", snacid);
+      return 1;
+    }
+  
+  if (snac->family != 0x000d)
+    {
+      printf("faim: chatnav_parse_info: recieved response that maps to corrupt request! (fam=%04x)\n", snac->family);
+      return 1;
+    }
+
+  /*
+   * We now know what the original SNAC subtype was.
+   */
+  switch(snac->type)
+    {
+    case 0x0002: /* request chat rights */
+      {
+         struct aim_tlvlist_t *tlvlist;
+         struct aim_chat_exchangeinfo *exchanges = NULL;
+         int curexchange = 0;
+         struct aim_tlv_t *exchangetlv;
+         u_char maxrooms = 0;
+         int ret = 1;
+         struct aim_tlvlist_t *innerlist;
+        
+         tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
+         
+         /* 
+          * Type 0x0002: Maximum concurrent rooms.
+          */ 
+         if (aim_gettlv(tlvlist, 0x0002, 1))
+           {
+             struct aim_tlv_t *maxroomstlv;
+             maxroomstlv = aim_gettlv(tlvlist, 0x0002, 1);
+             maxrooms = aimutil_get8(maxroomstlv->value);
+           }
+
+         /* 
+          * Type 0x0003: Exchange information
+          *
+          * There can be any number of these, each one
+          * representing another exchange.  
+          * 
+          */
+         curexchange = 0;
+         while ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange+1)))
+           {   
+             curexchange++;
+             exchanges = realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
+             
+             /* exchange number */
+             exchanges[curexchange-1].number = aimutil_get16(exchangetlv->value);
+             innerlist = aim_readtlvchain(exchangetlv->value+2, exchangetlv->length-2);
+             
+             /* 
+              * Type 0x000d: Unknown.
+              */
+             if (aim_gettlv(innerlist, 0x000d, 1))
+               ;
+             
+             /* 
+              * Type 0x0004: Unknown
+              */
+             if (aim_gettlv(innerlist, 0x0004, 1))
+               ;
+
+             /*
+              * Type 0x00c9: Unknown
+              */ 
+             if (aim_gettlv(innerlist, 0x00c9, 1))
+               ;
+             
+             /*
+              * Type 0x00ca: Creation Date 
+              */
+             if (aim_gettlv(innerlist, 0x00ca, 1))
+               ;
+             
+             /*
+              * Type 0x00d0: Unknown
+              */
+             if (aim_gettlv(innerlist, 0x00d0, 1))
+               ;
+
+             /*
+              * Type 0x00d1: Maximum Message length
+              */
+             if (aim_gettlv(innerlist, 0x00d1, 1))
+               ;
+
+             /*
+              * Type 0x00d2: Unknown
+              */
+             if (aim_gettlv(innerlist, 0x00d2, 1))     
+               ;       
+
+             /*
+              * Type 0x00d3: Exchange Name
+              */
+             if (aim_gettlv(innerlist, 0x00d3, 1))     
+               exchanges[curexchange-1].name = aim_gettlv_str(innerlist, 0x00d3, 1);
+             else
+               exchanges[curexchange-1].name = NULL;
+
+             /*
+              * Type 0x00d5: Unknown
+              */
+             if (aim_gettlv(innerlist, 0x00d5, 1))
+               ;
+
+             /*
+              * Type 0x00d6: Character Set (First Time)
+              */             
+             if (aim_gettlv(innerlist, 0x00d6, 1))     
+               exchanges[curexchange-1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1);
+             else
+               exchanges[curexchange-1].charset1 = NULL;
+             
+             /*
+              * Type 0x00d7: Language (First Time)
+              */             
+             if (aim_gettlv(innerlist, 0x00d7, 1))     
+               exchanges[curexchange-1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1);
+             else
+               exchanges[curexchange-1].lang1 = NULL;
+
+             /*
+              * Type 0x00d8: Character Set (Second Time)
+              */             
+             if (aim_gettlv(innerlist, 0x00d8, 1))     
+               exchanges[curexchange-1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1);
+             else
+               exchanges[curexchange-1].charset2 = NULL;
+
+             /*
+              * Type 0x00d9: Language (Second Time)
+              */             
+             if (aim_gettlv(innerlist, 0x00d9, 1))     
+               exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
+             else
+               exchanges[curexchange-1].lang2 = NULL;
+
+           }
+         
+         /*
+          * Call client.
+          */
+         userfunc = aim_callhandler(command->conn, 0x000d, 0x0009);
+         if (userfunc)
+           ret = userfunc(sess, 
+                          command, 
+                          snac->type,
+                          maxrooms,
+                          curexchange, 
+                          exchanges);
+         curexchange--;
+         while(curexchange)
+           {
+             if (exchanges[curexchange].name)
+               free(exchanges[curexchange].name);
+             if (exchanges[curexchange].charset1)
+               free(exchanges[curexchange].charset1);
+             if (exchanges[curexchange].lang1)
+               free(exchanges[curexchange].lang1);
+             if (exchanges[curexchange].charset2)
+               free(exchanges[curexchange].charset2);
+             if (exchanges[curexchange].lang2)
+               free(exchanges[curexchange].lang2);
+             curexchange--;
+           }
+         free(exchanges);
+         aim_freetlvchain(&innerlist);
+         aim_freetlvchain(&tlvlist);
+         return ret;
+      }
+    case 0x0003: /* request exchange info */
+      printf("faim: chatnav_parse_info: resposne to exchange info\n");
+      return 1;
+    case 0x0004: /* request room info */
+      printf("faim: chatnav_parse_info: response to room info\n");
+      return 1;
+    case 0x0005: /* request more room info */
+      printf("faim: chatnav_parse_info: response to more room info\n");
+      return 1;
+    case 0x0006: /* request occupant list */
+      printf("faim: chatnav_parse_info: response to occupant info\n");
+      return 1;
+    case 0x0007: /* search for a room */
+      printf("faim: chatnav_parse_info: search results\n");
+      return 1;
+    case 0x0008: /* create room */
+      printf("faim: chatnav_parse_info: response to create room\n");
+      return 1;
+    default: /* unknown */
+      printf("faim: chatnav_parse_info: unknown request subtype (%04x)\n", snac->type);
+    }
+
+  return 1; /* shouldn't get here */
+}
+
+u_long aim_chatnav_createroom(struct aim_session_t *sess,
+                             struct aim_conn_t *conn,
+                             char *name, 
+                             u_short exchange)
+{
+  struct command_tx_struct newpacket; 
+  int i;
+  struct aim_snac_t snac;
+
+  newpacket.lock = 1;
+  if (conn)
+    newpacket.conn = conn;
+  else
+    newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV);
+  newpacket.type = 0x02;
+
+  newpacket.commandlen = 10 + 12 + strlen("invite") + strlen(name);
+
+  newpacket.data = (char *) malloc(newpacket.commandlen);
+  i = aim_putsnac(newpacket.data, 0x000d, 0x0008, 0x0000, sess->snac_nextid);
+
+  /* exchange */
+  i+= aimutil_put16(newpacket.data+i, exchange);
+
+  /* room cookie */
+  i+= aimutil_put8(newpacket.data+i, strlen("invite"));
+  i+= aimutil_putstr(newpacket.data+i, "invite", strlen("invite"));
+
+  /* instance */
+  i+= aimutil_put16(newpacket.data+i, 0xffff);
+  
+  /* detail level */
+  i+= aimutil_put8(newpacket.data+i, 0x01);
+  
+  /* tlvcount */
+  i+= aimutil_put16(newpacket.data+i, 0x0001);
+
+  /* room name */
+  i+= aim_puttlv_str(newpacket.data+i, 0x00d3, strlen(name), name);
+
+  snac.id = sess->snac_nextid;
+  snac.family = 0x000d;
+  snac.type = 0x0008;
+  snac.flags = 0x0000;
+  snac.data = NULL;
+  
+  aim_newsnac(sess, &snac);
+
+  aim_tx_enqueue(sess, &newpacket);
+
+  return (sess->snac_nextid++);
+}
index ddc0ba8f4f00848d752bdfa3bad1e0163cf03164..ee2418c12c1cc731638667a88a7d2a1370e184ff 100644 (file)
@@ -45,6 +45,9 @@ void aim_conn_close(struct aim_conn_t *deadconn)
   deadconn->forcedlatency = 0;
   aim_clearhandlers(deadconn);
   deadconn->handlerlist = NULL;
+  if (deadconn->priv)
+    free(deadconn->priv);
+  deadconn->priv = NULL;
 }
 
 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
@@ -240,9 +243,9 @@ void aim_session_init(struct aim_session_t *sess)
   if (!sess)
     return;
 
-  sess->logininfo.screen_name[0] = '\0';
+  memset(sess->logininfo.screen_name, 0x00, MAXSNLEN);
   sess->logininfo.BOSIP = NULL;
-  sess->logininfo.cookie[0] = '\0';
+  memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN);
   sess->logininfo.email = NULL;
   sess->logininfo.regstatus = 0x00;
   
@@ -255,10 +258,12 @@ void aim_session_init(struct aim_session_t *sess)
       sess->conns[i].lastactivity = 0;
       sess->conns[i].forcedlatency = 0;
       sess->conns[i].handlerlist = NULL;
+      sess->conns[i].priv = NULL;
     }
   
   sess->queue_outgoing = NULL;
   sess->queue_incoming = NULL;
+  sess->pendingjoin = NULL;
   sess->outstanding_snacs = NULL;
   sess->snac_nextid = 0x00000001;
 
index c131687b432135740a3ca1708be209478056df44..867750b8944c63ff6a3eb5c504880398ccd30058 100644 (file)
--- a/aim_im.c
+++ b/aim_im.c
@@ -355,13 +355,12 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
       free(msg);
     }
   else if (channel == 0x0002)
-    {
+    {  
+      int rendtype;
       struct aim_tlv_t *block1;
       struct aim_tlvlist_t *list2;
       struct aim_tlv_t *tmptlv;
       int a;
-      u_short exchange,instance;
-      char *roomname,*msg,*encoding,*lang;
       
       /* Class. */
       if ((tmptlv = aim_gettlv(tlvlist, 0x0001, 1)))
@@ -388,46 +387,83 @@ int aim_parse_incoming_im_middle(struct aim_session_t *sess,
 
       a = 0x1a; /* skip -- not sure what this information is! */
 
-      list2 = aim_readtlvchain(block1->value+a, block1->length-a);
-      if (aim_gettlv(list2, 0x2711, 1))
+      /*
+       * XXX: Ignore if there's no data, only cookie information.
+       *
+       * Its probably just an accepted invitation or something.
+       *  
+       */
+      if (block1->length <= 0x1a)
        {
-         struct aim_tlv_t *name;
-         int len;
-
-         name = aim_gettlv(list2, 0x2711, 1);
-         
-         exchange = aimutil_get16(name->value+0);
-
-         len = aimutil_get16(name->value+2);
-         roomname = (char *)malloc(len+1);
-         memcpy(roomname, name->value+3, len);
-         roomname[len] = '\0';
-
-         instance = aimutil_get16(name->value+3+len);
+         aim_freetlvchain(&tlvlist);
+         return 1;
        }
 
-      if (aim_gettlv(list2, 0x000c, 1))
-         msg = aim_gettlv_str(list2, 0x000c, 1);
+      list2 = aim_readtlvchain(block1->value+a, block1->length-a);
 
-      if (aim_gettlv(list2, 0x000d, 1))
-         encoding = aim_gettlv_str(list2, 0x000d, 1);
-      if (aim_gettlv(list2, 0x000e, 1))
-         lang = aim_gettlv_str(list2, 0x000e, 1);
+      if (aim_gettlv(list2, 0x0004, 1) /* start connection */ ||  
+         aim_gettlv(list2, 0x000b, 1) /* close conncetion */)
+       {
+         rendtype = 1; /* voice request */
+
+         /*
+          * Call client.
+          */
+         userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+         if (userfunc)
+           i = userfunc(sess, 
+                        command, 
+                        channel, 
+                        rendtype,
+                        &userinfo);
+         else 
+           i = 0;
+       }
+      else
+       {
+         struct aim_chat_roominfo roominfo;
+         char *msg=NULL,*encoding=NULL,*lang=NULL;
+
+         rendtype = 0; /* chat invite */
+         if (aim_gettlv(list2, 0x2711, 1))
+           {
+             struct aim_tlv_t *nametlv;
+             
+             nametlv = aim_gettlv(list2, 0x2711, 1);
+             aim_chat_readroominfo(nametlv->value, &roominfo);
+           }
+         
+         if (aim_gettlv(list2, 0x000c, 1))
+           msg = aim_gettlv_str(list2, 0x000c, 1);
+         
+         if (aim_gettlv(list2, 0x000d, 1))
+           encoding = aim_gettlv_str(list2, 0x000d, 1);
+         
+         if (aim_gettlv(list2, 0x000e, 1))
+           lang = aim_gettlv_str(list2, 0x000e, 1);
       
-      /*
-       * Call client.
-       */
-      userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
-      if (userfunc)
-       i = userfunc(sess, command, channel, &userinfo, roomname, msg, encoding+1, lang+1, exchange, instance);
-      else 
-       i = 0;
+         /*
+          * Call client.
+          */
+         userfunc = aim_callhandler(command->conn, 0x0004, 0x0007);
+         if (userfunc)
+           i = userfunc(sess, 
+                        command, 
+                        channel, 
+                        rendtype,
+                        &userinfo, 
+                        &roominfo, 
+                        msg, 
+                        encoding?encoding+1:NULL, 
+                        lang?lang+1:NULL);
+         else 
+           i = 0;
       
-      free(roomname);
-      free(msg);
-      free(encoding);
-      free(lang);
+         free(roominfo.name);
+         free(msg);
+         free(encoding);
+         free(lang);
+       }
       aim_freetlvchain(&list2);
     }
 
index b0c9b7463b261c3dc112fa2f228a176ba20768cc..daf47469a484665baf9466779575c9d700443bff 100644 (file)
@@ -108,6 +108,7 @@ int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo)
           *      0x0004  AOL Main Service user
           *      0x0008  Unknown bit 4
           *      0x0010  Free (AIM) user 
+          *      0x0020  Away
           *
           * In some odd cases, we can end up with more
           * than one of these.  We only want the first,
@@ -306,6 +307,7 @@ int aim_parse_userinfo_middle(struct aim_session_t *sess,
   char *prof = NULL;
   u_int i = 0;
   rxcallback_t userfunc=NULL;
+  struct aim_tlvlist_t *tlvlist;
 
   {
     u_long snacid = 0x000000000;
@@ -320,43 +322,18 @@ int aim_parse_userinfo_middle(struct aim_session_t *sess,
   }
   
   i = 10;
-  i += aim_extractuserinfo(command->data+i, &userinfo);
-
-  if (i < command->commandlen)
-    {
-      if (aimutil_get16(&command->data[i]) == 0x0001)
-        {
-          int len = 0;
-
-         len = aimutil_get16(&command->data[i+2]);
-
-          prof_encoding = (char *) malloc(len+1);
-          memcpy(prof_encoding, &(command->data[i+4]), len);
-          prof_encoding[len] = '\0';
-
-          i += (2+2+len);
-        }
-      else
-        {
-          printf("faim: userinfo: **warning: unexpected TLV after TLVblock t(%04x) l(%04x)\n", aimutil_get16(command->data+i), aimutil_get16(command->data+i+2));
-          i += 2 + 2 + command->data[i+3];
-        }
-    }
 
-  if (i < command->commandlen)
-    {
-      if (aimutil_get16(&command->data[i]) == 0x0002)
-       {
-         int len = 0;
-         len = aimutil_get16(&command->data[i+2]);
-         
-         prof = (char *) malloc(len+1);
-         memcpy(prof, &(command->data[i+4]), len);
-         prof[len] = '\0';
-       }
-      else
-       printf("faim:userinfo: **warning: profile not found, but still have data\n");
-    }
+  /*
+   * extractuserinfo will give us the basic metaTLV information
+   */
+  i += aim_extractuserinfo(command->data+i, &userinfo);
+  
+  /*
+   * However, in this command, there's usually more TLVs following...
+   */ 
+  tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+  prof_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
+  prof = aim_gettlv_str(tlvlist, 0x0002, 1);
 
   userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
   if (userfunc)
@@ -367,9 +344,10 @@ int aim_parse_userinfo_middle(struct aim_session_t *sess,
                   prof_encoding, 
                   prof); 
     }
-
+  
   free(prof_encoding);
   free(prof);
+  aim_freetlvchain(&tlvlist);
 
   return 1;
 }
index b882c80bc97eb41a4f0da6e8c47b513fe8627c46..a451d7a99a45dd69ba71d5c91ed0864f92d8f2a4 100644 (file)
@@ -241,7 +241,8 @@ u_long aim_bos_setbuddylist(struct aim_session_t *sess,
  */
 u_long aim_bos_setprofile(struct aim_session_t *sess,
                          struct aim_conn_t *conn, 
-                         char *profile)
+                         char *profile,
+                         char *awaymsg)
 {
   struct command_tx_struct newpacket;
   int i = 0;
@@ -269,6 +270,9 @@ u_long aim_bos_setprofile(struct aim_session_t *sess,
     newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
 
   newpacket.commandlen = 1152+strlen(profile)+1; /*arbitrarily large */
+  if (awaymsg) 
+    newpacket.commandlen += strlen(awaymsg);
+
   newpacket.data = (char *) malloc(newpacket.commandlen);
 
   i += aim_putsnac(newpacket.data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
@@ -277,9 +281,11 @@ u_long aim_bos_setprofile(struct aim_session_t *sess,
   /* why do we send this twice?  */
   i += aim_puttlv_str(newpacket.data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
   
-  /* a blank TLV 0x0004   --- not sure what this is either */
-  i += aimutil_put16(newpacket.data+i, 0x0004);
-  i += aimutil_put16(newpacket.data+i, 0x0000);
+  /* Away message -- we send this no matter what, even if its blank */
+  if (awaymsg)
+    i += aim_puttlv_str(newpacket.data+i, 0x0004, strlen(awaymsg), awaymsg);
+  else
+    i += aim_puttlv_str(newpacket.data+i, 0x0004, 0x0000, NULL);
 
   /* Capability information. */
   i += aim_puttlv_str(newpacket.data+i, 0x0005, 0x0060, funkydata);
@@ -413,6 +419,8 @@ u_long aim_bos_ackrateresp(struct aim_session_t *sess,
     newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
   newpacket.type = 0x02;
   newpacket.commandlen = 18;
+  if (conn->type != AIM_CONN_TYPE_BOS)
+    newpacket.commandlen += 2;
 
   newpacket.data = (char *) malloc(newpacket.commandlen);
   aim_putsnac(newpacket.data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
@@ -425,6 +433,11 @@ u_long aim_bos_ackrateresp(struct aim_session_t *sess,
   newpacket.data[15] = 0x03;
   newpacket.data[16] = 0x00;
   newpacket.data[17] = 0x04;
+  if (conn->type != AIM_CONN_TYPE_BOS)
+    {
+      newpacket.data[16] = 0x00;
+      newpacket.data[17] = 0x05;
+    }
 
   aim_tx_enqueue(sess, &newpacket);
 
@@ -483,7 +496,7 @@ u_long aim_setversions(struct aim_session_t *sess,
                                struct aim_conn_t *conn)
 {
   struct command_tx_struct newpacket;
-  int i,j;
+  int i;
 
   newpacket.lock = 1;
   if (conn)
@@ -531,7 +544,6 @@ u_long aim_setversions(struct aim_session_t *sess,
 
 #if 0
   for (j = 0; j < 0x10; j++)
-A
     {
       i += aimutil_put16(newpacket.data+i, j); /* family */
       i += aimutil_put16(newpacket.data+i, 0x0003); /* version */
index 3e81c9251ded194d5c2605e0e1f31399503ddef2..9fa45d9ee1826e2533b769f0ca46aa1d246f6a67 100644 (file)
@@ -512,6 +512,8 @@ int aim_rxdispatch(struct aim_session_t *sess)
                    workingPtr->handled = 1;
                    aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY);
                  }
+               else if ((family == 0x000d) && (subtype == 0x0009))
+                 workingPtr->handled = aim_chatnav_parse_info(sess, workingPtr);
                else
                  {
                    workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
@@ -519,8 +521,44 @@ int aim_rxdispatch(struct aim_session_t *sess)
              }
              break;
            case AIM_CONN_TYPE_CHAT:
-             printf("\nAHH! Dont know what to do with CHAT stuff yet!\n");
-             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
+             {
+               u_short family, subtype;
+
+               family = aimutil_get16(workingPtr->data);
+               subtype= aimutil_get16(workingPtr->data+2);
+               
+               if ((family == 0x0000) && (subtype == 0x00001))
+                 workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0000, 0x0001, workingPtr);
+               else if (family == 0x0001)
+                 {
+                   if (subtype == 0x0001)
+                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0001, workingPtr);
+                   else if (subtype == 0x0003)
+                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0003, workingPtr);
+                   else if (subtype == 0x0007)
+                     workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0001, 0x0007, workingPtr);
+                   else
+                     printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+                 }
+               else if (family == 0x000e)
+                 {
+                   if (subtype == 0x0002)
+                     workingPtr->handled = aim_chat_parse_infoupdate(sess, workingPtr);
+                   else if (subtype == 0x0003)
+                     workingPtr->handled = aim_chat_parse_joined(sess, workingPtr);    
+                   else if (subtype == 0x0004)
+                     workingPtr->handled = aim_chat_parse_leave(sess, workingPtr);     
+                   else if (subtype == 0x0006)
+                     workingPtr->handled = aim_chat_parse_incoming(sess, workingPtr);
+                   else        
+                     printf("Chat: unknown snac %04x/%04x\n", family, subtype); 
+                 }
+               else
+                 {
+                   printf("Chat: unknown snac %04x/%04x\n", family, subtype);
+                   workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_DEFAULT, workingPtr);
+                 }
+             }
              break;
            default:
              printf("\nAHHHHH! UNKNOWN CONNECTION TYPE! (0x%02x)\n\n", workingPtr->conn->type);
@@ -589,10 +627,24 @@ int aim_handleredirect_middle(struct aim_session_t *sess,
   tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
   memcpy(cookie, tmptlv->value, AIM_COOKIELEN);
 
-  userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
-  if (userfunc)
-    ret =  userfunc(sess, command, serviceid, ip, cookie);
-
+  if (serviceid == AIM_CONN_TYPE_CHAT)
+    {
+      /*
+       * Chat hack.
+       *
+       */
+      userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
+      if (userfunc)
+       ret =  userfunc(sess, command, serviceid, ip, cookie, sess->pendingjoin);
+      free(sess->pendingjoin);
+      sess->pendingjoin = NULL;
+    }
+  else
+    {
+      userfunc = aim_callhandler(command->conn, 0x0001, 0x0005);
+      if (userfunc)
+       ret =  userfunc(sess, command, serviceid, ip, cookie);
+    }
   aim_freetlvchain(&tlvlist);
 
   return ret;
index 94acf033ea516fc55d16c55f229583c9fd58a560..d03f2f92cfdb41d40ea49c8c389e9e31ec10d3af 100644 (file)
--- a/aim_tlv.c
+++ b/aim_tlv.c
@@ -31,7 +31,7 @@ struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
              cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
              memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
 
-             cur->tlv = aim_createtlv();
+             cur->tlv = aim_createtlv();       
              cur->tlv->type = type;
              cur->tlv->length = length;
              cur->tlv->value = (u_char *)malloc(length*sizeof(u_char));
@@ -201,13 +201,12 @@ int aim_puttlv_32(u_char *buf, u_short t, u_long v)
 int aim_puttlv_str(u_char *buf, u_short t, u_short l, u_char *v)
 {
   int curbyte;
-  if (!v || !buf)
-    return 0;
   
   curbyte  = 0;
   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
   curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
-  memcpy(buf+curbyte, v, l);
+  if (v)
+    memcpy(buf+curbyte, v, l);
   curbyte += l;
   return curbyte;
 }
index 50bf425f10e8a9020ce8516be9d99e24e8670966..f2ed1e8b844ebd4737430e5226104e09926da8f1 100644 (file)
@@ -59,7 +59,7 @@ int aim_tx_enqueue(struct aim_session_t *sess,
 
 #if debug > 2
   printf("calling aim_tx_printqueue()\n");
-  aim_tx_printqueue();
+  aim_tx_printqueue(sess);
   printf("back from aim_tx_printqueue()\n");
 #endif
 
@@ -98,7 +98,7 @@ u_int aim_get_next_txseqnum(struct aim_conn_t *conn)
  *
  */
 #if debug > 2
-int aim_tx_printqueue(void)
+int aim_tx_printqueue(struct aim_session_t *sess)
 {
   struct command_tx_struct *workingPtr = NULL;
 
@@ -280,7 +280,7 @@ int aim_tx_purgequeue(struct aim_session_t *sess)
           (sess->queue_outgoing->sent == 1) )
        {
 #if debug > 1
-         printf("purgequeue(): purging seqnum 0x%04x\n", aim_queue_outgoing->seqnum);
+         printf("purgequeue(): purging seqnum 0x%04x\n", sess->queue_outgoing->seqnum);
 #endif
          workingPtr2 = sess->queue_outgoing;
          sess->queue_outgoing = NULL;
index 38450f33c3a671398abc10374f0c80a64c1fc4b2..8b52f855f9b0588d9dff353ef53cb0e879fe03ac 100644 (file)
@@ -176,6 +176,13 @@ struct aim_session_t {
   struct command_tx_struct *queue_outgoing; 
   struct command_rx_struct *queue_incoming; 
   
+  /*
+   * This is a dreadful solution to the what-room-are-we-joining
+   * problem.  (There's no connection between the service
+   * request and the resulting redirect.)
+   */ 
+  char *pendingjoin;
+
   /*
    * Outstanding snac handling 
    *
@@ -199,6 +206,15 @@ struct aim_userinfo_s {
   u_long sessionlen;  
 };
 
+#define AIM_CLASS_TRIAL        0x0001
+#define AIM_CLASS_UNKNOWN2     0x0002
+#define AIM_CLASS_AOL          0x0004
+#define AIM_CLASS_UNKNOWN4     0x0008
+#define AIM_CLASS_FREE                 0x0010
+#define AIM_CLASS_AWAY         0x0020
+#define AIM_CLASS_UNKNOWN40    0x0040
+#define AIM_CLASS_UNKNOWN80    0x0080
+
 /*
  * TLV handling
  */
@@ -321,7 +337,7 @@ void aim_session_init(struct aim_session_t *);
 u_long aim_bos_setidle(struct aim_session_t *, struct aim_conn_t *, u_long);
 u_long aim_bos_changevisibility(struct aim_session_t *, struct aim_conn_t *, int, char *);
 u_long aim_bos_setbuddylist(struct aim_session_t *, struct aim_conn_t *, char *);
-u_long aim_bos_setprofile(struct aim_session_t *, struct aim_conn_t *, char *);
+u_long aim_bos_setprofile(struct aim_session_t *, struct aim_conn_t *, char *, char *);
 u_long aim_bos_setgroupperm(struct aim_session_t *, struct aim_conn_t *, u_long);
 u_long aim_bos_clientready(struct aim_session_t *, struct aim_conn_t *);
 u_long aim_bos_reqrate(struct aim_session_t *, struct aim_conn_t *);
@@ -333,6 +349,7 @@ u_long aim_bos_reqrights(struct aim_session_t *, struct aim_conn_t *);
 u_long aim_bos_reqbuddyrights(struct aim_session_t *, struct aim_conn_t *);
 u_long aim_bos_reqlocaterights(struct aim_session_t *, struct aim_conn_t *);
 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *, struct aim_conn_t *);
+u_long aim_setversions(struct aim_session_t *sess, struct aim_conn_t *conn);
 
 /* aim_rxhandlers.c */
 int aim_rxdispatch(struct aim_session_t *);
@@ -372,6 +389,41 @@ u_long aim_remove_buddy(struct aim_session_t *, struct aim_conn_t *, char *);
 u_long aim_usersearch_address(struct aim_session_t *, struct aim_conn_t *, char *);
 /* u_long aim_usersearch_name(struct aim_session_t *, struct aim_conn_t *, char *); */
 
+
+struct aim_chat_roominfo {
+  u_short exchange;
+  char *name;
+  u_short instance;
+};
+int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo);
+int aim_chat_parse_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_joined(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_leave(struct aim_session_t *sess, struct command_rx_struct *command);
+int aim_chat_parse_incoming(struct aim_session_t *sess, struct command_rx_struct *command);
+u_long aim_chat_send_im(struct aim_session_t *sess, struct aim_conn_t *conn, char *msg);
+u_long aim_chat_join(struct aim_session_t *sess, struct aim_conn_t *conn, u_short exchange, const char *roomname);
+u_long aim_chat_clientready(struct aim_session_t *sess, struct aim_conn_t *conn);
+int aim_chat_attachname(struct aim_conn_t *conn, char *roomname);
+char *aim_chat_getname(struct aim_conn_t *conn);
+struct aim_conn_t *aim_chat_getconn(struct aim_session_t *, char *name);
+
+u_long aim_chatnav_reqrights(struct aim_session_t *sess, struct aim_conn_t *conn);
+u_long aim_chatnav_clientready(struct aim_session_t *sess, struct aim_conn_t *conn);
+
+u_long aim_chat_invite(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, char *msg, u_short exchange, char *roomname, u_short instance);
+
+struct aim_chat_exchangeinfo {
+  u_short number;
+  char *name;
+  char *charset1;
+  char *lang1;
+  char *charset2;
+  char *lang2;
+};
+int aim_chatnav_parse_info(struct aim_session_t *sess, struct command_rx_struct *command);
+u_long aim_chatnav_createroom(struct aim_session_t *sess, struct aim_conn_t *conn, char *name, u_short exchange);
+int aim_chat_leaveroom(struct aim_session_t *sess, char *name);
+
 /* aim_util.c */
 int aimutil_put8(u_char *, u_char);
 u_char aimutil_get8(u_char *buf);
index 78b1ab5c61fbda91613cb0287e4b369d2a6c9545..5c15b437143c32f78f3f189ce9d70612a6158590 100644 (file)
  * SNAC Family: Chat Navigation Services
  */ 
 #define AIM_CB_CTN_ERROR 0x0001
+#define AIM_CB_CTN_CREATE 0x0008
+#define AIM_CB_CTN_INFO 0x0009
 #define AIM_CB_CTN_DEFAULT 0xffff
 
 /*
  * SNAC Family: Chat Services
  */ 
 #define AIM_CB_CHT_ERROR 0x0001
+#define AIM_CB_CHT_ROOMINFOUPDATE 0x0002
+#define AIM_CB_CHT_USERJOIN 0x0003
+#define AIM_CB_CHT_USERLEAVE 0x0004
+#define AIM_CB_CHT_OUTGOINGMSG 0x0005
+#define AIM_CB_CHT_INCOMINGMSG 0x0006
 #define AIM_CB_CHT_DEFAULT 0xffff
 
 /*
index 395ed5a675d7d375a09ace14cc63d8d2d9949390..64229c8ad6834a6d044d10dbb633f9321a3864d2 100644 (file)
@@ -18,7 +18,7 @@
  *
  * Default: 0  
 */
-#define debug 0 
+#define debug 0
 
 /*
  * Maximum number of connections the library can simultaneously
diff --git a/tcpdumps/randombits.txt b/tcpdumps/randombits.txt
new file mode 100644 (file)
index 0000000..633b368
--- /dev/null
@@ -0,0 +1,728 @@
+
+17/6 (client)
+-----
+
+0100 0010
+7468 6973 6865 7265 6973 616e 616d 6532
+ t h  i s  h e  r e  i s  a n  a m  e 2
+
+17/7 (server)
+----
+
+0a00 3336 3831 3531 3737 3430
+      3 6  8 1  5 1  7 7  4 0
+
+17/2 (client)
+---- 
+0100 0010 
+7468 6973 6865 7265 6973 616e 616d 6532 
+ t h  i s  h e  r e  i s  a n  a m  e 2
+
+0025 0010
+473c 5d77 c795 1c1c 4aba 2c9c 50df 275b 
+ G <  ] w                 ,    P    '   
+
+0003 0032
+414f 4c20 496e 7374 616e 7420 4d65 7373
+ A O  L    I n  s t  a n  t    M e  s s 
+656e 6765 7220 2853 4d29 2c20 7665 7273
+ e n  g e  r    ( S  M )  ,    v e  r s
+696f 6e20 332e 352e 3136 3730 2f57 494e
+ i o  n    3 .  5 .  1 6  7 0  / W  I N 
+3332 
+ 3 2
+
+0016 0002 0004 
+0017 0002 0003 
+0018 0002 0005
+0019 0002 0000 
+001a 0002 0686 
+000e 0002 7573 
+           u s
+000f 0002 656e
+           e n 
+0014 0004 0000 002a
+0009 0002 0015
+
+17/3 (server)
+----
+
+0100 0010 
+5468 6973 4865 7265 4973 414e 616d 6532 
+
+0005 000d
+3230 352e 3138 382e 342e 3233 36
+ 2 0  5 .  1 8  8 .  4 .  2 3  6
+
+0006 0100 c11d 7e73 30d0 db
+        6ea7 88b7 b73d 6ad9 f73f e1e8 6359 dda0
+        4289 7651 9a32 9a27 edca 53c3 2b57 6838
+        5f38 4968 1b83 1ae3 db0f 47db c380 59d1
+        0b00 8f96 42e2 3785 68d8 3547 4c41 7dc9
+        85b0 c4e2 fc7e 63b6 248d 9c33 f899 0801
+        6e45 f038 5ff3 ea1e 2e29 0c4d d48c c902
+        5a1e 8417 2c81 919b fc67 5a82 e1ce 3180
+        f2b9 c3db a3cc c073 b0b2 4964 992f 1693
+        cd0d 817b 4ee6 2665 4a80 dada c301 19a8
+        388c 11d8 1e55 f2dd 0572 43a1 459d 884c
+        2733 0f7f 715d 8364 0c3d 13e0 e4a8 ebeb
+        a181 6b2d 278f cab1 b4ea 0bda f8b7 3d43
+        e4ec f6fb a66f b511 0009 1c1e 12ab 12fd
+        e083 f44b 38bc 7401 2a47 b739 558b 9e96
+        d365 e9ee 03d6 0e4d 3650 c9f8 c728 9c04
+        14c3 1505 0304 abc6 78
+0011 000a
+6d69 6440 6175 6b2e 6378 
+
+0013 0002 0003 
+
+2a04 ce58 0000 00
+
+
+2/4 (client)
+---
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+        2063 6861 7273 6574 3d22 7573 2d61 7363
+        6969 22
+
+0002 0001 00
+
+0003 001f 7465 7874
+        2f61 6f6c 7274 663b 2063 6861 7273 6574
+        3d22 7573 2d61 7363 6969 22
+
+0004 0000 
+
+0005 0060 
+        09 4613 464c 7f11 d182 2244 4553
+        5400 0009 4613 414c 7f11 d182 2244 4553
+        5400 0009 4613 454c 7f11 d182 2244 4553
+        5400 0074 8f24 2062 8711 d182 2244 4553
+        5400 0009 4613 484c 7f11 d182 2244 4553
+        5400 0009 4613 434c 7f11 d182 2244 4553
+        5400 00
+
+
+
+2a02 3764 000a 
+0003 0002 0000 0000 0000 
+
+2a02 3765 005c
+
+0003 0004 0000 0000 0000 
+       06 6d69 6467 6f64 
+       07 4d69 6447 7572 75
+       0a 7467 4161 7264 7661 726b 
+       10 5468 6973 4865 7265 4973 414e 616d 6532 
+       09 6d69 6465 6e64 6961 6e
+       09 7661 7868 6572 6465 72
+       0a 6d6f 7573 6574 726f 7574 
+       07 6177 7761 6969 64
+
+
+
+2a02 3766 001a 
+
+0004 0002 0000 0000 8012 
+       0000 0000 0003 1f40 
+       03e7 03e7 0000 0000
+
+
+
+4/4
+---
+2a02 3767 000a
+0004 0004 0000 0000 8013
+
+9/2
+---
+2a02 3768 000a 
+0009 0002 0000 0000 0000
+
+9/4
+---
+2a02 3769 000e 
+0009 0004 0000 0000 0000 
+       0000 001f 
+
+1/14
+----
+2a02 376a 000e 
+0001 0014 0000 0000 0000 
+       0000 0001 
+
+2a02 376b 00bd 
+0002 0004 0000 0000 0002
+       0001 001f 7465 7874 2f61 6f6c 7274 663b 2063 68
+        6172 7365 743d 2275 732d 6173 6369 6922
+
+        0002 0001 00
+
+       0003 001f 7465 7874 2f61 6f6c 7274 663b 2063 68 
+       6172 7365 743d 2275 732d 6173 6369 6922 
+
+       0004 0000
+       0005 0060
+        0946 1346 4c7f 11d1 8222 4445 5354 0000 
+        0946 1341 4c7f 11d1 8222 4445 5354 0000
+        0946 1345 4c7f 11d1 8222 4445 5354 0000
+        748f 2420 6287 11d1 8222 4445 5354 0000
+        0946 1348 4c7f 11d1 8222 4445 5354 0000
+        0946 1343 4c7f 11d1 8222 4445 5354 0000
+
+
+
+win chat invite
+----------------
+
+4233 3731 3931 5f00  cookie
+
+0002 channel
+
+10 5468 6973 4865 7265 4973 414e 616d 6532  src sn
+
+0000  warnlevel
+0004  num of tlvs that follow
+0001 0002 0011  class
+0004 0002 0000  idletime
+000f 0004 0000 0c7a sessionlen
+0003 0004 386a e35b onsince
+
+0005 0063 
+       0000 3342 3731 3931 5f00 748f 2420 6287 11d1 8222 4445 5354 0000 
+
+000a 0002 0001
+000f 0000 
+000c 001b 4a6f 696e 206d 6520 696e 2074 6869 7320 
+         4275 6464 7920 4368 6174 2e
+2711 001c 0004 1774 6869 7368 6572 6569 7361 6e61 
+         6d65 325f 6368 6174 3538 0000
+
+mac chat invite
+---------------
+4252 432d 0000 0009  cookie
+
+0002 channel
+
+07 4d69 6447 7572 75  src sn
+
+0000 warnlevel
+
+0004 tlvcount
+
+0001 0002 0010 class
+0004 0002 0000 idle
+000f 0004 0000 1978 sessionlen
+0003 0004 3869 93f9 onsince
+
+0005 0071 
+
+0000 5242 432d 0000 0009 748f 2420 6287 11d1 8222 4445 5354 0000
+
+000a 0002 0001 
+2711 0013 0004 0e6d 6964
+        6775 7275 5f63 6861 7434 3700 00
+000f 0000 
+000c 001b 4a6f 696e 206d 6520 696e 2074 6869 7320 
+         4275 6464 7920 4368 6174 2e
+000d 0008 0875 732d 6173 6369 
+000e 0007 0765 6e67 6c69 7320
+
+win voice invite
+----------------
+
+3434 4443 395f 7800  cookie
+
+0002 channel 
+
+10 5468 6973 4865 7265 4973 414e 616d 6532  src sn
+
+0000  warnlevel
+
+0004 tlvcount
+
+0001 0002 0011 class
+
+0004 0002 0000 
+000f 0004 0000 00d8 
+0003 0004 386b 27ab 
+0005 003c 
+0000 3434 4443 395f 7800 0946 1341 4c7f 11d1 8222 4445 5354 0000 
+000a 0002 0001 
+0003 0004 c63c 9612 
+000f 0000 
+2711 0004 0000 0001 
+0004 0004 18dd 0fac 
+00
+
+win voice disconnect
+--------------------
+
+3431 3246 3237 5f00 
+
+0002 
+
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000 
+
+0004 
+
+0001 0002 0011
+0004 0002 0000 
+000f 0004 0000 04ec
+0003 0004 386b 27ab
+0005 0020 
+0001 3134 3246 3237 5f00 0946 1341 4c7f 11d1 8222 4445 5354 0000 
+000b 0002 0001
+00
+
+
+gone away
+---------
+10 5468 6973 4865 7265 4973 414e 616d 6532 
+0000  warnlevel
+0004  tlvcount
+0001 0002 0031 
+0004 0002 0000
+000f 0004 0000 0817 
+0003 0004 386b 27ab 
+61
+
+came back
+---------
+10 5468 6973 4865 7265 4973 414e 616d 6532 
+0000 
+0004
+0001 0002 0011
+0004 0002 00
+        0000 0f00 0400 0008 2600 0300 0438 6b27
+        ab61
+
+2/4 -- going away
+-----------------
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+        2063 6861 7273 6574 3d22 7573 2d61 7363
+        6969 22
+0002 0001 00 
+0003 001f 7465 7874 2f61 6f6c 7274 663b
+       2063 6861 7273 6574 3d22 7573 2d61 7363 
+       6969 22
+
+0004 0025 49
+        2061 6d20 6177 6179 2066 726f 6d20 6d79
+        2063 6f6d 7075 7465 7220 7269 6768 7420
+        6e6f 772e
+
+
+2/4 -- coming back
+------------------
+0001 001f 7465 7874 2f61 6f6c 7274 663b
+        2063 6861 7273 6574 3d22 7573 2d61 7363
+        6969 22
+0002 0001 00
+0003 001f 7465 7874 2f61 6f6c 7274 663b 
+       2063 6861 7273 6574 3d22 7573 2d61 7363 
+       6969 22
+0004 0000 00
+
+getuserinfo with awaymsg 2/6
+------------------------
+06 6d69 6467 6f64
+
+0000 
+0005
+0001 0002 0030 
+0004 0002 0000 
+000f 0004 0000 0044
+0002 0004 374e 69cf
+0003 0004 386b 3aa4
+0001 0021 
+       7465 7874 2f78 2d61 6f6c 7274 663b 2063 
+       6861 7273 6574 3d22 7573 2d61 7363 6969
+       22 
+0002 003a 
+       3c70 3e6d 6661 696d 2d70 7265 322e 322d 
+       6d69 6428 3330 6465 6331 3939 3929 3b20 
+       6c69 6266 6169 6d20 302e 3935 6973 6828 
+       3330 6465 6331 3939 3929
+
+getuserinfo--parameter 3
+------------------------
+
+10 5468 6973 4865 7265 4973 414e 616d 6532
+
+0000 
+0004
+0001 0002 0031
+0004 0002 0000 
+000f 0004 0000 1797 
+0003 0004 386b 27ab
+0003 001f 7465 7874 2f61 6f6c 7274 663b 2063 6861 72 7365 743d 2275 732d 6173
+        6369 6922 0004 0025 4920 616d 2061 7761
+        7920 6672 6f6d 206d 7920 636f 6d70 7574
+        6572 2072 6967 6874 206e 6f77 2e00
+
+chat join -- 1/4
+----------
+000e 
+
+0001 001c 
+
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 3500 00 
+
+0000 0000
+
+redirect -- 1/5
+---------------
+000d 0002 000e  service id
+0005 000c 3230 352e 3138 382e 342e 3636  IP
+0006 0100 cookie
+        e2df 8c0b 8caf
+        adc3 3996 0883 d2a0 1af6 ea29 404c 1935
+        d364 d4cf 9c0a 0ad9 c3d7 ac7c 5f5d 2c57
+        cb3e 00a4 4deb 62e0 9d57 8dc6 9a6b 2916
+        15b8 d496 d735 7d28 0323 c931 795e b2cf
+        459d db9b c726 5467 7170 fd55 65ae 04df
+        fd94 979e f47a 1c9d 2c60 56bb 41a3 6778
+        6c8c 8b97 2397 e187 0541 a5cc 9927 b707
+        8340 3c42 e40d c070 65c4 c2c0 88c1 3af1
+        ec10 eda8 9875 89ec 2a17 eee6 e7dd 2a74
+        82cd 6b6d cb97 af9a c541 8b1b 5c9f f4e4
+        f858 93b3 5cea ff78 b816 cc37 c721 0097
+        c204 4fbb 8e66 ec3d 94ac 964e cb1b 2c78
+        a39e 6c2b 75f2 1acd ceb2 d529 2c82 81e8
+        ef84 b382 5d7d 90d2 7f31 12ac 35b6 cf51
+        a296 28fa 2623 0997 1e1b 636b 4154 d08f
+        c900 2137 3fa4 1a09 d1bc
+
+(open new connection)
+
+(send cookie on channel one, prefixed by 0000 0001 then type 6 TLV)
+
+(get server ready -- supports services 0001 and 000e)
+
+set client versions (client -- 1/17)
+-------------------
+000e 0001 
+0001 0003
+
+server versions (server 1/18)
+---------------
+0001 0003 
+000e 0001
+
+(request rate info 1/6 from client)
+
+(never gets rate info?)
+
+rate info ack (client -- 1/8)
+-------------
+0001 
+0002 
+0003 
+0004 
+0005
+
+send chat invite (client 4/6 -- on BOS connection)
+----------------
+3033 4136 3445 5f00  cookie
+
+0002  channel
+
+06 6d69 6467 6f64
+0005 0063 
+       0000 3330 4136 3445 5f00 74
+        8f24 2062 8711 d182 2244 4553 5400 00
+
+        000a 0002 0001 
+       000f 0000 
+       000c 001b 
+               4a6f 696e 206d 6520 69 6e20 7468 6973 2042 7564
+               6479 2043 6861 742e 
+       2711 001c 
+               0004 17 7468 6973 6865 7265 6973 616e 616d 6532 
+               5f63 6861 7438 3500 00
+
+client ready (1/2)
+------------
+000e 0001 
+0004 0001 
+0001 0003 
+0004 0686
+
+
+users joined -- e/3
+------------
+10 5468 6973 4865 7265 4973 414e 616d 6532  joining sn
+0000 warnlevel
+0004 tlvcount
+0001 0002 0011 class
+0002 0004 3355 6800
+0003 0004 386b e770
+0004 0002 0000
+
+user joined -- e/3  --another sample
+------------------------------------
+09 7661 7868 6572 6465 72
+0000 warnlevel
+0004
+0001 0002 0011 
+0002 0004 3566 7a92 
+0003 0004 386c 0d5a 
+0004 0002 0000 
+10 5468 6973 4865 7265 4973 414e 616d 6532 
+0000 
+0004 
+0001 0002 0011 
+0002 0004 3355 6800
+0003 0004 386b e770
+0004 0002 0028
+
+info update -- e/2 --another sample
+-----------------------------------
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 35 0000 
+02 detail level
+
+0009 
+
+006a 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+006f 0002 0002 
+
+0073 005b 
+       09 7661 7868 6572 6465 72
+               0000
+               0004
+               0001 0002 0011
+               0002 0004 3566 7a92
+               0003 0004 386c 0d5a
+               0004 0002 0000 
+       10 5468 6973 4865 7265 4973 414e 616d 6532 
+               0000 
+               0004
+               0001 0002 0011 
+               0002 0004 3355 6800 
+               0003 0004 386b e770 
+               0004 0002 0028 
+00c9 0002 0011 
+00ca 0004 386b e76f 
+00d1 0002 0200
+00d2 0002 0018 
+00d3 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+00d5 0001 02
+
+room info update -- e/2
+----------------
+0004 17 7468 6973 6865 7265 6973 616e 616d 6532 5f63 6861 7438 35 0000
+02 detail level
+
+0009 tlvcount
+
+006a 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+006f 0002 0001 
+0073 0031 
+       10 5468 6973 4865 7265 4973 414e 616d 6532 sn
+       0000  warnlevel
+       0004  tlvcount
+       0001 0002 0011 class
+        0002 0004 3355 6800 
+       0003 0004 386b e770
+        0004 0002 0000 
+       00c9 0002 0011 
+       00ca 0004 386b e76f 
+       00d1 0002 0200 
+       00d2 0002 0018
+        00d3 0017 5468 6973 4865 7265 4973 414e 616d 6532 2043 6861 7438 35
+       00d5 0001 02
+
+users left -- e/4
+----------
+07 4d69 6447 7572 75
+0000 
+0001 
+0001 0002 0000
+
+
+incoming message -- e/6
+-----------------
+
+3330 3945 3446 0000 
+
+0003 
+
+0003 0031 
+       10 5468 6973 4865 7265 4973 414e 616d 6532
+       0000    
+       0004 
+       0001 0002 0011 
+       0002 0004 3355 6800
+       0003 0004 386b e770
+       0004 0002 0000 
+0001 0000 
+0005 003f 
+       0001 003b 3c48 544d 4c
+        3e3c 424f 4459 2042 4743 4f4c 4f52 3d22
+        2366 6666 6666 6622 3e3c 464f 4e54 3e68
+        693c 2f46 4f4e 543e 3c2f 424f 4459 3e3c
+        2f48 544d 4c3e
+
+outgoing message -- e/5
+----------------
+3330 3945 3446 0000 
+
+0003 
+
+0001 0000 
+0006 0000 
+0005 003f 
+       0001 003b 
+               3c48 544d 4c3e 3c42 4f44 5920 4247 434f 4c4f 523d 2223
+               6666 6666 6666 223e 3c46 4f4e 543e 6869
+               3c2f 464f 4e54 3e3c 2f42 4f44 593e 3c2f
+               4854 4d4c 3e00
+
+
+
+
+CHATNAV
+--------
+
+
+
+request service: 1/4 -- data=0x000d
+
+gets normal redirect 1/5
+
+sends cookie
+
+gets server ready (supports 1, d)
+
+set client versions {{d,1}, {1,3}}
+
+gets server versions {{1,3}, {d,1}}
+
+request rate info -- 1/6
+
+rate info ack -- 1/8
+
+sets client ready -- 1/2 (supports d, 1, 4, 1, 1, 3, 4, 0686)
+
+request chat rights -- d/2 -- no data
+
+gets nav information -- d/9
+--------------------
+0002 0001 03 concurrent max rooms
+0003 006d    EXCHANGE DESC -- EXCHANGE 4
+       0004 exchange
+       000d 0003 0001 03                                       unknown
+       0004 0002 001e                                          unknown
+       00c9 0002 0011                                          unknown
+       00ca 0004 3842 4ca3                                     
+       00d0 0002 0003                                          unknown
+       00d1 0002 0200                                          maxmsglen?
+       00d2 0002 0018                                          unknown
+       00d3 0011 6169 6d20 7072 6976 6174 6520 6368 6174 73    exch name
+                       aim private chats
+       00d5 0001 02                                            unknown
+       00d6 0008 7573 2d61 7363 6969                           charset
+       00d7 0002 656e                                          lang
+       00d8 0008 7573 2d61 7363 6969                           charset
+        00d9 0002 656e                                         lang
+0003 006f   EXCHANGE DESC -- EXCHANGE 5
+       0005 
+       000d 0003 0001 03
+       0004 0002 001e
+       00c9 0002 0015 
+       00ca 0004 3842 4ca3
+       00d0 0002 0003
+       00d1 0002 0200
+       00d2 0002 0018
+       00d3 0013 616f 6c20 636f 6d6d 756e 6974 7920 6368 
+                 6174 73
+                       aol community chats
+       00d5 0001 02
+       00d6 0008 7573 2d61 7363 6969
+       00d7 0002 656e 
+       00d8 0008 7573 2d61 7363 6969
+       00d9 0002 656e
+0003 0075   EXCHANGE DESC -- EXCHANGE 6
+       0006 
+       000d 0003 0001 03                                       unknown
+       0004 0002 001e                                          unknown
+       00c9 0002 0015                                          unknown
+       00ca 0004 3842 4ca3                                     cookie?
+       00d0 0002 0003                                          mxchan?
+       00d1 0002 0200                                          msgsz?
+       00d2 0002 0018                                          unknown
+       00d3 0019 6e65 7463 656e 7465 7220 636f 6d6d 756e 
+                 6974 7920 6368 6174 73 
+                       netcenter community chats       exchange name
+       00d5 0001 02                                            unknown
+       00d6 0008 7573 2d61 7363 6969                           charset
+       00d7 0002 656e                                          lang
+       00d8 0008 7573 2d61 7363 6969                           charset
+       00d9 0002 656e                                          lang
+
+
+create room -- d/8
+------------------
+0004 06 69 6e76 6974 65 ffff  roominfo (cookie: invite)
+01 detail level
+0001  tlvcount
+00d3 000e 6177 7761 6969 6420 4368 6174 3235
+               awwaiid Chat25
+
+new room info -- d/9 (need to identify somehow!)
+-------------
+0004 0059 
+       0004 0e 6177 7761 6969 645f 6368 6174 3235 0000  roominfo
+       02 detail level
+       0007 
+       006a 000e 6177 7761 6969 6420 4368 6174 3235 
+       00c9 0002 0011 
+       00ca 0004 386c 72c5 
+       00d1 0002 0200
+        00d2 0002 0018 
+       00d3 000e 6177 7761 6969 6420 4368 6174 3235 
+       00d5 0001 02
+
+
+outgoing invitation -- 4/6
+--------------------
+3131 3538 3446 4100  cookie
+0002  channel
+07 4d69 6447 7572 75  destsn
+0005 0063 
+       0000 
+       3131 3538 3446 4100
+        748f 2420 6287 11d1 8222 4445 5354 0000
+
+        000a 0002 0001 
+       000f 0000 
+       000c 001b 
+               4a6f 696e 206d 6520 696e 2074 6869 7320 
+               4275 6464 7920 4368 6174 2e
+                       
+       
+       2711 001c 
+               0004 17 
+                       7468 6973 6865 7265 6973 616e 616d 6532 
+                       5f63 6861 7438 35 
+                    0000 
+
+
+invitation accepted
+-------------------
+3131 3538 3446 4100 
+
+0002 
+10 5468 6973 4865 7265 4973 414e 616d 6532
+0000 
+0004 
+0001 0002 0011
+0004 0002 0000 
+000f 0004 0000 001e
+0003 0004 386f 2026
+0005 001a
+       0002 3131 3538 3446 4100 748f 24 2062 8711
+        d182 2244 4553 5400 0000
index f54667f87ca6788c1922bfb72fecb35ee610ccfb..1456a0f99c8dded2b897825c442ecbcb8f3dca44 100644 (file)
@@ -49,7 +49,6 @@
 int faimtest_parse_oncoming(struct aim_session_t *, struct command_rx_struct *, ...);
 int faimtest_parse_offgoing(struct aim_session_t *, struct command_rx_struct *, ...);
 int faimtest_parse_login_phase3d_f(struct aim_session_t *, struct command_rx_struct *, ...);
-int faimtest_auth_error(struct aim_session_t *, struct command_rx_struct *, ...);
 int faimtest_parse_authresp(struct aim_session_t *, struct command_rx_struct *, ...);
 int faimtest_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *command, ...);
 int faimtest_parse_userinfo(struct aim_session_t *, struct command_rx_struct *command, ...);
@@ -60,6 +59,11 @@ int faimtest_serverready(struct aim_session_t *, struct command_rx_struct *comma
 int faimtest_parse_misses(struct aim_session_t *, struct command_rx_struct *command, ...);
 int faimtest_parse_motd(struct aim_session_t *, struct command_rx_struct *command, ...);
 int faimtest_parse_login(struct aim_session_t *, struct command_rx_struct *command, ...);
+int faimtest_chatnav_info(struct aim_session_t *, struct command_rx_struct *command, ...);
+int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 
 static char *screenname,*password;
 
@@ -175,8 +179,24 @@ int faimtest_serverready(struct aim_session_t *sess, struct command_rx_struct *c
       aim_bos_setgroupperm(sess, command->conn, 0x1f);
       fprintf(stderr, "faimtest: done with BOS ServerReady\n");
       break;
+
     case AIM_CONN_TYPE_CHATNAV:
       fprintf(stderr, "faimtest: chatnav: got server ready\n");
+      aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, faimtest_chatnav_info, 0);
+      aim_bos_reqrate(sess, command->conn);
+      aim_bos_ackrateresp(sess, command->conn);
+      aim_chatnav_clientready(sess, command->conn);
+      aim_chatnav_reqrights(sess, command->conn);
+
+      break;
+    case AIM_CONN_TYPE_CHAT:
+      aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
+      aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
+      aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
+      aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
+      aim_bos_reqrate(sess, command->conn);
+      aim_bos_ackrateresp(sess, command->conn);
+      aim_chat_clientready(sess, command->conn);
       break;
     default:
       fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
@@ -207,7 +227,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
   char *cookie;
 
   /* this is the new buddy list */
-  char buddies[] = "Buddy1&Buddy2&";
+  char buddies[] = "Buddy1&Buddy2&ThisHereIsAName2&";
   /* this is the new profile */
   char profile[] = "Hello";  
 
@@ -215,8 +235,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
   serviceid = va_arg(ap, int);
   ip = va_arg(ap, char *);
   cookie = va_arg(ap, char *);
-  va_end(ap);
-
   switch(serviceid)
     {
     case 0x0005: /* Advertisements */
@@ -228,7 +247,7 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
 
       /* send the buddy list and profile (required, even if empty) */
       aim_bos_setbuddylist(sess, command->conn, buddies);
-      aim_bos_setprofile(sess, command->conn, profile);
+      aim_bos_setprofile(sess, command->conn, profile, NULL);
 
       /* send final login command (required) */
       aim_bos_clientready(sess, command->conn); /* tell BOS we're ready to go live */
@@ -259,25 +278,37 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
            fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
            return 1;
          }
+#if 0
        aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
        aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
+#endif
+       aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
        aim_auth_sendcookie(sess, tstconn, cookie);
        fprintf(stderr, "\achatnav: connected\n");
       }
       break;
     case 0x000e: /* Chat */
       {
-#if 0
+       char *roomname = NULL;
        struct aim_conn_t *tstconn = NULL;
+
+       roomname = va_arg(ap, char *);
+
        tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip);
        if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
          {
            fprintf(stderr, "faimtest: unable to connect to chat server\n");
            return 1;
-         }
-       aim_auth_sendcookie(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHAT), cookie);
-       fprintf(stderr, "\achat: connected\n");
-#endif
+         }             
+       printf("faimtest: chat: connected\n");
+
+       /*
+        * We must do this to attach the stored name to the connection!
+        */
+       aim_chat_attachname(tstconn, roomname);
+
+       aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, faimtest_serverready, 0);
+       aim_auth_sendcookie(sess, tstconn, cookie);
       }
       break;
     default:
@@ -285,30 +316,10 @@ int faimtest_handleredirect(struct aim_session_t *sess, struct command_rx_struct
       /* dunno */
     }
 
-  return 1;
-}
-
-#if 0
-int faimtest_auth_error(struct aim_session_t *sess, struct command_rx_struct *command, ...)
-{
-  va_list ap;
-  char *errorurl;
-  short errorcode;
-
-  va_start(ap, command);
-  printf("Screen name: %s\n", sess->logininfo.screen_name);
-  errorurl = va_arg(ap, char *);
-  printf("Error URL: %s\n", errorurl);
-  errorcode = va_arg(ap, short);
-  printf("Error code: 0x%02x\n", errorcode);
   va_end(ap);
 
-  aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
-  exit(0);
-  
-  return 0;
+  return 1;
 }
-#endif
 
 int faimtest_parse_authresp(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
@@ -503,12 +514,23 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str
              printf("faimtest: icbm: sending response\n");
              aim_send_im(sess, command->conn, userinfo->sn, 0, "Good day to you too.");
            }
-#if 0
-         else if (!strncmp(tmpstr, "joinchat", 8))
+         else if (!strncmp(tmpstr, "open chatnav", 12))
            {
-             aim_chat_join(sess, command->conn, "GoodDay");
+             aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
+             //aim_chat_join(sess, command->conn, "thishereisaname2_chat85");
            }
-#endif
+         else if (!strncmp(tmpstr, "create", 6))
+           {
+             aim_chatnav_createroom(sess, aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), "WorldDomination", 0x0004);
+           }
+         else if (!strncmp(tmpstr, "close chatnav", 13))
+           aim_conn_close(aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV));
+         else if (!strncmp(tmpstr, "join", 4))
+           {
+             aim_chat_join(sess, command->conn, 0x0004, "worlddomination");
+           }
+         else if (!strncmp(tmpstr, "leave", 5))
+           aim_chat_leaveroom(sess, "worlddomination");
          else 
            {
 #if 0
@@ -522,43 +544,74 @@ int faimtest_parse_incoming_im(struct aim_session_t *sess, struct command_rx_str
        }
     }
   /*
-   * Channel 2: Chat Invitation
+   * Channel 2: Rendevous Request
    */
   else if (channel == 2)
     {
       struct aim_userinfo_s *userinfo;
-      char *roomname,*msg,*encoding,*lang;
-      u_short exchange, instance;
+      int rendtype = 0;
 
-      userinfo = va_arg(ap, struct aim_userinfo_s *);
-      roomname = va_arg(ap, char *);
-      msg = va_arg(ap, char *);
-      encoding = va_arg(ap, char *);
-      lang = va_arg(ap, char *);
-      exchange = va_arg(ap, u_short);
-      instance = va_arg(ap, u_short);
-      va_end(ap);
-      
-      printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
-      printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
-      printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
-      if (userinfo->class & 0x0010)
-       printf("(FREE) ");
-      if (userinfo->class & 0x0001)
-       printf("(TRIAL) ");
-      if (userinfo->class & 0x0004)
-       printf("(AOL) ");
-      printf("\n");
-      /* we dont get membersince on chat invites! */
-      printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
-      printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
-      
-      printf("faimtest: chat invitation: message = %s\n", msg);
-      printf("faimtest: chat invitation: room name = %s\n", roomname);
-      printf("faimtest: chat invitation: encoding = %s\n", encoding);
-      printf("faimtest: chat invitation: language = %s\n", lang);
-      printf("faimtest: chat invitation: exchange = 0x%04x\n", exchange);
-      printf("faimtest: chat invitation: instance = 0x%04x\n", instance);
+      rendtype = va_arg(ap, int);
+      if (rendtype == 0)
+       {
+         char *msg,*encoding,*lang;
+         struct aim_chat_roominfo *roominfo;
+         
+         userinfo = va_arg(ap, struct aim_userinfo_s *);
+         roominfo = va_arg(ap, struct aim_chat_roominfo *);
+         msg = va_arg(ap, char *);
+         encoding = va_arg(ap, char *);
+         lang = va_arg(ap, char *);
+         va_end(ap);
+         
+         printf("faimtest: chat invitation: source sn = %s\n", userinfo->sn);
+         printf("faimtest: chat invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+         printf("faimtest: chat invitation: \tclass = 0x%04x ", userinfo->class);
+         if (userinfo->class & 0x0010)
+           printf("(FREE) ");
+         if (userinfo->class & 0x0001)
+           printf("(TRIAL) ");
+         if (userinfo->class & 0x0004)
+           printf("(AOL) ");
+         printf("\n");
+         /* we dont get membersince on chat invites! */
+         printf("faimtest: chat invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+         printf("faimtest: chat invitation: \tidletime = 0x%04x\n", userinfo->idletime);
+         
+         printf("faimtest: chat invitation: message = %s\n", msg);
+         printf("faimtest: chat invitation: room name = %s\n", roominfo->name);
+         printf("faimtest: chat invitation: encoding = %s\n", encoding);
+         printf("faimtest: chat invitation: language = %s\n", lang);
+         printf("faimtest: chat invitation: exchange = 0x%04x\n", roominfo->exchange);
+         printf("faimtest: chat invitation: instance = 0x%04x\n", roominfo->instance);
+         printf("faimtest: chat invitiation: autojoining %s...\n", roominfo->name);
+         /*
+          * Automatically join room...
+          */ 
+         aim_chat_join(sess, command->conn, 0x0004, roominfo->name);
+       }       
+      else if (rendtype == 1)
+       {
+         userinfo = va_arg(ap, struct aim_userinfo_s *);
+         va_end(ap);
+         
+         printf("faimtest: voice invitation: source sn = %s\n", userinfo->sn);
+         printf("faimtest: voice invitation: \twarnlevel = 0x%04x\n", userinfo->warnlevel);
+         printf("faimtest: voice invitation: \tclass = 0x%04x ", userinfo->class);
+         if (userinfo->class & 0x0010)
+           printf("(FREE) ");
+         if (userinfo->class & 0x0001)
+           printf("(TRIAL) ");
+         if (userinfo->class & 0x0004)
+           printf("(AOL) ");
+         printf("\n");
+         /* we dont get membersince on chat invites! */
+         printf("faimtest: voice invitation: \tonlinesince = %lu\n", userinfo->onlinesince);
+         printf("faimtest: voice invitation: \tidletime = 0x%04x\n", userinfo->idletime);
+         
+       }
+      else
+       printf("faimtest: icbm: unknown rendtype (%d)\n", rendtype);
     }
   else
     printf("faimtest does not support channels > 2 (chan = %02x)\n", channel);
@@ -602,7 +655,15 @@ int faimtest_parse_oncoming(struct aim_session_t *sess, struct command_rx_struct
   userinfo = va_arg(ap, struct aim_userinfo_s *);
   va_end(ap);
 
-  printf("\n%s is now online\n", userinfo->sn);
+  printf("\n%s is now online (class: %04x = %s%s%s%s%s%s%s%s)\n", userinfo->sn, userinfo->class,
+        (userinfo->class&AIM_CLASS_TRIAL)?" TRIAL":"",
+        (userinfo->class&AIM_CLASS_UNKNOWN2)?" UNKNOWN2":"",
+        (userinfo->class&AIM_CLASS_AOL)?" AOL":"",
+        (userinfo->class&AIM_CLASS_UNKNOWN4)?" UNKNOWN4":"",
+        (userinfo->class&AIM_CLASS_FREE)?" FREE":"",
+        (userinfo->class&AIM_CLASS_AWAY)?" AWAY":"",
+        (userinfo->class&AIM_CLASS_UNKNOWN40)?" UNKNOWN40":"",
+        (userinfo->class&AIM_CLASS_UNKNOWN80)?" UNKNOWN80":"");
 
   return 1;
 }
@@ -694,3 +755,143 @@ int faimtest_parse_login(struct aim_session_t *sess, struct command_rx_struct *c
   return 1;
 }
 #endif
+
+int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  struct aim_userinfo_s *userinfo;
+  int count = 0, i = 0;
+  
+  va_start(ap, command);
+  count = va_arg(ap, int);
+  userinfo = va_arg(ap, struct aim_userinfo_s *);
+  va_end(ap);
+
+  printf("faimtest: chat: %s:  New occupants have joined:\n", (char *)command->conn->priv);
+  while (i < count)
+    printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+  return 1;
+}
+
+int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  struct aim_userinfo_s *userinfo;
+  int count = 0, i = 0;
+  
+  va_start(ap, command);
+  count = va_arg(ap, int);
+  userinfo = va_arg(ap, struct aim_userinfo_s *);
+  va_end(ap);
+
+  printf("faimtest: chat: %s:  Some occupants have left:\n", (char *)command->conn->priv);
+  while (i < count)
+    printf("faimtest: chat: %s: \t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+  return 1;
+}
+
+int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  struct aim_userinfo_s *userinfo;
+  struct aim_chat_roominfo *roominfo;
+  char *roomname;
+  int usercount,i;
+  char *roomdesc;
+
+  va_start(ap, command);
+  roominfo = va_arg(ap, struct aim_chat_roominfo *);
+  roomname = va_arg(ap, char *);
+  usercount= va_arg(ap, int);
+  userinfo = va_arg(ap, struct aim_userinfo_s *);
+  roomdesc = va_arg(ap, char *);
+  va_end(ap);
+
+  printf("faimtest: chat: %s:  info update:\n", (char *)command->conn->priv);
+  printf("faimtest: chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", 
+        (char *)command->conn->priv,
+        roominfo->exchange,
+        roominfo->name,
+        roominfo->instance);
+  printf("faimtest: chat: %s:  \tRoomname: %s\n", (char *)command->conn->priv, roomname);
+  printf("faimtest: chat: %s:  \tRoomdesc: %s\n", (char *)command->conn->priv, roomdesc);
+  printf("faimtest: chat: %s:  \tOccupants: (%d)\n", (char *)command->conn->priv, usercount);
+  
+  i = 0;
+  while (i < usercount)
+    printf("faimtest: chat: %s:  \t\t%s\n", (char *)command->conn->priv, userinfo[i++].sn);
+
+  return 1;
+}
+
+int faimtest_chat_incomingmsg(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  va_list ap;
+  struct aim_userinfo_s *userinfo;
+  char *msg;
+  char tmpbuf[1152];
+  va_start(ap, command);
+  userinfo = va_arg(ap, struct aim_userinfo_s *);      
+  msg = va_arg(ap, char *);
+  va_end(ap);
+
+  printf("faimtest: chat: %s: incoming msg from %s: %s\n", (char *)command->conn->priv, userinfo->sn, msg);
+
+  /*
+   * Do an echo for testing purposes.  But not for ourselves ("oops!")
+   */
+  if (strcmp(userinfo->sn, sess->logininfo.screen_name) != 0)
+    {
+      sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg);
+      aim_chat_send_im(sess, command->conn, tmpbuf);
+    }
+
+  return 1;
+}
+
+int faimtest_chatnav_info(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  u_short type;
+  va_list ap;
+
+  ap = va_start(ap, command);
+  type = va_arg(ap, u_short);
+
+  switch(type)
+    {
+    case 0x0002:
+      {
+       int maxrooms;
+       struct aim_chat_exchangeinfo *exchanges;
+       int exchangecount,i = 0;
+       
+       maxrooms = va_arg(ap, u_char);
+       exchangecount = va_arg(ap, int);
+       exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
+       va_end(ap);
+
+       printf("faimtest: chat info: Chat Rights:\n");
+       printf("faimtest: chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
+       
+       printf("faimtest: chat info: \tExchange List: (%d total)\n", exchangecount);
+       while (i < exchangecount)
+         {
+           printf("faimtest: chat info: \t\t%x: %s (%s/%s)\n", 
+                  exchanges[i].number, 
+                  exchanges[i].name,
+                  exchanges[i].charset1,
+                  exchanges[i].lang1);
+           i++;
+         }
+       
+      }
+      break;
+    default:
+      va_end(ap);
+      printf("faimtest: chatnav info: unknown type (%04x)\n", type);
+    }
+  return 1;
+}
This page took 0.149883 seconds and 5 git commands to generate.