Used when a post is served to the output stream.
Inheritance: System.EventArgs
Ejemplo n.º 1
0
 /// <summary>
 /// Raises the <see cref="Serving"/> event.
 /// </summary>
 /// <param name="eventArgs">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
 public void OnServing(ServingEventArgs eventArgs)
 {
     if (Serving != null)
     {
         Serving(this, eventArgs);
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Called when [serving].
 /// </summary>
 /// <param name="comment">The comment.</param>
 /// <param name="arg">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
 public static void OnServing(Comment comment, ServingEventArgs arg)
 {
     if (Serving != null)
     {
         Serving(comment, arg);
     }
 }
Ejemplo n.º 3
0
 private void Post_Serving(object sender, ServingEventArgs e)
 {
     if (e.Location != ServingLocation.PostList && e.Location != ServingLocation.SinglePost)
       {
       body.Attributes.Add("class", "altbg");
       }
 }
Ejemplo n.º 4
0
    /// <summary>
    /// Serves the page to the containing DIV tag on the page.
    /// </summary>
    /// <param name="id">
    /// The id of the page to serve.
    /// </param>
    private void ServePage(Guid id)
    {
		var pg = this.Page;

        if (pg == null || (!pg.IsVisible))
        {
            this.Response.Redirect(string.Format("{0}error404.aspx", Utils.RelativeWebRoot), true);
            return; // WLF: ReSharper is stupid and doesn't know that redirect returns this method.... or does it not...?
        }

        this.h1Title.InnerHtml = System.Web.HttpContext.Current.Server.HtmlEncode(pg.Title);

        var arg = new ServingEventArgs(pg.Content, ServingLocation.SinglePage);
        BlogEngine.Core.Page.OnServing(pg, arg);

        if (arg.Cancel)
        {
            this.Response.Redirect("error404.aspx", true);
        }

        if (arg.Body.Contains("[usercontrol", StringComparison.OrdinalIgnoreCase))
        {
            Utils.InjectUserControls(this.divText, arg.Body);
           // this.InjectUserControls(arg.Body);
        }
        else
        {
            this.divText.InnerHtml = arg.Body;
        }
    }
Ejemplo n.º 5
0
 /// <summary>
 /// Replaces the [more] string with a hyperlink to the full post.
 /// </summary>
 private static void AddMoreLink(object sender, ServingEventArgs e)
 {
     Post post = (Post)sender;
     int index = e.Body.IndexOf("[more]");
     string link = "<a class=\"more\" href=\"" + post.RelativeLink + "#continue\">" + Resources.labels.more + "...</a>";
     e.Body = e.Body.Substring(0, index) + link;
 }
Ejemplo n.º 6
0
    /// <summary>
    /// Handles the CommentServing event of the Post control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
    private static void PostCommentServing(object sender, ServingEventArgs e)
    {
        if (!ExtensionManager.ExtensionEnabled("Smilies"))
            return;

        if (string.IsNullOrEmpty(e.Body))
            return;

        e.Body = e.Body.Replace("(H)", Convert("cool", "Cool"));
        e.Body = e.Body.Replace(":'(", Convert("cry", "Cry"));
        e.Body = e.Body.Replace(":$", Convert("embarassed", "Embarassed"));
        e.Body = e.Body.Replace(":|", Convert("foot-in-mouth", "Foot"));
        e.Body = e.Body.Replace(":(", Convert("frown", "Frown"));
        e.Body = e.Body.Replace("(A)", Convert("innocent", "Innocent"));
        e.Body = e.Body.Replace("(K)", Convert("kiss", "Kiss"));
        e.Body = e.Body.Replace(":D", Convert("laughing", "Laughing"));
        e.Body = e.Body.Replace("($)", Convert("money-mouth", "Money"));
        e.Body = e.Body.Replace(":-#", Convert("sealed", "Sealed"));
        e.Body = e.Body.Replace(":)", Convert("smile", "Smile"));
        e.Body = e.Body.Replace(":-)", Convert("smile", "Smile"));
        e.Body = e.Body.Replace(":-O", Convert("surprised", "Surprised"));
        e.Body = e.Body.Replace(":P", Convert("tongue-out", "Tong"));
        e.Body = e.Body.Replace("*-)", Convert("undecided", "Undecided"));
        e.Body = e.Body.Replace(";-)", Convert("wink", "Wink"));
        e.Body = e.Body.Replace("8o|", Convert("yell", "Yell"));
    }
Ejemplo n.º 7
0
 /// <summary>
 /// Raises the event in a safe way
 /// </summary>
 public static void OnServing(Page page, ServingEventArgs arg)
 {
     if (Serving != null)
     {
         Serving(page, arg);
     }
 }
Ejemplo n.º 8
0
    /// <summary>
    /// The event handler that is triggered every time a comment is served to a client.
    /// </summary>
    private static void Post_CommentServing(object sender, ServingEventArgs e)
    {
        if (string.IsNullOrEmpty(e.Body))
            return;

        e.Body = regex.Replace(e.Body, new MatchEvaluator(ResolveLinks.Evaluator));
    }
Ejemplo n.º 9
0
 /// <summary>
 /// Raises the event in a safe way
 /// </summary>
 public static void OnServing(Post post, ServingEventArgs arg)
 {
     if (Serving != null)
     {
         Serving(post, arg);
     }
 }
Ejemplo n.º 10
0
    static string GetPostExcerpt(ServingEventArgs e, string moreLink)
    {
        e.Body = Utils.StripHtml(e.Body);

          if (e.Body.Length > postLength)
          return e.Body.Substring(0, postLength) + "... " + moreLink;

          return e.Body;
    }
    /// <summary>
    /// Handles the CommentServing event of the Post control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
    private static void PostCommentServing(object sender, ServingEventArgs e)
    {
        if (string.IsNullOrEmpty(e.Body))
        {
            return;
        }

        e.Body = LinkRegex.Replace(e.Body, new MatchEvaluator(Evaluator));
    }
Ejemplo n.º 12
0
 void Post_Serving(object sender, ServingEventArgs e)
 {
     // [gist id=1234]
     e.Body = Regex.Replace(e.Body, "\\[gist\\s[^\\]]*id=([\\da-fA-F]+)[^\\]]*\\]", "<script src=\"https://gist.github.com/$1.js\"></script>");
     // [gist]1234[/gist]
     e.Body = Regex.Replace(e.Body, "\\[gist\\]([\\da-fA-F]+)\\[\\/gist\\]", "<script src=\"https://gist.github.com/$1.js\"></script>");
     e.Body = Regex.Replace(e.Body, "(\\n|<(br|p)\\s*/?>)\\s*https://gist\\.github\\.com/(\\w+/)?(\\d+)/?\\s*(\\n|<(br|p)\\s*/?>|</p>|</li>)", "<script src=\"https://gist.github.com/$4.js\"></script>");
     e.Body = Regex.Replace(e.Body, "\\[gist\\s+https://gist\\.github\\.com/(\\w+/)?(\\d+)/?\\s*\\]", "<script src=\"https://gist.github.com/$2.js\"></script>");
 }
Ejemplo n.º 13
0
    /// <summary>
    /// Handles the CommentServing event of the Post control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
    private static void PostCommentServing(object sender, ServingEventArgs e)
    {
        if (!ExtensionManager.ExtensionEnabled("ResolveLinks"))
            return;

        if (string.IsNullOrEmpty(e.Body))
            return;

        e.Body = LinkRegex.Replace(e.Body, new MatchEvaluator(Evaluator));
    }
	private void InsertCopyCodeLink( ServingEventArgs e)
	{
		if( !string.IsNullOrEmpty(e.Body) )
		{

			//### find code-div
			string postID = Guid.NewGuid().ToString().Replace( "{", "" ).Replace( "}", "" ).Replace( "-", "" );
			string toFind = "<div class=\"csharpcode-wrapper\">";
			int index = e.Body.IndexOf(toFind);
			while( index != -1 )
			{

				//### grab code out of code-div
				int end = e.Body.IndexOf( "</div>", index ); //### the first </div> should be the end of "csharpcode"
				end = e.Body.IndexOf( "</div>", end ); //### the next </div> should be the end of "csharpcode-wrapper"
				string code = e.Body.Substring(index, end - index);

				//### parse code out of code-div
				int codeStart = code.IndexOf("<pre ");
				int codeEnd = code.LastIndexOf("</pre>") + 6;
				code = code.Substring(codeStart, codeEnd - codeStart);
				code = Regex.Replace( code, @"<(.|\n)*?>", string.Empty ); //### strip html
				code = code.Replace( "&#160;", "" ); //### remove unnecessary &#160;s from the blank lines
				code = code.Replace( "&nbsp;", " " ); //### convert &nbsp;s to spaces
				code = Regex.Replace( code, @"^(\s*)(\d+): ", "" ); //### remove line numbers on first line
				code = Regex.Replace( code, @"(\n)(\s*)(\d+): ", "\n" );  //### remove line numbers on subsequent lines

				//### create copy link
				string insertScript = @"
					<script type=""text/javascript"">
						var copyToClipboard@INDEX = CopyToClipboard_Strip('@CODE');
					</script>";
				string insertDiv = @"<div class=""CopyToClipboard"" style=""@STYLE""><div><a href=""javascript:void(0);"" onclick=""CopyToClipboard_ViewPlain(copyToClipboard@INDEX);"">@POPUPTEXT</a> | <a href=""javascript:void(0);"" onclick=""CopyToClipboard_Copy(copyToClipboard@INDEX);"">@COPYTEXT</a></div></div>";

				//### set values for copy link and insert above/below code
				string insert = insertDiv + OutputCommonMethods() + insertScript;
				insert = insert.Replace( "@STYLE", settings.GetSingleValue("style") );
				insert = insert.Replace( "@POPUPTEXT", settings.GetSingleValue("popupText") );
				insert = insert.Replace( "@COPYTEXT", settings.GetSingleValue("copyText") );
				insert = insert.Replace( "@INDEX", postID + "_" + index.ToString() ); //### use index of code-div as a unique ID to allow multiple code-divs on this post
				insert = insert.Replace( "@CODE", code.Replace( "\\", "\\\\" ).Replace( "'", "\\'" ).Replace( "\r\n", "\\r\\n" ).Replace( "\\r\\n\\r\\n\\r\\n", "\\r\\n" ) );
				if( settings.GetSingleValue("aboveBelow").ToLower() == "above" )
					e.Body = e.Body.Insert( index, insert );
				else
					e.Body = e.Body.Insert( e.Body.IndexOf( "</div>", end + 1 ) + 6, insert );

				//### prep index to find next code-div
				index = index + insert.Length + 1; //### ensure we don't find this same code-div again
				if( index > e.Body.Length ) break;
				index = e.Body.IndexOf( toFind, index ); //### find any other code divs

			}
		}
	}
Ejemplo n.º 15
0
 /// <summary>
 /// Replaces the [more] string on the full post page.
 /// </summary>
 private static void PrepareFullPost(ServingEventArgs e)
 {
     HttpRequest request = HttpContext.Current.Request;
     if (request.UrlReferrer == null || request.UrlReferrer.Host != request.Url.Host)
     {
       e.Body = e.Body.Replace("[more]", string.Empty);
     }
     else
     {
       e.Body = e.Body.Replace("[more]", "<span id=\"continue\"></span>");
     }
 }
Ejemplo n.º 16
0
    private static void PostServing(object sender, ServingEventArgs e)
    {
        if (e.Body.Contains("[more]"))
          return;

          if (e.Location == ServingLocation.PostList)
          {
          var post = (Post)sender;
          string moreLink = string.Format("<a class=\"more\" href=\"{0}#continue\">{1}</a>", post.RelativeLink, labels.more);

          //e.Body = GetPostPicture(e) + GetPostExcerpt(e, moreLink);
          }
    }
Ejemplo n.º 17
0
    private static void Post_CommentAdded(object sender, EventArgs e)
    {
        Post post = (Post)((Comment)sender).Parent;
        if (post != null && BlogSettings.Instance.SendMailOnComment && !Thread.CurrentPrincipal.Identity.IsAuthenticated)
        {
            Comment comment = post.Comments[post.Comments.Count - 1];
            // Trackback and pingback comments don't have a '@' symbol in the e-mail field.
            string from = comment.Email.Contains("@") ? comment.Email : BlogSettings.Instance.Email;
            string subject = " comment on ";

            if (comment.Email == "trackback")
                subject = " trackback on ";
            else if (comment.Email == "pingback")
                subject = " pingback on ";

            ServingEventArgs args = new ServingEventArgs(comment.Content, ServingLocation.Email);
            Comment.OnServing(comment, args);
            string body = args.Body;

            MailMessage mail = new MailMessage();
            mail.From = new MailAddress(from, HttpUtility.HtmlDecode(comment.Author));
            mail.To.Add(BlogSettings.Instance.Email);
            mail.Subject = BlogSettings.Instance.EmailSubjectPrefix + subject + post.Title;
            mail.Body = "<div style=\"font: 11px verdana, arial\">";
            mail.Body += body.Replace(Environment.NewLine, "<br />") + "<br /><br />";
            mail.Body += string.Format("<strong>{0}</strong>: <a href=\"{1}\">{2}</a><br /><br />", Resources.labels.post, post.PermaLink + "#id_" + comment.Id, post.Title);

            mail.Body += "_______________________________________________________________________________<br />";
            mail.Body += "<h3>Author information</h3>";
            mail.Body += "<div style=\"font-size:10px;line-height:16px\">";
            mail.Body += "<strong>Name:</strong> " + comment.Author + "<br />";
            mail.Body += "<strong>E-mail:</strong> " + comment.Email + "<br />";
            mail.Body += string.Format("<strong>Website:</strong> <a href=\"{0}\">{0}</a><br />", comment.Website);

            if (comment.Country != null)
                mail.Body += "<strong>Country code:</strong> " + comment.Country.ToUpperInvariant() + "<br />";

            if (HttpContext.Current != null)
            {
                mail.Body += "<strong>IP address:</strong> " + HttpContext.Current.Request.UserHostAddress + "<br />";
                mail.Body += string.Format("<strong>Referrer:</strong> <a href=\"{0}\">{0}</a><br />", HttpContext.Current.Request.UrlReferrer);
                mail.Body += "<strong>User-agent:</strong> " + HttpContext.Current.Request.UserAgent;
            }

            mail.Body += "</div>";
            mail.Body += "</div>";

            Utils.SendMailMessageAsync(mail);
        }
    }
Ejemplo n.º 18
0
    void Post_Serving(object sender, ServingEventArgs e)
    {
        if (e.Location == ServingLocation.Feed) return;

        bool ShowPostList = Convert.ToBoolean(_extensionSettings.GetSingleValue("ShowPostList"));
        if (e.Location == ServingLocation.PostList && !ShowPostList) return;

        Post post = sender as Post;
        ButtonSettings bSettings = new ButtonSettings();
        StringBuilder sBuild = new StringBuilder();
        sBuild.AppendLine("<div class=\"FacebookLike\">");
        string likeScript = string.Format("<iframe src=\"http://www.facebook.com/plugins/like.php?href={0}&amp;layout={1}&amp;show_faces={2}&amp;width={3}&amp;action={4}&amp;font&amp;colorscheme={5}&amp;height=80\" scrolling=\"no\" frameborder=\"0\" style=\"border:none; overflow:hidden; width:450px; height:80px;\" allowTransparency=\"true\"></iframe>",
            post.AbsoluteLink.AbsoluteUri, bSettings.Layout, bSettings.ShowFaces, bSettings.Width, bSettings.Action, bSettings.ColorScheme);
        sBuild.AppendLine(likeScript);
        sBuild.AppendLine("</div>");
        e.Body += sBuild.ToString();
    }
Ejemplo n.º 19
0
    /// <summary>
    /// Handles the Post.Serving event to take care of the [more] keyword.
    /// </summary>
    private static void Post_Serving(object sender, ServingEventArgs e)
    {
        if (!e.Body.Contains("[more]"))
          return;

        if (e.Location == ServingLocation.PostList)
        {
          AddMoreLink(sender, e);
        }
        else if (e.Location == ServingLocation.SinglePost)
        {
          PrepareFullPost(e);
        }
        else if (e.Location == ServingLocation.Feed)
        {
          e.Body = e.Body.Replace("[more]", string.Empty);
        }
    }
Ejemplo n.º 20
0
    /// <summary>
    /// Replaces the [more] string with a hyperlink to the full post.
    /// </summary>
    /// <param name="sender">
    /// The sender.
    /// </param>
    /// <param name="e">
    /// The event arguments.
    /// </param>
    private static void AddMoreLink(object sender, ServingEventArgs e)
    {
        var post = (Post)sender;
        var index = e.Body.IndexOf("[more]");
        var link = string.Format("<a class=\"more\" href=\"{0}#continue\">{1}...</a>", post.RelativeLink, labels.more);
        var newBody = e.Body.Substring(0, index);

        // Need to close any open HTML tags in NewBody where the matching close tags have been truncated.
        var closingTagsToAppend = string.Empty;
        var openingTagsCollection = OpeningTagRegex.Matches(newBody);

        if (openingTagsCollection.Count > 0)
        {
            // Copy the opening tags in MatchCollection to a generic list.
            var openingTags = openingTagsCollection.Cast<Match>().Where(openTag => openTag.Groups.Count == 2).Select(
                openTag => openTag.Groups[1].Value).ToList();

            var closingTagsCollection = ClosedTagRegex.Matches(newBody);

            // Iterate through closed tags and remove the first matching open tag from the openingTags list.
            foreach (var indexToRemove in from Match closedTag in closingTagsCollection
                                          where closedTag.Groups.Count == 2
                                          select openingTags.FindIndex(
                                              openTag =>
                                              openTag.Equals(
                                                  closedTag.Groups[1].Value, StringComparison.InvariantCultureIgnoreCase))
                                          into indexToRemove
                                          where indexToRemove != -1
                                          select indexToRemove)
            {
                openingTags.RemoveAt(indexToRemove);
            }

            // A closing tag needs to be created for any remaining tags in the openingTags list.
            if (openingTags.Count > 0)
            {
                // Reverse the order of the tags so tags opened later are closed first.
                openingTags.Reverse();
                closingTagsToAppend = string.Format("</{0}>", string.Join("></", openingTags.ToArray()));
            }
        }

        e.Body = newBody + link + closingTagsToAppend;
    }
    private static void AddSyntaxHighlighter(object sender, ServingEventArgs e)
    {
		if(e.Location == ServingLocation.Feed) return;
	
        HttpContext context = HttpContext.Current;
		
        Page page = (Page)context.CurrentHandler;

        if ((context.CurrentHandler is Page == false) || (context.Items[ExtensionName] != null))
        {
            return;
        }

        AddCssStyles(page);
        AddJavaScripts(page);
        AddOptions(page);

        context.Items[ExtensionName] = 1;
    }
Ejemplo n.º 22
0
    /// <summary>
    /// Replaces the [more] string with a hyperlink to the full post.
    /// </summary>
    private static void AddMoreLink(object sender, ServingEventArgs e)
    {
        Post post = (Post)sender;
        int index = e.Body.IndexOf("[more]");
        string link = "<a class=\"more\" href=\"" + post.RelativeLink + "#continue\">" + Resources.labels.more + "...</a>";
        string NewBody = e.Body.Substring(0, index);

        // Need to close any open HTML tags in NewBody where the matching close tags have been truncated.
        string closingTagsToAppend = string.Empty;
        MatchCollection openingTagsCollection = openingTagRegex.Matches(NewBody);

        if (openingTagsCollection.Count > 0)
        {
            // Copy the opening tags in MatchCollection to a generic list.
            List<string> openingTags = new List<string>();
            foreach (Match openTag in openingTagsCollection)
            {
                if (openTag.Groups.Count == 2)
                {
                    openingTags.Add(openTag.Groups[1].Value);
                }
            }
            MatchCollection closingTagsCollection = closedTagRegex.Matches(NewBody);
            // Iterate through closed tags and remove the first matching open tag from the openingTags list.
            foreach (Match closedTag in closingTagsCollection)
            {
                if (closedTag.Groups.Count == 2)
                {
                    int indexToRemove = openingTags.FindIndex(delegate(string openTag) { return openTag.Equals(closedTag.Groups[1].Value, StringComparison.InvariantCultureIgnoreCase); });
                    if (indexToRemove != -1)
                        openingTags.RemoveAt(indexToRemove);
                }
            }
            // A closing tag needs to be created for any remaining tags in the openingTags list.
            if (openingTags.Count > 0)
            {
                // Reverse the order of the tags so tags opened later are closed first.
                openingTags.Reverse();
                closingTagsToAppend = "</" + string.Join("></", openingTags.ToArray()) + ">";
            }
        }
        e.Body = NewBody + link + closingTagsToAppend;
    }
Ejemplo n.º 23
0
    static string GetPostPicture(ServingEventArgs e)
    {
        if (e.Body.IndexOf("<img ") <= 0)
          return pic;

          var start = e.Body.IndexOf("<img");
          var stop = e.Body.IndexOf("/>");

          if (stop > 0 && stop > start)
          {
          var s = e.Body.Substring(start, stop - start + 2);

          e.Body = e.Body.Replace(s, "");

          return s.Replace("<img ", "<img class=\"first-post-img\" ");
          }

          return pic;
    }
Ejemplo n.º 24
0
    /// <summary>
    /// The event handler that is triggered every time a comment is served to a client.
    /// </summary>
    private static void Post_CommentServing(object sender, ServingEventArgs e)
    {
        if (string.IsNullOrEmpty(e.Body))
            return;

        CultureInfo info = CultureInfo.InvariantCulture;

        foreach (Match match in regex.Matches(e.Body))
        {
            if (!match.Value.Contains("://"))
            {
                e.Body = e.Body.Replace(match.Value, string.Format(info, link, "http://", match.Value, ShortenUrl(match.Value, MAX_LENGTH)));
            }
            else
            {
                e.Body = e.Body.Replace(match.Value, string.Format(info, link, string.Empty, match.Value, ShortenUrl(match.Value, MAX_LENGTH)));
            }
        }
    }
Ejemplo n.º 25
0
    /// <summary>
    /// Handles the Serving event of the Post control.
    /// Handles the Post.Serving event to take care of the [more] keyword.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="BlogEngine.Core.ServingEventArgs"/> instance containing the event data.</param>
    private static void PostServing(object sender, ServingEventArgs e)
    {
        if (!e.Body.Contains("[more]"))
        {
            return;
        }

        switch (e.Location)
        {
            case ServingLocation.PostList:
                AddMoreLink(sender, e);
                break;
            case ServingLocation.SinglePost:
                PrepareFullPost(e);
                break;
            case ServingLocation.Feed:
                e.Body = e.Body.Replace("[more]", string.Empty);
                break;
        }
    }
	private void Post_PostServing(object sender, ServingEventArgs e)
	{
		//### executing here will execute the code on every iteration, but will not modify your post
		InsertCopyCodeLink(e);
	}
Ejemplo n.º 27
0
    private static void AddSyntaxHighlighter(object sender, ServingEventArgs e)
    {
        if (!ExtensionManager.ExtensionEnabled("SyntaxHighlighter"))
            return;

		if(e.Location == ServingLocation.Feed) 
            return;

        // if no code blocks on the page - don't bother
        if (!e.Body.ToLowerInvariant().Contains("<pre class=\"brush:"))
            return;
	
        HttpContext context = HttpContext.Current;
		
        Page page = (Page)context.CurrentHandler;

        if ((context.CurrentHandler is Page == false) || (context.Items[ExtensionName] != null))
        {
            return;
        }

        AddCssStyles(page);
        AddJavaScripts(page);
        AddOptions(page);

        context.Items[ExtensionName] = 1;
    }
Ejemplo n.º 28
0
    /// <summary>
    /// The event handler that is triggered every time a comment is served to a client.
    /// </summary>
    private static void Post_CommentServing(object sender, ServingEventArgs e)
    {
        string body = e.Body;

        // retrieve parameters back as a data table
        // column = parameter
        DataTable table = _settings.GetDataTable();
        foreach (DataRow row in table.Rows)
        {
            if (string.IsNullOrEmpty((string)row["CloseTag"]))
                Parse(ref body, (string)row["Code"], (string)row["OpenTag"]);
            else
                Parse(ref body, (string)row["Code"], (string)row["OpenTag"], (string)row["CloseTag"]);
        }

        e.Body = body;
    }
Ejemplo n.º 29
0
 static void ItemServing(object sender, ServingEventArgs e)
 {
     if (HttpContext.Current.CurrentHandler is BlogBasePage)
         (HttpContext.Current.CurrentHandler as BlogBasePage).LoadComplete += BasePageLoadComplete;
 }
        /// <summary>
        /// Writes the Atom feed entry element information to the specified <see cref="XmlWriter"/> using the supplied <see cref="Page"/>.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="XmlWriter"/> to write feed entry element information to.
        /// </param>
        /// <param name="publishable">
        /// The <see cref="IPublishable"/> used to generate feed entry content.
        /// </param>
        private static void WriteAtomEntry(XmlWriter writer, IPublishable publishable)
        {
            var post = publishable as Post;

            // var comment = publishable as Comment;

            // ------------------------------------------------------------
            // Raise serving event
            // ------------------------------------------------------------
            var arg = new ServingEventArgs(publishable.Content, ServingLocation.Feed);
            publishable.OnServing(arg);
            if (arg.Cancel)
            {
                return;
            }

            // ------------------------------------------------------------
            // Modify publishable content to make references absolute
            // ------------------------------------------------------------
            var content = Utils.ConvertPublishablePathsToAbsolute(arg.Body, publishable);

            writer.WriteStartElement("entry");

            // ------------------------------------------------------------
            // Write required entry elements
            // ------------------------------------------------------------
            writer.WriteElementString("id", publishable.AbsoluteLink.ToString());
            writer.WriteElementString("title", publishable.Title);
            writer.WriteElementString("updated", ToW3CDateTime(publishable.DateCreated.ToUniversalTime()));

            // ------------------------------------------------------------
            // Write recommended entry elements
            // ------------------------------------------------------------
            writer.WriteStartElement("link");
            writer.WriteAttributeString("rel", "self");
            writer.WriteAttributeString("href", GetPermaLink(publishable).ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("link");
            writer.WriteAttributeString("href", publishable.AbsoluteLink.ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("author");
            writer.WriteElementString("name", publishable.Author);
            writer.WriteEndElement();

            writer.WriteStartElement("summary");
            writer.WriteAttributeString("type", "html");
            writer.WriteString(content);
            writer.WriteEndElement();

            // ------------------------------------------------------------
            // Write optional entry elements
            // ------------------------------------------------------------
            writer.WriteElementString("published", ToW3CDateTime(publishable.DateCreated.ToUniversalTime()));

            writer.WriteStartElement("link");
            writer.WriteAttributeString("rel", "related");
            writer.WriteAttributeString("href", String.Concat(publishable.AbsoluteLink.ToString(),
                BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteEndElement();

            // ------------------------------------------------------------
            // Write enclosure tag for podcasting support
            // ------------------------------------------------------------
            if (BlogSettings.Instance.EnableEnclosures)
            {
                var encloser = GetEnclosure(content, publishable);
                if (!string.IsNullOrEmpty(encloser))
                {
                    writer.WriteRaw(encloser);
                }
            }

            // ------------------------------------------------------------
            // Write entry category elements
            // ------------------------------------------------------------
            if (publishable.Categories != null)
            {
                foreach (var category in publishable.Categories)
                {
                    writer.WriteStartElement("category");
                    writer.WriteAttributeString("term", category.Title);
                    writer.WriteEndElement();
                }
            }

            // ------------------------------------------------------------
            // Write Dublin Core syndication extension elements
            // ------------------------------------------------------------
            if (!String.IsNullOrEmpty(publishable.Author))
            {
                writer.WriteElementString("dc", "publisher", "http://purl.org/dc/elements/1.1/", publishable.Author);
            }

            if (!String.IsNullOrEmpty(publishable.Description))
            {
                writer.WriteElementString(
                    "dc", "description", "http://purl.org/dc/elements/1.1/", publishable.Description);
            }

            // ------------------------------------------------------------
            // Write pingback syndication extension elements
            // ------------------------------------------------------------
            Uri pingbackServer;
            if (Uri.TryCreate(
                String.Concat(publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), "/pingback.axd"),
                UriKind.RelativeOrAbsolute,
                out pingbackServer))
            {
                writer.WriteElementString(
                    "pingback",
                    "server",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    pingbackServer.ToString());
                writer.WriteElementString(
                    "pingback",
                    "target",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    GetPermaLink(publishable).ToString());
            }

            // ------------------------------------------------------------
            // Write slash syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.Comments != null)
            {
                writer.WriteElementString(
                    "slash",
                    "comments",
                    "http://purl.org/rss/1.0/modules/slash/",
                    post.Comments.Count.ToString(CultureInfo.InvariantCulture));
            }

            // ------------------------------------------------------------
            // Write trackback syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.TrackbackLink != null)
            {
                writer.WriteElementString(
                    "trackback",
                    "ping",
                    "http://madskills.com/public/xml/rss/module/trackback/",
                    post.TrackbackLink.ToString());
            }

            // ------------------------------------------------------------
            // Write well-formed web syndication extension elements
            // ------------------------------------------------------------
            writer.WriteElementString(
                "wfw",
                "comment",
                "http://wellformedweb.org/CommentAPI/",
                String.Concat(publishable.AbsoluteLink.ToString(),
                BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteElementString(
                "wfw",
                "commentRss",
                "http://wellformedweb.org/CommentAPI/",
                string.Format("{0}/syndication.axd?post={1}", publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), publishable.Id));

            // ------------------------------------------------------------
            // Write </entry> element
            // ------------------------------------------------------------
            writer.WriteEndElement();
        }
Ejemplo n.º 31
0
    /// <summary>
    /// Handles the CommentAdded event of the Post control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private static void PostCommentAdded(object sender, EventArgs e)
    {
        if (!BlogSettings.Instance.SendMailOnComment) { return; }

        var comment = (Comment)sender;
        if (comment == null) { return; }

        var post = comment.Parent as Post;
        if (post == null || post.CurrentUserOwns)
        {
            return;
        }

        // If moderation is on, send the email if the comment hasn't been moderated (so
        // the blog owner can determine if the comment should be approved/rejected).
        if (BlogSettings.Instance.EnableCommentsModeration &&
            !Utils.StringIsNullOrWhitespace(comment.ModeratedBy))
        {
            return;
        }
        else if (
        // If moderation is off, send the email only if it's been approved.
            !BlogSettings.Instance.EnableCommentsModeration &&
            !comment.IsApproved)
        {
            return;
        }

        // Trackback and pingback comments don't have a '@' symbol in the e-mail field.
        var replyTo = comment.Email.Contains("@") ? comment.Email : BlogSettings.Instance.Email;
        var subject = " comment on ";

        switch (comment.Email)
        {
            case "trackback":
                subject = " trackback on ";
                break;
            case "pingback":
                subject = " pingback on ";
                break;
        }

        var defaultCulture = Utils.GetDefaultCulture();

        var args = new ServingEventArgs(comment.Content, ServingLocation.Email);
        Comment.OnServing(comment, args);
        var body = args.Body;
        body = body.Replace(Environment.NewLine, "<br />");
        body = body.Replace(string.Format("<img src=\"{0}", Utils.RelativeWebRoot), string.Format("<img src=\"{0}", Utils.AbsoluteWebRoot));

        var mail = new MailMessage
            {
                From = new MailAddress(BlogSettings.Instance.Email),
                ReplyTo = new MailAddress(replyTo, HttpUtility.HtmlDecode(comment.Author)),
                Subject = BlogSettings.Instance.EmailSubjectPrefix + subject + post.Title
            };
        mail.To.Add(BlogSettings.Instance.Email);

        var sb = new StringBuilder();
        sb.Append("<div style=\"font: 11px verdana, arial\">");
        sb.AppendFormat("{0}<br /><br />", body);
        sb.AppendFormat(
            "<strong>{0}</strong>: <a href=\"{1}#id_{2}\">{3}</a><br /><br />",
            Utils.Translate("post", null, defaultCulture),
            post.PermaLink,
            comment.Id,
            post.Title);

        var deleteLink = string.Format("{0}?deletecomment={1}", post.AbsoluteLink, comment.Id);
        sb.AppendFormat(
            "<a href=\"{0}\">{1}</a>", deleteLink, Utils.Translate("delete", null, defaultCulture));

        if (BlogSettings.Instance.EnableCommentsModeration)
        {
            var approveLink = string.Format("{0}?approvecomment={1}", post.AbsoluteLink, comment.Id);
            sb.AppendFormat(
                " | <a href=\"{0}\">{1}</a>", approveLink, Utils.Translate("approve", null, defaultCulture));
        }

        sb.Append("<br />_______________________________________________________________________________<br />");
        sb.Append("<h3>Author information</h3>");
        sb.Append("<div style=\"font-size:10px;line-height:16px\">");
        sb.AppendFormat("<strong>Name:</strong> {0}<br />", comment.Author);
        sb.AppendFormat("<strong>E-mail:</strong> {0}<br />", comment.Email);
        sb.AppendFormat("<strong>Website:</strong> <a href=\"{0}\">{0}</a><br />", comment.Website);

        if (comment.Country != null)
        {
            sb.AppendFormat("<strong>Country code:</strong> {0}<br />", comment.Country.ToUpperInvariant());
        }

        if (HttpContext.Current != null)
        {
            sb.AppendFormat("<strong>IP address:</strong> {0}<br />", HttpContext.Current.Request.UserHostAddress);
            sb.AppendFormat("<strong>User-agent:</strong> {0}", HttpContext.Current.Request.UserAgent);
        }

        sb.Append("</div>");
        sb.Append("</div>");

        mail.Body = sb.ToString();

        Utils.SendMailMessageAsync(mail);
    }
Ejemplo n.º 32
0
    private static void Publishable_Serving(object sender, ServingEventArgs e)
    {
        if (!ExtensionManager.ExtensionEnabled("MediaElementPlayer"))
            return;

        if (e.Location == ServingLocation.PostList || e.Location == ServingLocation.SinglePost || e.Location == ServingLocation.Feed || e.Location == ServingLocation.SinglePage) {
	
			HttpContext context = HttpContext.Current;			
	
			string regex = @"(video|audio)";
			List<ShortCode> shortCodes = GetShortCodes(e.Body, regex, true);
	
			if (shortCodes.Count == 0)
				return;
							
			ProcessMediaTags(e, shortCodes);
			
			// this won't happen on feeds
			if (context.CurrentHandler is Page) {
				Page page = (Page)context.CurrentHandler;
				AddHeader(page);
                AddFooter(page);
			}
		}
	}
        /// <summary>
        /// Writes the RSS channel item element information to the specified <see cref="XmlWriter"/> using the supplied <see cref="Page"/>.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="XmlWriter"/> to write channel item element information to.
        /// </param>
        /// <param name="publishable">
        /// The <see cref="IPublishable"/> used to generate channel item content.
        /// </param>
        private static void WriteRssItem(XmlWriter writer, IPublishable publishable)
        {
            // ------------------------------------------------------------
            // Cast IPublishable as Post to support comments/trackback
            // ------------------------------------------------------------
            var post    = publishable as Post;
            var comment = publishable as Comment;

            // ------------------------------------------------------------
            // Raise serving event
            // ------------------------------------------------------------
            var arg = new ServingEventArgs(publishable.Content, ServingLocation.Feed);

            publishable.OnServing(arg);
            if (arg.Cancel)
            {
                return;
            }

            // ------------------------------------------------------------
            // Modify post content to make references absolute
            // ------------------------------------------------------------
            var content = Utils.ConvertPublishablePathsToAbsolute(arg.Body, publishable);

            if (comment != null)
            {
                content = content.Replace(Environment.NewLine, "<br />");
            }

            writer.WriteStartElement("item");

            // ------------------------------------------------------------
            // Write required channel item elements
            // ------------------------------------------------------------
            if (comment != null)
            {
                writer.WriteElementString("title", publishable.Author + " on " + comment.Parent.Title);
            }
            else
            {
                writer.WriteElementString("title", publishable.Title);
            }

            writer.WriteElementString("description", content);
            writer.WriteElementString("link", publishable.AbsoluteLink.ToString());

            // ------------------------------------------------------------
            // Write enclosure tag for podcasting support
            // ------------------------------------------------------------
            if (BlogSettings.Instance.EnableEnclosures)
            {
                var encloser = GetEnclosure(content, publishable);
                if (!string.IsNullOrEmpty(encloser))
                {
                    writer.WriteRaw(encloser);
                }
            }

            // ------------------------------------------------------------
            // Write optional channel item elements
            // ------------------------------------------------------------
            if (!string.IsNullOrEmpty(BlogSettings.Instance.FeedAuthor))
            {
                writer.WriteElementString("author", BlogSettings.Instance.FeedAuthor);
            }
            if (post != null)
            {
                writer.WriteElementString(
                    "comments", String.Concat(publishable.AbsoluteLink.ToString(),
                                              BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            }

            writer.WriteElementString("guid", GetPermaLink(publishable).ToString());
            writer.WriteElementString("pubDate", ToRfc822DateTime(publishable.DateCreated));

            // ------------------------------------------------------------
            // Write channel item category elements
            // ------------------------------------------------------------
            if (publishable.Categories != null)
            {
                foreach (var category in publishable.Categories)
                {
                    writer.WriteElementString("category", category.Title);
                }
            }

            // ------------------------------------------------------------
            // Write Dublin Core syndication extension elements
            // ------------------------------------------------------------
            if (!String.IsNullOrEmpty(publishable.Author))
            {
                writer.WriteElementString("dc", "publisher", "http://purl.org/dc/elements/1.1/", publishable.Author);
            }

            // if (!String.IsNullOrEmpty(publishable.Description))
            // {
            //     writer.WriteElementString("dc", "description", "http://purl.org/dc/elements/1.1/", publishable.Description);
            // }

            // ------------------------------------------------------------
            // Write pingback syndication extension elements
            // ------------------------------------------------------------
            Uri pingbackServer;

            if (Uri.TryCreate(
                    String.Concat(publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), "/pingback.axd"),
                    UriKind.RelativeOrAbsolute,
                    out pingbackServer))
            {
                writer.WriteElementString(
                    "pingback",
                    "server",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    pingbackServer.ToString());
                writer.WriteElementString(
                    "pingback",
                    "target",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    GetPermaLink(publishable).ToString());
            }

            // ------------------------------------------------------------
            // Write slash syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.Comments != null)
            {
                writer.WriteElementString(
                    "slash",
                    "comments",
                    "http://purl.org/rss/1.0/modules/slash/",
                    post.Comments.Count.ToString(CultureInfo.InvariantCulture));
            }

            // ------------------------------------------------------------
            // Write trackback syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.TrackbackLink != null)
            {
                writer.WriteElementString(
                    "trackback",
                    "ping",
                    "http://madskills.com/public/xml/rss/module/trackback/",
                    post.TrackbackLink.ToString());
            }

            // ------------------------------------------------------------
            // Write well-formed web syndication extension elements
            // ------------------------------------------------------------
            writer.WriteElementString(
                "wfw",
                "comment",
                "http://wellformedweb.org/CommentAPI/",
                String.Concat(publishable.AbsoluteLink.ToString(),
                              BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteElementString(
                "wfw",
                "commentRss",
                "http://wellformedweb.org/CommentAPI/",
                string.Format("{0}/syndication.axd?post={1}", publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), publishable.Id));

            // ------------------------------------------------------------
            // Write </item> element
            // ------------------------------------------------------------
            writer.WriteEndElement();
        }
Ejemplo n.º 34
0
    private static void ProcessMediaTags(ServingEventArgs e, List<ShortCode> shortCodes)
    {
	
		// path to media
        string folder = Settings.GetSingleValue("folder");			
		string path = Utils.RelativeWebRoot + folder.TrimEnd(new char[] {'/'}) + "/";
		
		// override for feed
		if (e.Location == ServingLocation.Feed) {
			path = Utils.AbsoluteWebRoot + folder.TrimEnd(new char[] { '/' }) + "/";			
		}
					
		// do replacement for media
		foreach (ShortCode sc in shortCodes)
		{
			string tagName = sc.TagName;
			string src = sc.GetAttributeValue("src", "");
			string w = sc.GetAttributeValue("width", "");
			string h = sc.GetAttributeValue("height", "");

			string mp4 = sc.GetAttributeValue("mp4", "");
			string mp3 = sc.GetAttributeValue("mp3", "");
			string webm = sc.GetAttributeValue("webm", "");
			string ogg = sc.GetAttributeValue("ogg", "");
			
			string poster = sc.GetAttributeValue("poster", "");
			string autoplay = sc.GetAttributeValue("autoplay", "");
			string preload = sc.GetAttributeValue("preload", "");

			string code =
				"<" + tagName + " class=\"mep\" controls=\"controls\"" + ((src != "") ? " src=\"" + ((src.IndexOf("http") == 0) ? "" : path) + src + "\"" : "") + ((poster != "") ? " poster=\"" + ((poster.IndexOf("http") == 0) ? "" : path) + poster + "\"" : "") + ((w != "") ? " width=\"" + w + "\"" : "") + ((h != "") ? " height=\"" + h + "\"" : "") + ((autoplay != "") ? " autoplay=\"autoplay\"" : "") + ((preload != "") ? " preload=\"" + preload + "\"" : "") + ">" +
					((mp4 != "") ? "<source src=\"" + ((mp4.IndexOf("http") == 0) ? "" : path) + mp4 + "\" type=\"video/mp4\" />" : "") +
					((mp3 != "") ? "<source src=\"" +((mp3.IndexOf("http") == 0) ? "" : path) + mp3 + "\" type=\"audio/mp3\" />" : "") +
					((webm != "") ? "<source src=\"" + ((webm.IndexOf("http") == 0) ? "" : path) + webm + "\" type=\"video/webm\" />" : "") +
					((ogg != "") ? "<source src=\"" + ((ogg.IndexOf("http") == 0) ? "" : path) + ogg + "\" type=\"video/ogg\" />" : "") + 
				
				"</" + tagName + ">";		
				
			e.Body = e.Body.Replace(sc.Text, code);
			
		}	
	}		
        /// <summary>
        /// Writes the RSS channel item element information to the specified <see cref="XmlWriter"/> using the supplied <see cref="Page"/>.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="XmlWriter"/> to write channel item element information to.
        /// </param>
        /// <param name="publishable">
        /// The <see cref="IPublishable"/> used to generate channel item content.
        /// </param>
        private static void WriteRssItem(XmlWriter writer, IPublishable publishable)
        {
            // ------------------------------------------------------------
            // Cast IPublishable as Post to support comments/trackback
            // ------------------------------------------------------------
            var post = publishable as Post;
            var comment = publishable as Comment;

            // ------------------------------------------------------------
            // Raise serving event
            // ------------------------------------------------------------
            var arg = new ServingEventArgs(publishable.Content, ServingLocation.Feed);
            publishable.OnServing(arg);
            if (arg.Cancel)
            {
                return;
            }

            // ------------------------------------------------------------
            // Modify post content to make references absolute
            // ------------------------------------------------------------
            var content = Utils.ConvertPublishablePathsToAbsolute(arg.Body, publishable);

            if (comment != null)
            {
                content = content.Replace(Environment.NewLine, "<br />");
            }

            writer.WriteStartElement("item");

            // ------------------------------------------------------------
            // Write required channel item elements
            // ------------------------------------------------------------
            if (comment != null)
            {
                writer.WriteElementString("title", publishable.Author + " on " + comment.Parent.Title);
            }
            else
            {
                writer.WriteElementString("title", publishable.Title);
            }

            writer.WriteElementString("description", content);
            writer.WriteElementString("link", publishable.AbsoluteLink.ToString());

            // ------------------------------------------------------------
            // Write enclosure tag for podcasting support
            // ------------------------------------------------------------
            if (BlogSettings.Instance.EnableEnclosures)
            {
                var encloser = GetEnclosure(content, publishable);
                if (!string.IsNullOrEmpty(encloser))
                {
                    writer.WriteRaw(encloser);
                }
            }

            // ------------------------------------------------------------
            // Write optional channel item elements
            // ------------------------------------------------------------
            if (!string.IsNullOrEmpty(BlogSettings.Instance.FeedAuthor))
            {
                writer.WriteElementString("author", BlogSettings.Instance.FeedAuthor);
            }
            if (post != null)
            {
                writer.WriteElementString(
                    "comments", String.Concat(publishable.AbsoluteLink.ToString(),
                    BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            }

            writer.WriteElementString("guid", GetPermaLink(publishable).ToString());
            writer.WriteElementString("pubDate", ToRfc822DateTime(publishable.DateCreated));

            // ------------------------------------------------------------
            // Write channel item category elements
            // ------------------------------------------------------------
            if (publishable.Categories != null)
            {
                foreach (var category in publishable.Categories)
                {
                    writer.WriteElementString("category", category.Title);
                }
            }

            // ------------------------------------------------------------
            // Write Dublin Core syndication extension elements
            // ------------------------------------------------------------
            if (!String.IsNullOrEmpty(publishable.Author))
            {
                writer.WriteElementString("dc", "publisher", "http://purl.org/dc/elements/1.1/", publishable.Author);
            }

            // if (!String.IsNullOrEmpty(publishable.Description))
            // {
            //     writer.WriteElementString("dc", "description", "http://purl.org/dc/elements/1.1/", publishable.Description);
            // }

            // ------------------------------------------------------------
            // Write pingback syndication extension elements
            // ------------------------------------------------------------
            Uri pingbackServer;
            if (Uri.TryCreate(
                String.Concat(publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), "/pingback.axd"),
                UriKind.RelativeOrAbsolute,
                out pingbackServer))
            {
                writer.WriteElementString(
                    "pingback",
                    "server",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    pingbackServer.ToString());
                writer.WriteElementString(
                    "pingback",
                    "target",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    GetPermaLink(publishable).ToString());
            }

            // ------------------------------------------------------------
            // Write slash syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.Comments != null)
            {
                writer.WriteElementString(
                    "slash",
                    "comments",
                    "http://purl.org/rss/1.0/modules/slash/",
                    post.Comments.Count.ToString(CultureInfo.InvariantCulture));
            }

            // ------------------------------------------------------------
            // Write trackback syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.TrackbackLink != null)
            {
                writer.WriteElementString(
                    "trackback",
                    "ping",
                    "http://madskills.com/public/xml/rss/module/trackback/",
                    post.TrackbackLink.ToString());
            }

            // ------------------------------------------------------------
            // Write well-formed web syndication extension elements
            // ------------------------------------------------------------
            writer.WriteElementString(
                "wfw",
                "comment",
                "http://wellformedweb.org/CommentAPI/",
                String.Concat(publishable.AbsoluteLink.ToString(),
                BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteElementString(
                "wfw",
                "commentRss",
                "http://wellformedweb.org/CommentAPI/",
                string.Format("{0}/syndication.axd?post={1}", publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), publishable.Id));

            // ------------------------------------------------------------
            // Write </item> element
            // ------------------------------------------------------------
            writer.WriteEndElement();
        }
        /// <summary>
        /// Writes the Atom feed entry element information to the specified <see cref="XmlWriter"/> using the supplied <see cref="Page"/>.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="XmlWriter"/> to write feed entry element information to.
        /// </param>
        /// <param name="publishable">
        /// The <see cref="IPublishable"/> used to generate feed entry content.
        /// </param>
        private static void WriteAtomEntry(XmlWriter writer, IPublishable publishable)
        {
            var post = publishable as Post;

            // var comment = publishable as Comment;

            // ------------------------------------------------------------
            // Raise serving event
            // ------------------------------------------------------------
            var arg = new ServingEventArgs(publishable.Content, ServingLocation.Feed);

            publishable.OnServing(arg);
            if (arg.Cancel)
            {
                return;
            }

            // ------------------------------------------------------------
            // Modify publishable content to make references absolute
            // ------------------------------------------------------------
            var content = Utils.ConvertPublishablePathsToAbsolute(arg.Body, publishable);

            writer.WriteStartElement("entry");

            // ------------------------------------------------------------
            // Write required entry elements
            // ------------------------------------------------------------
            writer.WriteElementString("id", publishable.AbsoluteLink.ToString());
            writer.WriteElementString("title", publishable.Title);
            writer.WriteElementString("updated", ToW3CDateTime(publishable.DateCreated.ToUniversalTime()));

            // ------------------------------------------------------------
            // Write recommended entry elements
            // ------------------------------------------------------------
            writer.WriteStartElement("link");
            writer.WriteAttributeString("rel", "self");
            writer.WriteAttributeString("href", GetPermaLink(publishable).ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("link");
            writer.WriteAttributeString("href", publishable.AbsoluteLink.ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("author");
            writer.WriteElementString("name", publishable.Author);
            writer.WriteEndElement();

            writer.WriteStartElement("summary");
            writer.WriteAttributeString("type", "html");
            writer.WriteString(content);
            writer.WriteEndElement();

            // ------------------------------------------------------------
            // Write optional entry elements
            // ------------------------------------------------------------
            writer.WriteElementString("published", ToW3CDateTime(publishable.DateCreated.ToUniversalTime()));

            writer.WriteStartElement("link");
            writer.WriteAttributeString("rel", "related");
            writer.WriteAttributeString("href", String.Concat(publishable.AbsoluteLink.ToString(),
                                                              BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteEndElement();

            // ------------------------------------------------------------
            // Write enclosure tag for podcasting support
            // ------------------------------------------------------------
            if (BlogSettings.Instance.EnableEnclosures)
            {
                var encloser = GetEnclosure(content, publishable);
                if (!string.IsNullOrEmpty(encloser))
                {
                    writer.WriteRaw(encloser);
                }
            }

            // ------------------------------------------------------------
            // Write entry category elements
            // ------------------------------------------------------------
            if (publishable.Categories != null)
            {
                foreach (var category in publishable.Categories)
                {
                    writer.WriteStartElement("category");
                    writer.WriteAttributeString("term", category.Title);
                    writer.WriteEndElement();
                }
            }

            // ------------------------------------------------------------
            // Write Dublin Core syndication extension elements
            // ------------------------------------------------------------
            if (!String.IsNullOrEmpty(publishable.Author))
            {
                writer.WriteElementString("dc", "publisher", "http://purl.org/dc/elements/1.1/", publishable.Author);
            }

            if (!String.IsNullOrEmpty(publishable.Description))
            {
                writer.WriteElementString(
                    "dc", "description", "http://purl.org/dc/elements/1.1/", publishable.Description);
            }

            // ------------------------------------------------------------
            // Write pingback syndication extension elements
            // ------------------------------------------------------------
            Uri pingbackServer;

            if (Uri.TryCreate(
                    String.Concat(publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), "/pingback.axd"),
                    UriKind.RelativeOrAbsolute,
                    out pingbackServer))
            {
                writer.WriteElementString(
                    "pingback",
                    "server",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    pingbackServer.ToString());
                writer.WriteElementString(
                    "pingback",
                    "target",
                    "http://madskills.com/public/xml/rss/module/pingback/",
                    GetPermaLink(publishable).ToString());
            }

            // ------------------------------------------------------------
            // Write slash syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.Comments != null)
            {
                writer.WriteElementString(
                    "slash",
                    "comments",
                    "http://purl.org/rss/1.0/modules/slash/",
                    post.Comments.Count.ToString(CultureInfo.InvariantCulture));
            }

            // ------------------------------------------------------------
            // Write trackback syndication extension elements
            // ------------------------------------------------------------
            if (post != null && post.TrackbackLink != null)
            {
                writer.WriteElementString(
                    "trackback",
                    "ping",
                    "http://madskills.com/public/xml/rss/module/trackback/",
                    post.TrackbackLink.ToString());
            }

            // ------------------------------------------------------------
            // Write well-formed web syndication extension elements
            // ------------------------------------------------------------
            writer.WriteElementString(
                "wfw",
                "comment",
                "http://wellformedweb.org/CommentAPI/",
                String.Concat(publishable.AbsoluteLink.ToString(),
                              BlogSettings.Instance.ModerationType == BlogSettings.Moderation.Disqus ? "#disqus_thread" : "#comment"));
            writer.WriteElementString(
                "wfw",
                "commentRss",
                "http://wellformedweb.org/CommentAPI/",
                string.Format("{0}/syndication.axd?post={1}", publishable.Blog.AbsoluteWebRoot.ToString().TrimEnd('/'), publishable.Id));

            // ------------------------------------------------------------
            // Write </entry> element
            // ------------------------------------------------------------
            writer.WriteEndElement();
        }