/*-
 * Copyright 2003 John-Mark Gurney.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$Id: mimemisc.c,v 1.2 2003/09/15 23:37:19 jmg Exp $
 *
 */

#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include <mimemisc_priv.h>

struct attrib *
attrib_create(void)
{
	struct attrib *ret;

	ret = malloc(sizeof *ret);

	ret->a_n = 0;
	ret->a_alloc = 0;
	ret->a_name = NULL;
	ret->a_value = NULL;

	return ret;
}

void
attrib_add(struct attrib *a, const char *name, const char *value)
{
	attrib_addnodup(a, strdup(name), strdup(value));
}

void
attrib_addnodup(struct attrib *a, char *name, char *value)
{
	if (a->a_n + 1 >= a->a_alloc) {
		a->a_alloc = 2 * (a->a_alloc == 0 ? 4 : a->a_alloc);
		a->a_name = realloc(a->a_name, a->a_alloc * sizeof *a->a_name);
		a->a_value = realloc(a->a_value,
		    a->a_alloc * sizeof *a->a_value);
	}
	a->a_name[a->a_n] = name;
	a->a_value[a->a_n] = value;
	a->a_n++;
}

const char *
attrib_get(struct attrib *a, const char *name, int *cnt)
{
	int i;

	for (i = cnt == NULL ? 0 : *cnt; i < a->a_n; i++)
		if (strcasecmp(name, a->a_name[i]) == 0) {
			if (cnt != NULL)
				*cnt = i;
			return a->a_value[i];
		}

	return NULL;
}

void
attrib_free(struct attrib *a)
{
	int i;

	for (i = 0; i < a->a_n; i++) {
		free(a->a_name[i]);
		free(a->a_value[i]);
	}

	free(a->a_name);
	free(a->a_value);
	free(a);
}

char *
bd_makenorm(const char *bd, const char *crlfpair)
{
	char *ret;

	ret = malloc(strlen(bd) + strlen(crlfpair) * 2 + 3);

	strcpy(ret, crlfpair);
	strcat(ret, "--");
	strcat(ret, bd);
	strcat(ret, crlfpair);

	return ret;
}

char *
bd_maketail(const char *bd, const char *crlfpair)
{
	char *ret;

	ret = malloc(strlen(bd) + strlen(crlfpair) * 2 + 5);

	strcpy(ret, crlfpair);
	strcat(ret, "--");
	strcat(ret, bd);
	strcat(ret, "--");
	strcat(ret, crlfpair);

	return ret;
}

static char *
getquotedstring(const char *qstr, const char **end)
{
	int n;
	char *spc;
	int len;
	int alloc;

	if (*qstr != '"') {
		n = strspn(qstr, "!#$%&'*+-.0123456789?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~");
		spc = malloc(sizeof *spc * (n + 1));
		strncpy(spc, qstr, n);
		spc[n] = '\0';

		*end = qstr + n;
		
		return spc;
	}

	spc = malloc((alloc = 64));
	len = 0;
	spc[0] = '\0';

	qstr++;

	for (;;) {
		if (*qstr == '\\') {
			spc[len++] = *++qstr;
			qstr++;
		} else if (*qstr == '\n') {
			spc[len++] = *++qstr;
			qstr++;
		} else if (*qstr == '"')
			break;
		else
			spc[len++] = *qstr++;
		if (len >= alloc)
			spc = realloc(spc, (alloc *= 2));
	}

	spc[len] = '\0';

	*end = ++qstr;

	return spc;
}

static int
addparameter(struct attrib *a, const char **ctr)
{
	const char *ct;
	char *eq;
	char *name;
	char *value;

	ct = *ctr;

	if ((ct = strchr(ct, ';')) == NULL)
		return 0;

	ct++;
	while (isspace(*ct))
		ct++;

	if ((eq = strchr(ct, '=')) == NULL)
		return 0;

	name = malloc(sizeof *name * (eq - ct + 1));
	strncpy(name, ct, eq - ct);
	name[eq - ct] = '\0';

	ct = eq + 1;
	value = getquotedstring(ct, &ct);

	attrib_addnodup(a, name, value);

	*ctr = ct;

	return 1;
}

struct attrib *
mime_getattrib(const char *ct)
{
	struct attrib *ret;

	ret = attrib_create();

	while (addparameter(ret, &ct));

	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1