#include "numeric.h"
#include "log.h"
-#include "base64.h"
#include "hex.h"
-#include "sha1.h"
#include "../porting.h"
#include <algorithm>
#include <iomanip>
#include <map>
-#if defined(_WIN32)
-#include <windows.h> // MultiByteToWideChar
+#ifndef _WIN32
+ #include <iconv.h>
+#else
+ #define _WIN32_WINNT 0x0501
+ #include <windows.h>
+#endif
+
+#if defined(_ICONV_H_) && (defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__) || defined(__DragonFly__))
+ #define BSD_ICONV_USED
#endif
static bool parseHexColorString(const std::string &value, video::SColor &color);
static bool parseNamedColorString(const std::string &value, video::SColor &color);
+#ifndef _WIN32
+
+bool convert(const char *to, const char *from, char *outbuf,
+ size_t outbuf_size, char *inbuf, size_t inbuf_size)
+{
+ iconv_t cd = iconv_open(to, from);
+
+#ifdef BSD_ICONV_USED
+ const char *inbuf_ptr = inbuf;
+#else
+ char *inbuf_ptr = inbuf;
+#endif
+
+ char *outbuf_ptr = outbuf;
+
+ size_t *inbuf_left_ptr = &inbuf_size;
+ size_t *outbuf_left_ptr = &outbuf_size;
+
+ size_t old_size = inbuf_size;
+ while (inbuf_size > 0) {
+ iconv(cd, &inbuf_ptr, inbuf_left_ptr, &outbuf_ptr, outbuf_left_ptr);
+ if (inbuf_size == old_size) {
+ iconv_close(cd);
+ return false;
+ }
+ old_size = inbuf_size;
+ }
+
+ iconv_close(cd);
+ return true;
+}
+
+std::wstring utf8_to_wide(const std::string &input)
+{
+ size_t inbuf_size = input.length() + 1;
+ // maximum possible size, every character is sizeof(wchar_t) bytes
+ size_t outbuf_size = (input.length() + 1) * sizeof(wchar_t);
+
+ char *inbuf = new char[inbuf_size];
+ memcpy(inbuf, input.c_str(), inbuf_size);
+ char *outbuf = new char[outbuf_size];
+ memset(outbuf, 0, outbuf_size);
+
+ if (!convert("WCHAR_T", "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size)) {
+ infostream << "Couldn't convert UTF-8 string 0x" << hex_encode(input)
+ << " into wstring" << std::endl;
+ delete[] inbuf;
+ delete[] outbuf;
+ return L"<invalid UTF-8 string>";
+ }
+ std::wstring out((wchar_t *)outbuf);
+
+ delete[] inbuf;
+ delete[] outbuf;
+
+ return out;
+}
+
+#ifdef __ANDROID__
+// TODO: this is an ugly fix for wide_to_utf8 somehow not working on android
+std::string wide_to_utf8(const std::wstring &input)
+{
+ return wide_to_narrow(input);
+}
+#else
+std::string wide_to_utf8(const std::wstring &input)
+{
+ size_t inbuf_size = (input.length() + 1) * sizeof(wchar_t);
+ // maximum possible size: utf-8 encodes codepoints using 1 up to 6 bytes
+ size_t outbuf_size = (input.length() + 1) * 6;
+
+ char *inbuf = new char[inbuf_size];
+ memcpy(inbuf, input.c_str(), inbuf_size);
+ char *outbuf = new char[outbuf_size];
+ memset(outbuf, 0, outbuf_size);
+
+ if (!convert("UTF-8", "WCHAR_T", outbuf, outbuf_size, inbuf, inbuf_size)) {
+ infostream << "Couldn't convert wstring 0x" << hex_encode(inbuf, inbuf_size)
+ << " into UTF-8 string" << std::endl;
+ delete[] inbuf;
+ delete[] outbuf;
+ return "<invalid wstring>";
+ }
+ std::string out(outbuf);
+
+ delete[] inbuf;
+ delete[] outbuf;
+
+ return out;
+}
+
+#endif
+#else // _WIN32
+
+std::wstring utf8_to_wide(const std::string &input)
+{
+ size_t outbuf_size = input.size() + 1;
+ wchar_t *outbuf = new wchar_t[outbuf_size];
+ memset(outbuf, 0, outbuf_size * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.size(),
+ outbuf, outbuf_size);
+ std::wstring out(outbuf);
+ delete[] outbuf;
+ return out;
+}
+
+std::string wide_to_utf8(const std::wstring &input)
+{
+ size_t outbuf_size = (input.size() + 1) * 6;
+ char *outbuf = new char[outbuf_size];
+ memset(outbuf, 0, outbuf_size);
+ WideCharToMultiByte(CP_UTF8, 0, input.c_str(), input.size(),
+ outbuf, outbuf_size, NULL, NULL);
+ std::string out(outbuf);
+ delete[] outbuf;
+ return out;
+}
+
+#endif // _WIN32
+
+wchar_t *utf8_to_wide_c(const char *str)
+{
+ std::wstring ret = utf8_to_wide(std::string(str)).c_str();
+ size_t len = ret.length();
+ wchar_t *ret_c = new wchar_t[len + 1];
+ memset(ret_c, 0, (len + 1) * sizeof(wchar_t));
+ memcpy(ret_c, ret.c_str(), len * sizeof(wchar_t));
+ return ret_c;
+}
+
+// You must free the returned string!
+// The returned string is allocated using new
+wchar_t *narrow_to_wide_c(const char *str)
+{
+ wchar_t *nstr = NULL;
+#if defined(_WIN32)
+ int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, 0, 0);
+ if (nResult == 0) {
+ errorstream<<"gettext: MultiByteToWideChar returned null"<<std::endl;
+ } else {
+ nstr = new wchar_t[nResult];
+ MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, (WCHAR *) nstr, nResult);
+ }
+#else
+ size_t len = strlen(str);
+ nstr = new wchar_t[len + 1];
+
+ std::wstring intermediate = narrow_to_wide(str);
+ memset(nstr, 0, (len + 1) * sizeof(wchar_t));
+ memcpy(nstr, intermediate.c_str(), len * sizeof(wchar_t));
+#endif
+
+ return nstr;
+}
+
+
#ifdef __ANDROID__
const wchar_t* wide_chars =
int mbtowc(wchar_t *pwc, const char *s, size_t n)
{
- if (s == NULL || *s == '\0')
- return -1;
+ std::wstring intermediate = narrow_to_wide(s);
- const wchar_t *tmp = narrow_to_wide_c(s);
- bool success = tmp[0] != '\0';
+ if (intermediate.length() > 0) {
+ *pwc = intermediate[0];
+ return 1;
+ }
+ else {
+ return -1;
+ }
+}
- if (success)
- *pwc = tmp[0];
+std::wstring narrow_to_wide(const std::string &mbs) {
+ size_t wcl = mbs.size();
- delete tmp;
+ std::wstring retval = L"";
- return success ? 1 : -1;
-}
+ for (unsigned int i = 0; i < wcl; i++) {
+ if (((unsigned char) mbs[i] >31) &&
+ ((unsigned char) mbs[i] < 127)) {
-// You must free the returned string!
-const wchar_t *narrow_to_wide_c(const char *mbs)
-{
- size_t mbl = strlen(mbs);
- wchar_t *wcs = new wchar_t[mbl + 1];
-
- for (size_t i = 0; i < mbl; i++) {
- if (((unsigned char) mbs[i] > 31) &&
- ((unsigned char) mbs[i] < 127)) {
- wcs[i] = wide_chars[(unsigned char) mbs[i] - 32];
+ retval += wide_chars[(unsigned char) mbs[i] -32];
}
//handle newline
else if (mbs[i] == '\n') {
- wcs[i] = L'\n';
+ retval += L'\n';
}
}
- return wcs;
-}
-
-#else
-
-// You must free the returned string!
-const wchar_t *narrow_to_wide_c(const char *mbs)
-{
- wchar_t *wcs = NULL;
-#if defined(_WIN32)
- int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, 0, 0);
- if (nResult == 0) {
- errorstream << "gettext: MultiByteToWideChar returned null" << std::endl;
- } else {
- wcs = new wchar_t[nResult];
- MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, nResult);
- }
-#else
- size_t wcl = mbstowcs(NULL, mbs, 0);
- if (wcl == (size_t) -1)
- return NULL;
- wcs = new wchar_t[wcl + 1];
- size_t l = mbstowcs(wcs, mbs, wcl);
- assert(l != (size_t) -1); // Should never happen if the last call worked
- wcs[l] = '\0';
-#endif
-
- return wcs;
+ return retval;
}
-#endif
+#else // not Android
-std::wstring narrow_to_wide(const std::string& mbs)
+std::wstring narrow_to_wide(const std::string &mbs)
{
size_t wcl = mbs.size();
Buffer<wchar_t> wcs(wcl + 1);
- size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
- if (l == (size_t)(-1))
+ size_t len = mbstowcs(*wcs, mbs.c_str(), wcl);
+ if (len == (size_t)(-1))
return L"<invalid multibyte string>";
- wcs[l] = 0;
+ wcs[len] = 0;
return *wcs;
}
+#endif
+
#ifdef __ANDROID__
-std::string wide_to_narrow(const std::wstring& wcs) {
+
+std::string wide_to_narrow(const std::wstring &wcs) {
size_t mbl = wcs.size()*4;
std::string retval = "";
return retval;
}
-#else
-std::string wide_to_narrow(const std::wstring& wcs)
+
+#else // not Android
+
+std::string wide_to_narrow(const std::wstring &wcs)
{
- size_t mbl = wcs.size()*4;
+ size_t mbl = wcs.size() * 4;
SharedBuffer<char> mbs(mbl+1);
- size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
- if(l == (size_t)(-1)) {
+ size_t len = wcstombs(*mbs, wcs.c_str(), mbl);
+ if (len == (size_t)(-1))
return "Character conversion failed!";
- }
else
- mbs[l] = 0;
+ mbs[len] = 0;
return *mbs;
}
#endif
-// Get an sha-1 hash of the player's name combined with
-// the password entered. That's what the server uses as
-// their password. (Exception : if the password field is
-// blank, we send a blank password - this is for backwards
-// compatibility with password-less players).
-std::string translatePassword(std::string playername, std::wstring password)
-{
- if(password.length() == 0)
- return "";
-
- std::string slt = playername + wide_to_narrow(password);
- SHA1 sha1;
- sha1.addBytes(slt.c_str(), slt.length());
- unsigned char *digest = sha1.getDigest();
- std::string pwd = base64_encode(digest, 20);
- free(digest);
- return pwd;
-}
-
-std::string urlencode(std::string str)
+std::string urlencode(const std::string &str)
{
// Encodes non-unreserved URI characters by a percent sign
// followed by two hex digits. See RFC 3986, section 2.3.
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 == '~')
+ if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~') {
oss << c;
- else
+ } else {
oss << "%"
<< url_hex_chars[(c & 0xf0) >> 4]
<< url_hex_chars[c & 0x0f];
+ }
}
return oss.str();
}
-std::string urldecode(std::string str)
+std::string urldecode(const std::string &str)
{
// Inverse of urlencode
std::ostringstream oss(std::ios::binary);
hex_digit_decode(str[i+2], lowvalue)) {
oss << (char) ((highvalue << 4) | lowvalue);
i += 2;
- }
- else
+ } else {
oss << str[i];
+ }
}
return oss.str();
}
u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask)
{
- u32 result = 0, mask = 0;
+ u32 result = 0;
+ u32 mask = 0;
char *s = &str[0];
- char *flagstr, *strpos = NULL;
+ char *flagstr;
+ char *strpos = NULL;
while ((flagstr = strtok_r(s, ",", &strpos))) {
s = NULL;
}
t++;
}
-
+
*lasts = t;
return s;
}
{
char *endptr;
u64 num;
-
+
if (str[0] == '0' && str[1] == 'x')
num = strtoull(str, &endptr, 16);
else
num = strtoull(str, &endptr, 10);
-
+
if (*endptr)
num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337);
-
+
return num;
}
colors["darkgoldenrod"] = 0xb8860b;
colors["darkgray"] = 0xa9a9a9;
colors["darkgreen"] = 0x006400;
+ colors["darkgrey"] = 0xa9a9a9;
colors["darkkhaki"] = 0xbdb76b;
colors["darkmagenta"] = 0x8b008b;
colors["darkolivegreen"] = 0x556b2f;
colors["darkseagreen"] = 0x8fbc8f;
colors["darkslateblue"] = 0x483d8b;
colors["darkslategray"] = 0x2f4f4f;
+ colors["darkslategrey"] = 0x2f4f4f;
colors["darkturquoise"] = 0x00ced1;
colors["darkviolet"] = 0x9400d3;
colors["deeppink"] = 0xff1493;
colors["deepskyblue"] = 0x00bfff;
colors["dimgray"] = 0x696969;
+ colors["dimgrey"] = 0x696969;
colors["dodgerblue"] = 0x1e90ff;
colors["firebrick"] = 0xb22222;
colors["floralwhite"] = 0xfffaf0;
colors["gray"] = 0x808080;
colors["green"] = 0x008000;
colors["greenyellow"] = 0xadff2f;
+ colors["grey"] = 0x808080;
colors["honeydew"] = 0xf0fff0;
colors["hotpink"] = 0xff69b4;
- colors["indianred "] = 0xcd5c5c;
- colors["indigo "] = 0x4b0082;
+ colors["indianred"] = 0xcd5c5c;
+ colors["indigo"] = 0x4b0082;
colors["ivory"] = 0xfffff0;
colors["khaki"] = 0xf0e68c;
colors["lavender"] = 0xe6e6fa;
colors["lightgoldenrodyellow"] = 0xfafad2;
colors["lightgray"] = 0xd3d3d3;
colors["lightgreen"] = 0x90ee90;
+ colors["lightgrey"] = 0xd3d3d3;
colors["lightpink"] = 0xffb6c1;
colors["lightsalmon"] = 0xffa07a;
colors["lightseagreen"] = 0x20b2aa;
colors["lightskyblue"] = 0x87cefa;
colors["lightslategray"] = 0x778899;
+ colors["lightslategrey"] = 0x778899;
colors["lightsteelblue"] = 0xb0c4de;
colors["lightyellow"] = 0xffffe0;
colors["lime"] = 0x00ff00;
colors["skyblue"] = 0x87ceeb;
colors["slateblue"] = 0x6a5acd;
colors["slategray"] = 0x708090;
+ colors["slategrey"] = 0x708090;
colors["snow"] = 0xfffafa;
colors["springgreen"] = 0x00ff7f;
colors["steelblue"] = 0x4682b4;
{
std::replace(str.begin(), str.end(), from, to);
}
-