From: <svn...@op...> - 2009-04-30 09:55:54
|
Author: bellmich Date: Thu Apr 30 11:55:50 2009 New Revision: 1078 URL: http://libsyncml.opensync.org/changeset/1078 Log: - patch for ticket #237 (supplied by Kwan hong Lee) - added two explicit test cases for the two different situations Modified: trunk/libsyncml/parser/sml_xml_parse.c trunk/tests/CMakeLists.txt trunk/tests/check_xml_parser.c Modified: trunk/libsyncml/parser/sml_xml_parse.c ============================================================================== --- trunk/libsyncml/parser/sml_xml_parse.c Thu Apr 30 11:53:22 2009 (r1077) +++ trunk/libsyncml/parser/sml_xml_parse.c Thu Apr 30 11:55:50 2009 (r1078) @@ -747,54 +747,64 @@ goto error_free_item; } } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) { - switch (type) { - case SML_COMMAND_TYPE_ALERT: - if (!_smlXmlParserStep(parser)) { - smlErrorSet(error, SML_ERROR_GENERIC, "The next element after the starting Data element in an Item is missing."); - goto error_free_item; - } + /* Do nothing if the Data element is empty. + * The first emptyness test only covers <Data/>. + * + * Example: Funambol with WBXML on scheduleworld.com + */ + if (!xmlTextReaderIsEmptyElement(parser->reader)) { + switch (type) { + case SML_COMMAND_TYPE_ALERT: + if (!_smlXmlParserStep(parser)) { + smlErrorSet(error, SML_ERROR_GENERIC, "The next element after the starting Data element in an Item is missing."); + goto error_free_item; + } - if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA) && - xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { - /* empty Data element - * e.g. from Funambol at scheduleworld.com */ - smlTrace(TRACE_INTERNAL, "%s: detected empty data element", __func__); - break; - } + if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA) && + xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { + /* Do nothing if the Data element is empty. + * This only covers <Data></Data>. + * + * Example: Funambol with XML on scheduleworld.com + */ + smlTrace(TRACE_INTERNAL, "%s: detected empty data element", __func__); + break; + } + + SmlAnchor *anchor = NULL; + if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) { + /* Google just copies the element Next from the Anchor + * Please see ticket #230 for more details. + */ + anchor = smlTryMalloc0(sizeof(SmlAnchor), error); + if (!anchor) + goto error_free_item; + anchor->next = g_strdup((char *)xmlTextReaderConstValue(parser->reader)); + } else { + /* normal behaviour with anchor copy */ + if (!_smlAnchorParse(&anchor, parser, error)) + goto error_free_item; + } + item->anchor = anchor; - SmlAnchor *anchor = NULL; - if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) { - /* Google just copies the element Next from the Anchor - * Please see ticket #230 for more details. - */ - anchor = smlTryMalloc0(sizeof(SmlAnchor), error); - if (!anchor) + if (!_smlXmlParserStep(parser)) { + smlErrorSet(error, SML_ERROR_GENERIC, "The closing Data element in an Item is missing."); goto error_free_item; - anchor->next = g_strdup((char *)xmlTextReaderConstValue(parser->reader)); - } else { - /* normal behaviour with anchor copy */ - if (!_smlAnchorParse(&anchor, parser, error)) + } + break; + default:; + char *data = NULL; + unsigned int size = 0; + if (!_smlXmlParserGetData(parser, &data, &size, SML_ELEMENT_DATA, error)) goto error_free_item; - } - item->anchor = anchor; - - if (!_smlXmlParserStep(parser)) { - smlErrorSet(error, SML_ERROR_GENERIC, "The closing Data element in an Item is missing."); - goto error_free_item; - } - break; - default:; - char *data = NULL; - unsigned int size = 0; - if (!_smlXmlParserGetData(parser, &data, &size, SML_ELEMENT_DATA, error)) - goto error_free_item; - - if (!smlItemAddData(item, data, size, error)) { + + if (!smlItemAddData(item, data, size, error)) { + smlSafeCFree(&data); + goto error_free_item; + } + smlSafeCFree(&data); - goto error_free_item; - } - - smlSafeCFree(&data); + } } } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOREDATA)) { if (parser->version == SML_VERSION_10) { Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Thu Apr 30 11:53:22 2009 (r1077) +++ trunk/tests/CMakeLists.txt Thu Apr 30 11:55:50 2009 (r1078) @@ -147,6 +147,8 @@ SML_ADD_TESTCASE( xml_parser_ctcap_property_size ) SML_ADD_TESTCASE( xml_parser_ctcap11_size ) SML_ADD_TESTCASE( xml_parser_item_with_meta_in_status ) + SML_ADD_TESTCASE( xml_parser_item_with_meta_and_long_empty_data_in_status ) + SML_ADD_TESTCASE( xml_parser_item_with_meta_and_short_empty_data_in_status ) SML_END_TEST() SML_START_TEST( "XML Assembler" xmlassembler check_xml_assembler.c ${TEST_TARGET_LIBRARIES} ) Modified: trunk/tests/check_xml_parser.c ============================================================================== --- trunk/tests/check_xml_parser.c Thu Apr 30 11:53:22 2009 (r1077) +++ trunk/tests/check_xml_parser.c Thu Apr 30 11:55:50 2009 (r1078) @@ -1701,10 +1701,8 @@ } END_TEST -/* - */ -/* some scheduleworld.com - * item in status including meta data like maxobjsize +/* Funambol (e.g. scheduleworld.com) embeds Item in to Status + * including the Meta element with MaxObjSize for example. */ START_TEST (xml_parser_item_with_meta_in_status) { @@ -1724,6 +1722,74 @@ "<Data>200</Data>" \ "<Item>" \ "<Meta><MaxObjSize>1024000</MaxObjSize></Meta>" \ + "</Item>" \ + "</Status>" \ + "<Final/>" \ + "</SyncBody>" \ + "</SyncML>"; + + /* check for valid document */ + + SmlError *error = NULL; + SmlParser *parser = start_parser(data, &error); + sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); + + /* parse header and first status */ + + SmlHeader *header = NULL; + SmlCred *cred = NULL; + + sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); + sml_fail_unless(header != NULL, NULL); + sml_fail_unless(cred == NULL, NULL); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(header->messageID == 4, "The message ID must be 4."); + smlHeaderFree(header); + + SmlStatus *status = NULL; + sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); + sml_fail_unless(status != NULL, NULL); + sml_fail_unless(error == NULL, NULL); + smlStatusUnref(status); + + /* parse second status with item and meta info */ + + sml_fail_unless(smlParserGetStatus(parser, &status, &error), "%s", smlErrorPrint(&error)); + sml_fail_unless(status != NULL, NULL); + sml_fail_unless(error == NULL, NULL); + smlStatusUnref(status); + + /* cleanup */ + + smlParserFree(parser); +} +END_TEST + +/* Funambol (e.g. scheduleworld.com) embeds Item in to Status + * including the Meta element with MaxObjSize for example. + * The Item element can include an empty Data element too. + * If XML native communication is used then an empty Data + * element usually looks like "<Data></Data>". + */ +START_TEST (xml_parser_item_with_meta_and_long_empty_data_in_status) +{ + const char *data = "<SyncML>" \ + "<SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>40142</SessionID><MsgID>4</MsgID><Target><LocURI>joh...@ex...</LocURI><LocName>1234567</LocName></Target><Source><LocURI>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</LocURI></Source><RespURI>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</RespURI></SyncHdr>" \ + "<SyncBody>" \ + "<Status>" \ + "<CmdID>1</CmdID><MsgRef>4</MsgRef><CmdRef>0</CmdRef><Cmd>SyncHdr</Cmd>" \ + "<TargetRef>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</TargetRef>" \ + "<SourceRef>jku@vili</SourceRef><Data>200</Data>" \ + "</Status>" \ + "<Status>" \ + "<CmdID>2</CmdID>" \ + "<MsgRef>4</MsgRef>" \ + "<CmdRef>10</CmdRef>" \ + "<Cmd>Alert</Cmd>" \ + "<Data>200</Data>" \ + "<Item>" \ + "<Meta><MaxObjSize>1024000</MaxObjSize></Meta>" \ "<Data></Data>" \ "</Item>" \ "</Status>" \ @@ -1769,5 +1835,76 @@ } END_TEST + +/* Funambol (e.g. scheduleworld.com) embeds Item in to Status + * including the Meta element with MaxObjSize for example. + * The Item element can include an empty Data element too. + * If WBXML encoded communication is used then an empty Data + * element usually looks like "<Data/>". + */ +START_TEST (xml_parser_item_with_meta_and_short_empty_data_in_status) +{ + const char *data = "<SyncML>" \ + "<SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>40142</SessionID><MsgID>4</MsgID><Target><LocURI>joh...@ex...</LocURI><LocName>1234567</LocName></Target><Source><LocURI>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</LocURI></Source><RespURI>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</RespURI></SyncHdr>" \ + "<SyncBody>" \ + "<Status>" \ + "<CmdID>1</CmdID><MsgRef>4</MsgRef><CmdRef>0</CmdRef><Cmd>SyncHdr</Cmd>" \ + "<TargetRef>http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==</TargetRef>" \ + "<SourceRef>jku@vili</SourceRef><Data>200</Data>" \ + "</Status>" \ + "<Status>" \ + "<CmdID>2</CmdID>" \ + "<MsgRef>4</MsgRef>" \ + "<CmdRef>10</CmdRef>" \ + "<Cmd>Alert</Cmd>" \ + "<Data>200</Data>" \ + "<Item>" \ + "<Meta><MaxObjSize>1024000</MaxObjSize></Meta>" \ + "<Data/>" \ + "</Item>" \ + "</Status>" \ + "<Final/>" \ + "</SyncBody>" \ + "</SyncML>"; + + /* check for valid document */ + + SmlError *error = NULL; + SmlParser *parser = start_parser(data, &error); + sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); + + /* parse header and first status */ + + SmlHeader *header = NULL; + SmlCred *cred = NULL; + + sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); + sml_fail_unless(header != NULL, NULL); + sml_fail_unless(cred == NULL, NULL); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(header->messageID == 4, "The message ID must be 4."); + smlHeaderFree(header); + + SmlStatus *status = NULL; + sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); + sml_fail_unless(status != NULL, NULL); + sml_fail_unless(error == NULL, NULL); + smlStatusUnref(status); + + /* parse second status with item and meta info */ + + sml_fail_unless(smlParserGetStatus(parser, &status, &error), "%s", smlErrorPrint(&error)); + sml_fail_unless(status != NULL, NULL); + sml_fail_unless(error == NULL, NULL); + smlStatusUnref(status); + + /* cleanup */ + + smlParserFree(parser); +} +END_TEST + + @SML_TESTCASE_CODE@ |