/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2005-2007  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>

#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

#include <expat.h>

#include "logging.h"
#include "sdp-xml.h"

static int compute_seq_size(sdp_data_t *data)
{
	int unit_size = data->unitSize;
	sdp_data_t *seq = data->val.dataseq;

	for (; seq; seq = seq->next)
		unit_size += seq->unitSize;

	return unit_size;
}

/* Expat specific implementation of the context struct */

struct sdp_xml_context {
	XML_Parser parser;			/* Parser object being used */
	sdp_record_t *sdprec;			/* SDP Record being built */
	struct sdp_xml_data *stack_head;	/* Top of the stack of attributes */
	int attrId;				/* Id of the most recently processed attribute */
};

static void convert_xml_to_sdp_start(void *data, const char *el, const char **attr)
{
	struct sdp_xml_context *context = data;
	int i;

	if (!strcmp(el, "record"))
		return;

	if (!strcmp(el, "attribute")) {
		/* Get the ID */
		for (i = 0; attr[i]; i += 1) {
			if (!strcmp(attr[i], "id")) {
				context->attrId = strtol(attr[i + 1], 0, 0);
				break;
			}
		}

		return;
	}

	/* Assume every other tag is an element of some sort */
	if (context->stack_head) {
		struct sdp_xml_data *newelem = sdp_xml_data_alloc();
		newelem->next = context->stack_head;
		context->stack_head = newelem;
	} else {
		context->stack_head = sdp_xml_data_alloc();
		context->stack_head->next = NULL;
	}

	if (!strcmp(el, "sequence"))
		context->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
	else if (!strcmp(el, "alternate"))
		context->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
	else {
		/* Parse value, name, encoding */
		for (i = 0; attr[i]; i += 2) {
			if (!strcmp(attr[i], "value")) {
				int curlen = strlen(context->stack_head->text);
				int attrlen = strlen(attr[i + 1]);

				/* Ensure we're big enough */
				while ((curlen + 1 + attrlen) > context->stack_head->size) {
					sdp_xml_data_expand(context->stack_head);
				}

				memcpy(&context->stack_head->text[curlen],
							attr[i + 1], attrlen);
				context->stack_head->text[curlen + attrlen] = '\0';
			}

			if (!strcmp(attr[i], "encoding")) {
				if (!strcmp(attr[i + 1], "hex"))
					context->stack_head->type = 1;
			}

			if (!strcmp(attr[i], "name")) {
				context->stack_head->name = strdup(attr[i + 1]);
			}
		}

		context->stack_head->data = sdp_xml_parse_datatype(el, context->stack_head);

		/* Could not parse an entry */
		if (context->stack_head->data == NULL)
			XML_StopParser(context->parser, 0);
	}
}

static void convert_xml_to_sdp_end(void *data, const char *el)
{
	struct sdp_xml_context *context = data;
	struct sdp_xml_data *elem;

	if (!strcmp(el, "record"))
		return;

	if (!strcmp(el, "attribute")) {
		if (context->stack_head && context->stack_head->data) {
			int ret = sdp_attr_add(context->sdprec, context->attrId,
							context->stack_head->data);
			if (ret == -1)
				debug("Trouble adding attribute\n");

			context->stack_head->data = NULL;
			sdp_xml_data_free(context->stack_head);
			context->stack_head = NULL;
		} else {
			debug("No Data for attribute: %d\n", context->attrId);
		}

		return;
	} else if (!strcmp(el, "sequence")) {
		context->stack_head->data->unitSize = compute_seq_size(context->stack_head->data);

		if (context->stack_head->data->unitSize > USHRT_MAX) {
			context->stack_head->data->unitSize += sizeof(uint32_t);
			context->stack_head->data->dtd = SDP_SEQ32;
		} else if (context->stack_head->data->unitSize > UCHAR_MAX) {
			context->stack_head->data->unitSize += sizeof(uint16_t);
			context->stack_head->data->dtd = SDP_SEQ16;
		} else {
			context->stack_head->data->unitSize += sizeof(uint8_t);
		}
	} else if (!strcmp(el, "alternate")) {
		context->stack_head->data->unitSize = compute_seq_size(context->stack_head->data);

		if (context->stack_head->data->unitSize > USHRT_MAX) {
			context->stack_head->data->unitSize += sizeof(uint32_t);
			context->stack_head->data->dtd = SDP_ALT32;
		} else if (context->stack_head->data->unitSize > UCHAR_MAX) {
			context->stack_head->data->unitSize += sizeof(uint16_t);
			context->stack_head->data->dtd = SDP_ALT16;
		} else {
			context->stack_head->data->unitSize += sizeof(uint8_t);
		}
	}

	/* If we're not inside a seq or alt, then we're inside an attribute
	   which will be taken care of later
	 */
	if (context->stack_head->next && context->stack_head->data &&
					context->stack_head->next->data) {
		switch (context->stack_head->next->data->dtd) {
		case SDP_SEQ8:
		case SDP_SEQ16:
		case SDP_SEQ32:
		case SDP_ALT8:
		case SDP_ALT16:
		case SDP_ALT32:
			context->stack_head->next->data->val.dataseq =
				sdp_seq_append(context->stack_head->next->data->val.dataseq,
								context->stack_head->data);
			context->stack_head->data = NULL;
			break;
		}

		elem = context->stack_head;
		context->stack_head = context->stack_head->next;

		sdp_xml_data_free(elem);
	}
}

static struct sdp_xml_context *sdp_xml_init_context()
{
	struct sdp_xml_context *context;

	context = malloc(sizeof(struct sdp_xml_context));

	if (!context)
		return NULL;

	context->parser = 0;
	context->sdprec = 0;
	context->stack_head = 0;

	context->parser = XML_ParserCreate(NULL);
	XML_SetElementHandler(context->parser, convert_xml_to_sdp_start,
						convert_xml_to_sdp_end);
	XML_SetUserData(context->parser, context);

	if (!context->parser)
		goto fail;

	context->sdprec = sdp_record_alloc();

	if (!context->sdprec)
		goto fail;

	return context;

fail:
	if (context->parser)
		free(context->parser);

	if (context->sdprec)
		sdp_record_free(context->sdprec);

	if (context)
		free(context);

	return NULL;
}

static void sdp_xml_free_context(struct sdp_xml_context *context)
{
	struct sdp_xml_data *elem;

	/* Free the stack */
	while (context->stack_head) {
		elem = context->stack_head;
		context->stack_head = elem->next;
		sdp_xml_data_free(elem);
	}

	XML_ParserFree(context->parser);

	free(context);
}

static int sdp_xml_parse_chunk(struct sdp_xml_context *context,
					const char *data, int size, int final)
{
	if (!XML_Parse(context->parser, data, size, final)) {
		error("Parse error at line %d: %s\n",
			XML_GetCurrentLineNumber(context->parser),
			XML_ErrorString(XML_GetErrorCode(context->parser)));
		return -1;
	}

	return 0;
}

sdp_record_t *sdp_xml_parse_record(const char *data, int size)
{
	struct sdp_xml_context *context;
	sdp_record_t *record;

	context = sdp_xml_init_context();

	if (sdp_xml_parse_chunk(context, data, size, 1) < 0) {
		sdp_record_free(context->sdprec);
		sdp_xml_free_context(context);
		return NULL;
	}

	record = context->sdprec;

	sdp_xml_free_context(context);

	return record;
}
