HttpListenerPrefix.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #region License
  2. /*
  3. * HttpListenerPrefix.cs
  4. *
  5. * This code is derived from ListenerPrefix.cs (System.Net) of Mono
  6. * (http://www.mono-project.com).
  7. *
  8. * The MIT License
  9. *
  10. * Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
  11. * Copyright (c) 2012-2020 sta.blockhead
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining a copy
  14. * of this software and associated documentation files (the "Software"), to deal
  15. * in the Software without restriction, including without limitation the rights
  16. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. * copies of the Software, and to permit persons to whom the Software is
  18. * furnished to do so, subject to the following conditions:
  19. *
  20. * The above copyright notice and this permission notice shall be included in
  21. * all copies or substantial portions of the Software.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  29. * THE SOFTWARE.
  30. */
  31. #endregion
  32. #region Authors
  33. /*
  34. * Authors:
  35. * - Gonzalo Paniagua Javier <gonzalo@novell.com>
  36. * - Oleg Mihailik <mihailik@gmail.com>
  37. */
  38. #endregion
  39. using System;
  40. namespace WebSocketSharp.Net
  41. {
  42. internal sealed class HttpListenerPrefix
  43. {
  44. #region Private Fields
  45. private string _host;
  46. private HttpListener _listener;
  47. private string _original;
  48. private string _path;
  49. private string _port;
  50. private string _prefix;
  51. private bool _secure;
  52. #endregion
  53. #region Internal Constructors
  54. /// <summary>
  55. /// Initializes a new instance of the <see cref="HttpListenerPrefix"/> class
  56. /// with the specified URI prefix and HTTP listener.
  57. /// </summary>
  58. /// <remarks>
  59. /// This constructor must be called after calling the CheckPrefix method.
  60. /// </remarks>
  61. /// <param name="uriPrefix">
  62. /// A <see cref="string"/> that specifies the URI prefix.
  63. /// </param>
  64. /// <param name="listener">
  65. /// A <see cref="HttpListener"/> that specifies the HTTP listener.
  66. /// </param>
  67. internal HttpListenerPrefix (string uriPrefix, HttpListener listener)
  68. {
  69. _original = uriPrefix;
  70. _listener = listener;
  71. parse (uriPrefix);
  72. }
  73. #endregion
  74. #region Public Properties
  75. public string Host {
  76. get {
  77. return _host;
  78. }
  79. }
  80. public bool IsSecure {
  81. get {
  82. return _secure;
  83. }
  84. }
  85. public HttpListener Listener {
  86. get {
  87. return _listener;
  88. }
  89. }
  90. public string Original {
  91. get {
  92. return _original;
  93. }
  94. }
  95. public string Path {
  96. get {
  97. return _path;
  98. }
  99. }
  100. public string Port {
  101. get {
  102. return _port;
  103. }
  104. }
  105. #endregion
  106. #region Private Methods
  107. private void parse (string uriPrefix)
  108. {
  109. if (uriPrefix.StartsWith ("https"))
  110. _secure = true;
  111. var len = uriPrefix.Length;
  112. var host = uriPrefix.IndexOf (':') + 3;
  113. var root = uriPrefix.IndexOf ('/', host + 1, len - host - 1);
  114. var colon = uriPrefix.LastIndexOf (':', root - 1, root - host - 1);
  115. if (uriPrefix[root - 1] != ']' && colon > host) {
  116. _host = uriPrefix.Substring (host, colon - host);
  117. _port = uriPrefix.Substring (colon + 1, root - colon - 1);
  118. }
  119. else {
  120. _host = uriPrefix.Substring (host, root - host);
  121. _port = _secure ? "443" : "80";
  122. }
  123. _path = uriPrefix.Substring (root);
  124. _prefix = String.Format (
  125. "{0}://{1}:{2}{3}",
  126. _secure ? "https" : "http",
  127. _host,
  128. _port,
  129. _path
  130. );
  131. }
  132. #endregion
  133. #region Public Methods
  134. public static void CheckPrefix (string uriPrefix)
  135. {
  136. if (uriPrefix == null)
  137. throw new ArgumentNullException ("uriPrefix");
  138. var len = uriPrefix.Length;
  139. if (len == 0) {
  140. var msg = "An empty string.";
  141. throw new ArgumentException (msg, "uriPrefix");
  142. }
  143. var schm = uriPrefix.StartsWith ("http://")
  144. || uriPrefix.StartsWith ("https://");
  145. if (!schm) {
  146. var msg = "The scheme is not 'http' or 'https'.";
  147. throw new ArgumentException (msg, "uriPrefix");
  148. }
  149. var end = len - 1;
  150. if (uriPrefix[end] != '/') {
  151. var msg = "It ends without '/'.";
  152. throw new ArgumentException (msg, "uriPrefix");
  153. }
  154. var host = uriPrefix.IndexOf (':') + 3;
  155. if (host >= end) {
  156. var msg = "No host is specified.";
  157. throw new ArgumentException (msg, "uriPrefix");
  158. }
  159. if (uriPrefix[host] == ':') {
  160. var msg = "No host is specified.";
  161. throw new ArgumentException (msg, "uriPrefix");
  162. }
  163. var root = uriPrefix.IndexOf ('/', host, len - host);
  164. if (root == host) {
  165. var msg = "No host is specified.";
  166. throw new ArgumentException (msg, "uriPrefix");
  167. }
  168. if (uriPrefix[root - 1] == ':') {
  169. var msg = "No port is specified.";
  170. throw new ArgumentException (msg, "uriPrefix");
  171. }
  172. if (root == end - 1) {
  173. var msg = "No path is specified.";
  174. throw new ArgumentException (msg, "uriPrefix");
  175. }
  176. }
  177. /// <summary>
  178. /// Determines whether the current instance is equal to the specified
  179. /// <see cref="object"/> instance.
  180. /// </summary>
  181. /// <remarks>
  182. /// This method will be required to detect duplicates in any collection.
  183. /// </remarks>
  184. /// <param name="obj">
  185. /// <para>
  186. /// An <see cref="object"/> instance to compare to the current instance.
  187. /// </para>
  188. /// <para>
  189. /// An reference to a <see cref="HttpListenerPrefix"/> instance.
  190. /// </para>
  191. /// </param>
  192. /// <returns>
  193. /// <c>true</c> if the current instance and <paramref name="obj"/> have
  194. /// the same URI prefix; otherwise, <c>false</c>.
  195. /// </returns>
  196. public override bool Equals (object obj)
  197. {
  198. var pref = obj as HttpListenerPrefix;
  199. return pref != null && _prefix.Equals (pref._prefix);
  200. }
  201. /// <summary>
  202. /// Gets the hash code for the current instance.
  203. /// </summary>
  204. /// <remarks>
  205. /// This method will be required to detect duplicates in any collection.
  206. /// </remarks>
  207. /// <returns>
  208. /// An <see cref="int"/> that represents the hash code.
  209. /// </returns>
  210. public override int GetHashCode ()
  211. {
  212. return _prefix.GetHashCode ();
  213. }
  214. public override string ToString ()
  215. {
  216. return _prefix;
  217. }
  218. #endregion
  219. }
  220. }