]> andersk Git - libfaim.git/blobdiff - aim_tlv.c
(guest commit by jbm)
[libfaim.git] / aim_tlv.c
index a8cf05b1478ba9e74bd18ed60fa19ada7cd52c91..3557d5a643208331a6df6d1f3dcec52a51c28d87 100644 (file)
--- a/aim_tlv.c
+++ b/aim_tlv.c
@@ -1,6 +1,6 @@
-#include <aim.h>
+#include <faim/aim.h>
 
-struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
+faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
 {
   int pos;
   struct aim_tlvlist_t *list;
@@ -28,18 +28,32 @@ struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
          
          if ((pos+length) <= 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->type = type;
-             cur->tlv->length = length;
-             cur->tlv->value = (u_char *)malloc(length*sizeof(u_char));
-             memcpy(cur->tlv->value, buf+pos, length);
-             
-             cur->next = list;
-             list = cur;
-             
+             /*
+              * Okay, so now AOL has decided that any TLV of
+              * type 0x0013 can only be two bytes, despite
+              * what the actual given length is.  So here 
+              * we dump any invalid TLVs of that sort.  Hopefully
+              * theres no special cases to this special case.
+              *   - mid (30jun2000)
+              */
+             if ((type == 0x0013) && (length != 0x0002)) {
+               printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
+               length = 0x0002;
+             } else {
+               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->type = type;
+               cur->tlv->length = length; 
+               if (length) {
+                 cur->tlv->value = (unsigned char *)malloc(length);
+                 memcpy(cur->tlv->value, buf+pos, length);
+               } 
+
+               cur->next = list;
+               list = cur;
+             }
              pos += length;
            }
        }
@@ -48,7 +62,7 @@ struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
   return list;
 }
 
-void aim_freetlvchain(struct aim_tlvlist_t **list)
+faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list)
 {
   struct aim_tlvlist_t *cur, *cur2;
 
@@ -67,10 +81,192 @@ void aim_freetlvchain(struct aim_tlvlist_t **list)
   return;
 }
 
+faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list)
+{
+  struct aim_tlvlist_t *cur;
+  int count = 0;
+
+  if (!list || !(*list))
+    return 0;
+
+  for (cur = *list; cur; cur = cur->next)
+    count++;
+  return count;
+}
+
+faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
+{
+  struct aim_tlvlist_t *cur;
+  int size = 0;
+
+  if (!list || !(*list))
+    return 0;
+
+  for (cur = *list; cur; cur = cur->next)
+    size += (4 + cur->tlv->length);
+  return size;
+}
+
+
+faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
+{
+  struct aim_tlvlist_t *newtlv;
+  struct aim_tlvlist_t *cur;
+
+  if (!list)
+    return 0;
+
+  newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+  memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
+
+  newtlv->tlv = aim_createtlv();       
+  newtlv->tlv->type = type;
+  newtlv->tlv->length = len;
+  newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
+  memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
+
+  newtlv->next = NULL;
+
+  if (*list == NULL) {
+    *list = newtlv;
+  } else if ((*list)->next == NULL) {
+    (*list)->next = newtlv;
+  } else {
+    for(cur = *list; cur->next; cur = cur->next)
+      ;
+    cur->next = newtlv;
+  }
+  return newtlv->tlv->length;
+}
+
+faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
+{
+  struct aim_tlvlist_t *newtl;
+  struct aim_tlvlist_t *cur;
+
+  if (!list)
+    return 0;
+
+  newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+  memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
+
+  newtl->tlv = aim_createtlv();        
+  newtl->tlv->type = type;
+  newtl->tlv->length = 2;
+  newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
+  aimutil_put16(newtl->tlv->value, val);
+
+  newtl->next = NULL;
+
+  if (*list == NULL) {
+    *list = newtl;
+  } else if ((*list)->next == NULL) {
+    (*list)->next = newtl;
+  } else {
+    for(cur = *list; cur->next; cur = cur->next)
+      ;
+    cur->next = newtl;
+  }
+  return 2;
+}
+
+faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
+{
+  struct aim_tlvlist_t *newtl;
+  struct aim_tlvlist_t *cur;
+
+  if (!list)
+    return 0;
+
+  newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
+  memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
+
+  newtl->tlv = aim_createtlv();        
+  newtl->tlv->type = type;
+  newtl->tlv->length = 4;
+  newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
+  aimutil_put32(newtl->tlv->value, val);
+
+  newtl->next = NULL;
+
+  if (*list == NULL) {
+    *list = newtl;
+  } else if ((*list)->next == NULL) {
+    (*list)->next = newtl;
+  } else {
+    for(cur = *list; cur->next; cur = cur->next)
+      ;
+    cur->next = newtl;
+  }
+  return 4;
+}
+
+faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
+{
+  unsigned char buf[128]; /* icky fixed length buffer */
+  struct aim_tlvlist_t *newtl;
+  struct aim_tlvlist_t *cur;
+
+  if(!list)
+    return 0;
+
+  newtl->tlv = aim_createtlv();        
+  newtl->tlv->type = type;
+
+  newtl->tlv->length = aim_putcap(buf, 128, caps);
+  newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
+  memcpy(newtl->tlv->value, &buf, newtl->tlv->length);
+
+  newtl->next = NULL;
+
+  if (*list == NULL) {
+    *list = newtl;
+  } else if ((*list)->next == NULL) {
+    (*list)->next = newtl;
+  } else {
+    for(cur = *list; cur->next; cur = cur->next)
+      ;
+    cur->next = newtl;
+  }
+  return newtl->tlv->length;
+}
+
+faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
+{
+  int goodbuflen = 0;
+  int i = 0;
+  struct aim_tlvlist_t *cur;
+
+  if (!list || !buf || !buflen)
+    return 0;
+
+  /* do an initial run to test total length */
+  for (cur = *list; cur; cur = cur->next) {
+    goodbuflen += 2 + 2; /* type + len */
+    goodbuflen += cur->tlv->length;
+  }
+
+  if (goodbuflen > buflen)
+    return 0; /* not enough buffer */
+
+  /* do the real write-out */
+  for (cur = *list; cur; cur = cur->next) {
+    i += aimutil_put16(buf+i, cur->tlv->type);
+    i += aimutil_put16(buf+i, cur->tlv->length);
+    memcpy(buf+i, cur->tlv->value, cur->tlv->length);
+    i += cur->tlv->length;
+  }
+
+  return i;
+}
+
+
 /*
  * Grab the Nth TLV of type type in the TLV list list.
  */
-struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
+faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
 {
   int i;
   struct aim_tlvlist_t *cur;
@@ -89,7 +285,7 @@ struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
   return NULL;
 }
 
-char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
+faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
 {
   struct aim_tlv_t *tlv;
   char *newstr;
@@ -104,7 +300,7 @@ char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
   return newstr;
 }
 
-struct aim_tlv_t *aim_grabtlv(u_char *src)
+faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
 {
   struct aim_tlv_t *dest = NULL;
 
@@ -124,7 +320,7 @@ struct aim_tlv_t *aim_grabtlv(u_char *src)
   return dest;
 }
 
-struct aim_tlv_t *aim_grabtlvstr(u_char *src)
+faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
 {
   struct aim_tlv_t *dest = NULL;
 
@@ -145,7 +341,7 @@ struct aim_tlv_t *aim_grabtlvstr(u_char *src)
   return dest;
 }
 
-int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv)
+faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
 {
   int i=0;
 
@@ -158,7 +354,7 @@ int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv)
   return i;
 }
 
-struct aim_tlv_t *aim_createtlv(void)
+faim_internal struct aim_tlv_t *aim_createtlv(void)
 {
   struct aim_tlv_t *newtlv = NULL;
   newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t));
@@ -166,7 +362,7 @@ struct aim_tlv_t *aim_createtlv(void)
   return newtlv;
 }
 
-int aim_freetlv(struct aim_tlv_t **oldtlv)
+faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
 {
   if (!oldtlv)
     return -1;
@@ -180,7 +376,7 @@ int aim_freetlv(struct aim_tlv_t **oldtlv)
   return 0;
 }
 
-int aim_puttlv_16(u_char *buf, u_short t, u_short v)
+faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
 {
   int curbyte=0;
   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
@@ -188,3 +384,25 @@ int aim_puttlv_16(u_char *buf, u_short t, u_short v)
   curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
   return curbyte;
 }
+
+faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
+{
+  int curbyte=0;
+  curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
+  curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
+  curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
+  return curbyte;
+}
+
+faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
+{
+  int curbyte;
+  
+  curbyte  = 0;
+  curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
+  curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
+  if (v)
+    memcpy(buf+curbyte, (unsigned char *)v, l);
+  curbyte += l;
+  return curbyte;
+}
This page took 0.19738 seconds and 4 git commands to generate.