mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -485,8 +485,8 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
 | 
			
		||||
	// find all names that start with the selected prefix
 | 
			
		||||
	std::vector<std::wstring> 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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<session_t> 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<session_t> 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() : "<unknown>";
 | 
			
		||||
 | 
			
		||||
			// 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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"<<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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::wstring narrow_to_wide(const std::string &mbs) {
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
	return utf8_to_wide(mbs);
 | 
			
		||||
#else
 | 
			
		||||
	size_t wcl = mbs.size();
 | 
			
		||||
	Buffer<wchar_t> wcs(wcl + 1);
 | 
			
		||||
	size_t len = mbstowcs(*wcs, mbs.c_str(), wcl);
 | 
			
		||||
	if (len == (size_t)(-1))
 | 
			
		||||
		return L"<invalid multibyte string>";
 | 
			
		||||
	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<char> 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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user