/*
 * libsyncml - A syncml protocol implementation
 * Copyright (C) 2005  Armin Bauer <armin.bauer@opensync.org>
 * Copyright (C) 2007-2008  Michael Bell <michael.bell@opensync.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 */
 
#include "tests/support.h"

#include <libsyncml/parser/sml_xml_parse.h>
#include <libsyncml/sml_command_internals.h>
#include <libsyncml/sml_elements_internals.h>
#include <libsyncml/sml_error_internals.h>
#include <libsyncml/data_sync_api/sml_data_sync_change_item_internals.h>

START_TEST (xml_parser_empty)
{
	const char *data = " ";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
}
END_TEST

START_TEST (xml_parser_syncml_empty)
{
	const char *data = "<SyncML></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
}
END_TEST

START_TEST (xml_parser_syncml_wrong_case)
{
	const char *data = "<SyncMl></SyncMl>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
}
END_TEST

START_TEST (xml_parser_syncml_additional)
{
	const char *data = "<SyncML></SyncML><test></test>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
}
END_TEST

START_TEST (xml_parser_no_syncbody)
{
	const char *data = "<SyncML><SyncHdr></SyncHdr></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_no_synchdr)
{
	const char *data = "<SyncML><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
}
END_TEST

START_TEST (xml_parser_synchdr_empty)
{
	const char *data = "<SyncML><SyncHdr></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_verproto)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_verdtd)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_msgid)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_sessionid)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_target)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_source)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	sml_fail_unless(header->target != NULL, NULL);
	sml_fail_unless(header->source != NULL, NULL);
	sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL);
	sml_fail_unless(header->version == SML_VERSION_11, NULL);
	sml_fail_unless(header->sessionID == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_source2)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>123</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	sml_fail_unless(header->target != NULL, NULL);
	sml_fail_unless(header->source != NULL, NULL);
	sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL);
	sml_fail_unless(header->version == SML_VERSION_11, NULL);
	sml_fail_unless(header->sessionID == 123, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_synchdr_additional)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source><test></test></SyncHdr><SyncBody></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status_empty)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	SML_ERROR_FREE(error);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status_cmdid)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	SML_ERROR_FREE(error);

	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status_msgref)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status_cmdref)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>1</CmdRef></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status2)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = TRUE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == FALSE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status3)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Final/></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = FALSE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == TRUE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_status_google)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>5</CmdID><MsgRef>2</MsgRef><CmdRef>3</CmdRef><Cmd>Alert</Cmd><SourceRef>contacts</SourceRef><TargetRef>contacts</TargetRef><Data>200</Data><Item><Data><![CDATA[20090417T092559Z]]></Data></Item></Status></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_final)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = FALSE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == TRUE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_final2)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>Sync</Cmd></Status><Final/></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = FALSE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == TRUE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_cmd)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Alert><CmdID>1</CmdID><Item><Target><LocURI>/test</LocURI></Target><Source><LocURI>/test</LocURI></Source><Meta><Anchor xmlns=\"syncml:metinf\"><Next>Next</Next><Last>last</Last></Anchor></Meta></Item><Data>200</Data></Alert></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = TRUE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == FALSE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_cmd_final)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.1</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Alert><CmdID>1</CmdID><Item><Target><LocURI>/test</LocURI></Target><Source><LocURI>/test</LocURI></Source><Meta><Anchor xmlns=\"syncml:metinf\"><Next>Next</Next><Last>last</Last></Anchor></Meta></Item><Data>200</Data></Alert><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_sync_subcommand)
{
	const char *data = "<SyncML xmlns=\"SYNCML:SYNCML1.2\"><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source></SyncHdr><SyncBody><Sync><CmdID>3</CmdID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source><NumberOfChanges>1</NumberOfChanges><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type></Meta><Item><Source><LocURI>uid</LocURI></Source><Data><![CDATA[data]]></Data></Item></Add></Sync><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL);
	sml_fail_unless(cmd->private.sync.numChanged == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 4, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL);
	sml_fail_unless(cmd->private.change.items != NULL, NULL);
	sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST


START_TEST (xml_parser_emi)
{
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\"><SyncML xmlns=\"syncml:SYNCML1.1\"><SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>1</SessionID><MsgID>1</MsgID><Target><LocURI>opium</LocURI></Target><Source><LocURI>IMEI:xxxxxxxxxxxxxxx</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">10000</MaxMsgSize><EMI xmlns=\"syncml:metinf\">NokiaInq/1.1</EMI></Meta></SyncHdr><SyncBody><Status><CmdID>1</CmdID><Cmd>SyncHdr</Cmd><Data>403</Data></Status><Status><CmdID>2</CmdID><CmdRef>1</CmdRef><Cmd>Alert</Cmd><Data>500</Data></Status><Status><CmdID>3</CmdID><CmdRef>2</CmdRef><Cmd>Alert</Cmd><Data>500</Data></Status><Status><CmdID>4</CmdID><CmdRef>3</CmdRef><Cmd>Alert</Cmd><Data>500</Data></Status><Final/></SyncBody></SyncML>";

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	
	sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(header->messageID == 1, NULL);

	smlHeaderFree(header);
	
	smlParserFree(parser);
}
END_TEST



START_TEST (xml_parser_doctype)
{
	const char *data = "<?xml version=\"1.0\"?>\n<!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\">\n<SyncML xmlns=\"syncml:SYNCML1.1\">\n<SyncHdr>\n<VerDTD>\n1.1\n</VerDTD>\n<VerProto>\nSyncML/1.1\n</VerProto>\n<SessionID>\n1125161435\n</SessionID>\n<MsgID>\n1\n</MsgID>\n<Target>\n<LocURI>\nhttp://test.com:7962/\n</LocURI>\n</Target>\n<Source>\n<LocURI>\n35686843434\n</LocURI>\n<LocName>\nasd\n</LocName>\n</Source>\n<Cred>\n<Meta>\n<Format xmlns=\"syncml:metinf\">\nb64\n</Format>\n<Type xmlns=\"syncml:metinf\">\nsyncml:auth-basic\n</Type>\n</Meta>\n<Data>\nYXNkOmFzZA==\n</Data>\n</Cred>\n<Meta>\n<MaxMsgSize xmlns=\"syncml:metinf\">\n3300\n</MaxMsgSize>\n</Meta>\n</SyncHdr>\n<SyncBody>\n<Alert>\n<CmdID>\n1\n</CmdID>\n<Data>\n201\n</Data>\n<Item>\n<Target>\n<LocURI>\npeople\n</LocURI>\n</Target>\n<Source>\n<LocURI>\npeople\n</LocURI>\n</Source>\n<Meta>\n<Anchor xmlns=\"syncml:metinf\">\n<Last>\n</Last>\n<Next>\n1\n</Next>\n</Anchor>\n</Meta>\n</Item>\n</Alert>\n<Put>\n<CmdID>\n2\n</CmdID>\n<Meta>\n<Format xmlns=\"syncml:metinf\">\nwbxml\n</Format>\n<Type xmlns=\"syncml:metinf\">\napplication/vnd.syncml-devinf+xml\n</Type>\n</Meta>\n<Item>\n<Source>\n<LocURI>\n./devinf11\n</LocURI>\n</Source>\n<Data>\n<DevInf xmlns=\"syncml:devinf\">\n<VerDTD>\n1.1\n</VerDTD>\n<Man>\nMotorola CE, Copyright 2004\n</Man>\n<Mod>\nV3\n</Mod>\n<SwV>\nR374_G_0E.41.C3R_A\n</SwV>\n<HwV>\nSJUG0851CA\n</HwV>\n<DevID>\n3564564556453\n</DevID>\n<DevTyp>\nphone\n</DevTyp>\n<DataStore>\n<SourceRef>\npeople\n</SourceRef>\n<Rx-Pref>\n<CTType>\ntext/x-vcard\n</CTType>\n<VerCT>\n2.1\n</VerCT>\n</Rx-Pref>\n<Tx-Pref>\n<CTType>\ntext/x-vcard\n</CTType>\n<VerCT>\n2.1\n</VerCT>\n</Tx-Pref>\n<SyncCap>\n<SyncType>\n1\n</SyncType>\n<SyncType>\n2\n</SyncType>\n</SyncCap>\n</DataStore>\n<CTCap>\n<CTType>\ntext/x-vcard\n</CTType>\n<PropName>\nBEGIN\n</PropName>\n<ValEnum>\nVCARD\n</ValEnum>\n<PropName>\nEND\n</PropName>\n<ValEnum>\nVCARD\n</ValEnum>\n<PropName>\nVERSION\n</PropName>\n<ValEnum>\n2.1\n</ValEnum>\n<PropName>\nFN\n</PropName>\n<PropName>\nN\n</PropName>\n<PropName>\nTEL\n</PropName>\n<ParamName>\nPREF\n</ParamName>\n<ParamName>\nWORK\n</ParamName>\n<ParamName>\nHOME\n</ParamName>\n<ParamName>\nCELL\n</ParamName>\n<ParamName>\nFAX\n</ParamName>\n<ParamName>\nPAGER\n</ParamName>\n<PropName>\nEMAIL\n</PropName>\n<ParamName>\nINTERNET\n</ParamName>\n<PropName>\nCHARSET\n</PropName>\n</CTCap>\n</DevInf>\n</Data>\n</Item>\n</Put>\n<Final>\n</Final>\n</SyncBody>\n</SyncML>\n";

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	smlHeaderFree(header);
	smlCredUnref(cred);
	
	SmlStatus *status = NULL;
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_large_obj)
{
	const char *data = "<SyncML xmlns=\"SYNCML:SYNCML1.2\"><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source></SyncHdr><SyncBody><Sync><CmdID>3</CmdID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source><NumberOfChanges>1</NumberOfChanges><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type><Size>200</Size></Meta><Item><Source><LocURI>uid</LocURI></Source><Data><![CDATA[data]]></Data><MoreData></MoreData></Item></Add></Sync><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL);
	sml_fail_unless(cmd->private.sync.numChanged == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 4, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL);
	sml_fail_unless(cmd->private.change.items != NULL, NULL);
	sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL);
	SmlDataSyncChangeItem *item = g_list_nth_data(cmd->private.change.items, 0);
	sml_fail_unless(sml_data_sync_change_item_get_missing_data(item) == TRUE, NULL);
	sml_fail_unless(cmd->size == 200, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_large_obj2)
{
	const char *data = "<SyncML xmlns=\"SYNCML:SYNCML1.2\"><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source></SyncHdr><SyncBody><Sync><CmdID>3</CmdID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source><NumberOfChanges>1</NumberOfChanges><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type><Size>200</Size></Meta><Item><Source><LocURI>uid</LocURI></Source><Data><![CDATA[data]]></Data><MoreData/></Item></Add></Sync><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL);
	sml_fail_unless(cmd->private.sync.numChanged == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 4, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL);
	sml_fail_unless(cmd->private.change.items != NULL, NULL);
	sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL);
	SmlDataSyncChangeItem *item = g_list_nth_data(cmd->private.change.items, 0);
	sml_fail_unless(sml_data_sync_change_item_get_missing_data(item) == TRUE, NULL);
	sml_fail_unless(cmd->size == 200, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_large_obj_error)
{
	const char *data = "<SyncML xmlns=\"SYNCML:SYNCML1.2\"><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source></SyncHdr><SyncBody><Sync><CmdID>3</CmdID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source><NumberOfChanges>1</NumberOfChanges><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type><Size>200</Size></Meta><Item><Source><LocURI>uid</LocURI></Source><Data><![CDATA[data]]></Data><MoreData></MoreData></Item></Add><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type><Size>200</Size></Meta><Item><Source><LocURI>uid</LocURI></Source><Data><![CDATA[data]]></Data></Item></Add></Sync><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL);
	sml_fail_unless(cmd->private.sync.numChanged == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 4, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL);
	sml_fail_unless(cmd->private.change.items != NULL, NULL);
	sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL);
	SmlDataSyncChangeItem *item = g_list_nth_data(cmd->private.change.items, 0);
	sml_fail_unless(sml_data_sync_change_item_get_missing_data(item) == TRUE, NULL);
	sml_fail_unless(cmd->size == 200, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_ERROR, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_ERROR, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(!smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_large_obj_mangled)
{
	const char *data = "<SyncML xmlns=\"SYNCML:SYNCML1.2\"><SyncHdr><VerProto>SyncML/1.1</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source></SyncHdr><SyncBody><Sync><CmdID>3</CmdID><Target><LocURI>/vcards</LocURI></Target><Source><LocURI>/vcards</LocURI></Source><NumberOfChanges>1</NumberOfChanges><Add><CmdID>4</CmdID><Meta><Type xmlns=\"syncml:metinf\">text/x-vcard</Type></Meta><Item><Source><LocURI>uid</LocURI></Source><Meta><Size>10</Size></Meta><Data><![CDATA[data\r\n\r\nda]]></Data><MoreData></MoreData></Item></Add></Sync><Final></Final></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL);
	sml_fail_unless(cmd->private.sync.numChanged == 1, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 4, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL);
	sml_fail_unless(cmd->private.change.items != NULL, NULL);
	sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL);
	SmlDataSyncChangeItem *item = g_list_nth_data(cmd->private.change.items, 0);
	sml_fail_unless(sml_data_sync_change_item_get_missing_data(item) == TRUE, NULL);
	sml_fail_unless(cmd->size == 10, NULL);
	
	const char *data2 = sml_data_sync_change_item_get_data(item);
	
	sml_fail_unless(!strcmp(data2, "data\n\nda"), NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_devinf)
{
	setup_testbed(NULL);
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\"><SyncML xmlns=\"syncml:SYNCML1.1\"><SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>21</SessionID><MsgID>1</MsgID><Target><LocURI>PC Suite</LocURI></Target><Source><LocURI>IMEI:XXXX</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">10000</MaxMsgSize></Meta></SyncHdr><SyncBody><Put><CmdID>8</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+xml</Type></Meta><Item><Source><LocURI>./devinf11</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.1</VerDTD><Man>NOKIA</Man><Mod>6680</Mod><SwV>3.04.37</SwV><DevID>IMEI:XXXX</DevID><DevTyp>phone</DevTyp><SupportLargeObjs/><SupportNumberOfChanges/><DataStore><SourceRef>./C\\Systemata\\Calendar</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Rx><CTType>text/calendar</CTType><VerCT>2.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./C\\System\\\\\\Data\\Contacts.cdb</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Rx><CTType>text/vcard</CTType><VerCT>3.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./C\\System\\Data\\Notepad.dat</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx-Pref><Rx><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx><Tx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx-Pref><Tx><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>DESCRIPTION</PropName><PropName>DTEND</PropName><PropName>DTSTART</PropName><PropName>AALARM</PropName><ParamName>TYPE</ParamName><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum><ValEnum>PRIVATE</ValEnum><ValEnum>CONFIDENTIAL</ValEnum><PropName>COMPLETED</PropName><PropName>LOCATION</PropName><PropName>DCREATED</PropName><PropName>LAST-MODIFIED</PropName><PropName>PRIORITY</PropName><PropName>STATUS</PropName><PropName>RRULE</PropName><PropName>DUE</PropName><PropName>EXDATE</PropName><PropName>X-EPOCAGENDAENTRYTYPE</PropName><CTType>text/calendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>VERSION</PropName><ValEnum>2.0</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>DESCRIPTION</PropName><PropName>DTEND</PropName><PropName>DTSTART</PropName><PropName>AALARM</PropName><ParamName>TYPE</ParamName><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum><ValEnum>PRIVATE</ValEnum><ValEnum>CONFIDENTIAL</ValEnum><PropName>COMPLETED</PropName><PropName>LOCATION</PropName><PropName>DCREATED</PropName><PropName>LAST-MODIFIED</PropName><PropName>PRIORITY</PropName><PropName>STATUS</PropName><PropName>RRULE</PropName><PropName>DUE</PropName><PropName>EXDATE</PropName><PropName>X-EPOCAGENDAENTRYTYPE</PropName><CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>2.1</ValEnum><PropName>REV</PropName><PropName>N</PropName><PropName>ADR</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>TEL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><ParamName>CELL</ParamName><ParamName>PAGER</ParamName><ParamName>FAX</ParamName><ParamName>VIDEO</ParamName><PropName>FN</PropName><PropName>EMAIL</PropName><ParamName>INTERNET</ParamName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>URL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>NOTE</PropName><PropName>TITLE</PropName><PropName>ORG</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>SOUND</PropName><ParamName>X-IRMC-N</ParamName><CTType>text/vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>3.0</ValEnum><PropName>REV</PropName><PropName>N</PropName><PropName>ADR</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>TEL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><ParamName>CELL</ParamName><ParamName>PAGER</ParamName><ParamName>FAX</ParamName><ParamName>VIDEO</ParamName><PropName>FN</PropName><PropName>EMAIL</PropName><ParamName>INTERNET</ParamName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>URL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>NOTE</PropName><PropName>TITLE</PropName><PropName>ORG</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>SOUND</PropName><ParamName>X-IRMC-N</ParamName><CTType>text/plain</CTType></CTCap></DevInf></Data></Item></Put><Final/></SyncBody></SyncML>";
	
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 8, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_devinf_ctcap)
{
	setup_testbed(NULL);
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/OMA-TS-SyncML_RepPro_DTD-V1_2.dtd\"><SyncML xmlns=\"syncml:SYNCML1.2\"><SyncHdr><VerDTD>1.2</VerDTD><VerProto>SyncML/1.2</VerProto><SessionID>1</SessionID><MsgID>1</MsgID><Target><LocURI>LibSyncML Test Suite</LocURI></Target><Source><LocURI>IMEI:xxxxxxxxxxxxxxx</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">6000</MaxMsgSize></Meta></SyncHdr><SyncBody><Put><CmdID>1</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+wbxml</Type></Meta><Item><Source><LocURI>./devinf12</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.2</VerDTD><Man>SonyEricsson</Man><Mod>K850i</Mod><FwV>R1CA029</FwV><SwV>R7A</SwV><HwV>R6A</HwV><DevID>IMEI:xxxxxxxxxxxxxxx</DevID><DevTyp>phone</DevTyp><UTC/><SupportNumberOfChanges/><SupportLargeObjs/><DataStore><SourceRef>Contacts</SourceRef><DisplayName>Contacts</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Rx><CTType>text/vcard</CTType><VerCT>3.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><CTCap><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT><Property><PropName>X-IRMC-LUID</PropName><Size>12</Size></Property><Property><PropName>GEO</PropName></Property><Property><PropName>PHOTO</PropName><Size>10000</Size><NoTruncate/><PropParam><ParamName>ENCODING</ParamName><ValEnum>BASE64</ValEnum></PropParam></Property><Property><PropName>BDAY</PropName><Size>8</Size></Property><Property><PropName>URL</PropName><Size>120</Size></Property><Property><PropName>TITLE</PropName><Size>30</Size></Property><Property><PropName>ORG</PropName><Size>30</Size></Property><Property><PropName>EMAIL</PropName><MaxOccur>3</MaxOccur><Size>128</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>ADR</PropName><MaxOccur>2</MaxOccur><Size>125</Size><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>NOTE</PropName><Size>512</Size></Property><Property><PropName>TEL</PropName><MaxOccur>7</MaxOccur><Size>80</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>CELL;WORK</ValEnum><ValEnum>CELL;HOME</ValEnum><ValEnum>CELL</ValEnum><ValEnum>HOME</ValEnum><ValEnum>FAX</ValEnum><ValEnum>WORK</ValEnum></PropParam></Property><Property><PropName>N</PropName><Size>60</Size></Property><Property><PropName>VERSION</PropName><ValEnum>2.1</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCARD</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum></Property></CTCap><CTCap><CTType>text/vcard</CTType><VerCT>3.0</VerCT><Property><PropName>X-IRMC-LUID</PropName><Size>12</Size></Property><Property><PropName>GEO</PropName></Property><Property><PropName>PHOTO</PropName><Size>10000</Size><NoTruncate/><PropParam><ParamName>ENCODING</ParamName><ValEnum>BASE64</ValEnum></PropParam></Property><Property><PropName>BDAY</PropName><Size>8</Size></Property><Property><PropName>URL</PropName><Size>120</Size></Property><Property><PropName>TITLE</PropName><Size>30</Size></Property><Property><PropName>ORG</PropName><Size>30</Size></Property><Property><PropName>EMAIL</PropName><MaxOccur>3</MaxOccur><Size>128</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>ADR</PropName><MaxOccur>2</MaxOccur><Size>125</Size><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>NOTE</PropName><Size>512</Size></Property><Property><PropName>TEL</PropName><MaxOccur>7</MaxOccur><Size>80</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>CELL;WORK</ValEnum><ValEnum>CELL;HOME</ValEnum><ValEnum>CELL</ValEnum><ValEnum>HOME</ValEnum><ValEnum>FAX</ValEnum><ValEnum>WORK</ValEnum></PropParam></Property><Property><PropName>N</PropName><Size>60</Size></Property><Property><PropName>VERSION</PropName><ValEnum>3.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCARD</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum></Property></CTCap><DSMem><MaxID>5000</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Calendar</SourceRef><DisplayName>Calendar</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT><Property><PropName>X-IRMC-LUID</PropName><Size>12</Size></Property><Property><PropName>X-SONYERICSSON-DST</PropName></Property><Property><PropName>DAYLIGHT</PropName></Property><Property><PropName>LAST-MODIFIED</PropName></Property><Property><PropName>EXDATE</PropName></Property><Property><PropName>RRULE</PropName><Size>50</Size></Property><Property><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum></Property><Property><PropName>CATEGORIES</PropName><ValEnum>BIRTHDAY</ValEnum><ValEnum>HOLIDAY</ValEnum><ValEnum>VACATION</ValEnum><ValEnum>TRAVEL</ValEnum><ValEnum>PHONE CALL</ValEnum><ValEnum>MISCELLANEOUS</ValEnum><ValEnum>MEETING</ValEnum></Property><Property><PropName>AALARM</PropName></Property><Property><PropName>DALARM</PropName></Property><Property><PropName>DTEND</PropName></Property><Property><PropName>DTSTART</PropName></Property><Property><PropName>DESCRIPTION</PropName><Size>512</Size></Property><Property><PropName>LOCATION</PropName><Size>50</Size></Property><Property><PropName>SUMMARY</PropName><Size>200</Size></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VEVENT</ValEnum><ValEnum>VCALENDAR</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VEVENT</ValEnum><ValEnum>VCALENDAR</ValEnum></Property></CTCap><DSMem><MaxID>1000</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Tasks</SourceRef><DisplayName>Tasks</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT><Property><PropName>X-IRMC-LUID</PropName><Size>12</Size></Property><Property><PropName>X-SONYERICSSON-DST</PropName></Property><Property><PropName>DAYLIGHT</PropName></Property><Property><PropName>LAST-MODIFIED</PropName></Property><Property><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum></Property><Property><PropName>CATEGORIES</PropName><ValEnum>BIRTHDAY</ValEnum><ValEnum>HOLIDAY</ValEnum><ValEnum>VACATION</ValEnum><ValEnum>TRAVEL</ValEnum><ValEnum>PHONE CALL</ValEnum><ValEnum>MISCELLANEOUS</ValEnum><ValEnum>MEETING</ValEnum></Property><Property><PropName>STATUS</PropName><ValEnum>COMPLETED</ValEnum><ValEnum>NEEDS ACTION</ValEnum><ValEnum>ACCEPTED</ValEnum></Property><Property><PropName>PRIORITY</PropName></Property><Property><PropName>DUE</PropName></Property><Property><PropName>COMPLETED</PropName></Property><Property><PropName>AALARM</PropName></Property><Property><PropName>DALARM</PropName></Property><Property><PropName>DESCRIPTION</PropName><Size>512</Size></Property><Property><PropName>SUMMARY</PropName><Size>200</Size></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VTODO</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VTODO</ValEnum></Property></CTCap><DSMem><MaxID>250</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Notes</SourceRef><DisplayName>Notes</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/plain</CTType><VerCT>1.0</VerCT><Property><PropName>BODY</PropName><Size>254</Size></Property></CTCap><DSMem><MaxID>50</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Bookmarks</SourceRef><DisplayName>Bookmarks</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT><Property><PropName>X-SONYERICSSON-ICON</PropName><Size>256</Size><PropParam><ParamName>ENCODING</ParamName><ValEnum>BASE64</ValEnum></PropParam></Property><Property><PropName>X-IRMC-URL</PropName></Property><Property><PropName>URL</PropName><Size>1024</Size></Property><Property><PropName>TITLE</PropName><Size>31</Size></Property><Property><PropName>BEGIN</PropName><ValEnum>VENV</ValEnum><ValEnum>VBKM</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VENV</ValEnum><ValEnum>VBKM</ValEnum></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property></CTCap><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore></DevInf></Data></Item></Put><Final/></SyncBody></SyncML>";
	
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 1, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST


START_TEST (xml_parser_devinf12)
{
	setup_testbed(NULL);
	/* The following string has been sent by a SE P1i */
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/OMA-TS-SyncML_RepPro_DTD-V1_2.dtd\"><SyncML xmlns=\"syncml:SYNCML1.2\"><SyncHdr><VerDTD>1.2</VerDTD><VerProto>SyncML/1.2</VerProto><SessionID>9284</SessionID><MsgID>1</MsgID><Target><LocURI>http://192.168.1.102:8080</LocURI></Target><Source><LocURI>IMEI:xxxxxxxxxxxxxxx</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">10000</MaxMsgSize></Meta></SyncHdr><SyncBody><Put><CmdID>1</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+wbxml</Type></Meta><Item><Source><LocURI>./devinf12</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.2</VerDTD><Man>Sony Ericsson</Man><Mod>P1i</Mod><OEM>SymbianUK</OEM><FwV>0</FwV><SwV>Z1.0.1</SwV><HwV>1.0</HwV><DevID>IMEI:xxxxxxxxxxxxxxx</DevID><DevTyp>smartphone</DevTyp><UTC/><SupportLargeObjs/><SupportNumberOfChanges/><DataStore><SourceRef>C:Calendar</SourceRef><DisplayName>Agenda</DisplayName><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><Rx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx><Tx><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx><CTCap><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT><Property><PropName>AALARM</PropName><DataType>text</DataType></Property><Property><PropName>ATTACH</PropName><DataType>text</DataType></Property><Property><PropName>ATTENDEE</PropName><DataType>text</DataType><PropParam><ParamName>EXPECT</ParamName><DataType>text</DataType></PropParam><PropParam><ParamName>ROLE</ParamName><DataType>text</DataType></PropParam><PropParam><ParamName>RSVP</ParamName><DataType>text</DataType></PropParam><PropParam><ParamName>STATUS</ParamName><DataType>text</DataType></PropParam></Property><Property><PropName>BEGIN</PropName><DataType>text</DataType><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum></Property><Property><PropName>CATEGORIES</PropName><DataType>text</DataType></Property><Property><PropName>COMPLETED</PropName><DataType>text</DataType></Property><Property><PropName>CLASS</PropName><DataType>text</DataType><ValEnum>PUBLIC</ValEnum><ValEnum>PRIVATE</ValEnum><ValEnum>CONFIDENTIAL</ValEnum></Property><Property><PropName>DAYLIGHT</PropName><DataType>text</DataType></Property><Property><PropName>DCREATED</PropName><DataType>text</DataType></Property><Property><PropName>DESCRIPTION</PropName><DataType>text</DataType></Property><Property><PropName>DTSTART</PropName><DataType>text</DataType></Property><Property><PropName>DTEND</PropName><DataType>text</DataType></Property><Property><PropName>DUE</PropName><DataType>text</DataType></Property><Property><PropName>END</PropName><DataType>text</DataType><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum></Property><Property><PropName>EXDATE</PropName><DataType>text</DataType></Property><Property><PropName>LAST-MODIFIED</PropName><DataType>text</DataType></Property><Property><PropName>LOCATION</PropName><DataType>text</DataType></Property><Property><PropName>PRIORITY</PropName><DataType>text</DataType></Property><Property><PropName>RRULE</PropName><DataType>text</DataType></Property><Property><PropName>STATUS</PropName><DataType>text</DataType></Property><Property><PropName>SUMMARY</PropName><DataType>text</DataType></Property><Property><PropName>UID</PropName><DataType>text</DataType></Property><Property><PropName>VERSION</PropName><DataType>text</DataType><ValEnum>1.0</ValEnum></Property><Property><PropName>X-EPOCALARM</PropName><DataType>text</DataType><PropParam><ParamName>VALUE</ParamName><DataType>text</DataType><ValEnum>INLINE</ValEnum><ValEnum>URL</ValEnum></PropParam><PropParam><ParamName>ENCODING</ParamName><DataType>text</DataType><ValEnum>BASE64</ValEnum></PropParam><PropParam><ParamName>X-CONTENTTYPE</ParamName><DataType>text</DataType></PropParam></Property><Property><PropName>X-EPOCAGENDAENTRYTYPE</PropName><DataType>text</DataType><ValEnum>APPOINTMENT</ValEnum><ValEnum>ANNIVERSARY</ValEnum><ValEnum>EVENT</ValEnum><ValEnum>TODO</ValEnum><ValEnum>REMINDER</ValEnum></Property></CTCap><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>4</SyncType><SyncType>7</SyncType></SyncCap></DataStore></DevInf></Data></Item></Put><Final/></SyncBody></SyncML>";
	
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 1, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_devinf_ext)
{
	setup_testbed(NULL);
	/* The following test ensures that the parser tolerates Ext in DevInf
	 * like this one from a ticket:
	 *   <Ext>
	 *     <XNam>X-funambol-smartslow</XNam>
	 *   </Ext>
	 */

	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\"><SyncML xmlns=\"syncml:SYNCML1.1\"><SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>21</SessionID><MsgID>1</MsgID><Target><LocURI>PC Suite</LocURI></Target><Source><LocURI>IMEI:XXXX</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">10000</MaxMsgSize></Meta></SyncHdr><SyncBody><Put><CmdID>8</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+xml</Type></Meta><Item><Source><LocURI>./devinf11</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.1</VerDTD><Man>NOKIA</Man><Mod>6680</Mod><SwV>3.04.37</SwV><DevID>IMEI:XXXX</DevID><DevTyp>phone</DevTyp><SupportLargeObjs/><SupportNumberOfChanges/><DataStore><SourceRef>./C\\Systemata\\Calendar</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Rx><CTType>text/calendar</CTType><VerCT>2.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./C\\System\\\\\\Data\\Contacts.cdb</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Rx><CTType>text/vcard</CTType><VerCT>3.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>./C\\System\\Data\\Notepad.dat</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx-Pref><Rx><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx><Tx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx-Pref><Tx><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>3</SyncType><SyncType>4</SyncType><SyncType>5</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>DESCRIPTION</PropName><PropName>DTEND</PropName><PropName>DTSTART</PropName><PropName>AALARM</PropName><ParamName>TYPE</ParamName><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum><ValEnum>PRIVATE</ValEnum><ValEnum>CONFIDENTIAL</ValEnum><PropName>COMPLETED</PropName><PropName>LOCATION</PropName><PropName>DCREATED</PropName><PropName>LAST-MODIFIED</PropName><PropName>PRIORITY</PropName><PropName>STATUS</PropName><PropName>RRULE</PropName><PropName>DUE</PropName><PropName>EXDATE</PropName><PropName>X-EPOCAGENDAENTRYTYPE</PropName><CTType>text/calendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>VERSION</PropName><ValEnum>2.0</ValEnum><PropName>UID</PropName><PropName>SUMMARY</PropName><PropName>DESCRIPTION</PropName><PropName>DTEND</PropName><PropName>DTSTART</PropName><PropName>AALARM</PropName><ParamName>TYPE</ParamName><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum><ValEnum>PRIVATE</ValEnum><ValEnum>CONFIDENTIAL</ValEnum><PropName>COMPLETED</PropName><PropName>LOCATION</PropName><PropName>DCREATED</PropName><PropName>LAST-MODIFIED</PropName><PropName>PRIORITY</PropName><PropName>STATUS</PropName><PropName>RRULE</PropName><PropName>DUE</PropName><PropName>EXDATE</PropName><PropName>X-EPOCAGENDAENTRYTYPE</PropName><CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>2.1</ValEnum><PropName>REV</PropName><PropName>N</PropName><PropName>ADR</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>TEL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><ParamName>CELL</ParamName><ParamName>PAGER</ParamName><ParamName>FAX</ParamName><ParamName>VIDEO</ParamName><PropName>FN</PropName><PropName>EMAIL</PropName><ParamName>INTERNET</ParamName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>URL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>NOTE</PropName><PropName>TITLE</PropName><PropName>ORG</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>SOUND</PropName><ParamName>X-IRMC-N</ParamName><CTType>text/vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>3.0</ValEnum><PropName>REV</PropName><PropName>N</PropName><PropName>ADR</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>TEL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><ParamName>CELL</ParamName><ParamName>PAGER</ParamName><ParamName>FAX</ParamName><ParamName>VIDEO</ParamName><PropName>FN</PropName><PropName>EMAIL</PropName><ParamName>INTERNET</ParamName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>URL</PropName><ParamName>HOME</ParamName><ParamName>WORK</ParamName><PropName>NOTE</PropName><PropName>TITLE</PropName><PropName>ORG</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>SOUND</PropName><ParamName>X-IRMC-N</ParamName><CTType>text/plain</CTType></CTCap>\n<Ext>\n  <XNam>X-funambol-smartslow</XNam>\n</Ext></DevInf></Data></Item></Put><Final/></SyncBody></SyncML>";
	
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 8, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_empty_data_element)
{
	const char *data = "<SyncML><SyncHdr><VerProto>SyncML/1.2</VerProto><VerDTD>1.2</VerDTD><MsgID>1</MsgID><SessionID>1</SessionID><Target><LocURI>test</LocURI></Target><Source><LocURI>test</LocURI></Source></SyncHdr><SyncBody><Get><CmdID>2</CmdID><Item><Target><LocURI>./devinf12</LocURI></Target><Data/></Item></Get></SyncBody></SyncML>";
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));

	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);
	
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = NULL;
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 2, NULL);
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL);
	sml_fail_unless(cmd == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = TRUE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == FALSE, NULL);
	sml_fail_unless(end == FALSE, NULL);

	smlParserFree(parser);
}
END_TEST


