/*
 *
 *  OBEX library with GLib integration
 *
 *  Copyright (C) 2011  Intel Corporation. All rights reserved.
 *
 *  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 <string.h>

#include "gobex-header.h"
#include "gobex-debug.h"

/* Header types */
#define G_OBEX_HDR_ENC_UNICODE	(0 << 6)
#define G_OBEX_HDR_ENC_BYTES	(1 << 6)
#define G_OBEX_HDR_ENC_UINT8	(2 << 6)
#define G_OBEX_HDR_ENC_UINT32	(3 << 6)

#define G_OBEX_HDR_ENC(id)	((id) & 0xc0)

struct _GObexHeader {
	guint8 id;
	gboolean extdata;
	gsize vlen;			/* Length of value */
	gsize hlen;			/* Length of full encoded header */
	union {
		char *string;		/* UTF-8 converted from UTF-16 */
		guint8 *data;		/* Own buffer */
		const guint8 *extdata;	/* Reference to external buffer */
		guint8 u8;
		guint32 u32;
	} v;
};

static glong utf8_to_utf16(gunichar2 **utf16, const char *utf8) {
	glong utf16_len;
	int i;

	if (*utf8 == '\0') {
		*utf16 = NULL;
		return 0;
	}

	*utf16 = g_utf8_to_utf16(utf8, -1, NULL, &utf16_len, NULL);
	if (*utf16 == NULL)
		return -1;

	/* g_utf8_to_utf16 produces host-byteorder UTF-16,
	 * but OBEX requires network byteorder (big endian) */
	for (i = 0; i < utf16_len; i++)
		(*utf16)[i] = g_htons((*utf16)[i]);

	utf16_len = (utf16_len + 1) << 1;

	return utf16_len;
}

static guint8 *put_bytes(guint8 *to, const void *from, gsize count)
{
	memcpy(to, from, count);
	return (to + count);
}

static const guint8 *get_bytes(void *to, const guint8 *from, gsize count)
{
	memcpy(to, from, count);
	return (from + count);
}

gssize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len)
{
	guint8 *ptr = buf;
	guint16 u16;
	guint32 u32;
	gunichar2 *utf16;
	glong utf16_len;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	if (buf_len < header->hlen)
		return -1;

	ptr = put_bytes(ptr, &header->id, sizeof(header->id));

	switch (G_OBEX_HDR_ENC(header->id)) {
	case G_OBEX_HDR_ENC_UNICODE:
		utf16_len = utf8_to_utf16(&utf16, header->v.string);
		if (utf16_len < 0 || (guint16) utf16_len > buf_len)
			return -1;
		g_assert_cmpuint(utf16_len + 3, ==, header->hlen);
		u16 = g_htons(utf16_len + 3);
		ptr = put_bytes(ptr, &u16, sizeof(u16));
		put_bytes(ptr, utf16, utf16_len);
		g_free(utf16);
		break;
	case G_OBEX_HDR_ENC_BYTES:
		u16 = g_htons(header->hlen);
		ptr = put_bytes(ptr, &u16, sizeof(u16));
		if (header->extdata)
			put_bytes(ptr, header->v.extdata, header->vlen);
		else
			put_bytes(ptr, header->v.data, header->vlen);
		break;
	case G_OBEX_HDR_ENC_UINT8:
		*ptr = header->v.u8;
		break;
	case G_OBEX_HDR_ENC_UINT32:
		u32 = g_htonl(header->v.u32);
		put_bytes(ptr, &u32, sizeof(u32));
		break;
	default:
		g_assert_not_reached();
	}

	return header->hlen;
}

