summaryrefslogtreecommitdiff
path: root/src/query_parser.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2015-05-28 21:14:52 +0200
committerJoel Klinghed <the_jk@yahoo.com>2015-05-28 21:16:14 +0200
commit720295848ea0d909cb39c004cbeaf1055fa7cffc (patch)
tree3a4c0332f8145986ddfc1c83e89b9cf8a1491546 /src/query_parser.cc
parent978bb2523f2eef42eca8dbe35e0ad351a4953aa7 (diff)
Start of CGI interface
Diffstat (limited to 'src/query_parser.cc')
-rw-r--r--src/query_parser.cc82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/query_parser.cc b/src/query_parser.cc
new file mode 100644
index 0000000..d957063
--- /dev/null
+++ b/src/query_parser.cc
@@ -0,0 +1,82 @@
+#include "common.hh"
+
+#include "query_parser.hh"
+
+namespace stuff {
+
+namespace {
+
+bool hex(char in, uint8_t* out) {
+ if (in >= '0' && in <= '9') {
+ *out = in - '0';
+ } else if (in >= 'A' && in <= 'F') {
+ *out = 10 + in - 'A';
+ } else if (in >= 'a' && in <= 'f') {
+ *out = 10 + in - 'a';
+ } else {
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+bool QueryParser::parse(const std::string& in,
+ std::map<std::string, std::string>* out) {
+ out->clear();
+ if (in.empty()) return true;
+ auto i = in.begin();
+ if (*i == '?' || *i == '&') {
+ ++i;
+ }
+ std::string key, value;
+ bool have_key = false;
+ while (true) {
+ char c;
+ if (i == in.end() || *i == '&') {
+ if (!have_key && key.empty()) return false;
+ (*out)[key] = value;
+ if (i == in.end()) return true;
+ have_key = false;
+ key.clear();
+ value.clear();
+ if (++i == in.end()) return true;
+ continue;
+ } else if (*i == '=') {
+ if (have_key) return false;
+ if (key.empty()) return false;
+ have_key = true;
+ ++i;
+ continue;
+ } else if (*i == '+') {
+ c = ' ';
+ } else if (*i == '%') {
+ if (++i == in.end()) return false;
+ uint8_t h, l;
+ if (!hex(*i, &h)) return false;
+ if (++i == in.end()) return false;
+ if (!hex(*i, &l)) return false;
+ c = (h << 4) | l;
+ } else if ((*i >= 'a' && *i <= 'z') ||
+ (*i >= '@' && *i <= 'Z') ||
+ (*i >= '0' && *i <= ';') ||
+ (*i >= '\'' && *i <= '*') ||
+ (*i >= ',' && *i <= '.') ||
+ *i == '!' || *i == '$' ||
+ *i == '_' || *i == '~') {
+ c = *i;
+ } else {
+ // Character not allowed
+ return false;
+ }
+ if (have_key) {
+ value.push_back(c);
+ } else {
+ key.push_back(c);
+ }
+ ++i;
+ }
+}
+
+
+} // namespace stuff