/*******************************************************************************/
/*                                                                             */
/*  Copyright 2005 Pascal Gloor <pascal.gloor@spale.com>                       */
/*                                                                             */
/*  Licensed under the Apache License, Version 2.0 (the "License");            */
/*  you may not use this file except in compliance with the License.           */
/*  You may obtain a copy of the License at                                    */
/*                                                                             */
/*     http://www.apache.org/licenses/LICENSE-2.0                              */
/*                                                                             */
/*  Unless required by applicable law or agreed to in writing, software        */
/*  distributed under the License is distributed on an "AS IS" BASIS,          */
/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/*  See the License for the specific language governing permissions and        */
/*  limitations under the License.                                             */
/*                                                                             */
/*******************************************************************************/

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

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <assert.h>

#include "user.h"
#include "internal.h"
#include "errors.h"

#ifndef __FILE__
#define __FILE__ unknown_file
#endif

#ifndef __LINE__
#define __LINE__ unknown_line
#endif


#define DEFAULT_MAX_LEN 1048576

CGI_CTX *CGI_Init(void)
{
	CGI_CTX *ctx;
	if ( ( ctx = malloc(sizeof(CGI_CTX)) ) == NULL )
		Error(__FILE__, __LINE__, 1, "malloc failed");

	memset(ctx, 0, sizeof(CGI_CTX));

	return ctx;
}

struct sockaddr_in *CGI_Peer(CGI_CTX *ctx)
{
	assert(ctx!=NULL);

	return &ctx->peer;
}

int CGI_Parse(CGI_CTX *ctx, const int flags, size_t maxlen)
{
	char *peer;
	char *port;

	assert(ctx!=NULL);

	peer = getenv("REMOTE_ADDR");
	port = getenv("REMOTE_PORT");

	if ( peer != NULL )
		ctx->peer.sin_addr.s_addr = inet_addr(peer);

	if ( port != NULL )
		ctx->peer.sin_port = htons(atoi(port));

	ctx->peer.sin_family = AF_INET;

	if ( maxlen > 0 )
		ctx->max_len = maxlen;
	else
		ctx->max_len = DEFAULT_MAX_LEN;

	if ( !flags || (flags & CGI_GET_ONLY) )
		__parseget(ctx);

	if ( !flags || (flags & CGI_POST_ONLY) )
		__parsepost(ctx);

	return ctx->var_num;
}

void CGI_FirstVar(CGI_CTX *ctx)
{
	assert(ctx!=NULL);
	ctx->cur_var = 0;
}

CGI_VAR *CGI_NextVar(CGI_CTX *ctx)
{
	assert(ctx!=NULL);

	if ( ctx->cur_var >= ctx->var_num )
		return NULL;

	ctx->cur_var++;

	return ctx->var[ctx->cur_var-1];
}

CGI_VAR *CGI_FindVar(CGI_CTX *ctx, char *name)
{
	int i;
	size_t len;

	assert(ctx!=NULL);

	len = strlen(name);

	for(i=0; i<CGI_MAX_VARS; i++)
	{
		if ( ctx->var[i] == NULL )
			break;

		if ( strlen(ctx->var[i]->name) != len )
			continue;

		if ( memcmp(ctx->var[i]->name, name, len) == 0 )
		{
			return ctx->var[i];
		}
	}

	return NULL;
}

void CGI_End(CGI_CTX *ctx)
{
	int i;

	if ( ctx == NULL )
		return;

	if ( ctx->qs != NULL )
		free(ctx->qs);

	if ( ctx->ct != NULL )
		free(ctx->ct);

	if ( ctx->buffer != NULL )
		free(ctx->buffer);

	for(i=0; i<CGI_MAX_VARS; i++)
	{
		if ( ctx->var[i] != NULL )
			free(ctx->var[i]);
	}

	free(ctx);
}