summaryrefslogtreecommitdiff
path: root/src/RssFeedParser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/RssFeedParser.cc')
-rw-r--r--src/RssFeedParser.cc180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/RssFeedParser.cc b/src/RssFeedParser.cc
new file mode 100644
index 0000000..db5558e
--- /dev/null
+++ b/src/RssFeedParser.cc
@@ -0,0 +1,180 @@
+/*
+ * vdr-vodcatcher - A plugin for the Linux Video Disk Recorder
+ * Copyright (c) 2007 - 2008 Tobias Grimm <vdr@e-tobi.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * $Id: RssFeedParser.cc 7652 2008-08-05 21:37:57Z svntobi $
+ *
+ */
+
+#include "RssFeedParser.h"
+#include "HtmlToText.h"
+#include "Feed.h"
+#include "IDownloadCache.h"
+#include "tinyxml.h"
+#include "Item.h"
+
+using namespace std;
+
+RssFeedParser::RssFeedParser(const IDownloadCache& downloadCache) :
+ _downloadCache(downloadCache)
+{
+}
+
+bool RssFeedParser::Parse(Feed& feed) const
+{
+ RefPtr<istream> source(_downloadCache.CreateStreamByUrl(feed.GetUrl()));
+
+ if (source.IsAssigned())
+ {
+ RefPtr<TiXmlDocument> rssDoc = CreateRssDocument(*source);
+
+ TiXmlHandle docHandle(rssDoc.get());
+ const TiXmlNode* channelNode = docHandle.FirstChild("rss").FirstChild("channel").Node();
+ if (channelNode)
+ {
+ feed.SetTitle(GetChildValue(*channelNode, "title"));
+
+ feed.SetTimeToLive(StringToIntDefault(GetChildValue(*channelNode, "ttl"), feed.GetTimeToLive()));
+
+ for (const TiXmlNode* itemNode = channelNode->FirstChild("item"); itemNode; itemNode
+ = itemNode->NextSibling("item"))
+ {
+ Item item = ParseItem(*itemNode);
+ feed.AddItem(item);
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+RefPtr<TiXmlDocument> RssFeedParser::CreateRssDocument(istream& rssStream) const
+{
+ RefPtr<TiXmlDocument> rssDoc(new TiXmlDocument());
+ rssStream >> *rssDoc;
+ if (!rssDoc->Error())
+ {
+ return rssDoc;
+ }
+
+ return RefPtr<TiXmlDocument>();
+}
+
+string RssFeedParser::GetValue(const TiXmlNode& node) const
+{
+ const TiXmlNode* textNode = node.FirstChild();
+ if (textNode)
+ {
+ return textNode->Value();
+ }
+ return "";
+}
+
+const string RssFeedParser::GetAttribute(const TiXmlElement& element, string name) const
+{
+ const string* value = element.Attribute(name);
+ if (value != NULL)
+ {
+ return *value;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+string RssFeedParser::GetChildValue(const TiXmlNode& root, const string& childName) const
+{
+ const TiXmlNode* childNode = root.FirstChild(childName);
+ if (childNode)
+ {
+ return GetValue(*childNode);
+ }
+
+ return "";
+}
+
+Item RssFeedParser::ParseItem(const TiXmlNode& itemNode) const
+{
+ string title = GetChildValue(itemNode, "title");
+ string description = GetChildValue(itemNode, "description");
+ string date = GetChildValue(itemNode, "pubDate");
+
+ Item item(title, Rfc822DateTime(date), HtmlToText::Convert(description));
+
+ const TiXmlElement* subFeedElement = itemNode.FirstChildElement("videocast:subfeed");
+ if (subFeedElement)
+ {
+ item.SetSubFeedUrl(GetAttribute(*subFeedElement, "url"));
+ }
+
+ const TiXmlElement* enclosureElement = itemNode.FirstChildElement("enclosure");
+ if (enclosureElement)
+ {
+ string type = GetAttribute(*enclosureElement, "type");
+ if (type.find("video/") == 0)
+ {
+ item.SetVideoCastStream(Low, GetAttribute(*enclosureElement, "url"));
+ }
+ }
+
+ const TiXmlElement* streamElement = itemNode.FirstChildElement("videocast:stream");
+ while (streamElement)
+ {
+ ParseStreamElement(*streamElement, item);
+ streamElement = streamElement->NextSiblingElement("videocast:stream");
+ }
+
+ const TiXmlElement* streamInfoElement = itemNode.FirstChildElement("videocast:streaminfo");
+ if (streamInfoElement)
+ {
+ item.SetStreamLength(GetAttribute(*streamInfoElement, "length"));
+ }
+
+ return item;
+}
+
+void RssFeedParser::ParseStreamElement(const TiXmlElement& streamElement, Item& item) const
+{
+ string quality = GetAttribute(streamElement, "quality");
+ string url = GetAttribute(streamElement, "url");
+
+ if (quality == "high")
+ {
+ item.SetVideoCastStream(High, url);
+ }
+ else if (quality == "medium")
+ {
+ item.SetVideoCastStream(Medium, url);
+ }
+ else if (quality == "low")
+ {
+ item.SetVideoCastStream(Low, url);
+ }
+}
+
+int RssFeedParser::StringToIntDefault(const string& str, const int defaultValue) const
+{
+ istringstream tempStream(str);
+ int value;
+ if (!(tempStream >> value))
+ {
+ value = defaultValue;
+ }
+ return value;
+}