/*
 *
 *  Multimedia Messaging Service
 *
 *  Copyright (C) 2010-2011  Intel Corporation. All rights reserved.
 *  Copyright (C) 2013-2014  Jolla Ltd.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  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
 *
 */

#ifndef WSPUTIL_H
#define WSPUTIL_H

enum wsp_header_iter_flag {
	WSP_HEADER_ITER_FLAG_REJECT_CP =		0x1,
	WSP_HEADER_ITER_FLAG_DETECT_MMS_MULTIPART =	0x2,
	WSP_HEADER_ITER_FLAG_DETECT_MULTIPART =		0x4,
};

enum wsp_header_type {
	WSP_HEADER_TYPE_WELL_KNOWN,
	WSP_HEADER_TYPE_APPLICATION
};

enum wsp_value_type {
	WSP_VALUE_TYPE_LONG,
	WSP_VALUE_TYPE_SHORT,
	WSP_VALUE_TYPE_TEXT,
};

enum wsp_header_token {
	WSP_HEADER_TOKEN_APP_ID =	0x2F,
};

enum wsp_parameter_type {
	WSP_PARAMETER_TYPE_Q =				0x00,
	WSP_PARAMETER_TYPE_CHARSET =			0x01,
	WSP_PARAMETER_TYPE_LEVEL =			0x02,
	WSP_PARAMETER_TYPE_TYPE =			0x03,
	WSP_PARAMETER_TYPE_NAME_DEFUNCT =		0x05,
	WSP_PARAMETER_TYPE_FILENAME_DEFUNCT =		0x06,
	WSP_PARAMETER_TYPE_DIFFERENCES =		0x07,
	WSP_PARAMETER_TYPE_PADDING =			0x08,
	WSP_PARAMETER_TYPE_CONTENT_TYPE =		0x09,
	WSP_PARAMETER_TYPE_START_DEFUNCT =		0x0A,
	WSP_PARAMETER_TYPE_START_INFO_DEFUNCT =		0x0B,
	WSP_PARAMETER_TYPE_COMMENT_DEFUNCT =		0x0C,
	WSP_PARAMETER_TYPE_DOMAIN_DEFUNCT =		0x0D,
	WSP_PARAMETER_TYPE_MAX_AGE =			0x0E,
	WSP_PARAMETER_TYPE_PATH_DEFUNCT =		0x0F,
	WSP_PARAMETER_TYPE_SECURE =			0x10,
	WSP_PARAMETER_TYPE_SEC =			0x11,
	WSP_PARAMETER_TYPE_MAC =			0x12,
	WSP_PARAMETER_TYPE_CREATION_DATE =		0x13,
	WSP_PARAMETER_TYPE_MODIFICATION_DATE =		0x14,
	WSP_PARAMETER_TYPE_READ_DATE =			0x15,
	WSP_PARAMETER_TYPE_SIZE =			0x16,
	WSP_PARAMETER_TYPE_NAME =			0x17,
	WSP_PARAMETER_TYPE_FILENAME =			0x18,
	WSP_PARAMETER_TYPE_START =			0x19,
	WSP_PARAMETER_TYPE_START_INFO =			0x1A,
	WSP_PARAMETER_TYPE_COMMENT =			0x1B,
	WSP_PARAMETER_TYPE_DOMAIN =			0x1C,
	WSP_PARAMETER_TYPE_PATH =			0x1D,
	WSP_PARAMETER_TYPE_UNTYPED =			0xFF,
};

enum wsp_parameter_value {
	WSP_PARAMETER_VALUE_TEXT,
	WSP_PARAMETER_VALUE_INT,
	WSP_PARAMETER_VALUE_DATE,
	WSP_PARAMETER_VALUE_Q,
};

struct wsp_parameter {
	enum wsp_parameter_type type;
	enum wsp_parameter_value value;
	const char *untyped;
	union {
		const char *text;
		unsigned int integer;
		time_t date;
		float q;
	};
};

struct wsp_header_iter {
	const unsigned char *pdu;
	unsigned int max;
	unsigned int pos;
	unsigned int flags;
	unsigned char code_page;
	unsigned char content_type_header;

	enum wsp_header_type header_type;
	const void *header;

	enum wsp_value_type value_type;
	const void *value;

	unsigned int len;
};

struct wsp_multipart_iter {
	const unsigned char *pdu;
	unsigned int max;
	unsigned int pos;

