Implement urlencode and urldecode
authorKahrl <kahrl@gmx.net>
Thu, 29 Aug 2013 03:56:48 +0000 (05:56 +0200)
committerKahrl <kahrl@gmx.net>
Fri, 13 Dec 2013 17:05:35 +0000 (18:05 +0100)
src/hex.h
src/test.cpp
src/util/string.cpp
src/util/string.h

index 87a6aecb4df04bd65dc9060de3959f33aeb77e68..6f00a79bff0a451115f4e1230fc1aa430d71203c 100644 (file)
--- a/src/hex.h
+++ b/src/hex.h
@@ -46,4 +46,17 @@ static inline std::string hex_encode(const std::string &data)
     return hex_encode(data.c_str(), data.size());
 }
 
+static inline bool hex_digit_decode(char hexdigit, unsigned char &value)
+{
+       if(hexdigit >= '0' && hexdigit <= '9')
+               value = hexdigit - '0';
+       else if(hexdigit >= 'A' && hexdigit <= 'F')
+               value = hexdigit - 'A' + 10;
+       else if(hexdigit >= 'a' && hexdigit <= 'f')
+               value = hexdigit - 'a' + 10;
+       else
+               return false;
+       return true;
+}
+
 #endif
index 5e025f2f5fb23164165a1b2ca80f97b871c279b6..c969c0951a76f72e859d7f88d9b723677eb7657a 100644 (file)
@@ -171,6 +171,10 @@ struct TestUtilities: public TestBase
                UASSERT(removeStringEnd("bc", ends) == "b");
                UASSERT(removeStringEnd("12c", ends) == "12");
                UASSERT(removeStringEnd("foo", ends) == "");
+               UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
+                               == "%22Aardvarks%20lurk%2C%20OK%3F%22");
+               UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
+                               == "\"Aardvarks lurk, OK?\"");
        }
 };
 
index 39a14598b5ca55ac59ac96ce5a720fc893143d15..925d0ea35f4cdc9fed8e7a55e73ff4832a2f7753 100644 (file)
@@ -21,8 +21,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "pointer.h"
 #include "numeric.h"
 
+#include <sstream>
+#include <iomanip>
+
 #include "../sha1.h"
 #include "../base64.h"
+#include "../hex.h"
 #include "../porting.h"
 
 std::wstring narrow_to_wide(const std::string& mbs)
@@ -68,11 +72,40 @@ std::string translatePassword(std::string playername, std::wstring password)
        return pwd;
 }
 
-size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
-    std::ostringstream *stream = (std::ostringstream*)userdata;
-    size_t count = size * nmemb;
-    stream->write(ptr, count);
-    return count;
+std::string urlencode(std::string str)
+{
+       // Encodes non-unreserved URI characters by a percent sign
+       // followed by two hex digits. See RFC 3986, section 2.3.
+       static const char url_hex_chars[] = "0123456789ABCDEF";
+       std::ostringstream oss(std::ios::binary);
+       for (u32 i = 0; i < str.size(); i++) {
+               unsigned char c = str[i];
+               if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')
+                       oss << c;
+               else
+                       oss << "%"
+                               << url_hex_chars[(c & 0xf0) >> 4]
+                               << url_hex_chars[c & 0x0f];
+       }
+       return oss.str();
+}
+
+std::string urldecode(std::string str)
+{
+       // Inverse of urlencode
+       std::ostringstream oss(std::ios::binary);
+       for (u32 i = 0; i < str.size(); i++) {
+               unsigned char highvalue, lowvalue;
+               if (str[i] == '%' &&
+                               hex_digit_decode(str[i+1], highvalue) &&
+                               hex_digit_decode(str[i+2], lowvalue)) {
+                       oss << (char) ((highvalue << 4) | lowvalue);
+                       i += 2;
+               }
+               else
+                       oss << str[i];
+       }
+       return oss.str();
 }
 
 u32 readFlagString(std::string str, FlagDesc *flagdesc) {
index 81855962f971d590f9d4583f1c7a1f23083c4395..e5a60bc47162824770b8e2af78270fa5d4cba609 100644 (file)
@@ -317,7 +317,8 @@ inline std::string unescape_string(std::string &s)
 }
 
 std::string translatePassword(std::string playername, std::wstring password);
-size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata);
+std::string urlencode(std::string str);
+std::string urldecode(std::string str);
 u32 readFlagString(std::string str, FlagDesc *flagdesc);
 std::string writeFlagString(u32 flags, FlagDesc *flagdesc);
 char *mystrtok_r(char *s, const char *sep, char **lasts);