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

struct {
        char *attr;
        char *value;
} query[1000];
int nquery;

char *query_string;

static void default_parsecgi_error(char *p)
{
        fprintf(stderr, "%s\n", p);
        exit(EXIT_FAILURE);
}

void (*parsecgi_error)(char *) = default_parsecgi_error;

void *cmalloc(size_t n)
{
        void *p = malloc(n);
        if (p == NULL) (*parsecgi_error)("Out of memory");
        return p;
}

char *dupstring(char *p)
{
        char *q = cmalloc(strlen(p)+1);
        strcpy(q, p);
        return q;
}

int cstrcasecmp(const char *p, const char *q)
{
        int c;

        while (!(c = toupper(*p)-toupper(*q)) && *p) {
                p++;
                q++;
        }
        return c;
}

/* translate the %NN stuff used in URLs into earthling characters */
static void decode_url(char *p)
{
        char *q = p;
        int c;

        while ((c = *p++)) {
                if (c == '+') {
                        *q++ = ' ';
                } else if (c == '%') {
                        sscanf(p, "%2x", &c);
                        *q++ = c;
                        if (*p) p++;
                        if (*p) p++;
                } else {
                        *q++ = c;
                }
        }
        *q = '\0';
}

/* translate bad characters _ to avoid quoting issues */
static void blacklist(char *p, char *q)
{
	while (*p) {
		if (strchr(q, *p)) *p = '_';
		p++;
	}
}

int main(void)
{
	char *method = getenv("REQUEST_METHOD");
	//char *type = getenv("CONTENT_TYPE");
	char *p;
	int i;

	nquery = 0;
	if (method == NULL) {
		query_string = dupstring("");
	} else if (!cstrcasecmp(method, "GET")) {
		char *qs = getenv("QUERY_STRING");
		if (qs == NULL) {
			qs = "";
		}
		query_string = dupstring(qs);
	} else if (!cstrcasecmp(method, "POST")) {
		int n;
		char *ql = getenv("CONTENT_LENGTH");
		if (ql == NULL) {
			query_string = dupstring("");
		} else {
			n = atoi(ql);
			query_string = cmalloc(n+1);
			fread(query_string, 1, n, stdin);
			query_string[n] = '\0';
		}
	} else {
		query_string = dupstring("");
	}
	for (p = strtok(query_string, "&"); p; p = strtok(NULL, "&")) {
		query[nquery++].attr = p;
	}
	for (i = 0; i < nquery; i++) {
		p = strchr(query[i].attr, '=');
		if (p) {
			*p = '\0';
			query[i].value = p+1;
			decode_url(query[i].value);
			blacklist(query[i].value, "'");
		} else {
			query[i].value = "";
		}
	}
	for (i = 0; i < nquery; i++) {
		printf("HTTP_%s='%s'\n", query[i].attr, query[i].value);
	}
	return 0;
}

