1 /*
2 cgi.c - Some simple routines for cgi programming
3 Copyright (c) 1996-8 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.
18 */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include "cgi.h"
26 int cgiDebugLevel = 0;
27 int cgiDebugStderr = 1;
29 void cgiHeader ()
30 {
31 printf ("Content-type: text/html\n\n");
32 }
34 void cgiDebug (int level, int where)
35 {
36 if (level > 0)
37 cgiDebugLevel = level;
38 else
39 cgiDebugLevel = 0;
40 if (where)
41 cgiDebugStderr = 0;
42 else
43 cgiDebugStderr = 1;
44 }
46 char *cgiDecodeString (char *text)
47 {
48 char *cp, *xp;
50 for (cp=text,xp=text; *cp; cp++) {
51 if (*cp == '%') {
52 if (strchr("0123456789ABCDEFabcdef", *(cp+1))
53 && strchr("0123456789ABCDEFabcdef", *(cp+2))) {
54 if (islower((unsigned int)*(cp+1)))
55 *(cp+1) = toupper((unsigned int)*(cp+1));
56 if (islower((unsigned int)*(cp+2)))
57 *(cp+2) = toupper((unsigned int)*(cp+2));
58 *(xp) = (*(cp+1) >= 'A' ? *(cp+1) - 'A' + 10 : *(cp+1) - '0' ) * 16
59 + (*(cp+2) >= 'A' ? *(cp+2) - 'A' + 10 : *(cp+2) - '0');
60 xp++;cp+=2;
61 }
62 } else {
63 *(xp++) = *cp;
64 }
65 }
66 memset(xp, 0, cp-xp);
67 return text;
68 }
70 /* cgiInit()
71 *
72 * Read from stdin if no string is provided via CGI. Variables that
73 * doesn't have a value associated with it doesn't get stored.
74 */
75 s_cgi **cgiInit ()
76 {
77 int length;
78 char *line = NULL;
79 int numargs;
80 char *cp, *ip, *esp, *sptr;
81 s_cgi **result;
82 int i, k;
83 char tmp[101];
85 cp = getenv("REQUEST_METHOD");
86 ip = getenv("CONTENT_LENGTH");
88 if (cp && !strcmp(cp, "POST")) {
89 if (ip) {
90 length = atoi(ip);
91 if ((line = (char *)malloc (length+2)) == NULL)
92 return NULL;
93 fgets(line, length+1, stdin);
94 } else
95 return NULL;
96 } else if (cp && !strcmp(cp, "GET")) {
97 esp = getenv("QUERY_STRING");
98 if (esp && strlen(esp)) {
99 if ((line = (char *)malloc (strlen(esp)+2)) == NULL)
100 return NULL;
101 sprintf (line, "%s", esp);
102 } else
103 return NULL;
104 } else {
105 length = 0;
106 printf ("(offline mode: enter name=value pairs on standard input)\n");
107 for (cp = fgets(tmp, 100, stdin); cp != NULL;
108 cp = fgets(tmp, 100, stdin) ) {
109 if (strlen(tmp)) {
110 length += strlen(tmp);
111 if ((ip = (char *)malloc ((length+1) * sizeof(char))) == NULL)
112 return NULL;
113 memset(ip,0, length);
114 if (line) {
115 if (line[strlen(line)-1] == '\n')
116 line[strlen(line)-1] = '&';
117 strcpy(ip, line);
118 }
119 ip = strcat(ip, tmp);
120 if (line)
121 free (line);
122 line = ip;
123 }
124 }
125 if (!line)
126 return NULL;
127 if (line[strlen(line)-1] == '\n')
128 line[strlen(line)-1] = '\0';
129 }
131 /*
132 * From now on all cgi variables are stored in the variable line
133 * and look like foo=bar&foobar=barfoo&foofoo=
134 */
136 if (cgiDebugLevel > 0) {
137 if (cgiDebugStderr) {
138 fprintf (stderr, "Received cgi input: %s\n", line);
139 } else {
140 printf ("<b>Received cgi input</b><br>\n<pre>\n--\n%s\n--\n</pre>\n\n", line);
141 }
142 }
143 for (cp=line; *cp; cp++) {
144 if (*cp == '+') {
145 *cp = ' ';
146 }
147 }
148 if (strlen(line)) {
149 for (numargs=1,cp=line; *cp; cp++) {
150 if (*cp == '&') numargs++;
151 }
152 } else {
153 numargs = 0;
154 }
155 if (cgiDebugLevel > 0) {
156 if (cgiDebugStderr) {
157 fprintf (stderr, "%d cgi variables found.\n", numargs);
158 } else {
159 printf ("%d cgi variables found.<br>\n", numargs);
160 }
161 }
162 if ((result = (s_cgi **)malloc((numargs+1) * sizeof(s_cgi *))) == NULL) {
163 return NULL;
164 }
166 memset (result, 0, (numargs+1) * sizeof(s_cgi *));
168 cp = line;
169 i=0;
170 while (*cp) {
171 if ((ip = (char *)strchr(cp, '&')) != NULL) {
172 *ip = '\0';
173 }else {
174 ip = cp + strlen(cp);
175 }
177 if ((esp=(char *)strchr(cp, '=')) == NULL) {
178 cp = ++ip;
179 continue;
180 }
182 if (!strlen(esp)) {
183 cp = ++ip;
184 continue;
185 }
187 if (i<numargs) {
189 for (k=0; k<i && (strncmp(result[k]->name,cp, esp-cp)); k++);
190 /* try to find out if there's already such a variable */
191 if (k == i) { /* No such variable yet */
192 if ((result[i] = (s_cgi *)malloc(sizeof(s_cgi))) == NULL)
193 return NULL;
194 if ((result[i]->name = (char *)malloc((esp-cp+1) * sizeof(char))) == NULL)
195 return NULL;
196 memset (result[i]->name, 0, esp-cp+1);
197 strncpy(result[i]->name, cp, esp-cp);
198 cp = ++esp;
199 if ((result[i]->value = (char *)malloc((ip-esp+1) * sizeof(char))) == NULL)
200 return NULL;
201 memset (result[i]->value, 0, ip-esp+1);
202 strncpy(result[i]->value, cp, ip-esp);
203 result[i]->value = cgiDecodeString(result[i]->value);
204 if (cgiDebugLevel) {
205 if (cgiDebugStderr)
206 fprintf (stderr, "%s: %s\n", result[i]->name, result[i]->value);
207 else
208 printf ("<h3>Variable %s</h3>\n<pre>\n%s\n</pre>\n\n", result[i]->name, result[i]->value);
209 }
210 i++;
211 } else { /* There is already such a name, suppose a mutiple field */
212 if ((sptr = (char *)malloc((strlen(result[k]->value)+(ip-esp)+2)* sizeof(char))) == NULL)
213 return NULL;
214 memset (sptr, 0, strlen(result[k]->value)+(ip-esp)+2);
215 sprintf (sptr, "%s\n", result[k]->value);
216 cp = ++esp;
217 strncat(sptr, cp, ip-esp);
218 free(result[k]->value);
219 result[k]->value = sptr;
220 }
221 }
222 cp = ++ip;
223 }
224 return result;
225 }
227 char *cgiGetValue(s_cgi **parms, const char *var)
228 {
229 int i;
231 if (parms) {
232 for (i=0;parms[i]; i++) {
233 if (!strcmp(var,parms[i]->name)) {
234 if (cgiDebugLevel > 0) {
235 if (cgiDebugStderr) {
236 fprintf (stderr, "%s found as %s\n", var, parms[i]->value);
237 } else {
238 printf ("%s found as %s<br>\n", var, parms[i]->value);
239 }
240 }
241 return parms[i]->value;
242 }
243 }
244 }
245 if (cgiDebugLevel) {
246 if (cgiDebugStderr) {
247 fprintf (stderr, "%s not found\n", var);
248 } else {
249 printf ("%s not found<br>\n", var);
250 }
251 }
252 return NULL;
253 }
255 void cgiRedirect (const char *url)
256 {
257 if (url && strlen(url)) {
258 printf ("Content-type: text/html\nContent-length: %d\n", 77+(strlen(url)*2));
259 printf ("Status: 302 Temporal Relocation\n");
260 printf ("Location: %s\n\n", url);
261 printf ("<html>\n<body>\nThe page has been moved to <a href=\"%s\">%s</a>\n</body>\n</html>\n", url, url);
262 }
263 }
265 /*
266 * Local variables:
267 * c-indent-level: 4
268 * c-basic-offset: 4
269 * tab-width: 8
270 * End:
271 */