Mercurial > pidgin
annotate libfaim/tlv.c @ 1999:591ebfe8ec00
[gaim-migrate @ 2009]
can be in two rooms of the same name
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Tue, 12 Jun 2001 07:57:27 +0000 |
| parents | ec31e23aadc7 |
| children |
| rev | line source |
|---|---|
| 1535 | 1 |
| 2 #define FAIM_INTERNAL | |
| 3 #include <aim.h> | |
| 4 | |
| 5 /** | |
| 6 * aim_readtlvchain - Read a TLV chain from a buffer. | |
| 7 * @buf: Input buffer | |
| 8 * @maxlen: Length of input buffer | |
| 9 * | |
| 10 * Reads and parses a series of TLV patterns from a data buffer; the | |
| 11 * returned structure is manipulatable with the rest of the TLV | |
| 12 * routines. When done with a TLV chain, aim_freetlvchain() should | |
| 13 * be called to free the dynamic substructures. | |
| 14 * | |
| 15 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
16 faim_export struct aim_tlvlist_t *aim_readtlvchain(const unsigned char *buf, const int maxlen) |
| 1535 | 17 { |
| 18 int pos; | |
| 19 struct aim_tlvlist_t *list; | |
| 20 struct aim_tlvlist_t *cur; | |
| 21 | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
22 unsigned short type, length; |
| 1535 | 23 |
| 24 if (!buf) | |
| 25 return NULL; | |
| 26 | |
| 27 list = NULL; | |
| 28 | |
| 29 pos = 0; | |
| 30 | |
| 31 while (pos < maxlen) | |
| 32 { | |
| 33 type = aimutil_get16(buf+pos); | |
| 34 pos += 2; | |
| 35 | |
| 36 if (pos < maxlen) | |
| 37 { | |
| 38 length = aimutil_get16(buf+pos); | |
| 39 pos += 2; | |
| 40 | |
| 41 if ((pos+length) <= maxlen) | |
| 42 { | |
| 43 /* | |
| 44 * Okay, so now AOL has decided that any TLV of | |
| 45 * type 0x0013 can only be two bytes, despite | |
| 46 * what the actual given length is. So here | |
| 47 * we dump any invalid TLVs of that sort. Hopefully | |
| 48 * theres no special cases to this special case. | |
| 49 * - mid (30jun2000) | |
| 50 */ | |
| 51 if ((type == 0x0013) && (length != 0x0002)) | |
| 52 length = 0x0002; | |
| 53 else { | |
| 54 cur = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 55 memset(cur, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 56 | |
| 57 cur->tlv = aim_createtlv(); | |
| 58 cur->tlv->type = type; | |
| 59 cur->tlv->length = length; | |
| 60 if (length) { | |
| 61 cur->tlv->value = (unsigned char *)malloc(length); | |
| 62 memcpy(cur->tlv->value, buf+pos, length); | |
| 63 } | |
| 64 | |
| 65 cur->next = list; | |
| 66 list = cur; | |
| 67 } | |
| 68 pos += length; | |
| 69 } | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 return list; | |
| 74 } | |
| 75 | |
| 76 /** | |
| 77 * aim_freetlvchain - Free a TLV chain structure | |
| 78 * @list: Chain to be freed | |
| 79 * | |
| 80 * Walks the list of TLVs in the passed TLV chain and | |
| 81 * frees each one. Note that any references to this data | |
| 82 * should be removed before calling this. | |
| 83 * | |
| 84 */ | |
| 85 faim_export void aim_freetlvchain(struct aim_tlvlist_t **list) | |
| 86 { | |
| 87 struct aim_tlvlist_t *cur, *cur2; | |
| 88 | |
| 89 if (!list || !(*list)) | |
| 90 return; | |
| 91 | |
| 92 cur = *list; | |
| 93 while (cur) | |
| 94 { | |
| 95 aim_freetlv(&cur->tlv); | |
| 96 cur2 = cur->next; | |
| 97 free(cur); | |
| 98 cur = cur2; | |
| 99 } | |
| 100 list = NULL; | |
| 101 return; | |
| 102 } | |
| 103 | |
| 104 /** | |
| 105 * aim_counttlvchain - Count the number of TLVs in a chain | |
| 106 * @list: Chain to be counted | |
| 107 * | |
| 108 * Returns the number of TLVs stored in the passed chain. | |
| 109 * | |
| 110 */ | |
| 111 faim_export int aim_counttlvchain(struct aim_tlvlist_t **list) | |
| 112 { | |
| 113 struct aim_tlvlist_t *cur; | |
| 114 int count = 0; | |
| 115 | |
| 116 if (!list || !(*list)) | |
| 117 return 0; | |
| 118 | |
| 119 for (cur = *list; cur; cur = cur->next) | |
| 120 count++; | |
| 121 | |
| 122 return count; | |
| 123 } | |
| 124 | |
| 125 /** | |
| 126 * aim_sizetlvchain - Count the number of bytes in a TLV chain | |
| 127 * @list: Chain to be sized | |
| 128 * | |
| 129 * Returns the number of bytes that would be needed to | |
| 130 * write the passed TLV chain to a data buffer. | |
| 131 * | |
| 132 */ | |
| 133 faim_export int aim_sizetlvchain(struct aim_tlvlist_t **list) | |
| 134 { | |
| 135 struct aim_tlvlist_t *cur; | |
| 136 int size = 0; | |
| 137 | |
| 138 if (!list || !(*list)) | |
| 139 return 0; | |
| 140 | |
| 141 for (cur = *list; cur; cur = cur->next) | |
| 142 size += (4 + cur->tlv->length); | |
| 143 | |
| 144 return size; | |
| 145 } | |
| 146 | |
| 147 /** | |
| 148 * aim_addtlvtochain_str - Add a string to a TLV chain | |
| 149 * @list: Desination chain (%NULL pointer if empty) | |
| 150 * @type: TLV type | |
| 151 * @str: String to add | |
| 152 * @len: Length of string to add (not including %NULL) | |
| 153 * | |
| 154 * Adds the passed string as a TLV element of the passed type | |
| 155 * to the TLV chain. | |
| 156 * | |
| 157 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
158 faim_export int aim_addtlvtochain_str(struct aim_tlvlist_t **list, const unsigned short type, const char *str, const int len) |
| 1535 | 159 { |
| 160 struct aim_tlvlist_t *newtlv; | |
| 161 struct aim_tlvlist_t *cur; | |
| 162 | |
| 163 if (!list) | |
| 164 return 0; | |
| 165 | |
| 166 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 167 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 168 | |
| 169 newtlv->tlv = aim_createtlv(); | |
| 170 newtlv->tlv->type = type; | |
| 171 newtlv->tlv->length = len; | |
| 172 newtlv->tlv->value = (unsigned char *)malloc(newtlv->tlv->length*sizeof(unsigned char)); | |
| 173 memcpy(newtlv->tlv->value, str, newtlv->tlv->length); | |
| 174 | |
| 175 newtlv->next = NULL; | |
| 176 | |
| 177 if (*list == NULL) { | |
| 178 *list = newtlv; | |
| 179 } else if ((*list)->next == NULL) { | |
| 180 (*list)->next = newtlv; | |
| 181 } else { | |
| 182 for(cur = *list; cur->next; cur = cur->next) | |
| 183 ; | |
| 184 cur->next = newtlv; | |
| 185 } | |
| 186 return newtlv->tlv->length; | |
| 187 } | |
| 188 | |
| 189 /** | |
| 190 * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain | |
| 191 * @list: Destination chain | |
| 192 * @type: TLV type to add | |
| 193 * @val: Value to add | |
| 194 * | |
| 195 * Adds a two-byte unsigned integer to a TLV chain. | |
| 196 * | |
| 197 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
198 faim_export int aim_addtlvtochain16(struct aim_tlvlist_t **list, const unsigned short type, const unsigned short val) |
| 1535 | 199 { |
| 200 struct aim_tlvlist_t *newtl; | |
| 201 struct aim_tlvlist_t *cur; | |
| 202 | |
| 203 if (!list) | |
| 204 return 0; | |
| 205 | |
| 206 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 207 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 208 | |
| 209 newtl->tlv = aim_createtlv(); | |
| 210 newtl->tlv->type = type; | |
| 211 newtl->tlv->length = 2; | |
| 212 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); | |
| 213 aimutil_put16(newtl->tlv->value, val); | |
| 214 | |
| 215 newtl->next = NULL; | |
| 216 | |
| 217 if (*list == NULL) { | |
| 218 *list = newtl; | |
| 219 } else if ((*list)->next == NULL) { | |
| 220 (*list)->next = newtl; | |
| 221 } else { | |
| 222 for(cur = *list; cur->next; cur = cur->next) | |
| 223 ; | |
| 224 cur->next = newtl; | |
| 225 } | |
| 226 return 2; | |
| 227 } | |
| 228 | |
| 229 /** | |
| 230 * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain | |
| 231 * @list: Destination chain | |
| 232 * @type: TLV type to add | |
| 233 * @val: Value to add | |
| 234 * | |
| 235 * Adds a four-byte unsigned integer to a TLV chain. | |
| 236 * | |
| 237 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
238 faim_export int aim_addtlvtochain32(struct aim_tlvlist_t **list, const unsigned short type, const unsigned long val) |
| 1535 | 239 { |
| 240 struct aim_tlvlist_t *newtl; | |
| 241 struct aim_tlvlist_t *cur; | |
| 242 | |
| 243 if (!list) | |
| 244 return 0; | |
| 245 | |
| 246 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 247 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 248 | |
| 249 newtl->tlv = aim_createtlv(); | |
| 250 newtl->tlv->type = type; | |
| 251 newtl->tlv->length = 4; | |
| 252 newtl->tlv->value = (unsigned char *)malloc(newtl->tlv->length*sizeof(unsigned char)); | |
| 253 aimutil_put32(newtl->tlv->value, val); | |
| 254 | |
| 255 newtl->next = NULL; | |
| 256 | |
| 257 if (*list == NULL) { | |
| 258 *list = newtl; | |
| 259 } else if ((*list)->next == NULL) { | |
| 260 (*list)->next = newtl; | |
| 261 } else { | |
| 262 for(cur = *list; cur->next; cur = cur->next) | |
| 263 ; | |
| 264 cur->next = newtl; | |
| 265 } | |
| 266 return 4; | |
| 267 } | |
| 268 | |
| 269 /** | |
| 270 * aim_addtlvtochain_caps - Add a capability block to a TLV chain | |
| 271 * @list: Destination chain | |
| 272 * @type: TLV type to add | |
| 273 * @caps: Bitfield of capability flags to send | |
| 274 * | |
| 275 * Adds a block of capability blocks to a TLV chain. The bitfield | |
| 276 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants: | |
| 277 * | |
| 278 * %AIM_CAPS_BUDDYICON Supports Buddy Icons | |
| 279 * | |
| 280 * %AIM_CAPS_VOICE Supports Voice Chat | |
| 281 * | |
| 282 * %AIM_CAPS_IMIMAGE Supports DirectIM/IMImage | |
| 283 * | |
| 284 * %AIM_CAPS_CHAT Supports Chat | |
| 285 * | |
| 286 * %AIM_CAPS_GETFILE Supports Get File functions | |
| 287 * | |
| 288 * %AIM_CAPS_SENDFILE Supports Send File functions | |
| 289 * | |
| 290 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
291 faim_export int aim_addtlvtochain_caps(struct aim_tlvlist_t **list, const unsigned short type, const unsigned short caps) |
| 1535 | 292 { |
| 293 unsigned char buf[128]; /* icky fixed length buffer */ | |
| 294 struct aim_tlvlist_t *newtl; | |
| 295 struct aim_tlvlist_t *cur; | |
| 296 | |
| 297 if(!list) | |
| 298 return 0; | |
| 299 | |
| 300 newtl = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 301 memset(newtl, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 302 | |
| 303 newtl->tlv = aim_createtlv(); | |
| 304 newtl->tlv->type = type; | |
| 305 | |
| 306 newtl->tlv->length = aim_putcap(buf, sizeof(buf), caps); | |
| 307 newtl->tlv->value = (unsigned char *)calloc(1, newtl->tlv->length); | |
| 308 memcpy(newtl->tlv->value, buf, newtl->tlv->length); | |
| 309 | |
| 310 newtl->next = NULL; | |
| 311 | |
| 312 if (*list == NULL) { | |
| 313 *list = newtl; | |
| 314 } else if ((*list)->next == NULL) { | |
| 315 (*list)->next = newtl; | |
| 316 } else { | |
| 317 for(cur = *list; cur->next; cur = cur->next) | |
| 318 ; | |
| 319 cur->next = newtl; | |
| 320 } | |
| 321 return newtl->tlv->length; | |
| 322 } | |
| 323 | |
| 324 /** | |
| 325 * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain | |
| 326 * @list: Destination chain | |
| 327 * @type: TLV type to add | |
| 328 * | |
| 329 * Adds a TLV with a zero length to a TLV chain. | |
| 330 * | |
| 331 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
332 faim_internal int aim_addtlvtochain_noval(struct aim_tlvlist_t **list, const unsigned short type) |
| 1535 | 333 { |
| 334 struct aim_tlvlist_t *newtlv; | |
| 335 struct aim_tlvlist_t *cur; | |
| 336 | |
| 337 newtlv = (struct aim_tlvlist_t *)malloc(sizeof(struct aim_tlvlist_t)); | |
| 338 memset(newtlv, 0x00, sizeof(struct aim_tlvlist_t)); | |
| 339 | |
| 340 newtlv->tlv = aim_createtlv(); | |
| 341 newtlv->tlv->type = type; | |
| 342 newtlv->tlv->length = 0; | |
| 343 newtlv->tlv->value = NULL; | |
| 344 | |
| 345 newtlv->next = NULL; | |
| 346 | |
| 347 if (*list == NULL) { | |
| 348 *list = newtlv; | |
| 349 } else if ((*list)->next == NULL) { | |
| 350 (*list)->next = newtlv; | |
| 351 } else { | |
| 352 for(cur = *list; cur->next; cur = cur->next) | |
| 353 ; | |
| 354 cur->next = newtlv; | |
| 355 } | |
| 356 return newtlv->tlv->length; | |
| 357 } | |
| 358 | |
| 359 /** | |
| 360 * aim_writetlvchain - Write a TLV chain into a data buffer. | |
| 361 * @buf: Destination buffer | |
| 362 * @buflen: Maximum number of bytes that will be written to buffer | |
| 363 * @list: Source TLV chain | |
| 364 * | |
| 365 * Copies a TLV chain into a raw data buffer, writing only the number | |
| 366 * of bytes specified. This operation does not free the chain; | |
| 367 * aim_freetlvchain() must still be called to free up the memory used | |
| 368 * by the chain structures. | |
| 369 * | |
| 370 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
371 faim_export int aim_writetlvchain(unsigned char *buf, int buflen, struct aim_tlvlist_t **list) |
| 1535 | 372 { |
| 373 int goodbuflen = 0; | |
| 374 int i = 0; | |
| 375 struct aim_tlvlist_t *cur; | |
| 376 | |
| 377 if (!list || !buf || !buflen) | |
| 378 return 0; | |
| 379 | |
| 380 /* do an initial run to test total length */ | |
| 381 for (cur = *list; cur; cur = cur->next) { | |
| 382 goodbuflen += 2 + 2; /* type + len */ | |
| 383 goodbuflen += cur->tlv->length; | |
| 384 } | |
| 385 | |
| 386 if (goodbuflen > buflen) | |
| 387 return 0; /* not enough buffer */ | |
| 388 | |
| 389 /* do the real write-out */ | |
| 390 for (cur = *list; cur; cur = cur->next) { | |
| 391 i += aimutil_put16(buf+i, cur->tlv->type); | |
| 392 i += aimutil_put16(buf+i, cur->tlv->length); | |
| 393 memcpy(buf+i, cur->tlv->value, cur->tlv->length); | |
| 394 i += cur->tlv->length; | |
| 395 } | |
| 396 | |
| 397 return i; | |
| 398 } | |
| 399 | |
| 400 | |
| 401 /** | |
| 402 * aim_gettlv - Grab the Nth TLV of type type in the TLV list list. | |
| 403 * @list: Source chain | |
| 404 * @type: Requested TLV type | |
| 405 * @nth: Index of TLV of type to get | |
| 406 * | |
| 407 * Returns a pointer to an aim_tlv_t of the specified type; | |
| 408 * %NULL on error. The @nth parameter is specified starting at %1. | |
| 409 * In most cases, there will be no more than one TLV of any type | |
| 410 * in a chain. | |
| 411 * | |
| 412 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
413 faim_export struct aim_tlv_t *aim_gettlv(struct aim_tlvlist_t *list, const unsigned short type, const int nth) |
| 1535 | 414 { |
| 415 int i; | |
| 416 struct aim_tlvlist_t *cur; | |
| 417 | |
| 418 i = 0; | |
| 419 for (cur = list; cur != NULL; cur = cur->next) | |
| 420 { | |
| 421 if (cur && cur->tlv) | |
| 422 { | |
| 423 if (cur->tlv->type == type) | |
| 424 i++; | |
| 425 if (i >= nth) | |
| 426 return cur->tlv; | |
| 427 } | |
| 428 } | |
| 429 return NULL; | |
| 430 } | |
| 431 | |
| 432 /** | |
| 433 * aim_gettlv_str - Retrieve the Nth TLV in chain as a string. | |
| 434 * @list: Source TLV chain | |
| 435 * @type: TLV type to search for | |
| 436 * @nth: Index of TLV to return | |
| 437 * | |
| 438 * Same as aim_gettlv(), except that the return value is a %NULL- | |
| 439 * terminated string instead of an aim_tlv_t. This is a | |
| 440 * dynamic buffer and must be freed by the caller. | |
| 441 * | |
| 442 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
443 faim_export char *aim_gettlv_str(struct aim_tlvlist_t *list, const unsigned short type, const int nth) |
| 1535 | 444 { |
| 445 struct aim_tlv_t *tlv; | |
| 446 char *newstr; | |
| 447 | |
| 448 if (!(tlv = aim_gettlv(list, type, nth))) | |
| 449 return NULL; | |
| 450 | |
| 451 newstr = (char *) malloc(tlv->length + 1); | |
| 452 memcpy(newstr, tlv->value, tlv->length); | |
| 453 *(newstr + tlv->length) = '\0'; | |
| 454 | |
| 455 return newstr; | |
| 456 } | |
| 457 | |
| 458 /** | |
| 459 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer. | |
| 460 * @list: Source TLV chain | |
| 461 * @type: TLV type to search for | |
| 462 * @nth: Index of TLV to return | |
| 463 * | |
| 464 * Same as aim_gettlv(), except that the return value is a | |
| 465 * 8bit integer instead of an aim_tlv_t. | |
| 466 * | |
| 467 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
468 faim_internal unsigned char aim_gettlv8(struct aim_tlvlist_t *list, const unsigned short type, const int num) |
| 1535 | 469 { |
| 470 struct aim_tlv_t *tlv; | |
| 471 | |
| 472 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
| 473 return 0; /* erm */ | |
| 474 return aimutil_get8(tlv->value); | |
| 475 } | |
| 476 | |
| 477 /** | |
| 478 * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer. | |
| 479 * @list: Source TLV chain | |
| 480 * @type: TLV type to search for | |
| 481 * @nth: Index of TLV to return | |
| 482 * | |
| 483 * Same as aim_gettlv(), except that the return value is a | |
| 484 * 16bit integer instead of an aim_tlv_t. | |
| 485 * | |
| 486 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
487 faim_internal unsigned short aim_gettlv16(struct aim_tlvlist_t *list, const unsigned short type, const int num) |
| 1535 | 488 { |
| 489 struct aim_tlv_t *tlv; | |
| 490 | |
| 491 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
| 492 return 0; /* erm */ | |
| 493 return aimutil_get16(tlv->value); | |
| 494 } | |
| 495 | |
| 496 /** | |
| 497 * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer. | |
| 498 * @list: Source TLV chain | |
| 499 * @type: TLV type to search for | |
| 500 * @nth: Index of TLV to return | |
| 501 * | |
| 502 * Same as aim_gettlv(), except that the return value is a | |
| 503 * 32bit integer instead of an aim_tlv_t. | |
| 504 * | |
| 505 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
506 faim_internal unsigned long aim_gettlv32(struct aim_tlvlist_t *list, const unsigned short type, const int num) |
| 1535 | 507 { |
| 508 struct aim_tlv_t *tlv; | |
| 509 | |
| 510 if (!(tlv = aim_gettlv(list, type, num)) || !tlv->value) | |
| 511 return 0; /* erm */ | |
| 512 return aimutil_get32(tlv->value); | |
| 513 } | |
| 514 | |
| 515 /** | |
| 516 * aim_grabtlv - Grab a single TLV from a data buffer | |
| 517 * @src: Source data buffer (must be at least 4 bytes long) | |
| 518 * | |
| 519 * Creates a TLV structure aim_tlv_t and returns it | |
| 520 * filled with values from a buffer, possibly including a | |
| 521 * dynamically allocated buffer for the value portion. | |
| 522 * | |
| 523 * Both the aim_tlv_t and the tlv->value pointer | |
| 524 * must be freed by the caller if non-%NULL. | |
| 525 * | |
| 526 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
527 faim_export struct aim_tlv_t *aim_grabtlv(const unsigned char *src) |
| 1535 | 528 { |
| 529 struct aim_tlv_t *dest = NULL; | |
| 530 | |
| 531 dest = aim_createtlv(); | |
| 532 | |
| 533 dest->type = src[0] << 8; | |
| 534 dest->type += src[1]; | |
| 535 | |
| 536 dest->length = src[2] << 8; | |
| 537 dest->length += src[3]; | |
| 538 | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
539 dest->value = (unsigned char *) malloc(dest->length); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
540 memset(dest->value, 0, dest->length); |
| 1535 | 541 |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
542 memcpy(dest->value, &(src[4]), dest->length); |
| 1535 | 543 |
| 544 return dest; | |
| 545 } | |
| 546 | |
| 547 /** | |
| 548 * aim_grabtlvstr - Grab a single TLV from a data buffer as string | |
| 549 * @src: Source data buffer (must be at least 4 bytes long) | |
| 550 * | |
| 551 * Creates a TLV structure aim_tlv_t and returns it | |
| 552 * filled with values from a buffer, possibly including a | |
| 553 * dynamically allocated buffer for the value portion, which | |
| 554 * is %NULL-terminated as a string. | |
| 555 * | |
| 556 * Both the aim_tlv_t and the tlv->value pointer | |
| 557 * must be freed by the caller if non-%NULL. | |
| 558 * | |
| 559 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
560 faim_export struct aim_tlv_t *aim_grabtlvstr(const unsigned char *src) |
| 1535 | 561 { |
| 562 struct aim_tlv_t *dest = NULL; | |
| 563 | |
| 564 dest = aim_createtlv(); | |
| 565 | |
| 566 dest->type = src[0] << 8; | |
| 567 dest->type += src[1]; | |
| 568 | |
| 569 dest->length = src[2] << 8; | |
| 570 dest->length += src[3]; | |
| 571 | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
572 dest->value = (unsigned char *) malloc(dest->length+1); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
573 memset(dest->value, 0, dest->length+1); |
| 1535 | 574 |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
575 memcpy(dest->value, src+4, dest->length); |
| 1535 | 576 dest->value[dest->length] = '\0'; |
| 577 | |
| 578 return dest; | |
| 579 } | |
| 580 | |
| 581 /** | |
| 582 * aim_puttlv - Write a aim_tlv_t into a data buffer | |
| 583 * @dest: Destination data buffer | |
| 584 * @newtlv: Source TLV structure | |
| 585 * | |
| 586 * Writes out the passed TLV structure into the buffer. No bounds | |
| 587 * checking is done on the output buffer. | |
| 588 * | |
| 589 * The passed aim_tlv_t is not freed. aim_freetlv() should | |
| 590 * still be called by the caller to free the structure. | |
| 591 * | |
| 592 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
593 faim_export int aim_puttlv(unsigned char *dest, struct aim_tlv_t *newtlv) |
| 1535 | 594 { |
| 595 int i=0; | |
| 596 | |
| 597 dest[i++] = newtlv->type >> 8; | |
| 598 dest[i++] = newtlv->type & 0x00FF; | |
| 599 dest[i++] = newtlv->length >> 8; | |
| 600 dest[i++] = newtlv->length & 0x00FF; | |
| 601 memcpy(&(dest[i]), newtlv->value, newtlv->length); | |
| 602 i+=newtlv->length; | |
| 603 return i; | |
| 604 } | |
| 605 | |
| 606 /** | |
| 607 * aim_createtlv - Generate an aim_tlv_t structure. | |
| 608 * | |
| 609 * Allocates an empty TLV structure and returns a pointer | |
| 610 * to it; %NULL on error. | |
| 611 * | |
| 612 */ | |
| 613 faim_export struct aim_tlv_t *aim_createtlv(void) | |
| 614 { | |
| 615 struct aim_tlv_t *newtlv; | |
| 616 | |
| 617 if (!(newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)))) | |
| 618 return NULL; | |
| 619 memset(newtlv, 0, sizeof(struct aim_tlv_t)); | |
| 620 return newtlv; | |
| 621 } | |
| 622 | |
| 623 /** | |
| 624 * aim_freetlv - Free a aim_tlv_t structure | |
| 625 * @oldtlv: TLV to be destroyed | |
| 626 * | |
| 627 * Frees both the TLV structure and the value portion. | |
| 628 * | |
| 629 */ | |
| 630 faim_export int aim_freetlv(struct aim_tlv_t **oldtlv) | |
| 631 { | |
| 632 if (!oldtlv) | |
| 633 return -1; | |
| 634 if (!*oldtlv) | |
| 635 return -1; | |
| 636 if ((*oldtlv)->value) | |
| 637 free((*oldtlv)->value); | |
| 638 free(*(oldtlv)); | |
| 639 (*oldtlv) = NULL; | |
| 640 | |
| 641 return 0; | |
| 642 } | |
| 643 | |
| 644 /** | |
| 645 * aim_puttlv_8 - Write a one-byte TLV. | |
| 646 * @buf: Destination buffer | |
| 647 * @t: TLV type | |
| 648 * @v: Value | |
| 649 * | |
| 650 * Writes a TLV with a one-byte integer value portion. | |
| 651 * | |
| 652 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
653 faim_export int aim_puttlv_8(unsigned char *buf, const unsigned short t, const unsigned char v) |
| 1535 | 654 { |
| 655 int curbyte=0; | |
| 656 | |
| 657 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); | |
| 658 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0001); | |
| 659 curbyte += aimutil_put8(buf+curbyte, (unsigned char)(v&0xff)); | |
| 660 | |
| 661 return curbyte; | |
| 662 } | |
| 663 | |
| 664 /** | |
| 665 * aim_puttlv_16 - Write a two-byte TLV. | |
| 666 * @buf: Destination buffer | |
| 667 * @t: TLV type | |
| 668 * @v: Value | |
| 669 * | |
| 670 * Writes a TLV with a two-byte integer value portion. | |
| 671 * | |
| 672 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
673 faim_export int aim_puttlv_16(unsigned char *buf, const unsigned short t, const unsigned short v) |
| 1535 | 674 { |
| 675 int curbyte=0; | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
676 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
677 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0002); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
678 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(v&0xffff)); |
| 1535 | 679 return curbyte; |
| 680 } | |
| 681 | |
| 682 /** | |
| 683 * aim_puttlv_32 - Write a four-byte TLV. | |
| 684 * @buf: Destination buffer | |
| 685 * @t: TLV type | |
| 686 * @v: Value | |
| 687 * | |
| 688 * Writes a TLV with a four-byte integer value portion. | |
| 689 * | |
| 690 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
691 faim_export int aim_puttlv_32(unsigned char *buf, const unsigned short t, const unsigned long v) |
| 1535 | 692 { |
| 693 int curbyte=0; | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
694 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
695 curbyte += aimutil_put16(buf+curbyte, (unsigned short)0x0004); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
696 curbyte += aimutil_put32(buf+curbyte, (unsigned long)(v&0xffffffff)); |
| 1535 | 697 return curbyte; |
| 698 } | |
| 699 | |
| 700 /** | |
| 701 * aim_puttlv_str - Write a string TLV. | |
| 702 * @buf: Destination buffer | |
| 703 * @t: TLV type | |
| 704 * @l: Length of string | |
| 705 * @v: String to write | |
| 706 * | |
| 707 * Writes a TLV with a string value portion. (Only the first @l | |
| 708 * bytes of the passed string will be written, which should not | |
| 709 * include the terminating NULL.) | |
| 710 * | |
| 711 */ | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
712 faim_export int aim_puttlv_str(unsigned char *buf, const unsigned short t, const int l, const char *v) |
| 1535 | 713 { |
| 714 int curbyte; | |
| 715 | |
| 716 curbyte = 0; | |
|
1593
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
717 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(t&0xffff)); |
|
ec31e23aadc7
[gaim-migrate @ 1603]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1535
diff
changeset
|
718 curbyte += aimutil_put16(buf+curbyte, (unsigned short)(l&0xffff)); |
| 1535 | 719 if (v) |
| 720 memcpy(buf+curbyte, (unsigned char *)v, l); | |
| 721 curbyte += l; | |
| 722 return curbyte; | |
| 723 } |
