#include "AccessControl.h"
#include "RequestMapper.h"
#include "SPRequest.h"
+#include "util/CGIParser.h"
#include "util/DOMPropertySet.h"
#include "util/SPConstants.h"
}
// Finally, check for query string matches. This is another "unrolled" recursive descent in a loop.
- // For now, only check if the method is GET, to avoid consuming POST data. Will need to revise the
- // CGIParser API to fix this.
- if (strcmp(request.getMethod(), "POST")) {
+ // To avoid consuming any POST data, we use a dedicated CGIParser.
+ if (!o->m_queries.empty()) {
bool descended;
+ CGIParser cgi(request, true);
do {
descended = false;
for (vector< pair< pair<string,RegularExpression*>,Override*> >::const_iterator q = o->m_queries.begin(); !descended && q != o->m_queries.end(); ++q) {
- vector<const char*> vals;
- if (request.getParameters(q->first.first.c_str(), vals)) {
+ pair<CGIParser::walker,CGIParser::walker> vals = cgi.getParameters(q->first.first.c_str());
+ if (vals.first != vals.second) {
if (q->first.second) {
// We have to match one of the values.
- for (vector<const char*>::const_iterator v = vals.begin(); v != vals.end(); ++v) {
- if (q->first.second->matches(*v)) {
+ while (vals.first != vals.second) {
+ if (q->first.second->matches(vals.first->second)) {
o = q->second;
descended = true;
break;
}
+ ++vals.first;
}
}
else {
using namespace xmltooling;
using namespace std;
+namespace {
+ /* Parsing routines modified from NCSA source. */
+ char* makeword(char *line, char stop)
+ {
+ int x = 0,y;
+ char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
+
+ for(x=0;((line[x]) && (line[x] != stop));x++)
+ word[x] = line[x];
+
+ word[x] = '\0';
+ if(line[x])
+ ++x;
+ y=0;
+
+ while(line[x])
+ line[y++] = line[x++];
+ line[y] = '\0';
+ return word;
+ }
+
+ char* fmakeword(char stop, size_t *cl, const char** ppch)
+ {
+ int wsize;
+ char *word;
+ int ll;
+
+ wsize = 1024;
+ ll=0;
+ word = (char *) malloc(sizeof(char) * (wsize + 1));
+
+ while(1)
+ {
+ word[ll] = *((*ppch)++);
+ if(ll==wsize-1)
+ {
+ word[ll+1] = '\0';
+ wsize+=1024;
+ word = (char *)realloc(word,sizeof(char)*(wsize+1));
+ }
+ --(*cl);
+ if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
+ {
+ if(word[ll] != stop)
+ ll++;
+ word[ll] = '\0';
+ return word;
+ }
+ ++ll;
+ }
+ }
+
+ void plustospace(char *str)
+ {
+ register int x;
+
+ for(x=0;str[x];x++)
+ if(str[x] == '+') str[x] = ' ';
+ }
+}
+
+CGIParser::CGIParser(const HTTPRequest& request, bool queryOnly)
+{
+ parse(request.getQueryString());
+ if (!queryOnly && !strcmp(request.getMethod(),"POST")) {
+ if (request.getContentType().find("application/x-www-form-urlencoded") != string::npos)
+ parse(request.getRequestBody());
+ }
+}
+
+CGIParser::~CGIParser()
+{
+ for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
+ free(i->second);
+}
-CGIParser::CGIParser(const HTTPRequest& request)
+void CGIParser::parse(const char* pch)
{
- const char* pch=nullptr;
- if (!strcmp(request.getMethod(),"POST"))
- pch=request.getRequestBody();
- else
- pch=request.getQueryString();
- size_t cl=pch ? strlen(pch) : 0;
-
+ size_t cl = pch ? strlen(pch) : 0;
const URLEncoder* dec = XMLToolingConfig::getConfig().getURLEncoder();
while (cl && pch) {
char *name;
char *value;
- value=fmakeword('&',&cl,&pch);
+ value=fmakeword('&', &cl, &pch);
plustospace(value);
dec->decode(value);
- name=makeword(value,'=');
- kvp_map.insert(pair<const string,char*>(name,value));
+ name=makeword(value, '=');
+ kvp_map.insert(pair<const string,char*>(name, value));
free(name);
}
}
-CGIParser::~CGIParser()
-{
- for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
- free(i->second);
-}
-
pair<CGIParser::walker,CGIParser::walker> CGIParser::getParameters(const char* name) const
{
if (name)
return kvp_map.equal_range(name);
return make_pair(kvp_map.begin(), kvp_map.end());
}
-
-/* Parsing routines modified from NCSA source. */
-char* CGIParser::makeword(char *line, char stop)
-{
- int x = 0,y;
- char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
-
- for(x=0;((line[x]) && (line[x] != stop));x++)
- word[x] = line[x];
-
- word[x] = '\0';
- if(line[x])
- ++x;
- y=0;
-
- while(line[x])
- line[y++] = line[x++];
- line[y] = '\0';
- return word;
-}
-
-char* CGIParser::fmakeword(char stop, size_t *cl, const char** ppch)
-{
- int wsize;
- char *word;
- int ll;
-
- wsize = 1024;
- ll=0;
- word = (char *) malloc(sizeof(char) * (wsize + 1));
-
- while(1)
- {
- word[ll] = *((*ppch)++);
- if(ll==wsize-1)
- {
- word[ll+1] = '\0';
- wsize+=1024;
- word = (char *)realloc(word,sizeof(char)*(wsize+1));
- }
- --(*cl);
- if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
- {
- if(word[ll] != stop)
- ll++;
- word[ll] = '\0';
- return word;
- }
- ++ll;
- }
-}
-
-void CGIParser::plustospace(char *str)
-{
- register int x;
-
- for(x=0;str[x];x++)
- if(str[x] == '+') str[x] = ' ';
-}
MAKE_NONCOPYABLE(CGIParser);
public:
/**
- * Constructor
+ * Constructor.
*
* @param request HTTP request interface
+ * @param queryOnly true iff the POST body should be ignored
*/
- CGIParser(const xmltooling::HTTPRequest& request);
+ CGIParser(const xmltooling::HTTPRequest& request, bool queryOnly=false);
~CGIParser();
std::pair<walker,walker> getParameters(const char* name) const;
private:
- char* fmakeword(char stop, size_t *cl, const char** ppch);
- char* makeword(char *line, char stop);
- void plustospace(char *str);
-
+ void parse(const char* pch);
std::multimap<std::string,char*> kvp_map;
};