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 // prefer content/content:encoded over summary/description for feeds that provide it
96 if (format == AtomFeed)
97 {
98 d->description = extractNode(node, TQString::fromLatin1("content"), false);
99 }
100 else
101 {
102 d->description = extractElementTextNS(node, ContentNamespace, TQString::fromLatin1("encoded"), false);
103 }
104
105 if (d->description.isEmpty())
106 {
107 if (!(elemText = extractNode(node, TQString::fromLatin1("body"), false)).isNull())
108 d->description = elemText;
109
110 if (d->description.isEmpty()) // 3rd try: see http://www.intertwingly.net/blog/1299.html
111 {
112 if (!(elemText = extractNode(node, TQString::fromLatin1((format==AtomFeed)? "summary" : "description"), false)).isNull())
113 d->description = elemText;
114 }
115 }
116
117 time_t time = 0;
118
119 if (format == AtomFeed)
120 {
121 if (version == vAtom_1_0)
122 elemText = extractNode(node, TQString::fromLatin1("updated"));
123 else
124 elemText = extractNode(node, TQString::fromLatin1("issued"));
125
126 if (!elemText.isNull())
127 time = parseISO8601Date(elemText);
128 }
129 else
130 {
131 elemText = extractNode(node, TQString::fromLatin1("pubDate"));
132 if (!elemText.isNull())
133 time = KRFCDate::parseDate(elemText);
134 }
135
136 if (!(elemText = extractElementTextNS(node, DublinCoreNamespace, TQString::fromLatin1("date"))).isNull())
137 {
138 time = parseISO8601Date(elemText);
139 }
140
141 // 0 means invalid, not epoch (parsers return epoch+1 when parsing epoch, see the KRFCDate::parseDate() docs)
142 if (time != 0)
143 d->pubDate.setTime_t(time);
144
145 d->commentsLink = extractElementTextNS(node, CommentAPINamespace, TQString::fromLatin1("comment"));
146 d->numComments = extractElementTextNS(node, SlashNamespace, TQString::fromLatin1("comments")).toInt();
147
148 TQDomElement element = TQDomNode(node).toElement();
149
150 // in RSS 1.0, we use <item about> attribute as ID
151 // FIXME: pass format version instead of checking for attribute
152
153 if (!element.isNull() && element.hasAttributeNS(RDFNamespace, TQString::fromLatin1("about")))
154 {
155 d->guid = element.attributeNS(RDFNamespace, TQString::fromLatin1("about"), TQString::null);
156 d->guidIsPermaLink = false;
157 }
158 else
159 {
160 TQString tagName=(format==AtomFeed)? TQString::fromLatin1("id"): TQString::fromLatin1("guid");
161 TQDomNode n = node.namedItem(tagName);
162 if (!n.isNull())
163 {
164 d->guidIsPermaLink = (format==AtomFeed)? false : true;
165 if (n.toElement().attribute(TQString::fromLatin1("isPermaLink"), "true") == "false") d->guidIsPermaLink = false;
166 if (!(elemText = extractNode(node, tagName)).isNull())
167 d->guid = elemText;
168 }
169 }
170
171 if(d->guid.isEmpty()) {
172 d->guidIsPermaLink = false;
173
174 md5Machine.reset();
175 TQDomNode n(node);
176 md5Machine.update(d->title.utf8());
177 md5Machine.update(d->description.utf8());
178 d->guid = TQString(md5Machine.hexDigest().data());
179 d->meta[TQString::fromLatin1("guidIsHash")] = TQString::fromLatin1("true");
180 }
181
182 TQDomNode enclosure = element.namedItem(TQString::fromLatin1("enclosure"));
183 if (enclosure.isElement())
184 d->enclosure = Enclosure::fromXML(enclosure.toElement());
185
186 d->author = parseItemAuthor(element, format, version);
187
188 for (TQDomNode i = node.firstChild(); !i.isNull(); i = i.nextSibling())
189 {
190 if (i.isElement())
191 {
192 if (i.toElement().tagName() == TQString::fromLatin1("metaInfo:meta"))
193 {
194 TQString type = i.toElement().attribute(TQString::fromLatin1("type"));
195 d->meta[type] = i.toElement().text();
196 }
197 else if (i.toElement().tagName() == TQString::fromLatin1("category"))
198 {
199 d->categories.append(Category::fromXML(i.toElement()));
200 }
201 }
202 }
203}
204
206{
207 if (d->deref())
208 delete d;
209}
210
211TQString Article::title() const
212{
213 return d->title;
214}
215
216TQString Article::author() const
217{
218 return d->author;
219}
220
221const KURL &Article::link() const
222{
223 return d->link;
224}
225
226TQString Article::description() const
227{
228 return d->description;
229}
230
231TQString Article::guid() const
232{
233 return d->guid;
234}
235
237{
238 return d->guidIsPermaLink;
239}
240
241const TQDateTime &Article::pubDate() const
242{
243 return d->pubDate;
244}
245
246const KURL &Article::commentsLink() const
247{
248 return d->commentsLink;
249}
250
251int Article::comments() const
252{
253 return d->numComments;
254}
255
256
257TQString Article::meta(const TQString &key) const
258{
259 return d->meta[key];
260}
261
262KURLLabel *Article::widget(TQWidget *parent, const char *name) const
263{
264 KURLLabel *label = new KURLLabel(d->link.url(), d->title, parent, name);
265 label->setUseTips(true);
266 if (!d->description.isNull())
267 label->setTipText(d->description);
268
269 return label;
270}
271
273{
274 if (this != &other) {
275 other.d->ref();
276 if (d && d->deref())
277 delete d;
278 d = other.d;
279 }
280 return *this;
281}
282
283bool Article::operator==(const Article &other) const
284{
285 return d->guid == other.guid();
286}
Represents an article as stored in a RSS file.
Definition: article.h:38
Article & operator=(const Article &other)
Assignment operator.
Definition: article.cpp:272
TQString guid() const
RSS 2.0 and upwards.
Definition: article.cpp:231
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:283
KURLLabel * widget(TQWidget *parent=0, const char *name=0) const
Definition: article.cpp:262
TQString title() const
RSS 0.90 and upwards.
Definition: article.cpp:211
virtual ~Article()
Destructor.
Definition: article.cpp:205
bool guidIsPermaLink() const
RSS 2.0 and upwards.
Definition: article.cpp:236
TQString author() const
a string desribing the author of the item.
Definition: article.cpp:216
Article()
Default constructor.
Definition: article.cpp:47
const TQDateTime & pubDate() const
RSS 2.0 and upwards.
Definition: article.cpp:241
const KURL & link() const
RSS 0.90 and upwards.
Definition: article.cpp:221
TQString description() const
RSS 0.91 and upwards.
Definition: article.cpp:226