akregator/src/librss

article.cpp
1/*
2 * article.cpp
3 *
4 * Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe <raabe@kde.org>
5 *
6 * This program is distributed in the hope that it will be useful, but WITHOUT
7 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8 * FOR A PARTICULAR PURPOSE. For licensing and distribution details, check the
9 * accompanying file 'COPYING'.
10 */
11#include "article.h"
12#include "tools_p.h"
13#include "enclosure.h"
14#include "category.h"
15
16#include <kdebug.h>
17#include <krfcdate.h>
18#include <kurl.h>
19#include <kurllabel.h>
20#include <kmdcodec.h>
21
22#include <tqdatetime.h>
23#include <tqdom.h>
24
25using namespace RSS;
26namespace RSS
27{
28 KMD5 md5Machine;
29}
30
31struct Article::Private : public Shared
32{
33 TQString title;
34 KURL link;
35 TQString description;
36 TQDateTime pubDate;
37 TQString guid;
38 TQString author;
39 bool guidIsPermaLink;
40 MetaInfoMap meta;
41 KURL commentsLink;
42 int numComments;
43 Enclosure enclosure;
44 TQValueList<Category> categories;
45};
46
47Article::Article() : d(new Private)
48{
49}
50
51Article::Article(const Article &other) : d(0)
52{
53 *this = other;
54}
55
56Enclosure Article::enclosure() const
57{
58 return d->enclosure;
59}
60
61TQValueList<Category> Article::categories() const
62{
63 return d->categories;
64}
65
66
67Article::Article(const TQDomNode &node, Format format, Version version) : d(new Private)
68{
69 TQString elemText;
70
71 d->numComments=0;
72
73 if (!(elemText = extractTitle(node)).isNull())
74 d->title = elemText;
75
76 if (format==AtomFeed)
77 {
78 TQDomNode n;
79 for (n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
80 const TQDomElement e = n.toElement();
81 if ( (e.tagName()==TQString::fromLatin1("link")) &&
82 (e.attribute(TQString::fromLatin1("rel"), TQString::fromLatin1("alternate")) == TQString::fromLatin1("alternate")))
83 {
84 d->link=n.toElement().attribute(TQString::fromLatin1("href"));
85 break;
86 }
87 }
88 }
89 else
90 {
91 if (!(elemText = extractNode(node, TQString::fromLatin1("link"))).isNull())
92 d->link = elemText;
93 }
94
95
96 // prefer content/content:encoded over summary/description for feeds that provide it
97 TQString tagName=(format==AtomFeed)? TQString::fromLatin1("content"): TQString::fromLatin1("content:encoded");
98
99 if (!(elemText = extractNode(node, tagName, false)).isNull())
100 d->description = elemText;
101
102 if (d->description.isEmpty())
103 {
104 if (!(elemText = extractNode(node, TQString::fromLatin1("body"), false)).isNull())
105 d->description = elemText;
106
107 if (d->description.isEmpty()) // 3rd try: see http://www.intertwingly.net/blog/1299.html
108 {
109 if (!(elemText = extractNode(node, TQString::fromLatin1((format==AtomFeed)? "summary" : "description"), false)).isNull())
110 d->description = elemText;
111 }
112 }
113
114 time_t time = 0;
115
116 if (format == AtomFeed)
117 {
118 if (version == vAtom_1_0)
119 elemText = extractNode(node, TQString::fromLatin1("updated"));
120 else
121 elemText = extractNode(node, TQString::fromLatin1("issued"));
122
123 if (!elemText.isNull())
124 time = parseISO8601Date(elemText);
125 }
126 else
127 {
128 elemText = extractNode(node, TQString::fromLatin1("pubDate"));
129 if (!elemText.isNull())
130 time = KRFCDate::parseDate(elemText);
131 }
132
133 if (!(elemText = extractNode(node, TQString::fromLatin1("dc:date"))).isNull())
134 {
135 time = parseISO8601Date(elemText);
136 }
137
138 // 0 means invalid, not epoch (parsers return epoch+1 when parsing epoch, see the KRFCDate::parseDate() docs)
139 if (time != 0)
140 d->pubDate.setTime_t(time);
141
142 if (!(elemText = extractNode(node, TQString::fromLatin1("wfw:comment"))).isNull()) {
143 d->commentsLink = elemText;
144 }
145
146 if (!(elemText = extractNode(node, TQString::fromLatin1("slash:comments"))).isNull()) {
147 d->numComments = elemText.toInt();
148 }
149
150 TQDomElement element = TQDomNode(node).toElement();
151
152 // in RSS 1.0, we use <item about> attribute as ID
153 // FIXME: pass format version instead of checking for attribute
154
155 if (!element.isNull() && element.hasAttribute(TQString::fromLatin1("rdf:about")))
156 {
157 d->guid = element.attribute(TQString::fromLatin1("rdf:about")); // HACK: using ns properly did not work
158 d->guidIsPermaLink = false;
159 }
160 else
161 {
162 tagName=(format==AtomFeed)? TQString::fromLatin1("id"): TQString::fromLatin1("guid");
163 TQDomNode n = node.namedItem(tagName);
164 if (!n.isNull())
165 {
166 d->guidIsPermaLink = (format==AtomFeed)? false : true;
167 if (n.toElement().attribute(TQString::fromLatin1("isPermaLink"), "true") == "false") d->guidIsPermaLink = false;
168 if (!(elemText = extractNode(node, tagName)).isNull())
169 d->guid = elemText;
170 }
171 }
172
173 if(d->guid.isEmpty()) {
174 d->guidIsPermaLink = false;
175
176 md5Machine.reset();
177 TQDomNode n(node);
178 md5Machine.update(d->title.utf8());
179 md5Machine.update(d->description.utf8());
180 d->guid = TQString(md5Machine.hexDigest().data());
181 d->meta[TQString::fromLatin1("guidIsHash")] = TQString::fromLatin1("true");
182 }
183
184 TQDomNode enclosure = element.namedItem(TQString::fromLatin1("enclosure"));
185 if (enclosure.isElement())
186 d->enclosure = Enclosure::fromXML(enclosure.toElement());
187
188 d->author = parseItemAuthor(element, format, version);
189
190 for (TQDomNode i = node.firstChild(); !i.isNull(); i = i.nextSibling())
191 {
192 if (i.isElement())
193 {
194 if (i.toElement().tagName() == TQString::fromLatin1("metaInfo:meta"))
195 {
196 TQString type = i.toElement().attribute(TQString::fromLatin1("type"));
197 d->meta[type] = i.toElement().text();
198 }
199 else if (i.toElement().tagName() == TQString::fromLatin1("category"))
200 {
201 d->categories.append(Category::fromXML(i.toElement()));
202 }
203 }
204 }
205}
206
208{
209 if (d->deref())
210 delete d;
211}
212
213TQString Article::title() const
214{
215 return d->title;
216}
217
218TQString Article::author() const
219{
220 return d->author;
221}
222
223const KURL &Article::link() const
224{
225 return d->link;
226}
227
228TQString Article::description() const
229{
230 return d->description;
231}
232
233TQString Article::guid() const
234{
235 return d->guid;
236}
237
239{
240 return d->guidIsPermaLink;
241}
242
243const TQDateTime &Article::pubDate() const
244{
245 return d->pubDate;
246}
247
248const KURL &Article::commentsLink() const
249{
250 return d->commentsLink;
251}
252
253int Article::comments() const
254{
255 return d->numComments;
256}
257
258
259TQString Article::meta(const TQString &key) const
260{
261 return d->meta[key];
262}
263
264KURLLabel *Article::widget(TQWidget *parent, const char *name) const
265{
266 KURLLabel *label = new KURLLabel(d->link.url(), d->title, parent, name);
267 label->setUseTips(true);
268 if (!d->description.isNull())
269 label->setTipText(d->description);
270
271 return label;
272}
273
275{
276 if (this != &other) {
277 other.d->ref();
278 if (d && d->deref())
279 delete d;
280 d = other.d;
281 }
282 return *this;
283}
284
285bool Article::operator==(const Article &other) const
286{
287 return d->guid == other.guid();
288}
Represents an article as stored in a RSS file.
Definition: article.h:38
Article & operator=(const Article &other)
Assignment operator.
Definition: article.cpp:274
TQString guid() const
RSS 2.0 and upwards.
Definition: article.cpp:233
TQValueList< Category > categories() const
returns a list of categories this article is assigned to.
Definition: article.cpp:61
bool operator==(const Article &other) const
Compares two articles.
Definition: article.cpp:285
KURLLabel * widget(TQWidget *parent=0, const char *name=0) const
Definition: article.cpp:264
TQString title() const
RSS 0.90 and upwards.
Definition: article.cpp:213
virtual ~Article()
Destructor.
Definition: article.cpp:207
bool guidIsPermaLink() const
RSS 2.0 and upwards.
Definition: article.cpp:238
TQString author() const
a string desribing the author of the item.
Definition: article.cpp:218
Article()
Default constructor.
Definition: article.cpp:47
const TQDateTime & pubDate() const
RSS 2.0 and upwards.
Definition: article.cpp:243
const KURL & link() const
RSS 0.90 and upwards.
Definition: article.cpp:223
TQString description() const
RSS 0.91 and upwards.
Definition: article.cpp:228