START_TEST (xml_parser_msgref_zero)
{
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\"><SyncML xmlns=\"syncml:SYNCML1.1\"><SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>16</SessionID><MsgID>1</MsgID><Target><LocURI>PC Suite</LocURI></Target><Source><LocURI>IMEI:XXXXXXXXXXXXXXX</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">6000</MaxMsgSize></Meta></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>0</MsgRef><CmdRef>0</CmdRef><Cmd>SyncHdr</Cmd><TargetRef>/</TargetRef><SourceRef>PC Suite</SourceRef><Data>513</Data></Status><Status><CmdID>2</CmdID><MsgRef>0</MsgRef><CmdRef>1</CmdRef><Cmd>Alert</Cmd><Data>513</Data></Status><Status><CmdID>3</CmdID><MsgRef>0</MsgRef><CmdRef>2</CmdRef><Cmd>Alert</Cmd><Data>513</Data></Status><Status><CmdID>4</CmdID><MsgRef>0</MsgRef><CmdRef>3</CmdRef><Cmd>Alert</Cmd><Data>513</Data></Status><Final/></SyncBody></SyncML>"
;
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));

	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);
	
	smlHeaderFree(header);

	SmlStatus *status = NULL;
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(status->msgRef == 0, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(status->msgRef == 0, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(status->msgRef == 0, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);

	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(status->msgRef == 0, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);

	gboolean final = FALSE;
	gboolean end = FALSE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == TRUE, NULL);

	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_ctcap_property_size)
{
	setup_testbed(NULL);
	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/OMA-TS-SyncML_RepPro_DTD-V1_2.dtd\"><SyncML xmlns=\"syncml:SYNCML1.2\"><SyncHdr><VerDTD>1.2</VerDTD><VerProto>SyncML/1.2</VerProto><SessionID>42</SessionID><MsgID>1</MsgID><Target><LocURI>http://www.foo.bar</LocURI></Target><Source><LocURI>IMEI:XXXXXXXXXX</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">6000</MaxMsgSize></Meta></SyncHdr><SyncBody><Put><CmdID>1</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+wbxml</Type></Meta><Item><Source><LocURI>./devinf12</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.2</VerDTD><Man>SonyEricsson</Man><Mod>W580i</Mod><FwV>R6BC002</FwV><SwV>R6A</SwV><HwV>R5A</HwV><DevID>IMEI:XXXXXXXXXXXX</DevID><DevTyp>phone</DevTyp><UTC/><SupportLargeObjs/><DataStore><SourceRef>Contacts</SourceRef><DisplayName>Contacts</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Rx><CTType>text/vcard</CTType><VerCT>3.0</VerCT></Rx><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><CTCap><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT><Property><PropName>BDAY</PropName></Property><Property><PropName>URL</PropName><Size>120</Size></Property><Property><PropName>TITLE</PropName><Size>15</Size></Property><Property><PropName>ORG</PropName><Size>30</Size></Property><Property><PropName>EMAIL</PropName><MaxOccur>3</MaxOccur><Size>50</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>INTERNET</ValEnum></PropParam></Property><Property><PropName>ADR</PropName><MaxOccur>2</MaxOccur><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>NOTE</PropName><Size>50</Size></Property><Property><PropName>TEL</PropName><MaxOccur>5</MaxOccur><Size>80</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>CELL</ValEnum><ValEnum>HOME</ValEnum><ValEnum>FAX</ValEnum><ValEnum>WORK</ValEnum></PropParam></Property><Property><PropName>N</PropName><Size>30</Size></Property><Property><PropName>VERSION</PropName><ValEnum>2.1</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCARD</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum></Property></CTCap><CTCap><CTType>text/vcard</CTType><VerCT>3.0</VerCT><Property><PropName>BDAY</PropName></Property><Property><PropName>URL</PropName><Size>120</Size></Property><Property><PropName>TITLE</PropName><Size>15</Size></Property><Property><PropName>ORG</PropName><Size>30</Size></Property><Property><PropName>EMAIL</PropName><MaxOccur>3</MaxOccur><Size>50</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>INTERNET</ValEnum></PropParam></Property><Property><PropName>ADR</PropName><MaxOccur>2</MaxOccur><PropParam><ParamName>TYPE</ParamName><ValEnum>WORK</ValEnum><ValEnum>HOME</ValEnum></PropParam></Property><Property><PropName>NOTE</PropName><Size>50</Size></Property><Property><PropName>TEL</PropName><MaxOccur>5</MaxOccur><Size>80</Size><NoTruncate/><PropParam><ParamName>TYPE</ParamName><ValEnum>CELL</ValEnum><ValEnum>HOME</ValEnum><ValEnum>FAX</ValEnum><ValEnum>WORK</ValEnum></PropParam></Property><Property><PropName>N</PropName><Size>30</Size></Property><Property><PropName>VERSION</PropName><ValEnum>3.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCARD</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum></Property></CTCap><DSMem><MaxID>1000</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Calendar</SourceRef><DisplayName>Calendar</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT><Property><PropName>LAST-MODIFIED</PropName></Property><Property><PropName>EXDATE</PropName></Property><Property><PropName>RRULE</PropName><Size>50</Size></Property><Property><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum></Property><Property><PropName>CATEGORIES</PropName><ValEnum>VACATION</ValEnum><ValEnum>TRAVEL</ValEnum><ValEnum>PHONE CALL</ValEnum><ValEnum>MISCELLANEOUS</ValEnum><ValEnum>MEETING</ValEnum></Property><Property><PropName>AALARM</PropName></Property><Property><PropName>DALARM</PropName></Property><Property><PropName>DTEND</PropName></Property><Property><PropName>DTSTART</PropName></Property><Property><PropName>DESCRIPTION</PropName><Size>128</Size></Property><Property><PropName>LOCATION</PropName><Size>50</Size></Property><Property><PropName>SUMMARY</PropName><Size>100</Size></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VEVENT</ValEnum><ValEnum>VCALENDAR</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VEVENT</ValEnum><ValEnum>VCALENDAR</ValEnum></Property></CTCap><DSMem><MaxID>300</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Tasks</SourceRef><DisplayName>Tasks</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT><Property><PropName>LAST-MODIFIED</PropName></Property><Property><PropName>CLASS</PropName><ValEnum>PUBLIC</ValEnum></Property><Property><PropName>CATEGORIES</PropName><ValEnum>VACATION</ValEnum><ValEnum>TRAVEL</ValEnum><ValEnum>PHONE CALL</ValEnum><ValEnum>MISCELLANEOUS</ValEnum><ValEnum>MEETING</ValEnum></Property><Property><PropName>STATUS</PropName><ValEnum>COMPLETED</ValEnum><ValEnum>NEEDS ACTION</ValEnum><ValEnum>ACCEPTED</ValEnum></Property><Property><PropName>PRIORITY</PropName></Property><Property><PropName>DUE</PropName></Property><Property><PropName>COMPLETED</PropName></Property><Property><PropName>AALARM</PropName></Property><Property><PropName>DALARM</PropName></Property><Property><PropName>DESCRIPTION</PropName><Size>128</Size></Property><Property><PropName>SUMMARY</PropName><Size>100</Size></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VTODO</ValEnum></Property><Property><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VTODO</ValEnum></Property></CTCap><DSMem><MaxID>80</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Notes</SourceRef><DisplayName>Notes</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/plain</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/plain</CTType><VerCT>1.0</VerCT><Property><PropName>BODY</PropName><Size>254</Size></Property></CTCap><DSMem><MaxID>25</MaxID></DSMem><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>Bookmarks</SourceRef><DisplayName>Bookmarks</DisplayName><MaxGUIDSize>64</MaxGUIDSize><Rx-Pref><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT></Tx-Pref><CTCap><CTType>text/x-vbookmark</CTType><VerCT>1.0</VerCT><Property><PropName>X-IRMC-URL</PropName></Property><Property><PropName>URL</PropName></Property><Property><PropName>TITLE</PropName></Property><Property><PropName>BEGIN</PropName><ValEnum>VENV</ValEnum><ValEnum>VBKM</ValEnum></Property><Property><PropName>END</PropName><ValEnum>VENV</ValEnum><ValEnum>VBKM</ValEnum></Property><Property><PropName>VERSION</PropName><ValEnum>1.0</ValEnum></Property></CTCap><DSMem/><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore></DevInf></Data></Item></Put><Alert><CmdID>2</CmdID><Data>201</Data><Item><Target><LocURI>contacts</LocURI></Target><Source><LocURI>Contacts</LocURI></Source><Meta><Anchor xmlns=\"syncml:metinf\"><Last>0</Last><Next>1</Next></Anchor><MaxObjSize xmlns=\"syncml:metinf\">65535</MaxObjSize><Mem xmlns=\"syncml:metinf\"><FreeMem>65469465</FreeMem><FreeID>999</FreeID></Mem></Meta></Item></Alert><Final/></SyncBody></SyncML>";
;
	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	SmlCommand *cmd = NULL;
        sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 1, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);

	smlCommandUnref(cmd);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

