aboutsummaryrefslogtreecommitdiff
path: root/web/mime-url-encoding.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'web/mime-url-encoding.cxx')
-rw-r--r--web/mime-url-encoding.cxx135
1 files changed, 135 insertions, 0 deletions
diff --git a/web/mime-url-encoding.cxx b/web/mime-url-encoding.cxx
new file mode 100644
index 0000000..1d68bf3
--- /dev/null
+++ b/web/mime-url-encoding.cxx
@@ -0,0 +1,135 @@
+// file : web/mime-url-encoding.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <web/mime-url-encoding>
+
+#include <ios> // hex, uppercase, right
+#include <string>
+#include <iomanip> // setw(), setfill ()
+#include <ostream>
+#include <sstream>
+#include <cstring> // size_t, strspn()
+#include <stdexcept> // invalid_argument
+
+using namespace std;
+
+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)
+ {
+ char f (o.fill ());
+ ostream::fmtflags g (o.flags ());
+ o << hex << uppercase << right << setfill ('0');
+
+ char c;
+ while ((c = *v++) != '\0')
+ {
+ 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<unsigned short> (c);
+ break;
+ }
+ }
+ }
+ }
+
+ o.flags (g);
+ o.fill (f);
+ }
+
+ string
+ mime_url_encode (const char* v)
+ {
+ stringstream o;
+ mime_url_encode (v, o);
+ return o.str ();
+ }
+
+ string
+ mime_url_encode (const string& v)
+ {
+ return mime_url_encode (v.c_str ());
+ }
+
+ string
+ mime_url_decode (const char* b, const char* e, bool trim)
+ {
+ if (trim)
+ {
+ b += strspn (b, " ");
+
+ 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<char> (vl));
+ b += 2;
+ break;
+ }
+ default:
+ {
+ value.append (1, c);
+ break;
+ }
+ }
+ }
+
+ return value;
+ }
+}