]> andersk Git - libfaim.git/blobdiff - src/info.c
- Mon Sep 3 18:48:26 PDT 2001
[libfaim.git] / src / info.c
index a36a7f52525f522d457cd9a8a1cbf56d784836b8..5ae956dd435eb66a4b3767b89328a25a67a68a9b 100644 (file)
@@ -2,7 +2,7 @@
  * aim_info.c
  *
  * The functions here are responsible for requesting and parsing information-
- * gathering SNACs.  
+ * gathering SNACs.  Or something like that. 
  *
  */
 
 #include <aim.h>
 
 struct aim_priv_inforeq {
-  char sn[MAXSNLEN+1];
-  unsigned short infotype;
+       char sn[MAXSNLEN+1];
+       fu16_t infotype;
 };
 
-faim_export int aim_getinfo(struct aim_session_t *sess,
-                           struct aim_conn_t *conn, 
-                           const char *sn,
-                           unsigned short infotype)
+faim_export int aim_getinfo(aim_session_t *sess, aim_conn_t *conn, const char *sn, fu16_t infotype)
 {
-  struct command_tx_struct *newpacket;
-  struct aim_priv_inforeq privdata;
-  int i = 0;
+       struct aim_priv_inforeq privdata;
+       aim_frame_t *fr;
+       aim_snacid_t snacid;
 
-  if (!sess || !conn || !sn)
-    return -1;
+       if (!sess || !conn || !sn)
+               return -EINVAL;
 
-  if ((infotype != AIM_GETINFO_GENERALINFO) &&
-      (infotype != AIM_GETINFO_AWAYMESSAGE))
-    return -1;
+       if ((infotype != AIM_GETINFO_GENERALINFO) && (infotype != AIM_GETINFO_AWAYMESSAGE))
+               return -EINVAL;
 
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 12+1+strlen(sn))))
-    return -1;
+       if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12+1+strlen(sn))))
+               return -ENOMEM;
 
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
-
-  i += aimutil_put16(newpacket->data+i, infotype);
-  i += aimutil_put8(newpacket->data+i, strlen(sn));
-  i += aimutil_putstr(newpacket->data+i, sn, strlen(sn));
-
-  newpacket->lock = 0;
-  aim_tx_enqueue(sess, newpacket);
+       strncpy(privdata.sn, sn, sizeof(privdata.sn));
+       privdata.infotype = infotype;
+       snacid = aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq));
+       
+       aim_putsnac(&fr->data, 0x0002, 0x0005, 0x0000, snacid);
+       aimbs_put16(&fr->data, infotype);
+       aimbs_put8(&fr->data, strlen(sn));
+       aimbs_putraw(&fr->data, sn, strlen(sn));
 
-  strncpy(privdata.sn, sn, sizeof(privdata.sn));
-  privdata.infotype = infotype;
-  aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq));
+       aim_tx_enqueue(sess, fr);
 