GObexHeader *g_obex_header_decode(const void *data, gsize len,
				GObexDataPolicy data_policy, gsize *parsed,
				GError **err)
{
	GObexHeader *header;
	const guint8 *ptr = data;
	guint16 hdr_len;
	gsize str_len;
	GError *conv_err = NULL;

	if (len < 2) {
		if (!err)
			return NULL;
		g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
						"Too short header in packet");
		g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
		return NULL;
	}

	header = g_new0(GObexHeader, 1);

	ptr = get_bytes(&header->id, ptr, sizeof(header->id));

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	switch (G_OBEX_HDR_ENC(header->id)) {
	case G_OBEX_HDR_ENC_UNICODE:
		if (len < 3) {
			g_set_error(err, G_OBEX_ERROR,
				G_OBEX_ERROR_PARSE_ERROR,
				"Not enough data for unicode header (0x%02x)",
				header->id);
			goto failed;
		}
		ptr = get_bytes(&hdr_len, ptr, sizeof(hdr_len));
		hdr_len = g_ntohs(hdr_len);

		if (hdr_len == 3) {
			header->v.string = g_strdup("");
			header->vlen = 0;
			header->hlen = hdr_len;
			*parsed = hdr_len;
			break;
		}

		if (hdr_len > len || hdr_len < 5) {
			g_set_error(err, G_OBEX_ERROR,
				G_OBEX_ERROR_PARSE_ERROR,
				"Invalid unicode header (0x%02x) length (%u)",
				header->id, hdr_len);
			goto failed;
		}

		header->v.string = g_convert((const char *) ptr, hdr_len - 5,
						"UTF-8", "UTF-16BE",
						NULL, &str_len, &conv_err);
		if (header->v.string == NULL) {
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_PARSE_ERROR,
					"Unicode conversion failed: %s",
					conv_err->message);
			g_error_free(conv_err);
			goto failed;
		}

		header->vlen = (gsize) str_len;
		header->hlen = hdr_len;

		*parsed = hdr_len;

		break;
	case G_OBEX_HDR_ENC_BYTES:
		if (len < 3) {
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_PARSE_ERROR,
					"Too short byte array header");
			goto failed;
		}
		ptr = get_bytes(&hdr_len, ptr, sizeof(hdr_len));
		hdr_len = g_ntohs(hdr_len);
		if (hdr_len > len) {
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_PARSE_ERROR,
					"Too long byte array header");
			goto failed;
		}

		if (hdr_len < 3) {
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_PARSE_ERROR,
					"Too small byte array length");
			goto failed;
		}

		header->vlen = hdr_len - 3;
		header->hlen = hdr_len;

		switch (data_policy) {
		case G_OBEX_DATA_COPY:
			header->v.data = g_memdup(ptr, header->vlen);
			break;
		case G_OBEX_DATA_REF:
			header->extdata = TRUE;
			header->v.extdata = ptr;
			break;
		default:
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_INVALID_ARGS,
					"Invalid data policy");
			goto failed;
		}

		*parsed = hdr_len;

		break;
	case G_OBEX_HDR_ENC_UINT8:
		header->vlen = 1;
		header->hlen = 2;
		header->v.u8 = *ptr;
		*parsed = 2;
		break;
	case G_OBEX_HDR_ENC_UINT32:
		if (len < 5) {
			g_set_error(err, G_OBEX_ERROR,
					G_OBEX_ERROR_PARSE_ERROR,
					"Too short uint32 header");
			goto failed;
		}
		header->vlen = 4;
		header->hlen = 5;
		get_bytes(&header->v.u32, ptr, sizeof(header->v.u32));
		header->v.u32 = g_ntohl(header->v.u32);
		*parsed = 5;
		break;
	default:
		g_assert_not_reached();
	}

	return header;

failed:
	if (*err)
		g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
	g_obex_header_free(header);
	return NULL;
}

void g_obex_header_free(GObexHeader *header)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	switch (G_OBEX_HDR_ENC(header->id)) {
	case G_OBEX_HDR_ENC_UNICODE:
		g_free(header->v.string);
		break;
	case G_OBEX_HDR_ENC_BYTES:
		if (!header->extdata)
			g_free(header->v.data);
		break;
	case G_OBEX_HDR_ENC_UINT8:
	case G_OBEX_HDR_ENC_UINT32:
		break;
	default:
		g_assert_not_reached();
	}

	g_free(header);
}

gboolean g_obex_header_get_unicode(GObexHeader *header, const char **str)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	if (G_OBEX_HDR_ENC(header->id) != G_OBEX_HDR_ENC_UNICODE)
		return FALSE;

	*str = header->v.string;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%s", *str);

	return TRUE;
}

gboolean g_obex_header_get_bytes(GObexHeader *header, const guint8 **val,
								gsize *len)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	if (G_OBEX_HDR_ENC(header->id) != G_OBEX_HDR_ENC_BYTES)
		return FALSE;

	*len = header->vlen;

	if (header->extdata)
		*val = header->v.extdata;
	else
		*val = header->v.data;

	return TRUE;
}

GObexApparam *g_obex_header_get_apparam(GObexHeader *header)
{
	gboolean ret;
	const guint8 *val;
	gsize len;

	ret = g_obex_header_get_bytes(header, &val, &len);
	if (!ret)
		return NULL;

	return g_obex_apparam_decode(val, len);
}

gboolean g_obex_header_get_uint8(GObexHeader *header, guint8 *val)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	if (G_OBEX_HDR_ENC(header->id) != G_OBEX_HDR_ENC_UINT8)
		return FALSE;

	*val = header->v.u8;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%u", *val);

	return TRUE;
}

