5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
19 /* Implementation of Attribute Payload routines */
22 #include "silcincludes.h"
23 #include "silcattrs.h"
25 /******************************************************************************
29 ******************************************************************************/
31 struct SilcAttributePayloadStruct {
32 SilcAttribute attribute;
33 SilcAttributeFlags flags;
38 /* Internal routine for encoding a attribute */
40 static unsigned char *
41 silc_attribute_payload_encode_int(SilcAttribute attribute,
42 SilcAttributeFlags flags,
44 SilcUInt32 object_size,
47 SilcBuffer tmpbuf = NULL;
48 unsigned char tmp[4], *str = NULL, *ret;
51 /* Encode according to attribute type */
52 if (flags & SILC_ATTRIBUTE_FLAG_VALID) {
53 if (!object && !object_size)
58 case SILC_ATTRIBUTE_USER_INFO:
60 SilcVCard vcard = object;
61 if (object_size != sizeof(*vcard))
63 str = silc_vcard_encode(vcard, &object_size);
70 case SILC_ATTRIBUTE_SERVICE:
72 SilcAttributeObjService *service = object;
73 if (object_size != sizeof(*service))
75 len = strlen(service->address);
76 str = silc_malloc(7 + len);
79 SILC_PUT32_MSB(service->port, str);
80 SILC_PUT16_MSB(len, str + 4);
81 memcpy(str + 6, service->address, len);
82 str[6 + len] = service->status;
84 object_size = 7 + len;
88 case SILC_ATTRIBUTE_STATUS_MOOD:
89 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
91 SilcUInt32 mask = (SilcUInt32)object;
92 if (object_size != sizeof(SilcUInt32))
94 SILC_PUT32_MSB(mask, tmp);
96 object_size = sizeof(SilcUInt32);
100 case SILC_ATTRIBUTE_STATUS_FREETEXT:
101 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
102 case SILC_ATTRIBUTE_TIMEZONE:
104 unsigned char *string = object;
105 str = silc_malloc(2 + object_size);
108 SILC_PUT16_MSB(object_size, str);
109 memcpy(str + 2, string, object_size);
115 case SILC_ATTRIBUTE_STATUS_MESSAGE:
116 case SILC_ATTRIBUTE_EXTENSION:
118 SilcAttributeObjMime *mime = object;
119 if (object_size != sizeof(*mime))
121 object = (void *)mime->mime;
122 object_size = mime->mime_len;
126 case SILC_ATTRIBUTE_GEOLOCATION:
128 SilcAttributeObjGeo *geo = object;
129 if (object_size != sizeof(*geo))
132 (geo->longitude ? strlen(geo->longitude) : 0) +
133 (geo->latitude ? strlen(geo->latitude) : 0) +
134 (geo->altitude ? strlen(geo->altitude) : 0) +
135 (geo->accuracy ? strlen(geo->accuracy) : 0);
138 tmpbuf = silc_buffer_alloc_size(8 + len);
141 silc_buffer_format(tmpbuf,
142 SILC_STR_UI16_STRING(geo->longitude),
143 SILC_STR_UI16_STRING(geo->latitude),
144 SILC_STR_UI16_STRING(geo->altitude),
145 SILC_STR_UI16_STRING(geo->accuracy),
147 object = tmpbuf->data;
148 object_size = tmpbuf->len;
152 case SILC_ATTRIBUTE_DEVICE_INFO:
154 SilcAttributeObjDevice *dev = object;
155 if (object_size != sizeof(*dev))
158 (dev->manufacturer ? strlen(dev->manufacturer) : 0) +
159 (dev->version ? strlen(dev->version) : 0) +
160 (dev->model ? strlen(dev->model) : 0) +
161 (dev->language ? strlen(dev->language) : 0);
162 tmpbuf = silc_buffer_alloc_size(4 + 8 + len);
165 silc_buffer_format(tmpbuf,
166 SILC_STR_UI_INT(dev->type),
167 SILC_STR_UI16_STRING(dev->manufacturer),
168 SILC_STR_UI16_STRING(dev->version),
169 SILC_STR_UI16_STRING(dev->model),
170 SILC_STR_UI16_STRING(dev->language),
172 object = tmpbuf->data;
173 object_size = tmpbuf->len;
177 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
178 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
180 SilcAttributeObjPk *pk = object;
181 if (object_size != sizeof(*pk))
183 len = (pk->type ? strlen(pk->type) : 0);
184 tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len);
187 silc_buffer_format(tmpbuf,
188 SILC_STR_UI_SHORT(len),
189 SILC_STR_UI16_STRING(pk->type),
190 SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
192 object = tmpbuf->data;
193 object_size = tmpbuf->len;
197 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
198 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
200 SilcAttributeObjPk *pk = object;
201 if (object_size != sizeof(*pk))
204 object_size = pk->data_len;
213 ret = silc_memdup(object, object_size);
216 silc_buffer_free(tmpbuf);
220 *ret_len = object_size;
228 /* Allocates attribute payload and encodes the attribute there */
230 SilcAttributePayload silc_attribute_payload_alloc(SilcAttribute attribute,
231 SilcAttributeFlags flags,
233 SilcUInt32 object_size)
235 SilcAttributePayload attr;
237 attr = silc_calloc(1, sizeof(*attr));
241 attr->attribute = attribute;
244 silc_attribute_payload_encode_int(attribute, flags, object,
246 (SilcUInt32 *)&attr->data_len);
255 /* Parse list of payloads */
257 SilcDList silc_attribute_payload_parse(const unsigned char *payload,
258 SilcUInt32 payload_len)
260 SilcBufferStruct buffer;
262 SilcAttributePayload newp;
265 SILC_LOG_DEBUG(("Parsing Attribute Payload list"));
267 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
268 list = silc_dlist_init();
271 newp = silc_calloc(1, sizeof(*newp));
274 ret = silc_buffer_unformat(&buffer,
275 SILC_STR_UI_CHAR(&newp->attribute),
276 SILC_STR_UI_CHAR(&newp->flags),
277 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
283 if (newp->data_len > buffer.len) {
284 SILC_LOG_ERROR(("Incorrect attribute payload in list"));
288 len = 4 + newp->data_len;
289 if (buffer.len < len)
291 silc_buffer_pull(&buffer, len);
293 silc_dlist_add(list, newp);
299 silc_attribute_payload_list_free(list);
303 /* Encode one attribute payload to buffer */
305 SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
306 SilcAttribute attribute,
307 SilcAttributeFlags flags,
309 SilcUInt32 object_size)
311 object = silc_attribute_payload_encode_int(attribute, flags, object,
312 object_size, &object_size);
313 attrs = silc_attribute_payload_encode_data(attrs, attribute, flags,
314 (const unsigned char *)object,
320 /* Encoded the attribute data directly to buffer */
322 SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
323 SilcAttribute attribute,
324 SilcAttributeFlags flags,
325 const unsigned char *data,
328 SilcBuffer buffer = attrs;
332 buffer = silc_buffer_realloc(buffer,
333 (buffer ? buffer->truelen + len : len));
336 silc_buffer_pull(buffer, buffer->len);
337 silc_buffer_pull_tail(buffer, len);
338 silc_buffer_format(buffer,
339 SILC_STR_UI_CHAR(attribute),
340 SILC_STR_UI_CHAR(flags),
341 SILC_STR_UI_SHORT((SilcUInt16)data_len),
342 SILC_STR_UI_XNSTRING(data, data_len),
344 silc_buffer_push(buffer, buffer->data - buffer->head);
349 /* Free Attribute Payload */
351 void silc_attribute_payload_free(SilcAttributePayload payload)
353 silc_free(payload->data);
357 /* Free's list of Attribute Payloads */
359 void silc_attribute_payload_list_free(SilcDList list)
361 SilcAttributePayload entry;
363 silc_dlist_start(list);
364 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
365 silc_attribute_payload_free(entry);
366 silc_dlist_del(list, entry);
369 silc_dlist_uninit(list);
372 /* Return attribute type */
374 SilcAttribute silc_attribute_get_attribute(SilcAttributePayload payload)
376 return payload->attribute;
379 /* Return attribute flags */
381 SilcAttributeFlags silc_attribute_get_flags(SilcAttributePayload payload)
383 return payload->flags;
386 /* Return attribute data from the payload */
388 const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
389 SilcUInt32 *data_len)
392 *data_len = payload->data_len;
393 return (const unsigned char *)payload->data;
396 /* Return parsed attribute object */
398 bool silc_attribute_get_object(SilcAttributePayload payload,
399 void **object, SilcUInt32 object_size)
404 if (!object || !(*object) || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
407 switch (payload->attribute) {
408 case SILC_ATTRIBUTE_USER_INFO:
410 SilcVCard vcard = *object;
411 if (object_size != sizeof(*vcard))
413 if (!silc_vcard_decode(payload->data, payload->data_len, vcard))
419 case SILC_ATTRIBUTE_SERVICE:
421 SilcAttributeObjService *service = *object;
422 if (object_size != sizeof(*service))
424 if (payload->data_len < 7)
426 SILC_GET32_MSB(service->port, payload->data);
427 SILC_GET16_MSB(len, payload->data + 4);
428 if (payload->data_len < 7 + len)
430 memcpy(service->address, payload->data + 6,
431 (len < sizeof(service->address) - 1 ? len :
432 sizeof(service->address) - 1));
433 service->status = payload->data[6 + len] ? TRUE : FALSE;
438 case SILC_ATTRIBUTE_STATUS_MOOD:
439 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
441 SilcUInt32 *mask = *object;
442 if (object_size != sizeof(SilcUInt32))
444 if (payload->data_len < 4)
446 SILC_GET32_MSB(*mask, payload->data);
451 case SILC_ATTRIBUTE_STATUS_FREETEXT:
452 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
453 case SILC_ATTRIBUTE_TIMEZONE:
455 char *string = *object;
456 if (payload->data_len < 2)
458 SILC_GET16_MSB(len, payload->data);
459 if (payload->data_len < 2 + len)
461 if (object_size < len)
463 memcpy(string, payload->data + 2, len);
468 case SILC_ATTRIBUTE_STATUS_MESSAGE:
469 case SILC_ATTRIBUTE_EXTENSION:
471 SilcAttributeObjMime *mime = *object;
472 if (object_size != sizeof(*mime))
474 mime->mime = (const unsigned char *)payload->data;
475 mime->mime_len = payload->data_len;
480 case SILC_ATTRIBUTE_GEOLOCATION:
482 SilcAttributeObjGeo *geo = *object;
483 SilcBufferStruct buffer;
485 if (object_size != sizeof(*geo))
487 silc_buffer_set(&buffer, (unsigned char *)payload->data,
489 res = silc_buffer_unformat(&buffer,
490 SILC_STR_UI16_STRING_ALLOC(&geo->longitude),
491 SILC_STR_UI16_STRING_ALLOC(&geo->latitude),
492 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
493 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
501 case SILC_ATTRIBUTE_DEVICE_INFO:
503 SilcAttributeObjDevice *dev = *object;
504 SilcBufferStruct buffer;
507 if (object_size != sizeof(*dev))
509 silc_buffer_set(&buffer, (unsigned char *)payload->data,
512 silc_buffer_unformat(&buffer,
513 SILC_STR_UI_INT(&type),
514 SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer),
515 SILC_STR_UI16_STRING_ALLOC(&dev->version),
516 SILC_STR_UI16_STRING_ALLOC(&dev->model),
517 SILC_STR_UI16_STRING_ALLOC(&dev->language),
526 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
527 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
529 SilcAttributeObjPk *pk = *object;
530 SilcBufferStruct buffer;
532 if (object_size != sizeof(*pk))
534 silc_buffer_set(&buffer, (unsigned char *)payload->data,
537 silc_buffer_unformat(&buffer,
538 SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
542 pk->data = silc_memdup(payload->data + 2 + len,
543 payload->data_len - 2 - len);
544 pk->data_len = payload->data_len - 2 - len;
549 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
550 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
552 SilcAttributeObjPk *pk = *object;
553 if (object_size != sizeof(*pk))
556 pk->data = silc_memdup(payload->data, payload->data_len);
557 pk->data_len = payload->data_len;