-  return 0;
+       return 0;
 }
 
 /*
  * Capability blocks.  
  */
 static const struct {
-  unsigned short flag;
-  unsigned char data[16];
+       unsigned short flag;
+       unsigned char data[16];
 } aim_caps[] = {
-  
-  {AIM_CAPS_BUDDYICON,
-   {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-  
-  {AIM_CAPS_VOICE,
-   {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  {AIM_CAPS_IMIMAGE,
-   {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-  
-  {AIM_CAPS_CHAT,
-   {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-  
-  {AIM_CAPS_GETFILE,
-   {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  {AIM_CAPS_SENDFILE,
-   {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  {AIM_CAPS_SAVESTOCKS,
-   {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  /*
-   * Indeed, there are two of these.  The former appears
-   * to be correct, but in some versions of winaim, the
-   * second one is set.  Either they forgot to fix endianness,
-   * or they made a typo. It really doesn't matter which.
-   */
-  {AIM_CAPS_GAMES,
-   {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-  {AIM_CAPS_GAMES2,
-   {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-    0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  {AIM_CAPS_SENDBUDDYLIST,
-   {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
-    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-
-  {AIM_CAPS_LAST}
+
+       {AIM_CAPS_BUDDYICON,
+        {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, 
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_VOICE,
+        {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, 
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_IMIMAGE,
+        {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, 
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_CHAT,
+        {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_GETFILE,
+        {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_SENDFILE,
+        {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, 
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_SAVESTOCKS,
+        {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       /*
+        * Indeed, there are two of these.  The former appears to be correct, 
+        * but in some versions of winaim, the second one is set.  Either they 
+        * forgot to fix endianness, or they made a typo. It really doesn't 
+        * matter which.
+        */
+       {AIM_CAPS_GAMES,
+        {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+       {AIM_CAPS_GAMES2,
+        {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
+         0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_SENDBUDDYLIST,
+        {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
+         0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+       {AIM_CAPS_LAST}
 };
 
-faim_internal unsigned short aim_getcap(struct aim_session_t *sess, unsigned char *capblock, int buflen)
+/*
+ * This still takes a length parameter even with a bstream because capabilities
+ * are not naturally bounded.
+ * 
+ */
+faim_internal fu16_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len)
 {
-  unsigned short flags;
-  int i;
-  int offset = 0;
-  int identified;
+       fu16_t flags = 0;
+       int offset;
+
+       for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) {
+               fu8_t *cap;
+               int i, identified;
 
-  for (offset = 0, flags = 0; offset < buflen; offset += 0x0010) {
+               cap = aimbs_getraw(bs, 0x10);
 
-    for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {
+               for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {
 
-      if (memcmp(&aim_caps[i].data, capblock+offset, 0x10) == 0) {
-       flags |= aim_caps[i].flag;
-       identified++;
-       break; /* should only match once... */
-      }
+                       if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
+                               flags |= aim_caps[i].flag;
+                               identified++;
+                               break; /* should only match once... */
 
-    }
+                       }
+               }
 
-    if (!identified)
-      faimdprintf(sess, 0, "unknown capability!\n");
+               if (!identified)
+                       faimdprintf(sess, 0, "unknown capability!\n");
 
-  }
+               free(cap);
+       }
 
-  return flags;
+       return flags;
 }
 
-faim_internal int aim_putcap(unsigned char *capblock, int buflen, unsigned short caps)
+faim_internal int aim_putcap(aim_bstream_t *bs, fu16_t caps)
 {
-  int offset, i;
+       int i;
 
-  if (!capblock)
-    return 0;
+       if (!bs)
+               return -EINVAL;
 
-  for (i = 0, offset = 0; 
-       !(aim_caps[i].flag & AIM_CAPS_LAST) && (offset < buflen); i++) {
+       for (i = 0; aim_bstream_empty(bs); i++) {
 
-    if (caps & aim_caps[i].flag) {
-      memcpy(capblock+offset, aim_caps[i].data, 16);
-      offset += 16;
-    }
+               if (aim_caps[i].flag == AIM_CAPS_LAST)
+                       break;
 
-  }
+               if (caps & aim_caps[i].flag)
+                       aimbs_putraw(bs, aim_caps[i].data, 0x10);
 
-  return offset;
+       }
+
+       return 0;
 }
 
 /*
- * AIM is fairly regular about providing user info.  This
- * is a generic routine to extract it in its standard form.
+ * AIM is fairly regular about providing user info.  This is a generic 
+ * routine to extract it in its standard form.
  */
-faim_internal int aim_extractuserinfo(struct aim_session_t *sess, unsigned char *buf, struct aim_userinfo_s *outinfo)
+faim_internal int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, struct aim_userinfo_s *outinfo)
 {
-  int i = 0;
-  int tlvcnt = 0;
-  int curtlv = 0;
-  int tlv1 = 0;
-  u_short curtype;
-  int lastvalid;
-
-
-  if (!buf || !outinfo)
-    return -1;
-
-  /* Clear out old data first */
-  memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
-
-  /*
-   * Screen name.    Stored as an unterminated string prepended
-   *                 with an unsigned byte containing its length.
-   */
-  if (buf[i] < MAXSNLEN) {
-    memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
-    outinfo->sn[(int)buf[i]] = '\0';
-  } else {
-    memcpy(outinfo->sn, &(buf[i+1]), MAXSNLEN-1);
-    outinfo->sn[MAXSNLEN] = '\0';
-  }
-  i = 1 + (int)buf[i];
-
-  /*
-   * Warning Level.  Stored as an unsigned short.
-   */
-  outinfo->warnlevel = aimutil_get16(&buf[i]);
-  i += 2;
-
-  /*
-   * TLV Count.      Unsigned short representing the number of 
-   *                 Type-Length-Value triples that follow.
-   */
-  tlvcnt = aimutil_get16(&buf[i]);
-  i += 2;
-
-  /* 
-   * Parse out the Type-Length-Value triples as they're found.
-   */
-  while (curtlv < tlvcnt) {
-    lastvalid = 1;
-    curtype = aimutil_get16(&buf[i]);
-    switch (curtype) {
-      /*
-       * Type = 0x0000: Invalid
-       *
-       * AOL has been trying to throw these in just to break us.
-       * They're real nice guys over there at AOL.  
-       *
-       * Just skip the two zero bytes and continue on. (This doesn't
-       * count towards tlvcnt!)
-       */
-    case 0x0000:
-      lastvalid = 0;
-      i += 2;
-      break;
-
-      /*
-       * Type = 0x0001: User flags
-       * 
-       * Specified as any of the following bitwise ORed together:
-       *      0x0001  Trial (user less than 60days)
-       *      0x0002  Unknown bit 2
-       *      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,
-       * as the others may not be something we want.
-       *
-       */
-    case 0x0001:
-      if (tlv1) /* use only the first */
-       break;
-      outinfo->flags = aimutil_get16(&buf[i+4]);
-      tlv1++;
-      break;
-      
-      /*
-       * Type = 0x0002: Member-Since date. 
-       *
-       * The time/date that the user originally
-       * registered for the service, stored in 
-       * time_t format
-       */
-    case 0x0002: 
-      outinfo->membersince = aimutil_get32(&buf[i+4]);
-      break;
-      
-      /*
-       * Type = 0x0003: On-Since date.
-       *
-       * The time/date that the user started 
-       * their current session, stored in time_t
-       * format.
-       */
-    case 0x0003:
-      outinfo->onlinesince = aimutil_get32(&buf[i+4]);
-      break;
-      
-      /*
-       * Type = 0x0004: Idle time.
-       *
-       * Number of seconds since the user
-       * actively used the service.
-       */
-    case 0x0004:
-      outinfo->idletime = aimutil_get16(&buf[i+4]);
-      break;
-      
-      /*
-       * Type = 0x0006: ICQ Online Status
-       *
-       * ICQ's Away/DND/etc "enriched" status
-       * Some decoding of values done by Scott <darkagl@pcnet.com>
-       */
-    case 0x0006:
-      outinfo->icqinfo.status = aimutil_get16(buf+i+2+2+2);
-      break;
-
-
-      /*
-       * Type = 0x000a
-       *
-       * ICQ User IP Address.
-       * Ahh, the joy of ICQ security.
-       */
-    case 0x000a:
-      outinfo->icqinfo.ipaddr = aimutil_get32(&buf[i+4]);
-      break;
-
-      /* Type = 0x000c
-       *
-       * random crap containing the IP address,
-       * apparently a port number, and some Other Stuff.
-       *
-       */
-    case 0x000c:
-      memcpy(outinfo->icqinfo.crap, &buf[i+4], 0x25);
-      break;
-
-      /*
-       * Type = 0x000d
-       *
-       * Capability information.  Not real sure of
-       * actual decoding.  See comment on aim_bos_setprofile()
-       * in aim_misc.c about the capability block, its the same.
-       *
-       */
-    case 0x000d:
-      {
-       int len;
-       len = aimutil_get16(buf+i+2);
-       if (!len)
-         break;
-       
-       outinfo->capabilities = aim_getcap(sess, buf+i+4, len);
-      }
-      break;
-      
-      /*
-       * Type = 0x000e
-       *
-       * Unknown.  Always of zero length, and always only
-       * on AOL users.
-       *
-       * Ignore.
-       *
-       */
-    case 0x000e:
-      break;
-      
-      /*
-       * Type = 0x000f: Session Length. (AIM)
-       * Type = 0x0010: Session Length. (AOL)
-       *
-       * The duration, in seconds, of the user's
-       * current session.
-       *
-       * Which TLV type this comes in depends
-       * on the service the user is using (AIM or AOL).
-       *
-       */
-    case 0x000f:
-    case 0x0010:
-      outinfo->sessionlen = aimutil_get32(&buf[i+4]);
-      break;
-      
-      /*
-       * Reaching here indicates that either AOL has
-       * added yet another TLV for us to deal with, 
-       * or the parsing has gone Terribly Wrong.
-       *
-       * Either way, inform the owner and attempt
-       * recovery.
-       *
-       */
-    default:
-      {
-       int len,z = 0, y = 0, x = 0;
-       char tmpstr[160];
-
-        faimdprintf(sess, 0, "userinfo: **warning: unexpected TLV:\n");
-       faimdprintf(sess, 0, "userinfo:   sn    =%s\n", outinfo->sn);
-       faimdprintf(sess, 0, "userinfo:   curtlv=0x%04x\n", curtlv);
-       faimdprintf(sess, 0, "userinfo:   type  =0x%04x\n",aimutil_get16(&buf[i]));
-       faimdprintf(sess, 0, "userinfo:   length=0x%04x\n", len = aimutil_get16(&buf[i+2]));
-       faimdprintf(sess, 0, "userinfo:   data: \n");
-       while (z<len)
-         {
-           x = snprintf(tmpstr, sizeof(tmpstr), "userinfo:      ");
-           for (y = 0; y < 8; y++)
-             {
-               if (z<len)
-                 {
-                   snprintf(tmpstr+x, sizeof(tmpstr)-x, "%02x ", buf[i+4+z]);
-                   z++;
-                   x += 3;
-                 }
-               else
-                 break;
-             }
-           faimdprintf(sess, 0, "%s\n", tmpstr);
-         }
-      }
-      break;
-    }  
-    /*
-     * No matter what, TLV triplets should always look like this:
-     *
-     *   u_short type;
-     *   u_short length;
-     *   u_char  data[length];
-     *
-     */
-    if (lastvalid) {
-      i += (2 + 2 + aimutil_get16(&buf[i+2]));            
-      curtlv++;
-    }
-  }
-  
-  return i;
+       int curtlv, tlvcnt;
+       fu8_t snlen;
+
+       if (!bs || !outinfo)
+               return -EINVAL;
+
+       /* Clear out old data first */
+       memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
+
+       /*
+        * Screen name.  Stored as an unterminated string prepended with a 
+        * byte containing its length.
+        */
+       snlen = aimbs_get8(bs);
+       aimbs_getrawbuf(bs, outinfo->sn, snlen);
+
+       /*
+        * Warning Level.  Stored as an unsigned short.
+        */
+       outinfo->warnlevel = aimbs_get16(bs);
+
+       /*
+        * TLV Count. Unsigned short representing the number of 
+        * Type-Length-Value triples that follow.
+        */
+       tlvcnt = aimbs_get16(bs);
+
+       /* 
+        * Parse out the Type-Length-Value triples as they're found.
+        */
+       for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
+               int endpos;
+               fu16_t type, length;
+
+               type = aimbs_get16(bs);
+               length = aimbs_get16(bs);
+
+               endpos = aim_bstream_curpos(bs) + length;
+
+               if (type == 0x0001) {
+                       /*
+                        * Type = 0x0001: User flags
+                        * 
+                        * Specified as any of the following ORed together:
+                        *      0x0001  Trial (user less than 60days)
+                        *      0x0002  Unknown bit 2
+                        *      0x0004  AOL Main Service user
+                        *      0x0008  Unknown bit 4
+                        *      0x0010  Free (AIM) user 
+                        *      0x0020  Away
+                        *
+                        */
+                       outinfo->flags = aimbs_get16(bs);
+
+               } else if (type == 0x0002) {
+                       /*
+                        * Type = 0x0002: Member-Since date. 
+                        *
+                        * The time/date that the user originally registered for
+                        * the service, stored in time_t format.
+                        */
+                       outinfo->membersince = aimbs_get32(bs);
+
+               } else if (type == 0x0003) {
+                       /*
+                        * Type = 0x0003: On-Since date.
+                        *
+                        * The time/date that the user started their current 
+                        * session, stored in time_t format.
+                        */
+                       outinfo->onlinesince = aimbs_get32(bs);
+
+               } else if (type == 0x0004) {
+                       /*
+                        * Type = 0x0004: Idle time.
+                        *
+                        * Number of seconds since the user actively used the 
+                        * service.
+                        *
+                        * Note that the client tells the server when to start
+                        * counting idle times, so this may or may not be 
+                        * related to reality.
+                        */
+                       outinfo->idletime = aimbs_get16(bs);
+
+               } else if (type == 0x0006) {
+                       /*
+                        * Type = 0x0006: ICQ Online Status
+                        *
+                        * ICQ's Away/DND/etc "enriched" status. Some decoding 
+                        * of values done by Scott <darkagl@pcnet.com>
+                        */
+                       aimbs_get16(bs);
+                       outinfo->icqinfo.status = aimbs_get16(bs);
+
+               } else if (type == 0x000a) {
+                       /*
+                        * Type = 0x000a
+                        *
+                        * ICQ User IP Address.
+                        * Ahh, the joy of ICQ security.
+                        */
+                       outinfo->icqinfo.ipaddr = aimbs_get32(bs);
+
+               } else if (type == 0x000c) {
+                       /* 
+                        * Type = 0x000c
+                        *
+                        * random crap containing the IP address,
+                        * apparently a port number, and some Other Stuff.
+                        *
+                        */
+                       aimbs_getrawbuf(bs, outinfo->icqinfo.crap, 0x25);
+
+               } else if (type == 0x000d) {
+                       /*
+                        * Type = 0x000d
+                        *
+                        * Capability information.
+                        *
+                        */
+                       outinfo->capabilities = aim_getcap(sess, bs, length);
+
+               } else if (type == 0x000e) {
+                       /*
+                        * Type = 0x000e
+                        *
+                        * Unknown.  Always of zero length, and always only
+                        * on AOL users.
+                        *
+                        * Ignore.
+                        *
+                        */
+
+               } else if ((type == 0x000f) || (type == 0x0010)) {
+                       /*
+                        * Type = 0x000f: Session Length. (AIM)
+                        * Type = 0x0010: Session Length. (AOL)
+                        *
+                        * The duration, in seconds, of the user's current 
+                        * session.
+                        *
+                        * Which TLV type this comes in depends on the
+                        * service the user is using (AIM or AOL).
+                        *
+                        */
+                       outinfo->sessionlen = aimbs_get32(bs);
+
+               } else {
+
+                       /*
+                        * Reaching here indicates that either AOL has
+                        * added yet another TLV for us to deal with, 
+                        * or the parsing has gone Terribly Wrong.
+                        *
+                        * Either way, inform the owner and attempt
+                        * recovery.
+                        *
+                        */
+                       faimdprintf(sess, 0, "userinfo: **warning: unexpected TLV:\n");
+                       faimdprintf(sess, 0, "userinfo:   sn    =%s\n", outinfo->sn);
+                       faimdprintf(sess, 0, "userinfo:   type  =0x%04x\n",type);
+                       faimdprintf(sess, 0, "userinfo:   length=0x%04x\n", length);
+
+               }
+
+               /* Save ourselves. */
+               aim_bstream_setpos(bs, endpos);
+       }
+
+       return 0;
 }
 
 /*
  * Inverse of aim_extractuserinfo()
  */
-faim_internal int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info)
+faim_internal int aim_putuserinfo(aim_bstream_t *bs, struct aim_userinfo_s *info)
 {
-  int i = 0, numtlv = 0;
-  struct aim_tlvlist_t *tlvlist = NULL;
+       aim_tlvlist_t *tlvlist = NULL;
 
-  if (!buf || !info)
-    return 0;
+       if (!bs || !info)
+               return -EINVAL;
 
-  i += aimutil_put8(buf+i, strlen(info->sn));
-  i += aimutil_putstr(buf+i, info->sn, strlen(info->sn));
+       aimbs_put8(bs, strlen(info->sn));
+       aimbs_putraw(bs, info->sn, strlen(info->sn));
 
-  i += aimutil_put16(buf+i, info->warnlevel);
+       aimbs_put16(bs, info->warnlevel);
 
 
-  aim_addtlvtochain16(&tlvlist, 0x0001, info->flags);
-  numtlv++;
-
-  aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince);
-  numtlv++;
-
-  aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince);
-  numtlv++;
-
-  aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime);
-  numtlv++;
+       aim_addtlvtochain16(&tlvlist, 0x0001, info->flags);
+       aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince);
+       aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince);
+       aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime);
 
 #if ICQ_OSCAR_SUPPORT
-  if(atoi(info->sn) != 0) {
-    aim_addtlvtochain16(&tlvlist, 0x0006, info->icqinfo.status);
-    aim_addtlvtochain32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
-  }
+       if (atoi(info->sn) != 0) {
+               aim_addtlvtochain16(&tlvlist, 0x0006, info->icqinfo.status);
+               aim_addtlvtochain32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
+       }
 #endif
 
-  aim_addtlvtochain_caps(&tlvlist, 0x000d, info->capabilities);
-  numtlv++;
+       aim_addtlvtochain_caps(&tlvlist, 0x000d, info->capabilities);
 
-  aim_addtlvtochain32(&tlvlist, (unsigned short)((info->flags)&AIM_FLAG_AOL?0x0010:0x000f), info->sessionlen);
-  numtlv++;
+       aim_addtlvtochain32(&tlvlist, (fu16_t)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen);
 
-  i += aimutil_put16(buf+i, numtlv); /* tlvcount */
-  i += aim_writetlvchain(buf+i, buflen-i, &tlvlist); /* tlvs */
-  aim_freetlvchain(&tlvlist);
+       aimbs_put16(bs, aim_counttlvchain(&tlvlist));
+       aim_writetlvchain(bs, &tlvlist);
+       aim_freetlvchain(&tlvlist);
 
-  return i;
+       return 0;
 }
 
-faim_export int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info)
+faim_export int aim_sendbuddyoncoming(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *info)
 {
-  struct command_tx_struct *tx;
-  int i = 0;
-
-  if (!sess || !conn || !info)
-    return 0;
+       aim_frame_t *fr;
+       aim_snacid_t snacid;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
-    return -1;
+       if (!sess || !conn || !info)
+               return -EINVAL;
 
-  tx->lock = 1;
+       if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
+               return -ENOMEM;
 
-  i += aimutil_put16(tx->data+i, 0x0003);
-  i += aimutil_put16(tx->data+i, 0x000b);
-  i += aimutil_put16(tx->data+i, 0x0000);
-  i += aimutil_put16(tx->data+i, 0x0000);
-  i += aimutil_put16(tx->data+i, 0x0000);
-
-  i += aim_putuserinfo(tx->data+i, tx->commandlen-i, info);
+       snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0);
+       
+       aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid);
+       aim_putuserinfo(&fr->data, info);
 
-  tx->commandlen = i;
-  tx->lock = 0;
-  aim_tx_enqueue(sess, tx);
+       aim_tx_enqueue(sess, fr);
 
-  return 0;
+       return 0;
 }
 
-faim_export int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn)
+faim_export int aim_sendbuddyoffgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn)
 {
-  struct command_tx_struct *tx;
-  int i = 0;
-
-  if (!sess || !conn || !sn)
-    return 0;
+       aim_frame_t *fr;
+       aim_snacid_t snacid;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+1+strlen(sn))))
-    return -1;
+       if (!sess || !conn || !sn)
+               return -EINVAL;
 
-  tx->lock = 1;
+       if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
+               return -ENOMEM;
 
-  i += aimutil_put16(tx->data+i, 0x0003);
-  i += aimutil_put16(tx->data+i, 0x000c);
-  i += aimutil_put16(tx->data+i, 0x0000);
-  i += aimutil_put16(tx->data+i, 0x0000);
-  i += aimutil_put16(tx->data+i, 0x0000);
+       snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0);
+       
+       aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid);
+       aimbs_put8(&fr->data, strlen(sn));
+       aimbs_putraw(&fr->data, sn, strlen(sn));
 
-  i += aimutil_put8(tx->data+i, strlen(sn));
-  i += aimutil_putstr(tx->data+i, sn, strlen(sn));
-  
-  tx->lock = 0;
-  aim_tx_enqueue(sess, tx);
+       aim_tx_enqueue(sess, fr);
 
-  return 0;
+       return 0;
 }
 
-faim_export int aim_0002_000b(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn)
+/*
+ * Huh? What is this?
+ */
+faim_export int aim_0002_000b(aim_session_t *sess, aim_conn_t *conn, const char *sn)
 {
-  struct command_tx_struct *tx;
-  int i = 0;
+       aim_frame_t *fr;
+       aim_snacid_t snacid;
 
-  if (!sess || !conn || !sn)
-    return 0;
+       if (!sess || !conn || !sn)
+               return -EINVAL;
 
-  if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+1+strlen(sn))))
-    return -1;
+       if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
+               return -ENOMEM;
 
-  tx->lock = 1;
+       snacid = aim_cachesnac(sess, 0x0002, 0x000b, 0x0000, NULL, 0);
+       
+       aim_putsnac(&fr->data, 0x0002, 0x000b, 0x0000, snacid);
+       aimbs_put8(&fr->data, strlen(sn));
+       aimbs_putraw(&fr->data, sn, strlen(sn));
 
-  i = aim_putsnac(tx->data, 0x0002, 0x000b, 0x0000, sess->snac_nextid);
-  i += aimutil_put8(tx->data+i, strlen(sn));
-  i += aimutil_putstr(tx->data+i, sn, strlen(sn));
-  
-  tx->commandlen = i;
-  tx->lock = 0;
-  aim_tx_enqueue(sess, tx);
+       aim_tx_enqueue(sess, fr);
 
-  return 0;
+       return 0;
 }
 
 /*
@@ -545,14 +446,14 @@ faim_export int aim_0002_000b(struct aim_session_t *sess, struct aim_conn_t *con
  *   t(0002)  - short - unknown (value = 16) [max MIME type length?]
  *   t(0003)  - short - unknown (value = 7)
  */
-static int rights(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
 {
-       struct aim_tlvlist_t *tlvlist;
+       aim_tlvlist_t *tlvlist;
        aim_rxcallback_t userfunc;
        int ret = 0;
-       unsigned short maxsiglen = 0;
+       fu16_t maxsiglen = 0;
 
-       tlvlist = aim_readtlvchain(data, datalen);
+       tlvlist = aim_readtlvchain(bs);
 
        if (aim_gettlv(tlvlist, 0x0001, 1))
                maxsiglen = aim_gettlv16(tlvlist, 0x0001, 1);
@@ -565,87 +466,83 @@ static int rights(struct aim_session_t *sess, aim_module_t *mod, struct command_
        return ret;
 }
 
-static int userinfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
 {
-  struct aim_userinfo_s userinfo;
-  char *text_encoding = NULL;
-  char *text = NULL;
-  int i = 0;
-  aim_rxcallback_t userfunc;
-  struct aim_tlvlist_t *tlvlist;
-  struct aim_snac_t *origsnac = NULL;
-  struct aim_priv_inforeq *inforeq;
-  int ret = 0;
-
-  origsnac = aim_remsnac(sess, snac->id);
-
-  if (!origsnac || !origsnac->data) {
-    faimdprintf(sess, 0, "parse_userinfo_middle: major problem: no snac stored!\n");
-    return 0;
-  }
-
-  inforeq = (struct aim_priv_inforeq *)origsnac->data;
-
-  if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) &&
-      (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE)) {
-    faimdprintf(sess, 0, "parse_userinfo_middle: unknown infotype in request! (0x%04x)\n", inforeq->infotype);
-    return 0;
-  }
-
-  i = aim_extractuserinfo(sess, data, &userinfo);
-  
-  tlvlist = aim_readtlvchain(data+i, datalen-i);
-
-  /* 
-   * Depending on what informational text was requested, different
-   * TLVs will appear here.
-   *
-   * Profile will be 1 and 2, away message will be 3 and 4.
-   */
-  if (aim_gettlv(tlvlist, 0x0001, 1)) {
-    text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
-    text = aim_gettlv_str(tlvlist, 0x0002, 1);
-  } else if (aim_gettlv(tlvlist, 0x0003, 1)) {
-    text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1);
-    text = aim_gettlv_str(tlvlist, 0x0004, 1);
-  }
-
-  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
-    ret = userfunc(sess, rx, &userinfo, text_encoding, text, inforeq->infotype);
-
-  free(text_encoding);
-  free(text);
-
-  aim_freetlvchain(&tlvlist);
-
-  if (origsnac) {
-    if (origsnac->data)
-      free(origsnac->data);
-    free(origsnac);
-  }
-
-  return ret;
+       struct aim_userinfo_s userinfo;
+       char *text_encoding = NULL, *text = NULL;
+       aim_rxcallback_t userfunc;
+       aim_tlvlist_t *tlvlist;
+       aim_snac_t *origsnac = NULL;
+       struct aim_priv_inforeq *inforeq;
+       int ret = 0;
+
+       origsnac = aim_remsnac(sess, snac->id);
+
+       if (!origsnac || !origsnac->data) {
+               faimdprintf(sess, 0, "parse_userinfo_middle: major problem: no snac stored!\n");
+               return 0;
+       }
+
+       inforeq = (struct aim_priv_inforeq *)origsnac->data;
+
+       if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) &&
+                       (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE)) {
+               faimdprintf(sess, 0, "parse_userinfo_middle: unknown infotype in request! (0x%04x)\n", inforeq->infotype);
+               return 0;
+       }
+
+       aim_extractuserinfo(sess, bs, &userinfo);
+
+       tlvlist = aim_readtlvchain(bs);
+
+       /* 
+        * Depending on what informational text was requested, different
+        * TLVs will appear here.
+        *
+        * Profile will be 1 and 2, away message will be 3 and 4.
+        */
+       if (aim_gettlv(tlvlist, 0x0001, 1)) {
+               text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
+               text = aim_gettlv_str(tlvlist, 0x0002, 1);
+       } else if (aim_gettlv(tlvlist, 0x0003, 1)) {
+               text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1);
+               text = aim_gettlv_str(tlvlist, 0x0004, 1);
+       }
+
+       if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+               ret = userfunc(sess, rx, &userinfo, text_encoding, text, inforeq->infotype);
+
+       free(text_encoding);
+       free(text);
+
+       aim_freetlvchain(&tlvlist);
+
+       if (origsnac)
+               free(origsnac->data);
+       free(origsnac);
+
+       return ret;
 }
 
-static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
 {
 
-  if (snac->subtype == 0x0003)
-    return rights(sess, mod, rx, snac, data, datalen);
-  else if (snac->subtype == 0x0006)
-    return userinfo(sess, mod, rx, snac, data, datalen);
+       if (snac->subtype == 0x0003)
+               return rights(sess, mod, rx, snac, bs);
+       else if (snac->subtype == 0x0006)
+               return userinfo(sess, mod, rx, snac, bs);
 
-  return 0;
+       return 0;
 }
 
-faim_internal int locate_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+faim_internal int locate_modfirst(aim_session_t *sess, aim_module_t *mod)
 {
 
-  mod->family = 0x0002;
-  mod->version = 0x0000;
-  mod->flags = 0;
-  strncpy(mod->name, "locate", sizeof(mod->name));
-  mod->snachandler = snachandler;
+       mod->family = 0x0002;
+       mod->version = 0x0000;
+       mod->flags = 0;
+       strncpy(mod->name, "locate", sizeof(mod->name));
+       mod->snachandler = snachandler;
 
-  return 0;
+       return 0;
 }
This page took 1.658886 seconds and 4 git commands to generate.