|
1 | 1 | using System; |
2 | 2 | using System.IO; |
| 3 | +using System.Linq; |
3 | 4 | using System.Text; |
4 | 5 |
|
5 | 6 | namespace DiscordChatExporter.Core.Utils.Extensions; |
6 | 7 |
|
7 | 8 | public static class PathExtensions |
8 | 9 | { |
| 10 | + // Characters that are invalid on common filesystems. |
| 11 | + // This is a union of invalid characters from Windows (NTFS/FAT32), Linux (ext4/XFS), and macOS (HFS+/APFS). |
| 12 | + // We use this instead of Path.GetInvalidFileNameChars() because that only returns OS-specific characters, |
| 13 | + // not filesystem-specific characters. This means that it's possible to use, for example, an NTFS drive on |
| 14 | + // Linux, which would allow the OS to create filenames with '?' but result in errors when writing to the filesystem. |
| 15 | + // https://github.com/Tyrrrz/DiscordChatExporter/issues/1452 |
| 16 | + private static readonly char[] InvalidFileNameChars = |
| 17 | + [ |
| 18 | + '\0', // Null character - invalid on all filesystems |
| 19 | + '/', // Path separator on Unix |
| 20 | + '\\', // Path separator on Windows |
| 21 | + ':', // Reserved on Windows (drive letters, NTFS streams) |
| 22 | + '*', // Wildcard on Windows |
| 23 | + '?', // Wildcard on Windows |
| 24 | + '"', // Reserved on Windows |
| 25 | + '<', // Redirection on Windows |
| 26 | + '>', // Redirection on Windows |
| 27 | + '|', // Pipe on Windows |
| 28 | + ]; |
| 29 | + |
9 | 30 | extension(Path) |
10 | 31 | { |
11 | 32 | public static string EscapeFileName(string path) |
12 | 33 | { |
13 | 34 | var buffer = new StringBuilder(path.Length); |
14 | 35 |
|
15 | 36 | foreach (var c in path) |
16 | | - buffer.Append(!Path.GetInvalidFileNameChars().Contains(c) ? c : '_'); |
| 37 | + buffer.Append(!InvalidFileNameChars.Contains(c) ? c : '_'); |
17 | 38 |
|
18 | 39 | // File names cannot end with a dot on Windows |
19 | 40 | // https://github.com/Tyrrrz/DiscordChatExporter/issues/977 |
|
0 commit comments