//All contents copyright Logical Expressions, Inc. 2004 using System; using System.Web; using System.Xml; using System.Configuration; using System.IO; using System.Data; using System.Data.OleDb; using System.Collections; namespace LEI.RssLib { public class RssHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { // Get the file name from the query string and see if the file is in the cache: string fileName = Path.GetFileName(context.Request.Path); string cachedChan = context.Cache[fileName] as String; if( cachedChan == null ) { // The file is not in the cache. // Verify that the profile folder has been configured: string profileFolder = ConfigurationSettings.AppSettings["profileFolder"]; if( profileFolder == null ) { context.Response.StatusCode = 404; context.Response.End(); return; } // Verify that you have a profile for the requested feed: string profilePath = profileFolder + "\\" + fileName; if( !File.Exists(profilePath) ) { context.Response.StatusCode = 404; context.Response.End(); return; } // RssChannel chan = new RssChannel(profilePath); cachedChan = chan.GetResponse(); double cacheTimeout; string appCacheTimeout = ConfigurationSettings.AppSettings["cacheTimeout"]; if( appCacheTimeout == null ) cacheTimeout = 15; else cacheTimeout = double.Parse(appCacheTimeout); context.Cache.Insert(fileName, cachedChan, null, DateTime.Now.AddMinutes(cacheTimeout), TimeSpan.Zero); } context.Response.ContentType = "text/xml"; context.Response.Write(cachedChan); } public bool IsReusable { get { return true; } } } internal class RssChannel { private string _title; private string _link; private string _description; private string _language; private string _itemSql; private string _itemConn; private string _profilePath; private string _linkFormat; private string _guidFormat; private string _guidIsPermanent; private ArrayList _items; public RssChannel(string profilePath) { _profilePath = profilePath; Load(); } public string ItemConn { get { return( _itemConn ); } set { _itemConn = value; } } public string ItemSql { get { return( _itemSql ); } set { _itemSql = value; } } public string Title { get { return( _title ); } set { _title = value; } } public string Link { get { return( _link ); } set { _link = value; } } public string Description { get { return( _description ); } set { _description = value; } } public string Language { get { return( _language ); } set { _language = value; } } public RssItem this[int index] { get { if( index < _items.Count) return( (RssItem) _items[index] ); return( null ); } } public string GetResponse() { XmlElement workNode; XmlElement itemNode; XmlAttribute workAttr; RssItem thisItem; XmlDocument rssDoc = new XmlDocument(); // Create the rss document node and set the version attribute: XmlElement docNode = rssDoc.CreateElement("rss"); XmlAttribute attr = rssDoc.CreateAttribute("version"); attr.Value = "2.0"; docNode.Attributes.Append(attr); rssDoc.AppendChild(docNode); // Create the channel element and its subelements: XmlElement chanNode = rssDoc.CreateElement("channel"); docNode.AppendChild(chanNode); workNode = rssDoc.CreateElement("title"); workNode.InnerText = _title; chanNode.AppendChild(workNode); workNode = rssDoc.CreateElement("link"); workNode.InnerText = _link; chanNode.AppendChild(workNode); workNode = rssDoc.CreateElement("description"); workNode.InnerText = _description; chanNode.AppendChild(workNode); workNode = rssDoc.CreateElement("language"); workNode.InnerText = _language; chanNode.AppendChild(workNode); // Append item nodes to the channel: for( int index=0; index < _items.Count; index++ ) { thisItem = (RssItem) _items[index]; itemNode = rssDoc.CreateElement("item"); chanNode.AppendChild(itemNode); workNode = rssDoc.CreateElement("title"); workNode.InnerText = thisItem.Title; itemNode.AppendChild(workNode); workNode = rssDoc.CreateElement("description"); workNode.InnerText = thisItem.Description; itemNode.AppendChild(workNode); workNode = rssDoc.CreateElement("link"); workNode.InnerText = thisItem.Link; itemNode.AppendChild(workNode); workNode = rssDoc.CreateElement("pubDate"); workNode.InnerText = thisItem.PubDate; itemNode.AppendChild(workNode); workNode = rssDoc.CreateElement("guid"); workAttr = rssDoc.CreateAttribute("isPermaLink"); workAttr.Value = _guidIsPermanent; workNode.Attributes.Append(workAttr); workNode.InnerText = thisItem.GUID; itemNode.AppendChild(workNode); } return( rssDoc.OuterXml ); } private void Load() { _items = new ArrayList(); XmlDocument profile = new XmlDocument(); // The profile is an xml document that provides configuration // data for the feed. Load the file into an XmlDocument object: try { profile.Load(_profilePath); } catch (Exception e) { HttpContext.Current.Response.Write(string.Format("
{0}: {1}
", e.Message, _profilePath)); return; } // Set channel properties from the profile: _title = profile.SelectSingleNode("/RssProfile/Title").InnerText; _link = profile.SelectSingleNode("/RssProfile/Link").InnerText; _description = profile.SelectSingleNode("/RssProfile/Description").InnerText; _language = profile.SelectSingleNode("/RssProfile/Language").InnerText; _itemConn = profile.SelectSingleNode("/RssProfile/ItemConnection").InnerText; _itemSql = profile.SelectSingleNode("/RssProfile/ItemSql").InnerText; _linkFormat = profile.SelectSingleNode("/RssProfile/LinkFormat").InnerText; _guidFormat = profile.SelectSingleNode("/RssProfile/GUIDFormat").InnerText; _guidIsPermanent = profile.SelectSingleNode("/RssProfile/GUIDIsPermanent").InnerText; // Retrieve items from the database: OleDbConnection conn = new OleDbConnection(_itemConn); IDbCommand cmd = new OleDbCommand(_itemSql); try { conn.Open(); cmd.Connection = conn; IDataReader reader = cmd.ExecuteReader(); while( reader.Read() ) { RssItem thisItem = new RssItem(reader, _linkFormat, _guidFormat); _items.Add(thisItem); } reader.Close(); reader.Dispose(); conn.Close(); } finally { conn.Dispose(); } } internal class RssItem { private string _title; private string _description; private string _link; private string _pubDate; private string _guid; internal RssItem( IDataReader reader, string linkFormat, string guidFormat ) { string itemId; itemId = reader[0].ToString(); _title = reader[1].ToString(); _description = reader[2].ToString(); _pubDate = reader[3].ToString(); // The linkFormat argument provides the URL of the // item's document. _link = string.Format(linkFormat, itemId); // The guidFormat argument provides the string that uniquely identifies // the item for RSS readers. _guid = string.Format(guidFormat, itemId); } public string Title { get { return( _title ); } set { _title = value; } } public string Description { get { return( _description ); } set { _description = value; } } public string Link { get { return( _link ); } set { _link = value; } } public string PubDate { get { return( _pubDate ); } set { _pubDate= value; } } public string GUID { get { return( _guid ); } set { _guid = value; } } } } }