You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
15 KiB
526 lines
15 KiB
/*
|
|
* document.cpp
|
|
*
|
|
* Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe <raabe@kde.org>
|
|
*
|
|
* 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 "document.h"
|
|
#include "article.h"
|
|
#include "image.h"
|
|
#include "textinput.h"
|
|
#include "tools_p.h"
|
|
|
|
#include <krfcdate.h>
|
|
#include <kurl.h>
|
|
|
|
#include <tqdatetime.h>
|
|
#include <tqdom.h>
|
|
#include <tqptrlist.h>
|
|
|
|
using namespace RSS;
|
|
|
|
struct Document::Private : public Shared
|
|
{
|
|
Private() : version(v0_90), image(NULL), textInput(NULL), language(en)
|
|
{
|
|
}
|
|
|
|
~Private()
|
|
{
|
|
delete textInput;
|
|
delete image;
|
|
}
|
|
|
|
Version version;
|
|
TQString title;
|
|
TQString description;
|
|
KURL link;
|
|
Image *image;
|
|
TextInput *textInput;
|
|
Article::List articles;
|
|
Language language;
|
|
TQString copyright;
|
|
TQDateTime pubDate;
|
|
TQDateTime lastBuildDate;
|
|
TQString rating;
|
|
KURL docs;
|
|
TQString managingEditor;
|
|
TQString webMaster;
|
|
HourList skipHours;
|
|
DayList skipDays;
|
|
};
|
|
|
|
Document::Document() : d(new Private)
|
|
{
|
|
}
|
|
|
|
Document::Document(const Document &other) : d(0)
|
|
{
|
|
*this = other;
|
|
}
|
|
|
|
Document::Document(const TQDomDocument &doc) : d(new Private)
|
|
{
|
|
TQString elemText;
|
|
TQDomNode rootNode = doc.documentElement();
|
|
|
|
// Determine the version of the present RSS markup.
|
|
TQString attr = rootNode.toElement().attribute(TQString::fromLatin1("xmlns"), TQString());
|
|
if (!attr.isNull()) {
|
|
/*
|
|
* Hardcoding these URLs is actually a bad idea, since the DTD doesn't
|
|
* dictate a specific namespace. Still, most RSS files seem to use
|
|
* these two, so I'll go for them now. If it turns out that many
|
|
* mirrors of this RSS namespace are in use, I'll probably have to
|
|
* distinguish the RSS versions by analyzing the relationship between
|
|
* the nodes.
|
|
*/
|
|
if (attr == TQString::fromLatin1("http://my.netscape.com/rdf/simple/0.9/"))
|
|
d->version = v0_90;
|
|
else if (attr == TQString::fromLatin1("http://purl.org/rss/1.0/")) {
|
|
d->version = v1_0;
|
|
}
|
|
} else {
|
|
attr = rootNode.toElement().attribute(TQString::fromLatin1("version"), TQString());
|
|
if (!attr.isNull()) {
|
|
if (attr == TQString::fromLatin1("0.91"))
|
|
d->version = v0_91;
|
|
else if (attr == TQString::fromLatin1("0.92"))
|
|
d->version = v0_92;
|
|
else if (attr == TQString::fromLatin1("0.93"))
|
|
d->version = v0_93;
|
|
else if (attr == TQString::fromLatin1("0.94"))
|
|
d->version = v0_94;
|
|
else if (attr == TQString::fromLatin1("2.0") || attr == TQString::fromLatin1("2"))
|
|
d->version = v2_0;
|
|
}
|
|
}
|
|
TQDomNode channelNode = rootNode.namedItem(TQString::fromLatin1("channel"));
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("title"))).isNull())
|
|
d->title = elemText;
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("description"))).isNull())
|
|
d->description = elemText;
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("link"))).isNull())
|
|
d->link = elemText;
|
|
|
|
/* This is ugly but necessary since RSS 0.90 and 1.0 have a different parent
|
|
* node for <image>, <textinput> and <item> than RSS 0.91-0.94 and RSS 2.0.
|
|
*/
|
|
TQDomNode parentNode;
|
|
if (d->version == v0_90 || d->version == v1_0)
|
|
parentNode = rootNode;
|
|
else
|
|
parentNode = channelNode;
|
|
|
|
TQDomNode n = parentNode.namedItem(TQString::fromLatin1("image"));
|
|
if (!n.isNull())
|
|
d->image = new Image(n);
|
|
|
|
n = parentNode.namedItem(TQString::fromLatin1("textinput"));
|
|
if (!n.isNull())
|
|
d->textInput = new TextInput(n);
|
|
|
|
// Our (hopefully faster) version of elementsByTagName()
|
|
for (n = parentNode.firstChild(); !n.isNull(); n = n.nextSibling()) {
|
|
const TQDomElement e = n.toElement();
|
|
if (e.tagName() == TQString::fromLatin1("item"))
|
|
d->articles.append(Article(e));
|
|
}
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("copyright"))).isNull())
|
|
d->copyright = elemText;
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("language"))).isNull()) {
|
|
if (elemText == TQString::fromLatin1("af"))
|
|
d->language = af;
|
|
else if (elemText == TQString::fromLatin1("sq"))
|
|
d->language = sq;
|
|
else if (elemText == TQString::fromLatin1("eu"))
|
|
d->language = eu;
|
|
else if (elemText == TQString::fromLatin1("be"))
|
|
d->language = be;
|
|
else if (elemText == TQString::fromLatin1("bg"))
|
|
d->language = bg;
|
|
else if (elemText == TQString::fromLatin1("ca"))
|
|
d->language = ca;
|
|
else if (elemText == TQString::fromLatin1("zh-cn"))
|
|
d->language = zh_cn;
|
|
else if (elemText == TQString::fromLatin1("zh-tw"))
|
|
d->language = zh_tw;
|
|
else if (elemText == TQString::fromLatin1("hr"))
|
|
d->language = hr;
|
|
else if (elemText == TQString::fromLatin1("cs"))
|
|
d->language = cs;
|
|
else if (elemText == TQString::fromLatin1("da"))
|
|
d->language = da;
|
|
else if (elemText == TQString::fromLatin1("nl"))
|
|
d->language = nl;
|
|
else if (elemText == TQString::fromLatin1("nl-be"))
|
|
d->language = nl_be;
|
|
else if (elemText == TQString::fromLatin1("nl-nl"))
|
|
d->language = nl_nl;
|
|
else if (elemText == TQString::fromLatin1("en"))
|
|
d->language = en;
|
|
else if (elemText == TQString::fromLatin1("en-au"))
|
|
d->language = en_au;
|
|
else if (elemText == TQString::fromLatin1("en-bz"))
|
|
d->language = en_bz;
|
|
else if (elemText == TQString::fromLatin1("en-ca"))
|
|
d->language = en_ca;
|
|
else if (elemText == TQString::fromLatin1("en-ie"))
|
|
d->language = en_ie;
|
|
else if (elemText == TQString::fromLatin1("en-jm"))
|
|
d->language = en_jm;
|
|
else if (elemText == TQString::fromLatin1("en-nz"))
|
|
d->language = en_nz;
|
|
else if (elemText == TQString::fromLatin1("en-ph"))
|
|
d->language = en_ph;
|
|
else if (elemText == TQString::fromLatin1("en-za"))
|
|
d->language = en_za;
|
|
else if (elemText == TQString::fromLatin1("en-tt"))
|
|
d->language = en_tt;
|
|
else if (elemText == TQString::fromLatin1("en-gb"))
|
|
d->language = en_gb;
|
|
else if (elemText == TQString::fromLatin1("en-us"))
|
|
d->language = en_us;
|
|
else if (elemText == TQString::fromLatin1("en-zw"))
|
|
d->language = en_zw;
|
|
else if (elemText == TQString::fromLatin1("fo"))
|
|
d->language = fo;
|
|
else if (elemText == TQString::fromLatin1("fi"))
|
|
d->language = fi;
|
|
else if (elemText == TQString::fromLatin1("fr"))
|
|
d->language = fr;
|
|
else if (elemText == TQString::fromLatin1("fr-be"))
|
|
d->language = fr_be;
|
|
else if (elemText == TQString::fromLatin1("fr-ca"))
|
|
d->language = fr_ca;
|
|
else if (elemText == TQString::fromLatin1("fr-fr"))
|
|
d->language = fr_fr;
|
|
else if (elemText == TQString::fromLatin1("fr-lu"))
|
|
d->language = fr_lu;
|
|
else if (elemText == TQString::fromLatin1("fr-mc"))
|
|
d->language = fr_mc;
|
|
else if (elemText == TQString::fromLatin1("fr-ch"))
|
|
d->language = fr_ch;
|
|
else if (elemText == TQString::fromLatin1("gl"))
|
|
d->language = gl;
|
|
else if (elemText == TQString::fromLatin1("gd"))
|
|
d->language = gd;
|
|
else if (elemText == TQString::fromLatin1("de"))
|
|
d->language = de;
|
|
else if (elemText == TQString::fromLatin1("de-at"))
|
|
d->language = de_at;
|
|
else if (elemText == TQString::fromLatin1("de-de"))
|
|
d->language = de_de;
|
|
else if (elemText == TQString::fromLatin1("de-li"))
|
|
d->language = de_li;
|
|
else if (elemText == TQString::fromLatin1("de-lu"))
|
|
d->language = de_lu;
|
|
else if (elemText == TQString::fromLatin1("de-ch"))
|
|
d->language = de_ch;
|
|
else if (elemText == TQString::fromLatin1("el"))
|
|
d->language = el;
|
|
else if (elemText == TQString::fromLatin1("hu"))
|
|
d->language = hu;
|
|
else if (elemText == TQString::fromLatin1("is"))
|
|
d->language = is;
|
|
else if (elemText == TQString::fromLatin1("id"))
|
|
d->language = id;
|
|
else if (elemText == TQString::fromLatin1("ga"))
|
|
d->language = ga;
|
|
else if (elemText == TQString::fromLatin1("it"))
|
|
d->language = it;
|
|
else if (elemText == TQString::fromLatin1("it-it"))
|
|
d->language = it_it;
|
|
else if (elemText == TQString::fromLatin1("it-ch"))
|
|
d->language = it_ch;
|
|
else if (elemText == TQString::fromLatin1("ja"))
|
|
d->language = ja;
|
|
else if (elemText == TQString::fromLatin1("ko"))
|
|
d->language = ko;
|
|
else if (elemText == TQString::fromLatin1("mk"))
|
|
d->language = mk;
|
|
else if (elemText == TQString::fromLatin1("no"))
|
|
d->language = no;
|
|
else if (elemText == TQString::fromLatin1("pl"))
|
|
d->language = pl;
|
|
else if (elemText == TQString::fromLatin1("pt"))
|
|
d->language = pt;
|
|
else if (elemText == TQString::fromLatin1("pt-br"))
|
|
d->language = pt_br;
|
|
else if (elemText == TQString::fromLatin1("pt-pt"))
|
|
d->language = pt_pt;
|
|
else if (elemText == TQString::fromLatin1("ro"))
|
|
d->language = ro;
|
|
else if (elemText == TQString::fromLatin1("ro-mo"))
|
|
d->language = ro_mo;
|
|
else if (elemText == TQString::fromLatin1("ro-ro"))
|
|
d->language = ro_ro;
|
|
else if (elemText == TQString::fromLatin1("ru"))
|
|
d->language = ru;
|
|
else if (elemText == TQString::fromLatin1("ru-mo"))
|
|
d->language = ru_mo;
|
|
else if (elemText == TQString::fromLatin1("ru-ru"))
|
|
d->language = ru_ru;
|
|
else if (elemText == TQString::fromLatin1("sr"))
|
|
d->language = sr;
|
|
else if (elemText == TQString::fromLatin1("sk"))
|
|
d->language = sk;
|
|
else if (elemText == TQString::fromLatin1("sl"))
|
|
d->language = sl;
|
|
else if (elemText == TQString::fromLatin1("es"))
|
|
d->language = es;
|
|
else if (elemText == TQString::fromLatin1("es-ar"))
|
|
d->language = es_ar;
|
|
else if (elemText == TQString::fromLatin1("es-bo"))
|
|
d->language = es_bo;
|
|
else if (elemText == TQString::fromLatin1("es-cl"))
|
|
d->language = es_cl;
|
|
else if (elemText == TQString::fromLatin1("es-co"))
|
|
d->language = es_co;
|
|
else if (elemText == TQString::fromLatin1("es-cr"))
|
|
d->language = es_cr;
|
|
else if (elemText == TQString::fromLatin1("es-do"))
|
|
d->language = es_do;
|
|
else if (elemText == TQString::fromLatin1("es-ec"))
|
|
d->language = es_ec;
|
|
else if (elemText == TQString::fromLatin1("es-sv"))
|
|
d->language = es_sv;
|
|
else if (elemText == TQString::fromLatin1("es-gt"))
|
|
d->language = es_gt;
|
|
else if (elemText == TQString::fromLatin1("es-hn"))
|
|
d->language = es_hn;
|
|
else if (elemText == TQString::fromLatin1("es-mx"))
|
|
d->language = es_mx;
|
|
else if (elemText == TQString::fromLatin1("es-ni"))
|
|
d->language = es_ni;
|
|
else if (elemText == TQString::fromLatin1("es-pa"))
|
|
d->language = es_pa;
|
|
else if (elemText == TQString::fromLatin1("es-py"))
|
|
d->language = es_py;
|
|
else if (elemText == TQString::fromLatin1("es-pe"))
|
|
d->language = es_pe;
|
|
else if (elemText == TQString::fromLatin1("es-pr"))
|
|
d->language = es_pr;
|
|
else if (elemText == TQString::fromLatin1("es-es"))
|
|
d->language = es_es;
|
|
else if (elemText == TQString::fromLatin1("es-uy"))
|
|
d->language = es_uy;
|
|
else if (elemText == TQString::fromLatin1("es-ve"))
|
|
d->language = es_ve;
|
|
else if (elemText == TQString::fromLatin1("sv"))
|
|
d->language = sv;
|
|
else if (elemText == TQString::fromLatin1("sv-fi"))
|
|
d->language = sv_fi;
|
|
else if (elemText == TQString::fromLatin1("sv-se"))
|
|
d->language = sv_se;
|
|
else if (elemText == TQString::fromLatin1("tr"))
|
|
d->language = tr;
|
|
else if (elemText == TQString::fromLatin1("uk"))
|
|
d->language = uk;
|
|
else
|
|
d->language = UndefinedLanguage;
|
|
}
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("pubDate"))).isNull()) {
|
|
time_t _time = KRFCDate::parseDate(elemText);
|
|
/* \bug This isn't really the right way since it will set the date to
|
|
* Jan 1 1970, 1:00:00 if the passed date was invalid; this means that
|
|
* we cannot distinguish between that date, and invalid values. :-/
|
|
*/
|
|
d->pubDate.setTime_t(_time);
|
|
}
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("dc:date"))).isNull()) {
|
|
time_t _time = KRFCDate::parseDateISO8601(elemText);
|
|
/* \bug This isn't really the right way since it will set the date to
|
|
* Jan 1 1970, 1:00:00 if the passed date was invalid; this means that
|
|
* we cannot distinguish between that date, and invalid values. :-/
|
|
*/
|
|
d->pubDate.setTime_t(_time);
|
|
}
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("lastBuildDate"))).isNull()) {
|
|
time_t _time = KRFCDate::parseDate(elemText);
|
|
d->lastBuildDate.setTime_t(_time);
|
|
}
|
|
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("rating"))).isNull())
|
|
d->rating = elemText;
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("docs"))).isNull())
|
|
d->docs = elemText;
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("managingEditor"))).isNull())
|
|
d->managingEditor = elemText;
|
|
if (!(elemText = extractNode(channelNode, TQString::fromLatin1("webMaster"))).isNull())
|
|
d->webMaster = elemText;
|
|
|
|
n = channelNode.namedItem(TQString::fromLatin1("skipHours"));
|
|
if (!n.isNull())
|
|
for (TQDomElement e = n.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement())
|
|
if (e.tagName() == TQString::fromLatin1("hour"))
|
|
d->skipHours.append(e.text().toUInt());
|
|
|
|
n = channelNode.namedItem(TQString::fromLatin1("skipDays"));
|
|
if (!n.isNull()) {
|
|
Day day;
|
|
TQString elemText;
|
|
for (TQDomElement e = n.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement())
|
|
if (e.tagName() == TQString::fromLatin1("day")) {
|
|
elemText = e.text().lower();
|
|
if (elemText == TQString::fromLatin1("monday"))
|
|
day = Monday;
|
|
else if (elemText == TQString::fromLatin1("tuesday"))
|
|
day = Tuesday;
|
|
else if (elemText == TQString::fromLatin1("wednesday"))
|
|
day = Wednesday;
|
|
else if (elemText == TQString::fromLatin1("thursday"))
|
|
day = Thursday;
|
|
else if (elemText == TQString::fromLatin1("friday"))
|
|
day = Friday;
|
|
else if (elemText == TQString::fromLatin1("saturday"))
|
|
day = Saturday;
|
|
else if (elemText == TQString::fromLatin1("sunday"))
|
|
day = Sunday;
|
|
else
|
|
day = UndefinedDay;
|
|
if (day != UndefinedDay)
|
|
d->skipDays.append(day);
|
|
}
|
|
}
|
|
}
|
|
|
|
Document::~Document()
|
|
{
|
|
if (d->deref())
|
|
delete d;
|
|
}
|
|
|
|
Version Document::version() const
|
|
{
|
|
return d->version;
|
|
}
|
|
|
|
TQString Document::verbVersion() const
|
|
{
|
|
switch (d->version) {
|
|
case v0_90: return TQString::fromLatin1("0.90");
|
|
case v0_91: return TQString::fromLatin1("0.91");
|
|
case v0_92: return TQString::fromLatin1("0.92");
|
|
case v0_93: return TQString::fromLatin1("0.93");
|
|
case v0_94: return TQString::fromLatin1("0.94");
|
|
case v1_0: return TQString::fromLatin1("1.0");
|
|
case v2_0: return TQString::fromLatin1("2.0");
|
|
}
|
|
return TQString();
|
|
}
|
|
|
|
TQString Document::title() const
|
|
{
|
|
return d->title;
|
|
}
|
|
|
|
TQString Document::description() const
|
|
{
|
|
return d->description;
|
|
}
|
|
|
|
const KURL &Document::link() const
|
|
{
|
|
return d->link;
|
|
}
|
|
|
|
Image *Document::image()
|
|
{
|
|
return d->image;
|
|
}
|
|
|
|
const Image *Document::image() const
|
|
{
|
|
return d->image;
|
|
}
|
|
|
|
TextInput *Document::textInput()
|
|
{
|
|
return d->textInput;
|
|
}
|
|
|
|
const TextInput *Document::textInput() const
|
|
{
|
|
return d->textInput;
|
|
}
|
|
|
|
const Article::List &Document::articles() const
|
|
{
|
|
return d->articles;
|
|
}
|
|
|
|
Language Document::language() const
|
|
{
|
|
return d->language;
|
|
}
|
|
|
|
TQString Document::copyright() const
|
|
{
|
|
return d->copyright;
|
|
}
|
|
|
|
const TQDateTime &Document::pubDate() const
|
|
{
|
|
return d->pubDate;
|
|
}
|
|
|
|
const TQDateTime &Document::lastBuildDate() const
|
|
{
|
|
return d->lastBuildDate;
|
|
}
|
|
|
|
TQString Document::rating() const
|
|
{
|
|
return d->rating;
|
|
}
|
|
|
|
const KURL &Document::docs() const
|
|
{
|
|
return d->docs;
|
|
}
|
|
|
|
TQString Document::managingEditor() const
|
|
{
|
|
return d->managingEditor;
|
|
}
|
|
|
|
TQString Document::webMaster() const
|
|
{
|
|
return d->webMaster;
|
|
}
|
|
|
|
const HourList &Document::skipHours() const
|
|
{
|
|
return d->skipHours;
|
|
}
|
|
|
|
const DayList &Document::skipDays() const
|
|
{
|
|
return d->skipDays;
|
|
}
|
|
|
|
Document &Document::operator=(const Document &other)
|
|
{
|
|
if (this != &other) {
|
|
other.d->ref();
|
|
if (d && d->deref())
|
|
delete d;
|
|
d = other.d;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// vim:noet:ts=4
|