root/tags/rel-5-0-2/mapserver/cgiutil.c

Revision 6764, 11.0 kB (checked in by tamas, 1 year ago)

Support for writing the QUERY_STRING to the debug output (#2274)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  *
3  * Project:  MapServer
4  * Purpose:  cgiRequestObj and CGI parameter parsing.
5  * Author:   Steve Lime and the MapServer team.
6  *
7  ******************************************************************************
8  * Copyright (c) 1996-2005 Regents of the University of Minnesota.
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies of this Software or works derived from this Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include "cgiutil.h"
34 #include "mapserver.h"
35
36 MS_CVSID("$Id$")
37
38 #define LF 10
39 #define CR 13
40
41 static char *readPostBody( cgiRequestObj *request )
42 {
43   char *data;
44   int data_max, data_len, chunk_size;
45
46   msIO_needBinaryStdin();
47
48   /* -------------------------------------------------------------------- */
49   /*      If the length is provided, read in one gulp.                    */
50   /* -------------------------------------------------------------------- */
51   if( getenv("CONTENT_LENGTH") != NULL ) {
52     data_max = atoi(getenv("CONTENT_LENGTH"));
53     data = (char *) malloc(data_max+1);
54     if( data == NULL ) {
55       msIO_printf("Content-type: text/html%c%c",10,10);
56       msIO_printf("malloc() failed, Content-Length: %d unreasonably large?\n", data_max );
57       exit( 1 );
58     }
59
60     if( (int) msIO_fread(data, 1, data_max, stdin) < data_max ) {
61       msIO_printf("Content-type: text/html%c%c",10,10);
62       msIO_printf("POST body is short\n");
63       exit(1);
64     }
65
66     data[data_max] = '\0';
67     return data;
68   }
69
70   /* -------------------------------------------------------------------- */
71   /*      Otherwise read in chunks to the end.                            */
72   /* -------------------------------------------------------------------- */
73   data_max = 10000;
74   data_len = 0;
75   data = (char *) malloc(data_max+1);
76
77   while( (chunk_size = msIO_fread( data + data_len, 1, data_max-data_len, stdin )) > 0 ) {
78     data_len += chunk_size;
79
80     if( data_len == data_max ) {
81       data_max = data_max + 10000;
82       data = (char *) realloc(data, data_max+1);
83
84       if( data == NULL ) {
85         msIO_printf("Content-type: text/html%c%c",10,10);
86         msIO_printf("out of memory trying to allocate %d input buffer, POST body too large?\n", data_max+1 );
87         exit(1);
88       }
89     }
90   }
91
92   data[data_len] = '\0'
93   return data;
94 }
95
96 int loadParams(cgiRequestObj *request) {
97   register int x,m=0;
98   char *s;
99   int debuglevel;
100
101   if(getenv("REQUEST_METHOD")==NULL) {
102     msIO_printf("This script can only be used to decode form results and \n");
103     msIO_printf("should be initiated as a CGI process via a httpd server.\n");
104     exit(0);
105   }
106
107   debuglevel = (int)msGetGlobalDebugLevel();
108
109   if(strcmp(getenv("REQUEST_METHOD"),"POST") == 0) { /* we've got a post from a form */     
110     char *post_data;
111
112     request->type = MS_POST_REQUEST;
113
114     s = getenv("CONTENT_TYPE");
115     if (s != NULL)
116       request->contenttype = strdup(s);
117      /* we've to set default content-type which is
118       * application/octet-stream according to
119       * W3 RFC 2626 section 7.2.1 */
120     else request->contenttype = strdup("application/octet-stream");
121
122     post_data = readPostBody( request );
123     if(strcmp(request->contenttype, "application/x-www-form-urlencoded"))
124       request->postrequest = post_data;
125     else {
126       int data_len = strlen(post_data);
127       while( data_len > 0 && isspace(post_data[data_len-1]) )
128         post_data[--data_len] = '\0';
129
130       while( post_data[0] ) {
131         if(m >= MS_MAX_CGI_PARAMS) {
132           msIO_printf("Too many name/value pairs, aborting.\n");
133           exit(0);
134         }
135
136         request->ParamValues[m] = makeword(post_data,'&');
137         plustospace(request->ParamValues[m]);
138         unescape_url(request->ParamValues[m]);
139         request->ParamNames[m] = makeword(request->ParamValues[m],'=');
140         m++;
141       }
142       free( post_data );
143     }
144
145     /* check the QUERY_STRING even in the post request since it can contain
146        information. Eg a wfs request with  */
147     s = getenv("QUERY_STRING");
148     if(s) {
149       if (debuglevel >= MS_DEBUGLEVEL_DEBUG)
150                   msDebug("loadParams() QUERY_STRING: %s\n", s);
151
152       for(x=0;s[0] != '\0';x++) {       
153         if(m >= MS_MAX_CGI_PARAMS) {
154           msIO_printf("Too many name/value pairs, aborting.\n");
155           exit(0);
156         }
157         request->ParamValues[m] = makeword(s,'&');
158         plustospace(request->ParamValues[m]);
159         unescape_url(request->ParamValues[m]);
160         request->ParamNames[m] = makeword(request->ParamValues[m],'=');
161         m++;
162       }
163     }     
164   } else {
165     if(strcmp(getenv("REQUEST_METHOD"),"GET") == 0) { /* we've got a get request */
166       request->type = MS_GET_REQUEST;
167
168       s = getenv("QUERY_STRING");
169       if(s == NULL) {
170         msIO_printf("Content-type: text/html%c%c",10,10);
171         msIO_printf("No query information to decode. QUERY_STRING not set.\n");
172         exit(1);
173       }
174
175           if (debuglevel >= MS_DEBUGLEVEL_DEBUG)
176                   msDebug("loadParams() QUERY_STRING: %s\n", s);
177
178       if(strlen(s)==0) {
179         msIO_printf("Content-type: text/html%c%c",10,10);
180         msIO_printf("No query information to decode. QUERY_STRING is set, but empty.\n");
181         exit(1);
182       }
183
184       for(x=0;s[0] != '\0';x++) {       
185         if(m >= MS_MAX_CGI_PARAMS) {
186           msIO_printf("Too many name/value pairs, aborting.\n");
187           exit(0);
188         }
189         request->ParamValues[m] = makeword(s,'&');
190         plustospace(request->ParamValues[m]);
191         unescape_url(request->ParamValues[m]);
192         request->ParamNames[m] = makeword(request->ParamValues[m],'=');
193         m++;
194       }
195     } else {
196       msIO_printf("Content-type: text/html%c%c",10,10);
197       msIO_printf("This script should be referenced with a METHOD of GET or METHOD of POST.\n");
198       exit(1);
199     }
200   }
201
202   /* check for any available cookies */
203   s = getenv("HTTP_COOKIE");
204   if(s != NULL) {   
205     for(x=0;s[0] != '\0';x++) {
206       if(m >= MS_MAX_CGI_PARAMS) {
207         msIO_printf("Too many name/value pairs, aborting.\n");
208         exit(0);
209       }
210       request->ParamValues[m] = makeword(s,';');
211       plustospace(request->ParamValues[m]);
212       unescape_url(request->ParamValues[m]);
213       request->ParamNames[m] = makeword_skip(request->ParamValues[m],'=',' ');
214       m++;
215     }
216   }
217
218   return(m);
219 }
220
221 void getword(char *word, char *line, char stop) {
222   int x = 0,y;
223
224   for(x=0;((line[x]) && (line[x] != stop));x++)
225     word[x] = line[x];
226
227   word[x] = '\0';
228   if(line[x]) ++x;
229   y=0;
230
231   while((line[y++] = line[x++]));
232 }
233
234 char *makeword_skip(char *line, char stop, char skip) {
235   int x = 0,y,offset=0;
236   char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
237
238   for(x=0;((line[x]) && (line[x] == skip));x++);
239   offset = x;
240
241   for(x=offset;((line[x]) && (line[x] != stop));x++)
242     word[x-offset] = line[x];
243
244   word[x-offset] = '\0';
245   if(line[x]) ++x;
246   y=0;
247
248   while((line[y++] = line[x++]));
249   return word;
250 }
251
252 char *makeword(char *line, char stop) {
253   int x = 0,y;
254   char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
255
256   for(x=0;((line[x]) && (line[x] != stop));x++)
257     word[x] = line[x];
258
259   word[x] = '\0';
260   if(line[x]) ++x;
261   y=0;
262
263   while((line[y++] = line[x++]));
264   return word;
265 }
266
267 char *fmakeword(FILE *f, char stop, int *cl) {
268   int wsize;
269   char *word;
270   int ll;
271
272   wsize = 102400;
273   ll=0;
274   word = (char *) malloc(sizeof(char) * (wsize + 1));
275
276   while(1) {
277     word[ll] = (char)fgetc(f);
278     if(ll==wsize) {
279       word[ll+1] = '\0';
280       wsize+=102400;
281       word = (char *)realloc(word,sizeof(char)*(wsize+1));
282     }
283     --(*cl);
284     if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
285       if(word[ll] != stop) ll++;
286       word[ll] = '\0';
287             word = (char *) realloc(word, ll+1);
288       return word;
289     }
290     ++ll;
291   }
292 }
293
294 char x2c(char *what) {
295   register char digit;
296
297   digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
298   digit *= 16;
299   digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
300   return(digit);
301 }
302
303 void unescape_url(char *url) {
304   register int x,y;
305
306   for(x=0,y=0;url[y];++x,++y) {
307     if((url[x] = url[y]) == '%') {
308       url[x] = x2c(&url[y+1]);
309       y+=2;
310     }
311   }
312   url[x] = '\0';
313 }
314
315 void plustospace(char *str) {
316   register int x;
317
318   for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
319 }
320
321 int rind(char *s, char c) {
322   register int x;
323   for(x=strlen(s) - 1;x != -1; x--)
324     if(s[x] == c) return x;
325   return -1;
326 }
327
328 int _getline(char *s, int n, FILE *f) {
329   register int i=0;
330
331   while(1) {
332     s[i] = (char)fgetc(f);
333
334     if(s[i] == CR)
335       s[i] = fgetc(f);
336
337     if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
338       s[i] = '\0';
339       return (feof(f) ? 1 : 0);
340     }
341     ++i;
342   }
343 }
344
345 void send_fd(FILE *f, FILE *fd) {
346   char c;
347
348   while (1) {
349     c = fgetc(f);
350     if(feof(f))
351       return;
352     fputc(c,fd);
353   }
354 }
355
356 int ind(char *s, char c) {
357   register int x;
358
359   for(x=0;s[x];x++)
360     if(s[x] == c) return x;
361
362   return -1;
363 }
364
365 /*
366 ** patched version according to CERT advisory...
367 */
368 void escape_shell_cmd(char *cmd) {
369   register int x,y,l;
370
371   l=strlen(cmd);
372   for(x=0;cmd[x];x++) {
373     if(ind("&;`'\"|*?~<>^()[]{}$\\\n",cmd[x]) != -1) {
374       for(y=l+1;y>x;y--)
375         cmd[y] = cmd[y-1];
376       l++; /* length has been increased */
377       cmd[x] = '\\';
378       x++; /* skip the character */
379     }
380   }
381 }
382
383 /*
384 ** Allocate a new request holder structure
385 */
386 cgiRequestObj *msAllocCgiObj() {
387   cgiRequestObj *request = (cgiRequestObj *)malloc(sizeof(cgiRequestObj));
388
389   if(!request)
390     return NULL;
391
392   request->ParamNames = NULL;
393   request->ParamValues = NULL;
394   request->NumParams = 0;
395   request->type = -1;
396   request->contenttype = NULL;
397   request->postrequest = NULL;
398
399   return request;
400 }
401      
402 void msFreeCgiObj(cgiRequestObj *request) {
403   msFreeCharArray(request->ParamNames, request->NumParams);
404   msFreeCharArray(request->ParamValues, request->NumParams);
405   request->ParamNames = NULL;
406   request->ParamValues = NULL;
407   request->NumParams = 0;
408   request->type = -1;
409   msFree(request->contenttype);
410   msFree(request->postrequest);
411   request->contenttype = NULL;
412   request->postrequest = NULL;
413
414   msFree(request);
415 }
Note: See TracBrowser for help on using the browser.