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 /* Parse one attribute payload */
41 silc_attribute_payload_parse(const unsigned char *payload,
42 SilcUInt32 payload_len)
44 SilcBufferStruct buffer;
45 SilcAttributePayload newp;
48 SILC_LOG_DEBUG(("Parsing attribute payload"));
50 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
51 newp = silc_calloc(1, sizeof(*newp));
55 /* Parse the Attribute Payload. */
56 ret = silc_buffer_unformat(&buffer,
57 SILC_STR_UI_CHAR(&newp->attribute),
58 SILC_STR_UI_CHAR(&newp->flags),
59 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
65 if (newp->data_len > buffer.len - 4) {
66 SILC_LOG_ERROR(("Incorrect attribute payload"));
73 silc_attribute_payload_free(newp);
77 /* Encode one attribute payload to buffer */
79 SilcBuffer silc_attribute_payload_encode(SilcBuffer attrs,
80 SilcAttribute attribute,
81 SilcAttributeFlags flags,
83 SilcUInt32 object_size)
85 SilcBuffer buffer, tmpbuf = NULL;
86 unsigned char tmp[4], *str = NULL;
89 SILC_LOG_DEBUG(("Encoding Attribute Payload"));
91 /* Encode according to attribute type */
92 if (flags & SILC_ATTRIBUTE_FLAG_VALID) {
93 if (!object || !object_size)
98 case SILC_ATTRIBUTE_NONE:
101 case SILC_ATTRIBUTE_USER_INFO:
102 SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
105 case SILC_ATTRIBUTE_SERVICE:
107 SilcAttributeObjService *service = object;
108 if (object_size != sizeof(*service))
110 len = strlen(service->address);
111 str = silc_malloc(7 + len);
114 SILC_PUT32_MSB(service->port, str);
115 SILC_PUT16_MSB(len, str + 4);
116 memcpy(str + 6, service->address, len);
117 str[6 + len] = service->status;
121 case SILC_ATTRIBUTE_STATUS_MOOD:
122 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
124 SilcUInt32 mask = (SilcUInt32)object;
125 if (object_size != sizeof(SilcUInt32))
127 SILC_PUT32_MSB(mask, tmp);
129 object_size = sizeof(SilcUInt32);
133 case SILC_ATTRIBUTE_STATUS_FREETEXT:
134 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
135 case SILC_ATTRIBUTE_TIMEZONE:
137 unsigned char *string = object;
138 str = silc_malloc(2 + object_size);
141 SILC_PUT16_MSB(object_size, str);
142 memcpy(str + 2, string, object_size);
148 case SILC_ATTRIBUTE_STATUS_MESSAGE:
149 case SILC_ATTRIBUTE_EXTENSION:
151 SilcAttributeObjMime *mime = object;
152 if (object_size != sizeof(*mime))
154 object = (void *)mime->mime;
155 object_size = mime->mime_len;
159 case SILC_ATTRIBUTE_GEOLOCATION:
161 SilcAttributeObjGeo *geo = object;
162 if (object_size != sizeof(*geo))
165 (geo->longitude ? strlen(geo->longitude) : 0) +
166 (geo->latitude ? strlen(geo->latitude) : 0) +
167 (geo->altitude ? strlen(geo->altitude) : 0) +
168 (geo->accuracy ? strlen(geo->accuracy) : 0);
171 tmpbuf = silc_buffer_alloc_size(8 + len);
174 silc_buffer_format(tmpbuf,
175 SILC_STR_UI16_STRING(geo->longitude),
176 SILC_STR_UI16_STRING(geo->latitude),
177 SILC_STR_UI16_STRING(geo->altitude),
178 SILC_STR_UI16_STRING(geo->accuracy),
183 case SILC_ATTRIBUTE_DEVICE_INFO:
185 SilcAttributeObjDevice *dev = object;
186 if (object_size != sizeof(*dev))
189 (dev->manufacturer ? strlen(dev->manufacturer) : 0) +
190 (dev->version ? strlen(dev->version) : 0) +
191 (dev->model ? strlen(dev->model) : 0) +
192 (dev->language ? strlen(dev->language) : 0);
193 tmpbuf = silc_buffer_alloc_size(4 + 8 + len);
196 silc_buffer_format(tmpbuf,
197 SILC_STR_UI_INT(dev->type),
198 SILC_STR_UI16_STRING(dev->manufacturer),
199 SILC_STR_UI16_STRING(dev->version),
200 SILC_STR_UI16_STRING(dev->model),
201 SILC_STR_UI16_STRING(dev->language),
206 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
207 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
209 SilcAttributeObjPk *pk = object;
210 if (object_size != sizeof(*pk))
212 len = (pk->type ? strlen(pk->type) : 0);
213 tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len);
216 silc_buffer_format(tmpbuf,
217 SILC_STR_UI_SHORT(len),
218 SILC_STR_UI16_STRING(pk->type),
219 SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
224 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
225 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
227 SilcAttributeObjPk *pk = object;
228 if (object_size != sizeof(*pk))
231 object_size = pk->data_len;
236 /* Other attributes must be in correct format already */
242 len = 4 + object_size;
245 buffer = silc_buffer_alloc_size(len);
247 buffer = silc_buffer_realloc(buffer,
248 (buffer ? buffer->truelen + len : len));
249 silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
252 silc_buffer_format(buffer,
253 SILC_STR_UI_CHAR(attribute),
254 SILC_STR_UI_CHAR(flags),
255 SILC_STR_UI_SHORT((SilcUInt16)object_size),
256 SILC_STR_UI_XNSTRING(object, object_size),
259 silc_buffer_pull(buffer, len);
261 silc_buffer_push(buffer, buffer->data - buffer->head);
264 silc_buffer_free(tmpbuf);
270 /* Parse list of payloads */
272 SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
273 SilcUInt32 payload_len)
275 SilcBufferStruct buffer;
277 SilcAttributePayload newp;
280 SILC_LOG_DEBUG(("Parsing Attribute Payload list"));
282 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
283 list = silc_dlist_init();
286 newp = silc_calloc(1, sizeof(*newp));
289 ret = silc_buffer_unformat(&buffer,
290 SILC_STR_UI_CHAR(&newp->attribute),
291 SILC_STR_UI_CHAR(&newp->flags),
292 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
298 if (newp->data_len > buffer.len) {
299 SILC_LOG_ERROR(("Incorrect attribute payload in list"));
303 len = 4 + newp->data_len;
304 if (buffer.len < len)
306 silc_buffer_pull(&buffer, len);
308 silc_dlist_add(list, newp);
314 silc_attribute_payload_list_free(list);
318 /* Free Attribute Payload */
320 void silc_attribute_payload_free(SilcAttributePayload payload)
322 silc_free(payload->data);
326 /* Free's list of Attribute Payloads */
328 void silc_attribute_payload_list_free(SilcDList list)
330 SilcAttributePayload entry;
332 silc_dlist_start(list);
333 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
334 silc_attribute_payload_free(entry);
335 silc_dlist_del(list, entry);
338 silc_dlist_uninit(list);
341 /* Return attribute type */
343 SilcAttribute silc_attribute_get_attribute(SilcAttributePayload payload)
345 return payload->attribute;
348 /* Return attribute flags */
350 SilcAttributeFlags silc_attribute_get_flags(SilcAttributePayload payload)
352 return payload->flags;
355 /* Return attribute data from the payload */
357 const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
358 SilcUInt32 *data_len)
361 *data_len = payload->data_len;
362 return (const unsigned char *)payload->data;
365 /* Return parsed attribute object */
367 bool silc_attribute_get_object(SilcAttributePayload payload,
368 SilcAttribute attribute,
369 void **object, SilcUInt32 object_size)
374 if (!attribute || payload->attribute != attribute || !object || !(*object) ||
375 payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
379 case SILC_ATTRIBUTE_USER_INFO:
380 SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
383 case SILC_ATTRIBUTE_SERVICE:
385 SilcAttributeObjService *service = *object;
386 if (object_size != sizeof(*service))
388 if (payload->data_len < 7)
390 SILC_GET32_MSB(service->port, payload->data);
391 SILC_GET16_MSB(len, payload->data + 4);
392 if (payload->data_len < 7 + len)
394 memcpy(service->address, payload->data + 6,
395 (len < sizeof(service->address) - 1 ? len :
396 sizeof(service->address) - 1));
397 service->status = payload->data[6 + len] ? TRUE : FALSE;
402 case SILC_ATTRIBUTE_STATUS_MOOD:
403 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
405 SilcUInt32 *mask = *object;
406 if (object_size != sizeof(SilcUInt32))
408 if (payload->data_len < 4)
410 SILC_GET32_MSB(*mask, payload->data);
415 case SILC_ATTRIBUTE_STATUS_FREETEXT:
416 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
417 case SILC_ATTRIBUTE_TIMEZONE:
419 char *string = *object;
420 if (payload->data_len < 2)
422 SILC_GET16_MSB(len, payload->data);
423 if (payload->data_len < 2 + len)
425 if (object_size < len)
427 memcpy(string, payload->data + 2, len);
432 case SILC_ATTRIBUTE_STATUS_MESSAGE:
433 case SILC_ATTRIBUTE_EXTENSION:
435 SilcAttributeObjMime *mime = *object;
436 if (object_size != sizeof(*mime))
438 mime->mime = (const unsigned char *)payload->data;
439 mime->mime_len = payload->data_len;
444 case SILC_ATTRIBUTE_GEOLOCATION:
446 SilcAttributeObjGeo *geo = *object;
447 SilcBufferStruct buffer;
449 if (object_size != sizeof(*geo))
451 silc_buffer_set(&buffer, (unsigned char *)payload->data,
453 res = silc_buffer_unformat(&buffer,
454 SILC_STR_UI16_STRING_ALLOC(&geo->longitude),
455 SILC_STR_UI16_STRING_ALLOC(&geo->latitude),
456 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
457 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
465 case SILC_ATTRIBUTE_DEVICE_INFO:
467 SilcAttributeObjDevice *dev = *object;
468 SilcBufferStruct buffer;
471 if (object_size != sizeof(*dev))
473 silc_buffer_set(&buffer, (unsigned char *)payload->data,
476 silc_buffer_unformat(&buffer,
477 SILC_STR_UI_INT(&type),
478 SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer),
479 SILC_STR_UI16_STRING_ALLOC(&dev->version),
480 SILC_STR_UI16_STRING_ALLOC(&dev->model),
481 SILC_STR_UI16_STRING_ALLOC(&dev->language),
490 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
491 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
493 SilcAttributeObjPk *pk = *object;
494 SilcBufferStruct buffer;
496 if (object_size != sizeof(*pk))
498 silc_buffer_set(&buffer, (unsigned char *)payload->data,
501 silc_buffer_unformat(&buffer,
502 SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
506 pk->data = silc_memdup(payload->data + 2 + len,
507 payload->data_len - 2 - len);
508 pk->data_len = payload->data_len - 2 - len;
513 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
514 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
516 SilcAttributeObjPk *pk = *object;
517 if (object_size != sizeof(*pk))
520 pk->data = silc_memdup(payload->data, payload->data_len);
521 pk->data_len = payload->data_len;