summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--icespider/fcgi/cgiRequestBase.cpp31
-rw-r--r--icespider/fcgi/cgiRequestBase.h3
-rw-r--r--icespider/fcgi/xwwwFormUrlEncoded.cpp222
-rw-r--r--icespider/fcgi/xwwwFormUrlEncoded.h34
-rw-r--r--icespider/unittests/testFcgi.cpp9
5 files changed, 183 insertions, 116 deletions
diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp
index c36e11c..efa9468 100644
--- a/icespider/fcgi/cgiRequestBase.cpp
+++ b/icespider/fcgi/cgiRequestBase.cpp
@@ -1,4 +1,5 @@
#include "cgiRequestBase.h"
+#include "xwwwFormUrlEncoded.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
@@ -40,21 +41,9 @@ namespace IceSpider {
auto qs = envmap.find("QUERY_STRING");
if (qs != envmap.end()) {
- auto start = std::get<0>(qs->second);
- auto end = std::get<1>(qs->second);
- while (start < end) {
- auto amp = orelse(strchr(start, '&'), end);
- auto eq = orelse(strchr(start, '='), end);
- *amp = '\0';
- if (eq < amp) {
- *eq = '\0';
- qsmap.insert({ start, Env( eq + 1, amp ) });
- }
- else {
- qsmap.insert({ start, Env( eq + 1, eq + 1 ) });
- }
- start = amp + 1;
- }
+ XWwwFormUrlEncoded::iterateVars(std::string(std::get<0>(qs->second), std::get<1>(qs->second)), [this](auto k, auto v) {
+ qsmap.insert({ k, v });
+ });
}
}
@@ -63,11 +52,21 @@ namespace IceSpider {
{
auto i = vm.find(key.c_str());
if (i == vm.end()) {
- return IceUtil::Optional<std::string>();
+ return IceUtil::None;
}
return std::string(std::get<0>(i->second), std::get<1>(i->second));
}
+ OptionalString
+ CgiRequestBase::optionalLookup(const std::string & key, const StringMap & vm)
+ {
+ auto i = vm.find(key.c_str());
+ if (i == vm.end()) {
+ return IceUtil::None;
+ }
+ return i->second;
+ }
+
const PathElements &
CgiRequestBase::getRequestPath() const
{
diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h
index 97d956a..20d7d05 100644
--- a/icespider/fcgi/cgiRequestBase.h
+++ b/icespider/fcgi/cgiRequestBase.h
@@ -29,9 +29,10 @@ namespace IceSpider {
private:
static OptionalString optionalLookup(const std::string & key, const VarMap &);
+ static OptionalString optionalLookup(const std::string & key, const StringMap &);
VarMap envmap;
- VarMap qsmap;
+ StringMap qsmap;
PathElements pathElements;
};
}
diff --git a/icespider/fcgi/xwwwFormUrlEncoded.cpp b/icespider/fcgi/xwwwFormUrlEncoded.cpp
index a2ca9ee..2f60367 100644
--- a/icespider/fcgi/xwwwFormUrlEncoded.cpp
+++ b/icespider/fcgi/xwwwFormUrlEncoded.cpp
@@ -1,6 +1,5 @@
-#include <slicer/slicer.h>
+#include "xwwwFormUrlEncoded.h"
#include <exceptions.h>
-#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>
#include <Ice/BuiltinSequences.h>
@@ -10,116 +9,141 @@ extern long hextable[];
namespace IceSpider {
- class XWwwFormUrlEncoded : public Slicer::Deserializer {
+ XWwwFormUrlEncoded::XWwwFormUrlEncoded(std::istream & in) :
+ input(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>())
+ {
+ }
+
+ void
+ XWwwFormUrlEncoded::Deserialize(Slicer::ModelPartForRootPtr mp)
+ {
+ mp->Create();
+ mp->OnEachChild([this](auto, auto mp, auto) {
+ switch (mp->GetType()) {
+ case Slicer::mpt_Simple:
+ this->DeserializeSimple(mp);
+ break;
+ case Slicer::mpt_Complex:
+ this->DeserializeComplex(mp);
+ break;
+ case Slicer::mpt_Dictionary:
+ this->DeserializeDictionary(mp);
+ break;
+ default:
+ throw IceSpider::Http400_BadRequest();
+ break;
+ }
+ });
+ mp->Complete();
+ }
+
+ class SetFromString : public Slicer::ValueSource {
public:
- XWwwFormUrlEncoded(std::istream & in) :
- input(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>())
+ SetFromString(const std::string & v) : s(v)
{
}
- void Deserialize(Slicer::ModelPartForRootPtr mp) override
+ void set(bool & t) const override
{
- mp->Create();
- mp->OnEachChild([this](auto, auto mp, auto) {
- switch (mp->GetType()) {
- case Slicer::mpt_Simple:
- this->DeserializeSimple(mp);
- break;
- case Slicer::mpt_Complex:
- this->DeserializeComplex(mp);
- break;
- case Slicer::mpt_Dictionary:
- this->DeserializeDictionary(mp);
- break;
- default:
- throw IceSpider::Http400_BadRequest();
- break;
- }
- });
- mp->Complete();
+ if (s == "true") t = true;
+ else if (s == "false") t = false;
+ else throw Http400_BadRequest();
}
- private:
- class SetFromString : public Slicer::ValueSource {
- public:
- SetFromString(const std::string & v) : s(v)
- {
- }
-
- void set(bool & t) const override
- {
- if (s == "true") t = true;
- else if (s == "false") t = false;
- else throw Http400_BadRequest();
- }
-
- void set(std::string & t) const override
- {
- t.reserve(s.size());
- for (auto i = s.begin(); i != s.end(); i++) {
- if (*i == '+') t += ' ';
- else if (*i == '%') {
- t += (16 * hextable[(int)*++i]) + hextable[(int)*++i];
- }
- else t += *i;
- }
- }
+ void set(std::string & t) const override
+ {
+ t = s;
+ }
#define SET(T) \
- void set(T & t) const override \
- { \
- t = boost::lexical_cast<T>(s); \
- }
-
- SET(Ice::Byte);
- SET(Ice::Short);
- SET(Ice::Int);
- SET(Ice::Long);
- SET(Ice::Float);
- SET(Ice::Double);
- const std::string & s;
- };
-
- typedef boost::function<void(const std::string &, const std::string &)> KVh;
- void iterateVars(const KVh & h)
- {
- for (auto pi = ba::make_split_iterator(input, ba::first_finder("&", ba::is_equal())); pi != decltype(pi)(); ++pi) {
- auto eq = std::find(pi->begin(), pi->end(), '=');
- if (eq == pi->end()) {
- h(std::string(pi->begin(), pi->end()), std::string());
- }
- else {
- h(std::string(pi->begin(), eq), std::string(eq + 1, pi->end()));
- }
- }
+ void set(T & t) const override \
+ { \
+ t = boost::lexical_cast<T>(s); \
}
- void DeserializeSimple(Slicer::ModelPartPtr mp)
- {
- iterateVars([mp](auto, auto v) {
- mp->SetValue(new SetFromString(v));
- });
+
+ SET(Ice::Byte);
+ SET(Ice::Short);
+ SET(Ice::Int);
+ SET(Ice::Long);
+ SET(Ice::Float);
+ SET(Ice::Double);
+ const std::string & s;
+ };
+
+ std::string
+ XWwwFormUrlEncoded::urldecode(std::string::const_iterator i, std::string::const_iterator e)
+ {
+ std::string t;
+ t.reserve(&*e - &*i);
+ while (i != e) {
+ if (*i == '+') t += ' ';
+ else if (*i == '%') {
+ t += (16 * hextable[(int)*++i]) + hextable[(int)*++i];
}
- void DeserializeComplex(Slicer::ModelPartPtr mp)
- {
- mp->Create();
- iterateVars([mp](auto k, auto v) {
- if (auto m = mp->GetChild(k)) {
- m->SetValue(new SetFromString(v));
- }
- });
- mp->Complete();
+ else t += *i;
+ ++i;
+ }
+ return t;
+ }
+
+ void
+ XWwwFormUrlEncoded::iterateVars(const KVh & h, ba::split_iterator<std::string::const_iterator> pi)
+ {
+ for (; pi != decltype(pi)(); ++pi) {
+ auto eq = std::find(pi->begin(), pi->end(), '=');
+ if (eq == pi->end()) {
+ h(urldecode(pi->begin(), pi->end()), std::string());
}
- void DeserializeDictionary(Slicer::ModelPartPtr mp)
- {
- iterateVars([mp](auto k, auto v) {
- auto p = mp->GetAnonChild();
- p->GetChild("key")->SetValue(new SetFromString(k));
- p->GetChild("value")->SetValue(new SetFromString(v));
- p->Complete();
- });
+ else {
+ h(urldecode(pi->begin(), eq), urldecode(eq + 1, pi->end()));
}
- const std::string input;
- };
+ }
+ }
+
+ void
+ XWwwFormUrlEncoded::iterateVars(const std::string & input, const KVh & h)
+ {
+ if (!input.empty()) {
+ iterateVars(h, ba::make_split_iterator(input, ba::first_finder("&", ba::is_equal())));
+ }
+ }
+
+ void
+ XWwwFormUrlEncoded::iterateVars(const KVh & h)
+ {
+ iterateVars(input, h);
+ }
+
+ void
+ XWwwFormUrlEncoded::DeserializeSimple(Slicer::ModelPartPtr mp)
+ {
+ iterateVars([mp](auto, auto v) {
+ mp->SetValue(new SetFromString(v));
+ });
+ }
+
+ void
+ XWwwFormUrlEncoded::DeserializeComplex(Slicer::ModelPartPtr mp)
+ {
+ mp->Create();
+ iterateVars([mp](auto k, auto v) {
+ if (auto m = mp->GetChild(k)) {
+ m->SetValue(new SetFromString(v));
+ }
+ });
+ mp->Complete();
+ }
+
+ void
+ XWwwFormUrlEncoded::DeserializeDictionary(Slicer::ModelPartPtr mp)
+ {
+ iterateVars([mp](auto k, auto v) {
+ auto p = mp->GetAnonChild();
+ p->GetChild("key")->SetValue(new SetFromString(k));
+ p->GetChild("value")->SetValue(new SetFromString(v));
+ p->Complete();
+ });
+ }
}
NAMEDFACTORY("application/x-www-form-urlencoded", IceSpider::XWwwFormUrlEncoded, Slicer::StreamDeserializerFactory);
diff --git a/icespider/fcgi/xwwwFormUrlEncoded.h b/icespider/fcgi/xwwwFormUrlEncoded.h
new file mode 100644
index 0000000..fe6aa00
--- /dev/null
+++ b/icespider/fcgi/xwwwFormUrlEncoded.h
@@ -0,0 +1,34 @@
+#ifndef ICESPIDER_CGI_XWWWFORMURLENCODED_H
+#define ICESPIDER_CGI_XWWWFORMURLENCODED_H
+
+#include <slicer/serializer.h>
+#include <boost/algorithm/string/split.hpp>
+
+namespace IceSpider {
+ class XWwwFormUrlEncoded : public Slicer::Deserializer {
+ public:
+ typedef boost::function<void(const std::string &, const std::string &)> KVh;
+
+ XWwwFormUrlEncoded(std::istream & in);
+
+ void Deserialize(Slicer::ModelPartForRootPtr mp) override;
+ static inline void iterateVars(const std::string & input, const KVh & h);
+
+ private:
+
+ static inline void iterateVars(const KVh & h, boost::algorithm::split_iterator<std::string::const_iterator> pi);
+ static std::string urldecode(std::string::const_iterator s, std::string::const_iterator);
+
+ void iterateVars(const KVh & h);
+
+ void DeserializeSimple(Slicer::ModelPartPtr mp);
+ void DeserializeComplex(Slicer::ModelPartPtr mp);
+ void DeserializeDictionary(Slicer::ModelPartPtr mp);
+
+ const std::string input;
+ };
+
+};
+
+#endif
+
diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp
index 94ce092..923c28d 100644
--- a/icespider/unittests/testFcgi.cpp
+++ b/icespider/unittests/testFcgi.cpp
@@ -151,6 +151,15 @@ BOOST_AUTO_TEST_CASE( query_string_three )
BOOST_REQUIRE_EQUAL("3", *r.getQueryStringParam("three"));
}
+BOOST_AUTO_TEST_CASE( query_string_urlencoding )
+{
+ CharPtrPtrArray env ({ "SCRIPT_NAME=/foo/bar", "QUERY_STRING=url+%65ncoded=%53tring%2e" });
+ TestRequest r(this, env);
+ BOOST_REQUIRE(!r.getQueryStringParam(""));
+ BOOST_REQUIRE(r.getQueryStringParam("url encoded"));
+ BOOST_REQUIRE_EQUAL("String.", *r.getQueryStringParam("url encoded"));
+}
+
BOOST_AUTO_TEST_CASE( query_string_three_emptyVal )
{
CharPtrPtrArray env ({ "SCRIPT_NAME=/foo/bar", "QUERY_STRING=one=1&two=&three=3" });