PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/App_Code/Extensions/Recaptcha/RecaptchaValidator.cs

#
C# | 188 lines | 105 code | 32 blank | 51 comment | 13 complexity | 443a98ce4b75bfbcf8d2b21c6d59a8ed MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. // Copyright (c) 2007 Adrian Godong, Ben Maurer
  2. // Permission is hereby granted, free of charge, to any person obtaining a copy
  3. // of this software and associated documentation files (the "Software"), to deal
  4. // in the Software without restriction, including without limitation the rights
  5. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  6. // copies of the Software, and to permit persons to whom the Software is
  7. // furnished to do so, subject to the following conditions:
  8. // The above copyright notice and this permission notice shall be included in
  9. // all copies or substantial portions of the Software.
  10. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  14. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  16. // THE SOFTWARE.
  17. // Adapted for dotnetblogengine by Filip Stanek ( http://www.bloodforge.com )
  18. namespace Recaptcha
  19. {
  20. using System;
  21. using System.IO;
  22. using System.Net;
  23. using System.Net.Sockets;
  24. using System.Text;
  25. using System.Web;
  26. /// <summary>
  27. /// Calls the reCAPTCHA server to validate the answer to a reCAPTCHA challenge. Normally,
  28. /// you will use the RecaptchaControl class to insert a web control on your page. However
  29. /// </summary>
  30. public class RecaptchaValidator
  31. {
  32. #region Constants and Fields
  33. /// <summary>
  34. /// The verify url.
  35. /// </summary>
  36. private const string VerifyUrl = "http://api-verify.recaptcha.net/verify";
  37. /// <summary>
  38. /// The remote ip.
  39. /// </summary>
  40. private string remoteIp;
  41. #endregion
  42. #region Properties
  43. /// <summary>
  44. /// Gets or sets Challenge.
  45. /// </summary>
  46. public string Challenge { get; set; }
  47. /// <summary>
  48. /// Gets or sets PrivateKey.
  49. /// </summary>
  50. public string PrivateKey { get; set; }
  51. /// <summary>
  52. /// Gets or sets RemoteIP.
  53. /// </summary>
  54. /// <exception cref="ArgumentException">
  55. /// </exception>
  56. public string RemoteIP
  57. {
  58. get
  59. {
  60. return this.remoteIp;
  61. }
  62. set
  63. {
  64. var ip = IPAddress.Parse(value);
  65. if (ip.AddressFamily != AddressFamily.InterNetwork && ip.AddressFamily != AddressFamily.InterNetworkV6)
  66. {
  67. throw new ArgumentException(string.Format("Expecting an IP address, got {0}", ip));
  68. }
  69. this.remoteIp = ip.ToString();
  70. }
  71. }
  72. /// <summary>
  73. /// Gets or sets Response.
  74. /// </summary>
  75. public string Response { get; set; }
  76. #endregion
  77. #region Public Methods
  78. /// <summary>
  79. /// Validates this instance.
  80. /// </summary>
  81. /// <returns>The response.</returns>
  82. public RecaptchaResponse Validate()
  83. {
  84. CheckNotNull(this.PrivateKey, "PrivateKey");
  85. CheckNotNull(this.RemoteIP, "RemoteIp");
  86. CheckNotNull(this.Challenge, "Challenge");
  87. CheckNotNull(this.Response, "Response");
  88. if (this.Challenge == string.Empty || this.Response == string.Empty)
  89. {
  90. return RecaptchaResponse.InvalidSolution;
  91. }
  92. var request = (HttpWebRequest)WebRequest.Create(VerifyUrl);
  93. // to avoid issues with Expect headers
  94. request.ProtocolVersion = HttpVersion.Version10;
  95. request.Timeout = 30 * 1000 /* 30 seconds */;
  96. request.Method = "POST";
  97. request.UserAgent = "reCAPTCHA/ASP.NET";
  98. request.ContentType = "application/x-www-form-urlencoded";
  99. var formdata = String.Format(
  100. "privatekey={0}&remoteip={1}&challenge={2}&response={3}",
  101. HttpUtility.UrlEncode(this.PrivateKey),
  102. HttpUtility.UrlEncode(this.RemoteIP),
  103. HttpUtility.UrlEncode(this.Challenge),
  104. HttpUtility.UrlEncode(this.Response));
  105. var formbytes = Encoding.ASCII.GetBytes(formdata);
  106. using (var requestStream = request.GetRequestStream())
  107. {
  108. requestStream.Write(formbytes, 0, formbytes.Length);
  109. }
  110. string[] results;
  111. try
  112. {
  113. using (var httpResponse = request.GetResponse())
  114. {
  115. var httpResponseStream = httpResponse.GetResponseStream();
  116. if (httpResponseStream == null)
  117. {
  118. return RecaptchaResponse.RecaptchaNotReachable;
  119. }
  120. using (TextReader readStream = new StreamReader(httpResponseStream, Encoding.UTF8))
  121. {
  122. results = readStream.ReadToEnd().Split();
  123. }
  124. }
  125. }
  126. catch (WebException)
  127. {
  128. return RecaptchaResponse.RecaptchaNotReachable;
  129. }
  130. switch (results[0])
  131. {
  132. case "true":
  133. return RecaptchaResponse.Valid;
  134. case "false":
  135. return new RecaptchaResponse(false, results[1]);
  136. default:
  137. throw new InvalidProgramException("Unknown status response.");
  138. }
  139. }
  140. #endregion
  141. #region Methods
  142. /// <summary>
  143. /// Checks the not null.
  144. /// </summary>
  145. /// <param name="obj">The object to check.</param>
  146. /// <param name="name">The object name.</param>
  147. private static void CheckNotNull(object obj, string name)
  148. {
  149. if (obj == null)
  150. {
  151. throw new ArgumentNullException(name);
  152. }
  153. }
  154. #endregion
  155. }
  156. }