https://issues.shibboleth.net/jira/browse/SSPCPP-335
authorScott Cantor <cantor.2@osu.edu>
Thu, 29 Sep 2011 04:04:45 +0000 (04:04 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 29 Sep 2011 04:04:45 +0000 (04:04 +0000)
shibsp/handler/impl/AbstractHandler.cpp
shibsp/impl/XMLRequestMapper.cpp
shibsp/util/CGIParser.cpp
shibsp/util/CGIParser.h

index 1b4cee1..5e95b39 100644 (file)
@@ -795,7 +795,7 @@ pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Applicati
 DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const
 {
     string contentType = request.getContentType();
-    if (contentType.compare("application/x-www-form-urlencoded") == 0) {
+    if (contentType.find("application/x-www-form-urlencoded") != string::npos) {
         const PropertySet* props=application.getPropertySet("Sessions");
         pair<bool,unsigned int> plimit = props ? props->getUnsignedInt("postLimit") : pair<bool,unsigned int>(false,0);
         if (!plimit.first)
index ad49533..f0cebd4 100644 (file)
@@ -28,6 +28,7 @@
 #include "AccessControl.h"
 #include "RequestMapper.h"
 #include "SPRequest.h"
+#include "util/CGIParser.h"
 #include "util/DOMPropertySet.h"
 #include "util/SPConstants.h"
 
@@ -450,23 +451,24 @@ const Override* Override::locate(const HTTPRequest& request) const
     }
 
     // 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 {
index 75ed711..27f4dc5 100644 (file)
@@ -35,97 +35,101 @@ using namespace shibsp;
 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] = ' ';
-}
index 0bafe0d..3e8c1c2 100644 (file)
@@ -51,11 +51,12 @@ namespace shibsp {
         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();
 
@@ -71,10 +72,7 @@ namespace shibsp {
         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;
     };