]> andersk Git - libfaim.git/blob - aim_tlv.c
75cc7eaa976ab529195572dd4955cabfb2c68de5
[libfaim.git] / aim_tlv.c
1 #include <faim/aim.h>
2
3 faim_internal struct aim_tlvlist_t *aim_readtlvchain(u_char *buf, int maxlen)
4 {
5   int pos;
6   struct aim_tlvlist_t *list;
7   struct aim_tlvlist_t *cur;
8   
9   u_short type;
10   u_short length;
11
12   if (!buf)
13     return NULL;
14
15   list = NULL;
16   
17   pos = 0;
18
19   while (pos < maxlen)
20     {
21       type = aimutil_get16(buf+pos);
22       pos += 2;
23
24       if (pos < maxlen)
25         {
26           length = aimutil_get16(buf+pos);
27           pos += 2;
28           
29           if ((pos+length) <= maxlen)
30             {
31               /*
32                * Okay, so now AOL has decided that any TLV of
33                * type 0x0013 can only be two bytes, despite
34                * what the actual given length is.  So here 
35                * we dump any invalid TLVs of that sort.  Hopefully
36                * theres no special cases to this special case.
37                *   - mid (30jun2000)
38                */
39               if ((type == 0x0013) && (length != 0x0002)) {
40                 printf("faim: skipping TLV t(0013) with invalid length (0x%04x)\n", length);
41                 length = 0x0002;
42               } else {
43                 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
44                 memset(cur, 0x00, sizeof(struct aim_tlvlist_t));
45
46                 cur->tlv = aim_createtlv();     
47                 cur->tlv->type = type;
48                 cur->tlv->length = length; 
49                 if (length) {
50                   cur->tlv->value = (unsigned char *)malloc(length);
51                   memcpy(cur->tlv->value, buf+pos, length);
52                 } 
53
54                 cur->next = list;
55                 list = cur;
56               }
57               pos += length;
58             }
59         }
60     }
61
62   return list;
63 }
64
65 faim_internal void aim_freetlvchain(struct aim_tlvlist_t **list)
66 {
67   struct aim_tlvlist_t *cur, *cur2;
68
69   if (!list || !(*list))
70     return;
71
72   cur = *list;
73   while (cur)
74     {
75       aim_freetlv(&cur->tlv);
76       cur2 = cur->next;
77       free(cur);
78       cur = cur2;
79     }
80   list = NULL;
81   return;
82 }
83
84 faim_internal int aim_counttlvchain(struct aim_tlvlist_t **list)
85 {
86   struct aim_tlvlist_t *cur;
87   int count = 0;
88
89   if (!list || !(*list))
90     return 0;
91
92   for (cur = *list; cur; cur = cur->next)
93     count++;
94  
95   return count;
96 }
97
98 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list)
99 {
100   struct aim_tlvlist_t *cur;
101   int size = 0;
102
103   if (!list || !(*list))
104     return 0;
105
106   for (cur = *list; cur; cur = cur->next)
107     size += (4 + cur->tlv->length);
108  
109   return size;
110 }
111
112
113 faim_internal int aim_addtlvtochain_str(struct aim_tlvlist_t **list, unsigned short type, char *str, int len)
114 {
115   struct aim_tlvlist_t *newtlv;
116   struct aim_tlvlist_t *cur;
117
118   if (!list)
119     return 0;
120
121   newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
122   memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t));
123
124   newtlv->tlv = aim_createtlv();        
125   newtlv->tlv->type = type;
126   newtlv->tlv->length = len;
127   newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char));
128   memcpy(newtlv->tlv->value, str, newtlv->tlv->length);
129
130   newtlv->next = NULL;
131
132   if (*list == NULL) {
133     *list = newtlv;
134   } else if ((*list)->next == NULL) {
135     (*list)->next = newtlv;
136   } else {
137     for(cur = *list; cur->next; cur = cur->next)
138       ;
139     cur->next = newtlv;
140   }
141   return newtlv->tlv->length;
142 }
143
144 faim_internal int aim_addtlvtochain16(struct aim_tlvlist_t **list, unsigned short type, unsigned short val)
145 {
146   struct aim_tlvlist_t *newtl;
147   struct aim_tlvlist_t *cur;
148
149   if (!list)
150     return 0;
151
152   newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
153   memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
154
155   newtl->tlv = aim_createtlv(); 
156   newtl->tlv->type = type;
157   newtl->tlv->length = 2;
158   newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
159   aimutil_put16(newtl->tlv->value, val);
160
161   newtl->next = NULL;
162
163   if (*list == NULL) {
164     *list = newtl;
165   } else if ((*list)->next == NULL) {
166     (*list)->next = newtl;
167   } else {
168     for(cur = *list; cur->next; cur = cur->next)
169       ;
170     cur->next = newtl;
171   }
172   return 2;
173 }
174
175 faim_internal int aim_addtlvtochain32(struct aim_tlvlist_t **list, unsigned short type, unsigned long val)
176 {
177   struct aim_tlvlist_t *newtl;
178   struct aim_tlvlist_t *cur;
179
180   if (!list)
181     return 0;
182
183   newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
184   memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
185
186   newtl->tlv = aim_createtlv(); 
187   newtl->tlv->type = type;
188   newtl->tlv->length = 4;
189   newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char));
190   aimutil_put32(newtl->tlv->value, val);
191
192   newtl->next = NULL;
193
194   if (*list == NULL) {
195     *list = newtl;
196   } else if ((*list)->next == NULL) {
197     (*list)->next = newtl;
198   } else {
199     for(cur = *list; cur->next; cur = cur->next)
200       ;
201     cur->next = newtl;
202   }
203   return 4;
204 }
205
206 faim_internal int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, unsigned short type, unsigned short caps)
207 {
208   unsigned char buf[128]; /* icky fixed length buffer */
209   struct aim_tlvlist_t *newtl;
210   struct aim_tlvlist_t *cur;
211
212   if(!list)
213     return 0;
214
215   newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t));
216   memset(newtl, 0x00, sizeof(struct aim_tlvlist_t));
217
218   newtl->tlv = aim_createtlv(); 
219   newtl->tlv->type = type;
220
221   newtl->tlv->length = aim_putcap(buf, sizeof(buf), caps);
222   newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length);
223   memcpy(newtl->tlv->value, buf, newtl->tlv->length);
224
225   newtl->next = NULL;
226
227   if (*list == NULL) {
228     *list = newtl;
229   } else if ((*list)->next == NULL) {
230     (*list)->next = newtl;
231   } else {
232     for(cur = *list; cur->next; cur = cur->next)
233       ;
234     cur->next = newtl;
235   }
236   return newtl->tlv->length;
237 }
238
239 faim_internal int aim_writetlvchain(u_char *buf, int buflen, struct aim_tlvlist_t **list)
240 {
241   int goodbuflen = 0;
242   int i = 0;
243   struct aim_tlvlist_t *cur;
244
245   if (!list || !buf || !buflen)
246     return 0;
247
248   /* do an initial run to test total length */
249   for (cur = *list; cur; cur = cur->next) {
250     goodbuflen += 2 + 2; /* type + len */
251     goodbuflen += cur->tlv->length;
252   }
253
254   if (goodbuflen > buflen)
255     return 0; /* not enough buffer */
256
257   /* do the real write-out */
258   for (cur = *list; cur; cur = cur->next) {
259     i += aimutil_put16(buf+i, cur->tlv->type);
260     i += aimutil_put16(buf+i, cur->tlv->length);
261     memcpy(buf+i, cur->tlv->value, cur->tlv->length);
262     i += cur->tlv->length;
263   }
264
265   return i;
266 }
267
268
269 /*
270  * Grab the Nth TLV of type type in the TLV list list.
271  */
272 faim_internal struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, u_short type, int nth)
273 {
274   int i;
275   struct aim_tlvlist_t *cur;
276   
277   i = 0;
278   for (cur = list; cur != NULL; cur = cur->next)
279     {
280       if (cur && cur->tlv)
281         {
282           if (cur->tlv->type == type)
283             i++;
284           if (i >= nth)
285             return cur->tlv;
286         }
287     }
288   return NULL;
289 }
290
291 faim_internal char *aim_gettlv_str(struct aim_tlvlist_t *list, u_short type, int nth)
292 {
293   struct aim_tlv_t *tlv;
294   char *newstr;
295
296   if (!(tlv = aim_gettlv(list, type, nth)))
297     return NULL;
298   
299   newstr = (char *) malloc(tlv->length + 1);
300   memcpy(newstr, tlv->value, tlv->length);
301   *(newstr + tlv->length) = '\0';
302
303   return newstr;
304 }
305
306 faim_internal struct aim_tlv_t *aim_grabtlv(u_char *src)
307 {
308   struct aim_tlv_t *dest = NULL;
309
310   dest = aim_createtlv();
311
312   dest->type = src[0] << 8;
313   dest->type += src[1];
314
315   dest->length = src[2] << 8;
316   dest->length += src[3];
317
318   dest->value = (u_char *) malloc(dest->length*sizeof(u_char));
319   memset(dest->value, 0, dest->length*sizeof(u_char));
320
321   memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
322   
323   return dest;
324 }
325
326 faim_internal struct aim_tlv_t *aim_grabtlvstr(u_char *src)
327 {
328   struct aim_tlv_t *dest = NULL;
329
330   dest = aim_createtlv();
331
332   dest->type = src[0] << 8;
333   dest->type += src[1];
334
335   dest->length = src[2] << 8;
336   dest->length += src[3];
337
338   dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char));
339   memset(dest->value, 0, (dest->length+1)*sizeof(u_char));
340
341   memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char));
342   dest->value[dest->length] = '\0';
343
344   return dest;
345 }
346
347 faim_internal int aim_puttlv(u_char *dest, struct aim_tlv_t *newtlv)
348 {
349   int i=0;
350
351   dest[i++] = newtlv->type >> 8;
352   dest[i++] = newtlv->type & 0x00FF;
353   dest[i++] = newtlv->length >> 8;
354   dest[i++] = newtlv->length & 0x00FF;
355   memcpy(&(dest[i]), newtlv->value, newtlv->length);
356   i+=newtlv->length;
357   return i;
358 }
359
360 faim_internal struct aim_tlv_t *aim_createtlv(void)
361 {
362   struct aim_tlv_t *newtlv = NULL;
363   newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t));
364   memset(newtlv, 0, sizeof(struct aim_tlv_t));
365   return newtlv;
366 }
367
368 faim_internal int aim_freetlv(struct aim_tlv_t **oldtlv)
369 {
370   if (!oldtlv)
371     return -1;
372   if (!*oldtlv)
373     return -1;
374   if ((*oldtlv)->value)
375     free((*oldtlv)->value);
376   free(*(oldtlv));
377   (*oldtlv) = NULL;
378
379   return 0;
380 }
381
382 faim_internal int aim_puttlv_16(u_char *buf, u_short t, u_short v)
383 {
384   int curbyte=0;
385   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
386   curbyte += aimutil_put16(buf+curbyte, (u_short)0x0002);
387   curbyte += aimutil_put16(buf+curbyte, (u_short)(v&0xffff));
388   return curbyte;
389 }
390
391 faim_internal int aim_puttlv_32(u_char *buf, u_short t, u_long v)
392 {
393   int curbyte=0;
394   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
395   curbyte += aimutil_put16(buf+curbyte, (u_short)0x0004);
396   curbyte += aimutil_put32(buf+curbyte, (u_long)(v&0xffffffff));
397   return curbyte;
398 }
399
400 faim_internal int aim_puttlv_str(u_char *buf, u_short t, int l, char *v)
401 {
402   int curbyte;
403   
404   curbyte  = 0;
405   curbyte += aimutil_put16(buf+curbyte, (u_short)(t&0xffff));
406   curbyte += aimutil_put16(buf+curbyte, (u_short)(l&0xffff));
407   if (v)
408     memcpy(buf+curbyte, (unsigned char *)v, l);
409   curbyte += l;
410   return curbyte;
411 }
This page took 0.070521 seconds and 3 git commands to generate.