Getting a Uri with escaped slashes on mono

六月ゝ 毕业季﹏ 提交于 2019-12-19 10:22:07

问题


Update: A fix has now made it's way into mono. This is good news!

Updated: Added logic to fix fragment handling.

I am trying to send a request with an encoded slash on Mono using the Uri class. This is basically the Mono equivalent of this question: GETting a URL with an url-encoded slash

The issue is that Mono similar to .NET will unescape any slashes it finds in the Uri when it is constructed. This logic was originally put in in place in order to remove vulnerabilities that could occur if paths were escape encoded and not detected.

In the previous post there is a hack which shows setting flags on the underlying Uri class via reflection which force the escaped slashes to be left alone. This behavior has been fixed in .NET 4.5 and by default the escaped slashes are allowed (as I mentioned in the comments).

I tried to do the same on Mono, but it fails as the internals of the Uri class are different. I came up with this approach to achieve what I want, which works but it is TERRIBLY hacky.

class Program { static void Main(string[] args) { var uri = new Uri("http://www.yahoo.com/%2F?Foo=Bar%2F#frag"); UriHelper.ForceCanonicalPathAndQuery(uri); Console.WriteLine ("uri.ToString() - " + uri.ToString ()); Console.WriteLine ("uri.AbsoluteUri - " + uri.AbsoluteUri); Console.WriteLine ("uri.Host - " + uri.Host); Console.WriteLine ("uri.Query - " + uri.Query); Console.WriteLine ("uri.PathAndQuery - " + uri.PathAndQuery); Console.WriteLine ("uri.AbsolutePath - " + uri.AbsolutePath); Console.WriteLine ("uri.Fragment - " + uri.Fragment); }

public class UriHelper {
  private static Type uriType = typeof(Uri);
  private static FieldInfo sourceField;
  private static FieldInfo queryField;
  private static FieldInfo pathField;
  private static FieldInfo cachedToStringField;
  private static FieldInfo cachedAbsoluteUriField;

  static UriHelper ()
  {
    sourceField = uriType.GetField ("source", BindingFlags.NonPublic | BindingFlags.Instance);
    queryField = uriType.GetField ("query", BindingFlags.NonPublic | BindingFlags.Instance);
    pathField = uriType.GetField ("path", BindingFlags.NonPublic | BindingFlags.Instance);
    cachedToStringField = uriType.GetField ("cachedToString", BindingFlags.NonPublic | BindingFlags.Instance);
    cachedAbsoluteUriField = uriType.GetField ("cachedAbsoluteUri", BindingFlags.NonPublic | BindingFlags.Instance);
  }

  public static void ForceCanonicalPathAndQuery(Uri uri)
  {
    var source = (string) sourceField.GetValue (uri);
    cachedToStringField.SetValue (uri, source);
    cachedAbsoluteUriField.SetValue (uri, source);
    var fragPos = source.IndexOf ("#");
    var queryPos = source.IndexOf ("?");
    var start = source.IndexOf (uri.Host) + uri.Host.Length;
    var pathEnd = queryPos == -1 ? fragPos : queryPos;
    if (pathEnd == -1)
      pathEnd = source.Length+1;
    var path = queryPos > -1 ? source.Substring (start, pathEnd - start) : source.Substring (start);
    pathField.SetValue (uri, path);
    queryField.SetValue(uri, fragPos > -1 ? source.Substring(queryPos, fragPos - queryPos) : source.Substring(queryPos));
  }
}

}

When you run this, it outputs the following:

uri.ToString() - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.AbsoluteUri - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.Host - www.yahoo.com
uri.Query - ?Foo=Bar%2F
uri.PathAndQuery - /%2F?Foo=Bar%2F
uri.AbsolutePath - /%2F
uri.Fragment - #frag

I don't at all feel good about it, but it does work, at least for the basic scenario of taking a Uri and issuing a query.

I might be missing something in the Uri class, so if you have a better / less hacky way to do what I am doing here, I'd really appreciate it.


回答1:


From the original question, it looks like the behaviour of MS.NET changed in .NET 4.5 to fix the bug.

Indeed, then, it is a bug in mono for not following the behaviour change in the .NET 4.5 profile. And it seems someone already fixed the bug and proposed a pull request, the problem is that nobody in the Mono team seems to have found the time to review it: https://github.com/mono/mono/pull/619



来源:https://stackoverflow.com/questions/20769150/getting-a-uri-with-escaped-slashes-on-mono

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!