new function list_deep_free
[swftools.git] / lib / modules / swfcgi.c
1 /* swfcgi.c
2
3    Parse CGI parameters
4    
5    Partly adopted from Steven Grimm's uncgi tool and library.
6
7    Extension module for the rfxswf library.
8    Part of the swftools package.
9
10    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
11  
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include "../rfxswf.h"
29
30 #define ishex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))
31
32 #define PREFIX "WWW_"
33
34 static int swf_htoi(unsigned char * s)
35 { int     value;
36   char    c;
37
38   c = s[0];
39   if (isupper(c)) c = tolower(c);
40   value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
41
42   c = s[1];
43   if (isupper(c)) c = tolower(c);
44   value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
45
46   return (value);
47 }
48
49 static void swf_url_unescape(unsigned char * s)
50 { unsigned char  *dest = s;
51
52   while (s[0])
53   { if (s[0] == '+') dest[0] = ' ';
54     else
55     { if (s[0] == '%' && ishex(s[1]) && ishex(s[2]))
56       { dest[0] = (unsigned char) swf_htoi(s + 1);
57         s += 2;
58       }
59       else dest[0] = s[0];
60     }
61     s++;dest++;
62   }
63   dest[0] = 0;
64 }
65
66 static void swf_cgienv(unsigned char * var)
67 { unsigned char *buf, *c, *s, *t, *oldval = NULL, *newval;
68   int despace = 0, got_cr = 0;
69
70   // fprintf(stderr,"%s\n",var);
71   swf_url_unescape(var);
72   // fprintf(stderr,"%s\n",var);
73
74   
75   buf = (unsigned char*)rfx_alloc(strlen((const char*)var) + sizeof(PREFIX) + 2);
76   if (!buf) return;
77
78   strcpy((char*)buf, (const char*)PREFIX);
79   if (var[0] == '_')
80   { strcpy((char*)&buf[sizeof(PREFIX)-1], (const char*)&var[1]);
81     despace = 1;
82   }
83   else strcpy((char*)&buf[sizeof(PREFIX)-1], (const char*)var);
84
85   for (c = buf; c[0] ; c++)
86   { if (c[0] == '.') c[0] = '_';
87     if (c[0] == '=') break;
88   }
89   if (!c[0]) c[1] = 0;
90   c[0] = 0;
91
92   if (despace && c[1])
93   { for (s = c+1; s[0] && isspace(s[0]); s++);
94     t = c + 1;
95     while (s[0])
96     { if (s[0] == '\r')
97       { got_cr = 1;
98         s++;
99         continue;
100       }
101       if (got_cr)
102       { if (s[0] != '\n')
103         *t++ = '\n';
104         got_cr = 0;
105       }
106       *t++ = *s++;
107     }
108     while (t > c && isspace(*--t));
109     t[1] = 0;
110   }
111
112   if ((oldval = (unsigned char*)getenv((const char*)buf)))
113   { newval = (unsigned char*)rfx_alloc(strlen((const char*)oldval) + strlen((const char *)buf) + strlen((const char*)&c[1]) + 3);
114     if (!newval) return;
115
116     c[0] = '=';
117     sprintf((char*)newval, "%s#%s", buf, oldval);
118     c[0] = 0;
119
120     oldval -= strlen((const char*)buf) + 1; // skip past VAR= 
121   }
122   else 
123   { c[0] = '=';
124     newval = buf;
125   }
126   
127   putenv((char *)newval);
128         
129   if (oldval)
130   { rfx_free(oldval);
131     rfx_free(buf);
132   }
133 }
134
135 static void swf_scanquery(char * q)
136 { char *next = q;
137   if (!q) return;
138
139   while (next)
140   { next = strchr(q, '&');
141     if (next) next[0] = 0;
142     swf_cgienv((unsigned char*)q);
143     if (next)
144     { next[0] = '&';
145       q = next+1;
146     }
147   } 
148 }
149
150 char * swf_postread()
151 { char * buf = NULL;
152   int size = 0, sofar = 0, got;
153
154   buf = getenv("CONTENT_TYPE");
155   if ((!buf) || strcmp(buf, "application/x-www-form-urlencoded")) return NULL;
156
157   buf = getenv("CONTENT_LENGTH");
158   if (!buf) return NULL;
159         
160   size = atoi(buf);
161   buf = (char*)rfx_alloc(size + 1);
162   if (buf)
163   { do
164     { got = fread(buf + sofar, 1, size - sofar, stdin);
165       sofar += got;
166     } while (got && sofar < size);
167     buf[sofar] = 0;
168   }
169
170   return buf;
171 }
172
173 void swf_uncgi()
174 { char *query, *dupquery, *method;
175
176   query = getenv("QUERY_STRING");
177   if ((query) && strlen(query))
178   { dupquery = strdup(query);
179     swf_scanquery(dupquery);
180     rfx_free(dupquery);
181   }
182
183   method = getenv("REQUEST_METHOD");
184   if ((method) && ! strcmp(method, "POST"))
185   { query = swf_postread();
186     if ((query)&&(query[0]!=0)) swf_scanquery(query);
187     rfx_free(query);
188   }
189   
190 }
191       
192 #undef ishex
193 #undef PREFIX