1/*
2 * dataretriever.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
12#include "dataretriever.h"
13#include "global.h"
14
15#include <kio/job.h>
16
17#include <kprocess.h>
18#include <kurl.h>
19
20#include <QtCore/QBuffer>
21#include <QtCore/QTimer>
22
23namespace Syndication {
24
25DataRetriever::DataRetriever()
26{
27}
28
29DataRetriever::~DataRetriever()
30{
31}
32
33struct FileRetriever::FileRetrieverPrivate
34{
35 FileRetrieverPrivate()
36 : buffer(NULL),
37 lastError(0), job(NULL)
38 {
39 }
40
41 ~FileRetrieverPrivate()
42 {
43 delete buffer;
44 }
45
46 QBuffer *buffer;
47 int lastError;
48 KIO::TransferJob *job;
49};
50
51FileRetriever::FileRetriever()
52 : d(new FileRetrieverPrivate)
53{
54}
55
56FileRetriever::~FileRetriever()
57{
58 delete d;
59}
60
61bool FileRetriever::m_useCache = true;
62QString FileRetriever::m_userAgent = QString::fromLatin1("Syndication %1").arg(QString::fromLatin1(SYNDICATION_VERSION));
63
64void FileRetriever::setUserAgent(const QString& userAgent)
65{
66 m_userAgent = userAgent;
67}
68
69void FileRetriever::setUseCache(bool enabled)
70{
71 m_useCache = enabled;
72}
73
74void FileRetriever::retrieveData(const KUrl &url)
75{
76 if (d->buffer)
77 return;
78
79 d->buffer = new QBuffer;
80 d->buffer->open(QIODevice::WriteOnly);
81
82 KUrl u = url;
83
84 if (u.protocol() == QLatin1String("feed"))
85 u.setProtocol(QLatin1String("http"));
86
87 d->job = KIO::get(u, KIO::NoReload, KIO::HideProgressInfo);
88
89 d->job->addMetaData(QLatin1String("UserAgent"), m_userAgent);
90 d->job->addMetaData(QLatin1String("cache"), m_useCache ? QLatin1String("refresh") : QLatin1String("reload"));
91
92 QTimer::singleShot(1000*90, this, SLOT(slotTimeout()));
93
94 connect(d->job, SIGNAL(data(KIO::Job*,QByteArray)),
95 SLOT(slotData(KIO::Job*,QByteArray)));
96 connect(d->job, SIGNAL(result(KJob*)), SLOT(slotResult(KJob*)));
97 connect(d->job, SIGNAL(permanentRedirection(KIO::Job*,KUrl,KUrl)),
98 SLOT(slotPermanentRedirection(KIO::Job*,KUrl,KUrl)));
99}
100
101void FileRetriever::slotTimeout()
102{
103 abort();
104
105 delete d->buffer;
106 d->buffer = NULL;
107
108 d->lastError = KIO::ERR_SERVER_TIMEOUT;
109
110 emit dataRetrieved(QByteArray(), false);
111}
112
113int FileRetriever::errorCode() const
114{
115 return d->lastError;
116}
117
118void FileRetriever::slotData(KIO::Job *, const QByteArray &data)
119{
120 d->buffer->write(data.data(), data.size());
121}
122
123void FileRetriever::slotResult(KJob *job)
124{
125 QByteArray data = d->buffer->buffer();
126 data.detach();
127
128 delete d->buffer;
129 d->buffer = NULL;
130
131 d->lastError = job->error();
132 emit dataRetrieved(data, d->lastError == 0);
133}
134
135void FileRetriever::slotPermanentRedirection(KIO::Job*, const KUrl&,
136 const KUrl& newUrl)
137{
138 emit permanentRedirection(newUrl);
139}
140
141void FileRetriever::abort()
142{
143 if (d->job)
144 {
145 d->job->kill();
146 d->job = NULL;
147 }
148}
149
150struct OutputRetriever::OutputRetrieverPrivate
151{
152 OutputRetrieverPrivate() : process(0L), buffer(0L), lastError(0)
153 {
154 }
155
156 ~OutputRetrieverPrivate()
157 {
158 delete process;
159 delete buffer;
160 }
161
162 KProcess *process;
163 QBuffer *buffer;
164 int lastError;
165};
166
167OutputRetriever::OutputRetriever() : d(new OutputRetrieverPrivate)
168{
169}
170
171OutputRetriever::~OutputRetriever()
172{
173 delete d;
174}
175
176void OutputRetriever::retrieveData(const KUrl &url)
177{
178 // Ignore subsequent calls if we didn't finish the previous job yet.
179 if (d->buffer || d->process)
180 return;
181
182 d->buffer = new QBuffer;
183 d->buffer->open(QIODevice::WriteOnly);
184
185 d->process = new KProcess();
186 connect(d->process, SIGNAL(finished(int,QProcess::ExitStatus)),
187 SLOT(slotFinished(int,QProcess::ExitStatus)));
188 d->process->setShellCommand(url.path());
189 d->process->start();
190}
191
192int OutputRetriever::errorCode() const
193{
194 return d->lastError;
195}
196
197void OutputRetriever::slotFinished(int exitCode, QProcess::ExitStatus exitStatus)
198{
199 Q_UNUSED( exitCode );
200 if (!d->process->exitCode())
201 d->lastError = d->process->exitCode();
202
203 QByteArray data = d->process->readAllStandardOutput();
204
205 delete d->buffer;
206 d->buffer = NULL;
207
208 int code = d->process->exitCode();
209
210 delete d->process;
211 d->process = NULL;
212
213 emit dataRetrieved(data, exitStatus == QProcess::NormalExit && code == 0);
214}
215
216} // namespace Syndication
217
218