diff options
Diffstat (limited to 'sca-cpp/trunk/modules/http/http.hpp')
-rw-r--r-- | sca-cpp/trunk/modules/http/http.hpp | 98 |
1 files changed, 81 insertions, 17 deletions
diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index 7050021fb9..1a207669c0 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -30,6 +30,8 @@ #include <curl/curl.h> #include <curl/types.h> #include <curl/easy.h> +#include <apr.h> +#include <apr_lib.h> #include <apr_network_io.h> #include <apr_portable.h> #include <apr_poll.h> @@ -93,6 +95,7 @@ private: friend CURL* handle(const CURLSession& cs); friend apr_socket_t* sock(const CURLSession& cs); + friend const failable<CURL*> setup(const string& url, const CURLSession& cs); friend const failable<bool> connect(const string& url, CURLSession& cs); friend const failable<bool> send(const char* c, const size_t l, const CURLSession& cs); friend const failable<size_t> recv(char* c, const size_t l, const CURLSession& cs); @@ -143,6 +146,45 @@ const string apreason(apr_status_t rc) { } /** + * Escape a URI or a query argument. + */ +const char escape_c2x[] = "0123456789ABCDEF"; + +const string escape(const string& unesc, const char* reserv) { + char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(unesc) + 3); + const unsigned char* s = (const unsigned char *)c_str(unesc); + unsigned char* d = (unsigned char*)copy; + unsigned c; + while ((c = *s)) { + if (!apr_isalnum(c) && !strchr(reserv, c)) { + *d++ = '%'; + *d++ = escape_c2x[c >> 4]; + *d++ = escape_c2x[c & 0xf]; + } + else { + *d++ = (unsigned char)c; + } + ++s; + } + *d = '\0'; + return copy; +} + +const string escapeURI(const string& uri) { + debug(uri, "http::escapeURI::uri"); + const string e = escape(uri, "?$-_.+!*'(),:@&=/~%"); + debug(e, "http::escapeURI::result"); + return e; +} + +const string escapeArg(const string& arg) { + debug(arg, "http::escapeArg::arg"); + const string e = escape(arg, "-_.~"); + debug(e, "http::escapeArg::result"); + return e; +} + +/** * Setup a CURL session */ const failable<CURL*> setup(const string& url, const CURLSession& cs) { @@ -177,7 +219,7 @@ const failable<CURL*> setup(const string& url, const CURLSession& cs) { } // Set target URL - curl_easy_setopt(ch, CURLOPT_URL, c_str(url)); + curl_easy_setopt(ch, CURLOPT_URL, c_str(escapeURI(url))); return ch; } @@ -430,6 +472,22 @@ const failable<value> get(const string& url, const CURLSession& cs) { debug(val, "http::get::result"); return val; } + if (contains(ct, "application/x-javascript")) { + // Read a JSON document enclosed in a javascript function call + // Extract the JSON out of the enclosing parenthesis + ostringstream os; + write(ls, os); + const string s = str(os); + const size_t fp = find(s, '('); + const size_t lp = find_last(s, ')'); + const list<string> jls = mklist<string>(substr(s, fp + 1, lp - (fp + 1))); + debug(jls, "http::get::javascript::content"); + + js::JSContext cx; + const value val(json::jsonValues(content(json::readJSON(jls, cx)))); + debug(val, "http::get::result"); + return val; + } if (contains(ct, "text/xml") || contains(ct, "application/xml") || isXML(ls)) { // Read an XML document const value val(elementsToValues(readXML(ls))); @@ -620,6 +678,23 @@ const failable<size_t> recv(char* c, const size_t l, const CURLSession& cs) { return recv(c, l, cs); } +/** + * Converts a list of key value pairs to a query string. + */ +ostringstream& queryString(const list<list<value> > args, ostringstream& os) { + if (isNil(args)) + return os; + debug(car(args), "http::queryString::arg"); + os << car(car(args)) << "=" << c_str(cadr(car(args))); + if (!isNil(cdr(args))) + os << "&"; + return queryString(cdr(args), os); +} + +const string queryString(const list<list<value> > args) { + ostringstream os; + return str(queryString(args, os)); +} /** * Filter path segment in a list of arguments. @@ -636,21 +711,11 @@ const bool filterQuery(const value& arg) { } /** - * Converts a list of key value pairs to a query string. + * Escape a query string argument. */ -ostringstream& queryString(const list<list<value> > args, ostringstream& os) { - if (isNil(args)) - return os; - debug(car(args), "http::queryString::arg"); - os << car(car(args)) << "=" << c_str(cadr(car(args))); - if (!isNil(cdr(args))) - os << "&"; - return queryString(cdr(args), os); -} - -const string queryString(const list<list<value> > args) { - ostringstream os; - return str(queryString(args, os)); +const value escapeQuery(const value& arg) { + return arg; + //return mklist<value>(car<value>(arg), escapeArg(cadr<value>(arg))); } /** @@ -665,8 +730,7 @@ struct proxy { if (fun == "get") { const list<value> lp = filter<value>(filterPath, cadr(args)); debug(lp, "http::queryString::arg"); - const list<value> lq = filter<value>(filterQuery, cadr(args)); - debug(lq, "http::get::query"); + const list<value> lq = map<value, value>(escapeQuery, filter<value>(filterQuery, cadr(args))); const value p = path(lp); const value q = queryString(lq); const failable<value> val = get(uri + p + (q != ""? string("?") + q : string("")), cs); |