// Copyright 2005 by Omar Al Zabir. All rights are reserved.
//
// If you like this code then feel free to go ahead and use it.
// The only thing I ask is that you don't remove or alter my copyright notice.
//
// Your use of this software is entirely at your own risk. I make no claims or
// warrantees about the reliability or fitness of this code for any particular purpose.
// If you make changes or additions to this code please mark your code as being yours.
//
// website http://www.oazabir.com, email OmarAlZabir@gmail.com, msn oazabir@hotmail.com
using System;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Drawing.Design;
namespace RSSCommon{
using PropertyEditor;
/// <summary>
/// Holds configuration informatino of a subscribed channel
/// </summary>
[System.Xml.Serialization.XmlRoot(Namespace="")]
[System.Xml.Serialization.XmlTypeAttribute("channel")]
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Channel
{
#region Events
///<summary>A PropertyChanged event is raised when a property is changed on a component. A PropertyChangedEventArgs object specifies the name of the property that changed.</summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Private Fields
private int _Id;
private string _Title;
private Uri _FeedUrl;
private TimeSpan _Frequency;
private DateTime _LastUpdated;
private DateTime _NextUpdate;
private DateTime _LastUpdatedInOutlook;
private string _FolderPath;
private string _XSLPath;
private bool _ShowInNewspaper;
private int _ItemCount;
private int _UnreadCount;
private string _UserName;
private string _UserPassword;
//private bool _StoreInOutlook;
#endregion
#region Public Properties
#region Store in outlook
/*
/// <summary>If true, this channel is stored in outlook</summary>
[Category("Outlook"),
Description(@"If true, this channel is stored in outlook")]
[XmlElement("storeInOutlook")]
public bool StoreInOutlook
{
get
{
return this._StoreInOutlook;
}
set
{
bool changed = !object.Equals(this._StoreInOutlook, value);
this._StoreInOutlook = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.StoreInOutlook));
}
}
*/
#endregion
#region Outlook Folder Type
public enum FolderCreationTypeEnum
{
Automatic_under_Base_Folder = 0,
Specific_Folder
}
private FolderCreationTypeEnum _FolderType;
/// <summary>
/// How folder will be created for this channel
/// </summary>
[Category("Outlook"),
Description(@"How folder will be created for this channel")]
[XmlElement("folderType")]
public FolderCreationTypeEnum FolderType
{
get
{
return this._FolderType;
}
set
{
bool changed = !object.Equals(this._FolderType, value);
this._FolderType = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.FolderType));
// Set back to default folder name if automatic selected
if( FolderCreationTypeEnum.Automatic_under_Base_Folder == this._FolderType )
{
this.FolderPath = Configuration.Instance.OutlookBaseFolder + "\\" + this.GetFolderName();
}
else
{
}
}
}
#endregion
#region Unread Count
/// <summary>
/// Number of unread messages
/// </summary>
[Category("Misc"), ReadOnly(true),
Description(@"Number of unread messages")]
[XmlElement("unreadCount")]
public int UnreadCount
{
get
{
return this._UnreadCount;
}
set
{
bool changed = !object.Equals(this._UnreadCount, value);
this._UnreadCount = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.UnreadCount));
}
}
#endregion
#region Database ID
/// <summary>
/// Internal database Id
/// </summary>
[Category("Misc"), ReadOnly(true),
Description(@"Internal ID of the channel")]
[XmlElement("id")]
public int Id
{
get
{
return this._Id;
}
set
{
bool changed = !object.Equals(this._Id, value);
this._Id = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.Id));
}
}
#endregion
#region Item Count
/// <summary>
/// Number of items in this channel
/// </summary>
[Category("Misc"), ReadOnly(true),
Description(@"Number of items in this channel")]
[XmlElement("itemCount")]
public int ItemCount
{
get
{
return this._ItemCount;
}
set
{
bool changed = !object.Equals(this._ItemCount, value);
this._ItemCount = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.ItemCount));
}
}
#endregion
#region Outlook View XML Path
private string _OutlookViewXmlPath;
/// <summary>Path to an Outlook View XML file which is applied to this folder</summary>
[Category("Outlook"),
Description(@"Path to an Outlook View XML file which is applied to this folder")]
[XmlElement("outlookViewXmlPath")]
[Editor(typeof(UIFileDialogEditor), typeof(UITypeEditor)),
CommonDialogFilterAttribute("XML File (*.xml)|*.xml")]
public string OutlookViewXmlPath
{
get
{
return this._OutlookViewXmlPath;
}
set
{
bool changed = !object.Equals(this._OutlookViewXmlPath, value);
this._OutlookViewXmlPath = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.OutlookViewXmlPath));
}
}
#endregion
#region Outlook XSL
private string _OutlookXSL;
/// <summary>Path to an XSL file which is used to transform feeds to HTML format for Outlook posts</summary>
[Category("Outlook"),
Description(@"Path to an XSL file which is used to transform feeds to HTML format for Outlook posts")]
[XmlElement("outlookXSL")]
[Editor(typeof(UIFileDialogEditor), typeof(UITypeEditor)),
CommonDialogFilterAttribute("XSLT File (*.xslt)|*.xslt|XSL File (*.xsl)|*.xsl")]
public string OutlookXSL
{
get
{
return this._OutlookXSL;
}
set
{
bool changed = !object.Equals(this._OutlookXSL, value);
this._OutlookXSL = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.OutlookXSL));
}
}
#endregion
#region Channel Title
/// <summary>The name of the channel. It's how people refer to your service.
/// If you have an HTML website that contains the same information as your RSS file,
/// the title of your channel should be the same as the title of your website.</summary>
[Category("Channel"),
Description(@"The name of the channel. It's how people refer to your service. If you have an HTML website that contains the same information as your RSS file, the title of your channel should be the same as the title of your website.")]
[XmlElement("title")]
public string Title
{
get
{
return this._Title;
}
set
{
bool changed = !object.Equals(this._Title, value);
this._Title = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.Title));
}
}
#endregion
#region Feed URL
/// <summary>URL of the RSS Feed from where the feed is downloaded</summary>
[Category("Source"),
Description(@"RSS feed URL from where the feed is downloaded. It can be a local file, or a remote server.
Please use http:// for web URL.")]
[XmlElement("feedURL")]
public Uri FeedURL
{
get
{
return this._FeedUrl;
}
set
{
bool changed = !object.Equals(this._FeedUrl, value);
this._FeedUrl = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.FeedURL));
}
}
#endregion
#region Download Frequency
/// <summary>Frequency of downloading this feed</summary>
[Category("Download"),
Description(@"Frequency of feed synchronization. For example, if it is 30 mins, then it will be snchronized every 30 mins")]
[XmlElement("frequency")]
public TimeSpan Frequency
{
get
{
return this._Frequency;
}
set
{
bool changed = !object.Equals(this._Frequency, value);
this._Frequency = value;
if(changed)
{
OnPropertyChanged(new PropertyChangedEventArgs(Properties.Frequency));
this.NextUpdate = this.LastUpdated + value;
}
}
}
#endregion
#region Last Updated
/// <summary>Last update date when the feed was downloaded</summary>
[Category("Download"), ReadOnly(true),
Description(@"Last update date when the feed was downloaded from the server")]
[XmlElement("lastUpdated")]
public DateTime LastUpdated
{
get
{
return this._LastUpdated;
}
set
{
bool changed = !object.Equals(this._LastUpdated, value);
this._LastUpdated = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.LastUpdated));
// Update next update time
this.NextUpdate = this.LastUpdated.Add( ( this.Frequency == TimeSpan.Zero ?
TimeSpan.FromMinutes( Configuration.Instance.DefaultDownloadFrequency ) : this.Frequency ) );
}
}
#endregion
#region Next Update Date Time
/// <summary>Next update date when the feed will be downloaded</summary>
[Category("Download"), ReadOnly(true),
Description(@"Next update date when the feed will be downloaded from the server")]
[XmlElement("nextUpdate")]
public DateTime NextUpdate
{
get
{
return this._NextUpdate;
}
set
{
bool changed = !object.Equals(this._NextUpdate, value);
this._NextUpdate = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.NextUpdate));
}
}
#endregion
#region Last Updated In Outlook
/// <summary>Last time when outlook received the RSS feeds</summary>
[Category("Outlook"), ReadOnly(true),
Description(@"Last time when outlook received the RSS feeds")]
[XmlElement("lastUpdatedInOutlook")]
public DateTime LastUpdatedInOutlook
{
get
{
return this._LastUpdatedInOutlook;
}
set
{
bool changed = !object.Equals(this._LastUpdatedInOutlook, value);
this._LastUpdatedInOutlook = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.LastUpdatedInOutlook));
}
}
#endregion
#region Folder path
/// <summary>Outlook folder path where RSS Feeds are stored</summary>
[Category("Outlook"),
Description(@"Outlook folder path where RSS Feeds are stored")]
[XmlElement("folderPath")]
[Editor(typeof(UIOutlookFolderPickerEditor), typeof(UITypeEditor))]
public string FolderPath
{
get
{
return this._FolderPath;
}
set
{
bool changed = !object.Equals(this._FolderPath, value);
this._FolderPath = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.FolderPath));
}
}
#endregion
#region XSL Path
/// <summary>XSL used to convert RSS XML to HTML</summary>
[Category("Outlook"),
Description(@"XSL used to convert RSS XML to HTML")]
[XmlElement("xslPath")]
[Editor(typeof(UIFileDialogEditor), typeof(UITypeEditor)),
CommonDialogFilterAttribute("XSLT File (*.xslt)|*.xslt|XSL File (*.xsl)|*.xsl")]
public string XSLPath
{
get
{
return this._XSLPath;
}
set
{
bool changed = !object.Equals(this._XSLPath, value);
this._XSLPath = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.XSLPath));
}
}
#endregion
#region Show In Newspaper
/// <summary>Whether this channel appears in newspaper</summary>
[Category("Outlook"),
Description(@"Whether this channel appears in newspaper")]
[XmlElement("showInNewsPaper")]
public bool ShowInNewspaper
{
get
{
return this._ShowInNewspaper;
}
set
{
bool changed = !object.Equals(this._ShowInNewspaper, value);
this._ShowInNewspaper = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.ShowInNewspaper));
}
}
#endregion
#region No of items in newspaper
private int _NumberOfItemsInNewspaper = 5;
/// <summary>Number of items to show in newspaper</summary>
[Category("Newspaper"),
Description(@"Number of items to show in newspaper")]
[XmlElement("newspaperItemCount")]
public int NumberOfItemsInNewspaper
{
get
{
return this._NumberOfItemsInNewspaper;
}
set
{
bool changed = !object.Equals(this._NumberOfItemsInNewspaper, value);
this._NumberOfItemsInNewspaper = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.NumberOfItemsInNewspaper));
}
}
#endregion
#region UserName
/// <summary>User Name to authentication connection to the RSS Feed source</summary>
[Category("Security"),
Description(@"User Name to authentication connection to the RSS Feed source")]
[XmlElement("userName")]
public string UserName
{
get
{
return this._UserName;
}
set
{
bool changed = !object.Equals(this._UserName, value);
this._UserName = value;
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.UserName));
}
}
#endregion
#region UserPassword
/// <summary>Password for the user account used to authenticate to the RSS Feed Source</summary>
[Category("Security"),
Description(@"DO NOT TYPE, CLICK THE '...' BUTTON")]
[XmlElement("userPassword")]
[Editor(typeof(PasswordEditor), typeof(UITypeEditor))]
public string UserPassword
{
get
{
return this._UserPassword;
}
set
{
bool changed = !object.Equals(this._UserPassword, value);
if( this.ValidPassword( value ) )
{
this._UserPassword = value;
}
else
{
this._UserPassword = "Don't Type. Click '...'";
}
if(changed) OnPropertyChanged(new PropertyChangedEventArgs(Properties.UserPassword));
}
}
#endregion
#endregion
#region Constructor
public Channel()
{
this._Title = string.Empty;
this._FeedUrl = null;
this._Frequency = TimeSpan.Zero;
this._LastUpdated = DateTime.MinValue;
this._NextUpdate = DateTime.MinValue;
this._LastUpdatedInOutlook = DateTime.MinValue;
this._ShowInNewspaper = false;
this._FolderPath = string.Empty;
this._XSLPath = string.Empty;
this._FolderType = FolderCreationTypeEnum.Specific_Folder;
}
public Channel( int id, string title, Uri feedUrl, TimeSpan frequency, DateTime lastUpdated,
DateTime nextUpdate, DateTime lastUpdateInOutlook, string folderPath, string xslPath,
bool showInNewspaper, int itemCount, int unreadCount, FolderCreationTypeEnum folderType,
string outlookViewXmlPath, string outlookXSL, string userName, string userPassword )
{
this._Id = id;
this._Title = title;
this._FeedUrl = feedUrl;
this._Frequency = frequency;
this._LastUpdated = lastUpdated;
this._NextUpdate = nextUpdate;
this._LastUpdatedInOutlook = LastUpdatedInOutlook;
this._ShowInNewspaper = showInNewspaper;
this._FolderPath = folderPath;
this._XSLPath = xslPath;
this._ItemCount = itemCount;
this._UnreadCount = unreadCount;
this.FolderType = folderType;
this._OutlookViewXmlPath = outlookViewXmlPath;
this._OutlookXSL = outlookXSL;
this._UserName = userName;
this._UserPassword = userPassword;
}
#endregion
#region Private Methods
private bool ValidPassword( string password )
{
// No password
if( null == password || 0 == password.Length ) return true;
// Password decryption provider is still not available
if( null == RSSCommon.PropertyEditor.PasswordEditor.PasswordProvider ) return true;
try
{
// If password decryption fails, surely user has manually typed the password
// inside the property dialog.
string decryptedPassword =
RSSCommon.PropertyEditor.PasswordEditor.PasswordProvider.Decrypt( password );
return ( null != decryptedPassword && decryptedPassword.Length > 0);
}
catch
{
return false;
}
}
private string GetFolderName()
{
char [] name = this.Title.ToCharArray();
for( int i = 0; i < name.Length; i ++ )
if( name[i] < ' ' && name[i] > 'z' )
name[i] = ' ';
return new string(name);
}
///<summary>A PropertyChanged event is raised when a property is
///changed on a component. A PropertyChangedEventArgs object
///specifies the name of the property that changed.</summary>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if( null != PropertyChanged )
{
PropertyChanged(this, e);
}
}
#endregion
#region Property Definition
public class Properties
{
public const string NumberOfItemsInNewspaper = "NumberOfItemsInNewspaper";
public const string OutlookXSL = "OutlookXSL";
public const string OutlookViewXmlPath = "OutlookViewXmlPath";
public const string StoreInOutlook = "StoreInOutlook";
public const string FolderType = "FolderType";
public const string Id = "Id";
public const string Title = "Title";
public const string FeedURL = "FeedURL";
public const string Frequency = "Frequency";
public const string LastUpdated = "LastUpdated";
public const string NextUpdate = "NextUpdate";
public const string LastUpdatedInOutlook = "LastUpdatedInOutlook";
public const string FolderPath = "FolderPath";
public const string XSLPath = "XSLPath";
public const string ShowInNewspaper = "ShowInNewspaper";
public const string ItemCount = "ItemCount";
public const string UnreadCount = "UnreadCount";
public const string UserName = "UserName";
public const string UserPassword = "UserPassword";
}
#endregion
#region Overrides
public override string ToString()
{
return this._Title + " (" + this.UnreadCount.ToString() + ")";
}
#endregion
}
/// <summary>
/// <see cref="Channel"/> Collection of Channels
/// </summary>
[Serializable]
public class ChannelCollection : System.Collections.CollectionBase
{
/// <summary>Adds an item to the IChannelCollection.</summary>
public int Add(Channel value)
{
return base.List.Add(value as object);
}
/// <summary>Removes an item to the ChannelCollection.</summary>
public void Remove(Channel value)
{
base.List.Remove(value as object);
}
/// <summary>Inserts an IChannel to the ChannelCollection at the specified position.</summary>
public void Insert(int index, Channel value)
{
base.List.Insert(index, value as object);
}
/// <summary>Determines whether the ChannelCollection contains a specific value.</summary>
public bool Contains(Channel value)
{
return base.List.Contains(value as object);
}
/// <summary>Gets the IChannel at the specified index.</summary>
public Channel this[int index]
{
get { return (base.List[index] as Channel ); }
}
}
}
|