2

https://msdn.microsoft.com/en-us/library/system.uri(v=vs.110).aspx

According to the reference above, when specifying an ftp url, the uri class should not compact the url. For example, the following ftp url:

Uri uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E");
Console.WriteLine(uri.AbsoluteUri);
Console.WriteLine(uri.PathAndQuery);

should result in:

AbsoluteUri: "ftp://myUrl/%2E%2E/%2E%2E"

PathAndQuery: "/%2E%2E/%2E%2E"

But, this is NOT what I'm seeing. When I execute the above code using .NET framework 4.5.1, I see:

AbsoluteUri: "ftp://myUrl/"

PathAndQuery: "/"

Moreover, adding to my app.config seems to have no effect:

<uri> 
    <schemeSettings>
        <add name="ftp" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
    </schemeSettings>
</uri>

Since several people have been able to recreate the issue, I've created a bug report with Microsoft. Feel free to upvote:

https://connect.microsoft.com/VisualStudio/feedback/details/2046491/uri-canonicalization-compacting-ftp-scheme

Michael
  • 434
  • 1
  • 5
  • 12
  • Side note: it is generally better to use lower level APIs when you trying to hack something - higher level APIs usually have more validation than you'd need. ("ftp://host/../.." is really questionable Url for valid resource locations) – Alexei Levenkov Nov 23 '15 at 18:05
  • This doesn't seem helpful... – Michael Nov 23 '15 at 18:08
  • I see them uncompacted. Are you using Mono? – Robert McKee Nov 23 '15 at 18:26
  • No, using standard .NET Framework 4.5.1. So, you are seeing the expected AbsoluteUri?: "ftp://myUrl/%2E%2E/%2E%2E" – Michael Nov 23 '15 at 18:35
  • It reproduces for me (on dot net 4.6), seeing same results as the OP. My uneducated guess is that the docs are out of date. – tzachs Nov 23 '15 at 22:12

1 Answers1

0

Created a bug report with Microsoft: https://connect.microsoft.com/VisualStudio/Feedback/Details/2046491

At present, I am working around this issue by (hacking via reflection) removing two flags from the UriParser object within the Uri class:

I call the method below once when my application is instantiating. After instantiation, every FTP Uri object will utilize the new flag combination when parsing.

// CompressPath = 0x800000, // For an authority based Uri remove/compress /./ /../ in the path
// UnEscapeDotsAndSlashes = 0x2000000, // additionally unescape dots and slashes before doing path compression

/// <summary>
/// http://referencesource.microsoft.com/#System/net/System/_UriSyntax.cs
/// </summary>
public static void LeaveDotsAndSlashesEscaped() {
    Uri uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E/");
    if (uri == null) {
        throw new ArgumentNullException("uri");
    }
    FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fieldInfo == null) {
        throw new MissingFieldException("'m_Syntax' field not found");
    }
    object uriParser = fieldInfo.GetValue(uri);
    fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fieldInfo == null) {
        throw new MissingFieldException("'m_Flags' field not found");
    }
    object uriSyntaxFlags = fieldInfo.GetValue(uriParser);
    // Clear the flags that we don't want
    uriSyntaxFlags = (int)uriSyntaxFlags & ~0x2000000 & ~0x800000;
    fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}
Michael
  • 434
  • 1
  • 5
  • 12