comparison libpurple/protocols/msn/tlv.c @ 31558:ce968e115c95

propagate from branch 'im.pidgin.cpw.masca.p2p' (head 33ca865dacb9e5bcf763d06f6a42cbaca337cc64) to branch 'im.pidgin.pidgin' (head 92f47f4e8b0cbb107fd97e1ab814d1cedbf109ad)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 06 May 2011 06:25:14 +0000
parents dfc2a8e98430
children bd59044a9100
comparison
equal deleted inserted replaced
31557:f021d93a1f9b 31558:ce968e115c95
43 { 43 {
44 g_free(oldtlv->value); 44 g_free(oldtlv->value);
45 g_free(oldtlv); 45 g_free(oldtlv);
46 } 46 }
47 47
48 static GSList * 48 GSList *
49 msn_tlv_read(GSList *list, char *bs, size_t *bs_len) 49 msn_tlvlist_read(const char *bs, size_t bs_len)
50 { 50 {
51 guint8 type, length; 51 GSList *list = NULL;
52 msn_tlv_t *tlv; 52
53 53 while (bs_len > 0) {
54 type = msn_read8(bs); 54 guint8 type, length;
55 length = msn_read8(bs); 55 msn_tlv_t *tlv;
56 *bs_len -= 2; 56
57 57 if (bs_len == 3 && *bs == 0) {
58 if (length > *bs_len) { 58 /* Padding to multiple of 4 */
59 msn_tlvlist_free(list); 59 break;
60 return NULL; 60 } else if (bs_len == 2 && *bs == 0) {
61 } 61 /* Padding to multiple of 4 */
62 62 break;
63 tlv = createtlv(type, length, NULL); 63 } else if (bs_len == 1) {
64 if (length > 0) { 64 if (*bs == 0) {
65 tlv->value = g_memdup(bs, length); 65 /* Padding to multiple of 4 */
66 if (!tlv->value) { 66 break;
67 freetlv(tlv); 67 } else {
68 /* TLV is not small enough to fit here */
69 msn_tlvlist_free(list);
70 return NULL;
71 }
72 }
73
74 type = msn_pop8(bs);
75 length = msn_pop8(bs);
76 bs_len -= 2;
77
78 if (length > bs_len) {
68 msn_tlvlist_free(list); 79 msn_tlvlist_free(list);
69 return NULL; 80 return NULL;
70 } 81 }
71 } 82
72 83 tlv = createtlv(type, length, NULL);
73 *bs_len -= length; 84 if (length > 0) {
74 85 tlv->value = g_memdup(bs, length);
75 return g_slist_prepend(list, tlv); 86 if (!tlv->value) {
87 freetlv(tlv);
88 msn_tlvlist_free(list);
89 return NULL;
90 }
91 }
92
93 bs_len -= length;
94 bs += length;
95
96 list = g_slist_prepend(list, tlv);
97 }
98
99 return g_slist_reverse(list);
76 } 100 }
77 101
78 GSList * 102 GSList *
79 msn_tlvlist_read(char *bs, size_t bs_len) 103 msn_tlvlist_copy(GSList *orig)
80 {
81 GSList *list = NULL;
82
83 while (bs_len > 0) {
84 list = msn_tlv_read(list, bs, &bs_len);
85 if (list == NULL)
86 return NULL;
87 }
88
89 return g_slist_reverse(list);
90 }
91
92 GSList *msn_tlvlist_copy(GSList *orig)
93 { 104 {
94 GSList *new = NULL; 105 GSList *new = NULL;
95 msn_tlv_t *tlv; 106 msn_tlv_t *tlv;
96 107
97 while (orig != NULL) { 108 while (orig != NULL) {
265 msn_write8(v8, value); 276 msn_write8(v8, value);
266 277
267 return msn_tlvlist_replace_raw(list, type, 1, v8); 278 return msn_tlvlist_replace_raw(list, type, 1, v8);
268 } 279 }
269 280
270 int 281 int
271 msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value) 282 msn_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
272 { 283 {
273 char v32[4]; 284 char v32[4];
274 285
275 msn_write32be(v32, value); 286 msn_write32be(v32, value);
300 311
301 cur = next; 312 cur = next;
302 } 313 }
303 } 314 }
304 315
305 #if 0 316 char *
306 int 317 msn_tlvlist_write(GSList *list, size_t *out_len)
307 msn_tlvlist_write(ByteStream *bs, GSList **list) 318 {
308 { 319 char *buf;
309 int goodbuflen; 320 char *tmp;
310 GSList *cur; 321 size_t bytes_left;
311 msn_tlv_t *tlv; 322 size_t total_len;
312 323
313 /* do an initial run to test total length */ 324 tmp = buf = g_malloc(256);
314 goodbuflen = msn_tlvlist_size(*list); 325 bytes_left = total_len = 256;
315 326
316 if (goodbuflen > byte_stream_bytes_left(bs)) 327 for (; list; list = g_slist_next(list)) {
317 return 0; /* not enough buffer */ 328 msn_tlv_t *tlv = (msn_tlv_t *)list->data;
318 329
319 /* do the real write-out */ 330 if (G_UNLIKELY(tlv->length + 2 > bytes_left)) {
320 for (cur = *list; cur; cur = cur->next) { 331 buf = g_realloc(buf, total_len + 256);
321 tlv = cur->data; 332 bytes_left += 256;
322 byte_stream_put16(bs, tlv->type); 333 total_len += 256;
323 byte_stream_put16(bs, tlv->length); 334 tmp = buf + (total_len - bytes_left);
324 if (tlv->length > 0) 335 }
325 byte_stream_putraw(bs, tlv->value, tlv->length); 336
326 } 337 msn_push8(tmp, tlv->type);
327 338 msn_push8(tmp, tlv->length);
328 return 1; /* TODO: This is a nonsensical return */ 339 memcpy(tmp, tlv->value, tlv->length);
329 } 340 tmp += tlv->length;
330 #endif 341
342 bytes_left -= (tlv->length + 2);
343 }
344
345 /* Align length to multiple of 4 */
346 total_len = total_len - bytes_left;
347 bytes_left = 4 - total_len % 4;
348 if (bytes_left != 4)
349 memset(tmp, 0, bytes_left);
350 else
351 bytes_left = 0;
352
353 *out_len = total_len + bytes_left;
354
355 return buf;
356 }
331 357
332 msn_tlv_t * 358 msn_tlv_t *
333 msn_tlv_gettlv(GSList *list, const guint16 type, const int nth) 359 msn_tlv_gettlv(GSList *list, const guint16 type, const int nth)
334 { 360 {
335 msn_tlv_t *tlv; 361 msn_tlv_t *tlv;