Initial revision
[rrdtool.git] / libraries / cgilib-0.4 / cgi.c
1 /*
2     cgi.c - Some simple routines for cgi programming
3     Copyright (c) 1996-8  Martin Schulze <joey@infodrom.north.de>
4
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.
9
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.
14
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  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include "cgi.h"
25
26 int cgiDebugLevel = 0;
27 int cgiDebugStderr = 1;
28
29 void cgiHeader ()
30 {
31     printf ("Content-type: text/html\n\n");
32 }
33
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 }
45
46 char *cgiDecodeString (char *text)
47 {
48     char *cp, *xp;
49
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 }
69
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];
84
85     cp = getenv("REQUEST_METHOD");
86     ip = getenv("CONTENT_LENGTH");
87
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     }
130
131     /*
132      *  From now on all cgi variables are stored in the variable line
133      *  and look like  foo=bar&foobar=barfoo&foofoo=
134      */
135
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     }
165
166     memset (result, 0, (numargs+1) * sizeof(s_cgi *));
167
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         }
176
177         if ((esp=(char *)strchr(cp, '=')) == NULL) {
178             cp = ++ip;
179             continue;
180         }
181
182         if (!strlen(esp)) {
183             cp = ++ip;
184             continue;
185         }
186
187         if (i<numargs) {
188
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 }
226
227 char *cgiGetValue(s_cgi **parms, const char *var)
228 {
229     int i;
230
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 }
254
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 }
264
265 /*
266  * Local variables:
267  *  c-indent-level: 4
268  *  c-basic-offset: 4
269  *  tab-width: 8
270  * End:
271  */