HttpHandlerAction.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //
  2. // System.Web.Configuration.HttpHandlerAction
  3. //
  4. // Authors:
  5. // Chris Toshok ([email protected])
  6. // Daniel Nauck (dna(at)mono-project(dot)de)
  7. //
  8. // (C) 2005 Novell, Inc (http://www.novell.com)
  9. // (C) 2008 Daniel Nauck
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. #if NET_2_0
  32. using System;
  33. using System.Collections;
  34. using System.Collections.Generic;
  35. using System.ComponentModel;
  36. using System.Configuration;
  37. using System.Reflection;
  38. using System.Text.RegularExpressions;
  39. using System.Threading;
  40. using System.Web;
  41. using System.Web.Util;
  42. namespace System.Web.Configuration
  43. {
  44. public sealed class HttpHandlerAction: ConfigurationElement
  45. {
  46. static ConfigurationPropertyCollection _properties;
  47. static ConfigurationProperty pathProp;
  48. static ConfigurationProperty typeProp;
  49. static ConfigurationProperty validateProp;
  50. static ConfigurationProperty verbProp;
  51. static HttpHandlerAction ()
  52. {
  53. pathProp = new ConfigurationProperty ("path", typeof (string), null,
  54. TypeDescriptor.GetConverter (typeof (string)),
  55. PropertyHelper.NonEmptyStringValidator,
  56. ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
  57. typeProp = new ConfigurationProperty ("type", typeof (string), null,
  58. TypeDescriptor.GetConverter (typeof (string)),
  59. PropertyHelper.NonEmptyStringValidator,
  60. ConfigurationPropertyOptions.IsRequired);
  61. validateProp = new ConfigurationProperty ("validate", typeof (bool), true);
  62. verbProp = new ConfigurationProperty ("verb", typeof (string), null,
  63. TypeDescriptor.GetConverter (typeof (string)),
  64. PropertyHelper.NonEmptyStringValidator,
  65. ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
  66. _properties = new ConfigurationPropertyCollection ();
  67. _properties.Add (pathProp);
  68. _properties.Add (typeProp);
  69. _properties.Add (validateProp);
  70. _properties.Add (verbProp);
  71. }
  72. internal HttpHandlerAction ()
  73. { }
  74. public HttpHandlerAction (string path, string type, string verb)
  75. : this (path, type, verb, true)
  76. { }
  77. public HttpHandlerAction (string path, string type, string verb, bool validate)
  78. {
  79. Path = path;
  80. Type = type;
  81. Verb = verb;
  82. Validate = validate;
  83. }
  84. [ConfigurationProperty ("path", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
  85. // LAMESPEC: MS lists no validator here but provides one in Properties.
  86. public string Path {
  87. get { return (string) base[pathProp]; }
  88. set { base[pathProp] = value; }
  89. }
  90. [ConfigurationProperty ("type", Options = ConfigurationPropertyOptions.IsRequired)]
  91. // LAMESPEC: MS lists no validator here but provides one in Properties.
  92. public string Type {
  93. get { return (string) base[typeProp]; }
  94. set { base[typeProp] = value; }
  95. }
  96. [ConfigurationProperty ("validate", DefaultValue = true)]
  97. public bool Validate {
  98. get { return (bool) base[validateProp]; }
  99. set { base[validateProp] = value; }
  100. }
  101. [ConfigurationProperty ("verb", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
  102. // LAMESPEC: MS lists no validator here but provides one in Properties.
  103. public string Verb {
  104. get { return (string) base[verbProp]; }
  105. set { base[verbProp] = value; }
  106. }
  107. protected override ConfigurationPropertyCollection Properties {
  108. get { return _properties; }
  109. }
  110. #region CompatabilityCode
  111. object instance;
  112. Type type;
  113. string cached_verb = null;
  114. string[] cached_verbs;
  115. string[] SplitVerbs ()
  116. {
  117. if (Verb == "*")
  118. cached_verbs = null;
  119. else
  120. cached_verbs = Verb.Split (',');
  121. return cached_verbs;
  122. }
  123. internal string[] Verbs {
  124. get {
  125. if (cached_verb != Verb) {
  126. cached_verbs = SplitVerbs();
  127. cached_verb = Verb;
  128. }
  129. return cached_verbs;
  130. }
  131. }
  132. //
  133. // Loads the a type by name and verifies that it implements
  134. // IHttpHandler or IHttpHandlerFactory
  135. //
  136. internal static Type LoadType (string type_name)
  137. {
  138. Type t = null;
  139. t = HttpApplication.LoadType (type_name, false);
  140. if (t == null)
  141. throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
  142. if (typeof (IHttpHandler).IsAssignableFrom (t) ||
  143. typeof (IHttpHandlerFactory).IsAssignableFrom (t))
  144. return t;
  145. throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
  146. }
  147. internal bool PathMatches (string pathToMatch)
  148. {
  149. if (String.IsNullOrEmpty (pathToMatch))
  150. return false;
  151. bool result = false;
  152. string[] handlerPaths = Path.Split (',');
  153. int slash = pathToMatch.LastIndexOf ('/');
  154. string origPathToMatch = pathToMatch;
  155. string noLeadingSlashPathToMatch = null;
  156. if (slash != -1)
  157. pathToMatch = pathToMatch.Substring (slash);
  158. SearchPattern sp = null;
  159. foreach (string handlerPath in handlerPaths)
  160. {
  161. if (handlerPath.Length == 0)
  162. continue;
  163. if (handlerPath == "*") {
  164. result = true;
  165. break;
  166. }
  167. string matchExact = null;
  168. string endsWith = null;
  169. if (handlerPath.Length > 0)
  170. {
  171. if (handlerPath [0] == '*' && (handlerPath.IndexOf ('*', 1) == -1))
  172. endsWith = handlerPath.Substring (1);
  173. if (handlerPath.IndexOf ('*') == -1)
  174. if (handlerPath [0] != '/')
  175. {
  176. HttpContext ctx = HttpContext.Current;
  177. HttpRequest req = ctx != null ? ctx.Request : null;
  178. string vpath = req != null ? req.BaseVirtualDir : HttpRuntime.AppDomainAppVirtualPath;
  179. if (vpath == "/")
  180. vpath = String.Empty;
  181. matchExact = String.Concat (vpath, "/", handlerPath);
  182. }
  183. }
  184. if (matchExact != null)
  185. {
  186. result = matchExact.Length == origPathToMatch.Length && StrUtils.EndsWith (origPathToMatch, matchExact, true);
  187. if (result == true)
  188. break;
  189. else
  190. continue;
  191. }
  192. else if (endsWith != null)
  193. {
  194. result = StrUtils.EndsWith (pathToMatch, endsWith, true);
  195. if (result == true)
  196. break;
  197. else
  198. continue;
  199. }
  200. string pattern;
  201. if (handlerPath [0] == '/')
  202. pattern = handlerPath.Substring (1);
  203. else
  204. pattern = handlerPath;
  205. if (sp == null)
  206. sp = new SearchPattern (pattern, true);
  207. else
  208. sp.SetPattern (pattern, true);
  209. if (noLeadingSlashPathToMatch == null) {
  210. if (origPathToMatch [0] == '/')
  211. noLeadingSlashPathToMatch = origPathToMatch.Substring (1);
  212. else
  213. noLeadingSlashPathToMatch = origPathToMatch;
  214. }
  215. if (pattern.IndexOf ('/') >= 0)
  216. noLeadingSlashPathToMatch = AdjustPath (pattern, noLeadingSlashPathToMatch);
  217. if (sp.IsMatch (noLeadingSlashPathToMatch)) {
  218. result = true;
  219. break;
  220. }
  221. }
  222. return result;
  223. }
  224. static string AdjustPath (string pattern, string path)
  225. {
  226. int nslashes = 0;
  227. foreach (char c in pattern)
  228. if (c == '/')
  229. nslashes++;
  230. int i;
  231. for (i = path.Length - 1; i >= 0; i--) {
  232. if (path [i] == '/') {
  233. nslashes--;
  234. if (nslashes == -1)
  235. break;
  236. }
  237. }
  238. if (nslashes >= 0 || i == 0)
  239. return path;
  240. return path.Substring (i + 1);
  241. }
  242. // Loads the handler, possibly delay-loaded.
  243. internal object GetHandlerInstance ()
  244. {
  245. IHttpHandler ihh = instance as IHttpHandler;
  246. if (instance == null || (ihh != null && !ihh.IsReusable)){
  247. if (type == null)
  248. type = LoadType (Type);
  249. instance = Activator.CreateInstance (type,
  250. BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
  251. null, null, null);
  252. }
  253. return instance;
  254. }
  255. #endregion
  256. }
  257. }
  258. #endif