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 */
79 SilcBuffer silc_attribute_payload_encode(SilcAttribute attribute,
80 SilcAttributeFlags flags,
81 const unsigned char *data,
86 SILC_LOG_DEBUG(("Encoding Attribute Payload"));
88 buffer = silc_buffer_alloc_size(4 + data_len);
92 /* Encode the Attribute Payload */
93 silc_buffer_format(buffer,
94 SILC_STR_UI_CHAR(attribute),
95 SILC_STR_UI_CHAR(flags),
96 SILC_STR_UI_SHORT((SilcUInt16)data_len),
97 SILC_STR_UI_XNSTRING(data, data_len),
103 /* Parse list of payloads */
105 SilcDList silc_attribute_payload_parse_list(const unsigned char *payload,
106 SilcUInt32 payload_len)
108 SilcBufferStruct buffer;
110 SilcAttributePayload newp;
113 SILC_LOG_DEBUG(("Parsing Attribute Payload list"));
115 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
116 list = silc_dlist_init();
119 newp = silc_calloc(1, sizeof(*newp));
122 ret = silc_buffer_unformat(&buffer,
123 SILC_STR_UI_CHAR(&newp->attribute),
124 SILC_STR_UI_CHAR(&newp->flags),
125 SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
131 if (newp->data_len > buffer.len) {
132 SILC_LOG_ERROR(("Incorrect attribute payload in list"));
136 len = 4 + newp->data_len;
137 if (buffer.len < len)
139 silc_buffer_pull(&buffer, len);
141 silc_dlist_add(list, newp);
147 silc_attribute_payload_list_free(list);
151 /* Encode list of payloads */
153 SilcBuffer silc_attribute_payload_encode_list(SilcUInt32 num_attrs, ...)
155 SilcBuffer buffer = NULL;
158 SilcAttribute attribute;
159 SilcAttributeFlags flags;
166 va_start(ap, num_attrs);
167 for (i = 0; i < num_attrs; i++) {
168 attribute = va_arg(ap, SilcUInt32);
169 flags = va_arg(ap, SilcUInt32);
170 data = va_arg(ap, unsigned char *);
171 data_len = va_arg(ap, SilcUInt32);
173 if (data || !data_len)
177 buffer = silc_buffer_realloc(buffer,
178 (buffer ? buffer->truelen + len : len));
179 silc_buffer_pull_tail(buffer, (buffer->end - buffer->data));
180 silc_buffer_format(buffer,
181 SILC_STR_UI_CHAR(attribute),
182 SILC_STR_UI_CHAR(flags),
183 SILC_STR_UI_SHORT((SilcUInt16)data_len),
184 SILC_STR_UI_XNSTRING(data, data_len),
186 silc_buffer_pull(buffer, len);
191 silc_buffer_push(buffer, buffer->data - buffer->head);
196 /* Free Attribute Payload */
198 void silc_attribute_payload_free(SilcAttributePayload payload)
200 silc_free(payload->data);
204 /* Free's list of Attribute Payloads */
206 void silc_attribute_payload_list_free(SilcDList list)
208 SilcAttributePayload entry;
210 silc_dlist_start(list);
211 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
212 silc_attribute_payload_free(entry);
213 silc_dlist_del(list, entry);
216 silc_dlist_uninit(list);
219 /* Return attribute type */
221 SilcAttribute silc_attribute_get_attribute(SilcAttributePayload payload)
223 return payload->attribute;
226 /* Return attribute flags */
228 SilcAttributeFlags silc_attribute_get_flags(SilcAttributePayload payload)
230 return payload->flags;
233 /* Return attribute data from the payload */
235 const unsigned char *silc_attribute_get_data(SilcAttributePayload payload,
236 SilcUInt32 *data_len)
239 *data_len = payload->data_len;
240 return (const unsigned char *)payload->data;
243 /* Return parsed attribute object */
245 bool silc_attribute_get_object(SilcAttributePayload payload,
246 SilcAttribute attribute,
247 void **object, SilcUInt32 object_size)
252 if (!attribute || !object || !(*object))
256 case SILC_ATTRIBUTE_USER_INFO:
257 SILC_NOT_IMPLEMENTED("SILC_ATTRIBUTE_USER_INFO");
260 case SILC_ATTRIBUTE_SERVICE:
262 SilcAttributeObjService *service = *object;
263 if (object_size != sizeof(*service))
265 if (payload->data_len < 7)
267 SILC_GET32_MSB(service->port, payload->data);
268 SILC_GET16_MSB(len, payload->data + 4);
269 if (payload->data_len < 7 + len)
271 memcpy(service->address, payload->data + 6,
272 (len < sizeof(service->address) - 1 ? len :
273 sizeof(service->address) - 1));
274 service->status = payload->data[6 + len] ? TRUE : FALSE;
279 case SILC_ATTRIBUTE_STATUS_MOOD:
280 case SILC_ATTRIBUTE_PREFERRED_CONTACT:
282 SilcUInt32 *mask = *object;
283 if (object_size != sizeof(SilcUInt32))
285 if (payload->data_len < 4)
287 SILC_GET32_MSB(*mask, payload->data);
292 case SILC_ATTRIBUTE_STATUS_FREETEXT:
293 case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
294 case SILC_ATTRIBUTE_TIMEZONE:
296 char *string = *object;
297 if (payload->data_len < 2)
299 SILC_GET16_MSB(len, payload->data);
300 if (payload->data_len < 2 + len)
302 if (object_size < len)
304 memcpy(string, payload->data + 2, len);
309 case SILC_ATTRIBUTE_STATUS_MESSAGE:
310 case SILC_ATTRIBUTE_EXTENSION:
312 SilcAttributeObjMime *mime = *object;
313 if (object_size != sizeof(*mime))
315 mime->mime = (const unsigned char *)payload->data;
316 mime->mime_len = payload->data_len;
321 case SILC_ATTRIBUTE_GEOLOCATION:
323 SilcAttributeObjGeo *geo = *object;
324 SilcBufferStruct buffer;
326 if (object_size != sizeof(*geo))
328 silc_buffer_set(&buffer, (unsigned char *)payload->data,
330 res = silc_buffer_unformat(&buffer,
331 SILC_STR_UI16_STRING_ALLOC(&geo->longitude),
332 SILC_STR_UI16_STRING_ALLOC(&geo->latitude),
333 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
334 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
342 case SILC_ATTRIBUTE_DEVICE_INFO:
344 SilcAttributeObjDevice *dev = *object;
345 SilcBufferStruct buffer;
348 if (object_size != sizeof(*dev))
350 silc_buffer_set(&buffer, (unsigned char *)payload->data,
353 silc_buffer_unformat(&buffer,
354 SILC_STR_UI_INT(&type),
355 SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer),
356 SILC_STR_UI16_STRING_ALLOC(&dev->version),
357 SILC_STR_UI16_STRING_ALLOC(&dev->model),
358 SILC_STR_UI16_STRING_ALLOC(&dev->language),
367 case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
368 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
370 SilcAttributeObjPk *pk = *object;
371 SilcBufferStruct buffer;
373 if (object_size != sizeof(*pk))
375 silc_buffer_set(&buffer, (unsigned char *)payload->data,
378 silc_buffer_unformat(&buffer,
379 SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
383 pk->data = silc_memdup(payload->data + 2 + len,
384 payload->data_len - 2 - len);
385 pk->data_len = payload->data_len - 2 - len;
390 case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
391 case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
393 SilcAttributeObjPk *pk = *object;
394 if (object_size != sizeof(*pk))
397 pk->data = silc_memdup(payload->data, payload->data_len);
398 pk->data_len = payload->data_len;