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; }