+/**
+ * aim_counttlvchain - Count the number of TLVs in a chain
+ * @list: Chain to be counted
+ *
+ * Returns the number of TLVs stored in the passed chain.
+ *
+ */
+faim_export 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;
+}
+
+/**
+ * aim_sizetlvchain - Count the number of bytes in a TLV chain
+ * @list: Chain to be sized
+ *
+ * Returns the number of bytes that would be needed to
+ * write the passed TLV chain to a data buffer.
+ *
+ */
+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;
+}
+
+/**
+ * aim_addtlvtochain_str - Add a string to a TLV chain
+ * @list: Desination chain (%NULL pointer if empty)
+ * @type: TLV type
+ * @str: String to add
+ * @len: Length of string to add (not including %NULL)
+ *
+ * Adds the passed string as a TLV element of the passed type
+ * to the TLV chain.
+ *
+ */
+faim_export 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;
+}
+
+/**
+ * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ * @val: Value to add
+ *
+ * Adds a two-byte unsigned integer to a TLV chain.
+ *
+ */
+faim_export 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;
+}
+
+/**
+ * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ * @val: Value to add
+ *
+ * Adds a four-byte unsigned integer to a TLV chain.
+ *
+ */
+faim_export 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;
+}
+
+/**
+ * aim_addtlvtochain_caps - Add a capability block to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ * @caps: Bitfield of capability flags to send
+ *
+ * Adds a block of capability blocks to a TLV chain. The bitfield
+ * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
+ *
+ * %AIM_CAPS_BUDDYICON Supports Buddy Icons
+ *
+ * %AIM_CAPS_VOICE Supports Voice Chat
+ *
+ * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage
+ *
+ * %AIM_CAPS_CHAT Supports Chat
+ *
+ * %AIM_CAPS_GETFILE Supports Get File functions
+ *
+ * %AIM_CAPS_SENDFILE Supports Send File functions
+ *
+ */
+faim_export 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 = (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 = aim_putcap(buf, sizeof(buf), 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;
+}
+
+/**
+ * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
+ * @list: Destination chain
+ * @type: TLV type to add
+ *
+ * Adds a TLV with a zero length to a TLV chain.
+ *