• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2005-2009  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
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.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <stdlib.h>
35 
36 #include <bluetooth/sdp.h>
37 #include <bluetooth/sdp_lib.h>
38 
39 #include "logging.h"
40 #include "sdp-xml.h"
41 
42 #define STRBUFSIZE 1024
43 #define MAXINDENT 64
44 
convert_raw_data_to_xml(sdp_data_t * value,int indent_level,void * data,void (* appender)(void *,const char *))45 static void convert_raw_data_to_xml(sdp_data_t *value, int indent_level,
46 		void *data, void (*appender)(void *, const char *))
47 {
48 	int i, hex;
49 	char buf[STRBUFSIZE];
50 	char indent[MAXINDENT];
51 	char next_indent[MAXINDENT];
52 
53 	if (!value)
54 		return;
55 
56 	if (indent_level >= MAXINDENT)
57 		indent_level = MAXINDENT - 2;
58 
59 	for (i = 0; i < indent_level; i++) {
60 		indent[i] = '\t';
61 		next_indent[i] = '\t';
62 	}
63 
64 	indent[i] = '\0';
65 	next_indent[i] = '\t';
66 	next_indent[i + 1] = '\0';
67 
68 	buf[STRBUFSIZE - 1] = '\0';
69 
70 	switch (value->dtd) {
71 	case SDP_DATA_NIL:
72 		appender(data, indent);
73 		appender(data, "<nil/>\n");
74 		break;
75 
76 	case SDP_BOOL:
77 		appender(data, indent);
78 		appender(data, "<boolean value=\"");
79 		appender(data, value->val.uint8 ? "true" : "false");
80 		appender(data, "\" />\n");
81 		break;
82 
83 	case SDP_UINT8:
84 		appender(data, indent);
85 		appender(data, "<uint8 value=\"");
86 		snprintf(buf, STRBUFSIZE - 1, "0x%02x", value->val.uint8);
87 		appender(data, buf);
88 		appender(data, "\" />\n");
89 		break;
90 
91 	case SDP_UINT16:
92 		appender(data, indent);
93 		appender(data, "<uint16 value=\"");
94 		snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uint16);
95 		appender(data, buf);
96 		appender(data, "\" />\n");
97 		break;
98 
99 	case SDP_UINT32:
100 		appender(data, indent);
101 		appender(data, "<uint32 value=\"");
102 		snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uint32);
103 		appender(data, buf);
104 		appender(data, "\" />\n");
105 		break;
106 
107 	case SDP_UINT64:
108 		appender(data, indent);
109 		appender(data, "<uint64 value=\"");
110 		snprintf(buf, STRBUFSIZE - 1, "0x%016jx", value->val.uint64);
111 		appender(data, buf);
112 		appender(data, "\" />\n");
113 		break;
114 
115 	case SDP_UINT128:
116 		appender(data, indent);
117 		appender(data, "<uint128 value=\"");
118 
119 		for (i = 0; i < 16; i++) {
120 			sprintf(&buf[i * 2], "%02x",
121 				(unsigned char) value->val.uint128.data[i]);
122 		}
123 
124 		appender(data, buf);
125 		appender(data, "\" />\n");
126 		break;
127 
128 	case SDP_INT8:
129 		appender(data, indent);
130 		appender(data, "<int8 value=\"");
131 		snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int8);
132 		appender(data, buf);
133 		appender(data, "\" />\n");
134 		break;
135 
136 	case SDP_INT16:
137 		appender(data, indent);
138 		appender(data, "<int16 value=\"");
139 		snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int16);
140 		appender(data, buf);
141 		appender(data, "\" />\n");
142 		break;
143 
144 	case SDP_INT32:
145 		appender(data, indent);
146 		appender(data, "<int32 value=\"");
147 		snprintf(buf, STRBUFSIZE - 1, "%d", value->val.int32);
148 		appender(data, buf);
149 		appender(data, "\" />\n");
150 		break;
151 
152 	case SDP_INT64:
153 		appender(data, indent);
154 		appender(data, "<int64 value=\"");
155 		snprintf(buf, STRBUFSIZE - 1, "%jd", value->val.int64);
156 		appender(data, buf);
157 		appender(data, "\" />\n");
158 		break;
159 
160 	case SDP_INT128:
161 		appender(data, indent);
162 		appender(data, "<int128 value=\"");
163 
164 		for (i = 0; i < 16; i++) {
165 			sprintf(&buf[i * 2], "%02x",
166 				(unsigned char) value->val.int128.data[i]);
167 		}
168 		appender(data, buf);
169 
170 		appender(data, "\" />\n");
171 		break;
172 
173 	case SDP_UUID16:
174 		appender(data, indent);
175 		appender(data, "<uuid value=\"");
176 		snprintf(buf, STRBUFSIZE - 1, "0x%04x", value->val.uuid.value.uuid16);
177 		appender(data, buf);
178 		appender(data, "\" />\n");
179 		break;
180 
181 	case SDP_UUID32:
182 		appender(data, indent);
183 		appender(data, "<uuid value=\"");
184 		snprintf(buf, STRBUFSIZE - 1, "0x%08x", value->val.uuid.value.uuid32);
185 		appender(data, buf);
186 		appender(data, "\" />\n");
187 		break;
188 
189 	case SDP_UUID128:
190 		appender(data, indent);
191 		appender(data, "<uuid value=\"");
192 
193 		snprintf(buf, STRBUFSIZE - 1,
194 			 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
195 			 (unsigned char) value->val.uuid.value.
196 			 uuid128.data[0],
197 			 (unsigned char) value->val.uuid.value.
198 			 uuid128.data[1],
199 			 (unsigned char) value->val.uuid.value.
200 			 uuid128.data[2],
201 			 (unsigned char) value->val.uuid.value.
202 			 uuid128.data[3],
203 			 (unsigned char) value->val.uuid.value.
204 			 uuid128.data[4],
205 			 (unsigned char) value->val.uuid.value.
206 			 uuid128.data[5],
207 			 (unsigned char) value->val.uuid.value.
208 			 uuid128.data[6],
209 			 (unsigned char) value->val.uuid.value.
210 			 uuid128.data[7],
211 			 (unsigned char) value->val.uuid.value.
212 			 uuid128.data[8],
213 			 (unsigned char) value->val.uuid.value.
214 			 uuid128.data[9],
215 			 (unsigned char) value->val.uuid.value.
216 			 uuid128.data[10],
217 			 (unsigned char) value->val.uuid.value.
218 			 uuid128.data[11],
219 			 (unsigned char) value->val.uuid.value.
220 			 uuid128.data[12],
221 			 (unsigned char) value->val.uuid.value.
222 			 uuid128.data[13],
223 			 (unsigned char) value->val.uuid.value.
224 			 uuid128.data[14],
225 			 (unsigned char) value->val.uuid.value.
226 			 uuid128.data[15]);
227 
228 		appender(data, buf);
229 		appender(data, "\" />\n");
230 		break;
231 
232 	case SDP_TEXT_STR8:
233 	case SDP_TEXT_STR16:
234 	case SDP_TEXT_STR32:
235 	{
236 		int num_chars_to_escape = 0;
237 		int length = value->unitSize - 1;
238 		char *strBuf = 0;
239 
240 		hex = 0;
241 
242 		for (i = 0; i < length; i++) {
243 			if (!isprint(value->val.str[i]) &&
244 					value->val.str[i] != '\0') {
245 				hex = 1;
246 				break;
247 			}
248 
249 			/* XML is evil, must do this... */
250 			if ((value->val.str[i] == '<') ||
251 					(value->val.str[i] == '>') ||
252 					(value->val.str[i] == '"') ||
253 					(value->val.str[i] == '&'))
254 				num_chars_to_escape++;
255 		}
256 
257 		appender(data, indent);
258 
259 		appender(data, "<text ");
260 
261 		if (hex) {
262 			appender(data, "encoding=\"hex\" ");
263 			strBuf = (char *) malloc(sizeof(char)
264 						 * ((value->unitSize-1) * 2 + 1));
265 
266 			/* Unit Size seems to include the size for dtd
267 			   It is thus off by 1
268 			   This is safe for Normal strings, but not
269 			   hex encoded data */
270 			for (i = 0; i < (value->unitSize-1); i++)
271 				sprintf(&strBuf[i*sizeof(char)*2],
272 					"%02x",
273 					(unsigned char) value->val.str[i]);
274 
275 			strBuf[(value->unitSize-1) * 2] = '\0';
276 		}
277 		else {
278 			int j;
279 			/* escape the XML disallowed chars */
280 			strBuf = (char *)
281 				malloc(sizeof(char) *
282 				(value->unitSize + 1 + num_chars_to_escape * 4));
283 			for (i = 0, j = 0; i < length; i++) {
284 				if (value->val.str[i] == '&') {
285 					strBuf[j++] = '&';
286 					strBuf[j++] = 'a';
287 					strBuf[j++] = 'm';
288 					strBuf[j++] = 'p';
289 				}
290 				else if (value->val.str[i] == '<') {
291 					strBuf[j++] = '&';
292 					strBuf[j++] = 'l';
293 					strBuf[j++] = 't';
294 				}
295 				else if (value->val.str[i] == '>') {
296 					strBuf[j++] = '&';
297 					strBuf[j++] = 'g';
298 					strBuf[j++] = 't';
299 				}
300 				else if (value->val.str[i] == '"') {
301 					strBuf[j++] = '&';
302 					strBuf[j++] = 'q';
303 					strBuf[j++] = 'u';
304 					strBuf[j++] = 'o';
305 					strBuf[j++] = 't';
306 				}
307 				else if (value->val.str[i] == '\0') {
308 					strBuf[j++] = ' ';
309 				} else {
310 					strBuf[j++] = value->val.str[i];
311 				}
312 			}
313 
314 			strBuf[j] = '\0';
315 		}
316 
317 		appender(data, "value=\"");
318 		appender(data, strBuf);
319 		appender(data, "\" />\n");
320 		free(strBuf);
321 		break;
322 	}
323 
324 	case SDP_URL_STR8:
325 	case SDP_URL_STR16:
326 	case SDP_URL_STR32:
327 	{
328 		char *strBuf;
329 
330 		appender(data, indent);
331 		appender(data, "<url value=\"");
332 		strBuf = strndup(value->val.str, value->unitSize - 1);
333 		appender(data, strBuf);
334 		free(strBuf);
335 		appender(data, "\" />\n");
336 		break;
337 	}
338 
339 	case SDP_SEQ8:
340 	case SDP_SEQ16:
341 	case SDP_SEQ32:
342 		appender(data, indent);
343 		appender(data, "<sequence>\n");
344 
345 		convert_raw_data_to_xml(value->val.dataseq,
346 					indent_level + 1, data, appender);
347 
348 		appender(data, indent);
349 		appender(data, "</sequence>\n");
350 
351 		break;
352 
353 	case SDP_ALT8:
354 	case SDP_ALT16:
355 	case SDP_ALT32:
356 		appender(data, indent);
357 
358 		appender(data, "<alternate>\n");
359 
360 		convert_raw_data_to_xml(value->val.dataseq,
361 					indent_level + 1, data, appender);
362 		appender(data, indent);
363 
364 		appender(data, "</alternate>\n");
365 
366 		break;
367 	}
368 
369 	convert_raw_data_to_xml(value->next, indent_level, data, appender);
370 }
371 
372 struct conversion_data {
373 	void *data;
374 	void (*appender)(void *data, const char *);
375 };
376 
convert_raw_attr_to_xml_func(void * val,void * data)377 static void convert_raw_attr_to_xml_func(void *val, void *data)
378 {
379 	struct conversion_data *cd = (struct conversion_data *) data;
380 	sdp_data_t *value = (sdp_data_t *) val;
381 	char buf[STRBUFSIZE];
382 
383 	buf[STRBUFSIZE - 1] = '\0';
384 	snprintf(buf, STRBUFSIZE - 1, "\t<attribute id=\"0x%04x\">\n",
385 		 value->attrId);
386 	cd->appender(cd->data, buf);
387 
388 	if (data)
389 		convert_raw_data_to_xml(value, 2, cd->data, cd->appender);
390 	else
391 		cd->appender(cd->data, "\t\tNULL\n");
392 
393 	cd->appender(cd->data, "\t</attribute>\n");
394 }
395 
396 /*
397  * Will convert the sdp record to XML.  The appender and data can be used
398  * to control where to output the record (e.g. file or a data buffer).  The
399  * appender will be called repeatedly with data and the character buffer
400  * (containing parts of the generated XML) to append.
401  */
convert_sdp_record_to_xml(sdp_record_t * rec,void * data,void (* appender)(void *,const char *))402 void convert_sdp_record_to_xml(sdp_record_t *rec,
403 			void *data, void (*appender)(void *, const char *))
404 {
405 	struct conversion_data cd;
406 
407 	cd.data = data;
408 	cd.appender = appender;
409 
410 	if (rec && rec->attrlist) {
411 		appender(data, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n");
412 		appender(data, "<record>\n");
413 		sdp_list_foreach(rec->attrlist,
414 				 convert_raw_attr_to_xml_func, &cd);
415 		appender(data, "</record>\n");
416 	}
417 }
418 
sdp_xml_parse_uuid128(const char * data)419 static sdp_data_t *sdp_xml_parse_uuid128(const char *data)
420 {
421 	uint128_t val;
422 	unsigned int i, j;
423 
424 	char buf[3];
425 
426 	memset(&val, 0, sizeof(val));
427 
428 	buf[2] = '\0';
429 
430 	for (j = 0, i = 0; i < strlen(data);) {
431 		if (data[i] == '-') {
432 			i++;
433 			continue;
434 		}
435 
436 		buf[0] = data[i];
437 		buf[1] = data[i + 1];
438 
439 		val.data[j++] = strtoul(buf, 0, 16);
440 		i += 2;
441 	}
442 
443 	return sdp_data_alloc(SDP_UUID128, &val);
444 }
445 
sdp_xml_parse_uuid(const char * data,sdp_record_t * record)446 sdp_data_t *sdp_xml_parse_uuid(const char *data, sdp_record_t *record)
447 {
448 	sdp_data_t *ret;
449 	char *endptr;
450 	uint32_t val;
451 	uint16_t val2;
452 	int len;
453 
454 	len = strlen(data);
455 
456 	if (len == 36) {
457 		ret = sdp_xml_parse_uuid128(data);
458 		goto result;
459 	}
460 
461 	val = strtoll(data, &endptr, 16);
462 
463 	/* Couldn't parse */
464 	if (*endptr != '\0')
465 		return NULL;
466 
467 	if (val > USHRT_MAX) {
468 		ret = sdp_data_alloc(SDP_UUID32, &val);
469 		goto result;
470 	}
471 
472 	val2 = val;
473 
474 	ret = sdp_data_alloc(SDP_UUID16, &val2);
475 
476 result:
477 	if (record && ret)
478 		sdp_pattern_add_uuid(record, &ret->val.uuid);
479 
480 	return ret;
481 }
482 
sdp_xml_parse_int(const char * data,uint8_t dtd)483 sdp_data_t *sdp_xml_parse_int(const char * data, uint8_t dtd)
484 {
485 	char *endptr;
486 	sdp_data_t *ret = NULL;
487 
488 	switch (dtd) {
489 	case SDP_BOOL:
490 	{
491 		uint8_t val = 0;
492 
493 		if (!strcmp("true", data)) {
494 			val = 1;
495 		}
496 
497 		else if (!strcmp("false", data)) {
498 			val = 0;
499 		}
500 		else {
501 			return NULL;
502 		}
503 
504 		ret = sdp_data_alloc(dtd, &val);
505 		break;
506 	}
507 
508 	case SDP_INT8:
509 	{
510 		int8_t val = strtoul(data, &endptr, 0);
511 
512 		/* Failed to parse */
513 		if ((endptr != data) && (*endptr != '\0'))
514 			return NULL;
515 
516 		ret = sdp_data_alloc(dtd, &val);
517 		break;
518 	}
519 
520 	case SDP_UINT8:
521 	{
522 		uint8_t val = strtoul(data, &endptr, 0);
523 
524 		/* Failed to parse */
525 		if ((endptr != data) && (*endptr != '\0'))
526 			return NULL;
527 
528 		ret = sdp_data_alloc(dtd, &val);
529 		break;
530 	}
531 
532 	case SDP_INT16:
533 	{
534 		int16_t val = strtoul(data, &endptr, 0);
535 
536 		/* Failed to parse */
537 		if ((endptr != data) && (*endptr != '\0'))
538 			return NULL;
539 
540 		ret = sdp_data_alloc(dtd, &val);
541 		break;
542 	}
543 
544 	case SDP_UINT16:
545 	{
546 		uint16_t val = strtoul(data, &endptr, 0);
547 
548 		/* Failed to parse */
549 		if ((endptr != data) && (*endptr != '\0'))
550 			return NULL;
551 
552 		ret = sdp_data_alloc(dtd, &val);
553 		break;
554 	}
555 
556 	case SDP_INT32:
557 	{
558 		int32_t val = strtoul(data, &endptr, 0);
559 
560 		/* Failed to parse */
561 		if ((endptr != data) && (*endptr != '\0'))
562 			return NULL;
563 
564 		ret = sdp_data_alloc(dtd, &val);
565 		break;
566 	}
567 
568 	case SDP_UINT32:
569 	{
570 		uint32_t val = strtoul(data, &endptr, 0);
571 
572 		/* Failed to parse */
573 		if ((endptr != data) && (*endptr != '\0'))
574 			return NULL;
575 
576 		ret = sdp_data_alloc(dtd, &val);
577 		break;
578 	}
579 
580 	case SDP_INT64:
581 	{
582 		int64_t val = strtoull(data, &endptr, 0);
583 
584 		/* Failed to parse */
585 		if ((endptr != data) && (*endptr != '\0'))
586 			return NULL;
587 
588 		ret = sdp_data_alloc(dtd, &val);
589 		break;
590 	}
591 
592 	case SDP_UINT64:
593 	{
594 		uint64_t val = strtoull(data, &endptr, 0);
595 
596 		/* Failed to parse */
597 		if ((endptr != data) && (*endptr != '\0'))
598 			return NULL;
599 
600 		ret = sdp_data_alloc(dtd, &val);
601 		break;
602 	}
603 
604 	case SDP_INT128:
605 	case SDP_UINT128:
606 	{
607 		uint128_t val;
608 		int i = 0;
609 		char buf[3];
610 
611 		buf[2] = '\0';
612 
613 		for (; i < 32; i += 2) {
614 			buf[0] = data[i];
615 			buf[1] = data[i + 1];
616 
617 			val.data[i >> 1] = strtoul(buf, 0, 16);
618 		}
619 
620 		ret = sdp_data_alloc(dtd, &val);
621 		break;
622 	}
623 
624 	};
625 
626 	return ret;
627 }
628 
sdp_xml_parse_string_decode(const char * data,char encoding,uint32_t * length)629 static char *sdp_xml_parse_string_decode(const char *data, char encoding, uint32_t *length)
630 {
631 	int len = strlen(data);
632 	char *text;
633 
634 	if (encoding == SDP_XML_ENCODING_NORMAL) {
635 		text = strdup(data);
636 		*length = len;
637 	} else {
638 		char buf[3], *decoded;
639 		int i;
640 
641 		decoded = malloc((len >> 1) + 1);
642 
643 		/* Ensure the string is a power of 2 */
644 		len = (len >> 1) << 1;
645 
646 		buf[2] = '\0';
647 
648 		for (i = 0; i < len; i += 2) {
649 			buf[0] = data[i];
650 			buf[1] = data[i + 1];
651 
652 			decoded[i >> 1] = strtoul(buf, 0, 16);
653 		}
654 
655 		decoded[len >> 1] = '\0';
656 		text = decoded;
657 		*length = len >> 1;
658 	}
659 
660 	return text;
661 }
662 
sdp_xml_parse_url(const char * data)663 sdp_data_t *sdp_xml_parse_url(const char *data)
664 {
665 	uint8_t dtd = SDP_URL_STR8;
666 	char *url;
667 	uint32_t length;
668 	sdp_data_t *ret;
669 
670 	url = sdp_xml_parse_string_decode(data,
671 				SDP_XML_ENCODING_NORMAL, &length);
672 
673 	if (length > UCHAR_MAX)
674 		dtd = SDP_URL_STR16;
675 
676 	ret = sdp_data_alloc_with_length(dtd, url, length);
677 
678 	debug("URL size %d length %d: -->%s<--", ret->unitSize, length, url);
679 
680 	free(url);
681 
682 	return ret;
683 }
684 
sdp_xml_parse_text(const char * data,char encoding)685 sdp_data_t *sdp_xml_parse_text(const char *data, char encoding)
686 {
687 	uint8_t dtd = SDP_TEXT_STR8;
688 	char *text;
689 	uint32_t length;
690 	sdp_data_t *ret;
691 
692 	text = sdp_xml_parse_string_decode(data, encoding, &length);
693 
694 	if (length > UCHAR_MAX)
695 		dtd = SDP_TEXT_STR16;
696 
697 	ret = sdp_data_alloc_with_length(dtd, text, length);
698 
699 	debug("Text size %d length %d: -->%s<--", ret->unitSize, length, text);
700 
701 	free(text);
702 
703 	return ret;
704 }
705 
sdp_xml_parse_nil(const char * data)706 sdp_data_t *sdp_xml_parse_nil(const char *data)
707 {
708 	return sdp_data_alloc(SDP_DATA_NIL, 0);
709 }
710 
711 #define DEFAULT_XML_DATA_SIZE 1024
712 
sdp_xml_data_alloc()713 struct sdp_xml_data *sdp_xml_data_alloc()
714 {
715 	struct sdp_xml_data *elem;
716 
717 	elem = malloc(sizeof(struct sdp_xml_data));
718 	if (!elem)
719 		return NULL;
720 
721 	memset(elem, 0, sizeof(struct sdp_xml_data));
722 
723 	/* Null terminate the text */
724 	elem->size = DEFAULT_XML_DATA_SIZE;
725 	elem->text = malloc(DEFAULT_XML_DATA_SIZE);
726 	elem->text[0] = '\0';
727 
728 	return elem;
729 }
730 
sdp_xml_data_free(struct sdp_xml_data * elem)731 void sdp_xml_data_free(struct sdp_xml_data *elem)
732 {
733 	if (elem->data)
734 		sdp_data_free(elem->data);
735 
736 	if (elem->name)
737 		free(elem->name);
738 
739 	if (elem->text)
740 
741 		free(elem->text);
742 	free(elem);
743 }
744 
sdp_xml_data_expand(struct sdp_xml_data * elem)745 struct sdp_xml_data *sdp_xml_data_expand(struct sdp_xml_data *elem)
746 {
747 	char *newbuf;
748 
749 	newbuf = malloc(elem->size * 2);
750 	if (!newbuf)
751 		return NULL;
752 
753 	memcpy(newbuf, elem->text, elem->size);
754 	elem->size *= 2;
755 	free(elem->text);
756 
757 	elem->text = newbuf;
758 
759 	return elem;
760 }
761 
sdp_xml_parse_datatype(const char * el,struct sdp_xml_data * elem,sdp_record_t * record)762 sdp_data_t *sdp_xml_parse_datatype(const char *el, struct sdp_xml_data *elem,
763 							sdp_record_t *record)
764 {
765 	const char *data = elem->text;
766 
767 	if (!strcmp(el, "boolean"))
768 		return sdp_xml_parse_int(data, SDP_BOOL);
769 	else if (!strcmp(el, "uint8"))
770 		return sdp_xml_parse_int(data, SDP_UINT8);
771 	else if (!strcmp(el, "uint16"))
772 		return sdp_xml_parse_int(data, SDP_UINT16);
773 	else if (!strcmp(el, "uint32"))
774 		return sdp_xml_parse_int(data, SDP_UINT32);
775 	else if (!strcmp(el, "uint64"))
776 		return sdp_xml_parse_int(data, SDP_UINT64);
777 	else if (!strcmp(el, "uint128"))
778 		return sdp_xml_parse_int(data, SDP_UINT128);
779 	else if (!strcmp(el, "int8"))
780 		return sdp_xml_parse_int(data, SDP_INT8);
781 	else if (!strcmp(el, "int16"))
782 		return sdp_xml_parse_int(data, SDP_INT16);
783 	else if (!strcmp(el, "int32"))
784 		return sdp_xml_parse_int(data, SDP_INT32);
785 	else if (!strcmp(el, "int64"))
786 		return sdp_xml_parse_int(data, SDP_INT64);
787 	else if (!strcmp(el, "int128"))
788 		return sdp_xml_parse_int(data, SDP_INT128);
789 	else if (!strcmp(el, "uuid"))
790 		return sdp_xml_parse_uuid(data, record);
791 	else if (!strcmp(el, "url"))
792 		return sdp_xml_parse_url(data);
793 	else if (!strcmp(el, "text"))
794 		return sdp_xml_parse_text(data, elem->type);
795 	else if (!strcmp(el, "nil"))
796 		return sdp_xml_parse_nil(data);
797 
798 	return NULL;
799 }
800