diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index c4dec4074..a959d9093 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -122,6 +122,7 @@ SET(common_headers cli/terminal_color.hpp data_verification.h database.h + database_schema.h dbcore.h deity.h emu_constants.h diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index ef46e0d9f..bbcdb4612 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -38,10 +38,6 @@ namespace EQEmuCommand { void DisplayDebug(argh::parser &cmd) { if (cmd[{"-d", "--debug"}]) { - std::cout << "Positional args:\n"; - for (auto &pos_arg : cmd) - std::cout << '\t' << pos_arg << std::endl; - std::cout << "Positional args:\n"; for (auto &pos_arg : cmd.pos_args()) std::cout << '\t' << pos_arg << std::endl; @@ -73,29 +69,37 @@ namespace EQEmuCommand { { bool arguments_filled = true; + int index = 2; for (auto &arg : arguments) { - if (cmd(arg).str().empty()) { + if (cmd(arg).str().empty() && cmd(index).str().empty()) { arguments_filled = false; } + index++; } if (!arguments_filled || argc == 2) { std::string arguments_string; for (auto &arg : arguments) { - arguments_string += " " + arg + "=*\n"; + arguments_string += " " + arg; } std::string options_string; - for (auto &opt : options) { + for (auto &opt : options) { options_string += " " + opt + "\n"; } - std::cout << fmt::format( - "Command\n\n{0} \n\nArgs\n{1}\nOptions\n{2}", - argv[1], - arguments_string, - options_string - ) << std::endl; + std::stringstream command_string; + + command_string << + termcolor::colorize << + termcolor::yellow << + "\nCommand" << + termcolor::reset << "\n\n" << + termcolor::green << argv[1] << arguments_string << termcolor::reset << "\n" << + termcolor::yellow << (!options_string.empty() ? "\nOptions\n" : "") << + termcolor::reset << termcolor::cyan << options_string << termcolor::reset; + + std::cout << command_string.str() << std::endl; exit(1); } @@ -123,10 +127,6 @@ namespace EQEmuCommand { bool ran_command = false; for (auto &it: in_function_map) { if (it.first == argv[1]) { - std::cout << std::endl; - std::cout << "> " << termcolor::cyan << "Executing CLI Command" << termcolor::reset << std::endl; - std::cout << std::endl; - (it.second)(argc, argv, cmd, description); ran_command = true; } @@ -182,12 +182,13 @@ namespace EQEmuCommand { } std::cout << std::endl; - } - else if (!ran_command) { - std::cerr << "Unknown command [" << argv[1] << "] ! Try --help" << std::endl; + + std::exit(1); } - exit(1); + if (ran_command) { + std::exit(1); + } } } diff --git a/common/database.cpp b/common/database.cpp index cbec7fc10..4e762f917 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -293,6 +293,37 @@ bool Database::SetAccountStatus(const char* name, int16 status) { return true; } +/** + * @param account_name + * @param status + * @return + */ +bool Database::SetAccountStatus(const std::string& account_name, int16 status) +{ + LogInfo("Account [{}] is attempting to be set to status [{}]", account_name, status); + + std::string query = fmt::format( + SQL( + UPDATE account SET status = {} WHERE name = '{}' + ), + status, + account_name + ); + + auto results = QueryDatabase(query); + + if (!results.Success()) { + return false; + } + + if (results.RowsAffected() == 0) { + LogWarning("Account [{}] does not exist!", account_name); + return false; + } + + return true; +} + /* This initially creates the character during character create */ bool Database::ReserveName(uint32 account_id, char* name) { std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name); diff --git a/common/database.h b/common/database.h index 9fc196d18..c84b5301c 100644 --- a/common/database.h +++ b/common/database.h @@ -179,6 +179,7 @@ public: bool DeleteAccount(const char *name, const char* loginserver); bool GetLiveChar(uint32 account_id, char* cname); bool SetAccountStatus(const char* name, int16 status); + bool SetAccountStatus(const std::string& account_name, int16 status); bool SetLocalPassword(uint32 accid, const char* password); bool UpdateLiveChar(char* charname, uint32 account_id); diff --git a/common/database_schema.h b/common/database_schema.h new file mode 100644 index 000000000..6033e85b5 --- /dev/null +++ b/common/database_schema.h @@ -0,0 +1,296 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef EQEMU_DATABASE_SCHEMA_H +#define EQEMU_DATABASE_SCHEMA_H + +#include + +namespace DatabaseSchema { + + /** + * Gets player tables + * + * @return + */ + static std::vector GetPlayerTables() + { + std::vector tables = { + "aa_timers", + "account", + "account_ip", + "account_flags", + "account_rewards", + "adventure_details", + "adventure_stats", + "buyer", + "char_recipe_list", + "character_activities", + "character_alt_currency", + "character_alternate_abilities", + "character_auras", + "character_bandolier", + "character_bind", + "character_buffs", + "character_corpse_items", + "character_corpses", + "character_currency", + "character_data", + "character_disciplines", + "character_enabledtasks", + "character_inspect_messages", + "character_item_recast", + "character_languages", + "character_leadership_abilities", + "character_material", + "character_memmed_spells", + "character_pet_buffs", + "character_pet_info", + "character_pet_inventory", + "character_potionbelt", + "character_skills", + "character_spells", + "character_tasks", + "character_tribute", + "completed_tasks", + "data_buckets", + "faction_values", + "friends", + "guild_bank", + "guild_members", + "guild_ranks", + "guild_relations", + "guilds", + "instance_list_player", + "inventory", + "inventory_snapshots", + "keyring", + "mail", + "player_titlesets", + "quest_globals", + "sharedbank", + "timers", + "titles", + "trader", + "trader_audit", + "zone_flags" + }; + + return tables; + } + + /** + * Gets content tables + * + * @return + */ + static std::vector GetContentTables() + { + std::vector tables = { + "aa_ability", + "aa_actions", + "aa_effects", + "aa_rank_effects", + "aa_rank_prereqs", + "aa_ranks", + "aa_required_level_cost", + "adventure_template", + "adventure_template_entry", + "adventure_template_entry_flavor", + "altadv_vars", + "alternate_currency", + "auras", + "base_data", + "blocked_spells", + "books", + "char_create_combinations", + "char_create_point_allocations", + "class_skill", + "damageshieldtypes", + "doors", + "faction_base_data", + "faction_list", + "faction_list_mod", + "fear_hints", + "fishing", + "forage", + "global_loot", + "goallists", + "graveyard", + "grid", + "grid_entries", + "ground_spawns", + "horses", + "instance_list", + "items", + "ldon_trap_entries", + "ldon_trap_templates", + "lootdrop", + "lootdrop_entries", + "loottable", + "loottable_entries", + "merchantlist", + "npc_emotes", + "npc_faction", + "npc_faction_entries", + "npc_scale_global_base", + "npc_spells", + "npc_spells_effects", + "npc_spells_effects_entries", + "npc_spells_entries", + "npc_types", + "npc_types_metadata", + "npc_types_tint", + "object", + "pets", + "pets_equipmentset", + "pets_equipmentset_entries", + "proximities", + "races", + "skill_caps", + "spawn2", + "spawn_condition_values", + "spawn_conditions", + "spawn_events", + "spawnentry", + "spawngroup", + "spells_new", + "start_zones", + "starting_items", + "task_activities", + "tasks", + "tasksets", + "titles", + "tradeskill_recipe", + "tradeskill_recipe_entries", + "traps", + "tribute_levels", + "tributes", + "veteran_reward_templates", + "zone", + "zone_points", + "zone_server", + "zoneserver_auth", + }; + + return tables; + } + + /** + * Gets server tables + * + * @return + */ + static std::vector GetServerTables() + { + std::vector tables = { + "banned_ips", + "bugs", + "bug_reports", + "command_settings", + "db_str", + "discovered_items", + "eqtime", + "eventlog", + "gm_ips", + "hackers", + "ip_exemptions", + "launcher", + "launcher_zones", + "level_exp_mods", + "logsys_categories", + "name_filter", + "perl_event_export_settings", + "petitions", + "profanity_list", + "reports", + "rule_sets", + "rule_values", + "saylink", + "variables", + }; + + return tables; + } + + /** + * Gets state tables + * Tables that keep track of server state + * + * @return + */ + static std::vector GetStateTables() + { + std::vector tables = { + "adventure_members", + "chatchannels", + "group_id", + "group_leaders", + "item_tick", + "lfguild", + "merchantlist_temp", + "object_contents", + "raid_details", + "raid_leaders", + "raid_members", + "respawn_times", + "spell_buckets", + "spell_globals", + }; + + return tables; + } + + /** + * Gets login tables + * + * @return + */ + static std::vector GetLoginTables() + { + std::vector tables = { + "login_accounts", + "login_api_tokens", + "login_server_admins", + "login_server_list_types", + "login_world_servers", + }; + + return tables; + } + + /** + * Gets login tables + * + * @return + */ + static std::vector GetVersionTables() + { + std::vector tables = { + "db_version", + "inventory_versions", + }; + + return tables; + } + +} + +#endif //EQEMU_DATABASE_SCHEMA_H diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index c2d786d94..f5d58a5fd 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -579,3 +579,25 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name) ); } } + +/** + * Silence console logging + */ +void EQEmuLogSys::SilenceConsoleLogging() +{ + for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) { + log_settings[log_index].log_to_console = 0; + log_settings[log_index].is_category_enabled = 0; + } +} + +/** + * Enables console logging + */ +void EQEmuLogSys::EnableConsoleLogging() +{ + for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) { + log_settings[log_index].log_to_console = Logs::General; + log_settings[log_index].is_category_enabled = 1; + } +} diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 11645c6fa..d2d860101 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -279,6 +279,16 @@ public: */ void SetConsoleHandler(std::function f) { on_log_console_hook = f; } + /** + * Silence console logging + */ + void SilenceConsoleLogging(); + + /** + * Turn on all console logging + */ + void EnableConsoleLogging(); + private: /** diff --git a/common/json/jsoncpp.cpp b/common/json/jsoncpp.cpp index 00c48700d..759e68fa6 100644 --- a/common/json/jsoncpp.cpp +++ b/common/json/jsoncpp.cpp @@ -5277,7 +5277,7 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings) { //! [StreamWriterBuilderDefaults] (*settings)["commentStyle"] = "All"; - (*settings)["indentation"] = "\t"; + (*settings)["indentation"] = " "; (*settings)["enableYAMLCompatibility"] = false; (*settings)["dropNullPlaceholders"] = false; (*settings)["useSpecialFloats"] = false; diff --git a/common/version.h b/common/version.h index e51279456..17e69601a 100644 --- a/common/version.h +++ b/common/version.h @@ -1,20 +1,22 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ #ifndef _EQEMU_VERSION_H #define _EQEMU_VERSION_H @@ -22,14 +24,15 @@ #define LOGIN_VERSION "0.8.0" #define EQEMU_PROTOCOL_VERSION "0.3.10" -#define CURRENT_VERSION "1.1.3" +#define CURRENT_VERSION "2.0" -/* - Everytime a Database SQL is added to Github, - increment CURRENT_BINARY_DATABASE_VERSION number and make sure you update the manifest - Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt -*/ +/** + * Every time a Database SQL is added to Github increment CURRENT_BINARY_DATABASE_VERSION + * number and make sure you update the manifest + * + * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt + */ #define CURRENT_BINARY_DATABASE_VERSION 9145 @@ -38,6 +41,7 @@ #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif + #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index ed98eae5e..7080f1996 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -21,6 +21,10 @@ #endif +/** + * @param mode + * @return + */ std::string GetEncryptionByModeId(uint32 mode) { switch (mode) { @@ -57,6 +61,13 @@ std::string GetEncryptionByModeId(uint32 mode) } } +/** + * @param buffer_in + * @param buffer_in_sz + * @param buffer_out + * @param enc + * @return + */ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc) { #ifdef EQEMU_USE_MBEDTLS @@ -125,6 +136,10 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff return buffer_out; } +/** + * @param msg + * @return + */ std::string eqcrypt_md5(const std::string &msg) { std::string ret; @@ -159,6 +174,10 @@ std::string eqcrypt_md5(const std::string &msg) return ret; } +/** + * @param msg + * @return + */ std::string eqcrypt_sha1(const std::string &msg) { std::string ret; @@ -193,6 +212,10 @@ std::string eqcrypt_sha1(const std::string &msg) return ret; } +/** + * @param msg + * @return + */ std::string eqcrypt_sha512(const std::string &msg) { std::string ret; diff --git a/loginserver/login_server.h b/loginserver/login_server.h index e71cc7da0..c130c41d2 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -38,6 +38,7 @@ struct LoginServer { public: + LoginServer() : db(nullptr), server_manager(nullptr) { } diff --git a/loginserver/loginserver_command_handler.cpp b/loginserver/loginserver_command_handler.cpp index ae487d676..35599e299 100644 --- a/loginserver/loginserver_command_handler.cpp +++ b/loginserver/loginserver_command_handler.cpp @@ -112,6 +112,9 @@ namespace LoginserverCommandHandler { return; } + server.token_manager = new LoginserverWebserver::TokenManager; + server.token_manager->LoadApiTokens(); + for (auto &it : server.token_manager->loaded_api_tokens) { LogInfo( "token [{0}] can_write [{1}] can_read [{2}]", @@ -133,8 +136,8 @@ namespace LoginserverCommandHandler { description = "Creates Local Loginserver Account"; std::vector arguments = { - "--username", - "--password" + "{username}", + "{password}" }; std::vector options = { "--email=*" @@ -147,8 +150,8 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); AccountManagement::CreateLoginServerAccount( - cmd("--username").str(), - cmd("--password").str(), + cmd(2).str(), + cmd(3).str(), cmd("--email").str() ); } @@ -164,9 +167,9 @@ namespace LoginserverCommandHandler { description = "Creates Loginserver World Administrator Account"; std::vector arguments = { - "--username", - "--password", - "--email" + "{username}", + "{password}", + "{email}" }; std::vector options = {}; @@ -177,9 +180,9 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); AccountManagement::CreateLoginserverWorldAdminAccount( - cmd("--username").str(), - cmd("--password").str(), - cmd("--email").str() + cmd(2).str(), + cmd(3).str(), + cmd(4).str() ); } @@ -194,8 +197,8 @@ namespace LoginserverCommandHandler { description = "Check user login credentials"; std::vector arguments = { - "--username", - "--password" + "{username}", + "{password}" }; std::vector options = {}; @@ -206,11 +209,11 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); auto res = AccountManagement::CheckLoginserverUserCredentials( - cmd("--username").str(), - cmd("--password").str() + cmd(2).str(), + cmd(3).str() ); - LogInfo("Credentials were {0}", res == true ? "accepted" : "not accepted"); + LogInfo("Credentials were {0}", res != 0 ? "accepted" : "not accepted"); } /** @@ -224,8 +227,8 @@ namespace LoginserverCommandHandler { description = "Change user login credentials"; std::vector arguments = { - "--username", - "--password" + "{username}", + "{password}" }; std::vector options = {}; @@ -236,8 +239,8 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); AccountManagement::UpdateLoginserverUserCredentials( - cmd("--username").str(), - cmd("--password").str() + cmd(2).str(), + cmd(3).str() ); } @@ -252,8 +255,8 @@ namespace LoginserverCommandHandler { description = "Check user external login credentials"; std::vector arguments = { - "--username", - "--password" + "{username}", + "{password}" }; std::vector options = {}; @@ -264,8 +267,8 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); auto res = AccountManagement::CheckExternalLoginserverUserCredentials( - cmd("--username").str(), - cmd("--password").str() + cmd(2).str(), + cmd(3).str() ); LogInfo("Credentials were {0}", res ? "accepted" : "not accepted"); @@ -282,8 +285,8 @@ namespace LoginserverCommandHandler { description = "Update world admin account password"; std::vector arguments = { - "--username", - "--password" + "{username}", + "{password}" }; std::vector options = {}; @@ -294,8 +297,8 @@ namespace LoginserverCommandHandler { EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName( - cmd("--username").str(), - cmd("--password").str() + cmd(2).str(), + cmd(3).str() ); } } diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 6941ad7e6..9e6006342 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -43,22 +43,28 @@ void CatchSignal(int sig_num) { } -int main(int argc, char **argv) +void LoadDatabaseConnection() { - RegisterExecutablePlatform(ExePlatformLogin); - set_exception_handler(); + LogInfo("MySQL Database Init"); - LogInfo("Logging System Init"); + server.db = new Database( + server.config.GetVariableString("database", "user", "root"), + server.config.GetVariableString("database", "password", ""), + server.config.GetVariableString("database", "host", "localhost"), + server.config.GetVariableString("database", "port", "3306"), + server.config.GetVariableString("database", "db", "peq") + ); - if (argc == 1) { - LogSys.LoadLogSettingsDefaults(); - } +} +void LoadServerConfig() +{ server.config = EQ::JsonConfigFile::Load("login.json"); LogInfo("Config System Init"); + /** - * options: logging + * Logging */ server.options.Trace(server.config.GetVariableBool("logging", "trace", false)); server.options.WorldTrace(server.config.GetVariableBool("logging", "world_trace", false)); @@ -66,7 +72,7 @@ int main(int argc, char **argv) server.options.DumpOutPackets(server.config.GetVariableBool("logging", "dump_packets_out", false)); /** - * options: worldservers + * Worldservers */ server.options.RejectDuplicateServers( server.config.GetVariableBool( @@ -77,7 +83,7 @@ int main(int argc, char **argv) server.options.AllowUnregistered(server.config.GetVariableBool("worldservers", "unregistered_allowed", true)); /** - * options: account + * Account */ server.options.AutoCreateAccounts(server.config.GetVariableBool("account", "auto_create_accounts", true)); server.options.AutoLinkAccounts(server.config.GetVariableBool("account", "auto_link_accounts", false)); @@ -92,6 +98,9 @@ int main(int argc, char **argv) ); #endif + /** + * Default Loginserver Name (Don't change) + */ server.options.DefaultLoginServerName( server.config.GetVariableString( "general", @@ -100,6 +109,10 @@ int main(int argc, char **argv) ) ); + /** + * Security + */ + #ifdef ENABLE_SECURITY server.options.EncryptionMode(server.config.GetVariableInt("security", "mode", 13)); #else @@ -115,19 +128,41 @@ int main(int argc, char **argv) true ) ); +} + +int main(int argc, char **argv) +{ + RegisterExecutablePlatform(ExePlatformLogin); + set_exception_handler(); + + LogInfo("Logging System Init"); + + if (argc == 1) { + LogSys.LoadLogSettingsDefaults(); + } + + /** + * Command handler + */ + if (argc > 1) { + LogSys.SilenceConsoleLogging(); + + LoadServerConfig(); + LoadDatabaseConnection(); + + LogSys.LoadLogSettingsDefaults(); + LogSys.log_settings[Logs::Debug].log_to_console = static_cast(Logs::General); + LogSys.log_settings[Logs::Debug].is_category_enabled = 1; + + LoginserverCommandHandler::CommandHandler(argc, argv); + } + + LoadServerConfig(); /** * mysql connect */ - LogInfo("MySQL Database Init"); - - server.db = new Database( - server.config.GetVariableString("database", "user", "root"), - server.config.GetVariableString("database", "password", ""), - server.config.GetVariableString("database", "host", "localhost"), - server.config.GetVariableString("database", "port", "3306"), - server.config.GetVariableString("database", "db", "peq") - ); + LoadDatabaseConnection(); if (argc == 1) { server.db->LoadLogSettings(LogSys.log_settings); @@ -195,14 +230,6 @@ int main(int argc, char **argv) LoginserverWebserver::RegisterRoutes(api); } - if (argc > 1) { - LogSys.LoadLogSettingsDefaults(); - LogSys.log_settings[Logs::Debug].log_to_console = static_cast(Logs::General); - LogSys.log_settings[Logs::Debug].is_category_enabled = 1; - - LoginserverCommandHandler::CommandHandler(argc, argv); - } - LogInfo("[Config] [Logging] IsTraceOn [{0}]", server.options.IsTraceOn()); LogInfo("[Config] [Logging] IsWorldTraceOn [{0}]", server.options.IsWorldTraceOn()); LogInfo("[Config] [Logging] IsDumpInPacketsOn [{0}]", server.options.IsDumpInPacketsOn()); diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index c042a7364..9906b0cfc 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -14,7 +14,7 @@ SET(world_sources lfplist.cpp login_server.cpp login_server_list.cpp - net.cpp + main.cpp queryserv.cpp ucs.cpp web_interface.cpp @@ -22,6 +22,7 @@ SET(world_sources wguild_mgr.cpp world_config.cpp world_console_connection.cpp + world_server_command_handler.cpp worlddb.cpp zonelist.cpp zoneserver.cpp @@ -51,6 +52,7 @@ SET(world_headers world_config.h world_console_connection.h world_tcp_connection.h + world_server_command_handler.h worlddb.h zonelist.h zoneserver.h diff --git a/world/net.cpp b/world/main.cpp similarity index 76% rename from world/net.cpp rename to world/main.cpp index aeb9d8b4d..0ab5f2089 100644 --- a/world/net.cpp +++ b/world/main.cpp @@ -1,20 +1,23 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ #include "../common/global_define.h" #include @@ -86,6 +89,7 @@ union semun { #include "../common/net/servertalk_server.h" #include "../zone/data_bucket.h" +#include "world_server_command_handler.h" ClientList client_list; GroupLFPList LFPGroupList; @@ -113,14 +117,30 @@ inline void UpdateWindowTitle(std::string new_title) { #endif } -int main(int argc, char** argv) { - RegisterExecutablePlatform(ExePlatformWorld); - LogSys.LoadLogSettingsDefaults(); - set_exception_handler(); +void LoadDatabaseConnections() +{ + LogInfo( + "Connecting to MySQL [{}]@[{}]:[{}]", + Config->DatabaseUsername.c_str(), + Config->DatabaseHost.c_str(), + Config->DatabasePort + ); - /** - * Auto convert json config from xml - */ + if (!database.Connect( + Config->DatabaseHost.c_str(), + Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), + Config->DatabaseDB.c_str(), + Config->DatabasePort + )) { + LogError("Cannot continue without a database connection"); + + std::exit(1); + } +} + +void CheckForXMLConfigUpgrade() +{ if (!std::ifstream("eqemu_config.json") && std::ifstream("eqemu_config.xml")) { CheckForServerScript(true); if(system("perl eqemu_server.pl convert_xml")); @@ -128,26 +148,105 @@ int main(int argc, char** argv) { else { CheckForServerScript(); } +} + +void LoadServerConfig() +{ + LogInfo("Loading server configuration"); + if (!WorldConfig::LoadConfig()) { + LogError("Loading server configuration failed"); + std::exit(1); + } +} + +void RegisterLoginservers() +{ + if (Config->LoginCount == 0) { + if (Config->LoginHost.length()) { + loginserverlist.Add( + Config->LoginHost.c_str(), + Config->LoginPort, + Config->LoginAccount.c_str(), + Config->LoginPassword.c_str(), + Config->LoginLegacy + ); + LogInfo("Added loginserver [{}]:[{}]", Config->LoginHost.c_str(), Config->LoginPort); + } + } + else { + LinkedList loginlist = Config->loginlist; + LinkedListIterator iterator(loginlist); + iterator.Reset(); + while (iterator.MoreElements()) { + if (iterator.GetData()->LoginHost.length()) { + loginserverlist.Add( + iterator.GetData()->LoginHost.c_str(), + iterator.GetData()->LoginPort, + iterator.GetData()->LoginAccount.c_str(), + iterator.GetData()->LoginPassword.c_str(), + iterator.GetData()->LoginLegacy + ); + + LogInfo( + "Added loginserver [{}]:[{}]", + iterator.GetData()->LoginHost.c_str(), + iterator.GetData()->LoginPort + ); + } + iterator.Advance(); + } + } +} + +/** + * World process entrypoint + * + * @param argc + * @param argv + * @return + */ +int main(int argc, char** argv) { + RegisterExecutablePlatform(ExePlatformWorld); + LogSys.LoadLogSettingsDefaults(); + set_exception_handler(); /** * Database version */ - uint32 Database_Version = CURRENT_BINARY_DATABASE_VERSION; - uint32 Bots_Database_Version = CURRENT_BINARY_BOTS_DATABASE_VERSION; + uint32 database_version = CURRENT_BINARY_DATABASE_VERSION; + uint32 bots_database_version = CURRENT_BINARY_BOTS_DATABASE_VERSION; if (argc >= 2) { if (strcasecmp(argv[1], "db_version") == 0) { - std::cout << "Binary Database Version: " << Database_Version << " : " << Bots_Database_Version << std::endl; + std::cout << "Binary Database Version: " << database_version << " : " << bots_database_version << std::endl; return 0; } } - // Load server configuration - LogInfo("Loading server configuration"); - if (!WorldConfig::LoadConfig()) { - LogError("Loading server configuration failed"); - return 1; + /** + * Command handler + */ + if (argc > 1) { + LogSys.SilenceConsoleLogging(); + + /** + * Get Config + */ + WorldConfig::LoadConfig(); + Config = WorldConfig::get(); + + /** + * Load database + */ + LoadDatabaseConnections(); + + LogSys.EnableConsoleLogging(); + + WorldserverCommandHandler::CommandHandler(argc, argv); } + CheckForXMLConfigUpgrade(); + LoadServerConfig(); + Config = WorldConfig::get(); LogInfo("CURRENT_VERSION: [{}]", CURRENT_VERSION); @@ -169,146 +268,23 @@ int main(int argc, char** argv) { } #endif - /** - * Add Loginserver - */ - if (Config->LoginCount == 0) { - if (Config->LoginHost.length()) { - loginserverlist.Add( - Config->LoginHost.c_str(), - Config->LoginPort, - Config->LoginAccount.c_str(), - Config->LoginPassword.c_str(), - Config->LoginLegacy - ); - LogInfo("Added loginserver [{}]:[{}]", Config->LoginHost.c_str(), Config->LoginPort); - } - } - else { - LinkedList loginlist = Config->loginlist; - LinkedListIterator iterator(loginlist); - iterator.Reset(); - while (iterator.MoreElements()) { - loginserverlist.Add( - iterator.GetData()->LoginHost.c_str(), - iterator.GetData()->LoginPort, - iterator.GetData()->LoginAccount.c_str(), - iterator.GetData()->LoginPassword.c_str(), - iterator.GetData()->LoginLegacy - ); + RegisterLoginservers(); + LoadDatabaseConnections(); - LogInfo("Added loginserver [{}]:[{}]", iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort); - iterator.Advance(); - } - } - - LogInfo("Connecting to MySQL [{}]@[{}]:[{}]", Config->DatabaseUsername.c_str(), Config->DatabaseHost.c_str(), Config->DatabasePort); - if (!database.Connect( - Config->DatabaseHost.c_str(), - Config->DatabaseUsername.c_str(), - Config->DatabasePassword.c_str(), - Config->DatabaseDB.c_str(), - Config->DatabasePort)) { - LogError("Cannot continue without a database connection"); - return 1; - } guild_mgr.SetDatabase(&database); - /* Register Log System and Settings */ + /** + * Logging + */ database.LoadLogSettings(LogSys.log_settings); LogSys.StartFileLogs(); + /** + * Parse simple CLI passes + */ bool ignore_db = false; if (argc >= 2) { - std::string tmp; - if (strcasecmp(argv[1], "help") == 0 || strcasecmp(argv[1], "?") == 0 || strcasecmp(argv[1], "/?") == 0 || strcasecmp(argv[1], "-?") == 0 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "-help") == 0) { - std::cout << "Worldserver command line commands:" << std::endl; - std::cout << "adduser username password flag - adds a user account" << std::endl; - std::cout << "flag username flag - sets GM flag on the account" << std::endl; - std::cout << "startzone zoneshortname - sets the starting zone" << std::endl; - std::cout << "-holdzones - reboots lost zones" << std::endl; - return 0; - } - else if (strcasecmp(argv[1], "-holdzones") == 0) { - std::cout << "Reboot Zones mode ON" << std::endl; - holdzones = true; - } - else if (database.GetVariable("disablecommandline", tmp)) { - if (tmp.length() == 1) { - if (tmp[0] == '1') { - std::cerr << "Command line disabled in database... exiting" << std::endl; - return 1; - } - } - } - else if (strcasecmp(argv[1], "adduser") == 0) { - if (argc == 5) { - if (Seperator::IsNumber(argv[4])) { - if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) { - std::string user; - std::string loginserver; - - ParseAccountString(argv[2], user, loginserver); - - if (database.CreateAccount(argv[2], argv[3], atoi(argv[4]), loginserver.c_str(), 0) == 0) { - std::cerr << "database.CreateAccount failed." << std::endl; - return 1; - } - else { - std::cout << "Account created: Username='" << argv[2] << "', Password='" << argv[3] << "', status=" << argv[4] << std::endl; - return 0; - } - } - } - } - std::cout << "Usage: world adduser username password flag" << std::endl; - std::cout << "flag = 0, 1 or 2" << std::endl; - return 0; - } - else if (strcasecmp(argv[1], "flag") == 0) { - if (argc == 4) { - if (Seperator::IsNumber(argv[3])) { - if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) { - if (database.SetAccountStatus(argv[2], atoi(argv[3]))) { - std::cout << "Account flagged: Username='" << argv[2] << "', status=" << argv[3] << std::endl; - return 0; - } - else { - std::cerr << "database.SetAccountStatus failed." << std::endl; - return 1; - } - } - } - } - std::cout << "Usage: world flag username flag" << std::endl; - std::cout << "flag = 0-200" << std::endl; - return 0; - } - else if (strcasecmp(argv[1], "startzone") == 0) { - if (argc == 3) { - if (strlen(argv[2]) < 3) { - std::cerr << "Error: zone name too short" << std::endl; - return 1; - } - else if (strlen(argv[2]) > 15) { - std::cerr << "Error: zone name too long" << std::endl; - return 1; - } - else { - if (database.SetVariable("startzone", argv[2])) { - std::cout << "Starting zone changed: '" << argv[2] << "'" << std::endl; - return 0; - } - else { - std::cerr << "database.SetVariable failed." << std::endl; - return 1; - } - } - } - std::cout << "Usage: world startzone zoneshortname" << std::endl; - return 0; - } - else if (strcasecmp(argv[1], "ignore_db") == 0) { + if (strcasecmp(argv[1], "ignore_db") == 0) { ignore_db = true; } else { @@ -360,7 +336,7 @@ int main(int argc, char** argv) { if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) { LogInfo("Failed to process 'Orphaned Rules' update operation."); } - + if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) { LogInfo("Failed to process 'Injected Rules' for ruleset 'default' update operation."); } @@ -407,13 +383,6 @@ int main(int argc, char** argv) { LogInfo("Loading launcher list"); launcher_list.LoadList(); - std::string tmp; - database.GetVariable("holdzones", tmp); - if (tmp.length() == 1 && tmp[0] == '1') { - holdzones = true; - } - LogInfo("Reboot zone modes [{}]", holdzones ? "ON" : "OFF"); - LogInfo("Deleted [{}] stale player corpses from database", database.DeleteStalePlayerCorpses()); LogInfo("Loading adventures"); diff --git a/world/net.h b/world/main.h similarity index 100% rename from world/net.h rename to world/main.h diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp new file mode 100644 index 000000000..003e9abe2 --- /dev/null +++ b/world/world_server_command_handler.cpp @@ -0,0 +1,205 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "world_server_command_handler.h" +#include "../common/eqemu_logsys.h" +#include "../common/json/json.h" +#include "../common/version.h" +#include "worlddb.h" +#include "../common/database_schema.h" + +namespace WorldserverCommandHandler { + + /** + * @param argc + * @param argv + */ + void CommandHandler(int argc, char **argv) + { + if (argc == 1) { return; } + + argh::parser cmd; + cmd.parse(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION); + EQEmuCommand::DisplayDebug(cmd); + + /** + * Declare command mapping + */ + auto function_map = EQEmuCommand::function_map; + + /** + * Register commands + */ + function_map["world:version"] = &WorldserverCommandHandler::Version; + function_map["database:version"] = &WorldserverCommandHandler::DatabaseVersion; + function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus; + function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema; + + EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); + } + + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Shows database version"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value database_version; + + database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; + database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; + + std::stringstream payload; + payload << database_version; + + std::cout << payload.str() << std::endl; + } + + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void Version(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Shows server version"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value database_version; + + database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION; + database_version["compile_date"] = COMPILE_DATE; + database_version["compile_time"] = COMPILE_TIME; + database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION; + database_version["server_version"] = CURRENT_VERSION; + + std::stringstream payload; + payload << database_version; + + std::cout << payload.str() << std::endl; + } + + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Sets account status by account name"; + + std::vector arguments = { + "{name}", + "{status}" + }; + + std::vector options = {}; + + if (cmd[{"-h", "--help"}]) { + return; + } + + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + + database.SetAccountStatus( + cmd(2).str(), + std::stoi(cmd(3).str()) + ); + } + + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Displays server database schema"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value player_tables_json; + std::vector player_tables = DatabaseSchema::GetPlayerTables(); + for (const auto &table : player_tables) { + player_tables_json.append(table); + } + + Json::Value content_tables_json; + std::vector content_tables = DatabaseSchema::GetContentTables(); + for (const auto &table : content_tables) { + content_tables_json.append(table); + } + + Json::Value server_tables_json; + std::vector server_tables = DatabaseSchema::GetServerTables(); + for (const auto &table : server_tables) { + server_tables_json.append(table); + } + + Json::Value login_tables_json; + std::vector login_tables = DatabaseSchema::GetLoginTables(); + for (const auto &table : login_tables) { + login_tables_json.append(table); + } + + Json::Value state_tables_json; + std::vector state_tables = DatabaseSchema::GetStateTables(); + for (const auto &table : state_tables) { + state_tables_json.append(table); + } + + Json::Value version_tables_json; + std::vector version_tables = DatabaseSchema::GetVersionTables(); + for (const auto &table : version_tables) { + version_tables_json.append(table); + } + + Json::Value schema; + + schema["server_tables"] = server_tables_json; + schema["player_tables"] = player_tables_json; + schema["content_tables"] = content_tables_json; + schema["login_tables"] = login_tables_json; + schema["state_tables"] = state_tables_json; + schema["version_tables"] = version_tables_json; + + std::stringstream payload; + payload << schema; + + std::cout << payload.str() << std::endl; + } + +} \ No newline at end of file diff --git a/world/world_server_command_handler.h b/world/world_server_command_handler.h new file mode 100644 index 000000000..f3d4317f2 --- /dev/null +++ b/world/world_server_command_handler.h @@ -0,0 +1,36 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "iostream" +#include "../common/cli/eqemu_command_handler.h" + +#ifndef EQEMU_WORLD_SERVER_COMMAND_HANDLER_H +#define EQEMU_WORLD_SERVER_COMMAND_HANDLER_H + +namespace WorldserverCommandHandler { + void CommandHandler(int argc, char **argv); + void Version(int argc, char **argv, argh::parser &cmd, std::string &description); + void DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description); + void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description); + void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); +}; + + +#endif //EQEMU_WORLD_SERVER_COMMAND_HANDLER_H