/*
 *		   Supports C routines for doing 
 *		   CGI with the f2c translator.
 *		----------------------------------
 *		Thierry Boudet
 *			101355.2112@compuserve.com
 *		----------------------------------
 */

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

/*----------------------------------------------------------*/
/*
 *	privates variables of this module
 */
#define MAXI_QUERIES	40
typedef struct
	{
	char	*name;
	char	*content;
	} ONE_QUERY;

static ONE_QUERY	queries[MAXI_QUERIES];
static int		nbre_queries;
static char		*p_query_string;

/*----------------------------------------------------------*/
int	get_env__(char *nom, char *ou, long l_nom, long l_ou)
{
char	*env, c;
char	*local_nom, *ptr;
int	foo;

if ( l_nom<1 || l_nom>1000 )
	return 0;
 
if ( (local_nom=malloc(l_nom+1))==NULL )
	return 0;

for (foo=0, ptr=local_nom; foo<l_nom; foo++)
	{
	if ( (c=nom[foo])==' ' )
		{
		*ptr++ = '\0';
		break;
		}
	*ptr++ = c;
	}
*ptr = '\0';

if ( (env=getenv(local_nom)) == NULL )
	foo = 0;
else
	{
	strncpy(ou, env, l_ou);
	for (foo=0; foo<l_ou; foo++)
		if (! ou[foo]) ou[foo]=' ';
	foo = 1;
	fprintf(stderr, "trouve : %s\n", env);
	}
free(local_nom);
return foo;
}
/*----------------------------------------------------------*/
static char x2c(const char *what) {
    register char digit;

    digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
    return(digit);
}

/*
 * Unescapes a URL.
 * Returns 0 on success, non-zero on error
 * Failure is due to
 *   bad % escape       returns BAD_REQUEST
 *
 *   decoding %00 -> \0
 *   decoding %2f -> /   (a special character)
 *                      returns NOT_FOUND
 */
#define BAD_REQUEST	-1
#define NOT_FOUND	-2
#define OK		0
static int unescape_url(char *url) {
    register int x,y, badesc, badpath;

    badesc = 0;
    badpath = 0;
    for(x=0,y=0;url[y];++x,++y) {
	if (url[y] != '%') url[x] = url[y];
	else
	{
	    if (!isxdigit(url[y+1]) || !isxdigit(url[y+2]))
	    {
		badesc = 1;
		url[x] = '%';
	    } else
	    {
		url[x] = x2c(&url[y+1]);
		y += 2;
		if (url[x] == '/' || url[x] == '\0') badpath = 1;
	    }
        }
    }
    url[x] = '\0';
    if (badesc) return BAD_REQUEST;
    else if (badpath) return NOT_FOUND;
    else return OK;
}

/*----------------------------------------------------------*/
/*
 *		private function
 */
static int analyze_query(void)
{
char		*ptr;
int		numq, foo;
char		*tmp[MAXI_QUERIES];

/*
 *	get the addr of the environ var and duplicate the content
 */
if ((p_query_string=getenv("QUERY_STRING"))==NULL)	return 0;
p_query_string = strdup(p_query_string);

numq = 0;
ptr = strtok(p_query_string, "&");
while ( ptr != NULL )
	{
	tmp[numq] = strdup(ptr);
	if (numq++ == MAXI_QUERIES) break;
	ptr = strtok(NULL, "&");
	}

for (foo=0; foo<numq; foo++)
	{
	queries[foo].name = strtok(tmp[foo], "=");
	unescape_url(queries[foo].name);
	queries[foo].content = strtok(NULL, "=");
	unescape_url(queries[foo].content);
	}

nbre_queries = numq;

return 1;
}
/*----------------------------------------------------------*/
int	get_query__(char *nom, char *ou, long l_nom, long l_ou)
{
int	foo, bar;

if (p_query_string == NULL)
	analyze_query();

if ( l_nom<1 || l_nom>1000 )
	return 0;

for (foo=0; foo<nbre_queries; foo++)
	if (!strncmp(nom, queries[foo].name, strlen(queries[foo].name)))
		{
		strncpy(ou, queries[foo].content, l_ou);
		/*
		 * add spaces to complete string 
		 */
		for (bar=strlen(queries[foo].content); bar<l_ou; bar++)
			ou[bar] = ' ';

		return 1;
		}

return 0;
}
/*----------------------------------------------------------*/
int get_double__(char *nom, double *p_res, long l_nom)
{
int		foo;
double		flottant;

if (p_query_string == NULL)		analyze_query();

if ( l_nom<1 || l_nom>1000 )		return 0;

for (foo=0; foo<nbre_queries; foo++)
	if (!strncmp(nom, queries[foo].name, strlen(queries[foo].name)))
		{
		if (sscanf(queries[foo].content, "%lf", &flottant)==1)
			{
			*p_res = flottant;
			return 1;
			}
		}

return 0;
}
/*----------------------------------------------------------*/
