HTML Encyclopaedia

The expr1.c program

This C program is used a CGI backend by the forms demonstrations in the encyclopaedia.

The program is compiled using the following command on scitsc cc -o expr1.cgi expr1.c -lncsa

#include	<stdio.h>
#include	<ncsa.h>
#include	<stdlib.h>

#define	NENT	15	
struct	entry	entries[NENT];

main()
{
	int	i,m;
	char	*cl = getenv("QUERY_STRING");
	printf("Content-Type: text/plain\n\n");
	for(i=0; cl[0] && i<NENT; i++)
	{
		getword(entries[i].val,cl,'&');
		plustospace(entries[i].val);
		unescape_url(entries[i].val);
		getword(entries[i].name,entries[i].val,'=');
	}
	m = i;
	for(i=0;i<m;i++) printf("Item %d Name = %s Value = %s\n",
			i,entries[i].name,entries[i].val);
}

The program shown above uses various routines that came with the scitsc NCSA WWW server, they are not particularly efficient. Here is some simple C code (it took me about 20 minutes) that decodes a CGI query string and stores the results. It could do with some refinement but you may find it useful as a starting point for developing your own programs.


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

struct	entry	
{
	char	*name;
	char	*value;
};

void	un_escape(char *);

main()
{
	int	i,m;
	int	pcts=0;
	char	*cp;
	char	**cfp;
	struct	entry	*entries;
	char	*cl = getenv("QUERY_STRING");
	printf("Content-Type: text/plain\n\n");
	cp =cl;

	/* first scan query string for ampersands which separate
		name=value pairs - count gives number of items */

	while(*cp) if(*cp++ == '&') pcts++;
	pcts++;

	/* get enough space to store the information - the text
		strings stay in the environment variable QUERY_STRING */

	cfp = (char **)calloc(pcts,sizeof(char *));


	/* now split the environment variable into separate strings */

	cfp[0] = cp = cl;
	i = 1;
	while(*cp)
	{
		if(*cp == '&')
		{
			*cp = '\0';
			cfp[i++] = cp+1;
		}
		cp++;
	}
	
	/* print obtained values - if you uncomment out this bit of code  

	for(i=0;i<pcts;i++) printf("%d %s\n",i,cfp[i]);

	*/


	/* allocate enough space to hold the actual struct entry items */
	
	entries = (struct entry *)calloc(pcts,sizeof(struct entry));

	/* now look for the = symbols that separate the names and
		values within each string - store the pointers in the
		struct entry items */

	for(i=0;i<pcts;i++)
	{
		cp = strchr(cfp[i],'=');
		if(cp == NULL) printf("Error in %d\n",i);
		*cp = '\0';
		entries[i].name = cfp[i];
		entries[i].value = cp+1;
	}

	/* more optional printing

	for(i=0;i<pcts;i++)
	{
		printf("%d name = %s value = %s\n",i,entries[i].name,
				entries[i].value);
	}

	*/

	/* now to undo the http escaping conventions */

	for(i=0;i<pcts;i++)
		un_escape(entries[i].value);

	/* and yet more optional printing 

	for(i=0;i<pcts;i++)
	{
		printf("%d name = %s value = %s\n",i,entries[i].name,
				entries[i].value);
	}

	*/

		
}

void	un_escape(char *s)
{

/*	in-place http unescaping - two things to do

	1. replace pluses by spaces
	2. deal with %XX escapes
*/

	char *s1;	/* destination */
	int	v1,v2;
	int	i;
	s1 = s;
	while(*s)
	{
		if(*s == '+') *s1=' ';	/* plus -> space */
		else if(*s == '%')	/* an %XX escape ?? */
		{
			for(i=1;i<=2;i++)	/* two hex digits MUST follow */
			{
				if(!isdigit(*(s+i))) /* special crude stuff for A-F */
				{
					*(s+i) = tolower(*(s+i));
					*(s+i) = *(s+i)-'a' + '9' + 1;
				}
			}
			v1 = 16*(*(s+1)-'0') + *(s+2)-'0';
			*s1 = v1;
			s+=2;
		}
		else	*s1 = *s;
		s++;
		s1++;
	}
	*s1 = '\0';
	return;
}