├── icons ├── logs.ico ├── next.ico ├── folder.png ├── refresh.ico ├── rss_add.ico ├── rss_edit.ico ├── settings.ico ├── Shutdown(4).ico ├── downloadimgs.ico └── google_logo_24px.png ├── RealNews ├── app.ico ├── Resources │ ├── Cog.png │ ├── Edit.png │ ├── Eye.png │ ├── Image.png │ ├── Rss.png │ ├── Star1.png │ ├── logs.ico │ ├── next.ico │ ├── rss.gif │ ├── star.png │ ├── tray.ico │ ├── Image1.png │ ├── Search.png │ ├── TrashO.png │ ├── folder.png │ ├── refresh.ico │ ├── rss_add.ico │ ├── Compress.png │ ├── EyeSlash.png │ ├── FileTextO.png │ ├── PowerOff.png │ ├── news_new.ico │ ├── notfound.img │ ├── notfound.png │ ├── rss_edit.ico │ ├── settings.ico │ ├── Shutdown(4).ico │ ├── downloadimgs.ico │ ├── star_yellow.ico │ ├── trayhighlight.ico │ ├── light.css │ └── dark.css ├── HtmlAgilityPack │ ├── crc32.cs │ ├── HtmlEntity.cs │ ├── HtmlNode.cs │ ├── HtmlDocument.cs │ ├── HtmlNodeType.cs │ ├── HtmlTextNode.cs │ ├── HtmlAttribute.cs │ ├── HtmlCommentNode.cs │ ├── HtmlElementFlag.cs │ ├── HtmlNameTable.cs │ ├── HtmlParseError.cs │ ├── HtmlNodeNavigator.cs │ ├── NameValuePairList.cs │ ├── HtmlNodeCollection.cs │ ├── HtmlParseErrorCode.cs │ ├── EncodingFoundException.cs │ ├── HtmlAttributeCollection.cs │ ├── Utilities.cs │ ├── NameValuePair.cs │ └── HtmlNode.Xpath.cs ├── feedreader │ ├── Parser │ │ ├── IFeedParser.cs │ │ ├── AtomParser.cs │ │ ├── Rss10Parser.cs │ │ ├── Rss20Parser.cs │ │ ├── AbstractXmlFeedParser.cs │ │ ├── Rss091Parser.cs │ │ ├── Rss092Parser.cs │ │ ├── Factory.cs │ │ ├── Exceptions │ │ │ ├── InvalidFeedLinkException.cs │ │ │ └── FeedTypeNotSupportedException.cs │ │ └── FeedParser.cs │ ├── Feeds │ │ ├── Itunes │ │ │ ├── ItunesImage.cs │ │ │ ├── ItunesCategory.cs │ │ │ ├── ItunesOwner.cs │ │ │ ├── ItunesExtensions.cs │ │ │ ├── ItunesChannel.cs │ │ │ └── ItunesItem.cs │ │ ├── 0.92 │ │ │ ├── Rss092FeedImage.cs │ │ │ ├── Rss092FeedItem.cs │ │ │ └── Rss092Feed.cs │ │ ├── 2.0 │ │ │ ├── Rss20FeedImage.cs │ │ │ └── Rss20FeedItem.cs │ │ ├── 1.0 │ │ │ ├── Rss10FeedImage.cs │ │ │ ├── Rss10FeedTextInput.cs │ │ │ ├── Rss10FeedItem.cs │ │ │ └── Rss10Feed.cs │ │ ├── Base │ │ │ ├── FeedItemSource.cs │ │ │ ├── FeedImage.cs │ │ │ ├── FeedItemEnclosure.cs │ │ │ ├── FeedTextInput.cs │ │ │ ├── FeedCloud.cs │ │ │ ├── BaseFeedItem.cs │ │ │ └── BaseFeed.cs │ │ ├── Syndication.cs │ │ ├── 0.91 │ │ │ ├── Rss091FeedImage.cs │ │ │ └── Rss091FeedItem.cs │ │ ├── Atom │ │ │ ├── AtomPerson.cs │ │ │ ├── AtomLink.cs │ │ │ ├── AtomFeedItem.cs │ │ │ └── AtomFeed.cs │ │ └── DublinCore.cs │ ├── FeedType.cs │ ├── HtmlFeedLink.cs │ ├── FeedReader.cs │ ├── FeedItem.cs │ ├── Feed.cs │ └── Helpers.cs ├── fastJSON │ ├── Getters.cs │ ├── SafeDictionary.cs │ ├── Formatter.cs │ └── dynamic.cs ├── Properties │ ├── Settings.settings │ ├── AssemblyInfo.cs │ └── Settings.Designer.cs ├── Renderer │ ├── OfficeColorTable.cs │ ├── Office2007BlackColorTable.cs │ └── Office2007BlueColorTable.cs ├── Program.cs ├── Forms │ ├── frmLog.cs │ ├── mWebClient.cs │ ├── placeholdertextbox.cs │ ├── frmLog.Designer.cs │ ├── AboutBox1.cs │ ├── frmFeed.cs │ ├── frmSettings.cs │ ├── myListBox.cs │ ├── frmFeed.resx │ ├── frmLog.resx │ └── AboutBox1.resx ├── Settings.cs ├── Singleinstance.cs ├── Helper │ ├── Compiler.cs │ ├── RealNewsWeb.cs │ ├── Logger.cs │ ├── ImageCache.cs │ └── HtmlSanitizer.cs └── Entities.cs ├── README.md ├── RealNews.sln └── history.txt /icons/logs.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/logs.ico -------------------------------------------------------------------------------- /icons/next.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/next.ico -------------------------------------------------------------------------------- /RealNews/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/app.ico -------------------------------------------------------------------------------- /icons/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/folder.png -------------------------------------------------------------------------------- /icons/refresh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/refresh.ico -------------------------------------------------------------------------------- /icons/rss_add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/rss_add.ico -------------------------------------------------------------------------------- /icons/rss_edit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/rss_edit.ico -------------------------------------------------------------------------------- /icons/settings.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/settings.ico -------------------------------------------------------------------------------- /icons/Shutdown(4).ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/Shutdown(4).ico -------------------------------------------------------------------------------- /icons/downloadimgs.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/downloadimgs.ico -------------------------------------------------------------------------------- /RealNews/Resources/Cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Cog.png -------------------------------------------------------------------------------- /RealNews/Resources/Edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Edit.png -------------------------------------------------------------------------------- /RealNews/Resources/Eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Eye.png -------------------------------------------------------------------------------- /RealNews/Resources/Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Image.png -------------------------------------------------------------------------------- /RealNews/Resources/Rss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Rss.png -------------------------------------------------------------------------------- /RealNews/Resources/Star1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Star1.png -------------------------------------------------------------------------------- /RealNews/Resources/logs.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/logs.ico -------------------------------------------------------------------------------- /RealNews/Resources/next.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/next.ico -------------------------------------------------------------------------------- /RealNews/Resources/rss.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/rss.gif -------------------------------------------------------------------------------- /RealNews/Resources/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/star.png -------------------------------------------------------------------------------- /RealNews/Resources/tray.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/tray.ico -------------------------------------------------------------------------------- /icons/google_logo_24px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/icons/google_logo_24px.png -------------------------------------------------------------------------------- /RealNews/Resources/Image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Image1.png -------------------------------------------------------------------------------- /RealNews/Resources/Search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Search.png -------------------------------------------------------------------------------- /RealNews/Resources/TrashO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/TrashO.png -------------------------------------------------------------------------------- /RealNews/Resources/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/folder.png -------------------------------------------------------------------------------- /RealNews/Resources/refresh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/refresh.ico -------------------------------------------------------------------------------- /RealNews/Resources/rss_add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/rss_add.ico -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/crc32.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/crc32.cs -------------------------------------------------------------------------------- /RealNews/Resources/Compress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Compress.png -------------------------------------------------------------------------------- /RealNews/Resources/EyeSlash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/EyeSlash.png -------------------------------------------------------------------------------- /RealNews/Resources/FileTextO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/FileTextO.png -------------------------------------------------------------------------------- /RealNews/Resources/PowerOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/PowerOff.png -------------------------------------------------------------------------------- /RealNews/Resources/news_new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/news_new.ico -------------------------------------------------------------------------------- /RealNews/Resources/notfound.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/notfound.img -------------------------------------------------------------------------------- /RealNews/Resources/notfound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/notfound.png -------------------------------------------------------------------------------- /RealNews/Resources/rss_edit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/rss_edit.ico -------------------------------------------------------------------------------- /RealNews/Resources/settings.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/settings.ico -------------------------------------------------------------------------------- /RealNews/Resources/Shutdown(4).ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/Shutdown(4).ico -------------------------------------------------------------------------------- /RealNews/Resources/downloadimgs.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/downloadimgs.ico -------------------------------------------------------------------------------- /RealNews/Resources/star_yellow.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/star_yellow.ico -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlEntity.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlEntity.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNode.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlNode.cs -------------------------------------------------------------------------------- /RealNews/Resources/trayhighlight.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/Resources/trayhighlight.ico -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlDocument.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlDocument.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNodeType.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlNodeType.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlTextNode.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlTextNode.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlAttribute.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlAttribute.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlCommentNode.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlCommentNode.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlElementFlag.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlElementFlag.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNameTable.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlNameTable.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlParseError.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlParseError.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNodeNavigator.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlNodeNavigator.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/NameValuePairList.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/NameValuePairList.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNodeCollection.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlNodeCollection.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlParseErrorCode.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlParseErrorCode.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/EncodingFoundException.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/EncodingFoundException.cs -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlAttributeCollection.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgholam/RealNews/HEAD/RealNews/HtmlAgilityPack/HtmlAttributeCollection.cs -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/IFeedParser.cs: -------------------------------------------------------------------------------- 1 | using CodeHollow.FeedReader.Feeds; 2 | 3 | namespace CodeHollow.FeedReader.Parser 4 | { 5 | internal interface IFeedParser 6 | { 7 | BaseFeed Parse(string feedXml); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /RealNews/fastJSON/Getters.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace fastJSON 4 | { 5 | public sealed class DatasetSchema 6 | { 7 | public List Info ;//{ get; set; } 8 | public string Name ;//{ get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /RealNews/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RealNews/Renderer/OfficeColorTable.cs: -------------------------------------------------------------------------------- 1 | namespace BSE.Windows.Forms 2 | { 3 | /// 4 | /// Baseclass for a colortable for the 5 | /// 6 | public class OfficeColorTable : BSE.Windows.Forms.ProfessionalColorTable 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RealNews 2 | .net RSS reader 3 | 4 | ## Features 5 | - Single EXE file 6 | - Similar to FeedReader 7 | - No Database 8 | - Schedule download images 9 | - Limit image sizes on download 10 | - Update All on an interval 11 | - Update single feed on an interval 12 | - Import OPML files 13 | - Dark mode 14 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/AtomParser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System.Xml.Linq; 4 | using Feeds; 5 | 6 | internal class AtomParser : AbstractXmlFeedParser 7 | { 8 | public override BaseFeed Parse(string feedXml, XDocument feedDoc) 9 | { 10 | AtomFeed feed = new AtomFeed(feedXml, feedDoc.Root); 11 | return feed; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Rss10Parser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System.Xml.Linq; 4 | using Feeds; 5 | 6 | internal class Rss10Parser : AbstractXmlFeedParser 7 | { 8 | public override BaseFeed Parse(string feedXml, XDocument feedDoc) 9 | { 10 | var rdf = feedDoc.Root; 11 | var channel = rdf.GetElement("channel"); 12 | Rss10Feed feed = new Rss10Feed(feedXml, channel); 13 | return feed; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Rss20Parser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System.Xml.Linq; 4 | using Feeds; 5 | 6 | internal class Rss20Parser : AbstractXmlFeedParser 7 | { 8 | public override BaseFeed Parse(string feedXml, XDocument feedDoc) 9 | { 10 | var rss = feedDoc.Root; 11 | var channel = rss.GetElement("channel"); 12 | Rss20Feed feed = new Rss20Feed(feedXml, channel); 13 | return feed; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/AbstractXmlFeedParser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using Feeds; 4 | using System.Xml.Linq; 5 | 6 | internal abstract class AbstractXmlFeedParser : IFeedParser 7 | { 8 | public BaseFeed Parse(string feedXml) 9 | { 10 | XDocument feedDoc = XDocument.Parse(feedXml); 11 | 12 | return this.Parse(feedXml, feedDoc); 13 | } 14 | 15 | public abstract BaseFeed Parse(string feedXml, XDocument feedDoc); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Rss091Parser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System.Xml.Linq; 4 | using Feeds; 5 | 6 | internal class Rss091Parser : AbstractXmlFeedParser 7 | { 8 | public override BaseFeed Parse(string feedXml, XDocument feedDoc) 9 | { 10 | var rss = feedDoc.Root; 11 | var channel = rss.GetElement("channel"); 12 | Rss091Feed feed = new Rss091Feed(feedXml, channel); 13 | return feed; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Rss092Parser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System.Xml.Linq; 4 | using Feeds; 5 | 6 | internal class Rss092Parser : AbstractXmlFeedParser 7 | { 8 | public override BaseFeed Parse(string feedXml, XDocument feedDoc) 9 | { 10 | var rss = feedDoc.Root; 11 | var channel = rss.GetElement("channel"); 12 | Rss092Feed feed = new Rss092Feed(feedXml, channel); 13 | return feed; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Factory.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | internal static class Factory 4 | { 5 | public static AbstractXmlFeedParser GetParser(FeedType feedType) 6 | { 7 | switch (feedType) 8 | { 9 | case FeedType.Atom: return new AtomParser(); 10 | case FeedType.Rss_0_91: return new Rss091Parser(); 11 | case FeedType.Rss_0_92: return new Rss092Parser(); 12 | case FeedType.Rss_1_0: return new Rss10Parser(); 13 | default: return new Rss20Parser(); 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /RealNews/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("RealNews")] 5 | [assembly: AssemblyDescription("Real News - Rss Feed Reader")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("RealNews")] 9 | [assembly: AssemblyCopyright("Copyright © 2018-2020")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("20c9cf96-5c3b-4ad9-8a48-7dc174b184c8")] 16 | 17 | [assembly: AssemblyVersion("1.5.6.0")] 18 | [assembly: AssemblyFileVersion("1.5.6.0")] 19 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds.Itunes 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// The itunes:image xml element 7 | /// 8 | public class ItunesImage 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// The itunes:image element 14 | public ItunesImage(XElement image) 15 | { 16 | Href = image.GetAttributeValue("href"); 17 | } 18 | 19 | /// 20 | /// The value of the href attribute 21 | /// 22 | public string Href { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /RealNews/Resources/light.css: -------------------------------------------------------------------------------- 1 | /*------ LIGHT MODE ------*/ 2 | 3 | body { 4 | font-family: Tahoma; 5 | font-weight: normal; 6 | } 7 | 8 | .title { 9 | background-color: aliceblue; 10 | padding: 10px; 11 | margin-bottom: 15px; 12 | } 13 | 14 | .title h2 { 15 | font-weight: normal; 16 | } 17 | 18 | .title h2 a { 19 | text-decoration: none; 20 | } 21 | 22 | .title label { 23 | margin-left: 5px; 24 | margin-right: 5px; 25 | font-size: xx-small; 26 | } 27 | 28 | .extradata { 29 | background-color: whitesmoke; 30 | font-size: x-small; 31 | margin-top : 30px; 32 | } 33 | 34 | .extradata tr { 35 | padding: 5px; 36 | } 37 | 38 | .extradata td { 39 | padding: 5px; 40 | } 41 | 42 | .extradata td:first-child { 43 | vertical-align: top; 44 | text-align: end; 45 | } 46 | -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/Utilities.cs: -------------------------------------------------------------------------------- 1 | // Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators. 2 | // Website & Documentation: http://html-agility-pack.net 3 | // Forum & Issues: https://github.com/zzzprojects/html-agility-pack 4 | // License: https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE 5 | // More projects: http://www.zzzprojects.com/ 6 | // Copyright © ZZZ Projects Inc. 2014 - 2017. All rights reserved. 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | 11 | namespace HtmlAgilityPack 12 | { 13 | internal static class Utilities 14 | { 15 | public static TValue GetDictionaryValueOrDefault(Dictionary dict, TKey key, TValue defaultValue = default(TValue)) where TKey : class 16 | { 17 | TValue value; 18 | if (!dict.TryGetValue(key, out value)) 19 | return defaultValue; 20 | return value; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesCategory.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds.Itunes 2 | { 3 | /// 4 | /// The itunes:category element 5 | /// 6 | public class ItunesCategory 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// itunes:category element 11 | /// 12 | /// 13 | /// 14 | internal ItunesCategory(string text, ItunesCategory[] children) 15 | { 16 | Text = text; 17 | Children = children; 18 | } 19 | 20 | /// 21 | /// The text attribute 22 | /// 23 | public string Text { get; } 24 | 25 | /// 26 | /// All child itunes:category elements 27 | /// 28 | public ItunesCategory[] Children { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RealNews/Resources/dark.css: -------------------------------------------------------------------------------- 1 | /*------ DARK MODE ------*/ 2 | 3 | body { 4 | font-family: Tahoma; 5 | font-weight: normal; 6 | background-color: #202020; 7 | color : #bbb; 8 | } 9 | 10 | a { 11 | color : #c0c0ff; 12 | } 13 | 14 | .title { 15 | background-color: #555; 16 | padding: 10px; 17 | margin-bottom: 15px; 18 | } 19 | 20 | .title h2 { 21 | font-weight: normal; 22 | } 23 | 24 | .title h2 a { 25 | text-decoration: none; 26 | } 27 | 28 | .title label { 29 | margin-left: 5px; 30 | margin-right: 5px; 31 | font-size: xx-small; 32 | } 33 | 34 | .extradata { 35 | background-color: #333; 36 | font-size: x-small; 37 | margin-top : 30px; 38 | } 39 | 40 | .extradata tr { 41 | padding: 5px; 42 | } 43 | 44 | .extradata td { 45 | padding: 5px; 46 | } 47 | 48 | .extradata td:first-child { 49 | vertical-align: top; 50 | text-align: end; 51 | } 52 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesOwner.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds.Itunes 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// The itunes:owner xml element 7 | /// 8 | public class ItunesOwner 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | /// the owner xml element 14 | public ItunesOwner(XElement ownerElement) 15 | { 16 | Name = ownerElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "name"); 17 | Email = ownerElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "email"); 18 | } 19 | 20 | /// 21 | /// The itunes:email of the owner 22 | /// 23 | public string Email { get; } 24 | 25 | /// 26 | /// The itunes:name of the owner 27 | /// 28 | public string Name { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RealNews/feedreader/FeedType.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | /// 4 | /// The type of the feed (Rss 0.91, Rss 2.0, Atom, ...) 5 | /// 6 | public enum FeedType 7 | { 8 | /// 9 | /// Atom Feed 10 | /// 11 | Atom, 12 | 13 | /// 14 | /// Rss 0.91 feed 15 | /// 16 | Rss_0_91, 17 | 18 | /// 19 | /// Rss 0.92 feed 20 | /// 21 | Rss_0_92, 22 | 23 | /// 24 | /// Rss 1.0 feed 25 | /// 26 | Rss_1_0, 27 | 28 | /// 29 | /// Rss 2.0 fedd 30 | /// 31 | Rss_2_0, 32 | 33 | /// 34 | /// Rss feed - is used for type 35 | /// 36 | Rss, 37 | 38 | /// 39 | /// Unknown - default type 40 | /// 41 | Unknown 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/0.92/Rss092FeedImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Rss 0.92 Feed Image according to specification: http://backend.userland.com/rss092 7 | /// 8 | public class Rss092FeedImage : Rss091FeedImage 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// default constructor (for serialization) 13 | /// 14 | public Rss092FeedImage() 15 | : base() 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// Creates this object based on the xml in the XElement parameter. 22 | /// 23 | /// rss 0.92 image as xml 24 | public Rss092FeedImage(XElement element) 25 | : base(element) 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/2.0/Rss20FeedImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Rss 2.0 Image according to specification: https://validator.w3.org/feed/docs/rss2.html#ltimagegtSubelementOfLtchannelgt 7 | /// 8 | public class Rss20FeedImage : Rss091FeedImage 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// default constructor (for serialization) 13 | /// 14 | public Rss20FeedImage() 15 | : base() 16 | { 17 | } 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// Reads a rss 2.0 feed image based on the xml given in element 22 | /// 23 | /// feed image as xml 24 | public Rss20FeedImage(XElement element) 25 | : base(element) 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds.Itunes 2 | { 3 | /// 4 | /// Extension method that allows to access the itunes tags for a feed 5 | /// 6 | public static class ItunesExtensions 7 | { 8 | /// 9 | /// Returns the itunes elements of a rss feed 10 | /// 11 | /// the rss feed 12 | /// ItunesChannel object which contains itunes:... properties 13 | public static ItunesChannel GetItunesChannel(this Feed feed) 14 | { 15 | return new ItunesChannel(feed.SpecificFeed.Element); 16 | } 17 | 18 | /// 19 | /// Returns the itunes element of a rss feeditem 20 | /// 21 | /// the rss feed item 22 | /// ItunesItem object which contains itunes:... properties 23 | public static ItunesItem GetItunesItem(this FeedItem item) 24 | { 25 | return new ItunesItem(item.SpecificItem.Element); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RealNews.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealNews", "RealNews\RealNews.csproj", "{20C9CF96-5C3B-4AD9-8A48-7DC174B184C8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {20C9CF96-5C3B-4AD9-8A48-7DC174B184C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {20C9CF96-5C3B-4AD9-8A48-7DC174B184C8}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {20C9CF96-5C3B-4AD9-8A48-7DC174B184C8}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {20C9CF96-5C3B-4AD9-8A48-7DC174B184C8}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {4BD1726F-BF7C-40F8-8F15-5B1F89973D88} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /RealNews/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RealNews.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/NameValuePair.cs: -------------------------------------------------------------------------------- 1 | // Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators. 2 | // Website & Documentation: http://html-agility-pack.net 3 | // Forum & Issues: https://github.com/zzzprojects/html-agility-pack 4 | // License: https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE 5 | // More projects: http://www.zzzprojects.com/ 6 | // Copyright © ZZZ Projects Inc. 2014 - 2017. All rights reserved. 7 | 8 | #if METRO 9 | namespace HtmlAgilityPack 10 | { 11 | internal class NameValuePair 12 | { 13 | #region Fields 14 | 15 | internal readonly string Name; 16 | internal string Value; 17 | 18 | #endregion 19 | 20 | #region Constructors 21 | 22 | internal NameValuePair() 23 | { 24 | } 25 | 26 | internal NameValuePair(string name) 27 | : 28 | this() 29 | { 30 | Name = name; 31 | } 32 | 33 | internal NameValuePair(string name, string value) 34 | : 35 | this(name) 36 | { 37 | Value = value; 38 | } 39 | 40 | #endregion 41 | } 42 | } 43 | #endif -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Exceptions/InvalidFeedLinkException.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System; 4 | 5 | /// 6 | /// Exception is thrown if the html link element contains a feed type that does not exist. Feed types are rss or atom 7 | /// 8 | public sealed class InvalidFeedLinkException : Exception 9 | { 10 | /// 11 | /// Initializes a new InvalidFeedLinkException 12 | /// 13 | public InvalidFeedLinkException() { } 14 | 15 | /// 16 | /// Initializes a new InvalidFeedLinkException with a message 17 | /// 18 | /// custom error message 19 | public InvalidFeedLinkException(string message) : base(message) { } 20 | 21 | /// 22 | /// Initializes a new InvalidFeedLinkException with a message and an innerException 23 | /// 24 | /// custom error message 25 | /// the inner exception 26 | public InvalidFeedLinkException(string message, Exception innerException) : base(message, innerException) { } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/1.0/Rss10FeedImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Rss 1.0 Feed image according to specification: http://web.resource.org/rss/1.0/spec 7 | /// 8 | public class Rss10FeedImage : FeedImage 9 | { 10 | /// 11 | /// The "about" attribute of the element 12 | /// 13 | public string About { get; set; } 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// default constructor (for serialization) 18 | /// 19 | public Rss10FeedImage() 20 | : base() 21 | { 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// Reads a rss 1.0 feed image based on the xml given in element 27 | /// 28 | /// feed image as xml 29 | public Rss10FeedImage(XElement element) 30 | : base(element) 31 | { 32 | this.About = element.GetAttribute("rdf:about").GetValue(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/1.0/Rss10FeedTextInput.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Rss 1.0 Feed textinput according to specification: http://web.resource.org/rss/1.0/spec 7 | /// 8 | public class Rss10FeedTextInput : FeedTextInput 9 | { 10 | /// 11 | /// The "about" attribute of the element 12 | /// 13 | public string About { get; set; } 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// default constructor (for serialization) 18 | /// 19 | public Rss10FeedTextInput() 20 | : base() 21 | { 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// Reads a rss 1.0 textInput element based on the xml given in item 27 | /// 28 | /// about element as xml 29 | public Rss10FeedTextInput(XElement element) 30 | : base(element) 31 | { 32 | this.About = element.GetAttribute("rdf:about").GetValue(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RealNews/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Windows.Forms; 5 | 6 | namespace RealNews 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | private static ILog _log = LogManager.GetLogger(typeof(Program)); 14 | private static string _path; 15 | 16 | [STAThread] 17 | static void Main() 18 | { 19 | _path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 20 | if (_path.EndsWith("\\") == false) _path += "\\"; 21 | 22 | if (Singleinstance.Running(_path) == false) 23 | { 24 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 25 | 26 | Application.EnableVisualStyles(); 27 | Application.SetCompatibleTextRenderingDefault(false); 28 | Application.Run(new frmMain()); 29 | } 30 | } 31 | 32 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 33 | { 34 | File.AppendAllText("error.txt", e.ExceptionObject.ToString()); 35 | _log.Error(e); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /RealNews/Forms/frmLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace RealNews 11 | { 12 | public partial class frmLog : Form 13 | { 14 | public frmLog() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | private void button1_Click(object sender, EventArgs e) 20 | { 21 | refreshitems(); 22 | } 23 | 24 | private void refreshitems() 25 | { 26 | listBox1.BeginUpdate(); 27 | listBox1.Items.Clear(); 28 | 29 | listBox1.Items.AddRange(ConsoleLogger.Instance.GetLastLogs()); 30 | 31 | listBox1.EndUpdate(); 32 | } 33 | 34 | private void frmLog_Load(object sender, EventArgs e) 35 | { 36 | this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 37 | refreshitems(); 38 | } 39 | 40 | private void frmLog_KeyUp(object sender, KeyEventArgs e) 41 | { 42 | if (e.KeyCode == Keys.F5) 43 | refreshitems(); 44 | if (e.KeyCode == Keys.Escape) 45 | this.Close(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/FeedItemSource.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// item source object from rss 2.0 according to specification: https://validator.w3.org/feed/docs/rss2.html 7 | /// 8 | public class FeedItemSource 9 | { 10 | /// 11 | /// The "url" element 12 | /// 13 | public string Url { get; set; } 14 | 15 | /// 16 | /// The value of the element 17 | /// 18 | public string Value { get; set; } 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// default constructor (for serialization) 23 | /// 24 | public FeedItemSource() 25 | { 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// Reads a rss feed item based on the xml given in element 31 | /// 32 | /// item source element as xml 33 | public FeedItemSource(XElement element) 34 | { 35 | this.Url = element.GetAttributeValue("url"); 36 | this.Value = element.GetValue(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/Exceptions/FeedTypeNotSupportedException.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System; 4 | 5 | /// 6 | /// Exception is thrown if the type of the feed is not supported. Supported feed types 7 | /// are RSS 0.91, RSS 0.92, RSS 1.0, RSS 2.0 and ATOM 8 | /// 9 | public class FeedTypeNotSupportedException : Exception 10 | { 11 | /// 12 | /// Initializes a new FeedTypeNotSupportedException 13 | /// 14 | public FeedTypeNotSupportedException() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new FeedTypeNotSupportedException with a message 20 | /// 21 | /// custom error message 22 | public FeedTypeNotSupportedException(string message) : base(message) 23 | { 24 | } 25 | 26 | /// 27 | /// Initializes a new FeedTypeNotSupportedException with a message and an innerException 28 | /// 29 | /// custom error message 30 | /// the inner exception 31 | public FeedTypeNotSupportedException(string message, Exception innerException) : base(message, innerException) 32 | { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /RealNews/Forms/mWebClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace RealNews 5 | { 6 | public class mWebClient : WebClient 7 | { 8 | public mWebClient() 9 | { 10 | Timeout = 10 * 1000; 11 | if (Environment.OSVersion.Version.Major >= 6) // >XP 12 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;// KLUDGE : https security for .net 4 13 | base.Encoding = System.Text.Encoding.UTF8; 14 | if (Settings.UseSytemProxy) // else define a proxy 15 | Proxy = WebRequest.DefaultWebProxy; 16 | else if (Settings.CustomProxy != "") 17 | Proxy = new WebProxy(Settings.CustomProxy); 18 | 19 | Headers.Add("User-Agent: Other"); // for some sites that return 403 20 | } 21 | public int Timeout { get; set; } 22 | 23 | protected override WebRequest GetWebRequest(Uri uri) 24 | { 25 | WebRequest request = base.GetWebRequest(uri); 26 | var http = request as HttpWebRequest; 27 | if (http != null) 28 | { 29 | http.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 30 | http.ReadWriteTimeout = Timeout; 31 | } 32 | 33 | request.Timeout = Timeout; 34 | return request; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/FeedImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// feed image object that is used in feed (rss 0.91, 2.0, atom, ...) 7 | /// 8 | public class FeedImage 9 | { 10 | /// 11 | /// The "title" element 12 | /// 13 | public string Title { get; set; } 14 | 15 | /// 16 | /// The "url" element 17 | /// 18 | public string Url { get; set; } 19 | 20 | /// 21 | /// The "link" element 22 | /// 23 | public string Link { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// default constructor (for serialization) 28 | /// 29 | public FeedImage() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// Reads a feed image based on the xml given in element 36 | /// 37 | /// feed image as xml 38 | public FeedImage(XElement element) 39 | { 40 | this.Title = element.GetValue("title"); 41 | this.Url = element.GetValue("url"); 42 | this.Link = element.GetValue("link"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RealNews/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RealNews 4 | { 5 | public class Settings 6 | { 7 | public static int webport = 11111; 8 | 9 | public static int treeviewwidth = 200; 10 | 11 | public static int feeditemlistwidth = 400; 12 | 13 | public static bool Maximized = true; 14 | 15 | public static bool UseSytemProxy = true; 16 | 17 | public static int GlobalUpdateEveryMin = 4*60; 18 | 19 | public static int CleanupItemAfterDays = 14; 20 | 21 | public static int DownloadImagesUnderKB = 200; 22 | 23 | public static DateTime LastUpdateTime = DateTime.Now; 24 | 25 | public static string StartDownloadImgTime = "03:00"; 26 | public static string EndDownloadImgTime = "06:00"; 27 | 28 | public static int FeedUpdateTimeout = 5 * 60 * 1000; 29 | 30 | public static string CustomProxy = ""; 31 | 32 | public static bool OnCloseMinimize = true; 33 | 34 | public static int SkipFeedItemsDaysOlderThan = 10; 35 | 36 | public static bool DarkMode = false; 37 | 38 | //public static int DownloadImgThreads = 20; 39 | 40 | public static bool MGFeatures = false; 41 | } 42 | 43 | public static class myextension{ 44 | 45 | public static bool myContains(this string str, string val) 46 | { 47 | return str.IndexOf(val.ToLower(), StringComparison.OrdinalIgnoreCase) > -1; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /RealNews/fastJSON/SafeDictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace fastJSON 4 | { 5 | public sealed class SafeDictionary 6 | { 7 | private readonly object _Padlock = new object(); 8 | private readonly Dictionary _Dictionary; 9 | 10 | public SafeDictionary(int capacity) 11 | { 12 | _Dictionary = new Dictionary(capacity); 13 | } 14 | 15 | public SafeDictionary() 16 | { 17 | _Dictionary = new Dictionary(); 18 | } 19 | 20 | public bool TryGetValue(TKey key, out TValue value) 21 | { 22 | lock (_Padlock) 23 | return _Dictionary.TryGetValue(key, out value); 24 | } 25 | 26 | public int Count() 27 | { 28 | lock (_Padlock) return _Dictionary.Count; 29 | } 30 | 31 | public TValue this[TKey key] 32 | { 33 | get 34 | { 35 | lock (_Padlock) 36 | return _Dictionary[key]; 37 | } 38 | set 39 | { 40 | lock (_Padlock) 41 | _Dictionary[key] = value; 42 | } 43 | } 44 | 45 | public void Add(TKey key, TValue value) 46 | { 47 | lock (_Padlock) 48 | { 49 | if (_Dictionary.ContainsKey(key) == false) 50 | _Dictionary.Add(key, value); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /RealNews/feedreader/HtmlFeedLink.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | /// 4 | /// An html feed link, containing the title, the url and the type of the feed 5 | /// 6 | public class HtmlFeedLink 7 | { 8 | /// 9 | /// The title of the feed 10 | /// 11 | public string Title { get; set; } 12 | 13 | /// 14 | /// The url to the feed 15 | /// 16 | public string Url { get; set; } 17 | 18 | /// 19 | /// The type of the feed - rss or atom 20 | /// 21 | public FeedType FeedType { get; set; } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// default constructor (for serialization) 26 | /// 27 | public HtmlFeedLink() 28 | { 29 | } 30 | 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// Creates an html feed link item 34 | /// 35 | /// title fo the feed 36 | /// url of the feed 37 | /// type of the feed (rss 1.0, 2.0, ...) 38 | public HtmlFeedLink(string title, string url, FeedType feedtype) 39 | { 40 | this.Title = title; 41 | this.Url = url; 42 | this.FeedType = feedtype; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RealNews/Singleinstance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace RealNews 6 | { 7 | class Singleinstance 8 | { 9 | public static int _msgID; 10 | 11 | public static bool Running(string path) 12 | { 13 | var s = "RealNews|" + path; 14 | _msgID = RegisterWindowMessage(s); 15 | 16 | var name = Process.GetCurrentProcess().MainModule.ModuleName.Split('.')[0]; 17 | var pp = Process.GetProcessesByName(name); 18 | var found = 0; 19 | foreach (var pi in pp) 20 | { 21 | if (pi.MainModule.FileName.StartsWith(path)) 22 | { 23 | found++; 24 | BringProcessToFront(pi); 25 | } 26 | } 27 | 28 | return found > 1 ? true : false; 29 | } 30 | 31 | public static void BringProcessToFront(Process process) 32 | { 33 | IntPtr handle = process.MainWindowHandle; 34 | PostMessage((IntPtr)0xffff, _msgID, IntPtr.Zero, IntPtr.Zero); 35 | SetForegroundWindow(handle); 36 | } 37 | 38 | 39 | [DllImport("user32")] 40 | public static extern int RegisterWindowMessage(string message); 41 | [DllImport("user32")] 42 | public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); 43 | [DllImport("User32.dll")] 44 | private static extern bool SetForegroundWindow(IntPtr handle); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Syndication.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// The parsed syndication elements. Those are all elements that start with "sy:" 7 | /// 8 | public class Syndication 9 | { 10 | /// 11 | /// The "updatePeriod" element 12 | /// 13 | public string UpdatePeriod { get; set; } 14 | 15 | /// 16 | /// The "updateFrequency" element 17 | /// 18 | public string UpdateFrequency { get; set; } 19 | 20 | /// 21 | /// The "updateBase" element 22 | /// 23 | public string UpdateBase { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// default constructor (for serialization) 28 | /// 29 | public Syndication() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// Creates the object based on the xml in the given XElement 36 | /// 37 | /// syndication element as xml 38 | public Syndication(XElement xelement) 39 | { 40 | this.UpdateBase = xelement.GetValue("sy:updateBase"); 41 | this.UpdateFrequency = xelement.GetValue("sy:updateFrequency"); 42 | this.UpdatePeriod = xelement.GetValue("sy:updatePeriod"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/FeedItemEnclosure.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Enclosure object of Rss 2.0 according to specification: https://validator.w3.org/feed/docs/rss2.html 7 | /// 8 | public class FeedItemEnclosure 9 | { 10 | /// 11 | /// The "url" element 12 | /// 13 | public string Url { get; set; } 14 | 15 | /// 16 | /// The "length" element as int 17 | /// 18 | public int? Length { get; set; } 19 | 20 | /// 21 | /// The "type" element 22 | /// 23 | public string MediaType { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// default constructor (for serialization) 28 | /// 29 | public FeedItemEnclosure() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// Reads a rss feed item enclosure based on the xml given in element 36 | /// 37 | /// enclosure element as xml 38 | public FeedItemEnclosure(XElement element) 39 | { 40 | this.Url = element.GetAttributeValue("url"); 41 | this.Length = Helpers.TryParseInt(element.GetAttributeValue("length")); 42 | this.MediaType = element.GetAttributeValue("type"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/0.91/Rss091FeedImage.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Rss 0.91 Feed Image according to specification: http://www.rssboard.org/rss-0-9-1-netscape#image 7 | /// 8 | public class Rss091FeedImage : FeedImage 9 | { 10 | /// 11 | /// The "description" element 12 | /// 13 | public string Description { get; set; } 14 | 15 | /// 16 | /// The "width" element 17 | /// 18 | public int? Width { get; set; } 19 | 20 | /// 21 | /// The "height" element 22 | /// 23 | public int? Height { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// default constructor (for serialization) 28 | /// 29 | public Rss091FeedImage() 30 | : base() 31 | { 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// Creates this object based on the xml in the XElement parameter. 37 | /// 38 | /// feed image as xml 39 | public Rss091FeedImage(XElement element) 40 | : base(element) 41 | { 42 | this.Description = element.GetValue("description"); 43 | this.Width = Helpers.TryParseInt(element.GetValue("width")); 44 | this.Height = Helpers.TryParseInt(element.GetValue("height")); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/FeedTextInput.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// default text input object for Rss 0.91, 0.92, 1.0, 2.0 and ATOM 7 | /// 8 | public class FeedTextInput 9 | { 10 | /// 11 | /// The "title" element 12 | /// 13 | public string Title { get; set; } 14 | 15 | /// 16 | /// The "link" element 17 | /// 18 | public string Link { get; set; } 19 | 20 | /// 21 | /// The "description" field 22 | /// 23 | public string Description { get; set; } 24 | 25 | /// 26 | /// The "name" element 27 | /// 28 | public string Name { get; set; } 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// default constructor (for serialization) 33 | /// 34 | public FeedTextInput() 35 | { 36 | } 37 | 38 | /// 39 | /// Initializes a new instance of the class. 40 | /// Reads a rss textInput element based on the xml given in element 41 | /// 42 | /// text input element as xml 43 | public FeedTextInput(XElement element) 44 | { 45 | this.Title = element.GetValue("title"); 46 | this.Link = element.GetValue("link"); 47 | this.Description = element.GetValue("description"); 48 | this.Name = element.GetValue("name"); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/0.92/Rss092FeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Xml.Linq; 6 | 7 | /// 8 | /// Rss 0.92 feed item according to specification: http://backend.userland.com/rss092 9 | /// 10 | public class Rss092FeedItem : Rss091FeedItem 11 | { 12 | /// 13 | /// All entries "category" entries 14 | /// 15 | public ICollection Categories { get; set; } 16 | 17 | ///// 18 | ///// The "enclosure" field 19 | ///// 20 | //public FeedItemEnclosure Enclosure { get; set; } 21 | 22 | /// 23 | /// The "source" field 24 | /// 25 | public FeedItemSource Source { get; set; } 26 | 27 | /// 28 | /// Initializes a new instance of the class. 29 | /// default constructor (for serialization) 30 | /// 31 | public Rss092FeedItem() 32 | : base() 33 | { 34 | } 35 | 36 | /// 37 | /// Initializes a new instance of the class. 38 | /// Creates a new feed item element based on the given xml XELement 39 | /// 40 | /// the xml containing the feed item 41 | public Rss092FeedItem(XElement item) 42 | : base(item) 43 | { 44 | this.Enclosure = new FeedItemEnclosure(item.GetElement("enclosure")); 45 | this.Source = new FeedItemSource(item.GetElement("source")); 46 | 47 | var categories = item.GetElements("category"); 48 | this.Categories = categories.Select(x => x.GetValue()).ToList(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /RealNews/Forms/placeholdertextbox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | public class PlaceHolderTextBox : TextBox 6 | { 7 | 8 | bool isPlaceHolder = true; 9 | string _placeHolderText; 10 | public string PlaceHolderText 11 | { 12 | get { return _placeHolderText; } 13 | set 14 | { 15 | _placeHolderText = value; 16 | setPlaceholder(); 17 | } 18 | } 19 | 20 | public Color NormalColor; 21 | public Color HighlightColor; 22 | 23 | public new string Text 24 | { 25 | get => isPlaceHolder ? string.Empty : base.Text; 26 | set => base.Text = value; 27 | } 28 | 29 | //when the control loses focus, the placeholder is shown 30 | public void setPlaceholder() 31 | { 32 | if (string.IsNullOrEmpty(base.Text)) 33 | { 34 | base.Text = PlaceHolderText; 35 | this.ForeColor = NormalColor; 36 | this.Font = new Font(this.Font, FontStyle.Italic); 37 | isPlaceHolder = true; 38 | } 39 | } 40 | 41 | //when the control is focused, the placeholder is removed 42 | private void removePlaceHolder() 43 | { 44 | if (isPlaceHolder) 45 | { 46 | base.Text = ""; 47 | this.ForeColor = NormalColor; 48 | this.Font = new Font(this.Font, FontStyle.Regular); 49 | isPlaceHolder = false; 50 | } 51 | else 52 | { 53 | this.ForeColor = HighlightColor; 54 | } 55 | } 56 | public PlaceHolderTextBox() 57 | { 58 | GotFocus += removePlaceHolder; 59 | LostFocus += setPlaceholder; 60 | } 61 | 62 | private void setPlaceholder(object sender, EventArgs e) 63 | { 64 | setPlaceholder(); 65 | } 66 | 67 | private void removePlaceHolder(object sender, EventArgs e) 68 | { 69 | removePlaceHolder(); 70 | } 71 | } -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Atom/AtomPerson.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Atom 1.0 person element according to specification: https://validator.w3.org/feed/docs/atom.html 7 | /// 8 | public class AtomPerson 9 | { 10 | /// 11 | /// The "name" element 12 | /// 13 | public string Name { get; set; } 14 | 15 | /// 16 | /// The "email" element 17 | /// 18 | public string EMail { get; set; } 19 | 20 | /// 21 | /// The "uri" element 22 | /// 23 | public string Uri { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// default constructor (for serialization) 28 | /// 29 | public AtomPerson() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// Reads an atom person based on the xml given in element 36 | /// 37 | /// person element as xml 38 | public AtomPerson(XElement element) 39 | { 40 | this.Name = element.GetValue("name"); 41 | this.EMail = element.GetValue("email"); 42 | this.Uri = element.GetValue("uri"); 43 | } 44 | 45 | /// 46 | /// returns the name of the author including the email if available 47 | /// 48 | /// name of the author with email if available 49 | public override string ToString() 50 | { 51 | if (string.IsNullOrEmpty(this.EMail)) 52 | return this.Name; 53 | 54 | return $"{this.Name} <{this.EMail}>".Trim(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /RealNews/Helper/Compiler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom.Compiler; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Text; 6 | 7 | namespace RealNews 8 | { 9 | class Compiler 10 | { 11 | static MethodInfo _process = null; 12 | internal static string CompileAndRun(string codefilename, object[] methodparams) 13 | { 14 | if (_process == null) 15 | { 16 | // compile .cs file 17 | CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp"); 18 | 19 | CompilerParameters compilerparams = new CompilerParameters(); 20 | compilerparams.GenerateInMemory = true; 21 | compilerparams.GenerateExecutable = false; 22 | 23 | compilerparams.ReferencedAssemblies.Add(typeof(System.Text.RegularExpressions.Regex).Assembly.Location); 24 | 25 | string code = "using System; public class plugin{%CODE%}" 26 | .Replace("%CODE%", File.ReadAllText(codefilename)); 27 | 28 | CompilerResults results = compiler.CompileAssemblyFromSource(compilerparams, code); 29 | 30 | if (results.Errors.HasErrors == true) 31 | { 32 | StringBuilder sb = new StringBuilder(); 33 | foreach (var e in results.Errors) 34 | sb.AppendLine(e.ToString()); 35 | var s = sb.ToString(); 36 | throw new Exception(s); 37 | } 38 | else 39 | { 40 | _process = results.CompiledAssembly 41 | .GetType("plugin") 42 | .GetMethod("Process"); 43 | } 44 | } 45 | var res = (string)_process.Invoke(null, BindingFlags.Static, null, methodparams, null); 46 | return res; 47 | 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/FeedCloud.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Cloud object according to Rss 2.0 specification: https://validator.w3.org/feed/docs/rss2.html#ltcloudgtSubelementOfLtchannelgt 7 | /// 8 | public class FeedCloud 9 | { 10 | /// 11 | /// The "domain" element 12 | /// 13 | public string Domain { get; set; } 14 | 15 | /// 16 | /// The "port" element 17 | /// 18 | public string Port { get; set; } 19 | 20 | /// 21 | /// The "path" element 22 | /// 23 | public string Path { get; set; } 24 | 25 | /// 26 | /// The "registerProcedure" element 27 | /// 28 | public string RegisterProcedure { get; set; } 29 | 30 | /// 31 | /// The "protocol" element 32 | /// 33 | public string Protocol { get; set; } 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// default constructor (for serialization) 38 | /// 39 | public FeedCloud() 40 | { 41 | } 42 | 43 | /// 44 | /// Initializes a new instance of the class. 45 | /// Reads a rss feed cloud element based on the xml given in element 46 | /// 47 | /// cloud element as xml 48 | public FeedCloud(XElement element) 49 | { 50 | this.Domain = element.GetAttributeValue("domain"); 51 | this.Port = element.GetAttributeValue("port"); 52 | this.Path = element.GetAttributeValue("path"); 53 | this.RegisterProcedure = element.GetAttributeValue("registerProcedure"); 54 | this.Protocol = element.GetAttributeValue("protocol"); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/0.92/Rss092Feed.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Collections.Generic; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// Rss 0.92 feed according to specification: http://backend.userland.com/rss092 8 | /// 9 | public class Rss092Feed : Rss091Feed 10 | { 11 | /// 12 | /// The "cloud" field 13 | /// 14 | public FeedCloud Cloud { get; set; } 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// default constructor (for serialization) 19 | /// 20 | public Rss092Feed() 21 | : base() 22 | { 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// Reads a rss 0.92 feed based on the xml given in channel 28 | /// 29 | /// the entire feed xml as string 30 | /// the "channel" element in the xml as XElement 31 | public Rss092Feed(string feedXml, XElement channel) 32 | : base(feedXml, channel) 33 | { 34 | this.Cloud = new FeedCloud(channel.GetElement("cloud")); 35 | } 36 | 37 | /// 38 | internal override void AddItems(IEnumerable items) 39 | { 40 | foreach (var item in items) 41 | { 42 | this.Items.Add(new Rss092FeedItem(item)); 43 | } 44 | } 45 | 46 | /// 47 | /// Creates the base element out of this feed. 48 | /// 49 | /// feed 50 | public override Feed ToFeed() 51 | { 52 | var feed = base.ToFeed(); 53 | feed.SpecificFeed = this; 54 | feed.Type = FeedType.Rss_0_92; 55 | return feed; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/BaseFeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Collections.Generic; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// The base object for all feed items 8 | /// 9 | public abstract class BaseFeedItem 10 | { 11 | /// 12 | /// The "title" element 13 | /// 14 | public string Title { get; set; } // title 15 | 16 | /// 17 | /// The "link" element 18 | /// 19 | public string Link { get; set; } // link 20 | /// 21 | /// The "enclosure" field 22 | /// 23 | public FeedItemEnclosure Enclosure { get; set; } 24 | 25 | /// 26 | /// Gets the underlying XElement in order to allow reading properties that are not available in the class itself 27 | /// 28 | public XElement Element { get; } 29 | /// 30 | /// 31 | /// 32 | public Dictionary ExtraData { get; set; } 33 | 34 | internal abstract FeedItem ToFeedItem(); 35 | 36 | /// 37 | /// Initializes a new instance of the class. 38 | /// default constructor (for serialization) 39 | /// 40 | protected BaseFeedItem() 41 | { 42 | ExtraData = new Dictionary(); 43 | } 44 | 45 | /// 46 | /// Initializes a new instance of the class. 47 | /// Reads a base feed item based on the xml given in element 48 | /// 49 | /// feed item as xml 50 | protected BaseFeedItem(XElement item) 51 | { 52 | this.Title = item.GetValue("title"); 53 | this.Link = item.GetValue("link"); 54 | this.Element = item; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /history.txt: -------------------------------------------------------------------------------- 1 | v1.5.6 2 | - bug fixes 3 | 4 | v1.5.5 5 | - bug fix sorted feed items 6 | 7 | v1.5.4 8 | - replaced ListView with custom ListBox because of theme problems 9 | - image cache check for zero length files 10 | 11 | v1.5.3 12 | - caching compiled plugin MethodInfo 13 | - internal feature flag 14 | 15 | v1.5.2 16 | - bug fix running on Win7 17 | - check for 0 length images in cache 18 | 19 | v1.5.1 20 | - bug fix ensuring items are visible at the end of the feed list 21 | - memory cleanup on load and save feeds 22 | - bug fix running on WinXP 23 | 24 | v1.5.0 25 | - bug fix filtering old items when item does not provide a publish date 26 | - cleanup all, resets failed feed colours 27 | - added dark mode theme 28 | 29 | v1.4.4 30 | - add/edit feed form validation checks 31 | - added OnCloseMinimize config to close or minimize on form close click 32 | - adding a new feed with category updates the tree correctly 33 | - added SkipFeedItemsDaysOlderThan config for feeds that don't filter recent items when sending 34 | - singleton app now works correctly and opens existing window even if in tray 35 | 36 | v1.4.3.1 37 | - fixed tab orders in forms 38 | 39 | v1.4.3 40 | - added the use of a custom proxy 41 | - colour coding feeds in tree if failed to get data 42 | 43 | v1.4.2 44 | - search title pre-process plugin 45 | 46 | v1.4.1 47 | - added google search the feed item title in the toolbar 48 | - cleanup the UI style 49 | - updated to new zipstorer.cs 50 | 51 | v1.4 52 | - added alt+up and down to navigate the feed list 53 | - usability tweaks 54 | - fix for some sites returning 403 55 | 56 | v1.3 57 | - usability tweaks 58 | - check image already downloaded before downloading 59 | 60 | v1.2 61 | - code cleanup 62 | - added feed update timeout 63 | - local datetime in settings.config 64 | - download images method checks if already downloaded 65 | - selecting folder/category shows all feeds below it 66 | 67 | v1.1 68 | - upgrade to fastJSON v2.2.0 69 | - search clear button only if text entered 70 | - fix search and current unread count update 71 | - added cleanup image cache for orphan images 72 | 73 | v1.0 74 | - initial release -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/0.91/Rss091FeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// Rss 0.91 Feed Item according to specification: http://www.rssboard.org/rss-0-9-1-netscape#image 8 | /// 9 | public class Rss091FeedItem : BaseFeedItem 10 | { 11 | /// 12 | /// The "description" field 13 | /// 14 | public string Description { get; set; } // description 15 | 16 | /// 17 | /// The "pubDate" field 18 | /// 19 | public string PublishingDateString { get; set; } 20 | 21 | /// 22 | /// The "pubDate" field as DateTime. Null if parsing failed or pubDate is empty. 23 | /// 24 | public DateTime? PublishingDate { get; set; } 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// default constructor (for serialization) 29 | /// 30 | public Rss091FeedItem() 31 | : base() 32 | { 33 | } 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// Creates this object based on the xml in the XElement parameter. 38 | /// 39 | /// feed item as xml 40 | public Rss091FeedItem(XElement item) 41 | : base(item) 42 | { 43 | this.Description = item.GetValue("description"); 44 | this.PublishingDateString = item.GetValue("pubDate"); 45 | this.PublishingDate = Helpers.TryParseDateTime(this.PublishingDateString); 46 | } 47 | 48 | internal override FeedItem ToFeedItem() 49 | { 50 | FeedItem fi = new FeedItem(this) 51 | { 52 | Description = this.Description, 53 | PublishingDate = this.PublishingDate, 54 | PublishingDateString = this.PublishingDateString, 55 | Id = this.Link 56 | }; 57 | return fi; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Base/BaseFeed.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Collections.Generic; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// BaseFeed object which contains the basic properties that each feed has. 8 | /// 9 | public abstract class BaseFeed 10 | { 11 | /// 12 | /// creates the generic object. 13 | /// 14 | /// Feed 15 | public abstract Feed ToFeed(); 16 | 17 | /// 18 | /// The title of the feed 19 | /// 20 | public string Title { get; set; } 21 | 22 | /// 23 | /// The link (url) to the feed 24 | /// 25 | public string Link { get; set; } 26 | 27 | /// 28 | /// The items that are in the feed 29 | /// 30 | public ICollection Items { get; set; } 31 | 32 | /// 33 | /// Gets the whole, original feed as string 34 | /// 35 | public string OriginalDocument { get; private set; } 36 | 37 | /// 38 | /// Gets the underlying XElement in order to allow reading properties that are not available in the class itself 39 | /// 40 | public XElement Element { get; } 41 | 42 | /// 43 | /// Initializes a new instance of the class. 44 | /// default constructor (for serialization) 45 | /// 46 | protected BaseFeed() 47 | { 48 | this.Items = new List(); 49 | } 50 | 51 | /// 52 | /// Initializes a new instance of the class. 53 | /// Reads a base feed based on the xml given in element 54 | /// 55 | /// the entire feed xml as string 56 | /// the "channel" element in the xml as XElement 57 | protected BaseFeed(string feedXml, XElement channel) 58 | : this() 59 | { 60 | this.OriginalDocument = feedXml; 61 | 62 | this.Title = channel.GetValue("title"); 63 | this.Link = channel.GetValue("link"); 64 | this.Element = channel; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /RealNews/Entities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml.Serialization; 4 | 5 | namespace RealNews 6 | { 7 | public class Feed 8 | { 9 | public int id; 10 | public string URL = ""; 11 | public string Title = ""; 12 | public bool RTL; 13 | public bool DownloadImages = true; 14 | public int UpdateEveryMin = 0; // use global settings else e.g. 8*60 min 15 | public DateTime LastUpdate; 16 | public DateTime LastItemDate; 17 | public string LastError; 18 | public int UnreadCount = 0; 19 | public int StarredCount = 0; 20 | public bool feediconfailed = false; 21 | public bool ExcludeInCleanup = false; 22 | public string Folder = ""; 23 | 24 | public string FullTitle 25 | { 26 | get 27 | { 28 | if (Folder != "") 29 | return Folder + "/" + Title; 30 | else 31 | return "\uFFFC"+ "/" + Title; // no category to the end of sort 32 | 33 | } 34 | } 35 | } 36 | 37 | 38 | public class FeedItem 39 | { 40 | public string Title; 41 | public string Link; 42 | public string Categories; 43 | public DateTime date; 44 | public string Author; 45 | public string Id; 46 | 47 | public string Description; 48 | public string FeedName; 49 | public string Attachment; 50 | 51 | public bool isRead = false; 52 | public bool isStarred = false; 53 | [XmlIgnore] 54 | public bool RTL = false; 55 | 56 | public override string ToString() 57 | { 58 | return Title; 59 | } 60 | } 61 | 62 | class FeedItemComparer : IEqualityComparer 63 | { 64 | public bool Equals(FeedItem p1, FeedItem p2) 65 | { 66 | return p1.Title.ToLower() == p2.Title.ToLower(); 67 | } 68 | 69 | public int GetHashCode(FeedItem p) 70 | { 71 | return p.Title.ToLower().GetHashCode(); 72 | } 73 | } 74 | class FeedItemSort : IComparer 75 | { 76 | public int Compare(FeedItem x, FeedItem y) 77 | { 78 | return y.date.CompareTo(x.date); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /RealNews/Helper/RealNewsWeb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing.Imaging; 4 | using System.IO; 5 | using System.Net; 6 | 7 | namespace RealNews 8 | { 9 | class RealNewsWeb : CoreWebServer 10 | { 11 | public RealNewsWeb( 12 | int HttpPort, 13 | ImageCache imgcache, 14 | Func show 15 | ) : base(HttpPort, true, true, AuthenticationSchemes.Anonymous, "api", "main.html") 16 | { 17 | _imgcache = imgcache; 18 | _show = show; 19 | } 20 | private Func _show; 21 | private ImageCache _imgcache; 22 | 23 | public override void InitializeCommandHandler(Dictionary handler, Dictionary apihelp) 24 | { 25 | handler.Add("show", ctx => 26 | { 27 | OutPutContentType(ctx, ".html"); 28 | WriteResponse(ctx, 200, _show()); 29 | }); 30 | 31 | handler.Add("image", ctx => 32 | { 33 | string gstr = ctx.Request.Url.GetComponents(UriComponents.Query, UriFormat.Unescaped); 34 | byte[] o = Properties.Resources.notfound; 35 | if (_imgcache.Contains(gstr)) 36 | { 37 | o = _imgcache.Get(gstr); 38 | if (o == null) 39 | o = Properties.Resources.notfound; 40 | } 41 | WriteResponse(ctx, 200, o, false); 42 | }); 43 | } 44 | 45 | public override void ServeFile(HttpListenerContext ctx, string path) 46 | { 47 | if (path == "style.css") 48 | { 49 | OutPutContentType(ctx, ".css"); 50 | WriteResponse(ctx, 200, File.ReadAllText("configs\\style.css")); 51 | } 52 | else if (path == "api/star.png") 53 | { 54 | OutPutContentType(ctx, ".png"); 55 | var ms = new MemoryStream(); 56 | if (Settings.DarkMode) 57 | Properties.Resources.star1.Save(ms, ImageFormat.Png); 58 | else 59 | Properties.Resources.Star.Save(ms, ImageFormat.Png); 60 | WriteResponse(ctx, 200, ms.ToArray(), false); 61 | } 62 | else 63 | base.ServeFile(ctx, path); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /RealNews/feedreader/Parser/FeedParser.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Parser 2 | { 3 | using System; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// Internal FeedParser - returns the type of the feed or the parsed feed. 8 | /// 9 | internal static class FeedParser 10 | { 11 | /// 12 | /// Returns the feed type - rss 1.0, rss 2.0, atom, ... 13 | /// 14 | /// the xml document 15 | /// the feed type 16 | public static FeedType ParseFeedType(XDocument doc) 17 | { 18 | string rootElement = doc.Root.Name.LocalName; 19 | 20 | if (rootElement.EqualsIgnoreCase("feed")) 21 | return FeedType.Atom; 22 | 23 | if (rootElement.EqualsIgnoreCase("rdf")) 24 | return FeedType.Rss_1_0; 25 | 26 | if (rootElement.EqualsIgnoreCase("rss")) 27 | { 28 | string version = doc.Root.Attribute("version").Value; 29 | if (version.EqualsIgnoreCase("2.0")) 30 | return FeedType.Rss_2_0; 31 | 32 | if (version.EqualsIgnoreCase("0.91")) 33 | return FeedType.Rss_0_91; 34 | 35 | if (version.EqualsIgnoreCase("0.92")) 36 | return FeedType.Rss_0_92; 37 | 38 | return FeedType.Rss; 39 | } 40 | 41 | throw new FeedTypeNotSupportedException($"unknown feed type {rootElement}"); 42 | } 43 | 44 | /// 45 | /// Returns the parsed feed 46 | /// 47 | /// the feed document 48 | /// parsed feed 49 | public static Feed GetFeed(string feedContent) 50 | { 51 | feedContent = feedContent.Replace(((char)0x1C).ToString(), string.Empty); // replaces special char 0x1C, fixes issues with at least one feed 52 | feedContent = feedContent.Replace(((char)65279).ToString(), string.Empty); // replaces special char, fixes issues with at least one feed 53 | 54 | XDocument feedDoc = XDocument.Parse(feedContent); 55 | 56 | var feedType = ParseFeedType(feedDoc); 57 | 58 | var parser = Factory.GetParser(feedType); 59 | var feed = parser.Parse(feedContent); 60 | 61 | return feed.ToFeed(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Atom/AtomLink.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System.Xml.Linq; 4 | 5 | /// 6 | /// Atom 1.0 link according to specification: https://validator.w3.org/feed/docs/atom.html#link 7 | /// 8 | public class AtomLink 9 | { 10 | /// 11 | /// The "href" element 12 | /// 13 | public string Href { get; set; } 14 | 15 | /// 16 | /// The "rel" element 17 | /// 18 | public string Relation { get; set; } // rel 19 | 20 | /// 21 | /// The "type" element 22 | /// 23 | public string LinkType { get; set; } // type 24 | 25 | /// 26 | /// The "hreflang" element 27 | /// 28 | public string HrefLanguage { get; set; } // hreflang 29 | 30 | /// 31 | /// The "title" element 32 | /// 33 | public string Title { get; set; } 34 | 35 | /// 36 | /// The "length" elemnt as int 37 | /// 38 | public int? Length { get; set; } 39 | 40 | /// 41 | /// Initializes a new instance of the class. 42 | /// default constructor (for serialization) 43 | /// 44 | public AtomLink() 45 | { 46 | } 47 | 48 | /// 49 | /// Initializes a new instance of the class. 50 | /// Reads an atom link based on the xml given in element 51 | /// 52 | /// link as xml 53 | public AtomLink(XElement element) 54 | { 55 | this.Href = element.GetAttributeValue("href"); 56 | this.Relation = element.GetAttributeValue("rel"); 57 | this.LinkType = element.GetAttributeValue("type"); 58 | this.HrefLanguage = element.GetAttributeValue("hreflang"); 59 | this.Title = element.GetAttributeValue("title"); 60 | this.Length = Helpers.TryParseInt(element.GetAttributeValue("length")); 61 | } 62 | 63 | /// 64 | /// Returns the Href of the link 65 | /// 66 | /// the href of the link 67 | public override string ToString() 68 | { 69 | return this.Href; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/1.0/Rss10FeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// Rss 1.0 Feed Item according to specification: http://web.resource.org/rss/1.0/spec 8 | /// 9 | public class Rss10FeedItem : BaseFeedItem 10 | { 11 | /// 12 | /// The "about" attribute of the element 13 | /// 14 | public string About { get; set; } 15 | 16 | /// 17 | /// The "description" field 18 | /// 19 | public string Description { get; set; } 20 | 21 | /// 22 | /// All elements starting with "dc:" 23 | /// 24 | public DublinCore DC { get; set; } 25 | 26 | /// 27 | /// All elements starting with "sy:" 28 | /// 29 | public Syndication Sy { get; set; } 30 | 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// default constructor (for serialization) 34 | /// 35 | public Rss10FeedItem() 36 | : base() 37 | { 38 | } 39 | 40 | /// 41 | /// Initializes a new instance of the class. 42 | /// Reads a rss 1.0 feed item based on the xml given in item 43 | /// 44 | /// feed item as xml 45 | public Rss10FeedItem(XElement item) 46 | : base(item) 47 | { 48 | this.DC = new DublinCore(item); 49 | this.Sy = new Syndication(item); 50 | 51 | this.About = item.GetAttribute("rdf:about").GetValue(); 52 | this.Description = item.GetValue("description"); 53 | } 54 | 55 | /// 56 | internal override FeedItem ToFeedItem() 57 | { 58 | FeedItem f = new FeedItem(this); 59 | 60 | if (this.DC != null) 61 | { 62 | f.Author = this.DC.Publisher; 63 | f.Content = this.DC.Description; 64 | f.PublishingDate = this.DC.Date; 65 | f.PublishingDateString = this.DC.DateString; 66 | } 67 | 68 | f.Description = this.Description; 69 | if (string.IsNullOrEmpty(f.Content)) 70 | f.Content = this.Description; 71 | f.Id = this.Link; 72 | 73 | return f; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /RealNews/fastJSON/Formatter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace fastJSON 4 | { 5 | internal static class Formatter 6 | { 7 | private static string _indent = " "; 8 | 9 | public static void AppendIndent(StringBuilder sb, int count) 10 | { 11 | for (; count > 0; --count) sb.Append(_indent); 12 | } 13 | 14 | public static string PrettyPrint(string input) 15 | { 16 | return PrettyPrint(input, " "); 17 | } 18 | 19 | public static string PrettyPrint(string input, string spaces) 20 | { 21 | _indent = spaces; 22 | var output = new StringBuilder(); 23 | int depth = 0; 24 | int len = input.Length; 25 | char[] chars = input.ToCharArray(); 26 | for (int i = 0; i < len; ++i) 27 | { 28 | char ch = chars[i]; 29 | 30 | if (ch == '\"') // found string span 31 | { 32 | bool str = true; 33 | while (str) 34 | { 35 | output.Append(ch); 36 | ch = chars[++i]; 37 | if (ch == '\\') 38 | { 39 | output.Append(ch); 40 | ch = chars[++i]; 41 | } 42 | else if (ch == '\"') 43 | str = false; 44 | } 45 | } 46 | 47 | switch (ch) 48 | { 49 | case '{': 50 | case '[': 51 | output.Append(ch); 52 | output.AppendLine(); 53 | AppendIndent(output, ++depth); 54 | break; 55 | case '}': 56 | case ']': 57 | output.AppendLine(); 58 | AppendIndent(output, --depth); 59 | output.Append(ch); 60 | break; 61 | case ',': 62 | output.Append(ch); 63 | output.AppendLine(); 64 | AppendIndent(output, depth); 65 | break; 66 | case ':': 67 | output.Append(" : "); 68 | break; 69 | default: 70 | if (!char.IsWhiteSpace(ch)) 71 | output.Append(ch); 72 | break; 73 | } 74 | } 75 | 76 | return output.ToString(); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /RealNews/feedreader/FeedReader.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using Parser; 9 | 10 | /// 11 | /// The static FeedReader class which allows to read feeds from a given url. Use it to 12 | /// parse a feed from an url , a file 13 | /// or a string . If the feed url is not known, 14 | /// returns all feed links on a given page. 15 | /// 16 | /// 17 | /// var links = FeedReader.ParseFeedUrlsFromHtml("https://codehollow.com"); 18 | /// var firstLink = links.First(); 19 | /// var feed = FeedReader.Read(firstLink.Url); 20 | /// Console.WriteLine(feed.Title); 21 | /// 22 | public static class FeedReader 23 | { 24 | /// 25 | /// gets a url (with or without http) and returns the full url 26 | /// 27 | /// url with or without http 28 | /// full url 29 | /// GetUrl("codehollow.com"); => returns https://codehollow.com 30 | public static string GetAbsoluteUrl(string url) 31 | { 32 | return new UriBuilder(url).ToString(); 33 | } 34 | 35 | /// 36 | /// reads a feed from a file 37 | /// 38 | /// the path to the feed file 39 | /// parsed feed 40 | public static Feed ReadFromFile(string filePath) 41 | { 42 | string feedContent = System.IO.File.ReadAllText(filePath); 43 | return ReadFromString(feedContent); 44 | } 45 | 46 | /// 47 | /// reads a feed from the 48 | /// 49 | /// the feed content (xml) 50 | /// parsed feed 51 | public static Feed ReadFromString(string feedContent) 52 | { 53 | return FeedParser.GetFeed(feedContent); 54 | } 55 | 56 | /// 57 | /// read the rss feed type from the type statement of an html link 58 | /// 59 | /// application/rss+xml or application/atom+xml or ... 60 | /// the feed type 61 | private static FeedType GetFeedTypeFromLinkType(string linkType) 62 | { 63 | if (linkType.Contains("application/rss")) 64 | return FeedType.Rss; 65 | 66 | if (linkType.Contains("application/atom")) 67 | return FeedType.Atom; 68 | 69 | throw new InvalidFeedLinkException($"The link type '{linkType}' is not a valid feed link!"); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /RealNews/fastJSON/dynamic.cs: -------------------------------------------------------------------------------- 1 | #if NET4 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Dynamic; 6 | using System.Linq; 7 | 8 | namespace fastJSON 9 | { 10 | internal class DynamicJson : DynamicObject, IEnumerable 11 | { 12 | private IDictionary _dictionary { get; set; } 13 | private List _list { get; set; } 14 | 15 | public DynamicJson(string json) 16 | { 17 | var parse = fastJSON.JSON.Parse(json); 18 | 19 | if (parse is IDictionary) 20 | _dictionary = (IDictionary)parse; 21 | else 22 | _list = (List)parse; 23 | } 24 | 25 | private DynamicJson(object dictionary) 26 | { 27 | if (dictionary is IDictionary) 28 | _dictionary = (IDictionary)dictionary; 29 | } 30 | 31 | public override IEnumerable GetDynamicMemberNames() 32 | { 33 | return _dictionary.Keys.ToList(); 34 | } 35 | 36 | public override bool TryGetIndex(GetIndexBinder binder, Object[] indexes, out Object result) 37 | { 38 | var index = indexes[0]; 39 | if (index is int) 40 | { 41 | result = _list[(int) index]; 42 | } 43 | else 44 | { 45 | result = _dictionary[(string) index]; 46 | } 47 | if (result is IDictionary) 48 | result = new DynamicJson(result as IDictionary); 49 | return true; 50 | } 51 | 52 | public override bool TryGetMember(GetMemberBinder binder, out object result) 53 | { 54 | if (_dictionary.TryGetValue(binder.Name, out result) == false) 55 | if (_dictionary.TryGetValue(binder.Name.ToLowerInvariant(), out result) == false) 56 | return false;// throw new Exception("property not found " + binder.Name); 57 | 58 | if (result is IDictionary) 59 | { 60 | result = new DynamicJson(result as IDictionary); 61 | } 62 | else if (result is List) 63 | { 64 | List list = new List(); 65 | foreach (object item in (List)result) 66 | { 67 | if (item is IDictionary) 68 | list.Add(new DynamicJson(item as IDictionary)); 69 | else 70 | list.Add(item); 71 | } 72 | result = list; 73 | } 74 | 75 | return _dictionary.ContainsKey(binder.Name); 76 | } 77 | 78 | IEnumerator IEnumerable.GetEnumerator() 79 | { 80 | foreach(var o in _list) 81 | { 82 | yield return new DynamicJson(o as IDictionary); 83 | } 84 | } 85 | } 86 | } 87 | #endif -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/1.0/Rss10Feed.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Xml.Linq; 5 | 6 | /// 7 | /// Rss 1.0 Feed according to specification: http://web.resource.org/rss/1.0/spec 8 | /// 9 | public class Rss10Feed : BaseFeed 10 | { 11 | /// 12 | /// The "about" attribute of the element 13 | /// 14 | public string About { get; set; } 15 | 16 | /// 17 | /// All elements starting with "dc:" 18 | /// 19 | public DublinCore DC { get; set; } 20 | 21 | /// 22 | /// All elements starting with "sy:" 23 | /// 24 | public Syndication Sy { get; set; } 25 | 26 | /// 27 | /// The "description" field 28 | /// 29 | public string Description { get; set; } 30 | 31 | /// 32 | /// The "image" element 33 | /// 34 | public FeedImage Image { get; set; } 35 | 36 | /// 37 | /// The "textInput" element 38 | /// 39 | public FeedTextInput TextInput { get; set; } 40 | 41 | /// 42 | /// Initializes a new instance of the class. 43 | /// default constructor (for serialization) 44 | /// 45 | public Rss10Feed() 46 | : base() 47 | { 48 | } 49 | 50 | /// 51 | /// Initializes a new instance of the class. 52 | /// Reads a rss 1.0 feed based on the xml given in xelement 53 | /// 54 | /// the entire feed xml as string 55 | /// the "channel" element in the xml as XElement 56 | public Rss10Feed(string feedXml, XElement channel) 57 | : base(feedXml, channel) 58 | { 59 | this.About = channel.GetAttribute("rdf:about").GetValue(); 60 | this.DC = new DublinCore(channel); 61 | this.Sy = new Syndication(channel); 62 | this.Description = channel.GetValue("description"); 63 | 64 | this.Image = new Rss10FeedImage(channel.Parent.GetElement("image")); 65 | this.TextInput = new Rss10FeedTextInput(channel.Parent.GetElement("textinput")); 66 | 67 | var items = channel.Parent.GetElements("item"); 68 | foreach (var item in items) 69 | { 70 | this.Items.Add(new Rss10FeedItem(item)); 71 | } 72 | } 73 | 74 | /// 75 | /// Creates the base element out of this feed. 76 | /// 77 | /// feed 78 | public override Feed ToFeed() 79 | { 80 | Feed f = new Feed(this); 81 | 82 | if (this.DC != null) 83 | { 84 | f.Copyright = this.DC.Rights; 85 | f.Language = this.DC.Language; 86 | f.LastUpdatedDate = this.DC.Date; 87 | f.LastUpdatedDateString = this.DC.DateString; 88 | } 89 | 90 | f.Description = this.Description; 91 | f.ImageUrl = this.Image?.Url; 92 | f.Type = FeedType.Rss_1_0; 93 | 94 | return f; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /RealNews/feedreader/FeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | using Feeds; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | /// 8 | /// Generic feed item object that contains some basic properties. The feed item is typically 9 | /// an article or a blog post. If a property is not available 10 | /// for a specific feed type (e.g. Rss 1.0), then the property is empty. 11 | /// If a feed item has more properties, like the Generator property for Rss 2.0, then you can use 12 | /// the property. 13 | /// 14 | public class FeedItem 15 | { 16 | /// 17 | /// The title of the feed item 18 | /// 19 | public string Title { get; set; } 20 | 21 | /// 22 | /// The link (url) to the feed item 23 | /// 24 | public string Link { get; set; } 25 | 26 | /// 27 | /// The description of the feed item 28 | /// 29 | public string Description { get; set; } 30 | 31 | /// 32 | /// The publishing date as string. This is filled, if a publishing 33 | /// date is set - independent if it is a correct date or not 34 | /// 35 | public string PublishingDateString { get; set; } 36 | 37 | /// 38 | /// The published date as datetime. Null if parsing failed or if 39 | /// no publishing date is set. If null, please check property. 40 | /// 41 | public DateTime? PublishingDate { get; set; } 42 | 43 | /// 44 | /// The author of the feed item 45 | /// 46 | public string Author { get; set; } 47 | 48 | /// 49 | /// The id of the feed item 50 | /// 51 | public string Id { get; set; } 52 | 53 | /// 54 | /// The categories of the feeditem 55 | /// 56 | public List Categories { get; set; } 57 | 58 | /// 59 | /// The content of the feed item 60 | /// 61 | public string Content { get; set; } 62 | 63 | /// 64 | /// The parsed feed item element - e.g. of type which contains 65 | /// e.g. the Enclosure property which does not exist in other feed types. 66 | /// 67 | public BaseFeedItem SpecificItem { get; set; } 68 | 69 | /// 70 | /// Initializes a new instance of the class. 71 | /// Default constructor, just there for serialization. 72 | /// 73 | public FeedItem() 74 | { 75 | } 76 | 77 | /// 78 | /// Initializes a new instance of the class. 79 | /// Creates the generic feed item object based on a parsed 80 | /// 81 | /// BaseFeedItem which is a , , or another. 82 | public FeedItem(BaseFeedItem feedItem) 83 | { 84 | this.Title = feedItem.Title; 85 | this.Link = feedItem.Link; 86 | this.Categories = new List(); 87 | this.SpecificItem = feedItem; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /RealNews/Forms/frmLog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace RealNews 2 | { 3 | partial class frmLog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.button1 = new System.Windows.Forms.Button(); 32 | this.listBox1 = new System.Windows.Forms.ListBox(); 33 | this.SuspendLayout(); 34 | // 35 | // button1 36 | // 37 | this.button1.Location = new System.Drawing.Point(12, 12); 38 | this.button1.Name = "button1"; 39 | this.button1.Size = new System.Drawing.Size(89, 23); 40 | this.button1.TabIndex = 0; 41 | this.button1.Text = "Refresh (F5)"; 42 | this.button1.UseVisualStyleBackColor = true; 43 | this.button1.Click += new System.EventHandler(this.button1_Click); 44 | // 45 | // listBox1 46 | // 47 | this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 48 | | System.Windows.Forms.AnchorStyles.Left) 49 | | System.Windows.Forms.AnchorStyles.Right))); 50 | this.listBox1.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(178))); 51 | this.listBox1.FormattingEnabled = true; 52 | this.listBox1.ItemHeight = 15; 53 | this.listBox1.Location = new System.Drawing.Point(11, 45); 54 | this.listBox1.Name = "listBox1"; 55 | this.listBox1.Size = new System.Drawing.Size(800, 364); 56 | this.listBox1.TabIndex = 1; 57 | // 58 | // frmLog 59 | // 60 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 61 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 62 | this.ClientSize = new System.Drawing.Size(821, 420); 63 | this.Controls.Add(this.listBox1); 64 | this.Controls.Add(this.button1); 65 | this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(178))); 66 | this.KeyPreview = true; 67 | this.Name = "frmLog"; 68 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 69 | this.Text = "Log Messages"; 70 | this.TopMost = true; 71 | this.Load += new System.EventHandler(this.frmLog_Load); 72 | this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.frmLog_KeyUp); 73 | this.ResumeLayout(false); 74 | 75 | } 76 | 77 | #endregion 78 | 79 | private System.Windows.Forms.Button button1; 80 | private System.Windows.Forms.ListBox listBox1; 81 | } 82 | } -------------------------------------------------------------------------------- /RealNews/feedreader/Feed.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | using Feeds; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | /// 9 | /// Generic Feed object that contains some basic properties. If a property is not available 10 | /// for a specific feed type (e.g. Rss 1.0), then the property is empty. 11 | /// If a feed has more properties, like the Generator property for Rss 2.0, then you can use 12 | /// the property. 13 | /// 14 | public class Feed 15 | { 16 | /// 17 | /// The Type of the feed - Rss 2.0, 1.0, 0.92, Atom or others 18 | /// 19 | public FeedType Type { get; set; } 20 | 21 | /// 22 | /// The title of the field 23 | /// 24 | public string Title { get; set; } 25 | 26 | /// 27 | /// The link (url) to the feed 28 | /// 29 | public string Link { get; set; } 30 | 31 | /// 32 | /// The description of the feed 33 | /// 34 | public string Description { get; set; } 35 | 36 | /// 37 | /// The language of the feed 38 | /// 39 | public string Language { get; set; } 40 | 41 | /// 42 | /// The copyright of the feed 43 | /// 44 | public string Copyright { get; set; } 45 | 46 | /// 47 | /// The last updated date as string. This is filled, if a last updated 48 | /// date is set - independent if it is a correct date or not 49 | /// 50 | public string LastUpdatedDateString { get; set; } 51 | 52 | /// 53 | /// The last updated date as datetime. Null if parsing failed or if 54 | /// no last updated date is set. If null, please check property. 55 | /// 56 | public DateTime? LastUpdatedDate { get; set; } 57 | 58 | /// 59 | /// The url of the image 60 | /// 61 | public string ImageUrl { get; set; } 62 | 63 | /// 64 | /// List of items 65 | /// 66 | public ICollection Items { get; set; } 67 | 68 | /// 69 | /// Gets the whole, original feed as string 70 | /// 71 | public string OriginalDocument 72 | { 73 | get { return SpecificFeed.OriginalDocument; } 74 | } 75 | 76 | /// 77 | /// The parsed feed element - e.g. of type which contains 78 | /// e.g. the Generator property which does not exist in others. 79 | /// 80 | public BaseFeed SpecificFeed { get; set; } 81 | 82 | /// 83 | /// Initializes a new instance of the class. 84 | /// Default constructor, just there for serialization. 85 | /// 86 | public Feed() 87 | { 88 | } 89 | 90 | /// 91 | /// Initializes a new instance of the class. 92 | /// Creates the generic feed object based on a parsed BaseFeed 93 | /// 94 | /// BaseFeed which is a , , or another. 95 | public Feed(BaseFeed feed) 96 | { 97 | SpecificFeed = feed; 98 | 99 | Title = feed.Title; 100 | Link = feed.Link; 101 | 102 | Items = feed.Items.Select(x => x.ToFeedItem()).ToList(); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /RealNews/Forms/AboutBox1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Windows.Forms; 4 | 5 | namespace RealNews 6 | { 7 | partial class AboutBox1 : Form 8 | { 9 | public AboutBox1() 10 | { 11 | InitializeComponent(); 12 | this.Text = String.Format("About {0}", AssemblyTitle); 13 | this.labelProductName.Text = AssemblyProduct; 14 | this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion); 15 | this.labelCopyright.Text = AssemblyCopyright; 16 | this.labelCompanyName.Text = AssemblyCompany; 17 | this.textBoxDescription.Text = AssemblyDescription + 18 | @" 19 | 20 | Keyboard shortcuts : 21 | space = next unread 22 | alt+up = move to previous in list 23 | alt+down = move to next in list 24 | ctrl+d = delete selected items 25 | ctrl+g = search selected title in Google 26 | "; 27 | } 28 | 29 | #region Assembly Attribute Accessors 30 | 31 | public string AssemblyTitle 32 | { 33 | get 34 | { 35 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 36 | if (attributes.Length > 0) 37 | { 38 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; 39 | if (titleAttribute.Title != "") 40 | { 41 | return titleAttribute.Title; 42 | } 43 | } 44 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); 45 | } 46 | } 47 | 48 | public string AssemblyVersion 49 | { 50 | get 51 | { 52 | return Assembly.GetExecutingAssembly().GetName().Version.ToString(); 53 | } 54 | } 55 | 56 | public string AssemblyDescription 57 | { 58 | get 59 | { 60 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); 61 | if (attributes.Length == 0) 62 | { 63 | return ""; 64 | } 65 | return ((AssemblyDescriptionAttribute)attributes[0]).Description; 66 | } 67 | } 68 | 69 | public string AssemblyProduct 70 | { 71 | get 72 | { 73 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); 74 | if (attributes.Length == 0) 75 | { 76 | return ""; 77 | } 78 | return ((AssemblyProductAttribute)attributes[0]).Product; 79 | } 80 | } 81 | 82 | public string AssemblyCopyright 83 | { 84 | get 85 | { 86 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); 87 | if (attributes.Length == 0) 88 | { 89 | return ""; 90 | } 91 | return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; 92 | } 93 | } 94 | 95 | public string AssemblyCompany 96 | { 97 | get 98 | { 99 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 100 | if (attributes.Length == 0) 101 | { 102 | return ""; 103 | } 104 | return ((AssemblyCompanyAttribute)attributes[0]).Company; 105 | } 106 | } 107 | #endregion 108 | 109 | private void labelVersion_Click(object sender, EventArgs e) 110 | { 111 | 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesChannel.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds.Itunes 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Xml.Linq; 6 | 7 | /// 8 | /// The basic itunes: elements that are part of the channel xml element of an rss2.0 feed 9 | /// 10 | public class ItunesChannel 11 | { 12 | internal const string NAMESPACEPREFIX = "itunes"; 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// 17 | public ItunesChannel(XElement channelElement) 18 | { 19 | Author = channelElement.GetValue(NAMESPACEPREFIX, "author"); 20 | Block = channelElement.GetValue(NAMESPACEPREFIX, "block").EqualsIgnoreCase("yes"); 21 | Categories = GetItunesCategories(channelElement); 22 | 23 | var imageElement = channelElement.GetElement(NAMESPACEPREFIX, "image"); 24 | if (imageElement != null) 25 | { 26 | Image = new ItunesImage(imageElement); 27 | } 28 | 29 | var explicitValue = channelElement.GetValue(NAMESPACEPREFIX, "explicit"); 30 | Explicit = explicitValue.EqualsIgnoreCase("yes", "explicit", "true"); 31 | 32 | Complete = channelElement.GetValue(NAMESPACEPREFIX, "complete").EqualsIgnoreCase("yes"); 33 | 34 | if (Uri.TryCreate(channelElement.GetValue(NAMESPACEPREFIX, "new-feed-url"), UriKind.Absolute, out var newFeedUrl)) 35 | { 36 | NewFeedUrl = newFeedUrl; 37 | } 38 | 39 | var ownerElement = channelElement.GetElement(NAMESPACEPREFIX, "owner"); 40 | 41 | if (ownerElement != null) 42 | { 43 | Owner = new ItunesOwner(ownerElement); 44 | } 45 | 46 | Subtitle = channelElement.GetValue(NAMESPACEPREFIX, "subtitle"); 47 | Summary = channelElement.GetValue(NAMESPACEPREFIX, "summary"); 48 | } 49 | 50 | /// 51 | /// The itunes:author element 52 | /// 53 | public string Author { get; } 54 | 55 | /// 56 | /// The itunes:block element 57 | /// 58 | public bool Block { get; } 59 | 60 | /// 61 | /// The itunes:category elements 62 | /// 63 | public ItunesCategory[] Categories { get; } 64 | 65 | /// 66 | /// The itunes:image element 67 | /// 68 | public ItunesImage Image { get; } 69 | 70 | /// 71 | /// The itunes:explicit element 72 | /// 73 | public bool Explicit { get; } 74 | 75 | /// 76 | /// The itunes:complete element 77 | /// 78 | public bool Complete { get; } 79 | 80 | /// 81 | /// The itunes:new-feed-url element 82 | /// 83 | public Uri NewFeedUrl { get; } 84 | 85 | /// 86 | /// The itunes:owner element 87 | /// 88 | public ItunesOwner Owner { get; } 89 | 90 | /// 91 | /// The itunes:subtitle element 92 | /// 93 | public string Subtitle { get; } 94 | 95 | /// 96 | /// The itunes:summary element 97 | /// 98 | public string Summary { get; } 99 | 100 | /// 101 | /// Sets the itunes categories 102 | /// 103 | /// the channel element 104 | /// the itunes:categries 105 | private ItunesCategory[] GetItunesCategories(XElement element) 106 | { 107 | var query = from categoryElement in element.GetElements(NAMESPACEPREFIX, "category") 108 | let children = GetItunesCategories(categoryElement) 109 | select new ItunesCategory(categoryElement.GetAttributeValue("text"), children); 110 | 111 | return query.ToArray(); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/DublinCore.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | 5 | /// 6 | /// The parsed "dc:" elements in a feed 7 | /// 8 | public class DublinCore 9 | { 10 | /// 11 | /// The "title" element 12 | /// 13 | public string Title { get; set; } 14 | 15 | /// 16 | /// The "creator" element 17 | /// 18 | public string Creator { get; set; } 19 | 20 | /// 21 | /// The "subject" element 22 | /// 23 | public string Subject { get; set; } 24 | 25 | /// 26 | /// The "description" field 27 | /// 28 | public string Description { get; set; } 29 | 30 | /// 31 | /// The "publisher" element 32 | /// 33 | public string Publisher { get; set; } 34 | 35 | /// 36 | /// The "contributor" element 37 | /// 38 | public string Contributor { get; set; } 39 | 40 | /// 41 | /// The "date" element 42 | /// 43 | public string DateString { get; set; } 44 | 45 | /// 46 | /// The "date" element as datetime. Null if parsing failed or date is empty. 47 | /// 48 | public DateTime? Date { get; set; } 49 | 50 | /// 51 | /// The "type" element 52 | /// 53 | public string Type { get; set; } 54 | 55 | /// 56 | /// The "format" element 57 | /// 58 | public string Format { get; set; } 59 | 60 | /// 61 | /// The "identifier" element 62 | /// 63 | public string Identifier { get; set; } 64 | 65 | /// 66 | /// The "source" element 67 | /// 68 | public string Source { get; set; } 69 | 70 | /// 71 | /// The "language" element 72 | /// 73 | public string Language { get; set; } 74 | 75 | /// 76 | /// The "rel" element 77 | /// 78 | public string Relation { get; set; } 79 | 80 | /// 81 | /// The "coverage" element 82 | /// 83 | public string Coverage { get; set; } 84 | 85 | /// 86 | /// The "rights" element 87 | /// 88 | public string Rights { get; set; } 89 | 90 | /// 91 | /// Initializes a new instance of the class. 92 | /// default constructor (for serialization) 93 | /// 94 | public DublinCore() 95 | { 96 | } 97 | 98 | /// 99 | /// Initializes a new instance of the class. 100 | /// Reads a dublincore (dc:) element based on the xml given in element 101 | /// 102 | /// item element as xml 103 | public DublinCore(System.Xml.Linq.XElement item) 104 | { 105 | this.Title = item.GetValue("dc:title"); 106 | this.Creator = item.GetValue("dc:creator"); 107 | this.Subject = item.GetValue("dc:subject"); 108 | this.Description = item.GetValue("dc:description"); 109 | this.Publisher = item.GetValue("dc:publisher"); 110 | this.Contributor = item.GetValue("dc:contributor"); 111 | this.DateString = item.GetValue("dc:date"); 112 | this.Date = Helpers.TryParseDateTime(DateString); 113 | this.Type = item.GetValue("dc:type"); 114 | this.Format = item.GetValue("dc:format"); 115 | this.Identifier = item.GetValue("dc:identifier"); 116 | this.Source = item.GetValue("dc:source"); 117 | this.Language = item.GetValue("dc:language"); 118 | this.Relation = item.GetValue("dc:relation"); 119 | this.Coverage = item.GetValue("dc:coverage"); 120 | this.Rights = item.GetValue("dc:rights"); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Itunes/ItunesItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Linq; 3 | 4 | namespace CodeHollow.FeedReader.Feeds.Itunes 5 | { 6 | /// 7 | /// The itunes:... elements of an rss 2.0 item 8 | /// 9 | public class ItunesItem 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// 15 | public ItunesItem(XElement itemElement) 16 | { 17 | Author = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "author"); 18 | Block = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "block").EqualsIgnoreCase("yes"); 19 | var imageElement = itemElement.GetElement(ItunesChannel.NAMESPACEPREFIX, "image"); 20 | 21 | if (imageElement != null) 22 | { 23 | Image = new ItunesImage(imageElement); 24 | } 25 | 26 | var duration = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "duration"); 27 | Duration = ParseDuration(duration); 28 | 29 | var explicitValue = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "explicit"); 30 | Explicit = explicitValue.EqualsIgnoreCase("yes", "explicit", "true"); 31 | 32 | IsClosedCaptioned = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "isClosedCaptioned").EqualsIgnoreCase("yes"); 33 | 34 | if (int.TryParse(itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "order"), out var order)) 35 | { 36 | Order = order; 37 | } 38 | 39 | Subtitle = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "subtitle"); 40 | Summary = itemElement.GetValue(ItunesChannel.NAMESPACEPREFIX, "summary"); 41 | } 42 | 43 | private static TimeSpan? ParseDuration(string duration) 44 | { 45 | if (String.IsNullOrWhiteSpace(duration)) 46 | return null; 47 | 48 | var durationArray = duration.Split(':'); 49 | 50 | if (durationArray.Length == 1 && long.TryParse(durationArray[0], out long result)) 51 | { 52 | return TimeSpan.FromSeconds(result); 53 | } 54 | 55 | if (durationArray.Length == 2 && int.TryParse(durationArray[0], out int minutes) && 56 | int.TryParse(durationArray[1], out int seconds)) 57 | { 58 | return new TimeSpan(0, minutes, seconds); 59 | } 60 | 61 | if (durationArray.Length == 3 && int.TryParse(durationArray[0], out int hours) && 62 | int.TryParse(durationArray[1], out int min) && 63 | int.TryParse(durationArray[2], out int sec)) 64 | { 65 | return new TimeSpan(hours, min, sec); 66 | } 67 | 68 | return null; 69 | } 70 | 71 | /// 72 | /// The itunes:author element 73 | /// 74 | public string Author { get; } 75 | 76 | /// 77 | /// The itunes:block element 78 | /// 79 | public bool Block { get; } 80 | 81 | /// 82 | /// The itunes:image element 83 | /// 84 | public ItunesImage Image { get; } 85 | 86 | /// 87 | /// The itunes:duration element 88 | /// 89 | public TimeSpan? Duration { get; } 90 | 91 | /// 92 | /// The itunes:explicit element 93 | /// 94 | public bool Explicit { get; } 95 | 96 | /// 97 | /// The itunes:isClosedCaptioned element 98 | /// 99 | public bool IsClosedCaptioned { get; } 100 | 101 | /// 102 | /// The itunes:order element 103 | /// 104 | public int Order { get; } 105 | 106 | /// 107 | /// The itunes:subtitle element 108 | /// 109 | public string Subtitle { get; } 110 | 111 | /// 112 | /// The itunes:summary element 113 | /// 114 | public string Summary { get; } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /RealNews/Forms/frmFeed.cs: -------------------------------------------------------------------------------- 1 | using CodeHollow.FeedReader; 2 | using System; 3 | using System.Drawing; 4 | using System.Net; 5 | using System.Windows.Forms; 6 | 7 | namespace RealNews 8 | { 9 | public partial class frmFeed : Form 10 | { 11 | public frmFeed() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | public Feed feed; 17 | public Feed ret; 18 | bool _isdirty = false; 19 | 20 | private void button3_Click(object sender, EventArgs e) 21 | { 22 | cancelclose(); 23 | } 24 | 25 | private void cancelclose() 26 | { 27 | ret = feed; 28 | this.DialogResult = DialogResult.Cancel; 29 | this.Close(); 30 | } 31 | 32 | private void frmFeed_Load(object sender, EventArgs e) 33 | { 34 | this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 35 | if (feed == null) 36 | feed = new Feed(); 37 | 38 | txtURL.Text = feed.URL; 39 | txtName.Text = feed.Title; 40 | txtFolder.Text = feed.Folder; 41 | lblLastError.Text = feed.LastError; 42 | numUpdate.Value = feed.UpdateEveryMin <0?0:feed.UpdateEveryMin; 43 | chkRTL.Checked = feed.RTL; 44 | chkImages.Checked = feed.DownloadImages; 45 | chkExcludeCleanup.Checked = feed.ExcludeInCleanup; 46 | _isdirty = false; 47 | } 48 | 49 | private void button2_Click(object sender, EventArgs e) 50 | { 51 | var s = txtFolder.Text.ToLower(); 52 | 53 | if(txtName.Text.Trim() == "") 54 | { 55 | MessageBox.Show("Please enter a name for the feed"); 56 | txtName.Focus(); 57 | return; 58 | } 59 | if(s == "unread" || s== "starred" || s== "search results") 60 | { 61 | MessageBox.Show("Category can not be one of : \r\n\r\n Unread, Starred, Search Results"); 62 | txtFolder.Focus(); 63 | return; 64 | } 65 | if(s.Contains("\\") || s.Contains("/")) 66 | { 67 | MessageBox.Show("Sub folders are not supported yet"); 68 | txtFolder.Focus(); 69 | return; 70 | } 71 | // save button 72 | ret = new Feed 73 | { 74 | Title = txtName.Text, 75 | URL = txtURL.Text, 76 | DownloadImages = chkImages.Checked, 77 | RTL = chkRTL.Checked, 78 | UpdateEveryMin = (int)numUpdate.Value, 79 | ExcludeInCleanup = chkExcludeCleanup.Checked, 80 | Folder = txtFolder.Text.Replace("\\", "/") 81 | }; 82 | 83 | this.DialogResult = DialogResult.OK; 84 | this.Close(); 85 | } 86 | 87 | private void button1_Click(object sender, EventArgs e) 88 | { 89 | // read feed header info 90 | txtName.Text = GetInfo(txtURL.Text); 91 | } 92 | 93 | private string GetInfo(string url) 94 | { 95 | try 96 | { 97 | //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; 98 | mWebClient wc = new mWebClient(); 99 | 100 | var feedxml = wc.DownloadString(url); 101 | var reader = FeedReader.ReadFromString(feedxml); 102 | return reader.Title; 103 | } 104 | catch (Exception ex) 105 | { 106 | MessageBox.Show(ex.Message, "Error"); 107 | return ""; 108 | } 109 | } 110 | 111 | private void button4_Click(object sender, EventArgs e) 112 | { 113 | ret = null; 114 | this.DialogResult = DialogResult.OK; 115 | this.Close(); 116 | } 117 | 118 | private void frmFeed_KeyUp(object sender, KeyEventArgs e) 119 | { 120 | if (_isdirty == false && e.KeyCode == Keys.Escape) 121 | cancelclose(); 122 | } 123 | 124 | private void txtURL_TextChanged(object sender, EventArgs e) 125 | { 126 | _isdirty = true; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /RealNews/Forms/frmSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | 7 | namespace RealNews 8 | { 9 | public partial class frmSettings : Form 10 | { 11 | public frmSettings() 12 | { 13 | InitializeComponent(); 14 | } 15 | bool _isdirty = false; 16 | 17 | private void frmSettings_Load(object sender, EventArgs e) 18 | { 19 | this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 20 | 21 | // setup form 22 | chkUseSystemProxy.Checked = Settings.UseSytemProxy; 23 | numUpdate.Value = Settings.GlobalUpdateEveryMin; 24 | numWebPort.Value = Settings.webport; 25 | numDownloadSize.Value = Settings.DownloadImagesUnderKB; 26 | txtStart.Text = Settings.StartDownloadImgTime; 27 | txtEnd.Text = Settings.EndDownloadImgTime; 28 | lblLastUpdated.Text = Settings.LastUpdateTime.ToLongTimeString(); 29 | numCleaupDays.Value = Settings.CleanupItemAfterDays; 30 | maskedTextBox1.Text = Settings.LastUpdateTime.ToLongTimeString(); 31 | txtCustomProxy.Text = Settings.CustomProxy.Trim(); 32 | chkCloseOnMinimize.Checked = Settings.OnCloseMinimize; 33 | numSkipFeedItems.Value = Settings.SkipFeedItemsDaysOlderThan; 34 | chkDarkMode.Checked = Settings.DarkMode; 35 | 36 | txtCustomProxy.Enabled = true; 37 | if (chkUseSystemProxy.Checked) 38 | txtCustomProxy.Enabled = false; 39 | 40 | _isdirty = false; 41 | } 42 | 43 | private void button3_Click(object sender, EventArgs e) 44 | { 45 | cancelclose(); 46 | } 47 | 48 | private void cancelclose() 49 | { 50 | this.DialogResult = DialogResult.Cancel; 51 | this.Close(); 52 | } 53 | 54 | private void button2_Click(object sender, EventArgs e) 55 | { 56 | try 57 | { 58 | Settings.UseSytemProxy = chkUseSystemProxy.Checked; 59 | Settings.GlobalUpdateEveryMin = (int)numUpdate.Value; 60 | Settings.webport = (int)numWebPort.Value; 61 | Settings.DownloadImagesUnderKB = (int)numDownloadSize.Value; 62 | Settings.CleanupItemAfterDays = (int)numCleaupDays.Value; 63 | Settings.CustomProxy = txtCustomProxy.Text.Trim(); 64 | Settings.OnCloseMinimize = chkCloseOnMinimize.Checked; 65 | Settings.SkipFeedItemsDaysOlderThan = (int)numSkipFeedItems.Value; 66 | Settings.DarkMode = chkDarkMode.Checked; 67 | 68 | var st = TimeSpan.Parse(txtStart.Text); 69 | var ed = TimeSpan.Parse(txtEnd.Text); 70 | // validate start end times 71 | if (st < ed) 72 | { 73 | Settings.StartDownloadImgTime = txtStart.Text; 74 | Settings.EndDownloadImgTime = txtEnd.Text; 75 | 76 | DialogResult = DialogResult.OK; 77 | 78 | this.Close(); 79 | } 80 | else 81 | MessageBox.Show("Start Time must be less than End Time"); 82 | } 83 | catch 84 | { 85 | MessageBox.Show("Invalid settings"); 86 | } 87 | } 88 | 89 | private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 90 | { 91 | if (chkDarkMode.Checked) 92 | Process.Start("notepad.exe", "configs/dark.css"); 93 | else 94 | Process.Start("notepad.exe", "configs/light.css"); 95 | } 96 | 97 | private void frmSettings_KeyUp(object sender, KeyEventArgs e) 98 | { 99 | if (_isdirty == false && e.KeyCode == Keys.Escape) 100 | cancelclose(); 101 | } 102 | 103 | private void chkUseSystemProxy_CheckedChanged(object sender, EventArgs e) 104 | { 105 | _isdirty = true; 106 | 107 | txtCustomProxy.Enabled = true; 108 | if (chkUseSystemProxy.Checked) 109 | txtCustomProxy.Enabled = false; 110 | } 111 | 112 | private void TxtCustomProxy_Enter(object sender, EventArgs e) 113 | { 114 | BeginInvoke((Action)delegate 115 | { 116 | txtCustomProxy.SelectAll(); 117 | }); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /RealNews/feedreader/Helpers.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader 2 | { 3 | using System; 4 | using System.Globalization; 5 | //using System.Net.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | /// 10 | /// static class with helper functions 11 | /// 12 | public static class Helpers 13 | { 14 | private const string ACCEPT_HEADER_NAME = "Accept"; 15 | private const string ACCEPT_HEADER_VALUE = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; 16 | private const string USER_AGENT_NAME = "User-Agent"; 17 | private const string USER_AGENT_VALUE = "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"; 18 | 19 | // The HttpClient instance must be a static field 20 | // https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ 21 | //private static readonly HttpClient _httpClient = new HttpClient(); 22 | 23 | ///// 24 | ///// Download the content from an url 25 | ///// 26 | ///// correct url 27 | ///// Content as string 28 | //[Obsolete("Use the DownloadAsync method")] 29 | //public static string Download(string url) 30 | //{ 31 | // return DownloadAsync(url).Result; 32 | //} 33 | 34 | ///// 35 | ///// Download the content from an url 36 | ///// 37 | ///// correct url 38 | ///// Content as string 39 | //public static async Task DownloadAsync(string url) 40 | //{ 41 | // url = System.Net.WebUtility.UrlDecode(url); 42 | // HttpResponseMessage response; 43 | // using (var request = new HttpRequestMessage(HttpMethod.Get, url)) 44 | // { 45 | // request.Headers.TryAddWithoutValidation(ACCEPT_HEADER_NAME, ACCEPT_HEADER_VALUE); 46 | // request.Headers.TryAddWithoutValidation(USER_AGENT_NAME, USER_AGENT_VALUE); 47 | 48 | // response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead); 49 | // } 50 | // if (!response.IsSuccessStatusCode) 51 | // { 52 | // using (var request = new HttpRequestMessage(HttpMethod.Get, url)) 53 | // { 54 | // response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead); 55 | // } 56 | // } 57 | 58 | // return Encoding.UTF8.GetString(await response.Content.ReadAsByteArrayAsync()); 59 | //} 60 | 61 | /// 62 | /// Tries to parse the string as datetime and returns null if it fails 63 | /// 64 | /// datetime as string 65 | /// The cultureInfo for parsing 66 | /// datetime or null 67 | public static DateTime? TryParseDateTime(string datetime, CultureInfo cultureInfo = null) 68 | { 69 | if (string.IsNullOrWhiteSpace(datetime)) 70 | return null; 71 | 72 | var dateTimeFormat = cultureInfo?.DateTimeFormat ?? DateTimeFormatInfo.CurrentInfo; 73 | 74 | if (!DateTimeOffset.TryParse(datetime, dateTimeFormat, DateTimeStyles.None, out var dt)) 75 | { 76 | // Do, 22 Dez 2016 17:36:00 +0000 77 | // note - tried ParseExact with diff formats like "ddd, dd MMM yyyy hh:mm:ss K" 78 | if (datetime.Contains(",")) 79 | { 80 | int pos = datetime.IndexOf(',') + 1; 81 | string newdtstring = datetime.Substring(pos).Trim(); 82 | newdtstring = newdtstring.Replace(" EST", "").Replace(" EDT",""); 83 | DateTimeOffset.TryParse(newdtstring, dateTimeFormat, DateTimeStyles.None, out dt); 84 | } 85 | } 86 | 87 | if (dt == default(DateTimeOffset)) 88 | return null; 89 | 90 | return dt.UtcDateTime; 91 | } 92 | 93 | /// 94 | /// Tries to parse the string as int and returns null if it fails 95 | /// 96 | /// int as string 97 | /// integer or null 98 | public static int? TryParseInt(string input) 99 | { 100 | if (!int.TryParse(input, out int tmp)) 101 | return null; 102 | return tmp; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Atom/AtomFeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Xml.Linq; 7 | 8 | /// 9 | /// Atom 1.0 feed item object according to specification: https://validator.w3.org/feed/docs/atom.html 10 | /// 11 | public class AtomFeedItem : BaseFeedItem 12 | { 13 | /// 14 | /// The "author" element 15 | /// 16 | public AtomPerson Author { get; set; } 17 | 18 | /// 19 | /// All "category" elements 20 | /// 21 | public List Categories { get; set; } 22 | 23 | /// 24 | /// The "content" element 25 | /// 26 | public string Content { get; set; } 27 | 28 | /// 29 | /// The "contributor" element 30 | /// 31 | public AtomPerson Contributor { get; set; } 32 | 33 | /// 34 | /// The "id" element 35 | /// 36 | public string Id { get; set; } 37 | 38 | /// 39 | /// The "published" date as string 40 | /// 41 | public string PublishedDateString { get; set; } 42 | 43 | /// 44 | /// The "published" element as DateTime. Null if parsing failed or published is empty. 45 | /// 46 | public DateTime? PublishedDate { get; set; } 47 | 48 | /// 49 | /// The "rights" element 50 | /// 51 | public string Rights { get; set; } 52 | 53 | /// 54 | /// The "source" element 55 | /// 56 | public string Source { get; set; } 57 | 58 | /// 59 | /// The "summary" element 60 | /// 61 | public string Summary { get; set; } 62 | 63 | /// 64 | /// The "updated" element 65 | /// 66 | public string UpdatedDateString { get; set; } 67 | 68 | /// 69 | /// The "updated" element as DateTime. Null if parsing failed or updated is empty 70 | /// 71 | public DateTime? UpdatedDate { get; set; } 72 | 73 | /// 74 | /// All "link" elements 75 | /// 76 | public ICollection Links { get; set; } 77 | 78 | /// 79 | /// Initializes a new instance of the class. 80 | /// default constructor (for serialization) 81 | /// 82 | public AtomFeedItem() 83 | : base() 84 | { 85 | } 86 | 87 | /// 88 | /// Initializes a new instance of the class. 89 | /// Reads an atom feed based on the xml given in item 90 | /// 91 | /// feed item as xml 92 | public AtomFeedItem(XElement item) 93 | : base(item) 94 | { 95 | this.Link = item.GetElement("link").Attribute("href")?.Value; 96 | 97 | this.Author = new AtomPerson(item.GetElement("author")); 98 | 99 | var categories = item.GetElements("category"); 100 | this.Categories = categories.Select(x => x.GetValue()).ToList(); 101 | 102 | this.Content = item.GetValue("content").HtmlDecode(); 103 | this.Contributor = new AtomPerson(item.GetElement("contributor")); 104 | this.Id = item.GetValue("id"); 105 | 106 | this.PublishedDateString = item.GetValue("published"); 107 | this.PublishedDate = Helpers.TryParseDateTime(this.PublishedDateString); 108 | this.Links = item.GetElements("link").Select(x => new AtomLink(x)).ToList(); 109 | 110 | this.Rights = item.GetValue("rights"); 111 | this.Source = item.GetValue("source"); 112 | this.Summary = item.GetValue("summary"); 113 | 114 | this.UpdatedDateString = item.GetValue("updated"); 115 | this.UpdatedDate = Helpers.TryParseDateTime(this.UpdatedDateString); 116 | } 117 | 118 | /// 119 | internal override FeedItem ToFeedItem() 120 | { 121 | FeedItem fi = new FeedItem(this) 122 | { 123 | Author = this.Author?.ToString(), 124 | Categories = this.Categories, 125 | Content = this.Content, 126 | Description = this.Summary, 127 | Id = this.Id, 128 | PublishingDate = this.PublishedDate, 129 | PublishingDateString = this.PublishedDateString 130 | }; 131 | return fi; 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/Atom/AtomFeed.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Xml.Linq; 7 | 8 | /// 9 | /// Atom 1.0 feed object according to specification: https://validator.w3.org/feed/docs/atom.html 10 | /// 11 | public class AtomFeed : BaseFeed 12 | { 13 | /// 14 | /// The "author" element 15 | /// 16 | public AtomPerson Author { get; set; } 17 | 18 | /// 19 | /// All "category" elements 20 | /// 21 | public ICollection Categories { get; set; } 22 | 23 | /// 24 | /// The "contributor" element 25 | /// 26 | public AtomPerson Contributor { get; set; } 27 | 28 | /// 29 | /// The "generator" element 30 | /// 31 | public string Generator { get; set; } 32 | 33 | /// 34 | /// The "icon" element 35 | /// 36 | public string Icon { get; set; } 37 | 38 | /// 39 | /// The "id" element 40 | /// 41 | public string Id { get; set; } 42 | 43 | /// 44 | /// The "logo" element 45 | /// 46 | public string Logo { get; set; } 47 | 48 | /// 49 | /// The "rights" element 50 | /// 51 | public string Rights { get; set; } 52 | 53 | /// 54 | /// The "subtitle" element 55 | /// 56 | public string Subtitle { get; set; } 57 | 58 | /// 59 | /// The "updated" element as string 60 | /// 61 | public string UpdatedDateString { get; set; } 62 | 63 | /// 64 | /// The "updated" element as DateTime. Null if parsing failed of updatedDate is empty. 65 | /// 66 | public DateTime? UpdatedDate { get; set; } 67 | 68 | /// 69 | /// All "link" elements 70 | /// 71 | public ICollection Links { get; set; } 72 | 73 | /// 74 | /// Initializes a new instance of the class. 75 | /// default constructor (for serialization) 76 | /// 77 | public AtomFeed() 78 | : base() 79 | { 80 | } 81 | 82 | /// 83 | /// Initializes a new instance of the class. 84 | /// Reads an atom feed based on the xml given in channel 85 | /// 86 | /// the entire feed xml as string 87 | /// the feed element in the xml as XElement 88 | public AtomFeed(string feedXml, XElement feed) 89 | : base(feedXml, feed) 90 | { 91 | this.Link = feed.GetElement("link").Attribute("href")?.Value; 92 | 93 | this.Author = new AtomPerson(feed.GetElement("author")); 94 | 95 | var categories = feed.GetElements("category"); 96 | this.Categories = categories.Select(x => x.GetValue()).ToList(); 97 | 98 | this.Contributor = new AtomPerson(feed.GetElement("contributor")); 99 | this.Generator = feed.GetValue("generator"); 100 | this.Icon = feed.GetValue("icon"); 101 | this.Id = feed.GetValue("id"); 102 | this.Logo = feed.GetValue("logo"); 103 | this.Rights = feed.GetValue("rights"); 104 | this.Subtitle = feed.GetValue("subtitle"); 105 | 106 | this.Links = feed.GetElements("link").Select(x => new AtomLink(x)).ToList(); 107 | 108 | this.UpdatedDateString = feed.GetValue("updated"); 109 | this.UpdatedDate = Helpers.TryParseDateTime(this.UpdatedDateString); 110 | 111 | var items = feed.GetElements("entry"); 112 | 113 | foreach (var item in items) 114 | { 115 | this.Items.Add(new AtomFeedItem(item)); 116 | } 117 | } 118 | 119 | /// 120 | /// Creates the base element out of this feed. 121 | /// 122 | /// feed 123 | public override Feed ToFeed() 124 | { 125 | Feed f = new Feed(this) 126 | { 127 | Copyright = this.Rights, 128 | Description = null, 129 | ImageUrl = this.Icon, 130 | Language = null, 131 | LastUpdatedDate = this.UpdatedDate, 132 | LastUpdatedDateString = this.UpdatedDateString, 133 | Type = FeedType.Atom 134 | }; 135 | return f; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /RealNews/Helper/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | using System.IO; 6 | using System.Threading.Tasks; 7 | 8 | namespace RealNews 9 | { 10 | public interface ILog 11 | { 12 | /// 13 | /// Fatal log = log level 5 14 | /// 15 | /// 16 | /// 17 | void Fatal(object msg, params object[] objs); // 5 18 | /// 19 | /// Error log = log level 4 20 | /// 21 | /// 22 | /// 23 | void Error(object msg, params object[] objs); // 4 24 | /// 25 | /// Warning log = log level 3 26 | /// 27 | /// 28 | /// 29 | void Warn(object msg, params object[] objs); // 3 30 | /// 31 | /// Debug log = log level 2 32 | /// 33 | /// 34 | /// 35 | void Debug(object msg, params object[] objs); // 2 36 | /// 37 | /// Info log = log level 1 38 | /// 39 | /// 40 | /// 41 | void Info(object msg, params object[] objs); // 1 42 | } 43 | 44 | internal class ConsoleLogger 45 | { 46 | // Sinlgeton pattern 4 from : http://csharpindepth.com/articles/general/singleton.aspx 47 | private static readonly ConsoleLogger instance = new ConsoleLogger(); 48 | // Explicit static constructor to tell C# compiler 49 | // not to mark type as beforefieldinit 50 | static ConsoleLogger() 51 | { 52 | } 53 | private ConsoleLogger() 54 | { 55 | } 56 | public static ConsoleLogger Instance { get { return instance; } } 57 | private Queue _log = new Queue(); 58 | private int _lastLogsToKeep = 100; 59 | internal bool Log2Console = false; 60 | 61 | private string FormatLog(string log, string msg, object[] objs) 62 | { 63 | StringBuilder sb = new StringBuilder(); 64 | sb.Append(DateTime.Now.ToString("HH:mm:ss")); 65 | sb.Append("|"); 66 | sb.Append(log); 67 | //sb.Append("|"); 68 | //sb.Append(Thread.CurrentThread.ManagedThreadId.ToString()); 69 | sb.Append("| "); 70 | sb.Append(msg); 71 | 72 | if (objs != null) 73 | foreach (object o in objs) 74 | if ("" + o != "") 75 | sb.AppendLine("" + o); 76 | 77 | return sb.ToString(); 78 | } 79 | 80 | public void Log(string logtype, string msg, params object[] objs) 81 | { 82 | var l = FormatLog(logtype, msg, objs); 83 | 84 | lock (_log) 85 | { 86 | _log.Enqueue(l); 87 | while (_log.Count > _lastLogsToKeep) 88 | _log.Dequeue(); 89 | } 90 | if (Log2Console) 91 | Task.Factory.StartNew(() => Console.WriteLine(l)); 92 | } 93 | 94 | public string[] GetLastLogs() 95 | { 96 | return _log.ToArray(); 97 | } 98 | } 99 | 100 | internal class logger : ILog 101 | { 102 | public logger(Type type) 103 | { 104 | typename = type.Namespace + "." + type.Name; 105 | } 106 | 107 | private string typename = ""; 108 | 109 | #region ILog Members 110 | public void Fatal(object msg, params object[] objs) 111 | { 112 | ConsoleLogger.Instance.Log("FATAL", "" + msg, objs); 113 | } 114 | 115 | public void Error(object msg, params object[] objs) 116 | { 117 | ConsoleLogger.Instance.Log("ERROR", "" + msg, objs); 118 | } 119 | 120 | public void Warn(object msg, params object[] objs) 121 | { 122 | ConsoleLogger.Instance.Log("WARN", "" + msg, objs); 123 | } 124 | 125 | public void Debug(object msg, params object[] objs) 126 | { 127 | ConsoleLogger.Instance.Log("DEBUG", "" + msg, objs); 128 | } 129 | 130 | public void Info(object msg, params object[] objs) 131 | { 132 | ConsoleLogger.Instance.Log("INFO", "" + msg, objs); 133 | } 134 | #endregion 135 | } 136 | 137 | public static class LogManager 138 | { 139 | public static ILog GetLogger(Type obj) 140 | { 141 | return new logger(obj); 142 | } 143 | 144 | public static void ConsoleMode() 145 | { 146 | ConsoleLogger.Instance.Log2Console = true; 147 | } 148 | 149 | public static string[] GetLastLogs() 150 | { 151 | return ConsoleLogger.Instance.GetLastLogs(); 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /RealNews/Renderer/Office2007BlackColorTable.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace BSE.Windows.Forms 5 | { 6 | /// 7 | /// Provides colors used for Microsoft Office 2007 black display elements. 8 | /// 9 | public class Office2007BlackColorTable : BSE.Windows.Forms.OfficeColorTable 10 | { 11 | //#region FieldsPrivate 12 | //private PanelColors m_panelColorTable; 13 | //#endregion 14 | 15 | //#region Properties 16 | ///// 17 | ///// Gets the associated ColorTable for the XPanderControls 18 | ///// 19 | //public override PanelColors PanelColorTable 20 | //{ 21 | // get 22 | // { 23 | // if (this.m_panelColorTable == null) 24 | // { 25 | // this.m_panelColorTable = new PanelColorsOffice2007Black(); 26 | // } 27 | // return this.m_panelColorTable; 28 | // } 29 | //} 30 | //#endregion 31 | 32 | #region MethodsProtected 33 | /// 34 | /// Initializes a color dictionary with defined colors. 35 | /// 36 | /// Dictionary with defined colors 37 | protected override void InitColors(Dictionary rgbTable) 38 | { 39 | rgbTable[KnownColors.ButtonPressedBorder] = Color.FromArgb(255, 189, 105); 40 | rgbTable[KnownColors.ButtonPressedGradientBegin] = Color.FromArgb(248, 181, 106); 41 | rgbTable[KnownColors.ButtonPressedGradientEnd] = Color.FromArgb(255, 208, 134); 42 | rgbTable[KnownColors.ButtonPressedGradientMiddle] = Color.FromArgb(251, 140, 60); 43 | rgbTable[KnownColors.ButtonSelectedBorder] = Color.FromArgb(255, 189, 105); 44 | rgbTable[KnownColors.ButtonSelectedGradientBegin] = Color.FromArgb(255, 245, 204); 45 | rgbTable[KnownColors.ButtonSelectedGradientEnd] = Color.FromArgb(255, 219, 117); 46 | rgbTable[KnownColors.ButtonSelectedGradientMiddle] = Color.FromArgb(255, 231, 162); 47 | rgbTable[KnownColors.ButtonSelectedHighlightBorder] = Color.FromArgb(255, 189, 105); 48 | rgbTable[KnownColors.CheckBackground] = Color.FromArgb(255, 227, 149); 49 | rgbTable[KnownColors.CheckSelectedBackground] = Color.FromArgb(254, 128, 62); 50 | rgbTable[KnownColors.GripDark] = Color.FromArgb(145, 153, 164); 51 | rgbTable[KnownColors.GripLight] = Color.FromArgb(221, 224, 227); 52 | rgbTable[KnownColors.ImageMarginGradientBegin] = Color.FromArgb(239, 239, 239); 53 | rgbTable[KnownColors.MenuBorder] = Color.FromArgb(145, 153, 164); 54 | rgbTable[KnownColors.MenuItemBorder] = Color.FromArgb(255, 189, 105); 55 | rgbTable[KnownColors.MenuItemPressedGradientBegin] = Color.FromArgb(145, 153, 164); 56 | rgbTable[KnownColors.MenuItemPressedGradientEnd] = Color.FromArgb(108, 117, 128); 57 | rgbTable[KnownColors.MenuItemPressedGradientMiddle] = Color.FromArgb(126, 135, 146); 58 | rgbTable[KnownColors.MenuItemSelected] = Color.FromArgb(255, 238, 194); 59 | rgbTable[KnownColors.MenuItemSelectedGradientBegin] = Color.FromArgb(255, 245, 204); 60 | rgbTable[KnownColors.MenuItemSelectedGradientEnd] = Color.FromArgb(255, 223, 132); 61 | rgbTable[KnownColors.MenuItemText] = Color.FromArgb(255, 255, 255); 62 | rgbTable[KnownColors.MenuStripGradientBegin] = Color.FromArgb(83, 83, 83); 63 | rgbTable[KnownColors.MenuStripGradientEnd] = Color.FromArgb(83, 83, 83); 64 | rgbTable[KnownColors.OverflowButtonGradientBegin] = Color.FromArgb(178, 183, 191); 65 | rgbTable[KnownColors.OverflowButtonGradientEnd] = Color.FromArgb(81, 88, 98); 66 | rgbTable[KnownColors.OverflowButtonGradientMiddle] = Color.FromArgb(145, 153, 164); 67 | rgbTable[KnownColors.RaftingContainerGradientBegin] = Color.FromArgb(83, 83, 83); 68 | rgbTable[KnownColors.RaftingContainerGradientEnd] = Color.FromArgb(83, 83, 83); 69 | rgbTable[KnownColors.SeparatorDark] = Color.FromArgb(145, 153, 164); 70 | rgbTable[KnownColors.SeparatorLight] = Color.FromArgb(221, 224, 227); 71 | rgbTable[KnownColors.StatusStripGradientBegin] = Color.FromArgb(76, 83, 92); 72 | rgbTable[KnownColors.StatusStripGradientEnd] = Color.FromArgb(35, 38, 42); 73 | rgbTable[KnownColors.StatusStripText] = Color.FromArgb(255, 255, 255); 74 | rgbTable[KnownColors.ToolStripBorder] = Color.FromArgb(76, 83, 92); 75 | rgbTable[KnownColors.ToolStripContentPanelGradientBegin] = Color.FromArgb(82, 82, 82); 76 | rgbTable[KnownColors.ToolStripContentPanelGradientEnd] = Color.FromArgb(10, 10, 10); 77 | rgbTable[KnownColors.ToolStripDropDownBackground] = Color.FromArgb(250, 250, 250); 78 | rgbTable[KnownColors.ToolStripGradientBegin] = Color.FromArgb(205, 208, 213); 79 | rgbTable[KnownColors.ToolStripGradientEnd] = Color.FromArgb(148, 156, 166); 80 | rgbTable[KnownColors.ToolStripGradientMiddle] = Color.FromArgb(188, 193, 200); 81 | rgbTable[KnownColors.ToolStripPanelGradientBegin] = Color.FromArgb(83, 83, 83); 82 | rgbTable[KnownColors.ToolStripPanelGradientEnd] = Color.FromArgb(83, 83, 83); 83 | rgbTable[KnownColors.ToolStripText] = Color.FromArgb(0, 0, 0); 84 | } 85 | 86 | #endregion 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /RealNews/Renderer/Office2007BlueColorTable.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace BSE.Windows.Forms 5 | { 6 | /// 7 | /// Provides colors used for Microsoft Office 2007 blue display elements. 8 | /// 9 | public class Office2007BlueColorTable : BSE.Windows.Forms.OfficeColorTable 10 | { 11 | //#region FieldsPrivate 12 | //private PanelColors m_panelColorTable; 13 | //#endregion 14 | 15 | //#region Properties 16 | ///// 17 | ///// Gets the associated ColorTable for the XPanderControls 18 | ///// 19 | //public override PanelColors PanelColorTable 20 | //{ 21 | // get 22 | // { 23 | // if (this.m_panelColorTable == null) 24 | // { 25 | // this.m_panelColorTable = new PanelColorsOffice2007Blue(); 26 | // } 27 | // return this.m_panelColorTable; 28 | // } 29 | //} 30 | //#endregion 31 | 32 | #region MethodsProtected 33 | /// 34 | /// Unitializes a color dictionary with defined colors 35 | /// 36 | /// Dictionary with defined colors 37 | protected override void InitColors(Dictionary rgbTable) 38 | { 39 | rgbTable[KnownColors.ButtonPressedBorder] = Color.FromArgb(255, 189, 105); 40 | rgbTable[KnownColors.ButtonPressedGradientBegin] = Color.FromArgb(248, 181, 106); 41 | rgbTable[KnownColors.ButtonPressedGradientEnd] = Color.FromArgb(255, 208, 134); 42 | rgbTable[KnownColors.ButtonPressedGradientMiddle] = Color.FromArgb(251, 140, 60); 43 | rgbTable[KnownColors.ButtonSelectedBorder] = Color.FromArgb(255, 189, 105); 44 | rgbTable[KnownColors.ButtonSelectedGradientBegin] = Color.FromArgb(255, 245, 204); 45 | rgbTable[KnownColors.ButtonSelectedGradientEnd] = Color.FromArgb(255, 219, 117); 46 | rgbTable[KnownColors.ButtonSelectedGradientMiddle] = Color.FromArgb(255, 231, 162); 47 | rgbTable[KnownColors.ButtonSelectedHighlightBorder] = Color.FromArgb(255, 189, 105); 48 | rgbTable[KnownColors.CheckBackground] = Color.FromArgb(255, 227, 149); 49 | rgbTable[KnownColors.CheckSelectedBackground] = Color.FromArgb(254, 128, 62); 50 | rgbTable[KnownColors.GripDark] = Color.FromArgb(111, 157, 217); 51 | rgbTable[KnownColors.GripLight] = Color.FromArgb(255, 255, 255); 52 | rgbTable[KnownColors.ImageMarginGradientBegin] = Color.FromArgb(233, 238, 238); 53 | rgbTable[KnownColors.MenuBorder] = Color.FromArgb(134, 134, 134); 54 | rgbTable[KnownColors.MenuItemBorder] = Color.FromArgb(255, 189, 105); 55 | rgbTable[KnownColors.MenuItemPressedGradientBegin] = Color.FromArgb(227, 239, 255); 56 | rgbTable[KnownColors.MenuItemPressedGradientEnd] = Color.FromArgb(152, 186, 230); 57 | rgbTable[KnownColors.MenuItemPressedGradientMiddle] = Color.FromArgb(222, 236, 255); 58 | rgbTable[KnownColors.MenuItemSelected] = Color.FromArgb(255, 238, 194); 59 | rgbTable[KnownColors.MenuItemSelectedGradientBegin] = Color.FromArgb(255, 245, 204); 60 | rgbTable[KnownColors.MenuItemSelectedGradientEnd] = Color.FromArgb(255, 223, 132); 61 | rgbTable[KnownColors.MenuItemText] = Color.FromArgb(0, 0, 0); 62 | rgbTable[KnownColors.MenuStripGradientBegin] = Color.FromArgb(191, 219, 255); 63 | rgbTable[KnownColors.MenuStripGradientEnd] = Color.FromArgb(191, 219, 255); 64 | rgbTable[KnownColors.OverflowButtonGradientBegin] = Color.FromArgb(167, 204, 251); 65 | rgbTable[KnownColors.OverflowButtonGradientEnd] = Color.FromArgb(101, 147, 207); 66 | rgbTable[KnownColors.OverflowButtonGradientMiddle] = Color.FromArgb(167, 204, 251); 67 | rgbTable[KnownColors.RaftingContainerGradientBegin] = Color.FromArgb(191, 219, 255); 68 | rgbTable[KnownColors.RaftingContainerGradientEnd] = Color.FromArgb(191, 219, 255); 69 | rgbTable[KnownColors.SeparatorDark] = Color.FromArgb(173, 209, 255); 70 | rgbTable[KnownColors.SeparatorLight] = Color.FromArgb(255, 255, 255); 71 | rgbTable[KnownColors.StatusStripGradientBegin] = Color.FromArgb(227, 239, 255); 72 | rgbTable[KnownColors.StatusStripGradientEnd] = Color.FromArgb(173, 209, 255); 73 | rgbTable[KnownColors.StatusStripText] = Color.FromArgb(21, 66, 139); 74 | rgbTable[KnownColors.ToolStripBorder] = Color.FromArgb(111, 157, 217); 75 | rgbTable[KnownColors.ToolStripContentPanelGradientBegin] = Color.FromArgb(191, 219, 255); 76 | rgbTable[KnownColors.ToolStripContentPanelGradientEnd] = Color.FromArgb(101, 145, 205); 77 | rgbTable[KnownColors.ToolStripDropDownBackground] = Color.FromArgb(250, 250, 250); 78 | rgbTable[KnownColors.ToolStripGradientBegin] = Color.FromArgb(227, 239, 255); 79 | rgbTable[KnownColors.ToolStripGradientEnd] = Color.FromArgb(152, 186, 230); 80 | rgbTable[KnownColors.ToolStripGradientMiddle] = Color.FromArgb(222, 236, 255); 81 | rgbTable[KnownColors.ToolStripPanelGradientBegin] = Color.FromArgb(191, 219, 255); 82 | rgbTable[KnownColors.ToolStripPanelGradientEnd] = Color.FromArgb(191, 219, 255); 83 | rgbTable[KnownColors.ToolStripText] = Color.FromArgb(0, 0, 0); 84 | } 85 | 86 | #endregion 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /RealNews/Helper/ImageCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using static RaptorDB.Common.ZipStorer; 6 | 7 | namespace RealNews 8 | { 9 | class ImageCache 10 | { 11 | public ImageCache() 12 | { 13 | } 14 | 15 | ConcurrentDictionary> _ziplookup = new ConcurrentDictionary>(); 16 | 17 | public class urlhash 18 | { 19 | public string folder; 20 | public string fn; 21 | } 22 | 23 | private string _path = "cache/"; 24 | 25 | private urlhash FixName(string url) 26 | { 27 | // remove http:// https:// 28 | url = url.Replace("http://", "").Replace("https://", ""); 29 | // KLUDGE : for engaget images 30 | url = url.Replace("amp;", ""); 31 | 32 | string fol = url.Substring(0, url.IndexOf('/')); 33 | 34 | var r = new urlhash 35 | { 36 | folder = fol, 37 | fn = fol + "/" + url.GetHashCode() + ".jpg" 38 | }; 39 | 40 | return r; 41 | } 42 | 43 | public urlhash GetUrlhash(string url) 44 | { 45 | return FixName(url); 46 | } 47 | 48 | public string GetFilename(string url) 49 | { 50 | if (url == null) 51 | return _path + "null.jpg"; 52 | 53 | var key = FixName(url); 54 | 55 | Directory.CreateDirectory(_path + key.folder); 56 | 57 | return _path + key.fn; 58 | } 59 | 60 | public void Add(string url, byte[] data) 61 | { 62 | if (url == null) 63 | return; 64 | 65 | var key = FixName(url); 66 | 67 | Directory.CreateDirectory(_path + key.folder); 68 | 69 | File.WriteAllBytes(_path + key.fn, data); 70 | 71 | return; 72 | } 73 | 74 | public bool Contains(string url) 75 | { 76 | if (url == null) 77 | return true; 78 | 79 | var key = FixName(url); 80 | var fi = new FileInfo(Path.GetFullPath(_path + key.fn)); 81 | 82 | if (fi.Exists && fi.Length > 0) // File.Exists(_path + key.fn)) 83 | return true; 84 | else 85 | { 86 | // check zip 87 | if (File.Exists(_path + key.folder + ".zip")) 88 | { 89 | if (_ziplookup.ContainsKey(key.folder) == false) 90 | { 91 | using (var zf = RaptorDB.Common.ZipStorer.Open(_path + key.folder + ".zip", FileAccess.Read)) 92 | { 93 | _ziplookup.TryAdd(key.folder, zf.ReadCentralDir()); 94 | } 95 | } 96 | _ziplookup.TryGetValue(key.folder, out List l); 97 | if (l != null) 98 | { 99 | var ze = l.Find(x => key.fn.EndsWith(x.FilenameInZip)); 100 | if (ze.FilenameInZip != null) 101 | return true; 102 | } 103 | } 104 | 105 | return false; 106 | } 107 | } 108 | 109 | public byte[] Get(string url) 110 | { 111 | if (url == null) 112 | return null; 113 | 114 | var key = FixName(url); 115 | var fi = new FileInfo(Path.GetFullPath(_path + key.fn)); 116 | if (fi.Exists && fi.Length>0) // File.Exists(_path + key.fn)) 117 | return File.ReadAllBytes(_path + key.fn); 118 | else 119 | { 120 | if (File.Exists(_path + key.folder + ".zip")) 121 | { 122 | try 123 | { 124 | using (var zf = RaptorDB.Common.ZipStorer.Open(_path + key.folder + ".zip", FileAccess.Read)) 125 | { 126 | var ze = zf.ReadCentralDir().Find(x => key.fn.EndsWith(x.FilenameInZip)); 127 | 128 | if (ze.FilenameInZip != null) 129 | { 130 | MemoryStream ms = new MemoryStream(); 131 | zf.ExtractFile(ze, ms); 132 | return ms.ToArray(); 133 | } 134 | } 135 | } 136 | catch { } 137 | } 138 | return null; 139 | } 140 | } 141 | 142 | public void ClearLookup() 143 | { 144 | _ziplookup = new ConcurrentDictionary>(); 145 | } 146 | 147 | public void Remove(List imgs) 148 | { 149 | // remove images 150 | imgs.ForEach(url => 151 | { 152 | if (url == null) 153 | return; 154 | 155 | var key = FixName(url); 156 | 157 | if (File.Exists(_path + key.fn)) 158 | File.Delete(_path + key.fn); 159 | }); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /RealNews/feedreader/Feeds/2.0/Rss20FeedItem.cs: -------------------------------------------------------------------------------- 1 | namespace CodeHollow.FeedReader.Feeds 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Xml.Linq; 7 | 8 | /// 9 | /// RSS 2.0 feed item accoring to specification: https://validator.w3.org/feed/docs/rss2.html 10 | /// 11 | public class Rss20FeedItem : BaseFeedItem 12 | { 13 | /// 14 | /// The "description" field of the feed item 15 | /// 16 | public string Description { get; set; } 17 | 18 | /// 19 | /// The "author" field of the feed item 20 | /// 21 | public string Author { get; set; } 22 | 23 | /// 24 | /// The "comments" field of the feed item 25 | /// 26 | public string Comments { get; set; } 27 | 28 | 29 | 30 | /// 31 | /// The "guid" field 32 | /// 33 | public string Guid { get; set; } 34 | 35 | /// 36 | /// The "pubDate" field 37 | /// 38 | public string PublishingDateString { get; set; } 39 | 40 | /// 41 | /// The "pubDate" field as DateTime. Null if parsing failed or pubDate is empty. 42 | /// 43 | public DateTime? PublishingDate { get; set; } 44 | 45 | /// 46 | /// The "source" field 47 | /// 48 | public FeedItemSource Source { get; set; } 49 | 50 | /// 51 | /// All entries "category" entries 52 | /// 53 | public List Categories { get; set; } 54 | 55 | /// 56 | /// The "content:encoded" field 57 | /// 58 | public string Content { get; set; } 59 | 60 | /// 61 | /// All elements starting with "dc:" 62 | /// 63 | public DublinCore DC { get; set; } 64 | 65 | /// 66 | /// Initializes a new instance of the class. 67 | /// default constructor (for serialization) 68 | /// 69 | public Rss20FeedItem() 70 | : base() 71 | { 72 | } 73 | 74 | /// 75 | /// Initializes a new instance of the class. 76 | /// Reads a new feed item element based on the given xml item 77 | /// 78 | /// the xml containing the feed item 79 | public Rss20FeedItem(XElement item) 80 | : base(item) 81 | { 82 | this.Comments = item.GetValue("comments"); 83 | this.Author = item.GetValue("author"); 84 | this.Enclosure = new FeedItemEnclosure(item.GetElement("enclosure")); 85 | this.PublishingDateString = item.GetValue("pubDate"); 86 | this.PublishingDate = Helpers.TryParseDateTime(this.PublishingDateString); 87 | this.DC = new DublinCore(item); 88 | this.Source = new FeedItemSource(item.GetElement("source")); 89 | 90 | var categories = item.GetElements("category"); 91 | this.Categories = categories.Select(x => x.GetValue()).ToList(); 92 | 93 | this.Guid = item.GetValue("guid"); 94 | this.Description = item.GetValue("description"); 95 | this.Content = item.GetValue("content:encoded")?.HtmlDecode(); 96 | if (this.ExtraData == null) 97 | this.ExtraData = new Dictionary(); 98 | foreach (var i in item.DescendantNodes()) 99 | { 100 | var x = i as XElement; 101 | if (x != null) 102 | { 103 | if (this.ExtraData.ContainsKey(x.Name.LocalName)) 104 | { 105 | this.ExtraData[x.Name.LocalName] += ", " + x.Value; 106 | } 107 | else 108 | { 109 | if (x.Name.LocalName == "content") 110 | { 111 | var w = x.GetAttribute("width"); 112 | if (w != null) 113 | { 114 | var s = x.GetAttribute("url"); 115 | if (s != null) 116 | { 117 | if (this.ExtraData.ContainsKey("image" + w.Value) == false) 118 | this.ExtraData.Add("image" + w.Value, ""); 119 | } 120 | } 121 | } 122 | else 123 | this.ExtraData.Add(x.Name.LocalName, x.Value); 124 | } 125 | } 126 | 127 | } 128 | } 129 | 130 | /// 131 | internal override FeedItem ToFeedItem() 132 | { 133 | FeedItem fi = new FeedItem(this) 134 | { 135 | Author = this.Author, 136 | Categories = this.Categories, 137 | Content = this.Content, 138 | Description = this.Description, 139 | Id = this.Guid, 140 | PublishingDate = this.PublishingDate, 141 | PublishingDateString = this.PublishingDateString 142 | }; 143 | return fi; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /RealNews/Helper/HtmlSanitizer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Xml; 4 | using HtmlAgilityPack; 5 | 6 | namespace Westwind.Web.Utilities 7 | { 8 | public class HtmlSanitizer 9 | { 10 | 11 | public HashSet BlackList = new HashSet() 12 | { 13 | { "script" }, 14 | { "iframe" }, 15 | { "form" }, 16 | { "object" }, 17 | { "embed" }, 18 | { "link" }, 19 | { "head" }, 20 | { "meta" } 21 | }; 22 | 23 | /// 24 | /// Cleans up an HTML string and removes HTML tags in blacklist 25 | /// 26 | /// 27 | /// 28 | public static string SanitizeHtml(string html, params string[] blackList) 29 | { 30 | var sanitizer = new HtmlSanitizer(); 31 | if (blackList != null && blackList.Length > 0) 32 | { 33 | sanitizer.BlackList.Clear(); 34 | foreach (string item in blackList) 35 | sanitizer.BlackList.Add(item); 36 | } 37 | return sanitizer.Sanitize(html); 38 | } 39 | 40 | /// 41 | /// Cleans up an HTML string by removing elements 42 | /// on the blacklist and all elements that start 43 | /// with onXXX . 44 | /// 45 | /// 46 | /// 47 | public string Sanitize(string html) 48 | { 49 | var doc = new HtmlDocument(); 50 | 51 | doc.LoadHtml(html); 52 | SanitizeHtmlNode(doc.DocumentNode); 53 | 54 | //return doc.DocumentNode.WriteTo(); 55 | 56 | string output = null; 57 | 58 | // Use an XmlTextWriter to create self-closing tags 59 | using (StringWriter sw = new StringWriter()) 60 | { 61 | XmlWriter writer = new XmlTextWriter(sw); 62 | doc.DocumentNode.WriteTo(writer); 63 | output = sw.ToString(); 64 | 65 | // strip off XML doc header 66 | if (!string.IsNullOrEmpty(output)) 67 | { 68 | int at = output.IndexOf("?>"); 69 | output = output.Substring(at + 2); 70 | } 71 | 72 | writer.Close(); 73 | } 74 | doc = null; 75 | 76 | return output; 77 | } 78 | 79 | private void SanitizeHtmlNode(HtmlNode node) 80 | { 81 | if (node.NodeType == HtmlNodeType.Element) 82 | { 83 | // check for blacklist items and remove 84 | if (BlackList.Contains(node.Name)) 85 | { 86 | node.Remove(); 87 | return; 88 | } 89 | 90 | // remove CSS Expressions and embedded script links 91 | if (node.Name == "style") 92 | { 93 | var val = node.InnerHtml; 94 | if (string.IsNullOrEmpty(node.InnerText)) 95 | { 96 | if (HasExpressionLinks(val) || HasScriptLinks(val) ) 97 | node.ParentNode.RemoveChild(node); 98 | } 99 | } 100 | 101 | // remove script attributes 102 | if (node.HasAttributes) 103 | { 104 | for (int i = node.Attributes.Count - 1; i >= 0; i--) 105 | { 106 | HtmlAttribute currentAttribute = node.Attributes[i]; 107 | 108 | var attr = currentAttribute.Name.ToLower(); 109 | var val = currentAttribute.Value.ToLower(); 110 | 111 | // remove event handlers 112 | if (attr.StartsWith("on")) 113 | node.Attributes.Remove(currentAttribute); 114 | 115 | // Remove CSS Expressions 116 | else if (attr == "style" && 117 | val != null && 118 | HasExpressionLinks(val) || HasScriptLinks(val)) 119 | node.Attributes.Remove(currentAttribute); 120 | 121 | // remove script links from all attributes 122 | else if ( 123 | //(attr == "href" || attr== "src" || attr == "dynsrc" || attr == "lowsrc") && 124 | val != null && 125 | HasScriptLinks(val) ) 126 | node.Attributes.Remove(currentAttribute); 127 | } 128 | } 129 | } 130 | 131 | // Look through child nodes recursively 132 | if (node.HasChildNodes) 133 | { 134 | for (int i = node.ChildNodes.Count - 1; i >= 0; i--) 135 | { 136 | SanitizeHtmlNode(node.ChildNodes[i]); 137 | } 138 | } 139 | } 140 | 141 | private bool HasScriptLinks(string value) 142 | { 143 | return value.Contains("javascript:") || value.Contains("vbscript:"); 144 | } 145 | 146 | private bool HasExpressionLinks(string value) 147 | { 148 | return value.Contains("expression"); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /RealNews/HtmlAgilityPack/HtmlNode.Xpath.cs: -------------------------------------------------------------------------------- 1 | // Description: Html Agility Pack - HTML Parsers, selectors, traversors, manupulators. 2 | // Website & Documentation: http://html-agility-pack.net 3 | // Forum & Issues: https://github.com/zzzprojects/html-agility-pack 4 | // License: https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE 5 | // More projects: http://www.zzzprojects.com/ 6 | // Copyright © ZZZ Projects Inc. 2014 - 2017. All rights reserved. 7 | 8 | #if !METRO 9 | 10 | using System; 11 | using System.Xml.XPath; 12 | 13 | namespace HtmlAgilityPack 14 | { 15 | public partial class HtmlNode : IXPathNavigable 16 | { 17 | /// 18 | /// Creates a new XPathNavigator object for navigating this HTML node. 19 | /// 20 | /// An XPathNavigator object. The XPathNavigator is positioned on the node from which the method was called. It is not positioned on the root of the document. 21 | public XPathNavigator CreateNavigator() 22 | { 23 | return new HtmlNodeNavigator(OwnerDocument, this); 24 | } 25 | 26 | /// 27 | /// Creates an XPathNavigator using the root of this document. 28 | /// 29 | /// 30 | public XPathNavigator CreateRootNavigator() 31 | { 32 | return new HtmlNodeNavigator(OwnerDocument, OwnerDocument.DocumentNode); 33 | } 34 | 35 | /// 36 | /// Selects a list of nodes matching the expression. 37 | /// 38 | /// The XPath expression. 39 | /// An containing a collection of nodes matching the query, or null if no node matched the XPath expression. 40 | public HtmlNodeCollection SelectNodes(string xpath) 41 | { 42 | HtmlNodeCollection list = new HtmlNodeCollection(null); 43 | 44 | HtmlNodeNavigator nav = new HtmlNodeNavigator(OwnerDocument, this); 45 | XPathNodeIterator it = nav.Select(xpath); 46 | while (it.MoveNext()) 47 | { 48 | HtmlNodeNavigator n = (HtmlNodeNavigator) it.Current; 49 | list.Add(n.CurrentNode, false); 50 | } 51 | 52 | if (list.Count == 0 && !OwnerDocument.OptionEmptyCollection) 53 | { 54 | return null; 55 | } 56 | 57 | return list; 58 | } 59 | 60 | /// 61 | /// Selects a list of nodes matching the expression. 62 | /// 63 | /// The XPath expression. 64 | /// An containing a collection of nodes matching the query, or null if no node matched the XPath expression. 65 | public HtmlNodeCollection SelectNodes(XPathExpression xpath) 66 | { 67 | HtmlNodeCollection list = new HtmlNodeCollection(null); 68 | 69 | HtmlNodeNavigator nav = new HtmlNodeNavigator(OwnerDocument, this); 70 | XPathNodeIterator it = nav.Select(xpath); 71 | while (it.MoveNext()) 72 | { 73 | HtmlNodeNavigator n = (HtmlNodeNavigator) it.Current; 74 | list.Add(n.CurrentNode, false); 75 | } 76 | 77 | if (list.Count == 0 && !OwnerDocument.OptionEmptyCollection) 78 | { 79 | return null; 80 | } 81 | 82 | return list; 83 | } 84 | 85 | /// 86 | /// Selects the first XmlNode that matches the XPath expression. 87 | /// 88 | /// The XPath expression. May not be null. 89 | /// The first that matches the XPath query or a null reference if no matching node was found. 90 | public HtmlNode SelectSingleNode(string xpath) 91 | { 92 | if (xpath == null) 93 | { 94 | throw new ArgumentNullException("xpath"); 95 | } 96 | 97 | HtmlNodeNavigator nav = new HtmlNodeNavigator(OwnerDocument, this); 98 | XPathNodeIterator it = nav.Select(xpath); 99 | if (!it.MoveNext()) 100 | { 101 | return null; 102 | } 103 | 104 | HtmlNodeNavigator node = (HtmlNodeNavigator) it.Current; 105 | return node.CurrentNode; 106 | } 107 | 108 | /// 109 | /// Selects a list of nodes matching the expression. 110 | /// 111 | /// The XPath expression. 112 | /// An containing a collection of nodes matching the query, or null if no node matched the XPath expression. 113 | public HtmlNode SelectSingleNode(XPathExpression xpath) 114 | { 115 | if (xpath == null) 116 | { 117 | throw new ArgumentNullException("xpath"); 118 | } 119 | 120 | HtmlNodeNavigator nav = new HtmlNodeNavigator(OwnerDocument, this); 121 | XPathNodeIterator it = nav.Select(xpath); 122 | if (!it.MoveNext()) 123 | { 124 | return null; 125 | } 126 | 127 | HtmlNodeNavigator node = (HtmlNodeNavigator)it.Current; 128 | return node.CurrentNode; 129 | } 130 | } 131 | } 132 | #endif -------------------------------------------------------------------------------- /RealNews/Forms/myListBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace RealNews 6 | { 7 | class myListBox : ListBox 8 | { 9 | public myListBox() 10 | { 11 | this.DrawMode = DrawMode.OwnerDrawVariable; 12 | this.MeasureItem += MyListBox_MeasureItem; 13 | this.MouseClick += MyListBox_MouseClick; 14 | this.KeyDown += MyListBox_KeyDown; 15 | this.DrawItem += MyListBox_DrawItem; 16 | this.DoubleBuffered = true; 17 | } 18 | public Color GroupColor { get; set; } 19 | public Color HighLightText { get; set; } 20 | 21 | public Action MoveNext { get; set; } 22 | 23 | private void MyListBox_DrawItem(object sender, DrawItemEventArgs e) 24 | { 25 | if (DesignMode) 26 | return; 27 | 28 | var lb = this; 29 | var fi = lb.Items[e.Index] as FeedItem; 30 | var t = fi.Title; 31 | var f = e.Font; 32 | //if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) 33 | //{ 34 | // e = new DrawItemEventArgs(e.Graphics, 35 | // e.Font, 36 | // e.Bounds, 37 | // e.Index, 38 | // e.State ^ DrawItemState.Selected, 39 | // e.ForeColor, 40 | // Color.DarkOrchid);//Choose the color 41 | //} 42 | 43 | e.DrawBackground(); 44 | 45 | //var ItemMargin = 0; 46 | Brush myBrush = new SolidBrush(this.ForeColor); 47 | if (fi.isRead == false) 48 | { 49 | myBrush = new SolidBrush(Color.White); 50 | f = new Font(f, FontStyle.Bold); 51 | } 52 | var sf = StringFormat.GenericTypographic; 53 | sf.Trimming = StringTrimming.EllipsisCharacter; 54 | sf.LineAlignment = StringAlignment.Center; 55 | int l = 0; 56 | int w = 20; 57 | if (this.RightToLeft == RightToLeft.Yes) 58 | { 59 | sf = new StringFormat(); 60 | //sf.Alignment = StringAlignment.Far; 61 | sf.Trimming = StringTrimming.EllipsisCharacter; 62 | sf.LineAlignment = StringAlignment.Center; 63 | sf.FormatFlags = StringFormatFlags.DirectionRightToLeft | StringFormatFlags.NoWrap; 64 | l = 20; 65 | w = 0; 66 | } 67 | if (fi.Id == "") 68 | { 69 | var c = GroupColor; 70 | myBrush = new SolidBrush(c); 71 | sf = new StringFormat(); 72 | sf.Alignment = StringAlignment.Center; 73 | sf.LineAlignment = StringAlignment.Center; 74 | e.Graphics.DrawLine(new Pen(c), e.Bounds.Left + l, e.Bounds.Bottom - 5, e.Bounds.Width - w, e.Bounds.Bottom - 5); 75 | } 76 | var m = 10; 77 | var b = new Rectangle(e.Bounds.X + m, e.Bounds.Y, e.Bounds.Width - 2 * m, e.Bounds.Height); 78 | if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) 79 | { 80 | // Selected. Draw with the system highlight color. 81 | e.Graphics.DrawString(t, e.Font, new SolidBrush(HighLightText), b, sf); 82 | } 83 | else 84 | { 85 | e.Graphics.DrawString(t, f, myBrush, b, sf); 86 | } 87 | 88 | e.DrawFocusRectangle(); 89 | } 90 | 91 | private void MyListBox_KeyDown(object sender, KeyEventArgs e) 92 | { 93 | if ((e.KeyCode == Keys.Down || e.KeyCode == Keys.Up) && e.Shift == false && e.Alt == false) 94 | { 95 | var o = Items[SelectedIndex] as FeedItem; 96 | o.isRead = true; 97 | //MoveNext(); 98 | //e.SuppressKeyPress = true; 99 | } 100 | 101 | EnsureVisible(10); 102 | } 103 | 104 | private void MyListBox_MouseClick(object sender, MouseEventArgs e) 105 | { 106 | var o = this.SelectedItem as FeedItem; 107 | if (o.Id == "") 108 | { 109 | // FIX : select all in group 110 | } 111 | } 112 | 113 | private void MyListBox_MeasureItem(object sender, MeasureItemEventArgs e) 114 | { 115 | if (DesignMode) 116 | return; 117 | 118 | var lb = this; 119 | var fi = lb.Items[e.Index] as FeedItem; 120 | if (fi.Id == "") 121 | { 122 | e.ItemHeight += 12; 123 | } 124 | } 125 | 126 | public void EnsureVisible(int items) 127 | { 128 | int row = this.SelectedIndex; 129 | int visibleItems = this.ClientSize.Height / this.ItemHeight; 130 | int top = this.TopIndex; 131 | if (row - top > visibleItems - items) 132 | this.TopIndex = row - (visibleItems - items); 133 | this.SelectedIndex = row; 134 | } 135 | 136 | public void EnsureVisible(int index, int items) 137 | { 138 | int row = index; 139 | int visibleItems = this.ClientSize.Height / this.ItemHeight; 140 | int top = this.TopIndex; 141 | if (row - top > visibleItems - items) 142 | this.TopIndex = row - (visibleItems - items); 143 | this.SelectedIndex = row; 144 | } 145 | 146 | //public int FindItemWithText(string text) 147 | //{ 148 | 149 | //} 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /RealNews/Forms/frmFeed.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /RealNews/Forms/frmLog.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /RealNews/Forms/AboutBox1.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | --------------------------------------------------------------------------------