XmlUrlResolver.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // System.Xml.XmlUrlResolver.cs
  2. //
  3. // Author: Duncan Mak ([email protected])
  4. // Atsushi Enomoto ([email protected])
  5. //
  6. // (C) Ximian, Inc.
  7. //
  8. using System.Net;
  9. using System.IO;
  10. using System.Text;
  11. using Mono.Xml.Native;
  12. namespace System.Xml
  13. {
  14. public class XmlUrlResolver : XmlResolver
  15. {
  16. // Field
  17. ICredentials credential;
  18. WebClient webClientInternal;
  19. WebClient webClient {
  20. get {
  21. if (webClientInternal == null)
  22. webClientInternal = new WebClient ();
  23. return webClientInternal;
  24. }
  25. }
  26. // Constructor
  27. public XmlUrlResolver ()
  28. : base ()
  29. {
  30. }
  31. // Properties
  32. public override ICredentials Credentials
  33. {
  34. set { credential = value; }
  35. }
  36. // Methods
  37. public override object GetEntity (Uri absoluteUri, string role, Type ofObjectToReturn)
  38. {
  39. if (ofObjectToReturn == null)
  40. ofObjectToReturn = typeof (Stream);
  41. if (ofObjectToReturn != typeof (Stream))
  42. throw new XmlException ("This object type is not supported.");
  43. if (absoluteUri.Scheme == "file") {
  44. if (absoluteUri.AbsolutePath == String.Empty)
  45. throw new ArgumentException ("uri must be absolute.", "absoluteUri");
  46. return new FileStream (UnescapeRelativeUriBody (absoluteUri.LocalPath), FileMode.Open, FileAccess.Read, FileShare.Read);
  47. }
  48. // (MS documentation says) parameter role isn't used yet.
  49. Stream s = null;
  50. using (s) {
  51. WebClient wc = new WebClient ();
  52. wc.Credentials = credential;
  53. s = wc.OpenRead (absoluteUri.ToString ());
  54. // Returned stream does not keep connection, so
  55. // it should read up all the stream content.
  56. MemoryStream ms = new MemoryStream ();
  57. byte [] data = new byte [10000];
  58. int length = 0;
  59. do {
  60. length = s.Read (data, 0, 10000);
  61. if (length > 0)
  62. ms.Write (data, 0, length);
  63. } while (length == 10000);
  64. s.Close ();
  65. ms.Close ();
  66. return new MemoryStream (ms.GetBuffer (), 0, (int) ms.Length);
  67. }
  68. }
  69. public override Uri ResolveUri (Uri baseUri, string relativeUri)
  70. {
  71. if (baseUri == null) {
  72. if (relativeUri == null)
  73. throw new NullReferenceException ("Either baseUri or relativeUri are required.");
  74. // Don't ignore such case that relativeUri is in fact absolute uri (e.g. ResolveUri (null, "http://foo.com")).
  75. if (relativeUri.StartsWith ("http:") ||
  76. relativeUri.StartsWith ("https:") ||
  77. relativeUri.StartsWith ("file:"))
  78. return new Uri (relativeUri);
  79. else
  80. // extraneous "/a" is required because current Uri stuff
  81. // seems ignorant of difference between "." and "./".
  82. // I'd be appleciate if it is fixed with better solution.
  83. return new Uri (Path.GetFullPath (relativeUri));
  84. // return new Uri (new Uri (Path.GetFullPath ("./a")), EscapeRelativeUriBody (relativeUri));
  85. }
  86. if (relativeUri == null)
  87. return baseUri;
  88. return new Uri (baseUri, EscapeRelativeUriBody (relativeUri));
  89. }
  90. private string EscapeRelativeUriBody (string src)
  91. {
  92. return src.Replace ("<", "%3C")
  93. .Replace (">", "%3E")
  94. .Replace ("#", "%23")
  95. .Replace ("%", "%25")
  96. .Replace ("\"", "%22");
  97. }
  98. private string UnescapeRelativeUriBody (string src)
  99. {
  100. return src.Replace ("%3C", "<")
  101. .Replace ("%3E", ">")
  102. .Replace ("%23", "#")
  103. .Replace ("%25", "%")
  104. .Replace ("%22", "\"");
  105. }
  106. }
  107. }