在单声道上获得带有逃逸斜线的Uri

时间:2013-12-25 04:50:24

标签: c# mono uri webrequest

更新:修复现在已进入mono。这是个好消息!

更新:添加了修复片段处理的逻辑。

我正在尝试使用Uri类在Mono上发送带有编码斜杠的请求。这基本上是此questionGETting a URL with an url-encoded slash

的Mono等价物

问题是类似于.NET的Mono会在构造Uri时发现它在Uri中找到的任何斜线。此逻辑最初是为了消除在路径被转义编码且未检测到时可能发生的漏洞而实施的。

在上一篇文章中有一个hack,它通过反射显示底层Uri类的设置标志,强制转义的斜杠单独留下。此行为已在.NET 4.5中得到修复,默认情况下允许使用转义斜杠(正如我在评论中提到的那样)。

我试图在Mono上做同样的事情,但它失败了,因为Uri类的内部是不同的。我想出了这种方法来实现我想要的东西,这种方法有效,但它很可怕。

课程计划   {     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));
  }
}

}

运行时,会输出以下内容:

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

我对此并不感到满意,但它确实有效,至少对于获取Uri和发出查询的基本情况而言。

我可能会在Uri课程中遗漏一些东西,所以如果你有更好/更少的hacky方式去做我在这里做的事情,我真的很感激。

1 个答案:

答案 0 :(得分:0)

从最初的问题看,MS.NET的行为在.NET 4.5中发生了变化,以修复错误。

的确,然而,由于不遵循.NET 4.5配置文件中的行为更改,因此它是单声道中的错误。似乎有人已经修复了这个错误并提出了一个拉取请求,问题是Mono团队中没有人似乎找到了审查它的时间:https://github.com/mono/mono/pull/619