New config API and session cache API
[shibboleth/sp.git] / apache-2.0 / cgiparse.cpp
1 /*
2  * The Shibboleth License, Version 1.
3  * Copyright (c) 2002
4  * University Corporation for Advanced Internet Development, Inc.
5  * All rights reserved
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution, if any, must include
17  * the following acknowledgment: "This product includes software developed by
18  * the University Corporation for Advanced Internet Development
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20  * may appear in the software itself, if and wherever such third-party
21  * acknowledgments normally appear.
22  *
23  * Neither the name of Shibboleth nor the names of its contributors, nor
24  * Internet2, nor the University Corporation for Advanced Internet Development,
25  * Inc., nor UCAID may be used to endorse or promote products derived from this
26  * software without specific prior written permission. For written permission,
27  * please contact shibboleth@shibboleth.org
28  *
29  * Products derived from this software may not be called Shibboleth, Internet2,
30  * UCAID, or the University Corporation for Advanced Internet Development, nor
31  * may Shibboleth appear in their name, without prior written permission of the
32  * University Corporation for Advanced Internet Development.
33  *
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 /* cgiparse.cpp - URL-encoded parameter parsing
51
52    Scott Cantor
53    7/6/03
54
55    Derek Atkins <derek@ihtfp.com>
56    2004-02-25
57 */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include <map>
64
65 #include "cgiparse.h"
66
67 using namespace shibtarget;
68 using namespace std;
69
70 class CgiParseImpl : CgiParse{
71 public:
72   ~CgiParseImpl() {};
73   CgiParseImpl(string& cgi);
74   const char * get_value(const string& name) const;
75
76 private:
77   map<string,string> kvp_map;
78 };
79
80
81 namespace {
82
83 /* Parsing routines modified from NCSA source. */
84 char *makeword(char *line, char stop)
85 {
86     int x = 0,y;
87     char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
88
89     for(x=0;((line[x]) && (line[x] != stop));x++)
90         word[x] = line[x];
91
92     word[x] = '\0';
93     if(line[x])
94         ++x;
95     y=0;
96
97     while(line[x])
98       line[y++] = line[x++];
99     line[y] = '\0';
100     return word;
101 }
102
103 char *fmakeword(char stop, int *cl, const char** ppch)
104 {
105     int wsize;
106     char *word;
107     int ll;
108
109     wsize = 1024;
110     ll=0;
111     word = (char *) malloc(sizeof(char) * (wsize + 1));
112
113     while(1)
114     {
115         word[ll] = *((*ppch)++);
116         if(ll==wsize-1)
117         {
118             word[ll+1] = '\0';
119             wsize+=1024;
120             word = (char *)realloc(word,sizeof(char)*(wsize+1));
121         }
122         --(*cl);
123         if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
124         {
125             if(word[ll] != stop)
126                 ll++;
127             word[ll] = '\0';
128             return word;
129         }
130         ++ll;
131     }
132 }
133
134 char x2c(char *what)
135 {
136     register char digit;
137
138     digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
139     digit *= 16;
140     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
141     return(digit);
142 }
143
144 void unescape_url(char *url)
145 {
146     register int x,y;
147
148     for(x=0,y=0;url[y];++x,++y)
149     {
150         if((url[x] = url[y]) == '%')
151         {
152             url[x] = x2c(&url[y+1]);
153             y+=2;
154         }
155     }
156     url[x] = '\0';
157 }
158
159 void plustospace(char *str)
160 {
161     register int x;
162
163     for(x=0;str[x];x++)
164         if(str[x] == '+') str[x] = ' ';
165 }
166
167 };  // end of private namespace
168
169 CgiParseImpl::CgiParseImpl(string& cgi)
170 {
171     int cl;
172     const char* pch;
173
174 #if 0
175     /* Verify method and content type. */
176     if(!stricmp(lpECB->lpszMethod,"POST"))
177     {
178         if (stricmp(lpECB->lpszContentType,"application/x-www-form-urlencoded"))
179             return NULL;
180         pch=lpECB->lpbData;
181         cl=lpECB->cbAvailable;
182     }
183     else if (!stricmp(lpECB->lpszMethod,"GET"))
184     {
185         pch=lpECB->lpszQueryString;
186         cl=strlen(pch);
187     }
188     else
189         return NULL;
190 #else
191     pch = cgi.c_str();
192     cl = strlen(pch);
193 #endif
194         
195     while (cl && pch)
196     {
197         char *name;
198         char *value;
199         value=fmakeword('&',&cl,&pch);
200         plustospace(value);
201         unescape_url(value);
202         name=makeword(value,'=');
203
204         kvp_map[name]=value;
205         free(name);
206         free(value);
207     }
208 }
209
210
211 const char *
212 CgiParseImpl::get_value(const string& name) const
213 {
214   map<string,string>::const_iterator i=kvp_map.find(name);
215   if (i==kvp_map.end())
216     return NULL;
217
218   return i->second.c_str();
219 }
220
221 CgiParse*
222 CgiParse::ParseCGI(string& input)
223 {
224   CgiParseImpl* res = new CgiParseImpl(input);
225   return (CgiParse*) res;
226 }