	const void *content_type;
	const void *headers;
	const void *body;

	unsigned int content_type_len;
	unsigned int headers_len;
	unsigned int body_len;
};

struct wsp_parameter_iter {
	const unsigned char *pdu;
	unsigned int max;
	unsigned int pos;
};

gboolean wsp_decode_uintvar(const unsigned char *pdu, unsigned int len,
				unsigned int *out_len, unsigned int *consumed);
gboolean wsp_decode_integer(const unsigned char *pdu, unsigned int len,
				unsigned int *out_val, unsigned int *consumed);
gboolean wsp_decode_field(const unsigned char *pdu, unsigned int max,
					enum wsp_value_type *out_type,
					const void **out_value,
					unsigned int *out_len,
					unsigned int *consumed);
gboolean wsp_get_well_known_content_type(const char *text,
							unsigned int *out_val);
gboolean wsp_get_well_known_charset(const char *text, unsigned int *out_val);
const char *wsp_decode_token_text(const unsigned char *pdu, unsigned int len,
					unsigned int *consumed);
const char *wsp_decode_text(const unsigned char *pdu, unsigned int len,
					unsigned int *consumed);
const char *wsp_decode_quoted_string(const unsigned char *pdu, unsigned int len,
					unsigned int *consumed);

gboolean wsp_decode_content_type(const unsigned char *pdu, unsigned int max,
					const void **out_value,
					unsigned int *out_read,
					unsigned int *out_param_len);
gboolean wsp_decode_application_id(struct wsp_header_iter *iter,
					const void **out_value);

gboolean wsp_encode_uintvar(unsigned int value, unsigned char *dest,
				unsigned int dest_size, unsigned int *written);
gboolean wsp_encode_value_length(unsigned int len, unsigned char *dest,
				unsigned int dest_size, unsigned int *written);
gboolean wsp_encode_integer(unsigned int value, unsigned char *dest,
				unsigned int dest_size, unsigned int *written);

void wsp_header_iter_init(struct wsp_header_iter *iter,
				const unsigned char *pdu, unsigned int len,
				unsigned int flags);
gboolean wsp_header_iter_next(struct wsp_header_iter *iter);
unsigned char wsp_header_iter_get_code_page(struct wsp_header_iter *iter);

gboolean wsp_header_iter_at_end(struct wsp_header_iter *iter);
gboolean wsp_header_iter_is_content_type(struct wsp_header_iter *iter);
gboolean wsp_header_iter_is_multipart(struct wsp_header_iter *iter);

enum wsp_header_type wsp_header_iter_get_hdr_type(struct wsp_header_iter *iter);
const unsigned char *wsp_header_iter_get_pdu(struct wsp_header_iter *iter);
const void *wsp_header_iter_get_hdr(struct wsp_header_iter *iter);
enum wsp_value_type wsp_header_iter_get_val_type(struct wsp_header_iter *iter);
const void *wsp_header_iter_get_val(struct wsp_header_iter *iter);
unsigned int wsp_header_iter_get_val_len(struct wsp_header_iter *iter);

gboolean wsp_multipart_iter_init(struct wsp_multipart_iter *mi,
					struct wsp_header_iter *hi,
					const void **out_content_type,
					unsigned int *out_content_type_len);
gboolean wsp_multipart_iter_next(struct wsp_multipart_iter *mi);
const void *wsp_multipart_iter_get_content_type(struct wsp_multipart_iter *mi);
unsigned int wsp_multipart_iter_get_content_type_len(
						struct wsp_multipart_iter *mi);
const void *wsp_multipart_iter_get_hdr(struct wsp_multipart_iter *mi);
unsigned int wsp_multipart_iter_get_hdr_len(struct wsp_multipart_iter *mi);
const void *wsp_multipart_iter_get_body(struct wsp_multipart_iter *mi);
unsigned int wsp_multipart_iter_get_body_len(struct wsp_multipart_iter *mi);
gboolean wsp_multipart_iter_close(struct wsp_multipart_iter *mi,
					struct wsp_header_iter *hi);

void wsp_parameter_iter_init(struct wsp_parameter_iter *pi,
				const unsigned char *pdu, unsigned int len);
gboolean wsp_parameter_iter_next(struct wsp_parameter_iter *pi,
					struct wsp_parameter *out_param);

#endif /* WSPUTIL_H */
