/// <summary> /// Initializes the supplied <see cref="RssCategory"/> using the specified <see cref="XPathNavigator"/> and <see cref="XmlNamespaceManager"/>. /// </summary> /// <param name="category">The <see cref="RssCategory"/> to be filled.</param> /// <param name="navigator">The <see cref="XPathNavigator"/> used to navigate the category XML data.</param> /// <param name="manager">The <see cref="XmlNamespaceManager"/> used to resolve XML namespace prefixes.</param> /// <param name="settings">The <see cref="SyndicationResourceLoadSettings"/> object used to configure the load operation.</param> /// <exception cref="ArgumentNullException">The <paramref name="category"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="navigator"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="manager"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="settings"/> is a null reference (Nothing in Visual Basic).</exception> private static void FillCategory(RssCategory category, XPathNavigator navigator, XmlNamespaceManager manager, SyndicationResourceLoadSettings settings) { Guard.ArgumentNotNull(category, "category"); Guard.ArgumentNotNull(navigator, "navigator"); Guard.ArgumentNotNull(manager, "manager"); Guard.ArgumentNotNull(settings, "settings"); if (navigator.HasAttributes) { string domainAttribute = navigator.GetAttribute("domain", String.Empty); if (!String.IsNullOrEmpty(domainAttribute)) { category.Domain = domainAttribute; } } if (!String.IsNullOrEmpty(navigator.Value)) { category.Value = navigator.Value; } SyndicationExtensionAdapter adapter = new SyndicationExtensionAdapter(navigator, settings); adapter.Fill(category); }
private void buttonNewCategory_Click(object sender, EventArgs e) { var rssg = new RssCategory(); var groupForm = new CategoryForm { RssCategory = rssg }; if (groupForm.ShowDialog(this) == DialogResult.OK) { Settings.RssCategories.Add(rssg); } }
/// <summary> /// Closes connection to file. /// </summary> /// <remarks> /// This method also releases any resources held while reading. /// </remarks> public void Close() { this.textInput = null; this.image = null; this.cloud = null; this.channel = null; this.source = null; this.enclosure = null; this.category = null; this.item = null; if (this.reader != null) { this.reader.Close(); this.reader = null; } this.elementText = null; this.xmlNodeStack = null; }
/// <summary> /// Initializes the supplied <see cref="RssItem"/> using the specified <see cref="XPathNavigator"/> and <see cref="XmlNamespaceManager"/>. /// </summary> /// <param name="item">The <see cref="RssItem"/> to be filled.</param> /// <param name="navigator">The <see cref="XPathNavigator"/> used to navigate the item XML data.</param> /// <param name="manager">The <see cref="XmlNamespaceManager"/> used to resolve XML namespace prefixes.</param> /// <param name="settings">The <see cref="SyndicationResourceLoadSettings"/> object used to configure the load operation.</param> /// <exception cref="ArgumentNullException">The <paramref name="item"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="navigator"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="manager"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="settings"/> is a null reference (Nothing in Visual Basic).</exception> private static void FillItem(RssItem item, XPathNavigator navigator, XmlNamespaceManager manager, SyndicationResourceLoadSettings settings) { Guard.ArgumentNotNull(item, "item"); Guard.ArgumentNotNull(navigator, "navigator"); Guard.ArgumentNotNull(manager, "manager"); Guard.ArgumentNotNull(settings, "settings"); XPathNavigator titleNavigator = navigator.SelectSingleNode("title", manager); XPathNavigator linkNavigator = navigator.SelectSingleNode("link", manager); XPathNavigator descriptionNavigator = navigator.SelectSingleNode("description", manager); XPathNavigator sourceNavigator = navigator.SelectSingleNode("source", manager); XPathNodeIterator enclosureIterator = navigator.Select("enclosure", manager); XPathNodeIterator categoryIterator = navigator.Select("category", manager); if (titleNavigator != null) { item.Title = titleNavigator.Value; } if (descriptionNavigator != null) { item.Description = descriptionNavigator.Value; } if (linkNavigator != null) { Uri link; if (Uri.TryCreate(linkNavigator.Value, UriKind.RelativeOrAbsolute, out link)) { item.Link = link; } } if (sourceNavigator != null) { item.Source = new RssSource(); if (sourceNavigator.HasAttributes) { string urlAttribute = sourceNavigator.GetAttribute("url", String.Empty); Uri url; if (Uri.TryCreate(urlAttribute, UriKind.RelativeOrAbsolute, out url)) { item.Source.Url = url; } } if (!String.IsNullOrEmpty(sourceNavigator.Value)) { item.Source.Title = sourceNavigator.Value; } } if (enclosureIterator != null && enclosureIterator.Count > 0) { while (enclosureIterator.MoveNext()) { RssEnclosure enclosure = new RssEnclosure(); Rss092SyndicationResourceAdapter.FillEnclosure(enclosure, enclosureIterator.Current, manager, settings); item.Enclosures.Add(enclosure); } } if (categoryIterator != null && categoryIterator.Count > 0) { while (categoryIterator.MoveNext()) { RssCategory category = new RssCategory(); Rss092SyndicationResourceAdapter.FillCategory(category, categoryIterator.Current, manager, settings); item.Categories.Add(category); } } SyndicationExtensionAdapter adapter = new SyndicationExtensionAdapter(navigator, settings); adapter.Fill(item); }
public void Category_Count() { var src = new RssCategory(GetInvoker()); Assert.That(src.Count, Is.EqualTo(0)); }
private RssRoot GetRssCore(string category, int maxDayCount, int maxEntryCount) { EntryCollection entries = null; //We only build the entries if blogcore doesn't exist and we'll need them later... if (_dataService.GetLastEntryUpdate() == DateTime.MinValue) { entries = BuildEntries(category, maxDayCount, maxEntryCount); } // TODO: Detecting modified data? //DateTime lastModified = this.GetLatestModifedEntryDateTime(entries); //if (SiteUtilities.GetStatusNotModified(lastModified)) // return null; RssRoot documentRoot = new RssRoot();; //However, if we made it this far, the not-modified check didn't work, and we may not have entries... if (entries == null) { entries = BuildEntries(category, maxDayCount, maxEntryCount); } documentRoot.Namespaces.Add("dc", "http://purl.org/dc/elements/1.1/"); documentRoot.Namespaces.Add("trackback", "http://madskills.com/public/xml/rss/module/trackback/"); documentRoot.Namespaces.Add("pingback", "http://madskills.com/public/xml/rss/module/pingback/"); if (_dasBlogSettings.SiteConfiguration.EnableComments) { documentRoot.Namespaces.Add("wfw", "http://wellformedweb.org/CommentAPI/"); documentRoot.Namespaces.Add("slash", "http://purl.org/rss/1.0/modules/slash/"); } if (_dasBlogSettings.SiteConfiguration.EnableGeoRss) { documentRoot.Namespaces.Add("georss", "http://www.georss.org/georss"); } RssChannel ch = new RssChannel(); if (category == null) { ch.Title = _dasBlogSettings.SiteConfiguration.Title; } else { ch.Title = _dasBlogSettings.SiteConfiguration.Title + " - " + category; } if (_dasBlogSettings.SiteConfiguration.Description == null || _dasBlogSettings.SiteConfiguration.Description.Trim().Length == 0) { ch.Description = _dasBlogSettings.SiteConfiguration.Subtitle; } else { ch.Description = _dasBlogSettings.SiteConfiguration.Description; } ch.Link = _dasBlogSettings.GetBaseUrl(); ch.Copyright = _dasBlogSettings.SiteConfiguration.Copyright; if (_dasBlogSettings.SiteConfiguration.RssLanguage != null && _dasBlogSettings.SiteConfiguration.RssLanguage.Length > 0) { ch.Language = _dasBlogSettings.SiteConfiguration.RssLanguage; } ch.ManagingEditor = _dasBlogSettings.SiteConfiguration.Contact; ch.WebMaster = _dasBlogSettings.SiteConfiguration.Contact; ch.Image = null; if (_dasBlogSettings.SiteConfiguration.ChannelImageUrl != null && _dasBlogSettings.SiteConfiguration.ChannelImageUrl.Trim().Length > 0) { newtelligence.DasBlog.Web.Services.Rss20.ChannelImage channelImage = new newtelligence.DasBlog.Web.Services.Rss20.ChannelImage(); channelImage.Title = ch.Title; channelImage.Link = ch.Link; if (_dasBlogSettings.SiteConfiguration.ChannelImageUrl.StartsWith("http")) { channelImage.Url = _dasBlogSettings.SiteConfiguration.ChannelImageUrl; } else { channelImage.Url = _dasBlogSettings.RelativeToRoot(_dasBlogSettings.SiteConfiguration.ChannelImageUrl); } ch.Image = channelImage; } documentRoot.Channels.Add(ch); foreach (Entry entry in entries) { if (entry.IsPublic == false || entry.Syndicated == false) { continue; } XmlDocument doc2 = new XmlDocument(); List <XmlElement> anyElements = new List <XmlElement>(); RssItem item = new RssItem(); item.Title = entry.Title; item.Guid = new newtelligence.DasBlog.Web.Services.Rss20.Guid(); item.Guid.IsPermaLink = false; item.Guid.Text = _dasBlogSettings.GetPermaLinkUrl(entry.EntryId); item.Link = _dasBlogSettings.GetPermaLinkUrl(entry.EntryId); User user = _dasBlogSettings.GetUser(entry.Author); XmlElement trackbackPing = doc2.CreateElement("trackback", "ping", "http://madskills.com/public/xml/rss/module/trackback/"); trackbackPing.InnerText = _dasBlogSettings.GetTrackbackUrl(entry.EntryId); anyElements.Add(trackbackPing); XmlElement pingbackServer = doc2.CreateElement("pingback", "server", "http://madskills.com/public/xml/rss/module/pingback/"); pingbackServer.InnerText = _dasBlogSettings.RelativeToRoot("pingback"); anyElements.Add(pingbackServer); XmlElement pingbackTarget = doc2.CreateElement("pingback", "target", "http://madskills.com/public/xml/rss/module/pingback/"); pingbackTarget.InnerText = _dasBlogSettings.GetPermaLinkUrl(entry.EntryId); anyElements.Add(pingbackTarget); XmlElement dcCreator = doc2.CreateElement("dc", "creator", "http://purl.org/dc/elements/1.1/"); if (user != null) { dcCreator.InnerText = user.DisplayName; } anyElements.Add(dcCreator); // Add GeoRSS if it exists. if (_dasBlogSettings.SiteConfiguration.EnableGeoRss) { Nullable <double> latitude = new Nullable <double>(); Nullable <double> longitude = new Nullable <double>(); if (entry.Latitude.HasValue) { latitude = entry.Latitude; } else { if (_dasBlogSettings.SiteConfiguration.EnableDefaultLatLongForNonGeoCodedPosts) { latitude = _dasBlogSettings.SiteConfiguration.DefaultLatitude; } } if (entry.Longitude.HasValue) { longitude = entry.Longitude; } else { if (_dasBlogSettings.SiteConfiguration.EnableDefaultLatLongForNonGeoCodedPosts) { longitude = _dasBlogSettings.SiteConfiguration.DefaultLongitude; } } if (latitude.HasValue && longitude.HasValue) { XmlElement geoLoc = doc2.CreateElement("georss", "point", "http://www.georss.org/georss"); geoLoc.InnerText = String.Format(CultureInfo.InvariantCulture, "{0:R} {1:R}", latitude, longitude); anyElements.Add(geoLoc); } } if (_dasBlogSettings.SiteConfiguration.EnableComments) { if (entry.AllowComments) { XmlElement commentApi = doc2.CreateElement("wfw", "comment", "http://wellformedweb.org/CommentAPI/"); commentApi.InnerText = _dasBlogSettings.GetCommentViewUrl(entry.EntryId); anyElements.Add(commentApi); } XmlElement commentRss = doc2.CreateElement("wfw", "commentRss", "http://wellformedweb.org/CommentAPI/"); commentRss.InnerText = _dasBlogSettings.GetEntryCommentsRssUrl(entry.EntryId); anyElements.Add(commentRss); //for RSS conformance per FeedValidator.org int commentsCount = _dataService.GetPublicCommentsFor(entry.EntryId).Count; if (commentsCount > 0) { XmlElement slashComments = doc2.CreateElement("slash", "comments", "http://purl.org/rss/1.0/modules/slash/"); slashComments.InnerText = commentsCount.ToString(); anyElements.Add(slashComments); } item.Comments = _dasBlogSettings.GetCommentViewUrl(entry.EntryId); } item.Language = entry.Language; if (entry.Categories != null && entry.Categories.Length > 0) { if (item.Categories == null) { item.Categories = new RssCategoryCollection(); } string[] cats = entry.Categories.Split(';'); foreach (string c in cats) { RssCategory cat = new RssCategory(); string cleanCat = c.Replace('|', '/'); cat.Text = cleanCat; item.Categories.Add(cat); } } if (entry.Attachments.Count > 0) { // RSS currently supports only a single enclsoure so we return the first one item.Enclosure = new Enclosure(); item.Enclosure.Url = entry.Attachments[0].Name; item.Enclosure.Type = entry.Attachments[0].Type; item.Enclosure.Length = entry.Attachments[0].Length.ToString(); } item.PubDate = entry.CreatedUtc.ToString("R"); if (ch.LastBuildDate == null || ch.LastBuildDate.Length == 0) { ch.LastBuildDate = item.PubDate; } if (!_dasBlogSettings.SiteConfiguration.AlwaysIncludeContentInRSS && entry.Description != null && entry.Description.Trim().Length > 0) { item.Description = PreprocessItemContent(entry.EntryId, entry.Description); } else { if (_dasBlogSettings.SiteConfiguration.HtmlTidyContent == false) { item.Description = "<div>" + PreprocessItemContent(entry.EntryId, entry.Content) + "</div>"; } else { item.Description = ContentFormatter.FormatContentAsHTML(PreprocessItemContent(entry.EntryId, entry.Content)); try { string xhtml = ContentFormatter.FormatContentAsXHTML(PreprocessItemContent(entry.EntryId, entry.Content)); doc2.LoadXml(xhtml); anyElements.Add((XmlElement)doc2.SelectSingleNode("//*[local-name() = 'body'][namespace-uri()='http://www.w3.org/1999/xhtml']")); } catch //(Exception ex) { //Debug.Write(ex.ToString()); // absorb } } } item.anyElements = anyElements.ToArray(); ch.Items.Add(item); } return(documentRoot); }
/// <summary> /// Searches for the specified RssCategory and returns the zero-based index of the first occurrence within the entire RssCategoryCollection. /// </summary> /// <param name="rssCategory"> The RssCategory to locate in the RssCategoryCollection. </param> /// <returns> The zero-based index of the first occurrence of RssCategory within the entire RssCategoryCollection, if found; otherwise, -1. </returns> public int IndexOf(RssCategory rssCategory) { return(this.List.IndexOf(rssCategory)); }
/// <summary> /// Determines whether the RssCategoryCollection contains a specific element. /// </summary> /// <param name="rssCategory"> The RssCategory to locate in the RssCategoryCollection. </param> /// <returns> true if the RssCategoryCollection contains the specified value; otherwise, false. </returns> public bool Contains(RssCategory rssCategory) { return(this.List.Contains(rssCategory)); }
/// <summary> /// Adds a specified category to this collection. /// </summary> /// <param name="rssCategory"> The category to add. </param> /// <returns> The zero-based index of the added category. </returns> public int Add(RssCategory rssCategory) { return(this.List.Add(rssCategory)); }
/// <summary> /// Removes a specified category from this collection. /// </summary> /// <param name="rssCategory"> The category to remove. </param> public void Remove(RssCategory rssCategory) { this.List.Remove(rssCategory); }
/// <summary> /// Inserts an category into this collection at a specified index. /// </summary> /// <param name="index"> The zero-based index of the collection at which to insert the category. </param> /// <param name="rssCategory"> The category to insert into this collection. </param> public void Insert(int index, RssCategory rssCategory) { this.List.Insert(index, rssCategory); }
/// <summary> /// Parse XML content from RSS feed /// </summary> /// <param name="html"></param> /// <param name="rssCategory"></param> /// <param name="rssWebsite"></param> private void ParseRss(string html, RssCategory rssCategory, RssWebsite rssWebsite) { var doc = new XmlDocument(); doc.LoadXml(html); var nodes = doc.SelectNodes("//item"); if (nodes == null) { return; } for (var i = nodes.Count - 1; i >= 0; i--) //get them in inverse order ( old items first { var rssItem = new RssItem { Category = rssCategory, Website = rssWebsite }; var xmlNode = nodes[i].SelectSingleNode("title"); if (xmlNode == null) { continue; } rssItem.Title = Utilities.CleanString(xmlNode.InnerText).Trim(); xmlNode = nodes[i].SelectSingleNode("link"); if (xmlNode == null) { continue; } rssItem.Link = xmlNode.InnerText; xmlNode = nodes[i].SelectSingleNode("description"); if (xmlNode == null) { continue; } rssItem.Description = Utilities.CleanString(xmlNode.InnerText).Trim(); xmlNode = nodes[i].SelectSingleNode("pubDate"); if (xmlNode != null) { var text = xmlNode.InnerText; if (Regex.IsMatch(text, "\\s[a-zA-Z]{3}$", RegexOptions.Multiline)) { text = text.Substring(0, text.Length - 4); } DateTime tempDateTime; if (DateTime.TryParse(text, new CultureInfo("en-US", false), DateTimeStyles.None, out tempDateTime)) { rssItem.PubDate = tempDateTime; } } xmlNode = nodes[i].SelectSingleNode("author"); if (xmlNode != null) { rssItem.Author = Utilities.CleanString(xmlNode.InnerText).Trim(); } xmlNode = nodes[i].SelectSingleNode("guid"); if (xmlNode != null) { rssItem.Guid = xmlNode.InnerText; } Logger.Info($"Retrieved RSS item \"{rssItem.Title}\" pub date {rssItem.PubDate} link {rssItem.Link}"); if (rssItem.PubDate > rssWebsite.LastUpdate) { Logger.Info($"Published RSS item \"{rssItem.Title}\" pub date {rssItem.PubDate} link {rssItem.Link}"); rssWebsite.LastUpdate = rssItem.PubDate; OnNewRss(rssItem); } } rssWebsite.FirstUpdate = false; }
public async Task <RssChannel> GetChannel(CancellationToken cancellationToken = default(CancellationToken)) { string username = contextAccessor.HttpContext.Request.Query["id"]; var channel = new RssChannel(); channel.Generator = "YInsights"; channel.Description = $"Feed for {username}"; channel.Title = "YInsights perosonalized feed"; channel.Language = new CultureInfo("en-US"); channel.PublicationDate = DateTime.Now; channel.TimeToLive = 5; var category = new RssCategory("articles"); channel.Categories.Add(category); channel.Image = new RssImage(new Uri("https://yinsights.torosent.com"), "YInsights", new Uri("https://yinsights.torosent.com/images/Logomakr_5r1SVn.png")); var baseUrl = string.Concat( contextAccessor.HttpContext.Request.Scheme, "://", contextAccessor.HttpContext.Request.Host.ToUriComponent() ); var feedUrl = string.Concat( contextAccessor.HttpContext.Request.Scheme, "://", contextAccessor.HttpContext.Request.Host.ToUriComponent(), contextAccessor.HttpContext.Request.PathBase.ToUriComponent(), contextAccessor.HttpContext.Request.Path.ToUriComponent(), contextAccessor.HttpContext.Request.QueryString.ToUriComponent()); channel.SelfLink = new Uri(feedUrl); channel.Link = channel.SelfLink; var items = new List <RssItem>(); var tuple = userArticleService.GetUserUnviewedArticles(username, null, null, -1, maxFeedItems); var articles = tuple.Item1.Take(maxFeedItems); foreach (var item in articles) { var rssItem = new RssItem(); rssItem.Author = "YInsights"; rssItem.Categories.Add(category); rssItem.Guid = new RssGuid(item.url, true); rssItem.Link = new Uri(item.url); rssItem.PublicationDate = ConvertExtentions.UnixTimeStampToDateTime(item.time); rssItem.Title = item.title; items.Add(rssItem); } channel.Items = items; return(channel); }
/// <summary> /// RSSを生成・取得する。 /// </summary> /// <param name="log">イベントログオブジェクト</param> /// <returns>RSS Feed</returns> internal static RssFeed GetFeed(EventLog log, Uri url, string type) { // エントリ取得最大数を決定 string maxLogEntryCountStr = ConfigurationManager.AppSettings["MaxLogEntryCount"]; int maxLogEntryCount = 100; int count = maxLogEntryCount; if (!string.IsNullOrEmpty(maxLogEntryCountStr) && int.TryParse(maxLogEntryCountStr, out count)) { maxLogEntryCount = count; } //イベントログ用の新規フィード作成 RssChannel channel = new RssChannel(); channel.Title = "EventLog(" + log.Log + ")"; channel.Description = log.LogDisplayName; channel.Link = url; //対象エントリを新しいものから全て抽出 //List<RssItem> itemList = new List<RssItem>(); count = 0; for (int i = log.Entries.Count - 1; i >= 0; i--) { EventLogEntry entry = log.Entries[i]; if (!EventLogUtil.IsVisible(entry, type)) { continue; } RssItem item = new RssItem(); item.Title = "[" + entry.EntryType.ToString() + "] " + entry.Source; item.PubDate = entry.TimeGenerated.ToUniversalTime(); if (!string.IsNullOrEmpty(entry.UserName)) { item.Author = entry.UserName; } item.Description = entry.Message; string query = entry.Source + " " + entry.Message; query = query.Replace('\n', ' '); if (query.Length > 127) { query = query.Substring(0, 127); } //query = Uri.EscapeUriString(query); //SecurityCenter%20Windows%20%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%20%E3%82%BB%E3%83%B3%E3%82%BF%E3%83%BC%20%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E9%96%8B%E5%A7%8B%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82 query = HttpUtility.UrlEncode(query); //SecurityCenter+Windows+%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3+%e3%82%bb%e3%83%b3%e3%82%bf%e3%83%bc+%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%82%92%e9%96%8b%e5%a7%8b%e3%81%97%e3%81%be%e3%81%97%e3%81%9f%e3%80%82 Debug.WriteLine("query : " + query); item.Link = new Uri("http://www.google.co.jp/search?q=" + query); RssGuid guid = new RssGuid(); guid.PermaLink = false; //とりあえず、発行時刻をglobally unique identifierに設定してみる guid.Name = entry.TimeGenerated.ToUniversalTime().ToString("yyyyMMdd_HHmmss.fff"); item.Guid = guid; RssCategory EntryType = new RssCategory(); EntryType.Domain = "EntryType"; EntryType.Name = entry.EntryType.ToString(); item.Categories.Add(EntryType); RssCategory Source = new RssCategory(); Source.Domain = "Source"; Source.Name = entry.Source; item.Categories.Add(Source); RssCategory Category = new RssCategory(); Category.Domain = "Category"; Category.Name = entry.Category; item.Categories.Add(Category); RssCategory InstanceId = new RssCategory(); InstanceId.Domain = "InstanceId"; InstanceId.Name = entry.InstanceId.ToString(); item.Categories.Add(InstanceId); channel.Items.Add(item); //itemList.Add(item); //指定最大数に達したら、抽出処理完了 if (++count >= maxLogEntryCount) { break; } } /* * //RSSオブジェクトに逆順で追加 * channel.Items.Capacity = itemList.Count; * for (int i = itemList.Count - 1; i >= 0; i--) * { * channel.Items.Add(itemList[i]); * } */ AddEmptyItemToEmptyChannel(channel); RssFeed feed = new RssFeed(Encoding.UTF8); feed.Channels.Add(channel); return(feed); }
private RssRoot GetRssCore(string category, int maxDayCount, int maxEntryCount) { if (RedirectToFeedBurnerIfNeeded(category) == true) { return(null); } EntryCollection entries = null; //We only build the entries if blogcore doesn't exist and we'll need them later... if (dataService.GetLastEntryUpdate() == DateTime.MinValue) { entries = BuildEntries(category, maxDayCount, maxEntryCount); } //Try to get out as soon as possible with as little CPU as possible if (inASMX) { DateTime lastModified = SiteUtilities.GetLatestModifedEntryDateTime(dataService, entries); if (SiteUtilities.GetStatusNotModified(lastModified)) { return(null); } } if (inASMX) { string referrer = Context.Request.UrlReferrer != null?Context.Request.UrlReferrer.AbsoluteUri:""; if (ReferralBlackList.IsBlockedReferrer(referrer)) { if (siteConfig.EnableReferralUrlBlackList404s) { return(null); } } else { loggingService.AddReferral( new LogDataItem( Context.Request.RawUrl, referrer, Context.Request.UserAgent, Context.Request.UserHostName)); } } //not-modified didn't work, do we have this in cache? string CacheKey = "Rss:" + category + ":" + maxDayCount.ToString() + ":" + maxEntryCount.ToString(); RssRoot documentRoot = cache[CacheKey] as RssRoot; if (documentRoot == null) //we'll have to build it... { //However, if we made it this far, the not-modified check didn't work, and we may not have entries... if (entries == null) { entries = BuildEntries(category, maxDayCount, maxEntryCount); } documentRoot = new RssRoot(); documentRoot.Namespaces.Add("dc", "http://purl.org/dc/elements/1.1/"); documentRoot.Namespaces.Add("trackback", "http://madskills.com/public/xml/rss/module/trackback/"); documentRoot.Namespaces.Add("pingback", "http://madskills.com/public/xml/rss/module/pingback/"); if (siteConfig.EnableComments) { documentRoot.Namespaces.Add("wfw", "http://wellformedweb.org/CommentAPI/"); documentRoot.Namespaces.Add("slash", "http://purl.org/rss/1.0/modules/slash/"); } if (siteConfig.EnableGeoRss) { documentRoot.Namespaces.Add("georss", "http://www.georss.org/georss"); } RssChannel ch = new RssChannel(); if (category == null) { ch.Title = siteConfig.Title; } else { ch.Title = siteConfig.Title + " - " + category; } if (siteConfig.Description == null || siteConfig.Description.Trim().Length == 0) { ch.Description = siteConfig.Subtitle; } else { ch.Description = siteConfig.Description; } ch.Link = SiteUtilities.GetBaseUrl(siteConfig); ch.Copyright = siteConfig.Copyright; if (siteConfig.RssLanguage != null && siteConfig.RssLanguage.Length > 0) { ch.Language = siteConfig.RssLanguage; } ch.ManagingEditor = siteConfig.Contact; ch.WebMaster = siteConfig.Contact; ch.Image = null; if (siteConfig.ChannelImageUrl != null && siteConfig.ChannelImageUrl.Trim().Length > 0) { ChannelImage channelImage = new ChannelImage(); channelImage.Title = ch.Title; channelImage.Link = ch.Link; if (siteConfig.ChannelImageUrl.StartsWith("http")) { channelImage.Url = siteConfig.ChannelImageUrl; } else { channelImage.Url = SiteUtilities.RelativeToRoot(siteConfig, siteConfig.ChannelImageUrl); } ch.Image = channelImage; } documentRoot.Channels.Add(ch); foreach (Entry entry in entries) { if (entry.IsPublic == false || entry.Syndicated == false) { continue; } XmlDocument doc2 = new XmlDocument(); List <XmlElement> anyElements = new List <XmlElement>(); RssItem item = new RssItem(); item.Title = entry.Title; item.Guid = new Rss20.Guid(); item.Guid.IsPermaLink = false; item.Guid.Text = SiteUtilities.GetPermaLinkUrl(siteConfig, entry.EntryId); item.Link = SiteUtilities.GetPermaLinkUrl(siteConfig, (ITitledEntry)entry); User user = SiteSecurity.GetUser(entry.Author); //Scott Hanselman: According to the RSS 2.0 spec and FeedValidator.org, // we can have EITHER an Author tag OR the preferred dc:creator tag, but NOT BOTH. // if (user != null && user.EmailAddress != null && user.EmailAddress.Length > 0) // { // if (user.DisplayName != null && user.DisplayName.Length > 0) // { // item.Author = String.Format("{0} ({1})", user.EmailAddress, user.DisplayName); // } // else // { // item.Author = user.EmailAddress; // } // } XmlElement trackbackPing = doc2.CreateElement("trackback", "ping", "http://madskills.com/public/xml/rss/module/trackback/"); trackbackPing.InnerText = SiteUtilities.GetTrackbackUrl(siteConfig, entry.EntryId); anyElements.Add(trackbackPing); XmlElement pingbackServer = doc2.CreateElement("pingback", "server", "http://madskills.com/public/xml/rss/module/pingback/"); pingbackServer.InnerText = new Uri(new Uri(SiteUtilities.GetBaseUrl(siteConfig)), "pingback.aspx").ToString(); anyElements.Add(pingbackServer); XmlElement pingbackTarget = doc2.CreateElement("pingback", "target", "http://madskills.com/public/xml/rss/module/pingback/"); pingbackTarget.InnerText = SiteUtilities.GetPermaLinkUrl(siteConfig, entry.EntryId); anyElements.Add(pingbackTarget); XmlElement dcCreator = doc2.CreateElement("dc", "creator", "http://purl.org/dc/elements/1.1/"); if (user != null) { // HACK AG No author e-mail address in feed items. // if (user.DisplayName != null && user.DisplayName.Length > 0) // { // if(user.EmailAddress != null && user.EmailAddress.Length > 0) // { // dcCreator.InnerText = String.Format("{0} ({1})", user.EmailAddress, user.DisplayName); // } // else // { dcCreator.InnerText = user.DisplayName; // } // } // else // { // dcCreator.InnerText = user.EmailAddress; // } } anyElements.Add(dcCreator); // Add GeoRSS if it exists. if (siteConfig.EnableGeoRss) { Nullable <double> latitude = new Nullable <double>(); Nullable <double> longitude = new Nullable <double>(); if (entry.Latitude.HasValue) { latitude = entry.Latitude; } else { if (siteConfig.EnableDefaultLatLongForNonGeoCodedPosts) { latitude = siteConfig.DefaultLatitude; } } if (entry.Longitude.HasValue) { longitude = entry.Longitude; } else { if (siteConfig.EnableDefaultLatLongForNonGeoCodedPosts) { longitude = siteConfig.DefaultLongitude; } } if (latitude.HasValue && longitude.HasValue) { XmlElement geoLoc = doc2.CreateElement("georss", "point", "http://www.georss.org/georss"); geoLoc.InnerText = String.Format(CultureInfo.InvariantCulture, "{0:R} {1:R}", latitude, longitude); anyElements.Add(geoLoc); } } if (siteConfig.EnableComments) { if (entry.AllowComments) { XmlElement commentApi = doc2.CreateElement("wfw", "comment", "http://wellformedweb.org/CommentAPI/"); commentApi.InnerText = SiteUtilities.GetCommentViewUrl(siteConfig, entry.EntryId); anyElements.Add(commentApi); } XmlElement commentRss = doc2.CreateElement("wfw", "commentRss", "http://wellformedweb.org/CommentAPI/"); commentRss.InnerText = SiteUtilities.GetEntryCommentsRssUrl(siteConfig, entry.EntryId); anyElements.Add(commentRss); //for RSS conformance per FeedValidator.org int commentsCount = dataService.GetPublicCommentsFor(entry.EntryId).Count; if (commentsCount > 0) { XmlElement slashComments = doc2.CreateElement("slash", "comments", "http://purl.org/rss/1.0/modules/slash/"); slashComments.InnerText = commentsCount.ToString(); anyElements.Add(slashComments); } item.Comments = SiteUtilities.GetCommentViewUrl(siteConfig, entry.EntryId); } item.Language = entry.Language; if (entry.Categories != null && entry.Categories.Length > 0) { if (item.Categories == null) { item.Categories = new RssCategoryCollection(); } string[] cats = entry.Categories.Split(';'); foreach (string c in cats) { RssCategory cat = new RssCategory(); string cleanCat = c.Replace('|', '/'); cat.Text = cleanCat; item.Categories.Add(cat); } } if (entry.Attachments.Count > 0) { // RSS currently supports only a single enclsoure so we return the first one item.Enclosure = new Enclosure(); item.Enclosure.Url = SiteUtilities.GetEnclosureLinkUrl(entry.EntryId, entry.Attachments[0]); item.Enclosure.Type = entry.Attachments[0].Type; item.Enclosure.Length = entry.Attachments[0].Length.ToString(); } item.PubDate = entry.CreatedUtc.ToString("R"); if (ch.LastBuildDate == null || ch.LastBuildDate.Length == 0) { ch.LastBuildDate = item.PubDate; } if (!siteConfig.AlwaysIncludeContentInRSS && entry.Description != null && entry.Description.Trim().Length > 0) { item.Description = PreprocessItemContent(entry.EntryId, entry.Description); } else { if (siteConfig.HtmlTidyContent == false) { item.Description = "<div>" + PreprocessItemContent(entry.EntryId, entry.Content) + "</div>"; } else { item.Description = ContentFormatter.FormatContentAsHTML(PreprocessItemContent(entry.EntryId, entry.Content)); try { string xhtml = ContentFormatter.FormatContentAsXHTML(PreprocessItemContent(entry.EntryId, entry.Content)); doc2.LoadXml(xhtml); anyElements.Add((XmlElement)doc2.SelectSingleNode("//*[local-name() = 'body'][namespace-uri()='http://www.w3.org/1999/xhtml']")); } catch //(Exception ex) { //Debug.Write(ex.ToString()); // absorb } } } item.anyElements = anyElements.ToArray(); ch.Items.Add(item); } cache.Insert(CacheKey, documentRoot, DateTime.Now.AddMinutes(5)); } return(documentRoot); }
/// <summary> /// Reads the next RssElement from the stream. /// </summary> /// <returns> An RSS Element </returns> /// <exception cref="InvalidOperationException">RssReader has been closed, and can not be read.</exception> /// <exception cref="System.IO.FileNotFoundException">RSS file not found.</exception> /// <exception cref="System.Xml.XmlException">Invalid XML syntax in RSS file.</exception> /// <exception cref="System.IO.EndOfStreamException">Unable to read an RssElement. Reached the end of the stream.</exception> public RssElement Read() { bool readData = false; RssElement rssElement = null; int lineNumber = -1; int linePosition = -1; if (this.reader == null) { throw new InvalidOperationException("RssReader has been closed, and can not be read."); } do { bool pushElement = true; try { readData = this.reader.Read(); } catch (EndOfStreamException e) { throw new EndOfStreamException("Unable to read an RssElement. Reached the end of the stream.", e); } catch (XmlException e) { if (lineNumber != -1 || linePosition != -1) { if (this.reader.LineNumber == lineNumber && this.reader.LinePosition == linePosition) { throw this.exceptions.LastException; } } lineNumber = this.reader.LineNumber; linePosition = this.reader.LinePosition; this.exceptions.Add(e); // just add to list of exceptions and continue :) } if (readData) { string readerName = this.reader.Name.ToLower(); switch (this.reader.NodeType) { case XmlNodeType.Element: { //if (reader.IsEmptyElement) // break; // doesnt take empty elements into account :/ this.elementText = new StringBuilder(); switch (readerName) { case "item": // is this the end of the channel element? (absence of </channel> before <item>) if (!this.wroteChannel) { this.wroteChannel = true; rssElement = this.channel; // return RssChannel readData = false; } this.item = new RssItem.RssItem(); // create new RssItem this.channel.Items.Add(this.item); break; case "source": this.source = new RssSource(); this.item.Source = this.source; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": try { this.source.Url = new Uri(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; } } break; case "enclosure": this.enclosure = new RssEnclosure(); this.item.Enclosure = this.enclosure; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": try { this.enclosure.Url = new Uri(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "length": try { this.enclosure.Length = int.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "type": this.enclosure.Type = this.reader.Value; break; } } break; case "guid": this.guid = new RssGuid(); this.item.Guid = this.guid; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "ispermalink": try { this.guid.PermaLink = bool.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; } } break; case "category": this.category = new RssCategory(); if ((string)this.xmlNodeStack.Peek() == "channel") { this.channel.Categories.Add(this.category); } else { this.item.Categories.Add(this.category); } for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "url": goto case "domain"; case "domain": this.category.Domain = this.reader.Value; break; } } break; case "channel": this.channel = new RssChannel.RssChannel(); this.textInput = null; this.image = null; this.cloud = null; this.source = null; this.enclosure = null; this.category = null; this.item = null; break; case "image": this.image = new RssImage(); this.channel.Image = this.image; break; case "textinput": this.textInput = new RssTextInput(); this.channel.TextInput = this.textInput; break; case "cloud": pushElement = false; this.cloud = new RssCloud(); this.channel.Cloud = this.cloud; for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); switch (this.reader.Name.ToLower()) { case "domain": this.cloud.Domain = this.reader.Value; break; case "port": try { this.cloud.Port = ushort.Parse(this.reader.Value); } catch (Exception e) { this.exceptions.Add(e); } break; case "path": this.cloud.Path = this.reader.Value; break; case "registerprocedure": this.cloud.RegisterProcedure = this.reader.Value; break; case "protocol": switch (this.reader.Value.ToLower()) { case "xml-rpc": this.cloud.Protocol = RssCloudProtocol.XmlRpc; break; case "soap": this.cloud.Protocol = RssCloudProtocol.Soap; break; case "http-post": this.cloud.Protocol = RssCloudProtocol.HttpPost; break; default: this.cloud.Protocol = RssCloudProtocol.Empty; break; } break; } } break; case "rss": for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); if (this.reader.Name.ToLower() == "version") { switch (this.reader.Value) { case "0.91": this.rssVersion = RssVersion.RSS091; break; case "0.92": this.rssVersion = RssVersion.RSS092; break; case "2.0": this.rssVersion = RssVersion.RSS20; break; default: this.rssVersion = RssVersion.NotSupported; break; } } } break; case "rdf": for (int i = 0; i < this.reader.AttributeCount; i++) { this.reader.MoveToAttribute(i); if (this.reader.Name.ToLower() == "version") { switch (this.reader.Value) { case "0.90": this.rssVersion = RssVersion.RSS090; break; case "1.0": this.rssVersion = RssVersion.RSS10; break; default: this.rssVersion = RssVersion.NotSupported; break; } } } break; } if (pushElement) { this.xmlNodeStack.Push(readerName); } break; } case XmlNodeType.EndElement: { if (this.xmlNodeStack.Count == 1) { break; } string childElementName = (string)this.xmlNodeStack.Pop(); string parentElementName = (string)this.xmlNodeStack.Peek(); switch (childElementName) // current element { // item classes case "item": rssElement = this.item; readData = false; break; case "source": this.source.Name = this.elementText.ToString(); rssElement = this.source; readData = false; break; case "enclosure": rssElement = this.enclosure; readData = false; break; case "guid": this.guid.Name = this.elementText.ToString(); rssElement = this.guid; readData = false; break; case "category": // parent is either item or channel this.category.Name = this.elementText.ToString(); rssElement = this.category; readData = false; break; // channel classes case "channel": if (this.wroteChannel) { this.wroteChannel = false; } else { this.wroteChannel = true; rssElement = this.channel; readData = false; } break; case "textinput": rssElement = this.textInput; readData = false; break; case "image": rssElement = this.image; readData = false; break; case "cloud": rssElement = this.cloud; readData = false; break; } switch (parentElementName) // parent element { case "item": switch (childElementName) { case "title": this.item.Title = this.elementText.ToString(); break; case "link": this.item.Link = new Uri(this.elementText.ToString()); break; case "description": this.item.Description = this.elementText.ToString(); break; case "author": this.item.Author = this.elementText.ToString(); break; case "comments": this.item.Comments = this.elementText.ToString(); break; case "pubdate": try { this.item.PubDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { try { string tmp = this.elementText.ToString(); tmp = tmp.Substring(0, tmp.Length - 5); tmp += "GMT"; this.item.PubDate = DateTime.Parse(tmp); } catch { this.exceptions.Add(e); } } break; } break; case "channel": switch (childElementName) { case "title": this.channel.Title = this.elementText.ToString(); break; case "link": try { this.channel.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "description": this.channel.Description = this.elementText.ToString(); break; case "language": this.channel.Language = this.elementText.ToString(); break; case "copyright": this.channel.Copyright = this.elementText.ToString(); break; case "managingeditor": this.channel.ManagingEditor = this.elementText.ToString(); break; case "webmaster": this.channel.WebMaster = this.elementText.ToString(); break; case "rating": this.channel.Rating = this.elementText.ToString(); break; case "pubdate": try { this.channel.PubDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "lastbuilddate": try { this.channel.LastBuildDate = DateTime.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "generator": this.channel.Generator = this.elementText.ToString(); break; case "docs": this.channel.Docs = this.elementText.ToString(); break; case "ttl": try { this.channel.TimeToLive = int.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "image": switch (childElementName) { case "url": try { this.image.Url = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "title": this.image.Title = this.elementText.ToString(); break; case "link": try { this.image.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "description": this.image.Description = this.elementText.ToString(); break; case "width": try { this.image.Width = Byte.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; case "height": try { this.image.Height = Byte.Parse(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "textinput": switch (childElementName) { case "title": this.textInput.Title = this.elementText.ToString(); break; case "description": this.textInput.Description = this.elementText.ToString(); break; case "name": this.textInput.Name = this.elementText.ToString(); break; case "link": try { this.textInput.Link = new Uri(this.elementText.ToString()); } catch (Exception e) { this.exceptions.Add(e); } break; } break; case "skipdays": if (childElementName == "day") { switch (this.elementText.ToString().ToLower()) { case "monday": this.channel.SkipDays[0] = true; break; case "tuesday": this.channel.SkipDays[1] = true; break; case "wednesday": this.channel.SkipDays[2] = true; break; case "thursday": this.channel.SkipDays[3] = true; break; case "friday": this.channel.SkipDays[4] = true; break; case "saturday": this.channel.SkipDays[5] = true; break; case "sunday": this.channel.SkipDays[6] = true; break; } } break; case "skiphours": if (childElementName == "hour") { this.channel.SkipHours[Byte.Parse(this.elementText.ToString().ToLower())] = true; } break; } break; } case XmlNodeType.Text: this.elementText.Append(this.reader.Value); break; case XmlNodeType.CDATA: this.elementText.Append(this.reader.Value); break; } } } while (readData); return(rssElement); }