2 cgi.c - Some simple routines for CGI programming
3 Copyright (c) 1996-9 Martin Schulze <joey@infodrom.north.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 Sat Aug 24 10:39:31 MET 1999: Martin Schulze <joey@infodrom.north.de>
22 Added cgiGetVariables(), corrected multiple values code
33 int cgiDebugLevel = 0;
34 int cgiDebugStderr = 1;
35 char *cgiHeaderString = NULL;
38 int cgiSetHeader (char *name, char *value)
40 char *cp, *vp, *pivot;
43 if (!name || !strlen (name) || !value || !strlen (value))
46 for (cp=name;*cp && *cp!=' ' && *cp!='\n' && *cp!=':';cp++);
47 for (vp=value;*vp && *vp!='\n';vp++);
49 if (cgiHeaderString) {
50 len = (strlen (cgiHeaderString) + cp-name + vp-value + 4) * sizeof (char);
51 if ((cgiHeaderString = (char *)realloc (cgiHeaderString,len)) == NULL)
53 pivot = cgiHeaderString;
54 pivot += strlen (cgiHeaderString);
55 strncpy (pivot, name, cp-name);
57 pivot[cp-name+1] = ' ';
58 pivot[cp-name+2] = '\0';
59 strncat (pivot, value, vp-value);
60 pivot[cp-name+2+vp-value] = '\n';
62 len = (cp-name + vp-value + 4) * sizeof (char);
63 if ((cgiHeaderString = (char *)malloc (len)) == NULL)
65 strncpy (cgiHeaderString, name, cp-name);
66 cgiHeaderString[cp-name] = ':';
67 cgiHeaderString[cp-name+1] = ' ';
68 cgiHeaderString[cp-name+2] = '\0';
69 strncat (cgiHeaderString, value, vp-value);
70 cgiHeaderString[cp-name+2+vp-value] = '\n';
75 int cgiSetType (char *type)
80 if (!type || !strlen (type))
85 for (cp=type;*cp && *cp!='\n';cp++);
87 len = (cp-type+1) * sizeof (char);
88 if ((cgiType = (char *)malloc (len+20)) == NULL)
90 memset (cgiType, 0, len);
91 strncpy (cgiType, type, cp-type);
99 printf ("Content-type: %s\n", cgiType);
101 printf ("Content-type: text/html\n");
103 printf ("%s", cgiHeaderString);
107 void cgiDebug (int level, int where)
110 cgiDebugLevel = level;
119 char *cgiDecodeString (char *text)
123 for (cp=text,xp=text; *cp; cp++) {
125 if (strchr("0123456789ABCDEFabcdef", *(cp+1))
126 && strchr("0123456789ABCDEFabcdef", *(cp+2))) {
127 if (islower(*(cp+1)))
128 *(cp+1) = toupper(*(cp+1));
129 if (islower(*(cp+2)))
130 *(cp+2) = toupper(*(cp+2));
131 *(xp) = (*(cp+1) >= 'A' ? *(cp+1) - 'A' + 10 : *(cp+1) - '0' ) * 16
132 + (*(cp+2) >= 'A' ? *(cp+2) - 'A' + 10 : *(cp+2) - '0');
139 memset(xp, 0, cp-xp);
145 * Read from stdin if no string is provided via CGI. Variables that
146 * doesn't have a value associated with it doesn't get stored.
153 char *cp, *ip, *esp, *sptr;
158 cp = getenv("REQUEST_METHOD");
159 ip = getenv("CONTENT_LENGTH");
161 if (cp && !strcmp(cp, "POST")) {
164 if ((line = (char *)malloc (length+2)) == NULL)
166 fgets(line, length+1, stdin);
169 } else if (cp && !strcmp(cp, "GET")) {
170 esp = getenv("QUERY_STRING");
171 if (esp && strlen(esp)) {
172 if ((line = (char *)malloc (strlen(esp)+2)) == NULL)
174 sprintf (line, "%s", esp);
179 printf ("(offline mode: enter name=value pairs on standard input)\n");
180 memset (tmp, 0, sizeof(tmp));
181 while((cp = fgets (tmp, 100, stdin)) != NULL) {
183 if (tmp[strlen(tmp)-1] == '\n')
184 tmp[strlen(tmp)-1] = '&';
186 length += strlen(tmp);
187 len = (length+1) * sizeof(char);
188 if ((line = (char *)realloc (line, len)) == NULL)
192 length = strlen(tmp);
193 len = (length+1) * sizeof(char);
194 if ((line = (char *)malloc (len)) == NULL)
196 memset (line, 0, len);
200 memset (tmp, 0, sizeof(tmp));
204 if (line[strlen(line)-1] == '&')
205 line[strlen(line)-1] = '\0';
209 * From now on all cgi variables are stored in the variable line
210 * and look like foo=bar&foobar=barfoo&foofoo=
213 if (cgiDebugLevel > 0) {
215 fprintf (stderr, "Received cgi input: %s\n", line);
217 printf ("<b>Received cgi input</b><br>\n<pre>\n--\n%s\n--\n</pre>\n\n", line);
220 for (cp=line; *cp; cp++)
225 for (numargs=1,cp=line; *cp; cp++)
226 if (*cp == '&') numargs++;
229 if (cgiDebugLevel > 0) {
231 fprintf (stderr, "%d cgi variables found.\n", numargs);
233 printf ("%d cgi variables found.<br>\n", numargs);
236 len = (numargs+1) * sizeof(s_cgi *);
237 if ((result = (s_cgi **)malloc (len)) == NULL)
239 memset (result, 0, len);
244 if ((ip = (char *)strchr(cp, '&')) != NULL) {
247 ip = cp + strlen(cp);
249 if ((esp=(char *)strchr(cp, '=')) == NULL) {
261 /* try to find out if there's already such a variable */
262 for (k=0; k<i && (strncmp (result[k]->name,cp, esp-cp) || !(strlen (result[k]->name) == esp-cp)); k++);
264 if (k == i) { /* No such variable yet */
265 if ((result[i] = (s_cgi *)malloc(sizeof(s_cgi))) == NULL)
267 if ((result[i]->name = (char *)malloc((esp-cp+1) * sizeof(char))) == NULL)
269 memset (result[i]->name, 0, esp-cp+1);
270 strncpy(result[i]->name, cp, esp-cp);
272 if ((result[i]->value = (char *)malloc((ip-esp+1) * sizeof(char))) == NULL)
274 memset (result[i]->value, 0, ip-esp+1);
275 strncpy(result[i]->value, cp, ip-esp);
276 result[i]->value = cgiDecodeString(result[i]->value);
279 fprintf (stderr, "%s: %s\n", result[i]->name, result[i]->value);
281 printf ("<h3>Variable %s</h3>\n<pre>\n%s\n</pre>\n\n", result[i]->name, result[i]->value);
284 } else { /* There is already such a name, suppose a mutiple field */
286 len = (strlen(result[k]->value)+(ip-esp)+2) * sizeof (char);
287 if ((sptr = (char *)malloc(len)) == NULL)
289 memset (sptr, 0, len);
290 sprintf (sptr, "%s\n", result[k]->value);
291 strncat(sptr, cp, ip-esp);
292 free(result[k]->value);
293 result[k]->value = cgiDecodeString (sptr);
301 char *cgiGetValue (s_cgi **parms, const char *var)
306 for (i=0;parms[i]; i++)
307 if (!strcmp(var,parms[i]->name)) {
308 if (cgiDebugLevel > 0) {
310 fprintf (stderr, "%s found as %s\n", var, parms[i]->value);
312 printf ("%s found as %s<br>\n", var, parms[i]->value);
314 return parms[i]->value;
318 fprintf (stderr, "%s not found\n", var);
320 printf ("%s not found<br>\n", var);
325 char **cgiGetVariables (s_cgi **parms)
332 for (i=0;parms[i]; i++);
333 len = sizeof (char *) * ++i;
334 if ((res = (char **)malloc (len)) == NULL)
336 memset (res, 0, len);
337 for (i=0;parms[i]; i++) {
338 len = strlen (parms[i]->name) +1;
339 if ((res[i] = (char *)malloc (len)) == NULL)
341 memset (res[i], 0, len);
342 strcpy (res[i], parms[i]->name);
348 void cgiRedirect (const char *url)
350 if (url && strlen(url)) {
351 printf ("Content-type: text/html\nContent-length: %d\n", 77+(strlen(url)*2));
352 printf ("Status: 302 Temporal Relocation\n");
353 printf ("Location: %s\n\n", url);
354 printf ("<html>\n<body>\nThe page has been moved to <a href=\"%s\">%s</a>\n</body>\n</html>\n", url, url);