From 60141cf8e54a97d55b62ffac71d9a56d1f36656c Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Mon, 21 Sep 2026 21:52:44 +0300
Subject: [PATCH 34/34] Allow hack access users to load savegame with plain
 name

The restriction that even hack access users cannot /load
savegames with plain name was inconsistent with the fact
that they don't have restrictions in loading savegames
with full path. Ability to load files by their full name
made it possible to load the same file, that plain name
restriction tried to prevent one from loading, anyway.

Reported by Dean Brown

See RM #2269

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 server/srv_main.c  |  2 +-
 server/stdinhand.c | 13 ++++++-------
 server/stdinhand.h |  2 +-
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/server/srv_main.c b/server/srv_main.c
index ccea7af97a..db726a4210 100644
--- a/server/srv_main.c
+++ b/server/srv_main.c
@@ -3185,7 +3185,7 @@ static void srv_prepare(void)
 
   /* Try to load a saved game */
   if ('\0' == srvarg.load_filename[0]
-      || !load_command(NULL, srvarg.load_filename, FALSE, TRUE)) {
+      || !load_command(NULL, srvarg.load_filename, FALSE)) {
     /* Savegame not loaded */
     sz_strlcpy(game.server.orig_game_version, freeciv_datafile_version());
 
diff --git a/server/stdinhand.c b/server/stdinhand.c
index e598a28be0..6b34f638af 100644
--- a/server/stdinhand.c
+++ b/server/stdinhand.c
@@ -3783,8 +3783,7 @@ static bool detach_command(struct connection *caller, char *str, bool check)
     legitimate but has inconsistencies) and would lead to a broken server
     afterwards.
 **************************************************************************/
-bool load_command(struct connection *caller, const char *filename, bool check,
-                  bool cmdline_load)
+bool load_command(struct connection *caller, const char *filename, bool check)
 {
   struct timer *loadtimer, *uloadtimer;
   struct section_file *file;
@@ -3820,9 +3819,9 @@ bool load_command(struct connection *caller, const char *filename, bool check,
     const char **ext, *found = NULL;
     const struct strvec **path;
 
-    if (cmdline_load) {
-      /* Allow plain names being loaded with '--file' option, but not otherwise
-       * (no loading of arbitrary files by unauthorized users)
+    if (!is_restricted(caller)) {
+      /* Allow plain names being loaded with '--file' option or hack access,
+       * but not otherwise (no loading of arbitrary files by unauthorized users)
        * Iterate through ALL paths to check for file with plain name before
        * looking any path with an extension, i.e., prefer plain name file
        * in later directory over file with extension in name in earlier
@@ -3966,7 +3965,7 @@ bool load_command(struct connection *caller, const char *filename, bool check,
 
   Security: There are some rudimentary checks in load_rulesets() to see
   if this directory really is a viable ruleset directory. For public
-  servers, we check against directory redirection (is_safe_filename) and
+  servers, we check against directory redirection (is_safe_filename() ) and
   other bad stuff in the directory name, and will only use directories
   inside the data directories.
 **************************************************************************/
@@ -4631,7 +4630,7 @@ static bool handle_stdin_input_real(struct connection *caller, char *str,
   case CMD_SCENSAVE:
     return scensave_command(caller, arg, check);
   case CMD_LOAD:
-    return load_command(caller, arg, check, FALSE);
+    return load_command(caller, arg, check);
   case CMD_METAPATCHES:
     return metapatches_command(caller, arg, check);
   case CMD_METAMESSAGE:
diff --git a/server/stdinhand.h b/server/stdinhand.h
index de0fba60b1..510783161e 100644
--- a/server/stdinhand.h
+++ b/server/stdinhand.h
@@ -52,7 +52,7 @@ enum rfc_status create_command_pregame(const char *name,
                                        char *buf, size_t buflen);
 
 bool load_command(struct connection *caller,
-                  const char *filename, bool check, bool cmdline_load);
+                  const char *filename, bool check);
 bool start_command(struct connection *caller, bool check, bool notify);
 
 void toggle_ai_player_direct(struct connection *caller,
-- 
2.53.0

