From bfec6fffb4acd9673ecf066a0e4f1b4baf2dd831 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 25 Dec 2017 08:37:54 +0300 Subject: Make use of butl url encode() and decode() functions --- mod/build-config.cxx | 4 +- mod/mod-package-details.cxx | 2 +- mod/mod-package-version-details.cxx | 6 +- mod/mod-repository-details.cxx | 4 +- mod/page.cxx | 8 +-- web/apache/request.cxx | 27 ++++---- web/mime-url-encoding.cxx | 124 ++++++++---------------------------- web/mime-url-encoding.hxx | 23 ++++--- 8 files changed, 71 insertions(+), 127 deletions(-) diff --git a/mod/build-config.cxx b/mod/build-config.cxx index aa25511..cbde252 100644 --- a/mod/build-config.cxx +++ b/mod/build-config.cxx @@ -118,9 +118,9 @@ namespace brep // the package version into the URL path part and so don't encode it. // string url (host + root.representation () + - mime_url_encode (b.package_name) + '/' + + mime_url_encode (b.package_name, false) + '/' + b.package_version.string () + "/log/" + - mime_url_encode (b.configuration) + '/' + + mime_url_encode (b.configuration, false) + '/' + b.toolchain_version.string ()); if (op != nullptr) diff --git a/mod/mod-package-details.cxx b/mod/mod-package-details.cxx index dce7f3b..ca2b94a 100644 --- a/mod/mod-package-details.cxx +++ b/mod/mod-package-details.cxx @@ -75,7 +75,7 @@ handle (request& rq, response& rs) const dir_path& root (options_->root ()); const string& name (*rq.path ().rbegin ()); - const string ename (mime_url_encode (name)); + const string ename (mime_url_encode (name, false)); params::package_details params; bool full; diff --git a/mod/mod-package-version-details.cxx b/mod/mod-package-version-details.cxx index 134fb9a..26838f7 100644 --- a/mod/mod-package-version-details.cxx +++ b/mod/mod-package-version-details.cxx @@ -130,7 +130,9 @@ handle (request& rq, response& rs) s << DIV(ID="heading") << H1 - << A(HREF=root / path (mime_url_encode (name))) << name << ~A + << A(HREF=root / path (mime_url_encode (name, false))) + << name + << ~A << "/" << A(HREF=url ()) << sver << ~A << ~H1 @@ -255,7 +257,7 @@ handle (request& rq, response& rs) const auto& dcon (d.constraint); const string& dname (p->id.name); - string ename (mime_url_encode (dname)); + string ename (mime_url_encode (dname, false)); if (r->url) { diff --git a/mod/mod-repository-details.cxx b/mod/mod-repository-details.cxx index 177f49d..53cd3aa 100644 --- a/mod/mod-repository-details.cxx +++ b/mod/mod-repository-details.cxx @@ -99,7 +99,9 @@ handle (request& rq, response& rs) // string id (html_id (r.name)); s << H1(ID=id) - << A(HREF="#" + web::mime_url_encode (id)) << r.display_name << ~A + << A(HREF="#" + web::mime_url_encode (id, false)) + << r.display_name + << ~A << ~H1; if (r.summary) diff --git a/mod/page.cxx b/mod/page.cxx index a7ec087..566406e 100644 --- a/mod/page.cxx +++ b/mod/page.cxx @@ -188,7 +188,7 @@ namespace brep // Propagate search criteria to the package details page. // - << root_ / path (mime_url_encode (name_)) << query_param_ + << root_ / path (mime_url_encode (name_, false)) << query_param_ << ~HREF << name_ @@ -218,7 +218,7 @@ namespace brep else { assert (root_ != nullptr); - s << A(HREF=*root_ / dir_path (mime_url_encode (*package_)) / + s << A(HREF=*root_ / dir_path (mime_url_encode (*package_, false)) / path (version_)) << version_; @@ -393,7 +393,7 @@ namespace brep ? p->internal_repository.load () : p->other_repositories[0].load ()); - auto en (mime_url_encode (n)); + auto en (mime_url_encode (n, false)); if (r->url) s << A(HREF=*r->url + en) << n << ~A; @@ -542,7 +542,7 @@ namespace brep << SPAN(CLASS="value") << A << HREF - << root_ << "?about#" << mime_url_encode (html_id (name_)) + << root_ << "?about#" << mime_url_encode (html_id (name_), false) << ~HREF << name_ << ~A diff --git a/web/apache/request.cxx b/web/apache/request.cxx index 3393555..51590e3 100644 --- a/web/apache/request.cxx +++ b/web/apache/request.cxx @@ -18,7 +18,6 @@ #include // unique_ptr #include #include -#include #include #include #include // str*(), memcpy(), size_t @@ -353,7 +352,7 @@ namespace web { if (path_.empty ()) { - path_ = path_type (rec_->uri); + path_ = path_type (rec_->uri); // Is already URL-decoded. // Module request handler can not be called if URI is empty. // @@ -514,10 +513,9 @@ namespace web { assert (!buffer); // Cookie buffering is not implemented yet. - ostringstream s; - mime_url_encode (name, s); - s << "="; - mime_url_encode (value, s); + string s (mime_url_encode (name)); + s += "="; + s += mime_url_encode (value); if (max_age) { @@ -528,20 +526,27 @@ namespace web // char b[100]; strftime (b, sizeof (b), "%a, %d-%b-%Y %H:%M:%S GMT", gmtime (&t)); - s << "; Expires=" << b; + s += "; Expires="; + s += b; } if (path) - s << ";Path=" << path; + { + s += ";Path="; + s += path; + } if (domain) - s << ";Domain=" << domain; + { + s += ";Domain="; + s += domain; + } if (secure) - s << ";Secure"; + s += ";Secure"; state (request_state::headers); - apr_table_add (rec_->err_headers_out, "Set-Cookie", s.str ().c_str ()); + apr_table_add (rec_->err_headers_out, "Set-Cookie", s.c_str ()); } void request:: diff --git a/web/mime-url-encoding.cxx b/web/mime-url-encoding.cxx index e0022bc..00f8852 100644 --- a/web/mime-url-encoding.cxx +++ b/web/mime-url-encoding.cxx @@ -4,132 +4,64 @@ #include -#include // hex, uppercase, right #include -#include // setw(), setfill() -#include -#include -#include // size_t, strspn() -#include // invalid_argument +#include // back_inserter + +#include using namespace std; +using namespace butl; namespace web { - // Encode characters different from unreserved ones specified in - // "2.3. Unreserved Characters" of http://tools.ietf.org/html/rfc3986. - // - void - mime_url_encode (const char* v, ostream& o) + inline static bool + encode_query (char& c) { - char f (o.fill ()); - ostream::fmtflags g (o.flags ()); - o << hex << uppercase << right << setfill ('0'); - - char c; - while ((c = *v++) != '\0') + if (c == ' ') { - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9')) - { - o << c; - } - else - { - switch (c) - { - case ' ': o << '+'; break; - case '.': - case '_': - case '-': - case '~': o << c; break; - default: - { - o << "%" << setw (2) << static_cast (c); - break; - } - } - } + c = '+'; + return false; } - o.flags (g); - o.fill (f); + return !url::unreserved (c); } string - mime_url_encode (const char* v) + mime_url_encode (const char* v, bool query) { - stringstream o; - mime_url_encode (v, o); - return o.str (); + return query ? url::encode (v, encode_query) : url::encode (v); } string - mime_url_encode (const string& v) + mime_url_encode (const string& v, bool query) { - return mime_url_encode (v.c_str ()); + return query ? url::encode (v, encode_query) : url::encode (v); } string - mime_url_decode (const char* b, const char* e, bool trim) + mime_url_decode (const char* b, const char* e, bool trim, bool query) { if (trim) { - b += strspn (b, " "); + for (; b != e && *b == ' '; ++b) ; - if (b >= e) + if (b == e) return string (); while (*--e == ' '); ++e; } - string value; - value.reserve (e - b); - - char bf[3]; - bf[2] = '\0'; - - while (b != e) - { - char c (*b++); - switch (c) - { - case '+': - { - value.append (" "); - break; - } - case '%': - { - if (*b == '\0' || b[1] == '\0') - { - throw invalid_argument ("::web::mime_url_decode short"); - } - - *bf = *b; - bf[1] = b[1]; - - char* ebf (nullptr); - size_t vl (strtoul (bf, &ebf, 16)); - - if (*ebf != '\0') - { - throw invalid_argument ("::web::mime_url_decode wrong"); - } - - value.append (1, static_cast (vl)); - b += 2; - break; - } - default: - { - value.append (1, c); - break; - } - } - } - - return value; + string r; + if (!query) + url::decode (b, e, back_inserter (r)); + else + url::decode (b, e, back_inserter (r), + [] (char& c) + { + if (c == '+') + c = ' '; + }); + return r; } } diff --git a/web/mime-url-encoding.hxx b/web/mime-url-encoding.hxx index d45f4ca..f748738 100644 --- a/web/mime-url-encoding.hxx +++ b/web/mime-url-encoding.hxx @@ -6,25 +6,28 @@ #define WEB_MIME_URL_ENCODING_HXX #include -#include namespace web { - // @@ Add the query flag (true by default). If true, then the encoding is - // applied to the URL query part, and so the plus character is used to - // encode the space character. Audit use cases afterwards. + // URL-encode characters other than unreserved (see RFC3986). If the query + // flag is true, then the encoding is applied to the URL query part, and so + // convert space characters to plus characters rather than percent-encode + // them. // - void - mime_url_encode (const char* v, std::ostream& o); - std::string - mime_url_encode (const char* v); + mime_url_encode (const char*, bool query = true); std::string - mime_url_encode (const std::string& v); + mime_url_encode (const std::string&, bool query = true); + // If the query flag is true, then convert plus characters to space + // characters (see above). Throw std::invalid_argument if an invalid encoding + // sequence is encountered. + // std::string - mime_url_decode (const char* b, const char* e, bool trim = false); + mime_url_decode (const char* b, const char* e, + bool trim = false, + bool query = true); } #endif // WEB_MIME_URL_ENCODING_HXX -- cgit v1.1