diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index c44f3fa7b1..14b7ac832b 100644 --- a/Source/Core/Common/StringUtil.cpp +++ b/Source/Core/Common/StringUtil.cpp @@ -412,6 +412,12 @@ void StringPopBackIf(std::string* s, char c) s->pop_back(); } +size_t StringUTF8CodePointCount(const std::string& str) +{ + return str.size() - + std::count_if(str.begin(), str.end(), [](char c) -> bool { return (c & 0xC0) == 0x80; }); +} + #ifdef _WIN32 std::wstring CPToUTF16(u32 code_page, std::string_view input) diff --git a/Source/Core/Common/StringUtil.h b/Source/Core/Common/StringUtil.h index 8c3db9ce34..4a97d2487b 100644 --- a/Source/Core/Common/StringUtil.h +++ b/Source/Core/Common/StringUtil.h @@ -167,6 +167,7 @@ void BuildCompleteFilename(std::string& complete_filename, std::string_view path bool StringBeginsWith(std::string_view str, std::string_view begin); bool StringEndsWith(std::string_view str, std::string_view end); void StringPopBackIf(std::string* s, char c); +size_t StringUTF8CodePointCount(const std::string& str); std::string CP1252ToUTF8(std::string_view str); std::string SHIFTJISToUTF8(std::string_view str); diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index bbc52a73fe..556849e533 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -252,6 +252,9 @@ bool NetPlayClient::Connect() case CON_ERR_GAME_RUNNING: m_dialog->OnConnectionError(_trans("The game is currently running.")); break; + case CON_ERR_NAME_TOO_LONG: + m_dialog->OnConnectionError(_trans("Nickname is too long.")); + break; default: m_dialog->OnConnectionError(_trans("The server sent an unknown error message.")); break; diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h index 517abde8e9..912e01fcaf 100644 --- a/Source/Core/Core/NetPlayProto.h +++ b/Source/Core/Core/NetPlayProto.h @@ -171,7 +171,8 @@ enum { CON_ERR_SERVER_FULL = 1, CON_ERR_GAME_RUNNING = 2, - CON_ERR_VERSION_MISMATCH = 3 + CON_ERR_VERSION_MISMATCH = 3, + CON_ERR_NAME_TOO_LONG = 4 }; enum @@ -197,6 +198,7 @@ enum constexpr u32 NETPLAY_LZO_IN_LEN = 1024 * 64; constexpr u32 NETPLAY_LZO_OUT_LEN = NETPLAY_LZO_IN_LEN + (NETPLAY_LZO_IN_LEN / 16) + 64 + 3; +constexpr u32 MAX_NAME_LENGTH = 30; constexpr size_t CHUNKED_DATA_UNIT_SIZE = 16384; constexpr u8 CHANNEL_COUNT = 2; constexpr u8 DEFAULT_CHANNEL = 0; diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 1359fceacb..0080cd8a83 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -377,9 +377,6 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) if (m_players.size() >= 255) return CON_ERR_SERVER_FULL; - // cause pings to be updated - m_update_pings = true; - Client player; player.pid = pid; player.socket = socket; @@ -387,6 +384,12 @@ unsigned int NetPlayServer::OnConnect(ENetPeer* socket, sf::Packet& rpac) rpac >> player.revision; rpac >> player.name; + if (StringUTF8CodePointCount(player.name) > MAX_NAME_LENGTH) + return CON_ERR_NAME_TOO_LONG; + + // cause pings to be updated + m_update_pings = true; + // try to automatically assign new user a pad for (PlayerId& mapping : m_pad_map) { diff --git a/Source/Core/DolphinQt/NetPlay/NetPlaySetupDialog.cpp b/Source/Core/DolphinQt/NetPlay/NetPlaySetupDialog.cpp index d35970288d..a9e31f5ed4 100644 --- a/Source/Core/DolphinQt/NetPlay/NetPlaySetupDialog.cpp +++ b/Source/Core/DolphinQt/NetPlay/NetPlaySetupDialog.cpp @@ -17,9 +17,11 @@ #include #include "Core/Config/NetplaySettings.h" +#include "Core/NetPlayProto.h" #include "DolphinQt/GameList/GameListModel.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/QtUtils/UTF8CodePointCountValidator.h" #include "DolphinQt/Settings.h" #include "UICommon/NetPlayIndex.h" @@ -87,6 +89,9 @@ void NetPlaySetupDialog::CreateMainLayout() m_reset_traversal_button = new QPushButton(tr("Reset Traversal Settings")); m_tab_widget = new QTabWidget; + m_nickname_edit->setValidator( + new UTF8CodePointCountValidator(NetPlay::MAX_NAME_LENGTH, m_nickname_edit)); + // Connection widget auto* connection_widget = new QWidget; auto* connection_layout = new QGridLayout;