libsyncml 0.5.4

- Main Page
- Modules
- Data Structures
- Files

- File List

sml_xml_parse.c
1 /*
2 * libsyncml - A syncml protocol implementation
3 * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4 * Copyright (C) 2007-2009 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include <libsyncml/syncml.h>
23
24 #include <libsyncml/syncml_internals.h>
25 #include <libsyncml/sml_elements_internals.h>
26 #include <libsyncml/sml_command_internals.h>
27 #include <libsyncml/sml_devinf_internals.h>
28 #include <libsyncml/sml_session_internals.h>
29 #include "libsyncml/sml_error_internals.h"
30
31 #include "sml_xml_parse.h"
32 #include "sml_xml_parse_internals.h"
33
34 #define BUFFER_SIZE 500
35
36 static SmlBool _smlXmlParserStep(SmlXmlParser *parser)
37 {
38 SmlBool ret = FALSE;
39 do {
40 ret = (xmlTextReaderRead(parser->reader) == 1) ? TRUE : FALSE;
41 } while (ret && (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE || \
42 xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE || \
43 xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE));
44
45 return ret;
46 }
47
48 static SmlBool _smlXmlParserStepData(SmlXmlParser *parser)
49 {
50 SmlBool ret = FALSE;
51 do {
52 ret = (xmlTextReaderRead(parser->reader) == 1) ? TRUE : FALSE;
53 } while (ret && (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE || \
54 xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE));
55
56 return ret;
57 }
58
59 static SmlBool _smlXmlSkipNode(SmlXmlParser *parser)
60 {
61 int node_type;
62
63 if (xmlTextReaderNext(parser->reader) != 1)
64 return FALSE;
65
66 node_type = xmlTextReaderNodeType(parser->reader);
67 while (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE ||
68 xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE ||
69 xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE)
70 {
71 if (!_smlXmlParserStep (parser))
72 return FALSE;
73 }
74
75 return TRUE;
76 }
77
78 static SmlBool _smlXmlParserExpectNode(SmlXmlParser *parser, int type, SmlBool empty, const char *name, SmlError **error)
79 {
80 CHECK_ERROR_REF
81 if (!_smlXmlParserStep(parser)) {
82 smlErrorSet(error, SML_ERROR_GENERIC, "No node at all");
83 return FALSE;
84 }
85
86 if (xmlTextReaderNodeType(parser->reader) != type) {
87 smlErrorSet(error, SML_ERROR_GENERIC, "wrong node type");
88 return FALSE;
89 }
90
91
92 switch (type) {
93 case XML_NODE_START:
94 case XML_NODE_CLOSE:
95 if (name) {
96 if (!xmlTextReaderConstName(parser->reader)) {
97 smlErrorSet(error, SML_ERROR_GENERIC, "no name");
98 return FALSE;
99 }
100
101 if (strcmp((char *)xmlTextReaderConstName(parser->reader), name)) {
102 smlErrorSet(error, SML_ERROR_GENERIC, "Wrong name");
103 return FALSE;
104 }
105 }
106 break;
107 case XML_NODE_TEXT:
108 if (!empty && !xmlTextReaderConstName(parser->reader)) {
109 smlErrorSet(error, SML_ERROR_GENERIC, "Empty.");
110 return FALSE;
111 }
112 break;
113 default:
114 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown node type");
115 return FALSE;
116 }
117
118 return TRUE;
119 }
120
121 static SmlBool _smlXmlParserGetID(SmlXmlParser *parser, unsigned int *id, const char *name, SmlError **error)
122 {
123 CHECK_ERROR_REF
124 smlAssert(parser);
125 smlAssert(id);
126
127 if (*id) {
128 smlErrorSet(error, SML_ERROR_GENERIC, "Id already set");
129 goto error;
130 }
131
132 if (!_smlXmlParserExpectNode(parser, XML_NODE_TEXT, FALSE, NULL, error))
133 goto error;
134
135 *id = atoi(g_strstrip((char *)xmlTextReaderConstValue(parser->reader)));
136
137 if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, name, error))
138 goto error;
139
140 return TRUE;
141
142 error:
143 return FALSE;
144 }
145
146 static SmlBool _smlXmlParserGetString(SmlXmlParser *parser, char **string, const char *name, SmlError **error)
147 {
148 CHECK_ERROR_REF
149 smlAssert(parser);
150 smlAssert(string);
151
152 if (*string) {
153 smlErrorSet(error, SML_ERROR_GENERIC, "string already set");
154 goto error;
155 }
156
157 /* required for empty elements like <FwV/> */
158 if (xmlTextReaderIsEmptyElement(parser->reader)) {
159 *string = g_strdup("");
160 return TRUE;
161 }
162
163 if (!_smlXmlParserStep(parser)) {
164 smlErrorSet(error, SML_ERROR_GENERIC, "No node at all");
165 goto error_clear;
166 }
167
168 if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) {
169 *string = g_strstrip(g_strdup((char *)xmlTextReaderConstValue(parser->reader)));
170
171 if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, name, error))
172 goto error_clear;
173 } else if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
174 *string = g_strdup("");
175 } else {
176 smlErrorSet(error, SML_ERROR_GENERIC, "wrong node type");
177 goto error_clear;
178 }
179
180 return TRUE;
181
182 error_clear:
183 *string = NULL;
184 error:
185 return FALSE;
186 }
187
188 static SmlBool _smlXmlParserGetData(SmlXmlParser *parser, char **string, unsigned int *size, const char *name, SmlError **error)
189 {
190 CHECK_ERROR_REF
191 smlAssert(parser);
192 smlAssert(string);
193 int rc = 0;
194
195 if (*string) {
196 smlErrorSet(error, SML_ERROR_GENERIC, "string already set");
197 return FALSE;
198 }
199
200
201 xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE);
202 if (!buffer) {
203 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
204 goto error;
205 }
206
207 xmlTextWriter *writer = xmlNewTextWriterMemory(buffer, 0);
208 if (!writer) {
209 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
210 goto error_free_buffer;
211 }
212
213 /* SyncML 1.2 allows empty data elements <Data /> */
214 if (xmlTextReaderIsEmptyElement(parser->reader))
215 goto out;
216
217 while (1) {
218 if (!_smlXmlParserStepData(parser)) {
219 smlErrorSet(error, SML_ERROR_GENERIC, "There is a missing node during the data parsing of %s.", name);
220 goto error_free_writer;
221 }
222
223 switch (xmlTextReaderNodeType(parser->reader)) {
224 case XML_NODE_CLOSE:
225 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), name))
226 goto out;
227
228 if (!xmlTextReaderIsEmptyElement(parser->reader))
229 rc = xmlTextWriterEndElement(writer);
230
231 if (rc < 0) {
232 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end node");
233 goto error_free_writer;
234 }
235 break;
236 case XML_NODE_START:
237 if (!xmlTextReaderIsEmptyElement(parser->reader))
238 rc = xmlTextWriterStartElementNS(writer, NULL, xmlTextReaderConstName(parser->reader), NULL);
239 else
240 rc = xmlTextWriterWriteElementNS(writer, NULL, xmlTextReaderConstName(parser->reader), NULL, (const xmlChar*)"");
241
242 if (rc < 0) {
243 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to start node");
244 goto error_free_writer;
245 }
246 break;
247 case XML_NODE_CDATA:
248 case XML_NODE_TEXT:
249 rc = xmlTextWriterWriteRaw(writer, xmlTextReaderConstValue(parser->reader));
250 if (rc < 0) {
251 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string");
252 goto error_free_writer;
253 }
254 break;
255 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
256 rc = xmlTextWriterWriteRaw(writer, xmlTextReaderConstValue(parser->reader));
257 if (rc < 0) {
258 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string");
259 goto error_free_writer;
260 }
261 break;
262 default:
263 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown node type");
264 goto error_free_writer;
265 }
266 }
267
268 out:
269 // do not call xmlTextWriterEndDocument here
270 // the writer was not started with xmlTextWriterStartDocument
271 // the function adds always a newline
272 // if you load only a CDATA field then a newline is additional data
273 // additional data invalidates size information of the remote peer
274 // additional data crashs by this way all length checks if smlItemCheck !!!
275
276 xmlFreeTextWriter(writer);
277 *string = g_strndup((const char *) xmlBufferContent(buffer), xmlBufferLength(buffer));
278 if (size)
279 *size = xmlBufferLength(buffer);
280
281 xmlBufferFree(buffer);
282
283 return TRUE;
284
285 error_free_writer:
286 xmlFreeTextWriter(writer);
287 error_free_buffer:
288 xmlBufferFree(buffer);
289 error:
290 *string = NULL;
291 if (size) *size = 0;
292 return FALSE;
293 }
294
295 static SmlBool _smlSyncHeaderParseDTD(SmlProtocolVersion *version, SmlXmlParser *parser, SmlError **error)
296 {
297 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, version, parser, error);
298 CHECK_ERROR_REF
299 smlAssert(parser);
300 smlAssert(version);
301
302 if (*version) {
303 smlErrorSet(error, SML_ERROR_GENERIC, "dtd already set");
304 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
305 return FALSE;
306 }
307
308 char *dtd = NULL;
309 if (!_smlXmlParserGetString(parser, &dtd, SML_ELEMENT_VERDTD, error))
310 goto error;
311
312 if (!strcmp(dtd, "1.0"))
313 *version = SML_VERSION_10;
314 else if (!strcmp(dtd, "1.1"))
315 *version = SML_VERSION_11;
316 else if (!strcmp(dtd, "1.2"))
317 *version = SML_VERSION_12;
318 else {
319 smlSafeCFree(&dtd);
320 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown VerDTD");
321 goto error;
322 }
323 smlSafeCFree(&dtd);
324
325 smlTrace(TRACE_EXIT, "%s", __func__);
326 return TRUE;
327
328 error:
329 *version = SML_VERSION_UNKNOWN;
330 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
331 return FALSE;
332 }
333
334 static SmlBool _smlSyncHeaderParseProto(SmlProtocolType *type, SmlXmlParser *parser, SmlError **error)
335 {
336 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, type, parser, error);
337 CHECK_ERROR_REF
338 smlAssert(parser);
339 smlAssert(type);
340
341 if (*type) {
342 smlErrorSet(error, SML_ERROR_GENERIC, "protocol already set");
343 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
344 return FALSE;
345 }
346
347 char *proto = NULL;
348 if (!_smlXmlParserGetString(parser, &proto, SML_ELEMENT_VERPROTO, error))
349 goto error;
350
351 if (!strcmp(proto, SML_VERSION_STRING_10) || !strcmp(proto, SML_VERSION_STRING_11) || !strcmp(proto, SML_VERSION_STRING_12))
352 *type = SML_PROTOCOL_SYNCML;
353 else {
354 smlSafeCFree(&proto);
355 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown VerProto");
356 goto error;
357 }
358 smlSafeCFree(&proto);
359
360 smlTrace(TRACE_EXIT, "%s", __func__);
361 return TRUE;
362
363 error:
364 *type = SML_PROTOCOL_UNKNOWN;
365 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
366 return FALSE;
367 }
368
369
370 static SmlBool _smlLocationParse(SmlLocation **location, SmlXmlParser *parser, SmlError **error)
371 {
372 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, location, parser, error);
373 CHECK_ERROR_REF
374 smlAssert(parser);
375 smlAssert(location);
376
377 if (*location) {
378 smlErrorSet(error, SML_ERROR_GENERIC, "Location already set");
379 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
380 return FALSE;
381 }
382
383 *location = smlTryMalloc0(sizeof(SmlLocation), error);
384 if (!location)
385 goto error;
386 (*location)->refCount = 1;
387
388 while (1) {
389 if (!_smlXmlParserStep(parser)) {
390 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
391 goto error_free_location;
392 }
393
394 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET) && \
395 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
396 break;
397 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE) && \
398 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
399 break;
400 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE_PARENT) && \
401 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
402 break;
403 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET_PARENT) && \
404 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
405 break;
406 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
407 smlErrorSet(error, SML_ERROR_GENERIC,
408 "The element %s is not a start node in locations (Target, Source, SourceParent or TargetParent).",
409 xmlTextReaderConstName(parser->reader));
410 goto error_free_location;
411 }
412
413 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LOCURI)) {
414 if (!_smlXmlParserGetString(parser, &((*location)->locURI), SML_ELEMENT_LOCURI, error))
415 goto error_free_location;
416 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LOCNAME)) {
417 if (!_smlXmlParserGetString(parser, &((*location)->locName), SML_ELEMENT_LOCNAME, error))
418 goto error_free_location;
419 } else {
420 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node. expected SyncHdr");
421 goto error_free_location;
422 }
423 }
424
425 if (!(*location)->locURI) {
426 smlErrorSet(error, SML_ERROR_GENERIC, "No locURI set");
427 goto error_free_location;
428 }
429
430 smlTrace(TRACE_EXIT, "%s", __func__);
431 return TRUE;
432
433 error_free_location:
434 smlLocationUnref(*location);
435 error:
436 *location = NULL;
437 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
438 return FALSE;
439 }
440
441 static SmlBool _smlAnchorParse(SmlAnchor **anchor, SmlXmlParser *parser, SmlError **error)
442 {
443 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, anchor, parser, error);
444 CHECK_ERROR_REF
445 smlAssert(parser);
446 smlAssert(anchor);
447
448 if (*anchor) {
449 smlErrorSet(error, SML_ERROR_GENERIC, "anchor already set");
450 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
451 return FALSE;
452 }
453
454 *anchor = smlTryMalloc0(sizeof(SmlAnchor), error);
455 if (!anchor)
456 goto error;
457
458 while (1) {
459 if (!_smlXmlParserStep(parser)) {
460 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
461 goto error_free_anchor;
462 }
463
464 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ANCHOR) && \
465 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
466 break;
467 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
468 smlErrorSet(error, SML_ERROR_GENERIC,
469 "The element %s is not a start node in Anchor.",
470 xmlTextReaderConstName(parser->reader));
471 goto error_free_anchor;
472 }
473
474 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NEXT)) {
475 if (!_smlXmlParserGetString(parser, &((*anchor)->next), SML_ELEMENT_NEXT, error))
476 goto error_free_anchor;
477 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LAST)) {
478 if (!_smlXmlParserGetString(parser, &((*anchor)->last), SML_ELEMENT_LAST, error))
479 goto error_free_anchor;
480 } else {
481 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
482 goto error_free_anchor;
483 }
484 }
485
486 if (!(*anchor)->next) {
487 smlErrorSet(error, SML_ERROR_GENERIC, "No next set");
488 goto error_free_anchor;
489 }
490
491 smlTrace(TRACE_EXIT, "%s", __func__);
492 return TRUE;
493
494 error_free_anchor:
495 smlAnchorFree(*anchor);
496 error:
497 *anchor = NULL;
498 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
499 return FALSE;
500 }
501
502 static SmlBool _smlChalMetaParse(SmlXmlParser *parser, char **format, char **type, char **nonce, SmlError **error)
503 {
504 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p, %p)", __func__, parser, format, type, nonce, error);
505 CHECK_ERROR_REF
506 smlAssert(parser);
507
508 while (1) {
509 if (!_smlXmlParserStep(parser)) {
510 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
511 goto error;
512 }
513
514 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \
515 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
516 break;
517 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
518 smlErrorSet(error, SML_ERROR_GENERIC,
519 "The element %s is not a start node in Chal/Meta.",
520 xmlTextReaderConstName(parser->reader));
521 goto error;
522 }
523
524 if (type && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TYPE)) {
525 if (!_smlXmlParserGetString(parser, type, SML_ELEMENT_TYPE, error))
526 goto error;
527 } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FORMAT)) {
528 if (!_smlXmlParserGetString(parser, format, SML_ELEMENT_FORMAT, error))
529 goto error;
530 } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NEXTNONCE)) {
531 if (!_smlXmlParserGetString(parser, nonce, SML_ELEMENT_NEXTNONCE, error))
532 goto error;
533 } else {
534 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", xmlTextReaderConstName(parser->reader));
535 goto error;
536 }
537 }
538
539 smlTrace(TRACE_EXIT, "%s", __func__);
540 return TRUE;
541
542 error:
543 if (format)
544 *format = NULL;
545 if (nonce)
546 *nonce = NULL;
547 if (type)
548 *type = NULL;
549
550 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
551 return FALSE;
552 }
553
554 static SmlBool _smlCommandMetaParse(SmlXmlParser *parser, char **format, char **type, SmlAnchor **anchor, unsigned int *size, int *maxobjsize, SmlError **error)
555 {
556 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p, %p)", __func__, parser, format, type, anchor, size, maxobjsize, error);
557 CHECK_ERROR_REF
558 smlAssert(parser);
559
560 if (maxobjsize)
561 *maxobjsize = -1;
562
563 if (xmlTextReaderIsEmptyElement(parser->reader))
564 {
565 /* empty meta element <meta/> */
566 smlTrace(TRACE_EXIT, "%s - empty meta element", __func__);
567 return TRUE;
568 }
569
570 while (1) {
571 if (!_smlXmlParserStep(parser)) {
572 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
573 goto error;
574 }
575
576 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MEM)) {
577 /* Ignored for now */
578 smlTrace(TRACE_INTERNAL, "%s: Skipping mem node");
579 if (!_smlXmlSkipNode(parser)) {
580 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to skip mem node");
581 goto error;
582 }
583 }
584
585 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \
586 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
587 break;
588 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
589 smlErrorSet(error, SML_ERROR_GENERIC,
590 "The element %s is not a start node in Command/Meta.",
591 xmlTextReaderConstName(parser->reader));
592 goto error;
593 }
594
595 if (type && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TYPE)) {
596 if (!_smlXmlParserGetString(parser, type, SML_ELEMENT_TYPE, error))
597 goto error;
598 } else if (anchor && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ANCHOR)) {
599 if (!_smlAnchorParse(anchor, parser, error))
600 goto error;
601 } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FORMAT)) {
602 if (!_smlXmlParserGetString(parser, format, SML_ELEMENT_FORMAT, error))
603 goto error;
604 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MARK)) {
605 /* Ignore the mark for now */
606 char *mark = NULL;
607 if (!_smlXmlParserGetString(parser, &mark, SML_ELEMENT_MARK, error))
608 goto error;
609 smlSafeCFree(&mark);
610 } else if (size && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SIZE)) {
611 if (!_smlXmlParserGetID(parser, size, SML_ELEMENT_SIZE, error))
612 goto error;
613 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXOBJSIZE)) {
614 /* MaxObjSize must be parsed even if there is no maxobjsize pointer */
615 unsigned int loc_maxobjsize = 0;
616 if (!_smlXmlParserGetID(parser, &loc_maxobjsize, SML_ELEMENT_MAXOBJSIZE, error))
617 goto error;
618 if (maxobjsize)
619 *maxobjsize = loc_maxobjsize;
620 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERSION)) {
621 /* Ignore the version for now */
622 char *version = NULL;
623 if (!_smlXmlParserGetString(parser, &version, SML_ELEMENT_VERSION, error))
624 goto error;
625 smlSafeCFree(&version);
626 } else {
627 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node for meta information: %s", xmlTextReaderConstName(parser->reader));
628 goto error;
629 }
630 }
631
632 smlTrace(TRACE_EXIT, "%s", __func__);
633 return TRUE;
634
635 error:
636 if (format)
637 *format = NULL;
638 if (anchor)
639 *anchor = NULL;
640 if (type)
641 *type = NULL;
642 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
643 return FALSE;
644 }
645
646 static SmlItem *_smlItemParse(SmlXmlParser *parser, SmlCommand *cmd, SmlCommandType type, SmlError **error)
647 {
648 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, cmd, type, error);
649 CHECK_ERROR_REF
650 smlAssert(parser);
651
652 if (parser->gotMoreData) {
653 smlErrorSet(error, SML_ERROR_GENERIC, "Last item already had more data set");
654 goto error;
655 }
656
657 SmlItem *item = smlItemNew(0, error);
658 if (!item)
659 goto error;
660
661 /* If the item is an empty element then return immediately. */
662 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM) &&
663 xmlTextReaderIsEmptyElement(parser->reader)) {
664 smlTrace(TRACE_EXIT, "%s - empty item", __func__);
665 return item;
666 }
667
668 if (!_smlXmlParserStep(parser)) {
669 smlErrorSet(error, SML_ERROR_GENERIC, "The first element inside of an Item structure cannot be parsed.");
670 goto error_free_item;
671 }
672
673 while (1) {
674 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM) && \
675 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
676 break;
677 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
678 smlErrorSet(error, SML_ERROR_GENERIC,
679 "The element %s is not a start node in Item.",
680 xmlTextReaderConstName(parser->reader));
681 goto error_free_item;
682 }
683
684 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) {
685 SmlLocation *source = NULL;
686 if (!_smlLocationParse(&source, parser, error))
687 goto error_free_item;
688
689 smlItemSetSource(item, source);
690 smlLocationUnref(source);
691 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) {
692 SmlLocation *target = NULL;
693 if (!_smlLocationParse(&target, parser, error))
694 goto error_free_item;
695
696 smlItemSetTarget(item, target);
697 smlLocationUnref(target);
698 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE_PARENT)) {
699 SmlLocation *source = NULL;
700 if (!_smlLocationParse(&source, parser, error))
701 goto error_free_item;
702
703 smlItemSetSourceParent(item, source);
704 smlLocationUnref(source);
705 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET_PARENT)) {
706 SmlLocation *target = NULL;
707 if (!_smlLocationParse(&target, parser, error))
708 goto error_free_item;
709
710 smlItemSetTargetParent(item, target);
711 smlLocationUnref(target);
712 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
713 switch (type) {
714 case SML_COMMAND_TYPE_ALERT:
715 if (!cmd) {
716 /* This is an item inside a status.
717 * We must parse the meta data
718 * but we ignore the content completely.
719 * FIXME: Can we ignore the content?
720 */
721 if (!_smlCommandMetaParse(parser, NULL, NULL, NULL, NULL, NULL, error))
722 goto error_free_item;
723 } else {
724 /* Some phones send the maxobjsize in the alert */
725 if (!_smlCommandMetaParse(parser, NULL, &(cmd->private.alert.contentType), &cmd->private.alert.anchor, NULL, &(cmd->private.alert.maxObjSize), error))
726 goto error_free_item;
727 }
728 break;
729 case SML_COMMAND_TYPE_ADD:
730 case SML_COMMAND_TYPE_DELETE:
731 case SML_COMMAND_TYPE_REPLACE:
732 if (!_smlCommandMetaParse(parser, NULL, &(item->contenttype), NULL, &cmd->size, NULL, error))
733 goto error_free_item;
734 break;
735 case SML_COMMAND_TYPE_RESULTS:
736 case SML_COMMAND_TYPE_PUT:;
737 /* Some phones send the type information for the devinf put
738 * not in the put itself but in the item */
739 if (!_smlCommandMetaParse(parser, NULL, &(item->contenttype), NULL, NULL, NULL, error))
740 goto error_free_item;
741
742 if (!item->contenttype)
743 goto error_free_item;
744 break;
745 default:
746 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type");
747 goto error_free_item;
748 }
749 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) {
750 /* Do nothing if the Data element is empty.
751 * The first emptyness test only covers <Data/>.
752 *
753 * Example: Funambol with WBXML on scheduleworld.com
754 */
755 if (!xmlTextReaderIsEmptyElement(parser->reader)) {
756 switch (type) {
757 case SML_COMMAND_TYPE_ALERT:
758 if (!_smlXmlParserStep(parser)) {
759 smlErrorSet(error, SML_ERROR_GENERIC, "The next element after the starting Data element in an Item is missing.");
760 goto error_free_item;
761 }
762
763 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA) &&
764 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
765 /* Do nothing if the Data element is empty.
766 * This only covers <Data></Data>.
767 *
768 * Example: Funambol with XML on scheduleworld.com
769 */
770 smlTrace(TRACE_INTERNAL, "%s: detected empty data element", __func__);
771 break;
772 }
773
774 SmlAnchor *anchor = NULL;
775 if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) {
776 /* Google just copies the element Next from the Anchor
777 * Please see ticket #230 for more details.
778 */
779 anchor = smlTryMalloc0(sizeof(SmlAnchor), error);
780 if (!anchor)
781 goto error_free_item;
782 anchor->next = g_strdup((char *)xmlTextReaderConstValue(parser->reader));
783 } else {
784 /* normal behaviour with anchor copy */
785 if (!_smlAnchorParse(&anchor, parser, error))
786 goto error_free_item;
787 }
788 item->anchor = anchor;
789
790 if (!_smlXmlParserStep(parser)) {
791 smlErrorSet(error, SML_ERROR_GENERIC, "The closing Data element in an Item is missing.");
792 goto error_free_item;
793 }
794 break;
795 default:;
796 char *data = NULL;
797 unsigned int size = 0;
798 if (!_smlXmlParserGetData(parser, &data, &size, SML_ELEMENT_DATA, error))
799 goto error_free_item;
800
801 if (!smlItemAddData(item, data, size, error)) {
802 smlSafeCFree(&data);
803 goto error_free_item;
804 }
805
806 smlSafeCFree(&data);
807 }
808 }
809 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOREDATA)) {
810 if (parser->version == SML_VERSION_10) {
811 smlErrorSet(error, SML_ERROR_GENERIC, "SyncML 1.0 does not allow MoreData");
812 goto error_free_item;
813 }
814
815 item->moreData = TRUE;
816 parser->gotMoreData = TRUE;
817 if (!_smlXmlParserStep(parser)) {
818 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2");
819 goto error_free_item;
820 }
821
822 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOREDATA) && \
823 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
824 if (!_smlXmlParserStep(parser)) {
825 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes3");
826 goto error_free_item;
827 }
828 }
829 continue;
830 } else {
831 smlErrorSet(error, SML_ERROR_GENERIC, "The element Item does not support the child element %s.", xmlTextReaderConstName(parser->reader));
832 goto error_free_item;
833 }
834
835 if (!_smlXmlParserStep(parser)) {
836 smlErrorSet(error, SML_ERROR_GENERIC, "The next element in an Item structure is missing.");
837 goto error_free_item;
838 }
839 }
840
841 smlTrace(TRACE_EXIT, "%s", __func__);
842 return item;
843
844 error_free_item:
845 smlItemUnref(item);
846 error:
847 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
848 return NULL;
849 }
850
851 static SmlCred *_smlCredParse(SmlXmlParser *parser, SmlError **error)
852 {
853 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error);
854 CHECK_ERROR_REF
855 smlAssert(parser);
856 SmlCred *cred = NULL;
857 char *format = NULL;
858 char *type = NULL;
859 char *data = NULL;
860
861 while (1) {
862 if (!_smlXmlParserStep(parser)) {
863 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
864 goto error;
865 }
866
867 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CRED) && \
868 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
869 break;
870 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
871 smlErrorSet(error, SML_ERROR_GENERIC,
872 "The element %s is not a start node in Cred.",
873 xmlTextReaderConstName(parser->reader));
874 goto error;
875 }
876
877 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
878 if (!_smlCommandMetaParse(parser, &format, &type, NULL, NULL, NULL, error))
879 goto error;
880 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) {
881 if (!_smlXmlParserGetString(parser, &data, SML_ELEMENT_DATA, error))
882 goto error;
883 } else {
884 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader));
885 goto error;
886 }
887 }
888
889 cred = smlCredNewFromString(type, format, data, error);
890
891 error:
892 if (data)
893 smlSafeCFree(&data);
894
895 if (format)
896 smlSafeCFree(&format);
897
898 if (type)
899 smlSafeCFree(&type);
900
901 if (!smlErrorIsSet(error))
902 {
903 smlTrace(TRACE_EXIT, "%s: %p", __func__, cred);
904 return cred;
905 } else {
906 if (cred)
907 smlCredUnref(cred);
908 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
909 return NULL;
910 }
911 }
912
913 static SmlChal *_smlChalParse(SmlXmlParser *parser, SmlError **error)
914 {
915 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error);
916 CHECK_ERROR_REF
917 smlAssert(parser);
918 char *format = NULL;
919 char *type = NULL;
920 char *nonce = NULL;
921
922 while (1) {
923 if (!_smlXmlParserStep(parser)) {
924 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
925 goto error;
926 }
927
928 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CHAL) && \
929 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
930 break;
931 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
932 smlErrorSet(error, SML_ERROR_GENERIC,
933 "The element %s is not a start node in Chal.",
934 xmlTextReaderConstName(parser->reader));
935 goto error;
936 }
937
938 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
939 if (!_smlChalMetaParse(parser, &format, &type, &nonce, error))
940 goto error;
941 } else {
942 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader));
943 goto error;
944 }
945 }
946
947 if (format && strcmp(format, SML_BASE64)) {
948 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown format");
949 goto error;
950 }
951
952 SmlAuthType auth;
953 if (!type || !strcmp(type, SML_AUTH_BASIC)) {
954 auth = SML_AUTH_TYPE_BASIC;
955 } else if (!strcmp(type, SML_AUTH_MD5)) {
956 auth = SML_AUTH_TYPE_MD5;
957 } else {
958 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type");
959 goto error;
960 }
961
962 if (format)
963 smlSafeCFree(&format);
964 if (type)
965 smlSafeCFree(&type);
966
967 SmlChal *chal = NULL;
968 if (nonce || auth == SML_AUTH_TYPE_MD5)
969 chal = smlChalNewFromBase64(auth, nonce, error);
970 else
971 chal = smlChalNew(auth, error);
972 if (!chal)
973 goto error;
974
975 if (nonce)
976 smlSafeCFree(&nonce);
977
978 smlTrace(TRACE_EXIT, "%s: %p", __func__, chal);
979 return chal;
980
981 error:
982 if (format)
983 smlSafeCFree(&format);
984 if (type)
985 smlSafeCFree(&type);
986 if (nonce)
987 smlSafeCFree(&nonce);
988 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
989 return NULL;
990 }
991
992 static SmlBool _smlChangeParse(SmlXmlParser *parser, SmlCommand **cmd, SmlCommandType type, const char *name, SmlError **error)
993 {
994 smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p)", __func__, parser, type, VA_STRING(name), error);
995 CHECK_ERROR_REF
996 smlAssert(parser);
997 smlAssert(name);
998 char *contenttype = NULL;
999
1000 *cmd = smlCommandNew(type, error);
1001 if (!*cmd)
1002 goto error;
1003 (*cmd)->refCount = 1;
1004
1005 while (1) {
1006 if (!_smlXmlParserStep(parser)) {
1007 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1008 goto error_free_cmd;
1009 }
1010
1011 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), name) && \
1012 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1013 break;
1014 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1015 smlErrorSet(error, SML_ERROR_GENERIC,
1016 "The element %s is not a start node in %s.",
1017 xmlTextReaderConstName(parser->reader), name);
1018 goto error_free_cmd;
1019 }
1020
1021 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1022 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1023 goto error_free_cmd;
1024 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
1025 SmlItem *item = _smlItemParse(parser, *cmd, type, error);
1026 if (!item)
1027 goto error_free_cmd;
1028 (*cmd)->private.change.items = g_list_append((*cmd)->private.change.items, item);
1029 if (!(*cmd)->private.change.items)
1030 {
1031 smlItemUnref(item);
1032 smlErrorSet(error, SML_ERROR_GENERIC, "g_list_append for item list of change command failed.");
1033 goto error_free_cmd;
1034 }
1035 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
1036 if (!_smlCommandMetaParse(parser, NULL, &contenttype, NULL, &(*cmd)->size, NULL, error))
1037 goto error_free_cmd;
1038 } else {
1039 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
1040 goto error_free_cmd;
1041 }
1042 }
1043
1044 if (!(*cmd)->cmdID) {
1045 smlErrorSet(error, SML_ERROR_GENERIC, "No cmdid set");
1046 goto error_free_cmd;
1047 }
1048
1049 if (!(*cmd)->private.change.items ||
1050 !g_list_length((*cmd)->private.change.items)) {
1051 smlErrorSet(error, SML_ERROR_GENERIC, "No items set");
1052 goto error_free_cmd;
1053 }
1054
1055 /* some clients set the contentype in the item, don't overwrite it with NULL */
1056 guint i;
1057 for (i=0; i < g_list_length((*cmd)->private.change.items); i++)
1058 {
1059 SmlItem *item = g_list_nth_data((*cmd)->private.change.items, i);
1060 if (item->contenttype == NULL && contenttype) {
1061 item->contenttype = g_strdup(contenttype);
1062 }
1063 }
1064 if (contenttype)
1065 smlSafeCFree(&contenttype);
1066
1067 for (i=0; i < g_list_length((*cmd)->private.change.items); i++)
1068 {
1069 SmlItem *item = g_list_nth_data((*cmd)->private.change.items, i);
1070 if ((*cmd)->size && !item->size)
1071 item->size = (*cmd)->size;
1072 }
1073
1074 switch (type) {
1075 case SML_COMMAND_TYPE_ADD:
1076 (*cmd)->private.change.type = SML_CHANGE_ADD;
1077 break;
1078 case SML_COMMAND_TYPE_REPLACE:
1079 (*cmd)->private.change.type = SML_CHANGE_REPLACE;
1080 break;
1081 case SML_COMMAND_TYPE_DELETE:
1082 (*cmd)->private.change.type = SML_CHANGE_DELETE;
1083 break;
1084 default:
1085 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown change type set");
1086 goto error_free_cmd;
1087 }
1088
1089 if (!(*cmd)->source)
1090 {
1091 SmlItem *item = g_list_nth_data((*cmd)->private.change.items, 0);
1092 if (item->source) {
1093 (*cmd)->source = smlLocationClone(item->source, error);
1094 if (!(*cmd)->source)
1095 goto error_free_cmd;
1096 }
1097 }
1098
1099 if (!(*cmd)->target)
1100 {
1101 SmlItem *item = g_list_nth_data((*cmd)->private.change.items, 0);
1102 if (item->target) {
1103 (*cmd)->target = smlLocationClone(item->target, error);
1104 if (!(*cmd)->target)
1105 goto error_free_cmd;
1106 }
1107 }
1108
1109 /* Step once more */
1110 if (!_smlXmlParserStep(parser)) {
1111 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1112 goto error_free_cmd;
1113 }
1114
1115 smlTrace(TRACE_EXIT, "%s: %p", __func__, *cmd);
1116 return TRUE;
1117
1118 error_free_cmd:
1119 smlCommandUnref(*cmd);
1120 error:
1121 if (contenttype)
1122 smlSafeCFree(&contenttype);
1123 *cmd = NULL;
1124 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1125 return FALSE;
1126 }
1127
1128 static SmlBool _smlMessageParseSynchdrMeta(SmlXmlParser *parser, unsigned int *maxmsgsize, unsigned int *maxobjsize, char **emi, SmlError **error)
1129 {
1130 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, maxmsgsize, maxobjsize, error);
1131 CHECK_ERROR_REF
1132 smlAssert(parser);
1133 smlAssert(maxmsgsize);
1134 smlAssert(maxobjsize);
1135 smlAssert(emi);
1136
1137
1138 while (1) {
1139 if (!_smlXmlParserStep(parser)) {
1140 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1141 goto error;
1142 }
1143
1144 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \
1145 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1146 break;
1147 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1148 smlErrorSet(error, SML_ERROR_GENERIC,
1149 "The element %s is not a start node in SyncHdr/Meta.",
1150 xmlTextReaderConstName(parser->reader));
1151 goto error;
1152 }
1153
1154 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXMSGSIZE)) {
1155 if (!_smlXmlParserGetID(parser, maxmsgsize, SML_ELEMENT_MAXMSGSIZE, error))
1156 goto error;
1157 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXOBJSIZE)) {
1158 if (!_smlXmlParserGetID(parser, maxobjsize, SML_ELEMENT_MAXOBJSIZE, error))
1159 goto error;
1160 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_EMI)) {
1161 if (!_smlXmlParserGetString(parser, emi, SML_ELEMENT_EMI, error))
1162 goto error;
1163 } else {
1164 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node. expected MaxMsgSize, MaxObjSize or EMI. Instead of that: %s", xmlTextReaderConstName(parser->reader));
1165 goto error;
1166 }
1167 }
1168
1169 if (!(*maxmsgsize) && !(*maxobjsize)) {
1170 smlErrorSet(error, SML_ERROR_GENERIC, "No maxmsgsize set");
1171 goto error;
1172 }
1173
1174 smlTrace(TRACE_EXIT, "%s", __func__);
1175 return TRUE;
1176
1177 error:
1178 *maxmsgsize = 0;
1179 *maxobjsize = 0;
1180 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1181 return FALSE;
1182 }
1183
1184 static SmlBool _smlAlertParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error)
1185 {
1186 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
1187 CHECK_ERROR_REF
1188 smlAssert(parser);
1189 smlAssert(cmd);
1190
1191 *cmd = smlCommandNew(SML_COMMAND_TYPE_ALERT, error);
1192 if (!*cmd)
1193 goto error;
1194 (*cmd)->refCount = 1;
1195 (*cmd)->private.alert.maxObjSize = -1;
1196
1197 while (1) {
1198 if (!_smlXmlParserStep(parser)) {
1199 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1200 goto error_free_cmd;
1201 }
1202
1203 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ALERT) && \
1204 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1205 break;
1206 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1207 smlErrorSet(error, SML_ERROR_GENERIC,
1208 "The element %s is not a start node in Alert.",
1209 xmlTextReaderConstName(parser->reader));
1210 goto error_free_cmd;
1211 }
1212
1213 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1214 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1215 goto error_free_cmd;
1216 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
1217 SmlItem *item = _smlItemParse(parser, (*cmd), SML_COMMAND_TYPE_ALERT, error);
1218 if (!item)
1219 goto error_free_cmd;
1220
1221 (*cmd)->target = item->target;
1222 item->target = NULL;
1223 (*cmd)->source = item->source;
1224 item->source = NULL;
1225
1226 smlItemUnref(item);
1227 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) {
1228 unsigned int id = 0;
1229 if (!_smlXmlParserGetID(parser, &id, SML_ELEMENT_DATA, error))
1230 goto error_free_cmd;
1231 (*cmd)->private.alert.type = smlAlertTypeConvert(id, error);
1232 if ((*cmd)->private.alert.type == SML_ALERT_UNKNOWN &&
1233 *error != NULL)
1234 goto error_free_cmd;
1235 } else {
1236 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader));
1237 goto error_free_cmd;
1238 }
1239 }
1240
1241 if (!(*cmd)->private.alert.type) {
1242 smlErrorSet(error, SML_ERROR_GENERIC, "No alert type set");
1243 goto error_free_cmd;
1244 }
1245
1246 /* Step once more */
1247 if (!_smlXmlParserStep(parser)) {
1248 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1249 goto error_free_cmd;
1250 }
1251
1252 smlTrace(TRACE_EXIT, "%s", __func__);
1253 return TRUE;
1254
1255 error_free_cmd:
1256 smlCommandUnref(*cmd);
1257 error:
1258 *cmd = NULL;
1259 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1260 return FALSE;
1261 }
1262
1263 static SmlParserResult _smlCommandSyncParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error)
1264 {
1265 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
1266 CHECK_ERROR_REF
1267 smlAssert(parser);
1268 smlAssert(cmd);
1269
1270 *cmd = smlCommandNew(SML_COMMAND_TYPE_SYNC, error);
1271 if (!*cmd)
1272 goto error;
1273 (*cmd)->private.sync.maxObjSize = -1;
1274
1275 while (1) {
1276 if (!_smlXmlParserStep(parser)) {
1277 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1278 goto error_free_cmd;
1279 }
1280
1281 if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNC))
1282 break;
1283 else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1284 smlErrorSet(error, SML_ERROR_GENERIC,
1285 "The element %s is not a start node in Sync.",
1286 xmlTextReaderConstName(parser->reader));
1287 goto error_free_cmd;
1288 }
1289
1290 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ADD) || \
1291 !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_REPLACE) || \
1292 !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DELETE))
1293 break;
1294
1295 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1296 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1297 goto error_free_cmd;
1298 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
1299 SmlItem *item = _smlItemParse(parser, (*cmd), SML_COMMAND_TYPE_SYNC, error);
1300 if (!item)
1301 goto error_free_cmd;
1302 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
1303 if (!_smlCommandMetaParse(parser, NULL, NULL, NULL, NULL, &((*cmd)->private.sync.maxObjSize), error))
1304 goto error;
1305 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) {
1306 if (!_smlLocationParse(&(*cmd)->target, parser, error))
1307 goto error_free_cmd;
1308 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) {
1309 if (!_smlLocationParse(&(*cmd)->source, parser, error))
1310 goto error_free_cmd;
1311 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NUMBEROFCHANGES)) {
1312 (*cmd)->private.sync.hasNumChanged = TRUE;
1313 if (!_smlXmlParserGetID(parser, &((*cmd)->private.sync.numChanged), SML_ELEMENT_NUMBEROFCHANGES, error))
1314 goto error_free_cmd;
1315 } else {
1316 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", xmlTextReaderConstName(parser->reader));
1317 goto error_free_cmd;
1318 }
1319 }
1320
1321 smlTrace(TRACE_EXIT, "%s", __func__);
1322 return TRUE;
1323
1324 error_free_cmd:
1325 smlCommandUnref(*cmd);
1326 error:
1327 *cmd = NULL;
1328 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1329 return FALSE;
1330 }
1331
1332 static SmlMapItem *_smlMapItemParse(SmlXmlParser *parser, SmlError **error)
1333 {
1334 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error);
1335 CHECK_ERROR_REF
1336 smlAssert(parser);
1337
1338 SmlMapItem *item = smlTryMalloc0(sizeof(SmlMapItem), error);
1339 if (!item)
1340 goto error;
1341 item->refCount = 1;
1342
1343 while (1) {
1344 if (!_smlXmlParserStep(parser)) {
1345 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1346 goto error_free_item;
1347 }
1348
1349 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAPITEM) && \
1350 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1351 break;
1352 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1353 smlErrorSet(error, SML_ERROR_GENERIC,
1354 "The element %s is not a start node in MapItem.",
1355 xmlTextReaderConstName(parser->reader));
1356 goto error_free_item;
1357 }
1358
1359 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) {
1360 if (!_smlLocationParse(&item->source, parser, error))
1361 goto error_free_item;
1362 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) {
1363 if (!_smlLocationParse(&item->target, parser, error))
1364 goto error_free_item;
1365 } else {
1366 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader));
1367 goto error_free_item;
1368 }
1369 }
1370
1371 smlTrace(TRACE_EXIT, "%s", __func__);
1372 return item;
1373
1374 error_free_item:
1375 smlMapItemUnref(item);
1376 error:
1377 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1378 return NULL;
1379 }
1380
1381 static SmlBool _smlCommandMapParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error)
1382 {
1383 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
1384 CHECK_ERROR_REF
1385 smlAssert(parser);
1386 smlAssert(cmd);
1387
1388 *cmd = smlCommandNew(SML_COMMAND_TYPE_MAP, error);
1389 if (!*cmd)
1390 goto error;
1391 (*cmd)->refCount = 1;
1392
1393 while (1) {
1394 if (!_smlXmlParserStep(parser)) {
1395 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1396 goto error_free_cmd;
1397 }
1398
1399 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAP) && \
1400 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1401 break;
1402 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1403 smlErrorSet(error, SML_ERROR_GENERIC,
1404 "The element %s is not a start node in Map.",
1405 xmlTextReaderConstName(parser->reader));
1406 goto error_free_cmd;
1407 }
1408
1409 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1410 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1411 goto error_free_cmd;
1412 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAPITEM)) {
1413 SmlMapItem *item = _smlMapItemParse(parser, error);
1414 if (!item)
1415 goto error_free_cmd;
1416 (*cmd)->private.map.items = g_list_append((*cmd)->private.map.items, item);
1417 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) {
1418 if (!_smlLocationParse(&(*cmd)->target, parser, error))
1419 goto error_free_cmd;
1420 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) {
1421 if (!_smlLocationParse(&(*cmd)->source, parser, error))
1422 goto error_free_cmd;
1423 } else {
1424 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
1425 goto error_free_cmd;
1426 }
1427 }
1428
1429 /* Step once more */
1430 if (!_smlXmlParserStep(parser)) {
1431 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1432 goto error_free_cmd;
1433 }
1434
1435 smlTrace(TRACE_EXIT, "%s", __func__);
1436 return TRUE;
1437
1438 error_free_cmd:
1439 smlCommandUnref(*cmd);
1440 error:
1441 *cmd = NULL;
1442 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1443 return FALSE;
1444 }
1445
1446 static SmlBool _smlCommandAccessParse(SmlXmlParser *parser, SmlCommand **cmd, SmlCommandType type, SmlError **error)
1447 {
1448 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, cmd, type, error);
1449 CHECK_ERROR_REF
1450 smlAssert(parser);
1451 smlAssert(cmd);
1452 char *contenttype = NULL;
1453
1454 *cmd = smlCommandNew(type, error);
1455 if (!*cmd)
1456 goto error;
1457 (*cmd)->refCount = 1;
1458
1459 while (1) {
1460 if (!_smlXmlParserStep(parser)) {
1461 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1462 goto error_free_cmd;
1463 }
1464
1465 if ((*cmd)->type == SML_COMMAND_TYPE_PUT &&!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_PUT) && \
1466 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1467 break;
1468 } else if ((*cmd)->type == SML_COMMAND_TYPE_GET &&!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_GET) && \
1469 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1470 break;
1471 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1472 smlErrorSet(error, SML_ERROR_GENERIC,
1473 "The element %s is not a start node in Put or Get.",
1474 xmlTextReaderConstName(parser->reader));
1475 goto error_free_cmd;
1476 }
1477
1478 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1479 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1480 goto error_free_cmd;
1481 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
1482 (*cmd)->private.access.item = _smlItemParse(parser, (*cmd), (*cmd)->type, error);
1483 if (!(*cmd)->private.access.item)
1484 goto error_free_cmd;
1485
1486 (*cmd)->target = (*cmd)->private.access.item->target;
1487 (*cmd)->private.access.item->target = NULL;
1488 (*cmd)->source = (*cmd)->private.access.item->source;
1489 (*cmd)->private.access.item->source = NULL;
1490 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
1491 char *format = NULL;
1492 if (!_smlCommandMetaParse(parser, &format, &contenttype, NULL, NULL, NULL, error))
1493 goto error_free_cmd;
1494 if (format) smlSafeCFree(&format);
1495 } else {
1496 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
1497 goto error_free_cmd;
1498 }
1499 }
1500
1501 if (!(*cmd)->private.access.item) {
1502 smlErrorSet(error, SML_ERROR_GENERIC, "Put/Get is missing item");
1503 goto error_free_cmd;
1504 }
1505
1506 /* We only use the content type of the put command if the item itself did not have
1507 * a content type set */
1508 if (!(*cmd)->private.access.item->contenttype && contenttype)
1509 (*cmd)->private.access.item->contenttype = g_strdup(contenttype);
1510
1511 if (contenttype)
1512 smlSafeCFree(&contenttype);
1513
1514 /* Step once more */
1515 if (!_smlXmlParserStep(parser)) {
1516 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1517 goto error_free_cmd;
1518 }
1519
1520 smlTrace(TRACE_EXIT, "%s", __func__);
1521 return TRUE;
1522
1523 error_free_cmd:
1524 smlCommandUnref(*cmd);
1525 error:
1526 *cmd = NULL;
1527 if (contenttype)
1528 smlSafeCFree(&contenttype);
1529 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1530 return FALSE;
1531 }
1532
1533 static SmlBool _smlResultsParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error)
1534 {
1535 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
1536 CHECK_ERROR_REF
1537 smlAssert(parser);
1538 smlAssert(cmd);
1539 char *contenttype = NULL;
1540 char *locURI = NULL;
1541
1542 *cmd = smlCommandNew(SML_COMMAND_TYPE_RESULTS, error);
1543 if (!*cmd)
1544 goto error;
1545 (*cmd)->refCount = 1;
1546
1547 (*cmd)->private.results.status = smlTryMalloc0(sizeof(SmlStatus), error);
1548 if (!(*cmd)->private.results.status)
1549 goto error;
1550 (*cmd)->private.results.status->refCount = 1;
1551 (*cmd)->private.results.status->result = (*cmd);
1552 (*cmd)->private.results.status->type = SML_COMMAND_TYPE_RESULTS;
1553
1554 while (1) {
1555 if (!_smlXmlParserStep(parser)) {
1556 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1557 goto error_free_cmd;
1558 }
1559
1560 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RESULTS) && \
1561 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1562 break;
1563 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
1564 smlErrorSet(error, SML_ERROR_GENERIC,
1565 "The element %s is not a start node in Results.",
1566 xmlTextReaderConstName(parser->reader));
1567 goto error_free_cmd;
1568 }
1569
1570
1571 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
1572 if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error))
1573 goto error_free_cmd;
1574 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGREF)) {
1575 if (!_smlXmlParserGetID(parser, &((*cmd)->private.results.status->msgRef), SML_ELEMENT_MSGREF, error))
1576 goto error_free_cmd;
1577 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDREF)) {
1578 if (!_smlXmlParserGetID(parser, &((*cmd)->private.results.status->cmdRef), SML_ELEMENT_CMDREF, error))
1579 goto error_free_cmd;
1580 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) {
1581 if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_SOURCEREF, error))
1582 goto error_free_cmd;
1583
1584 (*cmd)->private.results.status->sourceRef = smlLocationNew(locURI, NULL, error);
1585 smlSafeCFree(&locURI);
1586 if (!(*cmd)->private.results.status->sourceRef)
1587 goto error_free_cmd;
1588 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGETREF)) {
1589 if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_TARGETREF, error))
1590 goto error_free_cmd;
1591
1592 (*cmd)->private.results.status->targetRef = smlLocationNew(locURI, NULL, error);
1593 smlSafeCFree(&locURI);
1594 if (!(*cmd)->private.results.status->targetRef)
1595 goto error_free_cmd;
1596 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
1597 (*cmd)->private.results.status->item = _smlItemParse(parser, (*cmd), (*cmd)->type, error);
1598 if (!(*cmd)->private.results.status->item)
1599 goto error_free_cmd;
1600
1601 (*cmd)->target = (*cmd)->private.results.status->item->target;
1602 (*cmd)->private.results.status->item->target = NULL;
1603 (*cmd)->source = (*cmd)->private.results.status->item->source;
1604 (*cmd)->private.results.status->item->source = NULL;
1605 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
1606 /* ignore format */
1607 char *format = NULL;
1608 if (!_smlCommandMetaParse(parser, &format, &contenttype, NULL, NULL, NULL, error))
1609 goto error_free_cmd;
1610 if (format) smlSafeCFree(&format);
1611 } else {
1612 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
1613 goto error_free_cmd;
1614 }
1615 }
1616
1617 if (!(*cmd)->private.results.status->item) {
1618 smlErrorSet(error, SML_ERROR_GENERIC, "Result is missing item");
1619 goto error_free_cmd;
1620 }
1621
1622 /* We only use the content type of the put command if the item itself did not have
1623 * a content type set */
1624 if (!(*cmd)->private.results.status->item->contenttype) {
1625 if (!contenttype) {
1626 smlErrorSet(error, SML_ERROR_GENERIC, "Result is missing content type");
1627 goto error_free_cmd;
1628 }
1629
1630 (*cmd)->private.results.status->item->contenttype = g_strdup(contenttype);
1631 }
1632
1633 if (contenttype)
1634 smlSafeCFree(&contenttype);
1635
1636 /* Step once more */
1637 if (!_smlXmlParserStep(parser)) {
1638 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1639 goto error_free_cmd;
1640 }
1641
1642 smlTrace(TRACE_EXIT, "%s", __func__);
1643 return TRUE;
1644
1645 error_free_cmd:
1646 smlCommandUnref(*cmd);
1647 error:
1648 *cmd = NULL;
1649 if (contenttype)
1650 smlSafeCFree(&contenttype);
1651 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1652 return FALSE;
1653 }
1654
1655 static SmlBool _smlXmlParserFixBrokenItemData(
1656 const char *data, unsigned int size,
1657 char **fixed_data, unsigned int *fixed_size,
1658 SmlError **error)
1659 {
1660 smlTrace(TRACE_ENTRY, "%s(%p, %d, %p, %p, %p)", __func__, data, size, fixed_data, fixed_size, error);
1661 CHECK_ERROR_REF
1662 smlAssert(data);
1663 smlAssert(size);
1664 smlAssert(fixed_data);
1665 smlAssert(fixed_size);
1666
1667 /* *******************
1668 * fix wrong enconding
1669 * *******************
1670 */
1671
1672 /* This fix was implemented for text/x-vMessage.
1673 * Some mobiles encode SMS always as UTF-16
1674 * even if the XML document is encoded in UTF-8.
1675 * Example: Nokia E71
1676 */
1677
1678 *fixed_size = size;
1679 *fixed_data = smlTryMalloc0(size + 1, error);
1680 if (!*fixed_data)
1681 {
1682 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
1683 return FALSE;
1684 }
1685 memcpy(*fixed_data, data, size);
1686 const char *position = *fixed_data;
1687
1688 while (position + 1 < *fixed_data + *fixed_size)
1689 {
1690 /* check if the next character is a NULL byte */
1691 const char *byte = position + 1;
1692 if (*byte != 0) {
1693 /* the next byte is not NULL */
1694 position++;
1695 continue;
1696 }
1697 smlTrace(TRACE_INTERNAL, "%s: Found NULL byte in XML document at %p.", __func__, position);
1698
1699 /* the next character is a NULL byte
1700 * so let's check how long the UTF-16 string is
1701 */
1702 const char *last_utf16 = position;
1703 while (last_utf16 + 1 < *fixed_data + *fixed_size &&
1704 *((char *)(last_utf16 + 1)) == 0)
1705 {
1706 last_utf16 += 2;
1707 }
1708
1709 /* go to the last NULL byte */
1710 last_utf16--;
1711
1712 /* convert the whole strong to UTF-8 */
1713 smlTrace(TRACE_INTERNAL, "%s: Converting %d bytes ...", __func__, last_utf16 - position + 1);
1714 GError *gerror = NULL;
1715 size_t read_bytes = 0;
1716 size_t written_bytes = 0;
1717 gchar *conv_string = g_convert(
1718 position, (last_utf16 - position + 1),
1719 "UTF-8", "UTF-16",
1720 &read_bytes, &written_bytes,
1721 &gerror);
1722 if (gerror != NULL)
1723 {
1724 smlErrorSet(
1725 error, SML_ERROR_GENERIC,
1726 "Character conversion from UTF-16 to UTF-8 failed. %s",
1727 gerror->message);
1728 g_error_free(gerror);
1729 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
1730 return FALSE;
1731 }
1732 smlTrace(TRACE_INTERNAL, "%s: read %d --> written %d --> %d ::= %s", __func__, read_bytes, written_bytes, strlen(conv_string), conv_string);
1733
1734 /* replace the embedded string */
1735 char *new_data = smlTryMalloc0(*fixed_size - read_bytes + written_bytes + 1, error);
1736 if (!new_data)
1737 {
1738 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
1739 return FALSE;
1740 }
1741 memcpy(new_data, *fixed_data, (size_t) position - (size_t) *fixed_data);
1742 memcpy(new_data + (size_t) position - (size_t) *fixed_data, conv_string, written_bytes);
1743 memcpy(new_data + (size_t) position - (size_t) *fixed_data + written_bytes,
1744 position + read_bytes, *fixed_size - ( (size_t) position - (size_t) *fixed_data ) - read_bytes );
1745
1746 /* fix pointers */
1747 *fixed_size = *fixed_size - read_bytes + written_bytes;
1748 position = new_data + (position - *fixed_data) + written_bytes;
1749 smlSafeCFree(fixed_data);
1750 *fixed_data = new_data;
1751 new_data = NULL;
1752 smlSafeCFree(&conv_string);
1753
1754 smlTrace(TRACE_INTERNAL, "%s: Converted UTF-16 string to UTF-8", __func__);
1755 }
1756 smlTrace(TRACE_INTERNAL, "%s: Correctly encoded: %s", __func__, *fixed_data);
1757
1758 /* *****************
1759 * add missing CDATA
1760 * *****************
1761 */
1762
1763 position = *fixed_data;
1764
1765 while (position + 1 < *fixed_data + *fixed_size)
1766 {
1767 /* find item */
1768 const char *limit_item_start = strstr(position, "<Item>");
1769 if (! limit_item_start)
1770 {
1771 smlTrace(TRACE_EXIT, "%s - no (more) Item found", __func__);
1772 return TRUE;
1773 } else {
1774 smlTrace(TRACE_INTERNAL, "%s - Item found", __func__);
1775 }
1776 const char *limit_item_end = strstr(limit_item_start, "</Item>");
1777 if (! limit_item_end)
1778 {
1779 g_warning("%s - no end of Item found.", __func__);
1780 smlTrace(TRACE_EXIT, "%s - no end of Item found", __func__);
1781 return TRUE;
1782 } else {
1783 smlTrace(TRACE_INTERNAL, "%s - end of Item found", __func__);
1784 }
1785 if (limit_item_start >= limit_item_end)
1786 {
1787 /* </Item> is before <Item> ?! */
1788 position = limit_item_end + strlen("</Item>");
1789 continue;
1790 }
1791
1792 /* find data */
1793 const char *limit_data_start = strstr(limit_item_start, "<Data>");
1794 if (! limit_data_start)
1795 {
1796 smlTrace(TRACE_EXIT, "%s - no Data found", __func__);
1797 return TRUE;
1798 } else {
1799 smlTrace(TRACE_INTERNAL, "%s - Data found", __func__);
1800 }
1801 const char *limit_data_end = strstr(limit_data_start, "</Data>");
1802 if (! limit_data_end)
1803 {
1804 g_warning("%s - no end of Data found.", __func__);
1805 smlTrace(TRACE_EXIT, "%s - no end of Data found", __func__);
1806 return TRUE;
1807 } else {
1808 smlTrace(TRACE_INTERNAL, "%s - end of Data found", __func__);
1809 }
1810 if (limit_data_start >= limit_data_end)
1811 {
1812 /* </Data> is before <Data> ?! */
1813 position = limit_data_end + strlen("</Data>");
1814 continue;
1815 }
1816
1817 /* check limits */
1818 if (limit_item_start >= limit_data_start ||
1819 limit_data_start >= limit_data_end ||
1820 limit_data_end >= limit_item_end)
1821 {
1822 /* There is something wrong with the encapsulation.
1823 * Expected: <Item>...<Data>...</Data>...</Item>
1824 */
1825 position = limit_item_end + strlen("</Item>");
1826 continue;
1827 }
1828
1829 /* check for CDATA */
1830 const char *cdata_start = strstr(limit_data_start, "<![CDATA[");
1831 const char *cdata_end = NULL;
1832 if (cdata_start)
1833 cdata_end = strstr(cdata_start, "]]");
1834 if (cdata_start && cdata_end &&
1835 limit_data_start < cdata_start &&
1836 cdata_start < cdata_end &&
1837 cdata_end < limit_data_end)
1838 {
1839 /* Anything is fine. */
1840 position = limit_item_end + strlen("</Item>");
1841 continue;
1842 }
1843
1844 /* check that there is no tag inside Data */
1845 if (g_strstr_len(
1846 limit_data_start + strlen("<Data>"),
1847 limit_data_end - limit_data_start - strlen("<Data>"),
1848 "<"))
1849 {
1850 /* There is a tag in the Data area. */
1851 position = limit_item_end + strlen("</Item>");
1852 continue;
1853 }
1854
1855 /* There is data in an item element and it is not CDATA.
1856 * - allocate new memory
1857 * - copy before data
1858 * - add <![CDATA[
1859 * - copy data
1860 * - add ]]
1861 * - copy after data
1862 * - fix position
1863 * - cleanup
1864 */
1865
1866 smlTrace(TRACE_INTERNAL, "%s: There is data which is not CDATA.", __func__);
1867 /* 1 is added to the real length * because of the
1868 * trailing NULL byte. This NULL byte is required
1869 * because XML documents can be represented as strings
1870 * and a string must be terminated by a NULL byte.
1871 */
1872 char *new_data = smlTryMalloc0(*fixed_size + strlen("<![CDATA[]]>") + 1, error);
1873 if (!new_data)
1874 {
1875 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
1876 return FALSE;
1877 }
1878 size_t before_size = limit_data_start + strlen("<Data>") - *fixed_data;
1879 size_t data_size = limit_data_end - limit_data_start - strlen("<Data>");
1880 size_t after_size = *fixed_size - before_size - data_size;
1881
1882 smlTrace(TRACE_INTERNAL, "%s: %i = %i + %i +%i", __func__,
1883 *fixed_size, before_size, data_size, after_size);
1884
1885 memcpy(new_data, *fixed_data, before_size);
1886 memcpy(new_data + before_size, "<![CDATA[", strlen ("<![CDATA["));
1887 memcpy(new_data + before_size + strlen ("<![CDATA["),
1888 limit_data_start + strlen("<Data>"),
1889 data_size);
1890 memcpy(new_data + before_size + strlen ("<![CDATA[") + data_size,
1891 "]]>", strlen("]]>"));
1892 memcpy(new_data + before_size + strlen ("<![CDATA[]]>") + data_size,
1893 limit_data_end,
1894 after_size);
1895 smlSafeCFree(fixed_data);
1896 *fixed_data = new_data;
1897 new_data = NULL;
1898 *fixed_size += strlen("<![CDATA[]]>");
1899 /* The position must be calculated on base of the new string. */
1900 position = *fixed_data +
1901 before_size + strlen ("<![CDATA[]]>") +
1902 data_size + strlen("</Data></Item>");
1903 smlTrace(TRACE_INTERNAL, "%s: CDATA inserted", __func__);
1904 }
1905
1906 smlTrace(TRACE_EXIT, "%s", __func__);
1907 return TRUE;
1908 }
1909
1915 SmlBool smlXmlParserStart(SmlXmlParser *parser, const char *data, unsigned int size, SmlError **error)
1916 {
1917 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, data, size, error);
1918 CHECK_ERROR_REF
1919 smlAssert(parser);
1920 smlAssert(data);
1921 smlAssert(size);
1922
1923 /* Repair item data if necessary.
1924 * Some devices does not encapsulate the data correctly
1925 * (e.g. SE M600i send the second part of a chunked item
1926 * without CDATA and so the CR LF is normalied to a LF
1927 * which creates a wrong length and so the item is detected
1928 * as damaged).
1929 */
1930 parser->data = NULL;
1931 parser->size = 0;
1932 if (! _smlXmlParserFixBrokenItemData(
1933 data, size, &(parser->data), &(parser->size), error))
1934 {
1935 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
1936 return FALSE;
1937 }
1938
1939 char *debugstr = smlPrintBinary(parser->data, parser->size);
1940 smlTrace(TRACE_INTERNAL, "Xml input: %s", debugstr);
1941 smlLog("received-%i.xml", parser->data, parser->size);
1942 smlSafeCFree(&debugstr);
1943
1944 parser->got_command = FALSE;
1945
1946 /* Create the new parser */
1947 parser->reader = xmlReaderForMemory(parser->data, parser->size, "/", NULL, XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
1948 if (!parser->reader) {
1949 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new reader");
1950 goto error;
1951 }
1952 xmlSubstituteEntitiesDefault(1);
1953
1954 /* Check the First Node (SyncML)*/
1955 if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCML, error))
1956 goto error_free_reader;
1957
1958 /* Check the Second Node (SyncHdr)*/
1959 if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCHDR, error))
1960 goto error_free_reader;
1961
1962 smlTrace(TRACE_EXIT, "%s", __func__);
1963 return TRUE;
1964
1965 error_free_reader:
1966 xmlFreeTextReader(parser->reader);
1967 error:
1968 parser->reader = NULL;
1969 if (parser->data)
1970 smlSafeCFree(&(parser->data));
1971 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
1972 return FALSE;
1973 }
1974
1975 SmlBool smlXmlParserEnd(SmlXmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error)
1976 {
1977 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, final, end, error);
1978 CHECK_ERROR_REF
1979 smlAssert(parser);
1980 SmlBool got_final = FALSE;
1981
1982 /* Check for final */
1983 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL)) {
1984 got_final = TRUE;
1985 if (!_smlXmlParserStep(parser)) {
1986 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1987 goto error;
1988 }
1989
1990 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && \
1991 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
1992 if (!_smlXmlParserStep(parser)) {
1993 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
1994 goto error;
1995 }
1996 }
1997 }
1998
1999 if (final)
2000 *final = got_final;
2001
2002 /* Check for the end. We can only decide if this was the last message if this
2003 * was the final message */
2004 if (end) {
2005 if (got_final)
2006 *end = parser->got_command ? FALSE : TRUE;
2007 else
2008 *end = FALSE;
2009 }
2010
2011 /* Check the closing SyncBody - which is perhaps only an empty element. */
2012 if (strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) ||
2013 (!xmlTextReaderIsEmptyElement(parser->reader) &&
2014 xmlTextReaderNodeType(parser->reader) != XML_NODE_CLOSE
2015 )
2016 ) {
2017 smlErrorSet(error, SML_ERROR_GENERIC, "Wrong closing syncbody node");
2018 goto error;
2019 }
2020
2021 /* Check the next node (SyncML)*/
2022 if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_SYNCML, error))
2023 goto error;
2024
2025 xmlFreeTextReader(parser->reader);
2026 parser->reader = NULL;
2027 parser->size = 0;
2028 smlSafeCFree(&(parser->data));
2029
2030 smlTrace(TRACE_EXIT, "%s", __func__);
2031 return TRUE;
2032
2033 error:
2034 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2035 return FALSE;
2036 }
2037
2038 void smlXmlParserFree(SmlXmlParser *parser)
2039 {
2040 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, parser);
2041 smlAssert(parser);
2042
2043 if (parser->reader) {
2044 xmlFreeTextReader(parser->reader);
2045 }
2046 if (parser->data)
2047 smlSafeCFree(&(parser->data));
2048
2049 smlSafeFree((gpointer *)&parser);
2050
2051 smlTrace(TRACE_EXIT, "%s", __func__);
2052 }
2053
2054 SmlBool smlXmlParserGetHeader(SmlXmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error)
2055 {
2056 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, header, cred, error);
2057 CHECK_ERROR_REF
2058 smlAssert(parser);
2059 smlAssert(header);
2060 smlAssert(cred);
2061
2062 if (!xmlTextReaderConstName(parser->reader) || strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCHDR) || \
2063 xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2064 /* It is important to notice that empty headers are not allowed. */
2065 smlErrorSet(error, SML_ERROR_GENERIC, "Wrong starting node for a header");
2066 goto error;
2067 }
2068
2069 parser->version = SML_VERSION_UNKNOWN;
2070
2071 *header = smlTryMalloc0(sizeof(SmlHeader), error);
2072 if (!*header)
2073 goto error;
2074
2075 while (1) {
2076 if (!_smlXmlParserStep(parser)) {
2077 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2078 goto error_free_header;
2079 }
2080
2081 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCHDR) && \
2082 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2083 break;
2084 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2085 smlErrorSet(error, SML_ERROR_GENERIC,
2086 "The element %s is not a start node in SyncHdr.",
2087 xmlTextReaderConstName(parser->reader));
2088 goto error_free_header;
2089 }
2090
2091 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERDTD)) {
2092 if (!_smlSyncHeaderParseDTD(&((*header)->version), parser, error))
2093 goto error_free_header;
2094 parser->version = (*header)->version;
2095 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERPROTO)) {
2096 if (!_smlSyncHeaderParseProto(&((*header)->protocol), parser, error))
2097 goto error_free_header;
2098 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SESSIONID)) {
2099 if (!_smlXmlParserGetString(parser, &((*header)->sessionID), SML_ELEMENT_SESSIONID, error))
2100 goto error_free_header;
2101 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGID)) {
2102 if (!_smlXmlParserGetID(parser, &((*header)->messageID), SML_ELEMENT_MSGID, error))
2103 goto error_free_header;
2104 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) {
2105 if (!_smlLocationParse(&((*header)->target), parser, error))
2106 goto error_free_header;
2107 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) {
2108 if (!_smlLocationParse(&((*header)->source), parser, error))
2109 goto error_free_header;
2110 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RESPURI)) {
2111 /* Only one RespURI is allowed.
2112 * If the header is not correct (more than one RespURI)
2113 * then the last RespURI is taken.
2114 */
2115 if ((*header)->responseURI) {
2116 smlTrace(TRACE_ERROR, "%s: There is more than on RespURI.", __func__);
2117 smlSafeCFree(&((*header)->responseURI));
2118 }
2119 if (!_smlXmlParserGetString(parser, &((*header)->responseURI), SML_ELEMENT_RESPURI, error))
2120 goto error_free_header;
2121 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NORESP)) {
2122 /* This is an empty element. So the parser must not move one step forward. */
2123 (*header)->noResponse = TRUE;
2124 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) {
2125 if (!_smlMessageParseSynchdrMeta(parser, &((*header)->maxmsgsize), &((*header)->maxobjsize), &((*header)->emi), error))
2126 goto error_free_header;
2127 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CRED)) {
2128 *cred = _smlCredParse(parser, error);
2129 if (!(*cred))
2130 goto error_free_header;
2131 }
2132
2133 else {
2134 smlErrorSet(error, SML_ERROR_GENERIC, "Element %s not supported for SyncHdr.",
2135 (char *)xmlTextReaderConstName(parser->reader));
2136 goto error_free_header;
2137 }
2138 }
2139
2140 if (!(*header)->protocol) {
2141 smlErrorSet(error, SML_ERROR_GENERIC, "No protocol set");
2142 goto error_free_header;
2143 }
2144
2145 if (!(*header)->version) {
2146 smlErrorSet(error, SML_ERROR_GENERIC, "No dtd version set");
2147 goto error_free_header;
2148 }
2149
2150 if (!(*header)->sessionID) {
2151 smlErrorSet(error, SML_ERROR_GENERIC, "No sessionID set");
2152 goto error_free_header;
2153 }
2154
2155 if (!(*header)->target) {
2156 smlErrorSet(error, SML_ERROR_GENERIC, "No target set");
2157 goto error_free_header;
2158 }
2159
2160 if (!(*header)->source) {
2161 smlErrorSet(error, SML_ERROR_GENERIC, "No source set");
2162 goto error_free_header;
2163 }
2164
2165 if (!(*header)->messageID) {
2166 smlErrorSet(error, SML_ERROR_GENERIC, "No msgid set");
2167 goto error_free_header;
2168 }
2169
2170 /* Check the Next Node (SyncBody)*/
2171 if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCBODY, error))
2172 goto error_free_header;
2173
2174 /* Step once more if it is not an empty element. */
2175 if (!xmlTextReaderIsEmptyElement(parser->reader) && !_smlXmlParserStep(parser)) {
2176 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2177 goto error_free_header;
2178 }
2179
2180 smlTrace(TRACE_EXIT, "%s", __func__);
2181 return TRUE;
2182
2183 error_free_header:
2184 smlHeaderFree(*header);
2185 *header = NULL;
2186
2187 if (*cred)
2188 smlCredUnref(*cred);
2189 error:
2190 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2191 return FALSE;
2192 }
2193
2194 SmlBool smlXmlParserGetStatus(SmlXmlParser *parser, SmlStatus **status, SmlError **error)
2195 {
2196 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, status, error);
2197 CHECK_ERROR_REF
2198 smlAssert(parser);
2199 smlAssert(status);
2200
2201 char *locURI = NULL;
2202 SmlItem *item = NULL;
2203
2204 /* Lets check if the next node is a command node */
2205 if (smlCommandTypeFromString((char *)xmlTextReaderConstName(parser->reader), error) != SML_COMMAND_TYPE_UNKNOWN && xmlTextReaderNodeType(parser->reader) == XML_NODE_START) {
2206 *status = NULL;
2207 smlTrace(TRACE_EXIT, "%s: Next is command", __func__);
2208 return TRUE;
2209 } else {
2210 smlErrorDeref(error);
2211 }
2212
2213 /* Lets check if the next node is a final node */
2214 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_START || xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE)) {
2215 *status = NULL;
2216 smlTrace(TRACE_EXIT, "%s: Next is final", __func__);
2217 return TRUE;
2218 }
2219
2220 /* Let's check if the next node is a closing or empty syncbody node. */
2221 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) &&
2222 (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE ||
2223 xmlTextReaderIsEmptyElement(parser->reader)
2224 )
2225 ) {
2226 *status = NULL;
2227 smlTrace(TRACE_EXIT, "%s: Next is closing syncbody", __func__);
2228 return TRUE;
2229 }
2230
2231 if (strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS)) {
2232 smlErrorSet(error, SML_ERROR_GENERIC, "Unexpected element <%s>.",
2233 (char *)xmlTextReaderConstName(parser->reader));
2234 goto error;
2235 }
2236
2237 if (xmlTextReaderIsEmptyElement(parser->reader))
2238 {
2239 /* An empty status element is not allowed.
2240 * Try to finish in a way that the parser can still be used.
2241 * The parser can ignore this mistake and finish correctly.
2242 * Nevertheless a second mistake which crashs the NextStep
2243 * function cannot be handled.
2244 */
2245 _smlXmlParserStep(parser);
2246 smlErrorSet(error, SML_ERROR_GENERIC, "Empty status element");
2247 goto error;
2248 }
2249
2250 if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2251 smlErrorSet(error, SML_ERROR_GENERIC,
2252 "The element %s is not the start node of Status.",
2253 xmlTextReaderConstName(parser->reader));
2254 goto error;
2255 }
2256
2257 *status = smlStatusNew(SML_ERROR_UNKNOWN, 0, 0, NULL, NULL, SML_COMMAND_TYPE_UNKNOWN, error);
2258 if (!*status)
2259 goto error;
2260
2261 while (1) {
2262 if (!_smlXmlParserStep(parser)) {
2263 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2264 goto error_free_status;
2265 }
2266
2267 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS) && \
2268 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2269 break;
2270 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2271 smlErrorSet(error, SML_ERROR_GENERIC,
2272 "The element %s is not a start node in Status.",
2273 xmlTextReaderConstName(parser->reader));
2274 goto error_free_status;
2275 }
2276
2277 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) {
2278 //Errr... who cares?
2279 if (!_smlXmlParserExpectNode(parser, XML_NODE_TEXT, FALSE, NULL, error))
2280 goto error_free_status;
2281 if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_CMDID, error))
2282 goto error_free_status;
2283 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGREF)) {
2284 /* MsgRef is defined as parsed character data:
2285 OMA-SUP-DTD_SyncML_RepPro-V1_2-20070221-A.txt:<!ELEMENT MsgRef (#PCDATA)>
2286
2287 SyncML Reprent Version 1.1 20020215 - Chapter 5.1.13 MsgRef:
2288 "[...] reference to a SyncML session-uniquie identifier referenced by SyncML result or response status."
2289
2290 So it could be something else then an unsigned integer.
2291 */
2292 if (!_smlXmlParserGetID(parser, &((*status)->msgRef), SML_ELEMENT_MSGREF, error))
2293 goto error_free_status;
2294 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDREF)) {
2295 if (!_smlXmlParserGetID(parser, &((*status)->cmdRef), SML_ELEMENT_CMDREF, error))
2296 goto error_free_status;
2297 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMD)) {
2298 char *cmdname = NULL;
2299 if (!_smlXmlParserGetString(parser, &cmdname, SML_ELEMENT_CMD, error))
2300 goto error_free_status;
2301 (*status)->type = smlCommandTypeFromString(cmdname, error);
2302 smlSafeCFree(&cmdname);
2303 if ((*status)->type == SML_COMMAND_TYPE_UNKNOWN)
2304 goto error_free_status;
2305 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) {
2306 if (!_smlXmlParserGetString(parser, &((*status)->data), SML_ELEMENT_DATA, error))
2307 goto error_free_status;
2308 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) {
2309 if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_SOURCEREF, error))
2310 goto error_free_status;
2311
2312 (*status)->sourceRef = smlLocationNew(locURI, NULL, error);
2313 smlSafeCFree(&locURI);
2314 if (!(*status)->sourceRef)
2315 goto error_free_status;
2316 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGETREF)) {
2317 if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_TARGETREF, error))
2318 goto error_free_status;
2319
2320 (*status)->targetRef = smlLocationNew(locURI, NULL, error);
2321 smlSafeCFree(&locURI);
2322 if (!(*status)->targetRef)
2323 goto error_free_status;
2324 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) {
2325 /* Do not send SML_COMMAND_TYPE_ALERT
2326 * because this can give trouble.
2327 * Example: Error message for a failed ADD
2328 */
2329 item = _smlItemParse(parser, NULL, (*status)->type, error);
2330 if (!item)
2331 goto error_free_status;
2332 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CHAL)) {
2333 (*status)->chal = _smlChalParse(parser, error);
2334 if (!(*status)->chal)
2335 goto error_free_status;
2336 } else {
2337 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
2338 goto error;
2339 }
2340 }
2341
2342 /* Step once more */
2343 if (!_smlXmlParserStep(parser)) {
2344 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2345 goto error_free_status;
2346 }
2347
2348 if (item)
2349 {
2350 if ((*status)->type == SML_COMMAND_TYPE_ALERT) {
2351 (*status)->anchor = item->anchor;
2352 item->anchor = NULL;
2353 } else if ((*status)->type == SML_COMMAND_TYPE_ADD ||
2354 (*status)->type == SML_COMMAND_TYPE_REPLACE ||
2355 (*status)->type == SML_COMMAND_TYPE_DELETE) {
2356 /* Usually Sync is commited at once or together with an anchor.
2357 * If a single ADD, REPLACE or DELETE gets an item
2358 * then there is something going wrong.
2359 */
2360 g_warning("Received explicit status for add, delete or replace (%s).", xmlBufferContent(item->buffer));
2361 } else {
2362 smlErrorSet(error, SML_ERROR_GENERIC, "Got wrong item");
2363 smlItemUnref(item);
2364 goto error_free_status;
2365 }
2366 smlItemUnref(item);
2367 }
2368
2369 /* MsgRef is defined as #PCDATA - so it doesn't have to be a
2370 unsigned integer AND it could be set to 0/zero as well.
2371
2372 This sanity check breaks if MsgRef is set to 0/zero.
2373
2374 if (!(*status)->msgRef) {
2375 smlErrorSet(error, SML_ERROR_GENERIC, "No msgref set");
2376 goto error_free_status;
2377 }
2378 */
2379
2380 if ((*status)->type == SML_COMMAND_TYPE_UNKNOWN) {
2381 smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set");
2382 goto error_free_status;
2383 }
2384
2385 smlTrace(TRACE_INTERNAL, "Got status %p with: cmdRef %i, msgRef %i, type %i, data %s", *status, (*status)->cmdRef, (*status)->msgRef, (*status)->type, VA_STRING((*status)->data));
2386
2387 smlTrace(TRACE_EXIT, "%s", __func__);
2388 return TRUE;
2389
2390 error_free_status:
2391 smlStatusUnref(*status);
2392 error:
2393 *status = NULL;
2394 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2395 return FALSE;
2396 }
2397
2398 SmlParserResult smlXmlParserGetCommand(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error)
2399 {
2400 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
2401 CHECK_ERROR_REF
2402 smlAssert(parser);
2403 smlAssert(cmd);
2404 *cmd = NULL;
2405
2406 /* Lets check if the next node is a final node */
2407 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_START || xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE)) {
2408 *cmd = NULL;
2409 smlTrace(TRACE_EXIT, "%s: Next is final", __func__);
2410 return SML_PARSER_RESULT_OTHER;
2411 }
2412
2413 /* Let's check if the next node is a closing or empty syncbody node. */
2414 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) &&
2415 (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE ||
2416 xmlTextReaderIsEmptyElement(parser->reader)
2417 )
2418 ) {
2419 *cmd = NULL;
2420 smlTrace(TRACE_EXIT, "%s: Next is closing syncbody", __func__);
2421 return SML_PARSER_RESULT_OTHER;
2422 }
2423
2424 /* Lets check if the next node status node */
2425 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS) && xmlTextReaderNodeType(parser->reader) == XML_NODE_START) {
2426 *cmd = NULL;
2427 smlTrace(TRACE_EXIT, "%s: Next is status", __func__);
2428 return SML_PARSER_RESULT_STATUS;
2429 }
2430
2431 SmlCommandType type = smlCommandTypeFromString((char *)xmlTextReaderConstName(parser->reader), error);
2432 if (!type)
2433 goto error;
2434
2435 SmlParserResult result = SML_PARSER_RESULT_NORMAL;
2436
2437 switch (type) {
2438 case SML_COMMAND_TYPE_ALERT:
2439 if (!_smlAlertParse(parser, cmd, error))
2440 goto error;
2441 break;
2442 case SML_COMMAND_TYPE_PUT:
2443 case SML_COMMAND_TYPE_GET:
2444 if (!_smlCommandAccessParse(parser, cmd, type, error))
2445 goto error;
2446 break;
2447 case SML_COMMAND_TYPE_SYNC:
2448 if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2449 if (!_smlXmlParserStep(parser)) {
2450 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2451 goto error_free_cmd;
2452 }
2453
2454 smlTrace(TRACE_EXIT, "%s: SML_PARSER_RESULT_CLOSE", __func__);
2455 return SML_PARSER_RESULT_CLOSE;
2456 } else {
2457 if (!_smlCommandSyncParse(parser, cmd, error))
2458 goto error;
2459
2460 result = SML_PARSER_RESULT_OPEN;
2461 }
2462 break;
2463 case SML_COMMAND_TYPE_MAP:
2464 if (!_smlCommandMapParse(parser, cmd, error))
2465 goto error;
2466 break;
2467 case SML_COMMAND_TYPE_ADD:
2468 if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_ADD, SML_ELEMENT_ADD, error))
2469 goto error;
2470 break;
2471 case SML_COMMAND_TYPE_REPLACE:
2472 if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_REPLACE, SML_ELEMENT_REPLACE, error))
2473 goto error;
2474 break;
2475 case SML_COMMAND_TYPE_DELETE:
2476 if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_DELETE, SML_ELEMENT_DELETE, error))
2477 goto error;
2478 break;
2479 case SML_COMMAND_TYPE_RESULTS:
2480 if (!_smlResultsParse(parser, cmd, error))
2481 goto error;
2482 break;
2483 default:
2484 smlErrorSet(error, SML_ERROR_GENERIC, "Unsupported command type");
2485 goto error;
2486 }
2487
2488 if (!(*cmd)->cmdID) {
2489 smlErrorSet(error, SML_ERROR_GENERIC, "No cmdid set");
2490 goto error_free_cmd;
2491 }
2492
2493 parser->got_command = TRUE;
2494
2495 smlTrace(TRACE_EXIT, "%s: %i", __func__, result);
2496 return result;
2497
2498 error_free_cmd:
2499 if (*cmd)
2500 smlCommandUnref(*cmd);
2501 error:
2502 *cmd = NULL;
2503 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2504 return SML_PARSER_RESULT_ERROR;
2505 }
2506
2507 SmlXmlParser *smlXmlParserNew(SmlParserFunctions *functions, SmlError **error)
2508 {
2509 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, functions,error);
2510 CHECK_ERROR_REF
2511 smlAssert(functions);
2512
2513 SmlXmlParser *parser = smlTryMalloc0(sizeof(SmlXmlParser), error);
2514 if (!parser)
2515 goto error;
2516
2517 functions->start = (SmlParserStartFunction)smlXmlParserStart;
2518 functions->free = (SmlParserFreeFunction)smlXmlParserFree;
2519 functions->end = (SmlParserEndFunction)smlXmlParserEnd;
2520 functions->get_header = (SmlParserHeaderFunction)smlXmlParserGetHeader;
2521 functions->get_cmd = (SmlParserCommandFunction)smlXmlParserGetCommand;
2522 functions->get_status = (SmlParserStatusFunction)smlXmlParserGetStatus;
2523
2524 smlTrace(TRACE_EXIT, "%s: %p", __func__, parser);
2525 return parser;
2526
2527 error:
2528 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2529 return NULL;
2530 }
2531
2532 static SmlBool _smlXmlDevInfDataStoreParseDSMem(SmlXmlParser *parser, SmlDevInfDataStore *datastore, SmlError **error)
2533 {
2534 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, datastore, error);
2535 CHECK_ERROR_REF
2536 smlAssert(parser);
2537 smlAssert(datastore);
2538
2539 if (xmlTextReaderIsEmptyElement(parser->reader)) {
2540 /* An empty DSMem element is allowed according to SyncML DevInf 1.1.2. */
2541 smlTrace(TRACE_EXIT, "%s - empty DSMem", __func__);
2542 return TRUE;
2543 }
2544
2545 while (1) {
2546 if (!_smlXmlParserStep(parser)) {
2547 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2548 goto error;
2549 }
2550
2551 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DSMEM) && \
2552 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2553 break;
2554 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2555 smlErrorSet(error, SML_ERROR_GENERIC,
2556 "The element %s is not a start node in DSMem.",
2557 xmlTextReaderConstName(parser->reader));
2558 goto error;
2559 }
2560
2561 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXID)) {
2562 if (!_smlXmlParserGetID(parser, &(datastore->maxid), SML_ELEMENT_MAXID, error))
2563 goto error;
2564 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SHAREDMEM)) {
2565 datastore->sharedMem = TRUE;
2566 if (!_smlXmlParserStep(parser)) {
2567 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2568 goto error;
2569 }
2570
2571 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SHAREDMEM) && \
2572 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2573 if (!_smlXmlParserStep(parser)) {
2574 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2");
2575 goto error;
2576 }
2577 }
2578 continue;
2579 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXMEM)) {
2580 if (!_smlXmlParserGetID(parser, &(datastore->maxmem), SML_ELEMENT_MAXMEM, error))
2581 goto error;
2582 } else {
2583 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
2584 goto error;
2585 }
2586 }
2587
2588 smlTrace(TRACE_EXIT, "%s", __func__);
2589 return TRUE;
2590
2591 error:
2592 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2593 return FALSE;
2594 }
2595
2596 static SmlBool _smlXmlDevInfDataStoreParseSyncCap(SmlXmlParser *parser, SmlDevInfDataStore *datastore, SmlError **error)
2597 {
2598 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, datastore, error);
2599 CHECK_ERROR_REF
2600 smlAssert(parser);
2601 smlAssert(datastore);
2602
2603 while (1) {
2604 if (!_smlXmlParserStep(parser)) {
2605 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2606 goto error;
2607 }
2608
2609 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCCAP) && \
2610 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2611 break;
2612 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
2613 smlErrorSet(error, SML_ERROR_GENERIC,
2614 "The element %s is not a start node in SyncCap.",
2615 xmlTextReaderConstName(parser->reader));
2616 goto error;
2617 }
2618
2619 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCTYPE)) {
2620 unsigned int id = 0;
2621 if (!_smlXmlParserGetID(parser, &id, SML_ELEMENT_SYNCTYPE, error))
2622 goto error;
2623 id = 1 << (id - 1);
2624 SmlDevInfSyncCap synccap = smlDevInfSyncCapConvert(id, error);
2625 if (synccap == SML_DEVINF_SYNCTYPE_UNKNOWN &&
2626 error != NULL)
2627 goto error;
2628
2629 if (synccap != SML_DEVINF_SYNCTYPE_UNKNOWN)
2630 smlDevInfDataStoreSetSyncCap(datastore, synccap, TRUE);
2631 } else {
2632 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
2633 goto error;
2634 }
2635 }
2636
2637 smlTrace(TRACE_EXIT, "%s", __func__);
2638 return TRUE;
2639
2640 error:
2641 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2642 return FALSE;
2643 }
2644
2645 static SmlBool _smlXmlDevInfDataStoreParseCTCap11(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error)
2646 {
2647 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error);
2648 CHECK_ERROR_REF
2649 smlAssert(parser);
2650 smlAssert(devinf);
2651
2652 /* This function was designed to parse one CTCap section */
2653 /* which can include several CTCap definitions */
2654
2655 if (!_smlXmlParserStep(parser)) {
2656 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2657 goto error;
2658 }
2659
2660 SmlDevInfCTCap *ctcap = NULL;
2661 SmlDevInfProperty *property = NULL;
2662 SmlDevInfPropParam *param = NULL;
2663 char *value = NULL;
2664 while (1) {
2665
2666 const char *elem_name;
2667 elem_name = (const char*)xmlTextReaderConstName(parser->reader);
2668
2669 smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name);
2670 if (!strcmp(elem_name, SML_ELEMENT_CTCAP) &&
2671 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2672 // this is the end of the CTCap section
2673 break;
2674 }
2675
2676 if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START)
2677 {
2678 smlErrorSet(error, SML_ERROR_GENERIC,
2679 "The element %s is not a start node in CTCap.",
2680 xmlTextReaderConstName(parser->reader));
2681 goto error;
2682 }
2683
2684 /* determine list item type */
2685 SmlDevInfCTCapType type;
2686 type = smlDevInfCTCapTypeFromString(elem_name, error);
2687 value = NULL;
2688 if (type != SML_DEVINF_CTCAP_UNKNOWN)
2689 {
2690 _smlXmlParserGetString(parser, &value, elem_name, error);
2691 }
2692
2693 /* now react on the different items */
2694 switch(type)
2695 {
2696 case SML_DEVINF_CTCAP_CTTYPE:
2697 // CTType => new ctcap definition
2698 if (ctcap != NULL)
2699 {
2700 if (property != NULL)
2701 {
2702 if (param != NULL)
2703 {
2704 smlDevInfPropertyAddPropParam(property, param);
2705 param = NULL;
2706 }
2707 smlDevInfCTCapAddProperty(ctcap, property);
2708 property = NULL;
2709 }
2710 smlDevInfAppendCTCap(devinf, ctcap);
2711 ctcap = NULL;
2712 }
2713 ctcap = smlDevInfNewCTCap(error);
2714 if (!ctcap)
2715 goto error;
2716 smlDevInfCTCapSetCTType(ctcap, value);
2717 break;
2718 case SML_DEVINF_CTCAP_VERCT:
2719 if (ctcap == NULL)
2720 goto error;
2721 smlDevInfCTCapSetVerCT(ctcap, value);
2722 break;
2723 case SML_DEVINF_CTCAP_PROPNAME:
2724 // PropName => new property
2725 if (ctcap == NULL)
2726 goto error;
2727 if (property != NULL)
2728 {
2729 if (param != NULL)
2730 {
2731 smlDevInfPropertyAddPropParam(property, param);
2732 param = NULL;
2733 }
2734 smlDevInfCTCapAddProperty(ctcap, property);
2735 property = NULL;
2736 }
2737 property = smlDevInfNewProperty(error);
2738 if (!property)
2739 goto error;
2740 smlDevInfPropertySetPropName(property, value);
2741 break;
2742 case SML_DEVINF_CTCAP_DATATYPE:
2743 if (property == NULL)
2744 goto error;
2745 if (param != NULL)
2746 smlDevInfPropParamSetDataType(param, value);
2747 else
2748 smlDevInfPropertySetDataType(property, value);
2749 break;
2750 case SML_DEVINF_CTCAP_MAXOCCUR:
2751 if (property == NULL)
2752 goto error;
2753 smlDevInfPropertySetMaxOccur(property, atoi(value));
2754 break;
2755 case SML_DEVINF_CTCAP_MAXSIZE:
2756 if (property == NULL)
2757 goto error;
2758 smlDevInfPropertySetMaxSize(property, atoi(value));
2759 break;
2760 case SML_DEVINF_CTCAP_NOTRUNCATE:
2761 if (property == NULL)
2762 goto error;
2763 smlDevInfPropertySetNoTruncate(property);
2764 break;
2765 case SML_DEVINF_CTCAP_DISPLAYNAME:
2766 if (property == NULL)
2767 goto error;
2768 if (param != NULL)
2769 smlDevInfPropParamSetDisplayName(param, value);
2770 else
2771 smlDevInfPropertySetDisplayName(property, value);
2772 break;
2773 case SML_DEVINF_CTCAP_VALENUM:
2774 if (property == NULL)
2775 goto error;
2776 if (param != NULL)
2777 smlDevInfPropParamAddValEnum(param, value);
2778 else
2779 smlDevInfPropertyAddValEnum(property, value);
2780 break;
2781 case SML_DEVINF_CTCAP_PARAMNAME:
2782 if (property == NULL)
2783 goto error;
2784 if (param != NULL)
2785 {
2786 smlDevInfPropertyAddPropParam(property, param);
2787 param = NULL;
2788 }
2789 param = smlDevInfNewPropParam(error);
2790 if (!param)
2791 goto error;
2792 smlDevInfPropParamSetParamName(param, value);
2793 break;
2794 case SML_DEVINF_CTCAP_SIZE:
2795 smlDevInfPropertySetPropSize(property, atoi(value));
2796 break;
2797 default:
2798 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType: %s", elem_name);
2799 goto error;
2800 }
2801 smlSafeCFree(&value);
2802
2803 if (!_smlXmlParserStep(parser)) {
2804 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2805 goto error;
2806 }
2807 }
2808 if (param != NULL)
2809 smlDevInfPropertyAddPropParam(property, param);
2810 if (property != NULL)
2811 smlDevInfCTCapAddProperty(ctcap, property);
2812 if (ctcap != NULL)
2813 smlDevInfAppendCTCap(devinf, ctcap);
2814
2815 smlTrace(TRACE_EXIT, "%s", __func__);
2816 return TRUE;
2817
2818 error:
2819 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2820 if (value != NULL)
2821 smlSafeCFree(&value);
2822 return FALSE;
2823 }
2824
2825 static SmlDevInfPropParam *_smlXmlDevInfDataStoreParseCTCap12PropParam(SmlXmlParser *parser, SmlError **error)
2826 {
2827 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, error);
2828 CHECK_ERROR_REF
2829 smlAssert(parser);
2830
2831 if (!_smlXmlParserStep(parser)) {
2832 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2833 goto error;
2834 }
2835
2836 SmlDevInfPropParam *param = smlDevInfNewPropParam(error);
2837 if (!param)
2838 goto error;
2839
2840 char *value = NULL;
2841 while (1) {
2842
2843 const char *elem_name;
2844 elem_name = (const char*)xmlTextReaderConstName(parser->reader);
2845
2846 smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name);
2847 if (!strcmp(elem_name, SML_ELEMENT_PROPPARAM) &&
2848 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2849 // this is the end of the PropParam section
2850 break;
2851 }
2852
2853 if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START)
2854 {
2855 smlErrorSet(error, SML_ERROR_GENERIC,
2856 "The element %s is not a start node in PropParam.",
2857 xmlTextReaderConstName(parser->reader));
2858 goto error;
2859 }
2860
2861 /* determine item type */
2862 SmlDevInfCTCapType type;
2863 type = smlDevInfCTCapTypeFromString(elem_name, error);
2864 value = NULL;
2865 if (type != SML_DEVINF_CTCAP_UNKNOWN)
2866 {
2867 _smlXmlParserGetString(parser, &value, elem_name, error);
2868 }
2869
2870 /* now react on the different items */
2871 switch(type)
2872 {
2873 case SML_DEVINF_CTCAP_PARAMNAME:
2874 smlDevInfPropParamSetParamName(param, value);
2875 break;
2876 case SML_DEVINF_CTCAP_DATATYPE:
2877 smlDevInfPropParamSetDataType(param, value);
2878 break;
2879 case SML_DEVINF_CTCAP_DISPLAYNAME:
2880 smlDevInfPropParamSetDisplayName(param, value);
2881 break;
2882 case SML_DEVINF_CTCAP_VALENUM:
2883 smlDevInfPropParamAddValEnum(param, value);
2884 break;
2885 default:
2886 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for PropParam: %s", elem_name);
2887 goto error;
2888 }
2889 smlSafeCFree(&value);
2890
2891 if (!_smlXmlParserStep(parser)) {
2892 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2893 goto error;
2894 }
2895 }
2896
2897 smlTrace(TRACE_EXIT, "%s", __func__);
2898 return param;
2899
2900 error:
2901 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
2902 if (value != NULL)
2903 smlSafeCFree(&value);
2904 return NULL;
2905 }
2906
2907 static SmlDevInfProperty *_smlXmlDevInfDataStoreParseCTCap12Property(SmlXmlParser *parser, SmlError **error)
2908 {
2909 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, error);
2910 CHECK_ERROR_REF
2911 smlAssert(parser);
2912
2913 if (!_smlXmlParserStep(parser)) {
2914 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2915 goto error;
2916 }
2917
2918 SmlDevInfProperty *property = smlDevInfNewProperty(error);
2919 if (!property)
2920 goto error;
2921
2922 SmlDevInfPropParam *param;
2923 char *value = NULL;
2924 while (1) {
2925
2926 const char *elem_name;
2927 elem_name = (const char*)xmlTextReaderConstName(parser->reader);
2928
2929 smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name);
2930 if (!strcmp(elem_name, SML_ELEMENT_PROPERTY) &&
2931 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
2932 // this is the end of the Property section
2933 break;
2934 }
2935
2936 if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START)
2937 {
2938 smlErrorSet(error, SML_ERROR_GENERIC,
2939 "The element %s is not a start node in Property.",
2940 xmlTextReaderConstName(parser->reader));
2941 goto error;
2942 }
2943
2944 /* determine item type */
2945 SmlDevInfCTCapType type;
2946 type = smlDevInfCTCapTypeFromString(elem_name, error);
2947 value = NULL;
2948 if (type != SML_DEVINF_CTCAP_UNKNOWN &&
2949 type != SML_DEVINF_CTCAP_PROPPARAM)
2950 {
2951 _smlXmlParserGetString(parser, &value, elem_name, error);
2952 }
2953
2954 /* now react on the different items */
2955 switch(type)
2956 {
2957 case SML_DEVINF_CTCAP_PROPNAME:
2958 smlDevInfPropertySetPropName(property, value);
2959 break;
2960 case SML_DEVINF_CTCAP_DATATYPE:
2961 smlDevInfPropertySetDataType(property, value);
2962 break;
2963 case SML_DEVINF_CTCAP_MAXOCCUR:
2964 smlDevInfPropertySetMaxOccur(property, atoi(value));
2965 break;
2966 case SML_DEVINF_CTCAP_MAXSIZE:
2967 smlDevInfPropertySetMaxSize(property, atoi(value));
2968 break;
2969 case SML_DEVINF_CTCAP_NOTRUNCATE:
2970 smlDevInfPropertySetNoTruncate(property);
2971 break;
2972 case SML_DEVINF_CTCAP_DISPLAYNAME:
2973 smlDevInfPropertySetDisplayName(property, value);
2974 break;
2975 case SML_DEVINF_CTCAP_VALENUM:
2976 smlDevInfPropertyAddValEnum(property, value);
2977 break;
2978 case SML_DEVINF_CTCAP_PROPPARAM:
2979 param = _smlXmlDevInfDataStoreParseCTCap12PropParam(parser, error);
2980 if (!param)
2981 goto error;
2982 smlDevInfPropertyAddPropParam(property, param);
2983 break;
2984 case SML_DEVINF_CTCAP_SIZE:
2985 smlDevInfPropertySetPropSize(property, atoi(value));
2986 break;
2987 default:
2988 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for Property: %s", elem_name);
2989 goto error;
2990 }
2991 if (value) smlSafeCFree(&value);
2992
2993 if (!_smlXmlParserStep(parser)) {
2994 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
2995 goto error;
2996 }
2997 }
2998
2999 smlTrace(TRACE_EXIT, "%s", __func__);
3000 return property;
3001
3002 error:
3003 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
3004 if (value != NULL)
3005 smlSafeCFree(&value);
3006 return NULL;
3007 }
3008
3009 static SmlBool _smlXmlDevInfDataStoreParseCTCap12(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error)
3010 {
3011 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error);
3012 CHECK_ERROR_REF
3013 smlAssert(parser);
3014 smlAssert(devinf);
3015
3016 /* This function was designed to parse one CTCap section */
3017 /* which can include only one CTCap definition */
3018
3019 if (!_smlXmlParserStep(parser)) {
3020 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3021 goto error;
3022 }
3023
3024 SmlDevInfCTCap *ctcap = smlDevInfNewCTCap(error);
3025 if (!ctcap)
3026 goto error;
3027
3028 SmlDevInfProperty *property;
3029 char *value = NULL;
3030 while (1) {
3031
3032 const char *elem_name;
3033 elem_name = (const char*)xmlTextReaderConstName(parser->reader);
3034
3035 smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name);
3036 if (!strcmp(elem_name, SML_ELEMENT_CTCAP) &&
3037 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3038 // this is the end of the CTCap section
3039 break;
3040 }
3041
3042 if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START)
3043 {
3044 smlErrorSet(error, SML_ERROR_GENERIC,
3045 "The element %s is not a start node in CtCap.",
3046 xmlTextReaderConstName(parser->reader));
3047 goto error;
3048 }
3049
3050 /* determine item type */
3051 SmlDevInfCTCapType type;
3052 type = smlDevInfCTCapTypeFromString(elem_name, error);
3053 value = NULL;
3054 if (type != SML_DEVINF_CTCAP_UNKNOWN &&
3055 type != SML_DEVINF_CTCAP_PROPERTY)
3056 {
3057 _smlXmlParserGetString(parser, &value, elem_name, error);
3058 }
3059
3060 /* now react on the different items */
3061 switch(type)
3062 {
3063 case SML_DEVINF_CTCAP_CTTYPE:
3064 smlDevInfCTCapSetCTType(ctcap, value);
3065 break;
3066 case SML_DEVINF_CTCAP_VERCT:
3067 smlDevInfCTCapSetVerCT(ctcap, value);
3068 break;
3069 case SML_DEVINF_CTCAP_PROPERTY:
3070 property = _smlXmlDevInfDataStoreParseCTCap12Property(parser, error);
3071 if (!property)
3072 goto error;
3073 smlDevInfCTCapAddProperty(ctcap, property);
3074 break;
3075 default:
3076 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for CTCap: %s", elem_name);
3077 goto error;
3078 }
3079 if (value) smlSafeCFree(&value);
3080
3081 if (!_smlXmlParserStep(parser)) {
3082 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3083 goto error;
3084 }
3085 }
3086 smlDevInfAppendCTCap(devinf, ctcap);
3087
3088 smlTrace(TRACE_EXIT, "%s", __func__);
3089 return TRUE;
3090
3091 error:
3092 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
3093 if (value != NULL)
3094 smlSafeCFree(&value);
3095 return FALSE;
3096 }
3097
3098 static SmlBool _smlXmlDevInfDataStoreParseCTCap(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error)
3099 {
3100 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error);
3101 CHECK_ERROR_REF
3102 smlAssert(parser);
3103 smlAssert(devinf);
3104
3105 /* SyncML 1.0 and 1.1 start a new CTCap with a new CTType definition */
3106 /* SyncML 1.2 starts a new CTCap with a new CTCap definition */
3107 /* SyncML 1.2 attaches the CTCaps to the appropriate datastore */
3108 /* SyncML 1.0 and 1.1 attach the CTCaps to DevInf */
3109 /* The SyncML version is in devinf->version */
3110
3111 SmlBool ret;
3112 if (devinf->version == SML_DEVINF_VERSION_12)
3113 ret = _smlXmlDevInfDataStoreParseCTCap12(parser, devinf, error);
3114 else
3115 ret = _smlXmlDevInfDataStoreParseCTCap11(parser, devinf, error);
3116
3117 smlTrace(TRACE_EXIT, "%s (%d)", __func__, ret);
3118 return ret;
3119 }
3120
3121 static SmlBool _smlXmlDevInfDataStoreParseRxTx(SmlXmlParser *parser, const char *element, char **cttype, char **version, SmlError **error)
3122 {
3123 smlTrace(TRACE_ENTRY, "%s(%p, %s, %p, %p, %p)", __func__, parser, VA_STRING(element), cttype, version, error);
3124 CHECK_ERROR_REF
3125 smlAssert(parser);
3126 smlAssert(element);
3127 smlAssert(cttype);
3128
3129 if (!_smlXmlParserStep(parser)) {
3130 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3131 goto error;
3132 }
3133
3134 while (1) {
3135 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), element) && \
3136 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3137 break;
3138 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
3139 smlErrorSet(error, SML_ERROR_GENERIC,
3140 "The element %s is not a start node in %s.",
3141 xmlTextReaderConstName(parser->reader), element);
3142 goto error;
3143 }
3144
3145 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTTYPE)) {
3146 if (!_smlXmlParserGetString(parser, cttype, SML_ELEMENT_CTTYPE, error))
3147 goto error;
3148 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERCT)) {
3149 /* Some phones send an empty VerCT for formats that dont have a version
3150 * (like notes). */
3151 if (!_smlXmlParserStep(parser)) {
3152 smlErrorSet(error, SML_ERROR_GENERIC, "No node at all");
3153 goto error;
3154 }
3155
3156 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERCT) && \
3157 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3158 *version = g_strdup("");
3159 } else if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) {
3160 *version = g_strstrip(g_strdup((char *)xmlTextReaderConstValue(parser->reader)));
3161
3162 if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_VERCT, error))
3163 goto error;
3164 } else {
3165 *version = g_strdup("");
3166 continue;
3167 }
3168 } else {
3169 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node");
3170 goto error;
3171 }
3172
3173 if (!_smlXmlParserStep(parser)) {
3174 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3175 goto error;
3176 }
3177 }
3178
3179 smlTrace(TRACE_EXIT, "%s", __func__);
3180 return TRUE;
3181
3182 error:
3183 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
3184 return FALSE;
3185 }
3186
3187 static SmlBool _smlXmlDevInfDataStoreParse(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error)
3188 {
3189 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error);
3190 CHECK_ERROR_REF
3191 smlAssert(devinf);
3192 smlAssert(parser);
3193
3194 SmlDevInfDataStore *datastore = smlTryMalloc0(sizeof(SmlDevInfDataStore), error);
3195 if (!datastore)
3196 goto error;
3197 datastore->refCount = 1;
3198 datastore->rxPrefContentType = NULL;
3199 datastore->txPrefContentType = NULL;
3200
3201 if (!_smlXmlParserStep(parser)) {
3202 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3203 goto error_free_datastore;
3204 }
3205
3206 while (1) {
3207
3208 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATASTORE) && \
3209 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3210 break;
3211 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
3212 smlErrorSet(error, SML_ERROR_GENERIC,
3213 "The element %s is not a start node in Datastore.",
3214 xmlTextReaderConstName(parser->reader));
3215 goto error_free_datastore;
3216 }
3217
3218 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) {
3219 if (!_smlXmlParserGetString(parser, &(datastore->sourceref), SML_ELEMENT_SOURCEREF, error))
3220 goto error_free_datastore;
3221 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DISPLAYNAME)) {
3222 if (!_smlXmlParserGetString(parser, &(datastore->displayname), SML_ELEMENT_DISPLAYNAME, error))
3223 goto error_free_datastore;
3224 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXGUIDSIZE)) {
3225 if (!_smlXmlParserGetID(parser, &(datastore->maxGUIDSize), SML_ELEMENT_MAXGUIDSIZE, error))
3226 goto error_free_datastore;
3227 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RXPREF)) {
3228 if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_RXPREF, &(datastore->rxPrefContentType), &(datastore->rxPrefVersion), error))
3229 goto error_free_datastore;
3230 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RX)) {
3231 char *cttype = NULL;
3232 char *verct = NULL;
3233 if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_RX, &cttype, &verct, error))
3234 goto error_free_datastore;
3235 SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error);
3236 smlSafeCFree(&cttype);
3237 if (verct)
3238 smlSafeCFree(&verct);
3239 if (!ct)
3240 goto error_free_datastore;
3241 smlDevInfDataStoreAddRx(datastore, ct);
3242 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TXPREF)) {
3243 if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_TXPREF, &(datastore->txPrefContentType), &(datastore->txPrefVersion), error))
3244 goto error_free_datastore;
3245 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TX)) {
3246 char *cttype = NULL;
3247 char *verct = NULL;
3248 if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_TX, &cttype, &verct, error))
3249 goto error_free_datastore;
3250 SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error);
3251 smlSafeCFree(&cttype);
3252 if (verct)
3253 smlSafeCFree(&verct);
3254 if (!ct)
3255 goto error_free_datastore;
3256 smlDevInfDataStoreAddTx(datastore, ct);
3257 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTCAP)) {
3258 if (!_smlXmlDevInfDataStoreParseCTCap(parser, devinf, error))
3259 goto error_free_datastore;
3260 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCCAP)) {
3261 if (!_smlXmlDevInfDataStoreParseSyncCap(parser, datastore, error))
3262 goto error_free_datastore;
3263 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DSMEM)) {
3264 if (!_smlXmlDevInfDataStoreParseDSMem(parser, datastore, error))
3265 goto error_free_datastore;
3266 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORT_HIERARCHICAL_SYNC)) {
3267 if (devinf->version < SML_DEVINF_VERSION_12) {
3268 smlErrorSet(error, SML_ERROR_GENERIC, "SupportHierarchicalSync is only supported in OMA DS 1.2 DevInf and later.");
3269 goto error;
3270 }
3271 datastore->supportsHierarchicalSync = TRUE;
3272 if (!xmlTextReaderIsEmptyElement(parser->reader)) {
3273 if (!_smlXmlParserStep(parser)) {
3274 smlErrorSet(error, SML_ERROR_GENERIC, "The closing element of %s is missing.", SML_ELEMENT_SUPPORT_HIERARCHICAL_SYNC);
3275 goto error;
3276 }
3277 }
3278 } else {
3279 smlErrorSet(error, SML_ERROR_GENERIC, "A DataStore within DevInf includes the unsupported element %s.", (char *)xmlTextReaderConstName(parser->reader));
3280 goto error_free_datastore;
3281 }
3282
3283 if (!_smlXmlParserStep(parser)) {
3284 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3285 goto error_free_datastore;
3286 }
3287 }
3288
3289 smlDevInfAddDataStore(devinf, datastore);
3290
3291 smlTrace(TRACE_EXIT, "%s", __func__);
3292 return TRUE;
3293
3294 error_free_datastore:
3295 smlDevInfDataStoreUnref(datastore);
3296 error:
3297 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
3298 return FALSE;
3299 }
3300
3301 SmlDevInf *smlXmlDevInfParse(const char *data, unsigned int size, SmlError **error)
3302 {
3303 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, size, error);
3304 CHECK_ERROR_REF
3305 smlAssert(data);
3306 smlAssert(size);
3307 SmlDevInf *devinf = NULL;
3308
3309 //Fixme debug if
3310 char *debugstr = smlPrintBinary(data, size);
3311 smlTrace(TRACE_INTERNAL, "Xml devinf input: %s", debugstr);
3312 smlSafeCFree(&debugstr);
3313
3314 SmlXmlParser *parser = smlTryMalloc0(sizeof(SmlXmlParser), error);
3315 if (!parser)
3316 goto error;
3317
3318 /* Create the new parser */
3319 parser->reader = xmlReaderForMemory(data, size, "/", NULL, XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA | XML_PARSER_SUBST_ENTITIES);
3320 if (!parser->reader) {
3321 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new reader");
3322 goto error;
3323 }
3324 xmlSubstituteEntitiesDefault(1);
3325
3326 /* Check the First Node (DevInf)*/
3327 if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_DEVINF, error))
3328 goto error;
3329
3330 devinf = smlTryMalloc0(sizeof(SmlDevInf), error);
3331 if (!devinf)
3332 goto error;
3333
3334 smlDevInfRef(devinf);
3335
3336 if (!_smlXmlParserStep(parser)) {
3337 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3338 goto error;
3339 }
3340
3341 while (1) {
3342 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVINF) && \
3343 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3344 break;
3345 } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) {
3346 smlErrorSet(error, SML_ERROR_GENERIC,
3347 "The element %s is not a start node in DevInf.",
3348 xmlTextReaderConstName(parser->reader));
3349 goto error;
3350 }
3351
3352
3353 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERDTD)) {
3354 char *verdtd = NULL;
3355 if (!_smlXmlParserGetString(parser, &verdtd, SML_ELEMENT_VERDTD, error))
3356 goto error;
3357
3358 if (verdtd && !strcmp(verdtd, "1.1"))
3359 devinf->version = SML_DEVINF_VERSION_11;
3360 else if (verdtd && !strcmp(verdtd, "1.0"))
3361 devinf->version = SML_DEVINF_VERSION_10;
3362 else if (verdtd && !strcmp(verdtd, "1.2"))
3363 devinf->version = SML_DEVINF_VERSION_12;
3364 else {
3365 smlSafeCFree(&verdtd);
3366 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf version");
3367 goto error;
3368 }
3369 smlSafeCFree(&verdtd);
3370 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAN)) {
3371 if (!_smlXmlParserGetString(parser, &(devinf->manufacturer), SML_ELEMENT_MAN, error))
3372 goto error;
3373 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOD)) {
3374 if (!_smlXmlParserGetString(parser, &(devinf->model), SML_ELEMENT_MOD, error))
3375 goto error;
3376 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_OEM)) {
3377 if (!_smlXmlParserGetString(parser, &(devinf->oem), SML_ELEMENT_OEM, error))
3378 goto error;
3379 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FWV)) {
3380 if (!_smlXmlParserGetString(parser, &(devinf->firmwareVersion), SML_ELEMENT_FWV, error))
3381 goto error;
3382 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SWV)) {
3383 if (!_smlXmlParserGetString(parser, &(devinf->softwareVersion), SML_ELEMENT_SWV, error))
3384 goto error;
3385 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_HWV)) {
3386 if (!_smlXmlParserGetString(parser, &(devinf->hardwareVersion), SML_ELEMENT_HWV, error))
3387 goto error;
3388 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVID)) {
3389 if (!_smlXmlParserGetString(parser, &(devinf->devid), SML_ELEMENT_DEVID, error))
3390 goto error;
3391 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVTYPE)) {
3392 char *devtype = NULL;
3393 if (!_smlXmlParserGetString(parser, &devtype, SML_ELEMENT_DEVTYPE, error))
3394 goto error;
3395
3396 devinf->devtyp = smlDevInfDevTypeFromString(devtype, error);
3397 smlSafeCFree(&devtype);
3398
3399 if (devinf->devtyp == SML_DEVINF_DEVTYPE_UNKNOWN)
3400 goto error;
3401 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_UTC)) {
3402 if (devinf->version == SML_DEVINF_VERSION_10) {
3403 smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow UTC");
3404 goto error;
3405 }
3406
3407 devinf->supportsUTC = TRUE;
3408 if (!_smlXmlParserStep(parser)) {
3409 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3410 goto error;
3411 }
3412
3413 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_UTC) && \
3414 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3415 if (!_smlXmlParserStep(parser)) {
3416 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2");
3417 goto error;
3418 }
3419 }
3420 continue;
3421 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTLARGEOBJS)) {
3422 if (devinf->version == SML_DEVINF_VERSION_10) {
3423 smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow large objects");
3424 goto error;
3425 }
3426
3427 devinf->supportsLargeObjs = TRUE;
3428 if (!_smlXmlParserStep(parser)) {
3429 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3430 goto error;
3431 }
3432
3433 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTLARGEOBJS) && \
3434 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3435 if (!_smlXmlParserStep(parser)) {
3436 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2");
3437 goto error;
3438 }
3439 }
3440 continue;
3441 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTNUMBEROFCHANGES)) {
3442 if (devinf->version == SML_DEVINF_VERSION_10) {
3443 smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow number of changes");
3444 goto error;
3445 }
3446
3447 devinf->supportsNumberOfChanges = TRUE;
3448 if (!_smlXmlParserStep(parser)) {
3449 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3450 goto error;
3451 }
3452
3453 if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTNUMBEROFCHANGES) && \
3454 xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) {
3455 if (!_smlXmlParserStep(parser)) {
3456 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2");
3457 goto error;
3458 }
3459 }
3460 continue;
3461 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATASTORE)) {
3462 if (!_smlXmlDevInfDataStoreParse(parser, devinf, error))
3463 goto error;
3464 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTCAP)) {
3465 /* This must be SyncML 1.0 or 1.1.
3466 * OMA DM 1.2 puts CTCap into the datastores.
3467 */
3468 if (!_smlXmlDevInfDataStoreParseCTCap(parser, devinf, error))
3469 goto error;
3470 } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_EXT)) {
3471 /* Ignored for now */
3472 smlTrace(TRACE_INTERNAL, "%s: Skipping ext node");
3473 if (!_smlXmlSkipNode(parser)) {
3474 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to skip ext node");
3475 goto error;
3476 }
3477 continue;
3478 } else {
3479 smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", (char *)xmlTextReaderConstName(parser->reader));
3480 goto error;
3481 }
3482
3483 if (!_smlXmlParserStep(parser)) {
3484 smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes");
3485 goto error;
3486 }
3487 }
3488
3489 xmlFreeTextReader(parser->reader);
3490 parser->reader = NULL;
3491 smlSafeFree((gpointer *)&parser);
3492
3493 smlTrace(TRACE_EXIT, "%s", __func__);
3494 return devinf;
3495
3496 error:
3497 if (parser && parser->reader) {
3498 xmlFreeTextReader(parser->reader);
3499 parser->reader = NULL;
3500 }
3501 if (parser)
3502 smlSafeFree((gpointer *)&parser);
3503 if (devinf)
3504 smlDevInfUnref(devinf);
3505 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
3506 return NULL;
3507 }
3508