diff options
Diffstat (limited to 'plugins/rssfeed/rss/article.cpp')
-rw-r--r-- | plugins/rssfeed/rss/article.cpp | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/plugins/rssfeed/rss/article.cpp b/plugins/rssfeed/rss/article.cpp new file mode 100644 index 0000000..571490e --- /dev/null +++ b/plugins/rssfeed/rss/article.cpp @@ -0,0 +1,270 @@ +/* + * article.cpp + * + * Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe <[email protected]> + * + * 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. For licensing and distribution details, check the + * accompanying file 'COPYING'. + */ +#include "article.h" +#include "tools_p.h" + +#include <kdebug.h> +#include <krfcdate.h> +#include <kurl.h> +#include <kurllabel.h> +#include <kmdcodec.h> + +#include <qdatetime.h> +#include <qdom.h> + +using namespace RSS; +namespace RSS +{ + KMD5 md5Machine; +} + +struct Article::Private : public Shared +{ + QString title; + KURL link; + QString description; + QDateTime pubDate; + QString guid; + bool guidIsPermaLink; + MetaInfoMap meta; + KURL commentsLink; + int numComments; +}; + +Article::Article() : d(new Private) +{ +} + +Article::Article(const Article &other) : d(0) +{ + *this = other; +} + +Article::Article(const QDomNode &node, Format format) : d(new Private) +{ + QString elemText; + + d->numComments=0; + + if (!(elemText = extractNode(node, QString::fromLatin1("title"))).isNull()) + d->title = elemText; + + + QDomNode n; + bool foundTorrentEnclosure = false; + for (n = node.firstChild(); !n.isNull(); n = n.nextSibling()) { + const QDomElement e = n.toElement(); + if ( (e.tagName()==QString::fromLatin1("enclosure") ) ) + { + QString enclosureAttr = e.attribute(QString::fromLatin1("type")); + if (!enclosureAttr.isNull() ) + { + if (enclosureAttr == "application/x-bittorrent") + { + enclosureAttr = e.attribute(QString::fromLatin1("url")); + if (!enclosureAttr.isNull() ) + { + d->link=enclosureAttr; + foundTorrentEnclosure = true; + break; + } + } + } + } + } + + if (!foundTorrentEnclosure) + { + if (format==AtomFeed) + { + QDomNode n; + for (n = node.firstChild(); !n.isNull(); n = n.nextSibling()) { + const QDomElement e = n.toElement(); + if ( (e.tagName()==QString::fromLatin1("link")) && + (e.attribute(QString::fromLatin1("rel"))==QString::fromLatin1("alternate"))) + { + d->link=n.toElement().attribute(QString::fromLatin1("href")); + break; + } + } + } + else + { + if (!(elemText = extractNode(node, QString::fromLatin1("link"))).isNull()) + d->link = elemText; + } + } + + + // prefer content/content:encoded over summary/description for feeds that provide it + QString tagName=(format==AtomFeed)? QString::fromLatin1("content"): QString::fromLatin1("content:encoded"); + + if (!(elemText = extractNode(node, tagName, false)).isNull()) + d->description = elemText; + + if (d->description.isEmpty()) + { + if (!(elemText = extractNode(node, QString::fromLatin1("body"), false)).isNull()) + d->description = elemText; + + if (d->description.isEmpty()) // 3rd try: see http://www.intertwingly.net/blog/1299.html + { + if (!(elemText = extractNode(node, QString::fromLatin1((format==AtomFeed)? "summary" : "description"), false)).isNull()) + d->description = elemText; + } + } + + if (!(elemText = extractNode(node, QString::fromLatin1((format==AtomFeed)? "created": "pubDate"))).isNull()) + { + time_t _time; + if (format==AtomFeed) + _time = parseISO8601Date(elemText); + else + _time = KRFCDate::parseDate(elemText); + + // 0 means invalid, not epoch (it returns epoch+1 when it parsed epoch, see the KRFCDate::parseDate() docs) + if (_time != 0) + d->pubDate.setTime_t(_time); + } + if (!(elemText = extractNode(node, QString::fromLatin1("dc:date"))).isNull()) + { + time_t _time = parseISO8601Date(elemText); + + // 0 means invalid, not epoch (it returns epoch+1 when it parsed epoch, see the KRFCDate::parseDate() docs) + if (_time != 0) + d->pubDate.setTime_t(_time); + } + + //no luck so far - so let's set it to the current time + if (!d->pubDate.isValid()) + { + d->pubDate = QDateTime::currentDateTime(); + } + + + if (!(elemText = extractNode(node, QString::fromLatin1("wfw:comment"))).isNull()) { + d->commentsLink = elemText; + } + + if (!(elemText = extractNode(node, QString::fromLatin1("slash:comments"))).isNull()) { + d->numComments = elemText.toInt(); + } + + tagName=(format==AtomFeed)? QString::fromLatin1("id"): QString::fromLatin1("guid"); + n = node.namedItem(tagName); + if (!n.isNull()) { + d->guidIsPermaLink = (format==AtomFeed)? false : true; + if (n.toElement().attribute(QString::fromLatin1("isPermaLink"), "true") == "false") d->guidIsPermaLink = false; + + if (!(elemText = extractNode(node, tagName)).isNull()) + d->guid = elemText; + } + + if(d->guid.isEmpty()) { + d->guidIsPermaLink = false; + + md5Machine.reset(); + QDomNode n(node); + md5Machine.update(d->title.utf8()); + md5Machine.update(d->description.utf8()); + d->guid = QString(md5Machine.hexDigest().data()); + d->meta[QString::fromLatin1("guidIsHash")] = QString::fromLatin1("true"); + } + + for (QDomNode i = node.firstChild(); !i.isNull(); i = i.nextSibling()) + { + if (i.isElement() && i.toElement().tagName() == QString::fromLatin1("metaInfo:meta")) + { + QString type = i.toElement().attribute(QString::fromLatin1("type")); + d->meta[type] = i.toElement().text(); + } + } +} + +Article::~Article() +{ + if (d->deref()) + delete d; +} + +QString Article::title() const +{ + return d->title; +} + +const KURL &Article::link() const +{ + return d->link; +} + +QString Article::description() const +{ + return d->description; +} + +QString Article::guid() const +{ + return d->guid; +} + +bool Article::guidIsPermaLink() const +{ + return d->guidIsPermaLink; +} + +const QDateTime &Article::pubDate() const +{ + return d->pubDate; +} + +const KURL &Article::commentsLink() const +{ + return d->commentsLink; +} + +int Article::comments() const +{ + return d->numComments; +} + + +QString Article::meta(const QString &key) const +{ + return d->meta[key]; +} + +KURLLabel *Article::widget(QWidget *parent, const char *name) const +{ + KURLLabel *label = new KURLLabel(d->link.url(), d->title, parent, name); + label->setUseTips(true); + if (!d->description.isNull()) + label->setTipText(d->description); + + return label; +} + +Article &Article::operator=(const Article &other) +{ + if (this != &other) { + other.d->ref(); + if (d && d->deref()) + delete d; + d = other.d; + } + return *this; +} + +bool Article::operator==(const Article &other) const +{ + return d->guid == other.guid(); +} + +// vim:noet:ts=4 |