/BlogEngine/DotNetSlave.BusinessLogic/Web/HttpHandlers/Sioc.cs
C# | 707 lines | 391 code | 102 blank | 214 comment | 30 complexity | 0050623c1403cb623aeb18e8282a96bb MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
- namespace BlogEngine.Core.Web.HttpHandlers
- {
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Web;
- using System.Web.Security;
- using System.Xml;
-
- /// <summary>
- /// Based on John Dyer's (http://johndyer.name/) extension.
- /// </summary>
- public class Sioc : IHttpHandler
- {
- #region Constants and Fields
-
- /// <summary>
- /// The xml namespaces.
- /// </summary>
- private static Dictionary<string, string> xmlNamespaces;
-
- #endregion
-
- #region Properties
-
- /// <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 false;
- }
- }
-
- /// <summary>
- /// Gets SupportedNamespaces.
- /// </summary>
- private static Dictionary<string, string> SupportedNamespaces
- {
- get
- {
- return xmlNamespaces ??
- (xmlNamespaces =
- new Dictionary<string, string>
- {
- { "foaf", "http://xmlns.com/foaf/0.1/" },
- { "rss", "http://purl.org/rss/1.0/" },
- { "admin", "http://webns.net/mvcb/" },
- { "dc", "http://purl.org/dc/elements/1.1/" },
- { "dcterms", "http://purl.org/dc/terms/" },
- { "rdfs", "http://www.w3.org/2000/01/rdf-schema#" },
- { "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
- { "content", "http://purl.org/rss/1.0/modules/content" },
- { "sioc", "http://rdfs.org/sioc/ns#" }
- });
- }
- }
-
- #endregion
-
- #region Implemented Interfaces
-
- #region IHttpHandler
-
- /// <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)
- {
- context.Response.ContentType = "text/xml";
- var siocType = context.Request["sioc_type"] + string.Empty;
- var siocId = context.Request["sioc_id"] + string.Empty;
-
- switch (siocType)
- {
- default:
-
- // case "site":
- var list = Post.Posts.ConvertAll(ConvertToIPublishable);
- var max = Math.Min(BlogSettings.Instance.PostsPerFeed, list.Count);
- list = list.GetRange(0, max);
- WriteSite(context.Response.OutputStream, list);
- break;
-
- case "post":
- Guid postId;
- if (siocId.TryParse(out postId))
- {
- var post = Post.GetPost(postId);
- if (post != null)
- {
- WritePub(context.Response.OutputStream, post);
- }
- }
-
- break;
-
- case "comment":
- Guid commentId;
- if (siocId.TryParse(out commentId))
- {
- // TODO: is it possible to get a single comment?
- var comment = GetComment(commentId);
-
- if (comment != null)
- {
- WritePub(context.Response.OutputStream, comment);
- }
- }
-
- break;
-
- case "user":
- WriteAuthor(context.Response.OutputStream, siocId);
- break;
-
- /*
- case "post":
- generator.WriteSite(context.Response.OutputStream);
- break;
- */
- }
- }
-
- #endregion
-
- #endregion
-
- #region Methods
-
- /// <summary>
- /// Calculates the SHA1.
- /// </summary>
- /// <param name="text">
- /// The text string.
- /// </param>
- /// <param name="enc">
- /// The encoding.
- /// </param>
- /// <returns>
- /// The hash string.
- /// </returns>
- private static string CalculateSha1(string text, Encoding enc)
- {
- var buffer = enc.GetBytes(text);
- var cryptoTransformSha1 = new SHA1CryptoServiceProvider();
- var hash = BitConverter.ToString(cryptoTransformSha1.ComputeHash(buffer)).Replace("-", string.Empty);
-
- return hash.ToLower();
- }
-
- /// <summary>
- /// Closes the writer.
- /// </summary>
- /// <param name="xmlWriter">
- /// The XML writer.
- /// </param>
- private static void CloseWriter(XmlWriter xmlWriter)
- {
- xmlWriter.WriteEndElement(); // rdf:RDF
- xmlWriter.WriteEndDocument();
- xmlWriter.Close();
- }
-
- /// <summary>
- /// Converts to publishable interface.
- /// </summary>
- /// <param name="item">
- /// The publishable item.
- /// </param>
- /// <returns>
- /// The publishable interface.
- /// </returns>
- private static IPublishable ConvertToIPublishable(IPublishable item)
- {
- return item;
- }
-
- /// <summary>
- /// Gets the blog author URL.
- /// </summary>
- /// <param name="username">
- /// The username.
- /// </param>
- /// <returns>
- /// Blog author url.
- /// </returns>
- private static string GetBlogAuthorUrl(string username)
- {
- return string.Format("{0}author/{1}.aspx", Utils.AbsoluteWebRoot, HttpUtility.UrlEncode(username));
- }
-
- /// <summary>
- /// Gets the comment.
- /// </summary>
- /// <param name="commentId">
- /// The comment id.
- /// </param>
- /// <returns>
- /// The comment.
- /// </returns>
- private static Comment GetComment(Guid commentId)
- {
- var posts = Post.Posts;
- return posts.SelectMany(post => post.Comments).FirstOrDefault(comm => comm.Id == commentId);
- }
-
- /// <summary>
- /// Gets the sioc author URL.
- /// </summary>
- /// <param name="username">
- /// The username.
- /// </param>
- /// <returns>
- /// The SIOC Author Url.
- /// </returns>
- private static string GetSiocAuthorUrl(string username)
- {
- return string.Format(
- "{0}sioc.axd?sioc_type=user&sioc_id={1}", Utils.AbsoluteWebRoot, HttpUtility.UrlEncode(username));
- }
-
- /// <summary>
- /// Gets the sioc authors URL.
- /// </summary>
- /// <returns>
- /// The SIOC Author Url.
- /// </returns>
- private static string GetSiocAuthorsUrl()
- {
- return string.Format("{0}sioc.axd?sioc_type=site#authors", Utils.AbsoluteWebRoot);
- }
-
- /// <summary>
- /// Gets the sioc blog URL.
- /// </summary>
- /// <returns>
- /// The SIOC Blog Url.
- /// </returns>
- private static string GetSiocBlogUrl()
- {
- return string.Format("{0}sioc.axd?sioc_type=site#webblog", Utils.AbsoluteWebRoot);
- }
-
- /// <summary>
- /// Gets the sioc comment URL.
- /// </summary>
- /// <param name="id">
- /// The comment id.
- /// </param>
- /// <returns>
- /// The SIOC Comment Url.
- /// </returns>
- private static string GetSiocCommentUrl(string id)
- {
- return string.Format("{0}sioc.axd?sioc_type=comment&sioc_id={1}", Utils.AbsoluteWebRoot, id);
- }
-
- /// <summary>
- /// Gets the sioc post URL.
- /// </summary>
- /// <param name="id">
- /// The SIOC post id.
- /// </param>
- /// <returns>
- /// The SIOC Post Url.
- /// </returns>
- private static string GetSiocPostUrl(string id)
- {
- return string.Format("{0}sioc.axd?sioc_type=post&sioc_id={1}", Utils.AbsoluteWebRoot, id);
- }
-
- /*
- /// <summary>
- /// Gets the sioc site URL.
- /// </summary>
- /// <returns>
- /// The SIOC Site Url.
- /// </returns>
- private static string GetSiocSiteUrl()
- {
- return string.Format("{0}sioc.axd?sioc_type=site", Utils.AbsoluteWebRoot);
- }
- */
-
- /// <summary>
- /// Gets the writer.
- /// </summary>
- /// <param name="stream">
- /// The stream.
- /// </param>
- /// <returns>
- /// The Xml Writer.
- /// </returns>
- private static XmlWriter GetWriter(Stream stream)
- {
- var settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true };
- var xmlWriter = XmlWriter.Create(stream, settings);
-
- xmlWriter.WriteStartDocument();
- xmlWriter.WriteStartElement("rdf", "RDF", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
-
- // "http://xmlns.com/foaf/0.1/");
- foreach (var prefix in SupportedNamespaces.Keys)
- {
- xmlWriter.WriteAttributeString("xmlns", prefix, null, SupportedNamespaces[prefix]);
- }
-
- return xmlWriter;
- }
-
- /// <summary>
- /// Writes the author.
- /// </summary>
- /// <param name="stream">
- /// The stream.
- /// </param>
- /// <param name="authorName">
- /// Name of the author.
- /// </param>
- private static void WriteAuthor(Stream stream, string authorName)
- {
- var xmlWriter = GetWriter(stream);
-
- WriteFoafDocument(xmlWriter, "user", GetSiocAuthorUrl(authorName));
-
- var user = Membership.GetUser(authorName);
- var ap = AuthorProfile.GetProfile(authorName);
-
- // FOAF:Person
- xmlWriter.WriteStartElement("foaf", "Person", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocAuthorUrl(authorName));
-
- xmlWriter.WriteElementString("foaf", "Name", null, authorName);
- if (ap != null && !ap.Private && ap.FirstName != String.Empty)
- {
- xmlWriter.WriteElementString("foaf", "firstName", null, ap.FirstName);
- }
-
- if (ap != null && !ap.Private && ap.LastName != String.Empty)
- {
- xmlWriter.WriteElementString("foaf", "surname", null, ap.LastName);
- }
-
- xmlWriter.WriteElementString(
- "foaf", "mbox_sha1sum", null, (user != null) ? CalculateSha1(user.Email, Encoding.UTF8) : string.Empty);
- xmlWriter.WriteStartElement("foaf", "homepage", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot.ToString());
- xmlWriter.WriteEndElement(); // foaf:homepage
-
- xmlWriter.WriteStartElement("foaf", "holdsAccount", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetBlogAuthorUrl(authorName));
- xmlWriter.WriteEndElement(); // foaf:holdsAccount
-
- xmlWriter.WriteEndElement(); // foaf:Person
-
- // SIOC:User
- xmlWriter.WriteStartElement("sioc", "User", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(authorName));
- xmlWriter.WriteElementString("foaf", "accountName", null, authorName);
- xmlWriter.WriteElementString("sioc", "name", null, authorName);
-
- // xmlWriter.WriteElementString("dcterms", "created", null, "TODO:" + authorName);
- xmlWriter.WriteEndElement(); // sioc:User
-
- CloseWriter(xmlWriter);
- }
-
- /// <summary>
- /// Writes the foaf document.
- /// </summary>
- /// <param name="xmlWriter">
- /// The XML writer.
- /// </param>
- /// <param name="siocType">
- /// Type of the sioc.
- /// </param>
- /// <param name="url">
- /// The URL string.
- /// </param>
- private static void WriteFoafDocument(XmlWriter xmlWriter, string siocType, string url)
- {
- var title = string.Format("SIOC {0} profile for \"{1}\"", siocType, BlogSettings.Instance.Name);
- const string Description =
- "A SIOC profile describes the structure and contents of a weblog in a machine readable form. For more information please refer to http://sioc-project.org/.";
-
- xmlWriter.WriteStartElement("foaf", "Document", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, Utils.AbsoluteWebRoot.ToString());
-
- xmlWriter.WriteElementString("dc", "title", null, title);
- xmlWriter.WriteElementString("dc", "description", null, Description);
- xmlWriter.WriteElementString("foaf", "primaryTopic", null, url);
- xmlWriter.WriteElementString(
- "admin", "generatorAgent", null, string.Format("BlogEngine.NET{0}", BlogSettings.Instance.Version()));
-
- xmlWriter.WriteEndElement(); // foaf:Document
- }
-
- /// <summary>
- /// Writes the forum.
- /// </summary>
- /// <param name="xmlWriter">
- /// The xml writer.
- /// </param>
- /// <param name="list">
- /// The enumerable of publishable interface.
- /// </param>
- private static void WriteForum(XmlWriter xmlWriter, IEnumerable<IPublishable> list)
- {
- xmlWriter.WriteStartElement("sioc", "Forum", null);
-
- xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocBlogUrl());
- xmlWriter.WriteElementString("sioc", "name", null, BlogSettings.Instance.Name);
- xmlWriter.WriteStartElement("sioc", "link", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocBlogUrl());
- xmlWriter.WriteEndElement();
-
- foreach (var pub in list)
- {
- xmlWriter.WriteStartElement("sioc", "container_of", null);
- xmlWriter.WriteStartElement("sioc", "Post", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, pub.AbsoluteLink.ToString());
- xmlWriter.WriteAttributeString("dc", "title", null, pub.Title);
-
- xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocPostUrl(pub.Id.ToString()));
- xmlWriter.WriteEndElement(); // sioc:Post
-
- xmlWriter.WriteEndElement(); // sioc:Post
- xmlWriter.WriteEndElement(); // sioc:Forum
- }
-
- xmlWriter.WriteEndElement(); // sioc:Forum
- }
-
- /// <summary>
- /// Writes an IPublishable to a stream.
- /// </summary>
- /// <param name="stream">
- /// The stream.
- /// </param>
- /// <param name="pub">
- /// The publishable interface.
- /// </param>
- private static void WritePub(Stream stream, IPublishable pub)
- {
- var xmlWriter = GetWriter(stream);
-
- if (pub is Post)
- {
- WriteFoafDocument(xmlWriter, "post", pub.AbsoluteLink.ToString());
- }
- else
- {
- WriteFoafDocument(xmlWriter, "comment", pub.AbsoluteLink.ToString());
- }
-
- WriteSiocPost(xmlWriter, pub);
- CloseWriter(xmlWriter);
- }
-
- /// <summary>
- /// Writes SIOC post.
- /// </summary>
- /// <param name="xmlWriter">
- /// The xml writer.
- /// </param>
- /// <param name="pub">
- /// The publishable interface.
- /// </param>
- private static void WriteSiocPost(XmlWriter xmlWriter, IPublishable pub)
- {
- xmlWriter.WriteStartElement("sioc", "Post", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, pub.AbsoluteLink.ToString());
-
- xmlWriter.WriteStartElement("sioc", "link", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, pub.AbsoluteLink.ToString());
- xmlWriter.WriteEndElement(); // sioc:link
-
- xmlWriter.WriteStartElement("sioc", "has_container", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocBlogUrl());
- xmlWriter.WriteEndElement(); // sioc:has_container
-
- xmlWriter.WriteElementString("dc", "title", null, pub.Title);
-
- // SIOC:USER
- if (pub is Post)
- {
- xmlWriter.WriteStartElement("sioc", "has_creator", null);
- xmlWriter.WriteStartElement("sioc", "User", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(pub.Author));
- xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(pub.Author));
- xmlWriter.WriteEndElement(); // rdf:about
- xmlWriter.WriteEndElement(); // sioc:User
- xmlWriter.WriteEndElement(); // sioc:has_creator
- }
-
- // FOAF:maker
- xmlWriter.WriteStartElement("foaf", "maker", null);
- xmlWriter.WriteStartElement("foaf", "Person", null);
- if (pub is Post)
- {
- xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(pub.Author));
- }
-
- xmlWriter.WriteAttributeString("foaf", "name", null, pub.Author);
-
- if (pub is Post)
- {
- var user = Membership.GetUser(pub.Author);
- xmlWriter.WriteElementString(
- "foaf",
- "mbox_sha1sum",
- null,
- (user != null) ? CalculateSha1(user.Email, Encoding.UTF8) : string.Empty);
- }
- else
- {
- xmlWriter.WriteElementString(
- "foaf", "mbox_sha1sum", null, CalculateSha1(((Comment)pub).Email, Encoding.UTF8));
- }
-
- xmlWriter.WriteStartElement("foaf", "homepage", null);
- if (pub is Post)
- {
- xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot.ToString());
- }
- else
- {
- xmlWriter.WriteAttributeString("rdf", "resource", null, "TODO:");
- }
-
- xmlWriter.WriteEndElement(); // foaf:homepage
-
- if (pub is Post)
- {
- xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(pub.Author));
- xmlWriter.WriteEndElement(); // rdfs:seeAlso
- }
-
- xmlWriter.WriteEndElement(); // foaf:Person
- xmlWriter.WriteEndElement(); // foaf:maker
-
- // CONTENT
- // xmlWriter.WriteElementString("dcterms", "created", null, DpUtility.ToW3cDateTime(pub.DateCreated));
- xmlWriter.WriteElementString("sioc", "content", null, Utils.StripHtml(pub.Content));
- xmlWriter.WriteElementString("content", "encoded", null, pub.Content);
-
- // TOPICS
- if (pub is Post)
- {
- // categories
- foreach (var category in ((Post)pub).Categories)
- {
- xmlWriter.WriteStartElement("sioc", "topic", null);
- xmlWriter.WriteAttributeString("rdfs", "label", null, category.Title);
- xmlWriter.WriteAttributeString("rdf", "resource", null, category.AbsoluteLink.ToString());
- xmlWriter.WriteEndElement(); // sioc:topic
- }
-
- // tags are also supposed to be treated as sioc:topic
- foreach (var tag in ((Post)pub).Tags)
- {
- xmlWriter.WriteStartElement("sioc", "topic", null);
- xmlWriter.WriteAttributeString("rdfs", "label", null, tag);
- xmlWriter.WriteAttributeString("rdf", "resource", null, Utils.AbsoluteWebRoot + "?tag=/" + tag);
- xmlWriter.WriteEndElement(); // sioc:topic
- }
-
- // COMMENTS
- foreach (var comment in ((Post)pub).ApprovedComments)
- {
- xmlWriter.WriteStartElement("sioc", "has_reply", null);
- xmlWriter.WriteStartElement("sioc", "Post", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, comment.AbsoluteLink.ToString());
-
- xmlWriter.WriteStartElement("rdfs", "seeAlso", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocCommentUrl(comment.Id.ToString()));
- xmlWriter.WriteEndElement(); // rdfs:seeAlso
-
- xmlWriter.WriteEndElement(); // sioc:Post
- xmlWriter.WriteEndElement(); // sioc:has_reply
- }
-
- // TODO: LINKS
- var linkMatches = Regex.Matches(pub.Content, @"<a[^(href)]?href=""([^""]+)""[^>]?>([^<]+)</a>");
- var linkPairs = new List<string>();
-
- foreach (Match linkMatch in linkMatches)
- {
- var url = linkMatch.Groups[1].Value;
- var text = linkMatch.Groups[2].Value;
-
- if (url.IndexOf(Utils.AbsoluteWebRoot.ToString()) == 0)
- {
- continue;
- }
-
- var pair = url + "|" + text;
- if (linkPairs.Contains(pair))
- {
- continue;
- }
-
- xmlWriter.WriteStartElement("sioc", "links_to", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, url);
- xmlWriter.WriteAttributeString("rdfs", "label", null, text);
- xmlWriter.WriteEndElement(); // sioc:links_to
-
- linkPairs.Add(pair);
- }
- }
-
- xmlWriter.WriteEndElement(); // sioc:Post
- }
-
- /// <summary>
- /// Writes sioc site.
- /// </summary>
- /// <param name="xmlWriter">
- /// The xml writer.
- /// </param>
- private static void WriteSiocSite(XmlWriter xmlWriter)
- {
- xmlWriter.WriteStartElement("sioc", "Site", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, Utils.AbsoluteWebRoot.ToString());
-
- xmlWriter.WriteElementString("dc", "title", null, BlogSettings.Instance.Name);
- xmlWriter.WriteElementString("dc", "description", null, BlogSettings.Instance.Description);
- xmlWriter.WriteElementString("sioc", "link", null, Utils.AbsoluteWebRoot.ToString());
- xmlWriter.WriteElementString("sioc", "host_of", null, GetSiocBlogUrl());
- xmlWriter.WriteElementString("sioc", "has_group", null, GetSiocAuthorsUrl());
-
- xmlWriter.WriteEndElement(); // sioc:Site
- }
-
- /// <summary>
- /// Writes site.
- /// </summary>
- /// <param name="stream">
- /// The stream.
- /// </param>
- /// <param name="list">
- /// The enumerable of IPublishable.
- /// </param>
- private static void WriteSite(Stream stream, IEnumerable<IPublishable> list)
- {
- var xmlWriter = GetWriter(stream);
-
- WriteUserGroup(xmlWriter);
- WriteFoafDocument(xmlWriter, "site", Utils.AbsoluteWebRoot.ToString());
- WriteSiocSite(xmlWriter);
- WriteForum(xmlWriter, list);
-
- CloseWriter(xmlWriter);
- }
-
- /// <summary>
- /// Writes the user group.
- /// </summary>
- /// <param name="xmlWriter">
- /// The XML writer.
- /// </param>
- private static void WriteUserGroup(XmlWriter xmlWriter)
- {
- xmlWriter.WriteStartElement("sioc", "Usergroup", null);
-
- xmlWriter.WriteAttributeString("rdf", "about", null, GetSiocAuthorsUrl());
- xmlWriter.WriteElementString("dc", "title", null, "Authors at \"" + BlogSettings.Instance.Name + "\"");
-
- int count;
- var members = Membership.Provider.GetAllUsers(0, 999, out count);
-
- foreach (MembershipUser user in members)
- {
- xmlWriter.WriteStartElement("sioc", "has_member", null);
- xmlWriter.WriteStartElement("sioc", "User", null);
- xmlWriter.WriteAttributeString("rdf", "about", null, GetBlogAuthorUrl(user.UserName));
- xmlWriter.WriteAttributeString("rdfs", "label", null, user.UserName);
-
- xmlWriter.WriteStartElement("sioc", "see_also", null);
- xmlWriter.WriteAttributeString("rdf", "resource", null, GetSiocAuthorUrl(user.UserName));
- xmlWriter.WriteEndElement(); // sioc:see_also
-
- xmlWriter.WriteEndElement(); // sioc:User
- xmlWriter.WriteEndElement(); // sioc:has_member
- }
-
- xmlWriter.WriteEndElement(); // foaf:Document
- }
-
- #endregion
- }
- }