gboolean g_obex_header_get_uint32(GObexHeader *header, guint32 *val)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x",
						G_OBEX_HDR_ENC(header->id));

	if (G_OBEX_HDR_ENC(header->id) != G_OBEX_HDR_ENC_UINT32)
		return FALSE;

	*val = header->v.u32;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%u", *val);

	return TRUE;
}

GObexHeader *g_obex_header_new_unicode(guint8 id, const char *str)
{
	GObexHeader *header;
	gsize len;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x", G_OBEX_HDR_ENC(id));

	if (G_OBEX_HDR_ENC(id) != G_OBEX_HDR_ENC_UNICODE)
		return NULL;

	header = g_new0(GObexHeader, 1);

	header->id = id;

	len = g_utf8_strlen(str, -1);

	header->vlen = len;
	header->hlen = len == 0 ? 3 : 3 + ((len + 1) * 2);
	header->v.string = g_strdup(str);

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%s", header->v.string);

	return header;
}

GObexHeader *g_obex_header_new_bytes(guint8 id, const void *data, gsize len)
{
	GObexHeader *header;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x", G_OBEX_HDR_ENC(id));

	if (G_OBEX_HDR_ENC(id) != G_OBEX_HDR_ENC_BYTES)
		return NULL;

	header = g_new0(GObexHeader, 1);

	header->id = id;
	header->vlen = len;
	header->hlen = len + 3;
	header->v.data = g_memdup(data, len);

	return header;
}

GObexHeader *g_obex_header_new_tag(guint8 id, GObexApparam *apparam)
{
	guint8 buf[1024];
	gssize len;

	len = g_obex_apparam_encode(apparam, buf, sizeof(buf));
	if (len < 0)
		return NULL;

	return g_obex_header_new_bytes(id, buf, len);
}

GObexHeader *g_obex_header_new_apparam(GObexApparam *apparam)
{
	return g_obex_header_new_tag(G_OBEX_HDR_APPARAM, apparam);
}

GObexHeader *g_obex_header_new_uint8(guint8 id, guint8 val)
{
	GObexHeader *header;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x", G_OBEX_HDR_ENC(id));

	if (G_OBEX_HDR_ENC(id) != G_OBEX_HDR_ENC_UINT8)
		return NULL;

	header = g_new0(GObexHeader, 1);

	header->id = id;
	header->vlen = 1;
	header->hlen = 2;
	header->v.u8 = val;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%u", header->v.u8);

	return header;
}

GObexHeader *g_obex_header_new_uint32(guint8 id, guint32 val)
{
	GObexHeader *header;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x", G_OBEX_HDR_ENC(id));

	if (G_OBEX_HDR_ENC(id) != G_OBEX_HDR_ENC_UINT32)
		return NULL;

	header = g_new0(GObexHeader, 1);

	header->id = id;
	header->vlen = 4;
	header->hlen = 5;
	header->v.u32 = val;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "%u", header->v.u32);

	return header;
}

guint8 g_obex_header_get_id(GObexHeader *header)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x id 0x%02x",
				G_OBEX_HDR_ENC(header->id), header->id);

	return header->id;
}

guint16 g_obex_header_get_length(GObexHeader *header)
{
	g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x length %zu",
				G_OBEX_HDR_ENC(header->id), header->hlen);

	return header->hlen;
}

GSList *g_obex_header_create_list(guint8 first_hdr_id, va_list args,
							gsize *total_len)
{
	unsigned int id = first_hdr_id;
	GSList *l = NULL;

	g_obex_debug(G_OBEX_DEBUG_HEADER, "");

	*total_len = 0;

	while (id != G_OBEX_HDR_INVALID) {
		GObexHeader *hdr;
		const char *str;
		const void *bytes;
		unsigned int val;
		gsize len;

		switch (G_OBEX_HDR_ENC(id)) {
		case G_OBEX_HDR_ENC_UNICODE:
			str = va_arg(args, const char *);
			hdr = g_obex_header_new_unicode(id, str);
			break;
		case G_OBEX_HDR_ENC_BYTES:
			bytes = va_arg(args, void *);
			len = va_arg(args, gsize);
			hdr = g_obex_header_new_bytes(id, bytes, len);
			break;
		case G_OBEX_HDR_ENC_UINT8:
			val = va_arg(args, unsigned int);
			hdr = g_obex_header_new_uint8(id, val);
			break;
		case G_OBEX_HDR_ENC_UINT32:
			val = va_arg(args, unsigned int);
			hdr = g_obex_header_new_uint32(id, val);
			break;
		default:
			g_assert_not_reached();
		}

		l = g_slist_append(l, hdr);
		*total_len += hdr->hlen;
		id = va_arg(args, int);
	}

	return l;
}
