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:
59 SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
62 case SILC_ATTRIBUTE_SERVICE:
64 SilcAttributeObjService *service = object;
65 if (object_size != sizeof(*service))
67 len = strlen(service->address);
68 str = silc_malloc(7 + len);
71 SILC_PUT32_MSB(service->port, str);
72 SILC_PUT16_MSB(len, str + 4);
73 memcpy(str + 6, service->address, len);
74 str[6 + len] = service->status;
76 object_size = 7 + len;
80 case SILC_ATTRIBUTE_STATUS_MOOD:
81 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
83 SilcUInt32 mask = (SilcUInt32)object;
84 if (object_size != sizeof(SilcUInt32))
86 SILC_PUT32_MSB(mask, tmp);
88 object_size = sizeof(SilcUInt32);
92 case SILC_ATTRIBUTE_STATUS_FREETEXT:
93 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
94 case SILC_ATTRIBUTE_TIMEZONE:
96 unsigned char *string = object;
97 str = silc_malloc(2 + object_size);
100 SILC_PUT16_MSB(object_size, str);
101 memcpy(str + 2, string, object_size);
107 case SILC_ATTRIBUTE_STATUS_MESSAGE:
108 case SILC_ATTRIBUTE_EXTENSION:
110 SilcAttributeObjMime *mime = object;
111 if (object_size != sizeof(*mime))
113 object = (void *)mime->mime;
114 object_size = mime->mime_len;
118 case SILC_ATTRIBUTE_GEOLOCATION:
120 SilcAttributeObjGeo *geo = object;
121 if (object_size != sizeof(*geo))
124 (geo->longitude ? strlen(geo->longitude) : 0) +
125 (geo->latitude ? strlen(geo->latitude) : 0) +
126 (geo->altitude ? strlen(geo->altitude) : 0) +
127 (geo->accuracy ? strlen(geo->accuracy) : 0);
130 tmpbuf = silc_buffer_alloc_size(8 + len);
133 silc_buffer_format(tmpbuf,
134 SILC_STR_UI16_STRING(geo->longitude),
135 SILC_STR_UI16_STRING(geo->latitude),
136 SILC_STR_UI16_STRING(geo->altitude),
137 SILC_STR_UI16_STRING(geo->accuracy),
139 object = tmpbuf->data;
140 object_size = tmpbuf->len;
144 case SILC_ATTRIBUTE_DEVICE_INFO:
146 SilcAttributeObjDevice *dev = object;
147 if (object_size != sizeof(*dev))
150 (dev->manufacturer ? strlen(dev->manufacturer) : 0) +
151 (dev->version ? strlen(dev->version) : 0) +
152 (dev->model ? strlen(dev->model) : 0) +
153 (dev->language ? strlen(dev->language) : 0);
154 tmpbuf = silc_buffer_alloc_size(4 + 8 + len);
157 silc_buffer_format(tmpbuf,
158 SILC_STR_UI_INT(dev->type),
159 SILC_STR_UI16_STRING(dev->manufacturer),
160 SILC_STR_UI16_STRING(dev->version),
161 SILC_STR_UI16_STRING(dev->model),
162 SILC_STR_UI16_STRING(dev->language),
164 object = tmpbuf->data;
165 object_size = tmpbuf->len;
169 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
170 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
172 SilcAttributeObjPk *pk = object;
173 if (object_size != sizeof(*pk))
175 len = (pk->type ? strlen(pk->type) : 0);
176 tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len);
179 silc_buffer_format(tmpbuf,
180 SILC_STR_UI_SHORT(len),
181 SILC_STR_UI16_STRING(pk->type),
182 SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
184 object = tmpbuf->data;
185 object_size = tmpbuf->len;
189 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
190 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
192 SilcAttributeObjPk *pk = object;
193 if (object_size != sizeof(*pk))
196 object_size = pk->data_len;
205 ret = silc_memdup(object, object_size);
208 silc_buffer_free(tmpbuf);
212 *ret_len = object_size;
220 /* Allocates attribute payload and encodes the attribute there */
222 SilcAttributePayload silc_attribute_payload_alloc(SilcAttribute attribute,
223 SilcAttributeFlags flags,
225 SilcUInt32 object_size)
227 SilcAttributePayload attr;
229 attr = silc_calloc(1, sizeof(*attr));
233 attr->attribute = attribute;
236 silc_attribute_payload_encode_int(attribute, flags, object,
238 (SilcUInt32 *)&attr->data_len);
247 /* Parse list of payloads */
249 SilcDList silc_attribute_payload_parse(const unsigned char *payload,
250 SilcUInt32 payload_len)
252 SilcBufferStruct buffer;
254 SilcAttributePayload newp;
257 SILC_LOG_DEBUG(("Parsing Attribute Payload list"));
259 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
260 list = silc_dlist_init();
263 newp = silc_calloc(1, sizeof(*newp));
266 ret = silc_buffer_unformat(&buffer,
267 SILC_STR_UI_CHAR(&newp->attribute),
268 SILC_STR_UI_CHAR(&newp->flags),
269 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
275 if (newp->data_len > buffer.len) {
276 SILC_LOG_ERROR(("Incorrect attribute payload in list"));
280 len = 4 + newp->data_len;
281 if (buffer.len < len)
283 silc_buffer_pull(&buffer, len);
285 silc_dlist_add(list, newp);
291 silc_attribute_payload_list_free(list);
295 /* Encode one attribute payload to buffer */
297 SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
298 SilcAttribute attribute,
299 SilcAttributeFlags flags,
301 SilcUInt32 object_size)
303 object = silc_attribute_payload_encode_int(attribute, flags, object,
304 object_size, &object_size);
305 attrs = silc_attribute_payload_encode_data(attrs, attribute, flags,
306 (const unsigned char *)object,
312 /* Encoded the attribute data directly to buffer */
314 SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
315 SilcAttribute attribute,
316 SilcAttributeFlags flags,
317 const unsigned char *data,
320 SilcBuffer buffer = attrs;
324 buffer = silc_buffer_realloc(buffer,
325 (buffer ? buffer->truelen + len : len));
328 silc_buffer_pull(buffer, buffer->len);
329 silc_buffer_pull_tail(buffer, len);
330 silc_buffer_format(buffer,
331 SILC_STR_UI_CHAR(attribute),
332 SILC_STR_UI_CHAR(flags),
333 SILC_STR_UI_SHORT((SilcUInt16)data_len),
334 SILC_STR_UI_XNSTRING(data, data_len),
337 silc_buffer_push(buffer, buffer->data - buffer->head);
342 /* Free Attribute Payload */
344 void silc_attribute_payload_free(SilcAttributePayload payload)
346 silc_free(payload->data);
350 /* Free's list of Attribute Payloads */
352 void silc_attribute_payload_list_free(SilcDList list)
354 SilcAttributePayload entry;
356 silc_dlist_start(list);
357 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
358 silc_attribute_payload_free(entry);
359 silc_dlist_del(list, entry);
362 silc_dlist_uninit(list);
365 /* Return attribute type */
367 SilcAttribute silc_attribute_get_attribute(SilcAttributePayload payload)
369 return payload->attribute;
372 /* Return attribute flags */
374 SilcAttributeFlags silc_attribute_get_flags(SilcAttributePayload payload)
376 return payload->flags;
379 /* Return attribute data from the payload */
381 const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
382 SilcUInt32 *data_len)
385 *data_len = payload->data_len;
386 return (const unsigned char *)payload->data;
389 /* Return parsed attribute object */
391 bool silc_attribute_get_object(SilcAttributePayload payload,
392 void **object, SilcUInt32 object_size)
397 if (!object || !(*object) || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
400 switch (payload->attribute) {
401 case SILC_ATTRIBUTE_USER_INFO:
402 SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
405 case SILC_ATTRIBUTE_SERVICE:
407 SilcAttributeObjService *service = *object;
408 if (object_size != sizeof(*service))
410 if (payload->data_len < 7)
412 SILC_GET32_MSB(service->port, payload->data);
413 SILC_GET16_MSB(len, payload->data + 4);
414 if (payload->data_len < 7 + len)
416 memcpy(service->address, payload->data + 6,
417 (len < sizeof(service->address) - 1 ? len :
418 sizeof(service->address) - 1));
419 service->status = payload->data[6 + len] ? TRUE : FALSE;
424 case SILC_ATTRIBUTE_STATUS_MOOD:
425 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
427 SilcUInt32 *mask = *object;
428 if (object_size != sizeof(SilcUInt32))
430 if (payload->data_len < 4)
432 SILC_GET32_MSB(*mask, payload->data);
437 case SILC_ATTRIBUTE_STATUS_FREETEXT:
438 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
439 case SILC_ATTRIBUTE_TIMEZONE:
441 char *string = *object;
442 if (payload->data_len < 2)
444 SILC_GET16_MSB(len, payload->data);
445 if (payload->data_len < 2 + len)
447 if (object_size < len)
449 memcpy(string, payload->data + 2, len);
454 case SILC_ATTRIBUTE_STATUS_MESSAGE:
455 case SILC_ATTRIBUTE_EXTENSION:
457 SilcAttributeObjMime *mime = *object;
458 if (object_size != sizeof(*mime))
460 mime->mime = (const unsigned char *)payload->data;
461 mime->mime_len = payload->data_len;
466 case SILC_ATTRIBUTE_GEOLOCATION:
468 SilcAttributeObjGeo *geo = *object;
469 SilcBufferStruct buffer;
471 if (object_size != sizeof(*geo))
473 silc_buffer_set(&buffer, (unsigned char *)payload->data,
475 res = silc_buffer_unformat(&buffer,
476 SILC_STR_UI16_STRING_ALLOC(&geo->longitude),
477 SILC_STR_UI16_STRING_ALLOC(&geo->latitude),
478 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
479 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
487 case SILC_ATTRIBUTE_DEVICE_INFO:
489 SilcAttributeObjDevice *dev = *object;
490 SilcBufferStruct buffer;
493 if (object_size != sizeof(*dev))
495 silc_buffer_set(&buffer, (unsigned char *)payload->data,
498 silc_buffer_unformat(&buffer,
499 SILC_STR_UI_INT(&type),
500 SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer),
501 SILC_STR_UI16_STRING_ALLOC(&dev->version),
502 SILC_STR_UI16_STRING_ALLOC(&dev->model),
503 SILC_STR_UI16_STRING_ALLOC(&dev->language),
512 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
513 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
515 SilcAttributeObjPk *pk = *object;
516 SilcBufferStruct buffer;
518 if (object_size != sizeof(*pk))
520 silc_buffer_set(&buffer, (unsigned char *)payload->data,
523 silc_buffer_unformat(&buffer,
524 SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
528 pk->data = silc_memdup(payload->data + 2 + len,
529 payload->data_len - 2 - len);
530 pk->data_len = payload->data_len - 2 - len;
535 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
536 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
538 SilcAttributeObjPk *pk = *object;
539 if (object_size != sizeof(*pk))
542 pk->data = silc_memdup(payload->data, payload->data_len);
543 pk->data_len = payload->data_len;