Boost changes
[shibboleth/cpp-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 <boost/bind.hpp>
31 #include <xmltooling/XMLToolingConfig.h>
32 #include <xmltooling/io/HTTPRequest.h>
33 #include <xmltooling/util/URLEncoder.h>
34
35 using namespace shibsp;
36 using namespace xmltooling;
37 using namespace boost;
38 using namespace std;
39
40 namespace {
41     /* Parsing routines modified from NCSA source. */
42     char* makeword(char *line, char stop)
43     {
44         int x = 0,y;
45         char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
46
47         for(x=0;((line[x]) && (line[x] != stop));x++)
48             word[x] = line[x];
49
50         word[x] = '\0';
51         if(line[x])
52             ++x;
53         y=0;
54
55         while(line[x])
56           line[y++] = line[x++];
57         line[y] = '\0';
58         return word;
59     }
60
61     char* fmakeword(char stop, size_t *cl, const char** ppch)
62     {
63         int wsize;
64         char *word;
65         int ll;
66
67         wsize = 1024;
68         ll=0;
69         word = (char *) malloc(sizeof(char) * (wsize + 1));
70
71         while(1)
72         {
73             word[ll] = *((*ppch)++);
74             if(ll==wsize-1)
75             {
76                 word[ll+1] = '\0';
77                 wsize+=1024;
78                 word = (char *)realloc(word,sizeof(char)*(wsize+1));
79             }
80             --(*cl);
81             if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
82             {
83                 if(word[ll] != stop)
84                     ll++;
85                 word[ll] = '\0';
86                 return word;
87             }
88             ++ll;
89         }
90     }
91
92     void plustospace(char *str)
93     {
94         register int x;
95
96         for(x=0;str[x];x++)
97             if(str[x] == '+') str[x] = ' ';
98     }
99 }
100
101 CGIParser::CGIParser(const HTTPRequest& request, bool queryOnly)
102 {
103     parse(request.getQueryString());
104     if (!queryOnly && !strcmp(request.getMethod(),"POST")) {
105         if (request.getContentType().find("application/x-www-form-urlencoded") != string::npos)
106             parse(request.getRequestBody());
107     }
108 }
109
110 CGIParser::~CGIParser()
111 {
112     for_each(kvp_map.begin(), kvp_map.end(), boost::bind<void>(&free, boost::bind(&multimap<string,char*>::value_type::second, _1)));
113 }
114
115 void CGIParser::parse(const char* pch)
116 {
117     size_t cl = pch ? strlen(pch) : 0;
118     const URLEncoder* dec = XMLToolingConfig::getConfig().getURLEncoder();
119     while (cl && pch) {
120         char *name;
121         char *value;
122         value=fmakeword('&', &cl, &pch);
123         plustospace(value);
124         dec->decode(value);
125         name=makeword(value, '=');
126         kvp_map.insert(pair<const string,char*>(name, value));
127         free(name);
128     }
129 }
130
131 pair<CGIParser::walker,CGIParser::walker> CGIParser::getParameters(const char* name) const
132 {
133     if (name)
134         return kvp_map.equal_range(name);
135     return make_pair(kvp_map.begin(), kvp_map.end());
136 }