27f4dc55839647488e50cd01b5b9ed1e37899eb4
[shibboleth/sp.git] / shibsp / util / CGIParser.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * CGIParser.cpp
23  * 
24  * CGI GET/POST parameter parsing.
25  */
26
27 #include "internal.h"
28 #include "util/CGIParser.h"
29
30 #include <xmltooling/XMLToolingConfig.h>
31 #include <xmltooling/io/HTTPRequest.h>
32 #include <xmltooling/util/URLEncoder.h>
33
34 using namespace shibsp;
35 using namespace xmltooling;
36 using namespace std;
37
38 namespace {
39     /* Parsing routines modified from NCSA source. */
40     char* makeword(char *line, char stop)
41     {
42         int x = 0,y;
43         char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
44
45         for(x=0;((line[x]) && (line[x] != stop));x++)
46             word[x] = line[x];
47
48         word[x] = '\0';
49         if(line[x])
50             ++x;
51         y=0;
52
53         while(line[x])
54           line[y++] = line[x++];
55         line[y] = '\0';
56         return word;
57     }
58
59     char* fmakeword(char stop, size_t *cl, const char** ppch)
60     {
61         int wsize;
62         char *word;
63         int ll;
64
65         wsize = 1024;
66         ll=0;
67         word = (char *) malloc(sizeof(char) * (wsize + 1));
68
69         while(1)
70         {
71             word[ll] = *((*ppch)++);
72             if(ll==wsize-1)
73             {
74                 word[ll+1] = '\0';
75                 wsize+=1024;
76                 word = (char *)realloc(word,sizeof(char)*(wsize+1));
77             }
78             --(*cl);
79             if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
80             {
81                 if(word[ll] != stop)
82                     ll++;
83                 word[ll] = '\0';
84                 return word;
85             }
86             ++ll;
87         }
88     }
89
90     void plustospace(char *str)
91     {
92         register int x;
93
94         for(x=0;str[x];x++)
95             if(str[x] == '+') str[x] = ' ';
96     }
97 }
98
99 CGIParser::CGIParser(const HTTPRequest& request, bool queryOnly)
100 {
101     parse(request.getQueryString());
102     if (!queryOnly && !strcmp(request.getMethod(),"POST")) {
103         if (request.getContentType().find("application/x-www-form-urlencoded") != string::npos)
104             parse(request.getRequestBody());
105     }
106 }
107
108 CGIParser::~CGIParser()
109 {
110     for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
111         free(i->second);
112 }
113
114 void CGIParser::parse(const char* pch)
115 {
116     size_t cl = pch ? strlen(pch) : 0;
117     const URLEncoder* dec = XMLToolingConfig::getConfig().getURLEncoder();
118     while (cl && pch) {
119         char *name;
120         char *value;
121         value=fmakeword('&', &cl, &pch);
122         plustospace(value);
123         dec->decode(value);
124         name=makeword(value, '=');
125         kvp_map.insert(pair<const string,char*>(name, value));
126         free(name);
127     }
128 }
129
130 pair<CGIParser::walker,CGIParser::walker> CGIParser::getParameters(const char* name) const
131 {
132     if (name)
133         return kvp_map.equal_range(name);
134     return make_pair(kvp_map.begin(), kvp_map.end());
135 }