From 65e53f19e5494e00fc555cde4c3cf70696ce2b02 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 9 May 2019 14:36:47 +0800 Subject: [PATCH] Add framework for reporting player --- NETWORKING.md | 32 +++-- src/network/protocols/client_lobby.cpp | 4 + src/network/protocols/client_lobby.hpp | 4 + src/network/protocols/server_lobby.cpp | 127 +++++++----------- src/network/protocols/server_lobby.hpp | 4 + src/network/server_config.cpp | 2 + src/network/server_config.hpp | 20 ++- .../dialogs/network_user_dialog.cpp | 6 +- 8 files changed, 109 insertions(+), 90 deletions(-) diff --git a/NETWORKING.md b/NETWORKING.md index 8b15c25de..e4e0a2db9 100644 --- a/NETWORKING.md +++ b/NETWORKING.md @@ -147,17 +147,23 @@ The current server configuration xml looks like this: - + - - + + - - + + + + + + + + @@ -242,9 +248,9 @@ Current players in server with ip in human readable format and time played of ea `*_player_stats` All players with online id and username with their time played stats in this server since creation of this database. -For IP or online ID ban list, you need to create one yourself: +For IP, online ID ban list or player reports, you need to create one yourself: ```sql -CREATE TABLE ipban +CREATE TABLE ip_ban ( ip_start INTEGER UNSIGNED NOT NULL UNIQUE, -- Starting of ip decimal for banning (inclusive) ip_end INTEGER UNSIGNED NOT NULL UNIQUE, -- Ending of ip decimal for banning (inclusive) @@ -256,7 +262,7 @@ CREATE TABLE ipban last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered ); -CREATE TABLE onlineidban +CREATE TABLE online_id_ban ( online_id INTEGER UNSIGNED NOT NULL UNIQUE, -- Online id from STK addons database for banning starting_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Starting time of this banning entry to be effective @@ -266,4 +272,14 @@ CREATE TABLE onlineidban trigger_count INTEGER UNSIGNED NOT NULL DEFAULT 0, -- Number of banning triggered by this ban entry last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered ); + +CREATE TABLE player_reports +( + reported_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player who reports, 0 for offline player + reported_username TEXT NOT NULL, -- Player name who reports + reported_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time of reporting + info TEXT NOT NULL, -- Report info by reporter + reporting_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player being reported, 0 for offline player + reporting_username TEXT NOT NULL -- Player name being reported +); ``` diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index 6f7cd2b37..c9bdd2cdf 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -99,6 +99,7 @@ ClientLobby::ClientLobby(const TransportAddress& a, std::shared_ptr s) m_server_send_live_load_world = false; m_server_enabled_chat = true; m_server_enabled_track_voting = true; + m_server_enabled_report_player = false; } // ClientLobby //----------------------------------------------------------------------------- @@ -622,6 +623,9 @@ void ClientLobby::connectionAccepted(Event* event) if (auto_start_timer != std::numeric_limits::max()) NetworkingLobby::getInstance()->setStartingTimerTo(auto_start_timer); m_server_enabled_chat = data.getUInt8() == 1; + if (NetworkConfig::get()->getServerCapabilities().find("report_player") != + NetworkConfig::get()->getServerCapabilities().end()) + m_server_enabled_report_player = data.getUInt8() == 1; } // connectionAccepted //----------------------------------------------------------------------------- diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 2bf11b6b6..6a59df1c0 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -107,6 +107,8 @@ private: bool m_server_enabled_track_voting; + bool m_server_enabled_report_player; + uint64_t m_auto_back_to_lobby_time; uint64_t m_start_live_game_time; @@ -173,6 +175,8 @@ public: bool serverEnabledChat() const { return m_server_enabled_chat; } bool serverEnabledTrackVoting() const { return m_server_enabled_track_voting; } + bool serverEnabledReportPlayer() const + { return m_server_enabled_report_player; } }; #endif // CLIENT_LOBBY_HPP diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 4492d080c..c2a358f98 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -144,6 +144,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL) m_difficulty.store(ServerConfig::m_server_difficulty); m_game_mode.store(ServerConfig::m_server_mode); m_default_vote = new PeerVote(); + m_player_reports_table_exists = false; initDatabase(); } // ServerLobby @@ -171,7 +172,6 @@ void ServerLobby::initDatabase() #ifdef ENABLE_SQLITE3 m_last_cleanup_db_time = StkTime::getMonoTimeMs(); m_db = NULL; - sqlite3_stmt* stmt = NULL;; m_ip_ban_table_exists = false; m_online_id_ban_table_exists = false; if (!ServerConfig::m_sql_management) @@ -186,80 +186,11 @@ void ServerLobby::initDatabase() return; } - const std::string ip_ban_table = ServerConfig::m_ip_ban_table; - if (!ip_ban_table.empty()) - { - std::string query = StringUtils::insertValues( - "SELECT count(type) FROM sqlite_master " - "WHERE type='table' AND name='%s';", ip_ban_table.c_str()); - - ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0); - if (ret == SQLITE_OK) - { - ret = sqlite3_step(stmt); - if (ret == SQLITE_ROW) - { - int number = sqlite3_column_int(stmt, 0); - if (number == 1) - { - Log::info("ServerLobby", "%s ip ban table will used.", - ip_ban_table.c_str()); - m_ip_ban_table_exists = true; - } - } - ret = sqlite3_finalize(stmt); - if (ret != SQLITE_OK) - { - Log::error("ServerLobby", - "Error finalize database for query %s: %s", query.c_str(), - sqlite3_errmsg(m_db)); - } - } - } - if (!m_ip_ban_table_exists && !ip_ban_table.empty()) - { - Log::warn("ServerLobby", "%s ip ban table not found in database.", - ip_ban_table.c_str()); - } - - const std::string online_id_ban_table = - ServerConfig::m_online_id_ban_table; - if (!online_id_ban_table.empty()) - { - std::string query = StringUtils::insertValues( - "SELECT count(type) FROM sqlite_master " - "WHERE type='table' AND name='%s';", online_id_ban_table.c_str()); - - int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0); - if (ret == SQLITE_OK) - { - ret = sqlite3_step(stmt); - if (ret == SQLITE_ROW) - { - int number = sqlite3_column_int(stmt, 0); - if (number == 1) - { - Log::info("ServerLobby", - "%s online id ban table will used.", - online_id_ban_table.c_str()); - m_online_id_ban_table_exists = true; - } - } - ret = sqlite3_finalize(stmt); - if (ret != SQLITE_OK) - { - Log::error("ServerLobby", - "Error finalize database for query %s: %s", - query.c_str(), sqlite3_errmsg(m_db)); - } - } - } - if (!m_online_id_ban_table_exists && !online_id_ban_table.empty()) - { - Log::warn("ServerLobby", - "%s online id ban table not found in database.", - online_id_ban_table.c_str()); - } + checkTableExists(ServerConfig::m_ip_ban_table, m_ip_ban_table_exists); + checkTableExists(ServerConfig::m_online_id_ban_table, + m_online_id_ban_table_exists); + checkTableExists(ServerConfig::m_player_reports_table, + m_player_reports_table_exists); #endif } // initDatabase @@ -790,6 +721,49 @@ void ServerLobby::easySQLQuery(const std::string& query) const query.c_str(), sqlite3_errmsg(m_db)); } } // easySQLQuery + +//----------------------------------------------------------------------------- +/* Write true to result if table name exists in database. */ +void ServerLobby::checkTableExists(const std::string& table, bool& result) +{ + if (!m_db) + return; + sqlite3_stmt* stmt = NULL; + if (!table.empty()) + { + std::string query = StringUtils::insertValues( + "SELECT count(type) FROM sqlite_master " + "WHERE type='table' AND name='%s';", table.c_str()); + + int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0); + if (ret == SQLITE_OK) + { + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) + { + int number = sqlite3_column_int(stmt, 0); + if (number == 1) + { + Log::info("ServerLobby", "Table named %s will used.", + table.c_str()); + result = true; + } + } + ret = sqlite3_finalize(stmt); + if (ret != SQLITE_OK) + { + Log::error("ServerLobby", + "Error finalize database for query %s: %s", + query.c_str(), sqlite3_errmsg(m_db)); + } + } + } + if (!result && !table.empty()) + { + Log::warn("ServerLobby", "Table named %s not found in database.", + table.c_str()); + } +} // checkTableExists #endif //----------------------------------------------------------------------------- @@ -2767,7 +2741,8 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, message_ack->addFloat(auto_start_timer) .addUInt32(ServerConfig::m_state_frequency) - .addUInt8(ServerConfig::m_chat ? 1 : 0); + .addUInt8(ServerConfig::m_chat ? 1 : 0) + .addUInt8(m_player_reports_table_exists ? 1 : 0); peer->setSpectator(false); if (game_started) diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp index e0a88c238..bc27ac8bc 100644 --- a/src/network/protocols/server_lobby.hpp +++ b/src/network/protocols/server_lobby.hpp @@ -70,6 +70,8 @@ private: irr::core::stringw m_name; bool m_tried = false; }; + bool m_player_reports_table_exists; + #ifdef ENABLE_SQLITE3 sqlite3* m_db; @@ -84,6 +86,8 @@ private: void cleanupDatabase(); void easySQLQuery(const std::string& query) const; + + void checkTableExists(const std::string& table, bool& result); #endif void initDatabase(); diff --git a/src/network/server_config.cpp b/src/network/server_config.cpp index 418996d72..e2f7cb9ae 100644 --- a/src/network/server_config.cpp +++ b/src/network/server_config.cpp @@ -311,6 +311,8 @@ void loadServerLobbyFromConfig() } NetworkConfig::get()->setStateFrequency(m_state_frequency); + if (m_player_reports_expired_days < 0.0f) + m_player_reports_expired_days.revertToDefaults(); if (m_server_difficulty > RaceManager::DIFFICULTY_LAST) m_server_difficulty = RaceManager::DIFFICULTY_LAST; if (m_server_mode > 8) diff --git a/src/network/server_config.hpp b/src/network/server_config.hpp index 2ac3434ea..df4b613b2 100644 --- a/src/network/server_config.hpp +++ b/src/network/server_config.hpp @@ -322,8 +322,8 @@ namespace ServerConfig SERVER_CFG_PREFIX BoolServerConfigParam m_sql_management SERVER_CFG_DEFAULT(BoolServerConfigParam(false, "sql-management", - "Use sql to manage server stats and banlist, STK needs to be compiled " - "with sqlite3 supported.")); + "Use sql database for handling server stats and maintenance, STK " + "needs to be compiled with sqlite3 supported.")); SERVER_CFG_PREFIX StringServerConfigParam m_database_file SERVER_CFG_DEFAULT(StringServerConfigParam("stkservers.db", @@ -334,17 +334,29 @@ namespace ServerConfig "NETWORKING.md for details")); SERVER_CFG_PREFIX StringServerConfigParam m_ip_ban_table - SERVER_CFG_DEFAULT(StringServerConfigParam("ipban", + SERVER_CFG_DEFAULT(StringServerConfigParam("ip_ban", "ip-ban-table", "Ip ban list table name, you need to create the table first, see " "NETWORKING.md for details, empty to disable.")); SERVER_CFG_PREFIX StringServerConfigParam m_online_id_ban_table - SERVER_CFG_DEFAULT(StringServerConfigParam("onlineidban", + SERVER_CFG_DEFAULT(StringServerConfigParam("online_id_ban", "online-id-ban-table", "Online ID ban list table name, you need to create the table first, " "see NETWORKING.md for details, empty to disable.")); + SERVER_CFG_PREFIX StringServerConfigParam m_player_reports_table + SERVER_CFG_DEFAULT(StringServerConfigParam("player_reports", + "player-reports-table", + "Player reports table name, which will be written when a player " + "reports player in the network user dialog, you need to create the " + "table first, see NETWORKING.md for details, empty to disable.")); + + SERVER_CFG_PREFIX FloatServerConfigParam m_player_reports_expired_days + SERVER_CFG_DEFAULT(FloatServerConfigParam(3.0f, + "player-reports-expired-days", "Days to keep player reports, " + "older than that will be auto cleared, 0 to keep them forever.")); + // ======================================================================== /** Server version, will be advanced if there are protocol changes. */ static const uint32_t m_server_version = 6; diff --git a/src/states_screens/dialogs/network_user_dialog.cpp b/src/states_screens/dialogs/network_user_dialog.cpp index fd8ee2733..dce66ada9 100644 --- a/src/states_screens/dialogs/network_user_dialog.cpp +++ b/src/states_screens/dialogs/network_user_dialog.cpp @@ -26,7 +26,7 @@ #include "guiengine/widgets/ribbon_widget.hpp" #include "guiengine/widgets/text_box_widget.hpp" #include "online/online_profile.hpp" -#include "network/protocols/lobby_protocol.hpp" +#include "network/protocols/client_lobby.hpp" #include "network/stk_host.hpp" #include "states_screens/dialogs/general_text_field_dialog.hpp" #include "states_screens/state_manager.hpp" @@ -129,7 +129,9 @@ void NetworkUserDialog::beforeAddingWidgets() getWidget("remove")->setVisible(false); m_report_widget = getWidget("enter"); assert(m_report_widget != NULL); - if (m_host_id != STKHost::get()->getMyHostId()) + auto cl = LobbyProtocol::get(); + if (cl->serverEnabledReportPlayer() && + m_host_id != STKHost::get()->getMyHostId()) { // I18N: In the network user dialog, // report player about for example abusive behaviour in game