#region Using using System; using System.IO; using System.Web; using System.Net; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Xml; using System.Web.UI; using System.Web.UI.HtmlControls; #endregion using BlogEngine.Core; namespace Controls { /// /// Creates and displays a dynamic blogroll. /// public class Blogroll : Control { public Blogroll() { BlogRollItem.Saved += new EventHandler(BlogRollItem_Saved); } private void BlogRollItem_Saved(object sender, SavedEventArgs e) { if (e.Action == SaveAction.Insert || e.Action == SaveAction.Update || e.Action == SaveAction.Delete) { if (e.Action == SaveAction.Insert) { AddBlog((BlogRollItem)sender); } else if (e.Action == SaveAction.Delete) { blogRequest affected = null; foreach (blogRequest req in _Items) { if (req.RollItem.Equals(sender)) { affected = req; break; } } _Items.Remove(affected); } if (_Items.Count > 0) { // Re-sort _Items collection in case sorting of blogroll items was changed. _Items.Sort(delegate(blogRequest br1, blogRequest br2) { return br1.RollItem.CompareTo(br2.RollItem); }); } } } protected override void Render(HtmlTextWriter writer) { if (!Page.IsPostBack && !Page.IsCallback) { HtmlGenericControl ul = DisplayBlogroll(); StringWriter sw = new StringWriter(); ul.RenderControl(new HtmlTextWriter(sw)); string html = sw.ToString(); writer.WriteLine("
"); writer.WriteLine(html); writer.WriteLine("
"); } } #region Private fields private static DateTime _LastUpdated = DateTime.Now; private static List _Items; #endregion #region Methods private static object _SyncRoot = new object(); /// /// Displays the RSS item collection. /// private HtmlGenericControl DisplayBlogroll() { if (DateTime.Now > _LastUpdated.AddMinutes(BlogSettings.Instance.BlogrollUpdateMinutes) && BlogSettings.Instance.BlogrollVisiblePosts > 0) { _Items = null; _LastUpdated = DateTime.Now; } if (_Items == null) { lock (_SyncRoot) { if (_Items == null) { _Items = new List(); foreach (BlogEngine.Core.BlogRollItem roll in BlogEngine.Core.BlogRollItem.BlogRolls) { AddBlog(roll); } } } } return BindControls(); } /// /// Parses the processed RSS items and returns the HTML /// private HtmlGenericControl BindControls() { HtmlGenericControl ul = new HtmlGenericControl("ul"); ul.Attributes.Add("class", "xoxo"); foreach (blogRequest item in _Items) { HtmlAnchor feedAnchor = new HtmlAnchor(); feedAnchor.HRef = item.RollItem.FeedUrl.AbsoluteUri; HtmlImage image = new HtmlImage(); image.Src = Utils.RelativeWebRoot + "pics/rssButton.gif"; image.Alt = "RSS feed for " + item.RollItem.Title; feedAnchor.Controls.Add(image); HtmlAnchor webAnchor = new HtmlAnchor(); webAnchor.HRef = item.RollItem.BlogUrl.AbsoluteUri; webAnchor.InnerHtml = EnsureLength(item.RollItem.Title); if (!String.IsNullOrEmpty(item.RollItem.Xfn)) webAnchor.Attributes["rel"] = item.RollItem.Xfn; HtmlGenericControl li = new HtmlGenericControl("li"); li.Controls.Add(feedAnchor); li.Controls.Add(webAnchor); AddRssChildItems(item, li); ul.Controls.Add(li); } return ul; } private void AddRssChildItems(blogRequest item, HtmlGenericControl li) { if (item.ItemTitles.Count > 0 && BlogSettings.Instance.BlogrollVisiblePosts > 0) { HtmlGenericControl div = new HtmlGenericControl("ul"); for (int i = 0; i < item.ItemTitles.Count; i++) { if (i >= BlogSettings.Instance.BlogrollVisiblePosts) break; HtmlGenericControl subLi = new HtmlGenericControl("li"); HtmlAnchor a = new HtmlAnchor(); a.HRef = item.ItemLinks[i]; a.Title = HttpUtility.HtmlEncode(item.ItemTitles[i]); a.InnerHtml = EnsureLength(item.ItemTitles[i]); subLi.Controls.Add(a); div.Controls.Add(subLi); } li.Controls.Add(div); } } /// /// Ensures that the name is no longer than the MaxLength. /// private string EnsureLength(string textToShorten) { if (textToShorten.Length > BlogSettings.Instance.BlogrollMaxLength) return textToShorten.Substring(0, BlogSettings.Instance.BlogrollMaxLength).Trim() + "..."; return HttpUtility.HtmlEncode(textToShorten); } /// /// Adds a blog to the item collection and start retrieving the blogs. /// private static void AddBlog(BlogEngine.Core.BlogRollItem br) { blogRequest affected = null; foreach (blogRequest req in _Items) { if (req.RollItem.Equals(br)) { affected = req; break; } } if (affected == null) { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(br.FeedUrl); req.Credentials = CredentialCache.DefaultNetworkCredentials; blogRequest bReq = new blogRequest(br, req); _Items.Add(bReq); req.BeginGetResponse(ProcessRespose, bReq); } } /// /// Gets the request and processes the response. /// private static void ProcessRespose(IAsyncResult async) { blogRequest blogReq = (blogRequest)async.AsyncState; try { using (HttpWebResponse response = (HttpWebResponse)blogReq.Request.EndGetResponse(async)) { XmlDocument doc = new XmlDocument(); doc.Load(response.GetResponseStream()); XmlNodeList nodes = doc.SelectNodes("rss/channel/item"); foreach (XmlNode node in nodes) { string title = node.SelectSingleNode("title").InnerText; string link = node.SelectSingleNode("link").InnerText; DateTime date = DateTime.Now; if (node.SelectSingleNode("pubDate") != null) date = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText); blogReq.ItemTitles.Add(title); blogReq.ItemLinks.Add(link); } } } catch { } } #endregion } internal class blogRequest { internal BlogEngine.Core.BlogRollItem RollItem; internal HttpWebRequest Request; internal List ItemTitles = new List(); internal List ItemLinks = new List(); internal blogRequest(BlogEngine.Core.BlogRollItem rollItem, HttpWebRequest request) { this.RollItem = rollItem; this.Request = request; } } }