Fix character replacement for non-windows platforms.

This commit is contained in:
Michael Bucari-Tovo 2022-12-13 16:33:37 -07:00
parent f2ea02ae0b
commit 2b16e86c7b
3 changed files with 101 additions and 61 deletions

View File

@ -61,7 +61,13 @@ namespace FileManager
[JsonConverter(typeof(ReplacementCharactersConverter))]
public class ReplacementCharacters
{
public static readonly ReplacementCharacters Default = new()
static ReplacementCharacters()
{
}
public static readonly ReplacementCharacters Default
= IsWindows
? new()
{
Replacements = new List<Replacement>()
{
@ -78,9 +84,23 @@ namespace FileManager
Replacement.QuestionMark(""),
Replacement.Pipe("⏐"),
}
}
: new()
{
Replacements = new List<Replacement>()
{
Replacement.OtherInvalid("_"),
Replacement.FilenameForwardSlash(""),
Replacement.FilenameBackSlash(""),
Replacement.OpenQuote("“"),
Replacement.CloseQuote("”"),
Replacement.OtherQuote("")
}
};
public static readonly ReplacementCharacters LoFiDefault = new()
public static readonly ReplacementCharacters LoFiDefault
= IsWindows
? new()
{
Replacements = new List<Replacement>()
{
@ -94,9 +114,12 @@ namespace FileManager
Replacement.CloseAngleBracket("}"),
Replacement.Colon("-"),
}
};
}
: Barebones;
public static readonly ReplacementCharacters Barebones = new()
public static readonly ReplacementCharacters Barebones
= IsWindows
? new ()
{
Replacements = new List<Replacement>()
{
@ -105,15 +128,30 @@ namespace FileManager
Replacement.FilenameBackSlash("_"),
Replacement.OpenQuote("_"),
Replacement.CloseQuote("_"),
Replacement.OtherQuote("_"),
Replacement.OtherQuote("_")
}
}
: new ()
{
Replacements = new List<Replacement>()
{
Replacement.OtherInvalid("_"),
Replacement.FilenameForwardSlash("_"),
Replacement.FilenameBackSlash("\\"),
Replacement.OpenQuote("\""),
Replacement.CloseQuote("\""),
Replacement.OtherQuote("\"")
}
};
private static readonly char[] invalidChars = Path.GetInvalidPathChars().Union(new[] {
'*', '?', ':',
// these are weird. If you run Path.GetInvalidPathChars() in Visual Studio's "C# Interactive", then these characters are included.
// In live code, Path.GetInvalidPathChars() does not include them
'"', '<', '>'
private static bool IsWindows => Environment.OSVersion.Platform is PlatformID.Win32NT;
private static readonly char[] invalidPathChars = Path.GetInvalidFileNameChars().Except(new[] {
'\\', '/'
}).ToArray();
private static readonly char[] invalidSlashes = Path.GetInvalidFileNameChars().Intersect(new[] {
'\\', '/'
}).ToArray();
public IReadOnlyList<Replacement> Replacements { get; init; }
@ -125,11 +163,14 @@ namespace FileManager
private string OtherQuote => Replacements[5].ReplacementString;
private string GetFilenameCharReplacement(char toReplace, char preceding, char succeding)
{
if (invalidSlashes.Contains(toReplace))
{
if (toReplace == ForwardSlash.CharacterToReplace)
return ForwardSlash.ReplacementString;
else if (toReplace == BackSlash.CharacterToReplace)
else
return BackSlash.ReplacementString;
}
else return GetPathCharReplacement(toReplace, preceding, succeding);
}
private string GetPathCharReplacement(char toReplace, char preceding, char succeding)
@ -158,6 +199,7 @@ namespace FileManager
return OtherQuote;
}
//Replace any other non-mandatory characters
for (int i = Replacement.FIXED_COUNT; i < Replacements.Count; i++)
{
var r = Replacements[i];
@ -167,11 +209,10 @@ namespace FileManager
return DefaultReplacement;
}
public static bool ContainsInvalidPathChar(string path)
=> path.Any(c => invalidChars?.Contains(c) == true);
=> path.Any(c => invalidPathChars.Contains(c));
public static bool ContainsInvalidFilenameChar(string path)
=> path.Any(c => invalidChars?.Concat(new char[] { '\\', '/' })?.Contains(c) == true);
=> ContainsInvalidPathChar(path) || path.Any(c => invalidSlashes.Contains(c));
public string ReplaceInvalidFilenameChars(string fileName)
{
@ -181,7 +222,7 @@ namespace FileManager
{
var c = fileName[i];
if (invalidChars.Contains(c) || c == ForwardSlash.CharacterToReplace || c == BackSlash.CharacterToReplace)
if (invalidPathChars.Contains(c) || invalidSlashes.Contains(c))
{
char preceding = i > 0 ? fileName[i - 1] : default;
char succeeding = i < fileName.Length - 1 ? fileName[i + 1] : default;
@ -204,7 +245,7 @@ namespace FileManager
{
var c = pathStr[i];
if (!invalidChars.Contains(c) || (c == ':' && i == 1 && Path.IsPathRooted(pathStr)))
if (!invalidPathChars.Contains(c) || (c == ':' && i == 1 && Path.IsPathRooted(pathStr)))
builder.Append(c);
else
{
@ -212,7 +253,6 @@ namespace FileManager
char succeeding = i < pathStr.Length - 1 ? pathStr[i + 1] : default;
builder.Append(GetPathCharReplacement(c, preceding, succeeding));
}
}
return builder.ToString();
}
@ -248,7 +288,7 @@ namespace FileManager
dict[3].CharacterToReplace != default3.CharacterToReplace || dict[3].Description != default3.Description ||
dict[4].CharacterToReplace != default4.CharacterToReplace || dict[4].Description != default4.Description ||
dict[5].CharacterToReplace != default5.CharacterToReplace || dict[5].Description != default5.Description ||
dict.Any(r => ReplacementCharacters.ContainsInvalidPathChar(r.ReplacementString))
dict.Any(r => ReplacementCharacters.ContainsInvalidFilenameChar(r.ReplacementString))
)
{
dict = ReplacementCharacters.Default.Replacements;

View File

@ -143,7 +143,7 @@ namespace LibationAvalonia.Dialogs
get => _replacementText;
set
{
if (ReplacementCharacters.ContainsInvalidPathChar(value))
if (ReplacementCharacters.ContainsInvalidFilenameChar(value))
this.RaisePropertyChanged(nameof(ReplacementText));
else
this.RaiseAndSetIfChanged(ref _replacementText, value);
@ -158,7 +158,7 @@ namespace LibationAvalonia.Dialogs
set
{
if (value?.Length != 1 || !ReplacementCharacters.ContainsInvalidPathChar(value))
if (value?.Length != 1 || !ReplacementCharacters.ContainsInvalidFilenameChar(value))
this.RaisePropertyChanged(nameof(CharacterToReplace));
else
{

View File

@ -101,7 +101,7 @@ namespace LibationWinForms.Dialogs
{
dataGridView1.Rows[e.RowIndex].ErrorText = $"The {charToReplaceStr[0]} character is already being replaced";
}
else if (ReplacementCharacters.ContainsInvalidPathChar(replacement))
else if (ReplacementCharacters.ContainsInvalidFilenameChar(replacement))
{
dataGridView1.Rows[e.RowIndex].ErrorText = $"Your {replacementStringCol.HeaderText} contains illegal characters";
}