diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs
index ec6b5ac6de..18c991297a 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,15 +153,34 @@ 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.
///
///
- /// 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) => 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)
{