diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index f69ee8b0f1..9da40c8564 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -621,23 +621,27 @@ bool HasXmppClient(void* UNUSED(cbdata)) } #if CONFIG2_LOBBY -void StartXmppClient(void* cbdata, std::string sUsername, std::string sPassword, std::string sRoom, std::string sNick) +void StartXmppClient(void* cbdata, std::wstring username, std::wstring password, std::wstring room, std::wstring nick) { CGUIManager* guiManager = static_cast (cbdata); ENSURE(!g_XmppClient); - g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), sUsername, sPassword, sRoom, sNick); + g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), + utf8_from_wstring(username), utf8_from_wstring(password), + utf8_from_wstring(room), utf8_from_wstring(nick)); g_rankedGame = true; } -void StartRegisterXmppClient(void* cbdata, std::string sUsername, std::string sPassword) +void StartRegisterXmppClient(void* cbdata, std::wstring username, std::wstring password) { CGUIManager* guiManager = static_cast (cbdata); ENSURE(!g_XmppClient); - g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), sUsername, sPassword, "", "", true); + g_XmppClient = IXmppClient::create(guiManager->GetScriptInterface(), + utf8_from_wstring(username), utf8_from_wstring(password), + "", "", true); } void StopXmppClient(void* UNUSED(cbdata)) @@ -701,11 +705,11 @@ void SendUnregisterGame(void* UNUSED(cbdata)) g_XmppClient->SendIqUnregisterGame(); } -void SendChangeStateGame(void* UNUSED(cbdata), std::string nbp, std::string players) +void SendChangeStateGame(void* UNUSED(cbdata), std::wstring nbp, std::wstring players) { if (!g_XmppClient) return; - g_XmppClient->SendIqChangeStateGame(nbp, players); + g_XmppClient->SendIqChangeStateGame(utf8_from_wstring(nbp), utf8_from_wstring(players)); } CScriptVal GetPlayerList(void* UNUSED(cbdata)) @@ -748,102 +752,101 @@ CScriptVal LobbyGuiPollMessage(void* UNUSED(cbdata)) return poll.get(); } -void LobbySendMessage(void* UNUSED(cbdata), std::string message) +void LobbySendMessage(void* UNUSED(cbdata), std::wstring message) { if (!g_XmppClient) return; - g_XmppClient->SendMUCMessage(message); + g_XmppClient->SendMUCMessage(utf8_from_wstring(message)); } -void LobbySetPlayerPresence(void* UNUSED(cbdata), std::string presence) +void LobbySetPlayerPresence(void* UNUSED(cbdata), std::wstring presence) { if (!g_XmppClient) return; - g_XmppClient->SetPresence(presence); + g_XmppClient->SetPresence(utf8_from_wstring(presence)); } -void LobbySetNick(void* UNUSED(cbdata), std::string nick) +void LobbySetNick(void* UNUSED(cbdata), std::wstring nick) { if (!g_XmppClient) return; - g_XmppClient->SetNick(nick); + g_XmppClient->SetNick(utf8_from_wstring(nick)); } -std::string LobbyGetNick(void* UNUSED(cbdata)) +std::wstring LobbyGetNick(void* UNUSED(cbdata)) { if (!g_XmppClient) - return ""; + return L""; std::string nick; g_XmppClient->GetNick(nick); - return nick; + return wstring_from_utf8(nick); } -void LobbyKick(void* UNUSED(cbdata), std::string nick, std::string reason) +void LobbyKick(void* UNUSED(cbdata), std::wstring nick, std::wstring reason) { if (!g_XmppClient) return; - g_XmppClient->kick(nick, reason); + g_XmppClient->kick(utf8_from_wstring(nick), utf8_from_wstring(reason)); } -void LobbyBan(void* UNUSED(cbdata), std::string nick, std::string reason) +void LobbyBan(void* UNUSED(cbdata), std::wstring nick, std::wstring reason) { if (!g_XmppClient) return; - g_XmppClient->ban(nick, reason); + g_XmppClient->ban(utf8_from_wstring(nick), utf8_from_wstring(reason)); } -std::string LobbyGetPlayerPresence(void* UNUSED(cbdata), std::string nickname) +std::wstring LobbyGetPlayerPresence(void* UNUSED(cbdata), std::wstring nickname) { if (!g_XmppClient) - return ""; + return L""; std::string presence; - g_XmppClient->GetPresence(nickname, presence); - return presence; + g_XmppClient->GetPresence(utf8_from_wstring(nickname), presence); + return wstring_from_utf8(presence); } // Non-public secure PBKDF2 hash function with salting and 1,337 iterations -void EncryptPassword(const std::string& username, std::string& password) +static std::string EncryptPassword(const std::string& password, const std::string& username) { - const int DIGESTSIZE = SHA_DIGEST_SIZE; - const int ITERATIONS = 1337; + const int DIGESTSIZE = SHA_DIGEST_SIZE; + const int ITERATIONS = 1337; - static const byte salt_base[DIGESTSIZE] = { - 244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 }; + static const byte salt_base[DIGESTSIZE] = { + 244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 }; - // initialize the salt buffer - byte salt_buffer[DIGESTSIZE] = {0}; - SHA256 hash; - hash.update(salt_base, username.length()); - hash.update(username.c_str(), username.length()); - hash.finish(salt_buffer); + // initialize the salt buffer + byte salt_buffer[DIGESTSIZE] = {0}; + SHA256 hash; + hash.update(salt_base, sizeof(salt_base)); + hash.update(username.c_str(), username.length()); + hash.finish(salt_buffer); - // PBKDF2 to create the buffer - byte encrypted[DIGESTSIZE]; - pbkdf2(encrypted, (byte*)password.c_str(), password.length(), salt_buffer, DIGESTSIZE, ITERATIONS); + // PBKDF2 to create the buffer + byte encrypted[DIGESTSIZE]; + pbkdf2(encrypted, (byte*)password.c_str(), password.length(), salt_buffer, DIGESTSIZE, ITERATIONS); - static const char base16[] = "0123456789ABCDEF"; - char hex[2 * DIGESTSIZE]; - for(int i = 0; i < DIGESTSIZE; ++i) - { - hex[i*2] = base16[encrypted[i] >> 4]; // 4 high bits - hex[i*2 + 1] = base16[encrypted[i] & 0x0F];// 4 low bits - } - password.assign(hex, sizeof(hex)); + static const char base16[] = "0123456789ABCDEF"; + char hex[2 * DIGESTSIZE]; + for (int i = 0; i < DIGESTSIZE; ++i) + { + hex[i*2] = base16[encrypted[i] >> 4]; // 4 high bits + hex[i*2 + 1] = base16[encrypted[i] & 0x0F];// 4 low bits + } + return std::string(hex, sizeof(hex)); } // Public hash interface. -std::string EncryptPassword(void* UNUSED(cbdata), std::string user, std::string pass) +std::wstring EncryptPassword(void* UNUSED(cbdata), std::wstring pass, std::wstring user) { - EncryptPassword(user, pass); - return pass; + return wstring_from_utf8(EncryptPassword(utf8_from_wstring(pass), utf8_from_wstring(user))); } bool IsRankedGame(void* UNUSED(cbdata)) @@ -969,8 +972,8 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) // Lobby functions scriptInterface.RegisterFunction("HasXmppClient"); #if CONFIG2_LOBBY // Allow the lobby to be disabled - scriptInterface.RegisterFunction("StartXmppClient"); - scriptInterface.RegisterFunction("StartRegisterXmppClient"); + scriptInterface.RegisterFunction("StartXmppClient"); + scriptInterface.RegisterFunction("StartRegisterXmppClient"); scriptInterface.RegisterFunction("StopXmppClient"); scriptInterface.RegisterFunction("ConnectXmppClient"); scriptInterface.RegisterFunction("DisconnectXmppClient"); @@ -980,19 +983,19 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) scriptInterface.RegisterFunction("SendRegisterGame"); scriptInterface.RegisterFunction("SendGameReport"); scriptInterface.RegisterFunction("SendUnregisterGame"); - scriptInterface.RegisterFunction("SendChangeStateGame"); + scriptInterface.RegisterFunction("SendChangeStateGame"); scriptInterface.RegisterFunction("GetPlayerList"); scriptInterface.RegisterFunction("GetGameList"); scriptInterface.RegisterFunction("GetBoardList"); scriptInterface.RegisterFunction("LobbyGuiPollMessage"); - scriptInterface.RegisterFunction("LobbySendMessage"); - scriptInterface.RegisterFunction("LobbySetPlayerPresence"); - scriptInterface.RegisterFunction("LobbySetNick"); - scriptInterface.RegisterFunction("LobbyGetNick"); - scriptInterface.RegisterFunction("LobbyKick"); - scriptInterface.RegisterFunction("LobbyBan"); - scriptInterface.RegisterFunction("LobbyGetPlayerPresence"); - scriptInterface.RegisterFunction("EncryptPassword"); + scriptInterface.RegisterFunction("LobbySendMessage"); + scriptInterface.RegisterFunction("LobbySetPlayerPresence"); + scriptInterface.RegisterFunction("LobbySetNick"); + scriptInterface.RegisterFunction("LobbyGetNick"); + scriptInterface.RegisterFunction("LobbyKick"); + scriptInterface.RegisterFunction("LobbyBan"); + scriptInterface.RegisterFunction("LobbyGetPlayerPresence"); + scriptInterface.RegisterFunction("EncryptPassword"); scriptInterface.RegisterFunction("IsRankedGame"); scriptInterface.RegisterFunction("SetRankedGame"); #endif // CONFIG2_LOBBY diff --git a/source/lobby/XmppClient.cpp b/source/lobby/XmppClient.cpp index d28792f077..7ca4dc0af9 100644 --- a/source/lobby/XmppClient.cpp +++ b/source/lobby/XmppClient.cpp @@ -19,6 +19,8 @@ #include "XmppClient.h" #include "StanzaExtensions.h" +#include "lib/utf8.h" + // Debug // TODO: Use builtin error/warning/logging functions. #include @@ -301,9 +303,9 @@ void XmppClient::SendIqGameReport(CScriptVal data) m_ScriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties); for (std::vector::size_type i = 0; i != properties.size(); i++) { - std::string value; + std::wstring value; m_ScriptInterface.GetProperty(dataval, properties[i].c_str(), value); - report->addAttribute(properties[i], value); + report->addAttribute(properties[i], utf8_from_wstring(value)); } // Add stanza to IQ @@ -338,9 +340,9 @@ void XmppClient::SendIqRegisterGame(CScriptVal data) m_ScriptInterface.EnumeratePropertyNamesWithPrefix(dataval, "", properties); for (std::vector::size_type i = 0; i != properties.size(); i++) { - std::string value; + std::wstring value; m_ScriptInterface.GetProperty(dataval, properties[i].c_str(), value); - game->addAttribute(properties[i], value); + game->addAttribute(properties[i], utf8_from_wstring(value)); } // Push the stanza onto the IQ @@ -470,10 +472,10 @@ CScriptValRooted XmppClient::GUIGetPlayerList() CScriptValRooted player; GetPresenceString(it->second, presence); m_ScriptInterface.Eval("({})", player); - m_ScriptInterface.SetProperty(player.get(), "name", it->first.c_str()); - m_ScriptInterface.SetProperty(player.get(), "presence", presence.c_str()); + m_ScriptInterface.SetProperty(player.get(), "name", wstring_from_utf8(it->first)); + m_ScriptInterface.SetProperty(player.get(), "presence", wstring_from_utf8(presence)); - m_ScriptInterface.SetProperty(playerList.get(), it->first.c_str(), player); + m_ScriptInterface.SetProperty(playerList.get(), wstring_from_utf8(it->first).c_str(), player); } return playerList; @@ -496,7 +498,7 @@ CScriptValRooted XmppClient::GUIGetGameList() const char* stats[] = { "name", "ip", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" }; short stats_length = 11; for (short i = 0; i < stats_length; i++) - m_ScriptInterface.SetProperty(game.get(), stats[i], (*it)->findAttribute(stats[i]).c_str()); + m_ScriptInterface.SetProperty(game.get(), stats[i], wstring_from_utf8((*it)->findAttribute(stats[i]).to_string())); m_ScriptInterface.CallFunctionVoid(gameList.get(), "push", game); } @@ -521,7 +523,7 @@ CScriptValRooted XmppClient::GUIGetBoardList() const char* attributes[] = { "name", "rank", "rating" }; short attributes_length = 3; for (short i = 0; i < attributes_length; i++) - m_ScriptInterface.SetProperty(board.get(), attributes[i], (*it)->findAttribute(attributes[i]).c_str()); + m_ScriptInterface.SetProperty(board.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string())); m_ScriptInterface.CallFunctionVoid(boardList.get(), "push", board); } @@ -574,8 +576,8 @@ void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Me CScriptValRooted message; m_ScriptInterface.Eval("({ 'type':'mucmessage'})", message); - m_ScriptInterface.SetProperty(message.get(), "from", msg.from().resource().to_string()); - m_ScriptInterface.SetProperty(message.get(), "text", msg.body().to_string()); + m_ScriptInterface.SetProperty(message.get(), "from", wstring_from_utf8(msg.from().resource().to_string())); + m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(msg.body().to_string())); PushGuiMessage(message); } @@ -589,8 +591,8 @@ void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::M CScriptValRooted message; m_ScriptInterface.Eval("({'type':'message'})", message); - m_ScriptInterface.SetProperty(message.get(), "from", msg.from().username().to_string()); - m_ScriptInterface.SetProperty(message.get(), "text", msg.body().to_string()); + m_ScriptInterface.SetProperty(message.get(), "from", wstring_from_utf8(msg.from().username().to_string())); + m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(msg.body().to_string())); PushGuiMessage(message); } @@ -654,10 +656,10 @@ void XmppClient::CreateSimpleMessage(const std::string& type, const std::string& { CScriptValRooted message; m_ScriptInterface.Eval("({})", message); - m_ScriptInterface.SetProperty(message.get(), "type", type); - m_ScriptInterface.SetProperty(message.get(), "level", level); - m_ScriptInterface.SetProperty(message.get(), "text", text); - m_ScriptInterface.SetProperty(message.get(), "data", data); + m_ScriptInterface.SetProperty(message.get(), "type", wstring_from_utf8(type)); + m_ScriptInterface.SetProperty(message.get(), "level", wstring_from_utf8(level)); + m_ScriptInterface.SetProperty(message.get(), "text", wstring_from_utf8(text)); + m_ScriptInterface.SetProperty(message.get(), "data", wstring_from_utf8(data)); PushGuiMessage(message); } diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index 9278cba26a..983b8b9284 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -803,6 +803,24 @@ bool ScriptInterface::SetProperty_(jsval obj, const char* name, jsval value, boo return true; } +bool ScriptInterface::SetProperty_(jsval obj, const wchar_t* name, jsval value, bool constant, bool enumerate) +{ + uintN attrs = 0; + if (constant) + attrs |= JSPROP_READONLY | JSPROP_PERMANENT; + if (enumerate) + attrs |= JSPROP_ENUMERATE; + + if (! JSVAL_IS_OBJECT(obj)) + return false; + JSObject* object = JSVAL_TO_OBJECT(obj); + + utf16string name16(name, name + wcslen(name)); + if (! JS_DefineUCProperty(m->m_cx, object, reinterpret_cast(name16.c_str()), name16.length(), value, NULL, NULL, attrs)) + return false; + return true; +} + bool ScriptInterface::SetPropertyInt_(jsval obj, int name, jsval value, bool constant, bool enumerate) { uintN attrs = 0; diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index b6c6848948..586cf79243 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -189,6 +189,13 @@ public: template bool SetProperty(jsval obj, const char* name, const T& value, bool constant = false, bool enumerate = true); + /** + * Set the named property on the given object. + * Optionally makes it {ReadOnly, DontDelete, DontEnum}. + */ + template + bool SetProperty(jsval obj, const wchar_t* name, const T& value, bool constant = false, bool enumerate = true); + /** * Set the integer-named property on the given object. * Optionally makes it {ReadOnly, DontDelete, DontEnum}. @@ -327,6 +334,7 @@ private: bool Eval_(const wchar_t* code, jsval& ret); bool SetGlobal_(const char* name, jsval value, bool replace); bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate); + bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate); bool SetPropertyInt_(jsval obj, int name, jsval value, bool readonly, bool enumerate); bool GetProperty_(jsval obj, const char* name, jsval& value); bool GetPropertyInt_(jsval obj, int name, jsval& value); @@ -464,6 +472,12 @@ bool ScriptInterface::SetProperty(jsval obj, const char* name, const T& value, b return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly, enumerate); } +template +bool ScriptInterface::SetProperty(jsval obj, const wchar_t* name, const T& value, bool readonly, bool enumerate) +{ + return SetProperty_(obj, name, ToJSVal(GetContext(), value), readonly, enumerate); +} + template bool ScriptInterface::SetPropertyInt(jsval obj, int name, const T& value, bool readonly, bool enumerate) {