From ba9d6bac067fd425a2d9fe5d026283a2f339381a Mon Sep 17 00:00:00 2001 From: chrg6 Date: Wed, 11 Nov 2026 00:20:22 -0500 Subject: [PATCH] Keep co-op's private settings out of the log and out of bug reports. This line logs every setting nx2navi.ini sets, and a bug report takes a copy of nx2navi.ini along: with co-op both would have carried a room's secret, the relay's address and the player's name to whoever reads the report, and the secret lets anyone into the room. One list (runtime/cfg_private.h: the room's secret, the offer number, the relay, the name, the key a maker removes, the menu's test hook) now serves the log's line, "Copy system info" and the report's copy of the file, in the game and in the launcher: such a key reads "(set, not shown)", every other byte of the file stays. Also: the last leftovers of the restorations that were left out with the puppets (their settings prefix and section), main.c's byte order mark as it was, and two comments that cited files this tree does not have. Checked: with a room, a relay and a name in nx2navi.ini the log's line shows all three as set and none of their values; the same text gives the same bytes through the game's scrub and the launcher's (a launcher test, and the C function built alone); the launcher tests, the co-op probe, the relay tests and the tab check pass. Co-Authored-By: Claude Fable 5.2 --- launcher/saves.py | 35 ++++++++++++++++- nx2navi.ini.example | 9 +---- runtime/cfg.c | 11 +++--- runtime/cfg_private.h | 71 ++++++++++++++++++++++++++++++++++ runtime/coop.h | 2 +- runtime/main.c | 2 +- runtime/save_share.c | 16 +++++++- runtime/sysinfo.c | 10 ++--- runtime/ui/menu_text_input.cpp | 4 +- tests/launcher_test.py | 18 +++++++++ 10 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 runtime/cfg_private.h diff --git a/launcher/saves.py b/launcher/saves.py index 2a720da0..5bf97074 100644 --- a/launcher/saves.py +++ b/launcher/saves.py @@ -393,6 +393,37 @@ def _fresh_file(folder, stem, suffix): NO_SAVE = 'the game has no save yet: play until it saves, then export' +# Settings whose values stay on the player's PC (runtime/cfg_private.h has the same list): a co-op room's secret and +# the offer number made for it, the relay's address, the player's name, the key a maker removes, the menu's test hook. +PRIVATE_SETTINGS = ('coop_room', 'coop_server', 'coop_name', 'coop_accept', 'coop_remove', 'menu_test_set') +PRIVATE_SHOWN = b'(set, not shown)' + + +def scrub_settings(data): + """The bytes of an nx2navi.ini for a bug report: every private setting that has a value reads + "key = (set, not shown)"; everything else, comments and line ends included, byte for byte (cfg_ini_scrub in + runtime/cfg_private.h does the same for the game's own export).""" + out = [] + for n, line in enumerate(data.split(b'\n')): + text = line[:-1] if line.endswith(b'\r') else line + start = 3 if n == 0 and text.startswith(b'\xef\xbb\xbf') else 0 + body = text[start:].lstrip(b' \t') + key, eq, value = body.partition(b'=') + if (eq and value.strip(b' \t') and body[:1] not in (b'#', b';', b'[') + and key.strip(b' \t').lower() in tuple(k.encode() for k in PRIVATE_SETTINGS)): + line = text[:text.index(b'=') + 1] + b' ' + PRIVATE_SHOWN + line[len(text):] + out.append(line) + return b'\n'.join(out) + + +def _add_report_file(z, f): + """One file of a bug report into the zip: nx2navi.ini without its private values, anything else as it is.""" + if f.name == 'nx2navi.ini': + z.writestr(REPORT_DIR + f.name, scrub_settings(f.read_bytes())) + else: + z.write(f, REPORT_DIR + f.name) + + def _export_log(game, dest, version, log): """The bug report of a game without a save (it stopped before its first one): NX2navi-log-_