aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hex.h13
-rw-r--r--src/test.cpp4
-rw-r--r--src/util/string.cpp43
-rw-r--r--src/util/string.h3
4 files changed, 57 insertions, 6 deletions
diff --git a/src/hex.h b/src/hex.h
index 87a6aecb4..6f00a79bf 100644
--- 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
diff --git a/src/test.cpp b/src/test.cpp
index 5e025f2f5..c969c0951 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -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?\"");
}
};
diff --git a/src/util/string.cpp b/src/util/string.cpp
index 39a14598b..925d0ea35 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -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) {
diff --git a/src/util/string.h b/src/util/string.h
index 81855962f..e5a60bc47 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -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);