From ffc532a302a1213852ca1cff9b61f85015181f73 Mon Sep 17 00:00:00 2001 From: def Date: Sun, 19 Dec 2021 01:13:08 +0100 Subject: [PATCH 1/2] Add open_file, works on macOS, safer --- src/base/system.cpp | 25 ++++++++++++++----- src/base/system.h | 23 ++++++++++++++--- src/game/client/components/menus_demo.cpp | 6 ++--- src/game/client/components/menus_settings.cpp | 12 +++------ .../components/menus_settings_assets.cpp | 5 ++-- 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/base/system.cpp b/src/base/system.cpp index 9094d752b..2f573f521 100644 --- a/src/base/system.cpp +++ b/src/base/system.cpp @@ -3666,13 +3666,26 @@ int open_link(const char *link) MultiByteToWideChar(CP_UTF8, 0, link, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR)); return (uintptr_t)ShellExecuteW(NULL, L"open", wBuffer, NULL, NULL, SW_SHOWDEFAULT) > 32; #elif defined(CONF_PLATFORM_LINUX) - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "xdg-open %s >/dev/null 2>&1 &", link); - return system(aBuf) == 0; + const int pid = fork(); + if(pid == 0) + execlp("xdg-open", "xdg-open", link, nullptr); + return pid > 0; #elif defined(CONF_FAMILY_UNIX) - char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "open %s &", link); - return system(aBuf) == 0; + const int pid = fork(); + if(pid == 0) + execlp("open", "open", link, nullptr); + return pid > 0; +#endif +} + +int open_file(const char *path) +{ +#if defined(CONF_PLATFORM_MACOS) + return open_link(path); +#else + char buf[512]; + str_format(buf, sizeof(buf), "file://%s", path); + return open_link(buf); #endif } diff --git a/src/base/system.h b/src/base/system.h index a23e0b7ca..275c0d218 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1807,18 +1807,33 @@ int net_socket_read_wait(NETSOCKET sock, int time); /* Function: open_link Opens a link in the browser. - + Parameters: link - The link to open in a browser. - + Returns: Returns 1 on success, 0 on failure. - + Remarks: - This may not be called with untrusted input or it'll result in arbitrary code execution. + This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows. */ int open_link(const char *link); +/* + Function: open_file + Opens a file or directory with default program. + + Parameters: + path - The path to open. + + Returns: + Returns 1 on success, 0 on failure. + + Remarks: + This may not be called with untrusted input or it'll result in arbitrary code execution, especially on Windows. +*/ +int open_file(const char *path); + void swap_endian(void *data, unsigned elem_size, unsigned num); typedef void (*DBG_LOGGER)(const char *line, void *user); diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index 761cd4623..d5caa0aa9 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -1254,13 +1254,11 @@ void CMenus::RenderDemoList(CUIRect MainView) if(DoButton_Menu(&s_DirectoryButtonID, Localize("Demos directory"), 0, &DirectoryButton)) { char aBuf[IO_MAX_PATH_LENGTH]; - char aBufFull[IO_MAX_PATH_LENGTH + 7]; Storage()->GetCompletePath(IStorage::TYPE_SAVE, "demos", aBuf, sizeof(aBuf)); Storage()->CreateFolder("demos", IStorage::TYPE_SAVE); - str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf); - if(!open_link(aBufFull)) + if(!open_file(aBuf)) { - dbg_msg("menus", "couldn't open link"); + dbg_msg("menus", "couldn't open file"); } } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 46941b6a3..530422951 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -268,13 +268,11 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) if(DoButton_Menu(&s_ThemesButtonID, Localize("Themes directory"), 0, &DirectoryButton)) { char aBuf[IO_MAX_PATH_LENGTH]; - char aBufFull[IO_MAX_PATH_LENGTH + 7]; Storage()->GetCompletePath(IStorage::TYPE_SAVE, "themes", aBuf, sizeof(aBuf)); Storage()->CreateFolder("themes", IStorage::TYPE_SAVE); - str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf); - if(!open_link(aBufFull)) + if(!open_file(aBuf)) { - dbg_msg("menus", "couldn't open link"); + dbg_msg("menus", "couldn't open file"); } } @@ -733,13 +731,11 @@ void CMenus::RenderSettingsTee(CUIRect MainView) if(DoButton_Menu(&s_DirectoryButtonID, Localize("Skins directory"), 0, &DirectoryButton)) { char aBuf[IO_MAX_PATH_LENGTH]; - char aBufFull[IO_MAX_PATH_LENGTH + 7]; Storage()->GetCompletePath(IStorage::TYPE_SAVE, "skins", aBuf, sizeof(aBuf)); Storage()->CreateFolder("skins", IStorage::TYPE_SAVE); - str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf); - if(!open_link(aBufFull)) + if(!open_file(aBuf)) { - dbg_msg("menus", "couldn't open link"); + dbg_msg("menus", "couldn't open file"); } } diff --git a/src/game/client/components/menus_settings_assets.cpp b/src/game/client/components/menus_settings_assets.cpp index 81a56a7f6..09172004e 100644 --- a/src/game/client/components/menus_settings_assets.cpp +++ b/src/game/client/components/menus_settings_assets.cpp @@ -547,10 +547,9 @@ void CMenus::RenderSettingsCustom(CUIRect MainView) Storage()->GetCompletePath(IStorage::TYPE_SAVE, aBufFull, aBuf, sizeof(aBuf)); Storage()->CreateFolder("assets", IStorage::TYPE_SAVE); Storage()->CreateFolder(aBufFull, IStorage::TYPE_SAVE); - str_format(aBufFull, sizeof(aBufFull), "file://%s", aBuf); - if(!open_link(aBufFull)) + if(!open_file(aBuf)) { - dbg_msg("menus", "couldn't open link"); + dbg_msg("menus", "couldn't open file"); } } From 7484ffc125031a9400b10be9958769f2753d78bd Mon Sep 17 00:00:00 2001 From: def Date: Sun, 19 Dec 2021 01:23:29 +0100 Subject: [PATCH 2/2] Add buttons to open settings file and config directory Only tested on macOS --- src/game/client/components/menus_settings.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 530422951..b41bcd4db 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -258,6 +258,38 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) m_NeedRestartGeneral = s_ClShowConsole != g_Config.m_ClShowConsole; #endif + Left.HSplitTop(15.0f, 0, &Left); + CUIRect SettingsButton; + Left.HSplitBottom(25.0f, &Left, &SettingsButton); + + SettingsButton.HSplitTop(5.0f, 0, &SettingsButton); + static int s_SettingsButtonID = 0; + if(DoButton_Menu(&s_SettingsButtonID, Localize("Settings file"), 0, &SettingsButton)) + { + char aBuf[IO_MAX_PATH_LENGTH]; + Storage()->GetCompletePath(IStorage::TYPE_SAVE, "settings_ddnet.cfg", aBuf, sizeof(aBuf)); + if(!open_file(aBuf)) + { + dbg_msg("menus", "couldn't open file"); + } + } + + Left.HSplitTop(15.0f, 0, &Left); + CUIRect ConfigButton; + Left.HSplitBottom(25.0f, &Left, &ConfigButton); + + ConfigButton.HSplitTop(5.0f, 0, &ConfigButton); + static int s_ConfigButtonID = 0; + if(DoButton_Menu(&s_ConfigButtonID, Localize("Config directory"), 0, &ConfigButton)) + { + char aBuf[IO_MAX_PATH_LENGTH]; + Storage()->GetCompletePath(IStorage::TYPE_SAVE, "", aBuf, sizeof(aBuf)); + if(!open_file(aBuf)) + { + dbg_msg("menus", "couldn't open file"); + } + } + Left.HSplitTop(15.0f, 0, &Left); CUIRect DirectoryButton; Left.HSplitBottom(25.0f, &Left, &DirectoryButton);