summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-07-10 17:11:07 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-07-11 20:50:41 +0200
commite09248620ad430fbbd907dab5e54fe96fd69baa9 (patch)
treebaf1508e7bfa076069311177bd06260d74bfc029
parent6b89b661df1a2682edfa491e1bb9a21c4ab0943c (diff)
downloadmana-master.tar.gz
mana-master.tar.bz2
mana-master.tar.xz
mana-master.zip
Make the screenshot file name a clickable linkHEADmaster
Some security checks are done because players might also write "screenshot:" in the chat to create file:// URLs and `SDL_OpenURL` can be used to open many things. So we disallow ".." and require a ".png" extension.
-rw-r--r--NEWS1
-rw-r--r--src/game.cpp10
-rw-r--r--src/gui/widgets/itemlinkhandler.cpp19
-rw-r--r--src/utils/stringutils.h13
4 files changed, 40 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 13bcbd17..64bd4374 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,7 @@
- Enabled whispers in tabs by default
- Made pickup notifications to appear as particle instead of text by default
- Made names update immediately when changing "Show gender" option
+- Made the screenshot file name a clickable link
- Made client config statically typed and save as more structured XML
- Custom mouse cursor is now rendered by the system
- Limit shop's Max button to available carry weight
diff --git a/src/game.cpp b/src/game.cpp
index b91df9db..86a943d8 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -325,8 +325,16 @@ static bool saveScreenshot()
if (success)
{
+ std::string screenshotLink;
+#if SDL_VERSION_ATLEAST(2, 0, 14)
+ screenshotLink = strprintf("@@screenshot:%s|%s@@",
+ filenameSuffix.str().c_str(),
+ filenameSuffix.str().c_str());
+#else
+ screenshotLink = filenameSuffix.str();
+#endif
serverNotice(strprintf(_("Screenshot saved as %s"),
- filenameSuffix.str().c_str()));
+ screenshotLink.c_str()));
}
else
{
diff --git a/src/gui/widgets/itemlinkhandler.cpp b/src/gui/widgets/itemlinkhandler.cpp
index 81a332ad..d9d6f506 100644
--- a/src/gui/widgets/itemlinkhandler.cpp
+++ b/src/gui/widgets/itemlinkhandler.cpp
@@ -33,6 +33,7 @@
#include "gui/widgets/itemlinkhandler.h"
+#include "client.h"
#include "resources/iteminfo.h"
#include "resources/itemdb.h"
#include "utils/gettext.h"
@@ -56,6 +57,24 @@ static bool isUrl(const std::string &link)
void ItemLinkHandler::handleLink(const std::string &link)
{
+#if SDL_VERSION_ATLEAST(2, 0, 14)
+ // Handle screenshots by constructing full file path
+ if (startsWith(link, "screenshot:"))
+ {
+ std::string filename = link.substr(11); // Remove "screenshot:" prefix
+
+ // Prevent directory traversal attacks or opening malicious files
+ if (filename.find("..") == std::string::npos && endsWith(filename, ".png"))
+ {
+ std::string fileUrl = "file://" + Client::getScreenshotDirectory() + "/" + filename;
+ if (SDL_OpenURL(fileUrl.c_str()) == -1)
+ new OkDialog(_("Open URL Failed"), SDL_GetError(), true, mParent);
+ }
+
+ return;
+ }
+#endif
+
if (isUrl(link))
{
mLink = link;
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
index 8dd4454a..885ddcb8 100644
--- a/src/utils/stringutils.h
+++ b/src/utils/stringutils.h
@@ -117,9 +117,18 @@ std::string &removeColors(std::string &msg);
/**
* Returns whether a string starts with a given prefix.
*/
-inline bool startsWith(const std::string &str, const char *prefix)
+inline bool startsWith(std::string_view str, std::string_view prefix)
{
- return str.rfind(prefix, 0) == 0;
+ return str.substr(0, prefix.size()) == prefix;
+}
+
+/**
+ * Returns whether a string ends with a given suffix.
+ */
+inline bool endsWith(std::string_view str, std::string_view suffix)
+{
+ return str.size() >= suffix.size() &&
+ str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
/**