alphaleonis / AlphaFS

AlphaFS is a .NET library providing more complete Win32 file system functionality to the .NET platform than the standard System.IO classes.
http://alphafs.alphaleonis.com/
MIT License
563 stars 99 forks source link

Path.GetFullPath: Allow novell style relative paths #302

Open HugoRoss opened 7 years ago

HugoRoss commented 7 years ago

Add support for Novell-style relative path, e.g. "...\foo\bar" (same as "..\..\foo\bar") or "....\foo\bar" (same as "..\..\..\foo\bar") etc.

This could be achieved with the following code:

//Path.GetFullPath.cs
private static string NormalizeNovellStylePath(string relativePath) {
    //Check arg
    Debug.Assert(relativePath != null, "The path is never null.");
    //Declare replacement string
    string myReplacement = null;
    //Replace as long as there is something to replace
    while ((relativePath.IndexOf("...") > -1)) {
        //Initialize replacement string
        if (myReplacement == null) myReplacement = GrandParentDirectoryPrefix;
        //Replace "..."
        relativePath = relativePath.Replace("...", myReplacement);
    }
    //Return result
    return relativePath;
}

//Path.Constants.cs
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
private static string _grandParentDirectoryPrefix;

private static string GrandParentDirectoryPrefix {
    get {
        var result = _grandParentDirectoryPrefix;
        if (result == null) {
            result = ParentDirectoryPrefix + DirectorySeparatorChar + ParentDirectoryPrefix;
            _grandParentDirectoryPrefix = result;
        }
        return result;
    }
}

Usage:

private static string GetFullPathTackleCore(KernelTransaction transaction, string path, GetFullPathOptions options) {
    //...
    path = NormalizeNovellStylePath(path);
    //...
}
damiarnold commented 7 years ago

I would recommend not implementing this for a number of reasons:

  1. This is tied to a proprietary implementation that used to be possible with Win9x and the NetWare file redirectors...it is no longer common nor builtin any more (see https://blogs.msdn.microsoft.com/oldnewthing/20160202-00/?p=92953). While this may be possible via direct NCP calls using a Novell/OES client (I'd need to run a test in my other lab), this is outside the realm of what the Windows experience via Explorer, cmd shell, etc. provide, and what my understanding of AlphaFS is focused on.

  2. This could create an inconsistent set of expectations for what users may believe to be possible. The use of multiple dots for ancestor traversal (beyond parent directory) either breaks, or may expose improperly handled traversal anomalies by other products. Personally, for the projects and products I'm using AlphaFS with, I wouldn't want this behavior as it could potentially lead to these very issues with our end users and clients in cases where paths are passed in.

  3. The name '...' (or any length > 2 and < 256) is actually a valid file entry name in NTFS! Using the long path specifier, you can actually create and read (via cmd console and direct API calls, at least) a valid file entry. Try the following from a cmd prompt:

copy con: \\?\C:\tmp\test\... This is a test ctl-z

here's a directory listing from my machine:

dir
Volume in drive C has no label.
Volume Serial Number is XXXX-XXXX

Directory of C:\tmp\test

01/30/2017 10:32 AM

.
01/30/2017 10:32 AM ..
01/30/2017 10:32 AM 16 ...
1 File(s) 16 bytes
2 Dir(s) 209,200,001,024 bytes free

And here is the output from typing the text:

type \\?\C:\tmp\test\... This is a test

  1. I'm sure there are other reasons as well (such as security concerns with multi-path traversal), but these are the ones off the top of my head.

Anyway, I would vote to keep AlphaFS behavior as a 'pure' Windows experience. If it were to be added, I would hope it would require an opt-in flag, and not be the default behavior.

Hope this makes sense! Thanks.

HugoRoss commented 7 years ago

(I updated the original comment as some backslashes haven't been visible and I had to double them...)

My statement to @damiarnold comments above:

Point 1) Yes, it's not standard behavior but simple and helpful.

Point 2) That's true, if that is a concern, there should be an option enabling/disabling Novell-style relative paths.

Point 3) The file name "..." does not seem valid, I can't issue a type command like in your example nor open it with notepad nor visual studio (on Win 8.1), although the file was written. Also I couldn't create a folder with that name. Same conclusion as with 2): An option enabling/disabling Novell-style relative paths solves that problem. By the way, it's also valid to have a file or folder that ends with a space or consists only of a space character and windows still trims them in normal (non "\\?\"-prefix) mode...

Point 4) There can't be any security issue, the traversal is done by windows resp. the according file system natively as usual. The only issue I see is that one could get a path that gets too long but that can be handled.

Me I prefer to provide a better than the 'pure' Windows experience!

damiarnold commented 7 years ago

Hey, thanks for the feedback! Not sure why you were unable to recreate the '...' file entry, as I have been able to do this repeatedly on different Windows servers and workstations. And, no, many of the "standard" tools will never be able to open it, but it remains that it is still a valid entry (as are entries with trailing spaces, various control characters, and any other character or pattern not restricted by the file system itself). Maybe you tried the example from my original post before I soon after fixed the backslash issues in mine as well? :-)

Anyway, I fully appreciate the need to enhance the experience (otherwise, why would we use AlphaFS in the first place?), but having worked with and developed products against mixed file system management for the past 20+ years including Windows, Novell/OES, and various Linux and Unix environments, it makes me somewhat uneasy when platform-specific core standards (such as well-defined path specifications) are made "generic" across the board for whatever the reason may be. I'll agree to disagree here :-)

My point on security still stands, in that depending on where this change is made, higher level code may not be checking for what was never expected to ever be a valid path specifier, and now it suddenly could start returning data instead of throwing an exception....that is a security concern.

Again, if this behavior is never enabled by default, I could probably live with it. Thanks for the dialog!

damiarnold commented 7 years ago

If this were to be an optional behavior for just the Path.GetFullPath() function, would it be ok if it were limited to the overload that includes GetFullPathOptions, and just extend the options enum?

This could work around the concerns I have with adjusting default behavior handling, and provide an option that is truly opt-in.

e.g.:

Path.GetFullPath(@"...\some\path\text.txt", GetFullPathOptions.UseMultiAncestorTraversalNotation) or something like that?

HugoRoss commented 7 years ago

Yes, that would be perfectly fine with me.