From c834d2ab25694ef2d67dc24f85f304269d202c8e Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 29 Jan 2021 14:03:27 +0100 Subject: [PATCH] Drop wide/narrow conversion functions The only valid usecase for these is interfacing with OS APIs that want a locale/OS-specific multibyte encoding. But they weren't used for that anywhere, instead UTF-8 is pretty much assumed when it comes to that. Since these are only a potential source of bugs and do not fulfil their purpose at all, drop them entirely. --- src/chat.cpp | 4 +- src/client/client.cpp | 4 +- src/client/keycode.cpp | 3 +- src/gui/guiConfirmRegistration.cpp | 3 +- src/network/serverpackethandler.cpp | 8 ++-- src/script/lua_api/l_server.cpp | 2 +- src/server.cpp | 61 +++++++++++------------------ src/server.h | 8 ++-- src/unittest/test_utilities.cpp | 4 +- src/util/string.cpp | 59 +--------------------------- src/util/string.h | 28 ------------- 11 files changed, 41 insertions(+), 143 deletions(-) diff --git a/src/chat.cpp b/src/chat.cpp index 2f65e68b3..c9317a079 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -485,8 +485,8 @@ void ChatPrompt::nickCompletion(const std::list& names, bool backwa // find all names that start with the selected prefix std::vector completions; for (const std::string &name : names) { - if (str_starts_with(narrow_to_wide(name), prefix, true)) { - std::wstring completion = narrow_to_wide(name); + std::wstring completion = utf8_to_wide(name); + if (str_starts_with(completion, prefix, true)) { if (prefix_start == 0) completion += L": "; completions.push_back(completion); diff --git a/src/client/client.cpp b/src/client/client.cpp index 61888b913..ef4a3cdfc 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1196,7 +1196,7 @@ void Client::sendChatMessage(const std::wstring &message) if (canSendChatMessage()) { u32 now = time(NULL); float time_passed = now - m_last_chat_message_sent; - m_last_chat_message_sent = time(NULL); + m_last_chat_message_sent = now; m_chat_message_allowance += time_passed * (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f); if (m_chat_message_allowance > CLIENT_CHAT_MESSAGE_LIMIT_PER_10S) @@ -1832,7 +1832,7 @@ void Client::makeScreenshot() sstr << "Failed to save screenshot '" << filename << "'"; } pushToChatQueue(new ChatMessage(CHATMESSAGE_TYPE_SYSTEM, - narrow_to_wide(sstr.str()))); + utf8_to_wide(sstr.str()))); infostream << sstr.str() << std::endl; image->drop(); } diff --git a/src/client/keycode.cpp b/src/client/keycode.cpp index 6a0e9f569..ce5214f54 100644 --- a/src/client/keycode.cpp +++ b/src/client/keycode.cpp @@ -316,7 +316,8 @@ KeyPress::KeyPress(const char *name) int chars_read = mbtowc(&Char, name, 1); FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character"); m_name = ""; - warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char."; + warningstream << "KeyPress: Unknown key '" << name + << "', falling back to first char." << std::endl; } KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character) diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 020a2796a..4a798c39b 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -192,8 +192,7 @@ void GUIConfirmRegistration::acceptInput() bool GUIConfirmRegistration::processInput() { - std::wstring m_password_ws = narrow_to_wide(m_password); - if (m_password_ws != m_pass_confirm) { + if (utf8_to_wide(m_password) != m_pass_confirm) { gui::IGUIElement *e = getElementFromId(ID_message); if (e) e->setVisible(true); diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 4d79f375c..02af06abc 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -778,15 +778,13 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt) return; } - // Get player name of this client std::string name = player->getName(); - std::wstring wname = narrow_to_wide(name); - std::wstring answer_to_sender = handleChat(name, wname, message, true, player); + std::wstring answer_to_sender = handleChat(name, message, true, player); if (!answer_to_sender.empty()) { // Send the answer to sender - SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_NORMAL, - answer_to_sender, wname)); + SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + answer_to_sender)); } } diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 78cf4b403..bf5292521 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -44,7 +44,7 @@ int ModApiServer::l_request_shutdown(lua_State *L) int ModApiServer::l_get_server_status(lua_State *L) { NO_MAP_LOCK_REQUIRED; - lua_pushstring(L, wide_to_narrow(getServer(L)->getStatusString()).c_str()); + lua_pushstring(L, getServer(L)->getStatusString().c_str()); return 1; } diff --git a/src/server.cpp b/src/server.cpp index 90496129e..907bc6d24 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2955,7 +2955,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt) } } -std::wstring Server::handleChat(const std::string &name, const std::wstring &wname, +std::wstring Server::handleChat(const std::string &name, std::wstring wmessage, bool check_shout_priv, RemotePlayer *player) { // If something goes wrong, this player is to blame @@ -2993,7 +2993,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna auto message = trim(wide_to_utf8(wmessage)); if (message.find_first_of("\n\r") != std::wstring::npos) { - return L"New lines are not permitted in chat messages"; + return L"Newlines are not permitted in chat messages"; } // Run script hook, exit if script ate the chat message @@ -3014,10 +3014,10 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna the Cyrillic alphabet and some characters on older Android devices */ #ifdef __ANDROID__ - line += L"<" + wname + L"> " + wmessage; + line += L"<" + utf8_to_wide(name) + L"> " + wmessage; #else - line += narrow_to_wide(m_script->formatChatMessage(name, - wide_to_narrow(wmessage))); + line += utf8_to_wide(m_script->formatChatMessage(name, + wide_to_utf8(wmessage))); #endif } @@ -3030,35 +3030,23 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna /* Send the message to others */ - actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl; + actionstream << "CHAT: " << wide_to_utf8(unescape_enriched(line)) << std::endl; + + ChatMessage chatmsg(line); std::vector clients = m_clients.getClientIDs(); + for (u16 cid : clients) + SendChatMessage(cid, chatmsg); - /* - Send the message back to the inital sender - if they are using protocol version >= 29 - */ - - session_t peer_id_to_avoid_sending = - (player ? player->getPeerId() : PEER_ID_INEXISTENT); - - if (player && player->protocol_version >= 29) - peer_id_to_avoid_sending = PEER_ID_INEXISTENT; - - for (u16 cid : clients) { - if (cid != peer_id_to_avoid_sending) - SendChatMessage(cid, ChatMessage(line)); - } return L""; } void Server::handleAdminChat(const ChatEventChat *evt) { std::string name = evt->nick; - std::wstring wname = utf8_to_wide(name); std::wstring wmessage = evt->evt_msg; - std::wstring answer = handleChat(name, wname, wmessage); + std::wstring answer = handleChat(name, wmessage); // If asked to send answer to sender if (!answer.empty()) { @@ -3095,46 +3083,43 @@ PlayerSAO *Server::getPlayerSAO(session_t peer_id) return player->getPlayerSAO(); } -std::wstring Server::getStatusString() +std::string Server::getStatusString() { - std::wostringstream os(std::ios_base::binary); - os << L"# Server: "; + std::ostringstream os(std::ios_base::binary); + os << "# Server: "; // Version - os << L"version=" << narrow_to_wide(g_version_string); + os << "version=" << g_version_string; // Uptime - os << L", uptime=" << m_uptime_counter->get(); + os << ", uptime=" << m_uptime_counter->get(); // Max lag estimate - os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0); + os << ", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0); // Information about clients bool first = true; - os << L", clients={"; + os << ", clients={"; if (m_env) { std::vector clients = m_clients.getClientIDs(); for (session_t client_id : clients) { RemotePlayer *player = m_env->getPlayer(client_id); // Get name of player - std::wstring name = L"unknown"; - if (player) - name = narrow_to_wide(player->getName()); + const char *name = player ? player->getName() : ""; // Add name to information string if (!first) - os << L", "; + os << ", "; else first = false; - os << name; } } - os << L"}"; + os << "}"; if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled()) - os << std::endl << L"# Server: " << " WARNING: Map saving is disabled."; + os << std::endl << "# Server: " << " WARNING: Map saving is disabled."; if (!g_settings->get("motd").empty()) - os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd")); + os << std::endl << "# Server: " << g_settings->get("motd"); return os.str(); } diff --git a/src/server.h b/src/server.h index 5c143a657..0b4084aa9 100644 --- a/src/server.h +++ b/src/server.h @@ -219,7 +219,7 @@ public: void onMapEditEvent(const MapEditEvent &event); // Connection must be locked when called - std::wstring getStatusString(); + std::string getStatusString(); inline double getUptime() const { return m_uptime_counter->get(); } // read shutdown state @@ -495,10 +495,8 @@ private: void handleChatInterfaceEvent(ChatEvent *evt); // This returns the answer to the sender of wmessage, or "" if there is none - std::wstring handleChat(const std::string &name, const std::wstring &wname, - std::wstring wmessage_input, - bool check_shout_priv = false, - RemotePlayer *player = NULL); + std::wstring handleChat(const std::string &name, std::wstring wmessage_input, + bool check_shout_priv = false, RemotePlayer *player = nullptr); void handleAdminChat(const ChatEventChat *evt); // When called, connection mutex should be locked diff --git a/src/unittest/test_utilities.cpp b/src/unittest/test_utilities.cpp index 5559cdbf2..93ba3f844 100644 --- a/src/unittest/test_utilities.cpp +++ b/src/unittest/test_utilities.cpp @@ -247,8 +247,8 @@ void TestUtilities::testStartsWith() void TestUtilities::testStrEqual() { - UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc"))); - UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true)); + UASSERT(str_equal(utf8_to_wide("abc"), utf8_to_wide("abc"))); + UASSERT(str_equal(utf8_to_wide("ABC"), utf8_to_wide("abc"), true)); } diff --git a/src/util/string.cpp b/src/util/string.cpp index 7e6d6d3b3..611ad35cb 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -175,62 +175,6 @@ wchar_t *utf8_to_wide_c(const char *str) 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 = nullptr; -#if defined(_WIN32) - int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, 0, 0); - if (nResult == 0) { - errorstream<<"gettext: MultiByteToWideChar returned null"< wcs(wcl + 1); - size_t len = mbstowcs(*wcs, mbs.c_str(), wcl); - if (len == (size_t)(-1)) - return L""; - wcs[len] = 0; - return *wcs; -#endif -} - - -std::string wide_to_narrow(const std::wstring &wcs) -{ -#ifdef __ANDROID__ - return wide_to_utf8(wcs); -#else - size_t mbl = wcs.size() * 4; - SharedBuffer mbs(mbl+1); - size_t len = wcstombs(*mbs, wcs.c_str(), mbl); - if (len == (size_t)(-1)) - return "Character conversion failed!"; - - mbs[len] = 0; - return *mbs; -#endif -} - std::string urlencode(const std::string &str) { @@ -757,7 +701,8 @@ void translate_string(const std::wstring &s, Translations *translations, } else { // This is an escape sequence *inside* the template string to translate itself. // This should not happen, show an error message. - errorstream << "Ignoring escape sequence '" << wide_to_narrow(escape_sequence) << "' in translation" << std::endl; + errorstream << "Ignoring escape sequence '" + << wide_to_utf8(escape_sequence) << "' in translation" << std::endl; } } diff --git a/src/util/string.h b/src/util/string.h index ec14e9a2d..d4afcaec8 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -73,16 +73,6 @@ std::string wide_to_utf8(const std::wstring &input); // The returned string is allocated using new[] wchar_t *utf8_to_wide_c(const char *str); -// NEVER use those two functions unless you have a VERY GOOD reason to -// they just convert between wide and multibyte encoding -// multibyte encoding depends on current locale, this is no good, especially on Windows - -// You must free the returned string! -// The returned string is allocated using new -wchar_t *narrow_to_wide_c(const char *str); -std::wstring narrow_to_wide(const std::string &mbs); -std::string wide_to_narrow(const std::wstring &wcs); - std::string urlencode(const std::string &str); std::string urldecode(const std::string &str); u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask); @@ -355,11 +345,6 @@ inline s32 mystoi(const std::string &str, s32 min, s32 max) return i; } - -// MSVC2010 includes it's own versions of these -//#if !defined(_MSC_VER) || _MSC_VER < 1600 - - /** * Returns a 32-bit value reprensented by the string \p str (decimal). * @see atoi(3) for further limitations @@ -369,17 +354,6 @@ inline s32 mystoi(const std::string &str) return atoi(str.c_str()); } - -/** - * Returns s 32-bit value represented by the wide string \p str (decimal). - * @see atoi(3) for further limitations - */ -inline s32 mystoi(const std::wstring &str) -{ - return mystoi(wide_to_narrow(str)); -} - - /** * Returns a float reprensented by the string \p str (decimal). * @see atof(3) @@ -389,8 +363,6 @@ inline float mystof(const std::string &str) return atof(str.c_str()); } -//#endif - #define stoi mystoi #define stof mystof