/*
* Box Socialâ„¢
* http://boxsocial.net/
* Copyright © 2007, David Lachlan Smith
*
* $Id:$
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* This file is based on skmRSS by Scott Mitchell
* http://www.4GuysFromRolla.com/ScottMitchell
*/
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Text.RegularExpressions;
using System.Collections;
namespace BoxSocial.Internals
{
///
/// Summary description for RssDocument.
///
[XmlRootAttribute("rss")]
public class RssDocument
{
[XmlAttribute]
public string version;
[XmlElement("channel")]
public RssChannel[] channels;
public RssDocument()
{
channels = new RssChannel[1];
channels[0] = new RssChannel();
}
}
public class RssChannel
{
[XmlElement]
public string title;
public string link;
[XmlElementAttribute(IsNullable = false)]
public string description;
private DateTime pubDate;
public string generator;
public string category;
public string copyright;
[XmlElement("pubDate")]
public string pubdate
{
get
{
string temp = pubDate.ToString(@"ddd, dd MMM yyyy hh:mm:ss zzz");
if (temp.Length > 5)
temp = temp.Substring(0, temp.Length - 3) + temp.Substring(temp.Length - 2, 2);
return temp;
}
set
{
pubDate = DateTimeExt.Parse(value);
}
}
//[XmlArrayAttribute("item")]
[XmlElement("item")]
public RssDocumentItem[] items;
public RssChannel()
{
generator = "Buddy";
description = "";
}
}
public class RssChannelImage
{
}
public class RssChannelTtl
{
}
public class RssDocumentItem
{
public string title;
public string link;
public string comments;
private DateTime pubDate;
public string category;
public string guid;
public string content;
//[XmlAnyElement(NodeType = XmlNodeType.CDATA)]
public string description;
[XmlElement("dc:creator")]
public string dcCreator;
public string author;
[XmlElement("pubDate")]
public string pubdate
{
get
{
string temp = pubDate.ToString(@"ddd, dd MMM yyyy hh:mm:ss zzz");
if (temp.Length > 5)
temp = temp.Substring(0, temp.Length - 3) + temp.Substring(temp.Length - 2, 2);
return temp;
}
set
{
pubDate = DateTimeExt.Parse(value);
}
}
public RssDocumentItem()
{
}
}
///
/// DateTimeExt is able to parse RFC2822/RFC822 formatted dates.
///
public class DateTimeExt
{
private static Regex rfc2822 = new Regex(@"\s*(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?(\d{1,2})\s+(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+(\d{2,})\s+(\d{2})\s*:\s*(\d{2})\s*(?::\s*(\d{2}))?\s+([+\-]\d{4}|UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])", RegexOptions.Compiled);
private static ArrayList months = new ArrayList(new string[]{"ZeroIndex","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" });
/// Parse is able to parse RFC2822/RFC822 formatted dates.
/// It has a fallback mechanism: if the string does not match,
/// the normal DateTime.Parse() is called. If that throws a FormatException
/// the current date (DateTime.Now) will be returned.
public static DateTime Parse(string dateTimeString)
{
if (dateTimeString == null)
return DateTime.Now;
if (dateTimeString.Trim().Length == 0)
return DateTime.Now;
Match m = rfc2822.Match(dateTimeString);
if (m.Success)
{
try
{
int dd = Int32.Parse(m.Groups[1].Value);
int mth = months.IndexOf(m.Groups[2].Value);
int yy = Int32.Parse(m.Groups[3].Value);
// following year completion is compliant with RFC 2822.
yy = (yy < 50 ? 2000 + yy: (yy < 1000 ? 1900 + yy: yy));
int hh = Int32.Parse(m.Groups[4].Value);
int mm = Int32.Parse(m.Groups[5].Value);
int ss = Int32.Parse(m.Groups[6].Value);
string zone = m.Groups[7].Value;
DateTime xd = new DateTime(yy, mth, dd, hh, mm, ss);
return xd.AddHours(-RFCTimeZoneToGMTBias(zone));
}
catch
{
for (int i = 0; i < m.Groups.Count; i++)
{
Console.WriteLine("Found:'" + m.Groups[i] + "' at "
+ m.Groups[i].Index);
}
}
}
else
{
try
{
return DateTime.Parse(dateTimeString);
}
catch
{
}
}
return DateTime.Now;
}
private DateTimeExt(){}
private struct TZB
{
public TZB(string z, int b) { Zone = z; Bias = b; }
public string Zone;
public int Bias;
}
private const int timeZones = 35;
private static TZB[] ZoneBias = new TZB[timeZones]
{
new TZB("GMT", 0), new TZB("UT", 0),
new TZB("EST", -5*60), new TZB("EDT", -4*60),
new TZB("CST", -6*60), new TZB("CDT", -5*60),
new TZB("MST", -7*60), new TZB("MDT", -6*60),
new TZB("PST", -8*60), new TZB("PDT", -7*60),
new TZB("Z", 0), new TZB("A", -1*60),
new TZB("B", -2*60), new TZB("C", -3*60),
new TZB("D", -4*60), new TZB("E", -5*60),
new TZB("F", -6*60), new TZB("G", -7*60),
new TZB("H", -8*60), new TZB("I", -9*60),
new TZB("K", -10*60), new TZB("L", -11*60),
new TZB("M", -12*60), new TZB("N", 1*60),
new TZB("O", 2*60), new TZB("P", 3*60),
new TZB("Q", 4*60), new TZB("R", 3*60),
new TZB("S", 6*60), new TZB("T", 3*60),
new TZB("U", 8*60), new TZB("V", 3*60),
new TZB("W", 10*60), new TZB("X", 3*60),
new TZB("Y", 12*60)
};
private static double RFCTimeZoneToGMTBias(string zone)
{
string s;
if ( zone.IndexOfAny(new char[]{'+', '-'}) == 0 ) // +hhmm format
{
int fact = (zone.Substring(0,1) == "-"? -1: 1);
s = zone.Substring(1).TrimEnd();
double hh = Math.Min(23, Int32.Parse(s.Substring(0,2)));
double mm = Math.Min(59, Int32.Parse(s.Substring(2,2)))/60;
return fact * (hh+mm);
}
else
{ // named format
s = zone.ToUpper().Trim();
for (int i = 0; i < timeZones; i++)
if (ZoneBias[i].Zone.Equals(s))
{
return ZoneBias[i].Bias / 60;
}
}
return 0.0;
}
}
}