START_TEST (xml_parser_ctcap11_size)
{
	setup_testbed(NULL);

	const char *data = "<?xml version=\"1.0\"?><!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\"><SyncML xmlns=\"syncml:SYNCML1.1\"><SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>1</SessionID><MsgID>1</MsgID><Target><LocURI>PC Suite</LocURI></Target><Source><LocURI>IMEI:..............</LocURI></Source><Meta><MaxMsgSize xmlns=\"syncml:metinf\">3584</MaxMsgSize></Meta></SyncHdr><SyncBody><Status><CmdID>1</CmdID><MsgRef>1</MsgRef><CmdRef>0</CmdRef><Cmd>SyncHdr</Cmd><TargetRef>/</TargetRef><SourceRef>PC Suite</SourceRef><Data>200</Data></Status><Status><CmdID>2</CmdID><MsgRef>1</MsgRef><CmdRef>1</CmdRef><Cmd>Alert</Cmd><SourceRef>Contacts</SourceRef><Data>200</Data></Status><Put><CmdID>3</CmdID><Meta><Type xmlns=\"syncml:metinf\">application/vnd.syncml-devinf+xml</Type></Meta><Item><Source><LocURI>./devinf11</LocURI></Source><Data><DevInf xmlns=\"syncml:devinf\"><VerDTD>1.1</VerDTD><Man>Nokia</Man><Mod>Nokia 6300</Mod><FwV>V 05.00\n27-04-07\nRM-217\n(c) N..</FwV><SwV>V 05.00\n27-04-07\nRM-217\n(c) N..</SwV><HwV>4001</HwV><DevID>IMEI:..............</DevID><DevTyp>phone</DevTyp><SupportLargeObjs/><SupportNumberOfChanges/><DataStore><SourceRef>/telecom/pb.vcf</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcard</CTType><VerCT>2.1</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>/telecom/cal.vcs</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Rx-Pref><Tx-Pref><CTType>text/x-vcalendar</CTType><VerCT>1.0</VerCT></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><DataStore><SourceRef>/telecom/note.txt</SourceRef><MaxGUIDSize>8</MaxGUIDSize><Rx-Pref><CTType>text/plain</CTType><VerCT/></Rx-Pref><Tx-Pref><CTType>text/plain</CTType><VerCT/></Tx-Pref><SyncCap><SyncType>1</SyncType><SyncType>2</SyncType><SyncType>4</SyncType><SyncType>6</SyncType><SyncType>7</SyncType></SyncCap></DataStore><CTCap><CTType>text/x-vcard</CTType><PropName>BEGIN</PropName><ValEnum>VCARD</ValEnum><PropName>VERSION</PropName><ValEnum>2.1</ValEnum><PropName>END</PropName><ValEnum>VCARD</ValEnum><PropName>N</PropName><PropName>FN</PropName><PropName>TEL</PropName><ParamName>PREF</ParamName><ParamName>WORK</ParamName><ParamName>HOME</ParamName><ParamName>VOICE</ParamName><ParamName>FAX</ParamName><ParamName>CELL</ParamName><PropName>NOTE</PropName><PropName>URL</PropName><PropName>EMAIL</PropName><PropName>ADR</PropName><PropName>PHOTO</PropName><PropName>BDAY</PropName><PropName>TITLE</PropName><PropName>ORG</PropName><PropName>X-NICKNAME</PropName></CTCap><CTCap><CTType>text/x-vcalendar</CTType><PropName>BEGIN</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>VERSION</PropName><ValEnum>1.0</ValEnum><PropName>END</PropName><ValEnum>VCALENDAR</ValEnum><ValEnum>VEVENT</ValEnum><ValEnum>VTODO</ValEnum><PropName>DTSTART</PropName><PropName>DTEND</PropName><PropName>SUMMARY</PropName><PropName>DESCRIPTION</PropName><PropName>DUE</PropName><PropName>AALARM</PropName><PropName>DALARM</PropName><PropName>RRULE</PropName><PropName>CATEGORIES</PropName><ParamName>SPECIAL OCCASION</ParamName><ParamName>MEETING</ParamName><ParamName>PHONE CALL</ParamName><ParamName>MISCELLANEOUS</ParamName><ParamName>REMINDER</ParamName><PropName>LOCATION</PropName><PropName>STATUS</PropName><ParamName>NEEDS ACTION</ParamName><ParamName>COMPLETED</ParamName><PropName>PRIORITY</PropName><ParamName>1</ParamName><ParamName>2</ParamName><ParamName>3</ParamName><PropName>EXDATE</PropName></CTCap><CTCap><CTType>text/plain</CTType><PropName/><DataType>chr</DataType><Size>3000</Size></CTCap></DevInf></Data></Item></Put><Alert><CmdID>4</CmdID><Data>201</Data><Item><Target><LocURI>Contacts</LocURI></Target><Source><LocURI>/telecom/pb.vcf</LocURI></Source><Meta><Anchor xmlns=\"syncml:metinf\"><Last>0</Last><Next>297</Next></Anchor></Meta></Item></Alert><Final/></SyncBody></SyncML>";

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	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 == 1, NULL);
	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);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);

	SmlCommand *cmd = NULL;	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(cmd->cmdID == 3, NULL);
	sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL);
	sml_fail_unless(cmd->private.access.item != NULL, NULL);
	
	char *buffer = NULL;
	gsize size = 0;
	sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlDevInf *devinf = smlXmlDevInfParse(buffer, size, &error);
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	g_object_unref(devinf);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlCommandUnref(cmd);
	
	gboolean final = FALSE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
}
END_TEST

/* 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)
{
	const char *data = "<SyncML>" \
			"<SyncHdr><VerDTD>1.1</VerDTD><VerProto>SyncML/1.1</VerProto><SessionID>40142</SessionID><MsgID>4</MsgID><Target><LocURI>john.doe@example.com</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>" \
				"</Item>" \
			"</Status>" \
			"<Final/>" \
			"</SyncBody>" \
			"</SyncML>";

	/* check for valid document */

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(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", GET_ERROR_MESSAGE(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>john.doe@example.com</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>" \
			"<Final/>" \
			"</SyncBody>" \
			"</SyncML>";

	/* check for valid document */

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(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", GET_ERROR_MESSAGE(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 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>john.doe@example.com</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 */

	GError *error = NULL;
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(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", GET_ERROR_MESSAGE(error));
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);

	/* cleanup */

	smlParserFree(parser);
}
END_TEST


@SML_TESTCASE_CODE@

