From 81aaddca349417057fabc34a827df8a657260d51 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Jun 2025 19:25:07 +0900 Subject: [PATCH 1/2] Change lazer's valid filename method to match stable On revisiting the issue at hand, this honestly seems like the best way forward. It also addresses my concerns that with the method we were using, filenames could end up being half underscores. The main reason for choosing to change the lazer end is that stable's difficulty update process is based on sending the beatmap's filename to the server. This means that if we use a proposed fix of checking online ID, it will still mean beatmaps cannot be updated on stable (for all users which have downloaded the beatmap) if a mapper updates once on lazer. Implementation inspired by: - https://referencesource.microsoft.com/#mscorlib/system/io/path.cs,1144ad3c4eff3f24 - https://github.com/peppy/osu-stable-reference/blob/996648fba06baf4e7d2e0b248959399444017895/osu!/GameplayElements/Beatmaps/Beatmap.cs#L1575-L1590 Closes #33060. --- osu.Game/Extensions/ModelExtensions.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs index ec6b5ac6de..2514c6029a 100644 --- a/osu.Game/Extensions/ModelExtensions.cs +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.IO; -using System.Text.RegularExpressions; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.IO; @@ -16,8 +15,6 @@ namespace osu.Game.Extensions { public static class ModelExtensions { - private static readonly Regex invalid_filename_chars = new Regex(@"(?!$)[^A-Za-z0-9_()[\]. \-]", RegexOptions.Compiled); - /// /// Get the relative path in osu! storage for this file. /// @@ -156,6 +153,14 @@ namespace osu.Game.Extensions return instance.OnlineID.Equals(other.OnlineID); } + // intentionally chosen to match stable. + // see https://referencesource.microsoft.com/#mscorlib/system/io/path.cs,88 + private static readonly char[] invalid_filename_chars = + { + '\"', '<', '>', '|', '\0', (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, + (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, ':', '*', '?', '\\', '/' + }; + /// /// Create a valid filename which should work across all platforms. /// @@ -164,7 +169,12 @@ namespace osu.Game.Extensions /// across all operating systems. We are using this in place of as /// that function does not have per-platform considerations (and is only made to work on windows). /// - public static string GetValidFilename(this string filename) => invalid_filename_chars.Replace(filename, "_"); + public static string GetValidFilename(this string filename) + { + foreach (char c in invalid_filename_chars) + filename = filename.Replace(c.ToString(), string.Empty); + return filename; + } public static bool RequiresSupporter(this BeatmapLeaderboardScope scope, bool filterMods) { From 257fec87958635f36f0370bd99e2498ab0d2736e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 9 Jun 2025 14:34:41 +0200 Subject: [PATCH 2/2] Correct xmldoc of `GetValidFilename()` and make it intentionally scary --- osu.Game/Extensions/ModelExtensions.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs index 2514c6029a..18c991297a 100644 --- a/osu.Game/Extensions/ModelExtensions.cs +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -165,9 +165,15 @@ namespace osu.Game.Extensions /// Create a valid filename which should work across all platforms. /// /// - /// This function replaces all characters not included in a very pessimistic list which should be compatible - /// across all operating systems. We are using this in place of as - /// that function does not have per-platform considerations (and is only made to work on windows). + /// + /// We are using this in place of + /// as that function works per-platform, and therefore returns a different set of characters on different OSes. + /// + /// + /// Note that the behaviour of this method is LOAD-BEARING for things such as interoperability of beatmap exports with stable, + /// especially with respect to beatmap submission. + /// DO NOT CHANGE THE SEMANTICS OF THIS METHOD unless you know well what you are doing. + /// /// public static string GetValidFilename(this string filename) {