⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pingbackhandler.cs

📁 个人博客系统
💻 CS
字号:
#region Using

using System;
using System.IO;
using System.Web;
using System.Net;
using System.Xml;
using System.Text.RegularExpressions;
using BlogEngine.Core;

#endregion

namespace BlogEngine.Core.Web.HttpHandlers
{
  /// <summary>
  /// Recieves pingbacks from other blogs and websites, and 
  /// registers them as a comment.
  /// </summary>
  public class PingbackHandler : IHttpHandler
  {

    #region Private fields

    private static Regex _Regex = new Regex(@"(?<=<title.*>)([\s\S]*)(?=</title>)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
    private string _Title;
    private bool _SourceHasLink;

    #endregion

    /// <summary>
    /// Enables processing of HTTP Web requests by a custom HttpHandler that 
    /// implements the <see cref="T:System.Web.IHttpHandler"></see> interface.
    /// </summary>
    /// <param name="context">An <see cref="T:System.Web.HttpContext"></see> 
    /// object that provides references to the intrinsic server objects 
    /// (for example, Request, Response, Session, and Server) used to service HTTP requests.
    /// </param>
    public void ProcessRequest(HttpContext context)
    {
      OnReceived();
      string html = string.Empty;
      try
      {
        string xml = ParseRequest(context);
        html = xml;
        if (!xml.Contains("<methodName>pingback.ping</methodName>"))
          return;

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xml);

        XmlNodeList list = doc.SelectNodes("methodCall/params/param/value/string");
        string sourceUrl = list[0].InnerText.Trim();
        string targetUrl = list[1].InnerText.Trim();

        ExamineSourcePage(sourceUrl, targetUrl);

        Post post = GetPostByUrl(targetUrl);
        if (post != null)
        {
          if (IsFirstPingBack(post, sourceUrl))
          {
            if (_SourceHasLink)
            {
              AddComment(sourceUrl, post);
              OnAccepted(sourceUrl);
              context.Response.Write("OK");
            }
            else
            {
              OnSpammed(sourceUrl);
            }
          }
          else
          {
            OnRejected(sourceUrl);
          }
        }

      }
      catch
      {
        context.Response.Write("ERROR");
      }
    }

    /// <summary>
    /// Insert the pingback as a comment on the post.
    /// </summary>
    private void AddComment(string sourceUrl, Post post)
    {
      Comment comment = new Comment();
      comment.Id = Guid.NewGuid();
      comment.Author = GetDomain(sourceUrl);
      comment.Website = new Uri(sourceUrl);
      comment.Content = "Pingback from " + comment.Author + Environment.NewLine + Environment.NewLine + _Title;
      comment.DateCreated = DateTime.Now;
      comment.Email = "pingback";
      comment.IP = HttpContext.Current.Request.UserHostAddress;
      comment.Post = post;
      comment.IsApproved = true; //NOTE: Pingback comments are approved by default.
      post.AddComment(comment);
    }

    /// <summary>
    /// Retrieves the content of the input stream
    /// and return it as plain text.
    /// </summary>
    private static string ParseRequest(HttpContext context)
    {
      byte[] buffer = new byte[context.Request.InputStream.Length];
      context.Request.InputStream.Read(buffer, 0, buffer.Length);

      return System.Text.Encoding.Default.GetString(buffer);
    }

    /// <summary>
    /// Parse the source URL to get the domain.
    /// It is used to fill the Author property of the comment.
    /// </summary>
    private static string GetDomain(string sourceUrl)
    {
      int start = sourceUrl.IndexOf("://") + 3;
      int stop = sourceUrl.IndexOf("/", start);
      return sourceUrl.Substring(start, stop - start).Replace("www.", string.Empty);
    }

    /// <summary>
    /// Checks to see if the source has already pinged the target.
    /// If it has, there is no reason to add it again.
    /// </summary>
    private static bool IsFirstPingBack(Post post, string sourceUrl)
    {
      foreach (Comment comment in post.Comments)
      {
        if (comment.Website != null && comment.Website.ToString().Equals(sourceUrl, StringComparison.OrdinalIgnoreCase))
          return false;

        if (comment.IP != null && comment.IP == HttpContext.Current.Request.UserHostAddress)
          return false;
      }

      return true;
    }

    /// <summary>
    /// Parse the HTML of the source page.
    /// </summary>
    private void ExamineSourcePage(string sourceUrl, string targetUrl)
    {
      try
      {
        using (WebClient client = new WebClient())
        {
          client.Credentials = CredentialCache.DefaultNetworkCredentials;
          string html = client.DownloadString(sourceUrl);
          _Title = _Regex.Match(html).Value.Trim();
          _SourceHasLink = html.ToLowerInvariant().Contains(targetUrl.ToLowerInvariant());
        }
      }
      catch (WebException)
      {
        _SourceHasLink = false;
      }
    }

    /// <summary>
    /// Retrieve the post that belongs to the target URL.
    /// </summary>
    private static Post GetPostByUrl(string url)
    {
      int start = url.LastIndexOf("/") + 1;
      int stop = url.ToLowerInvariant().IndexOf(".aspx");
      string name = url.Substring(start, stop - start).ToLowerInvariant();

      foreach (Post post in Post.Posts)
      {
        string legalTitle = Utils.RemoveIllegalCharacters(post.Title).ToLowerInvariant();
        if (name == legalTitle)
        {
          return post;
        }
      }

      return null;
    }

    /// <summary>
    /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"></see> instance.
    /// </summary>
    /// <value></value>
    /// <returns>true if the <see cref="T:System.Web.IHttpHandler"></see> instance is reusable; otherwise, false.</returns>
    public bool IsReusable
    {
      get { return true; }
    }

    #region Events

    /// <summary>
    /// Occurs when a hit is made to the trackback.axd handler.
    /// </summary>
    public static event EventHandler<EventArgs> Received;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    protected virtual void OnReceived()
    {
      if (Received != null)
      {
        Received(null, EventArgs.Empty);
      }
    }

    /// <summary>
    /// Occurs when a pingback is accepted as valid and added as a comment.
    /// </summary>
    public static event EventHandler<EventArgs> Accepted;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    protected virtual void OnAccepted(string url)
    {
      if (Accepted != null)
      {
        Accepted(url, EventArgs.Empty);
      }
    }

    /// <summary>
    /// Occurs when a pingback request is rejected because the sending
    /// website already made a trackback or pingback to the specific page.
    /// </summary>
    public static event EventHandler<EventArgs> Rejected;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    protected virtual void OnRejected(string url)
    {
      if (Rejected != null)
      {
        Rejected(url, EventArgs.Empty);
      }
    }

    /// <summary>
    /// Occurs when the request comes from a spammer.
    /// </summary>
    public static event EventHandler<EventArgs> Spammed;
    /// <summary>
    /// Raises the event in a safe way
    /// </summary>
    protected virtual void OnSpammed(string url)
    {
      if (Spammed != null)
      {
        Spammed(url, EventArgs.Empty);
      }
    }

    #endregion

  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -