KIO

multigetjob.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2000 Stephan Kulow <[email protected]>
3  2000-2009 David Faure <[email protected]>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "multigetjob.h"
22 #include "job_p.h"
23 #include "scheduler.h"
24 #include "slave.h"
25 #include <kurlauthorized.h>
26 
27 using namespace KIO;
28 
29 class KIO::MultiGetJobPrivate: public KIO::TransferJobPrivate
30 {
31 public:
32  explicit MultiGetJobPrivate(const QUrl &url)
33  : TransferJobPrivate(url, 0, QByteArray(), QByteArray()),
34  m_currentEntry(0, QUrl(), MetaData())
35  {}
36  struct GetRequest {
37  GetRequest(long _id, const QUrl &_url, const MetaData &_metaData)
38  : id(_id), url(_url), metaData(_metaData) { }
39  long id;
40  QUrl url;
41  MetaData metaData;
42 
43  inline bool operator==(const GetRequest &req) const
44  {
45  return req.id == id;
46  }
47  };
48  typedef std::list<GetRequest> RequestQueue;
49 
50  RequestQueue m_waitQueue;
51  RequestQueue m_activeQueue;
52  GetRequest m_currentEntry;
53  bool b_multiGetActive;
54 
61  void start(Slave *slave) override;
62 
63  bool findCurrentEntry();
64  void flushQueue(RequestQueue &queue);
65 
66  Q_DECLARE_PUBLIC(MultiGetJob)
67 
68  static inline MultiGetJob *newJob(const QUrl &url)
69  {
70  MultiGetJob *job = new MultiGetJob(*new MultiGetJobPrivate(url));
72  return job;
73  }
74 };
75 
76 MultiGetJob::MultiGetJob(MultiGetJobPrivate &dd)
77  : TransferJob(dd)
78 {
79 }
80 
81 MultiGetJob::~MultiGetJob()
82 {
83 }
84 
85 void MultiGetJob::get(long id, const QUrl &url, const MetaData &metaData)
86 {
87  Q_D(MultiGetJob);
88  MultiGetJobPrivate::GetRequest entry(id, url, metaData);
89  entry.metaData[QStringLiteral("request-id")] = QString::number(id);
90  d->m_waitQueue.push_back(entry);
91 }
92 
93 void MultiGetJobPrivate::flushQueue(RequestQueue &queue)
94 {
95  // Use multi-get
96  // Scan all jobs in m_waitQueue
97  auto wqIt = m_waitQueue.begin();
98  while (wqIt != m_waitQueue.end()) {
99  const GetRequest &entry = *wqIt;
100  if ((m_url.scheme() == entry.url.scheme()) &&
101  (m_url.host() == entry.url.host()) &&
102  (m_url.port() == entry.url.port()) &&
103  (m_url.userName() == entry.url.userName())) {
104  queue.push_back(entry);
105  wqIt = m_waitQueue.erase(wqIt);
106  } else {
107  ++wqIt;
108  }
109  }
110  // Send number of URLs, (URL, metadata)*
111  KIO_ARGS << (qint32) queue.size();
112  for (const GetRequest &entry : queue) {
113  stream << entry.url << entry.metaData;
114  }
115  m_packedArgs = packedArgs;
116  m_command = CMD_MULTI_GET;
117  m_outgoingMetaData.clear();
118 }
119 
120 void MultiGetJobPrivate::start(Slave *slave)
121 {
122  if (m_waitQueue.empty()) {
123  return;
124  }
125  // Get the first entry from m_waitQueue and add it to m_activeQueue
126  const GetRequest entry = m_waitQueue.front();
127  m_activeQueue.push_back(entry);
128  // then remove it from m_waitQueue
129  m_waitQueue.pop_front();
130 
131  m_url = entry.url;
132 
133  if (!entry.url.scheme().startsWith(QLatin1String("http"))) {
134  // Use normal get
135  KIO_ARGS << entry.url;
136  m_packedArgs = packedArgs;
137  m_outgoingMetaData = entry.metaData;
138  m_command = CMD_GET;
139  b_multiGetActive = false;
140  } else {
141  flushQueue(m_activeQueue);
142  b_multiGetActive = true;
143  }
144 
145  TransferJobPrivate::start(slave); // Anything else to do??
146 }
147 
148 bool MultiGetJobPrivate::findCurrentEntry()
149 {
150  if (b_multiGetActive) {
151  const long id = m_incomingMetaData.value(QStringLiteral("request-id")).toLong();
152  for (const GetRequest &entry : m_activeQueue) {
153  if (entry.id == id) {
154  m_currentEntry = entry;
155  return true;
156  }
157  }
158 
159  m_currentEntry.id = 0;
160  return false;
161  } else {
162  if (m_activeQueue.empty()) {
163  return false;
164  }
165  m_currentEntry = m_activeQueue.front();
166  return true;
167  }
168 }
169 
170 void MultiGetJob::slotRedirection(const QUrl &url)
171 {
172  Q_D(MultiGetJob);
173  if (!d->findCurrentEntry()) {
174  return; // Error
175  }
176  if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("redirect"), d->m_url, url)) {
177  qCWarning(KIO_CORE) << "Redirection from" << d->m_currentEntry.url << "to" << url << "REJECTED!";
178  return;
179  }
180  d->m_redirectionURL = url;
181  get(d->m_currentEntry.id, d->m_redirectionURL, d->m_currentEntry.metaData); // Try again
182 }
183 
184 void MultiGetJob::slotFinished()
185 {
186  Q_D(MultiGetJob);
187  if (!d->findCurrentEntry()) {
188  return;
189  }
190  if (d->m_redirectionURL.isEmpty()) {
191  // No redirection, tell the world that we are finished.
192  emit result(d->m_currentEntry.id);
193  }
194  d->m_redirectionURL = QUrl();
195  setError(0);
196  d->m_incomingMetaData.clear();
197  d->m_activeQueue.remove(d->m_currentEntry);
198  if (d->m_activeQueue.empty()) {
199  if (d->m_waitQueue.empty()) {
200  // All done
201  TransferJob::slotFinished();
202  } else {
203  // return slave to pool
204  // fetch new slave for first entry in d->m_waitQueue and call start
205  // again.
206  d->slaveDone();
207 
208  d->m_url = d->m_waitQueue.front().url;
209  if ((d->m_extraFlags & JobPrivate::EF_KillCalled) == 0) {
210  Scheduler::doJob(this);
211  }
212  }
213  }
214 }
215 
216 void MultiGetJob::slotData(const QByteArray &_data)
217 {
218  Q_D(MultiGetJob);
219  if (d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid() || error()) {
220  emit data(d->m_currentEntry.id, _data);
221  }
222 }
223 
224 void MultiGetJob::slotMimetype(const QString &_mimetype)
225 {
226  Q_D(MultiGetJob);
227  if (d->b_multiGetActive) {
228  MultiGetJobPrivate::RequestQueue newQueue;
229  d->flushQueue(newQueue);
230  if (!newQueue.empty()) {
231  d->m_activeQueue.splice(d->m_activeQueue.cend(), newQueue);
232  d->m_slave->send(d->m_command, d->m_packedArgs);
233  }
234  }
235  if (!d->findCurrentEntry()) {
236  return; // Error, unknown request!
237  }
238  emit mimetype(d->m_currentEntry.id, _mimetype);
239 }
240 
241 MultiGetJob *KIO::multi_get(long id, const QUrl &url, const MetaData &metaData)
242 {
243  MultiGetJob *job = MultiGetJobPrivate::newJob(url);
244  job->get(id, url, metaData);
245  return job;
246 }
247 
248 #include "moc_multigetjob.cpp"
static void doJob(SimpleJob *job)
Register job with the scheduler.
Definition: scheduler.cpp:810
void setUiDelegate(KJobUiDelegate *delegate)
KIOCORE_EXPORT MultiGetJob * multi_get(long id, const QUrl &url, const MetaData &metaData)
Creates a new multiple get job.
A namespace for KIO globals.
Definition: authinfo.h:34
void setError(int errorCode)
MetaData is a simple map of key/value strings.
Definition: metadata.h:34
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
QString number(int n, int base)
KIOCORE_EXPORT KJobUiDelegate * createDefaultJobUiDelegate()
Convenience method: use default factory, if there&#39;s one, to create a delegate and return it...
KIOCORE_EXPORT MimetypeJob * mimetype(const QUrl &url, JobFlags flags=DefaultFlags)
Find mimetype for one file or directory.
Definition: mimetypejob.cpp:93
MetaData metaData() const
Get meta data received from the slave.
Definition: job.cpp:227
void get(long id, const QUrl &url, const MetaData &metaData)
Get an additional file.
Definition: multigetjob.cpp:85
void result(KJob *job)
The transfer job pumps data into and/or out of a Slave.
Definition: transferjob.h:38
The MultiGetJob is a TransferJob that allows you to get several files from a single server...
Definition: multigetjob.h:38
bool authorizeUrlAction(const QString &action, const QUrl &baseURL, const QUrl &destURL)
Returns whether a certain URL related action is authorized.
int error() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Aug 2 2020 22:59:48 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.