Add detection of Windows reserved filenames
Description
This PR adds functionality to detect Windows reserved filenames (like COM1, LPT1, etc.) in the WindowsNameTransform class. The implementation adds a new IsReservedName method that detects reserved names despite differences between different Windows versions.
Background
I encountered an issue on a Windows 10 based system today where an InvalidNameException was thrown:
ICSharpCode.SharpZipLib.Core.InvalidNameException: Parent traversal in paths is not allowed.
The only problem was that this was completely unrelated to parent traversal but was actually because the filename was C:\example\folder\con.xhtml, which in Windows 10 is considered a reserved word. The incorrect exception message about the parent directory traversal led us down the wrong path when diagnosing the file's issue, so I wanted to update SharpZipLib to handle this scenario better.
Additional Information
To make this slightly more complicated, Windows has changed how it handles reserved names across different OS versions:
- In older Windows versions:
- Path.GetFullPath("COM3") gives \.\COM3
- Path.GetFullPath("C:\COM3") gives \.\COM3
- Path.GetFullPath("COM3.txt") gives \.\COM3
- In newer Windows versions, this behavior can be inconsistent depending on context
- Path.GetFullPath("COM3") gives \.\COM3
- Path.GetFullPath("C:\COM3") gives C:\COM3
- Path.GetFullPath("COM3.txt") gives "COM3.txt
More information on this can be found on the dotnet/runtime issue and Microsoft's own Naming Conventions Guide.
Solution
The new IsReservedName method uses Path.GetFullPath() and checks if the result starts with \\.\ or \\?\, which identifies Windows reserved names. When detected, the code throws an InvalidNameException with an appropriate message pointing to Microsoft's documentation.
Changes
- Added new
IsReservedNamemethod with detailed documentation - Updated
MakeValidNameto check for reserved names - Added xml documentation and comments
- Added a test to
WindowsNameTransformHandling.csto check theInvalidNameExceptionis being thrown as expected
I certify that I own, and have sufficient rights to contribute, all source code and related material intended to be compiled or integrated with the source code for the SharpZipLib open source product (the "Contribution"). My Contribution is licensed under the MIT License.