• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

Syndication Library

  • sources
  • kde-4.14
  • kdepimlibs
  • syndication
loader.cpp
1 /*
2  * loader.cpp
3  *
4  * Copyright (c) 2001, 2002, 2003 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 "loader.h"
12 #include "dataretriever.h"
13 #include "documentsource.h"
14 #include "feed.h"
15 #include "global.h"
16 #include "parsercollection.h"
17 
18 #include <kio/global.h>
19 #include <kurl.h>
20 
21 #include <QtCore/QBuffer>
22 #include <QtCore/QRegExp>
23 #include <QtCore/QStringList>
24 
25 #include <boost/shared_ptr.hpp>
26 
27 // test: TODO remove
28 #include <iostream>
29 
30 namespace Syndication {
31 
32 struct Loader::LoaderPrivate
33 {
34  LoaderPrivate() : retriever(0), lastError(Success),
35  retrieverError(0)
36  {
37  }
38 
39  ~LoaderPrivate()
40  {
41  delete retriever;
42  }
43 
44  DataRetriever* retriever;
45  Syndication::ErrorCode lastError;
46  int retrieverError;
47  KUrl discoveredFeedURL;
48  KUrl url;
49 };
50 
51 Loader* Loader::create()
52 {
53  return new Loader;
54 }
55 
56 Loader *Loader::create(QObject* object, const char* slot)
57 {
58  Loader *loader = create();
59  connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,
60  Syndication::FeedPtr, Syndication::ErrorCode)),
61  object, slot);
62  return loader;
63 }
64 
65 Loader::Loader() : d(new LoaderPrivate)
66 {
67 }
68 
69 Loader::~Loader()
70 {
71  delete d;
72 }
73 
74 void Loader::loadFrom(const KUrl& url)
75 {
76  loadFrom(url, new FileRetriever);
77 }
78 
79 void Loader::loadFrom(const KUrl &url, DataRetriever *retriever)
80 {
81  if (d->retriever != 0L)
82  return;
83 
84  d->url = url;
85  d->retriever = retriever;
86 
87  connect(d->retriever, SIGNAL(dataRetrieved(QByteArray,bool)),
88  this, SLOT(slotRetrieverDone(QByteArray,bool)));
89 
90  d->retriever->retrieveData(url);
91 }
92 
93 int Loader::retrieverError() const
94 {
95  return d->retrieverError;
96 }
97 
98 Syndication::ErrorCode Loader::errorCode() const
99 {
100  return d->lastError;
101 }
102 
103 void Loader::abort()
104 {
105  if (d && d->retriever)
106  {
107  d->retriever->abort();
108  delete d->retriever;
109  d->retriever = 0L;
110  }
111 
112  emit loadingComplete(this, FeedPtr(), Aborted);
113  delete this;
114 }
115 
116 KUrl Loader::discoveredFeedURL() const
117 {
118  return d->discoveredFeedURL;
119 }
120 
121 void Loader::slotRetrieverDone(const QByteArray& data, bool success)
122 {
123  d->retrieverError = d->retriever->errorCode();
124  ErrorCode status = Success;
125  FeedPtr feed;
126  bool isFileRetriever = dynamic_cast<FileRetriever*>(d->retriever) != 0;
127  delete d->retriever;
128  d->retriever = 0;
129 
130  if (success)
131  {
132  DocumentSource src(data, d->url.url());
133  feed = parserCollection()->parse(src);
134 
135  if (parserCollection()->lastError() != Syndication::Success)
136  {
137  status = parserCollection()->lastError();
138  discoverFeeds(data);
139  }
140  }
141  else
142  {
143  if (isFileRetriever)
144  {
145  // retriever is a FileRetriever, so we interpret the
146  // error code and set lastError accordingly
147  status = FileNotFound; // TODO
148  std::cout << "file retriever error: " << d->retrieverError << std::endl;
149  }
150  else
151  {
152  // retriever is a custom impl, so we set OtherRetrieverError
153  status = OtherRetrieverError;
154  }
155  }
156 
157  emit loadingComplete(this, feed, status);
158 
159  delete this;
160 }
161 
162 void Loader::discoverFeeds(const QByteArray &data)
163 {
164  QString str = QString::fromLatin1(data.constData()).simplified();
165  QString s2;
166  //QTextStream ts( &str, QIODevice::WriteOnly );
167  //ts << data.data();
168 
169  // "<[\\s]link[^>]*rel[\\s]=[\\s]\\\"[\\s]alternate[\\s]\\\"[^>]*>"
170  // "type[\\s]=[\\s]\\\"application/rss+xml\\\""
171  // "href[\\s]=[\\s]\\\"application/rss+xml\\\""
172  QRegExp rx( QLatin1String("(?:REL)[^=]*=[^sAa]*(?:service.feed|ALTERNATE)[\\s]*[^s][^s](?:[^>]*)(?:HREF)[^=]*=[^A-Z0-9-_~,./$]*([^'\">\\s]*)"), Qt::CaseInsensitive );
173  if (rx.indexIn(str)!=-1)
174  s2=rx.cap(1);
175  else{
176  // does not support Atom/RSS autodiscovery.. try finding feeds by brute force....
177  int pos=0;
178  QStringList feeds;
179  QString host=d->url.host();
180  rx.setPattern(QLatin1String("(?:<A )[^H]*(?:HREF)[^=]*=[^A-Z0-9-_~,./]*([^'\">\\s]*)"));
181  while ( pos >= 0 ) {
182  pos = rx.indexIn( str, pos );
183  s2=rx.cap(1);
184  if (s2.endsWith(QLatin1String(".rdf")) ||
185  s2.endsWith(QLatin1String(".rss")) ||
186  s2.endsWith(QLatin1String(".xml")))
187  feeds.append(s2);
188  if ( pos >= 0 ) {
189  pos += rx.matchedLength();
190  }
191  }
192 
193  KUrl testURL;
194  // loop through, prefer feeds on same host
195  QStringList::const_iterator end( feeds.constEnd() );
196  for ( QStringList::const_iterator it = feeds.constBegin(); it != end; ++it ) {
197  testURL=*it;
198  if (testURL.host()==host)
199  {
200  s2=*it;
201  break;
202  }
203  }
204  }
205 
206  if (s2.isNull())
207  {
208  return;
209  }
210 
211  if (KUrl::isRelativeUrl(s2))
212  {
213  if (s2.startsWith(QLatin1String("//")))
214  {
215  s2=s2.prepend(d->url.protocol()+QLatin1Char(':'));
216  d->discoveredFeedURL=s2;
217  }
218  else if (s2.startsWith(QLatin1Char('/')))
219  {
220  d->discoveredFeedURL=d->url;
221  d->discoveredFeedURL.setPath(s2);
222  }
223  else
224  {
225  d->discoveredFeedURL=d->url;
226  d->discoveredFeedURL.addPath(s2);
227  }
228  d->discoveredFeedURL.cleanPath();
229  }
230  else
231  d->discoveredFeedURL=s2;
232 
233  d->discoveredFeedURL.cleanPath();
234 }
235 
236 } // namespace Syndication
237 
Syndication::Loader::errorCode
ErrorCode errorCode() const
Retrieves the error code of the last loading process (if any).
Definition: loader.cpp:98
QByteArray
QString::prepend
QString & prepend(QChar ch)
Syndication::Loader::discoveredFeedURL
KUrl discoveredFeedURL() const
returns the URL of a feed discovered in the feed source
Definition: loader.cpp:116
Syndication::FileNotFound
the host was contacted successfully, but reported a 404 error
Definition: global.h:95
QList::const_iterator
Syndication::FileRetriever
Implements a file retriever, to be used with Loader::loadFrom().
Definition: dataretriever.h:150
Syndication::DocumentSource
Represents the source of a syndication document, as read from the downloaded file.
Definition: documentsource.h:50
Syndication::Loader::loadingComplete
void loadingComplete(Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode error)
This signal gets emitted when the loading process triggered by calling loadFrom() finished...
Syndication::Loader
This class is the preferred way of loading feed sources.
Definition: loader.h:75
QString::isNull
bool isNull() const
Syndication::Success
No error occurred, feed was fetched and parsed successfully.
Definition: global.h:87
Syndication::ErrorCode
ErrorCode
error code indicating fetching or parsing errors
Definition: global.h:85
QRegExp
Syndication::Loader::loadFrom
void loadFrom(const KUrl &url, DataRetriever *retriever)
Loads the feed source referenced by the given URL using the specified retrieval algorithm.
Definition: loader.cpp:79
QList::append
void append(const T &value)
Syndication::Loader::abort
void abort()
aborts the loading process
Definition: loader.cpp:103
QObject
Syndication::OtherRetrieverError
retriever error not covered by the error codes above.
Definition: global.h:98
QByteArray::constData
const char * constData() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QString
QStringList
Syndication::parserCollection
ParserCollection< Feed > * parserCollection()
The default ParserCollection instance parsing a DocumentSource into a Feed object.
Definition: global.cpp:55
Syndication::Aborted
file downloading/parsing was aborted by the user
Definition: global.h:90
QLatin1Char
QLatin1String
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
Syndication::Loader::retrieverError
int retrieverError() const
the error code returned from the retriever.
Definition: loader.cpp:93
Syndication::DataRetriever
Abstract baseclass for all data retriever classes.
Definition: dataretriever.h:36
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Syndication::Loader::create
static Loader * create()
Constructs a Loader instance.
Definition: loader.cpp:51
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:32 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Syndication Library

Skip menu "Syndication Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal