From 92812d0b0b1a78febc34d3e5fbb551e50ad77eb9 Mon Sep 17 00:00:00 2001 From: Techjar Date: Thu, 16 Jul 2020 18:47:51 -0400 Subject: [PATCH 1/2] QtUtils: Add UTF8CodePointCountValidator --- Source/Core/DolphinQt/CMakeLists.txt | 6 ++++-- Source/Core/DolphinQt/DolphinQt.vcxproj | 5 ++++- .../QtUtils/UTF8CodePointCountValidator.cpp | 20 +++++++++++++++++++ .../QtUtils/UTF8CodePointCountValidator.h | 19 ++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.cpp create mode 100644 Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 3ef723300d76..269083c4dc2a 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -235,6 +235,8 @@ add_executable(dolphin-emu QtUtils/ParallelProgressDialog.h QtUtils/ImageConverter.cpp QtUtils/ImageConverter.h + QtUtils/UTF8CodePointCountValidator.cpp + QtUtils/UTF8CodePointCountValidator.h QtUtils/WindowActivationEventFilter.cpp QtUtils/WindowActivationEventFilter.h QtUtils/WinIconHelper.cpp @@ -459,8 +461,8 @@ if(APPLE) include(DolphinPostprocessBundle) dolphin_postprocess_bundle(dolphin-emu) # Fix rpath - add_custom_command(TARGET dolphin-emu - POST_BUILD COMMAND + add_custom_command(TARGET dolphin-emu + POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $) else() diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 0fdfc5311881..1e4fd3b0b20b 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -186,6 +186,7 @@ + @@ -291,6 +292,7 @@ + @@ -433,6 +435,7 @@ + @@ -555,4 +558,4 @@ - \ No newline at end of file + diff --git a/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.cpp b/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.cpp new file mode 100644 index 000000000000..d5020ea8dd3d --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.cpp @@ -0,0 +1,20 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/QtUtils/UTF8CodePointCountValidator.h" + +#include "Common/StringUtil.h" + +UTF8CodePointCountValidator::UTF8CodePointCountValidator(int max_count, QObject* parent) + : QValidator(parent), m_max_count(max_count) +{ +} + +QValidator::State UTF8CodePointCountValidator::validate(QString& input, int& pos) const +{ + if (StringUTF8CodePointCount(input.toStdString()) > m_max_count) + return QValidator::Invalid; + + return QValidator::Acceptable; +} diff --git a/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.h b/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.h new file mode 100644 index 000000000000..89a8bc8e1de3 --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/UTF8CodePointCountValidator.h @@ -0,0 +1,19 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +class UTF8CodePointCountValidator : public QValidator +{ + Q_OBJECT +public: + explicit UTF8CodePointCountValidator(int max_count, QObject* parent = nullptr); + + QValidator::State validate(QString& input, int& pos) const override; + + int m_max_count; +}; From 037aa2192fa9b3de481e2acf125180bab16d6084 Mon Sep 17 00:00:00 2001 From: Techjar Date: Wed, 21 Nov 2018 00:15:44 -0500 Subject: [PATCH 2/2] NetPlay: Limit nickname length Ridiculously long nicknames cause UI silliness, so 30 characters seems like a reasonable limit, as it's the same as the forum. --- Source/Core/Common/StringUtil.cpp | 6 ++++++ Source/Core/Common/StringUtil.h | 1 + Source/Core/Core/NetPlayClient.cpp | 3 +++ Source/Core/Core/NetPlayProto.h | 4 +++- Source/Core/Core/NetPlayServer.cpp | 9 ++++++--- Source/Core/DolphinQt/NetPlay/NetPlaySetupDialog.cpp | 5 +++++ 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index c44f3fa7b1c2..14b7ac832bde 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 8c3db9ce34a1..4a97d2487bdc 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 bbc52a73feba..556849e53311 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 517abde8e9af..912e01fcaff8 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 1359fceacb90..0080cd8a83fe 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 d35970288d27..a9e31f5ed4d7 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;