using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Roadie.Library.Utility { /// /// Cleans paths of invalid characters. /// public static class PathSanitizer { /// /// The set of invalid filename characters, kept sorted for fast binary search /// private static readonly char[] invalidFilenameChars; /// /// The set of invalid path characters, kept sorted for fast binary search /// private static readonly char[] invalidPathChars; static PathSanitizer() { // set up the two arrays -- sorted once for speed. var c = new List(); c.AddRange(Path.GetInvalidFileNameChars()); // Some Roadie instances run in Linux to Windows SMB clients via Samba this helps with Windows clients and invalid characters in Windows var badWindowsFileAndFoldercharacters = new List { '\\', '"', '/', ':', '*', '$', '?', '\'', '<', '>', '|', '*' }; foreach (var badWindowsFilecharacter in badWindowsFileAndFoldercharacters) { if (!c.Contains(badWindowsFilecharacter)) { c.Add(badWindowsFilecharacter); } } invalidFilenameChars = c.ToArray(); var f = new List(); f.AddRange(Path.GetInvalidPathChars()); foreach (var badWindowsFilecharacter in badWindowsFileAndFoldercharacters) { if (!f.Contains(badWindowsFilecharacter)) { f.Add(badWindowsFilecharacter); } } invalidFilenameChars = c.ToArray(); invalidPathChars = f.ToArray(); Array.Sort(invalidFilenameChars); Array.Sort(invalidPathChars); } /// /// Cleans a filename of invalid characters /// /// the string to clean /// the character which replaces bad characters /// public static string SanitizeFilename(string input, char errorChar) { return Sanitize(input, invalidFilenameChars, errorChar); } /// /// Cleans a path of invalid characters /// /// the string to clean /// the character which replaces bad characters /// public static string SanitizePath(string input, char errorChar) { return Sanitize(input, invalidPathChars, errorChar); } /// /// Cleans a string of invalid characters. /// /// /// /// /// private static string Sanitize(string input, char[] invalidChars, char errorChar) { // null always sanitizes to null if (input == null) { return null; } var result = new StringBuilder(); foreach (var characterToTest in input) { // we binary search for the character in the invalid set. This should be lightning fast. if (Array.BinarySearch(invalidChars, characterToTest) >= 0) { // we found the character in the array of result.Append(errorChar); } else { // the character was not found in invalid, so it is valid. result.Append(characterToTest); } } // we're done. return result.ToString(); } } }