KIO

simplejob.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Stephan Kulow <[email protected]>
4  SPDX-FileCopyrightText: 2000-2013 David Faure <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "simplejob.h"
10 #include "job_p.h"
11 #include "kprotocolinfo.h"
12 #include "scheduler.h"
13 #include "slave.h"
14 #include <QDebug>
15 #include <QTimer>
16 #include <kdirnotify.h>
17 
18 using namespace KIO;
19 
20 SimpleJob::SimpleJob(SimpleJobPrivate &dd)
21  : Job(dd)
22 {
23  d_func()->simpleJobInit();
24 }
25 
26 void SimpleJobPrivate::simpleJobInit()
27 {
28  Q_Q(SimpleJob);
29  if (!m_url.isValid() || m_url.scheme().isEmpty()) {
30  qCWarning(KIO_CORE) << "Invalid URL:" << m_url;
31  q->setError(ERR_MALFORMED_URL);
32  q->setErrorText(m_url.toString());
34  return;
35  }
36 
38 }
39 
41 {
42  Q_D(SimpleJob);
43  if ((d->m_extraFlags & JobPrivate::EF_KillCalled) == 0) {
44  d->m_extraFlags |= JobPrivate::EF_KillCalled;
45  Scheduler::cancelJob(this); // deletes the slave if not 0
46  } else {
47  qCWarning(KIO_CORE) << this << "killed twice, this is overkill";
48  }
49  return Job::doKill();
50 }
51 
53 {
54  Q_D(SimpleJob);
55  if (d->m_slave) {
56  d->m_slave->suspend();
57  }
58  return Job::doSuspend();
59 }
60 
62 {
63  Q_D(SimpleJob);
64  if (d->m_slave) {
65  d->m_slave->resume();
66  }
67  return Job::doResume();
68 }
69 
70 const QUrl &SimpleJob::url() const
71 {
72  return d_func()->m_url;
73 }
74 
76 {
77  Q_D(SimpleJob);
78  Q_ASSERT(d->m_slave);
79  if (d->m_slave) {
80  Scheduler::putWorkerOnHold(this, d->m_url);
81  }
82  // we should now be disassociated from the slave
83  Q_ASSERT(!d->m_slave);
84  kill(Quietly);
85 }
86 
88 {
90 }
91 
93 {
94  return d_func()->m_redirectionHandlingEnabled;
95 }
96 
98 {
99  Q_D(SimpleJob);
100  d->m_redirectionHandlingEnabled = handle;
101 }
102 
103 SimpleJob::~SimpleJob()
104 {
105  Q_D(SimpleJob);
106  // last chance to remove this job from the scheduler!
107  if (d->m_schedSerial) {
108  // qDebug() << "Killing job" << this << "in destructor!"/* << qBacktrace()*/;
109  Scheduler::cancelJob(this);
110  }
111 }
112 
113 void SimpleJobPrivate::start(Slave *slave)
114 {
115  Q_Q(SimpleJob);
116  m_slave = slave;
117 
118  // Slave::setJob can send us SSL metadata if there is a persistent connection
119  QObject::connect(slave, &Slave::metaData, q, &SimpleJob::slotMetaData);
120 
121  slave->setJob(q);
122 
123  QObject::connect(slave, &Slave::error, q, &SimpleJob::slotError);
124 
125  QObject::connect(slave, &Slave::warning, q, &SimpleJob::slotWarning);
126 
127  QObject::connect(slave, &Slave::finished, q, &SimpleJob::slotFinished);
128 
129  QObject::connect(slave, &Slave::infoMessage, q, [this](const QString &message) {
130  _k_slotSlaveInfoMessage(message);
131  });
132 
133  QObject::connect(slave, &Slave::connected, q, [this]() {
134  slotConnected();
135  });
136 
137  QObject::connect(slave, &Slave::privilegeOperationRequested, q, [this]() {
138  slotPrivilegeOperationRequested();
139  });
140 
141  if ((m_extraFlags & EF_TransferJobDataSent) == 0) { // this is a "get" job
142  QObject::connect(slave, &Slave::totalSize, q, [this](KIO::filesize_t size) {
143  slotTotalSize(size);
144  });
145 
146  QObject::connect(slave, &Slave::processedSize, q, [this](KIO::filesize_t size) {
147  slotProcessedSize(size);
148  });
149 
150  QObject::connect(slave, &Slave::speed, q, [this](ulong speed) {
151  slotSpeed(speed);
152  });
153  }
154 
155  const QVariant windowIdProp = q->property("window-id"); // see KJobWidgets::setWindow
156  if (windowIdProp.isValid()) {
157  m_outgoingMetaData.insert(QStringLiteral("window-id"), QString::number(windowIdProp.toULongLong()));
158  }
159 
160  const QVariant userTimestampProp = q->property("userTimestamp"); // see KJobWidgets::updateUserTimestamp
161  if (userTimestampProp.isValid()) {
162  m_outgoingMetaData.insert(QStringLiteral("user-timestamp"), QString::number(userTimestampProp.toULongLong()));
163  }
164 
165  if (q->uiDelegate() == nullptr) { // not interactive
166  m_outgoingMetaData.insert(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
167  }
168 
169  if (!m_outgoingMetaData.isEmpty()) {
170  KIO_ARGS << m_outgoingMetaData;
171  slave->send(CMD_META_DATA, packedArgs);
172  }
173 
174  if (!m_subUrl.isEmpty()) { // TODO KF6 remove
175  KIO_ARGS << m_subUrl;
176  slave->send(CMD_SUBURL, packedArgs);
177  }
178 
179  slave->send(m_command, m_packedArgs);
180  if (q->isSuspended()) {
181  slave->suspend();
182  }
183 }
184 
185 void SimpleJobPrivate::slaveDone()
186 {
187  Q_Q(SimpleJob);
188  if (m_slave) {
189  if (m_command == CMD_OPEN) {
190  m_slave->send(CMD_CLOSE);
191  }
192  q->disconnect(m_slave); // Remove all signals between slave and job
193  }
194  // only finish a job once; Scheduler::jobFinished() resets schedSerial to zero.
195  if (m_schedSerial) {
196  Scheduler::jobFinished(q, m_slave);
197  }
198 }
199 
201 {
202  Q_D(SimpleJob);
203  // Return slave to the scheduler
204  d->slaveDone();
205 
206  if (!hasSubjobs()) {
207  if (!error() && (d->m_command == CMD_MKDIR || d->m_command == CMD_RENAME)) {
208  if (d->m_command == CMD_MKDIR) {
210 #ifndef KIO_ANDROID_STUB
211  org::kde::KDirNotify::emitFilesAdded(urlDir);
212 #endif
213  } else { /*if ( m_command == CMD_RENAME )*/
214  QUrl src;
215  QUrl dst;
216  QDataStream str(d->m_packedArgs);
217  str >> src >> dst;
218  if (src.adjusted(QUrl::RemoveFilename) == dst.adjusted(QUrl::RemoveFilename) // For the user, moving isn't renaming. Only renaming is.
219 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
220  && !KProtocolInfo::slaveHandlesNotify(dst.scheme()).contains(QLatin1String("Rename"))
221 #endif
222  ) {
223 #ifndef KIO_ANDROID_STUB
224  org::kde::KDirNotify::emitFileRenamed(src, dst);
225 #endif
226  }
227 
228 #ifndef KIO_ANDROID_STUB
229  org::kde::KDirNotify::emitFileMoved(src, dst);
230 #endif
231  if (d->m_uiDelegateExtension) {
232  d->m_uiDelegateExtension->updateUrlInClipboard(src, dst);
233  }
234  }
235  }
236  emitResult();
237  }
238 }
239 
240 void SimpleJob::slotError(int err, const QString &errorText)
241 {
242  Q_D(SimpleJob);
243  setError(err);
245  if ((error() == ERR_UNKNOWN_HOST) && d->m_url.host().isEmpty()) {
247  }
248  // error terminates the job
249  slotFinished();
250 }
251 
252 void SimpleJob::slotWarning(const QString &errorText)
253 {
254  Q_EMIT warning(this, errorText);
255 }
256 
257 void SimpleJobPrivate::_k_slotSlaveInfoMessage(const QString &msg)
258 {
259  Q_EMIT q_func()->infoMessage(q_func(), msg);
260 }
261 
262 void SimpleJobPrivate::slotConnected()
263 {
264  Q_EMIT q_func()->connected(q_func());
265 }
266 
267 void SimpleJobPrivate::slotTotalSize(KIO::filesize_t size)
268 {
269  Q_Q(SimpleJob);
270  if (size != q->totalAmount(KJob::Bytes)) {
271  q->setTotalAmount(KJob::Bytes, size);
272  }
273 }
274 
275 void SimpleJobPrivate::slotProcessedSize(KIO::filesize_t size)
276 {
277  Q_Q(SimpleJob);
278  // qDebug() << KIO::number(size);
279  q->setProcessedAmount(KJob::Bytes, size);
280 }
281 
282 void SimpleJobPrivate::slotSpeed(unsigned long speed)
283 {
284  // qDebug() << speed;
285  q_func()->emitSpeed(speed);
286 }
287 
288 void SimpleJobPrivate::restartAfterRedirection(QUrl *redirectionUrl)
289 {
290  Q_Q(SimpleJob);
291  // Return slave to the scheduler while we still have the old URL in place; the scheduler
292  // requires a job URL to stay invariant while the job is running.
293  slaveDone();
294 
295  m_url = *redirectionUrl;
296  redirectionUrl->clear();
297  if ((m_extraFlags & EF_KillCalled) == 0) {
298  Scheduler::doJob(q);
299  }
300 }
301 
303 {
304  Q_D(SimpleJob);
305  QMapIterator<QString, QString> it(_metaData);
306  while (it.hasNext()) {
307  it.next();
308  if (it.key().startsWith(QLatin1String("{internal~"), Qt::CaseInsensitive)) {
309  d->m_internalMetaData.insert(it.key(), it.value());
310  } else {
311  d->m_incomingMetaData.insert(it.key(), it.value());
312  }
313  }
314 
315  // Update the internal meta-data values as soon as possible. Waiting until
316  // the KIO worker is finished has unintended consequences if the client starts
317  // a new connection without waiting for the KIO worker to finish.
318  if (!d->m_internalMetaData.isEmpty()) {
320  }
321 }
322 
323 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
324 void SimpleJob::storeSSLSessionFromJob(const QUrl &redirectionURL)
325 {
326  Q_UNUSED(redirectionURL);
327 }
328 #endif
329 
330 void SimpleJobPrivate::slotPrivilegeOperationRequested()
331 {
332  m_slave->send(MSG_PRIVILEGE_EXEC, privilegeOperationData());
333 }
334 
335 //////////
337 {
338  // qDebug() << "rmdir " << url;
339  KIO_ARGS << url << qint8(false); // isFile is false
340  return SimpleJobPrivate::newJob(url, CMD_DEL, packedArgs);
341 }
342 
343 SimpleJob *KIO::chmod(const QUrl &url, int permissions)
344 {
345  // qDebug() << "chmod " << url;
346  KIO_ARGS << url << permissions;
347  return SimpleJobPrivate::newJob(url, CMD_CHMOD, packedArgs);
348 }
349 
350 SimpleJob *KIO::chown(const QUrl &url, const QString &owner, const QString &group)
351 {
352  KIO_ARGS << url << owner << group;
353  return SimpleJobPrivate::newJob(url, CMD_CHOWN, packedArgs);
354 }
355 
357 {
358  // qDebug() << "setModificationTime " << url << " " << mtime;
359  KIO_ARGS << url << mtime;
360  return SimpleJobPrivate::newJobNoUi(url, CMD_SETMODIFICATIONTIME, packedArgs);
361 }
362 
363 SimpleJob *KIO::rename(const QUrl &src, const QUrl &dest, JobFlags flags)
364 {
365  // qDebug() << "rename " << src << " " << dest;
366  KIO_ARGS << src << dest << (qint8)(flags & Overwrite);
367  return SimpleJobPrivate::newJob(src, CMD_RENAME, packedArgs, flags);
368 }
369 
370 SimpleJob *KIO::symlink(const QString &target, const QUrl &dest, JobFlags flags)
371 {
372  // qDebug() << "symlink target=" << target << " " << dest;
373  KIO_ARGS << target << dest << (qint8)(flags & Overwrite);
374  return SimpleJobPrivate::newJob(dest, CMD_SYMLINK, packedArgs, flags);
375 }
376 
377 SimpleJob *KIO::special(const QUrl &url, const QByteArray &data, JobFlags flags)
378 {
379  // qDebug() << "special " << url;
380  return SimpleJobPrivate::newJob(url, CMD_SPECIAL, data, flags);
381 }
382 
383 SimpleJob *KIO::mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags)
384 {
385  KIO_ARGS << int(1) << qint8(ro ? 1 : 0) << QString::fromLatin1(fstype) << dev << point;
386  SimpleJob *job = special(QUrl(QStringLiteral("file:///")), packedArgs, flags);
387  if (!(flags & HideProgressInfo)) {
388  KIO::JobPrivate::emitMounting(job, dev, point);
389  }
390  return job;
391 }
392 
393 SimpleJob *KIO::unmount(const QString &point, JobFlags flags)
394 {
395  KIO_ARGS << int(2) << point;
396  SimpleJob *job = special(QUrl(QStringLiteral("file:///")), packedArgs, flags);
397  if (!(flags & HideProgressInfo)) {
398  KIO::JobPrivate::emitUnmounting(job, point);
399  }
400  return job;
401 }
402 
403 //////////
404 
405 SimpleJob *KIO::http_update_cache(const QUrl &url, bool no_cache, const QDateTime &expireDate)
406 {
407  Q_ASSERT(url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"));
408  // Send http update_cache command (2)
409  KIO_ARGS << (int)2 << url << no_cache << qlonglong(expireDate.toMSecsSinceEpoch() / 1000);
410  return SimpleJobPrivate::newJob(url, CMD_SPECIAL, packedArgs);
411 }
412 
413 #include "moc_simplejob.cpp"
@ Overwrite
When set, automatically overwrite the destination if it exists already.
Definition: job_base.h:291
static void jobFinished(KIO::SimpleJob *job, KIO::Slave *slave)
Called when a job is done.
Definition: scheduler.cpp:800
KIOCORE_EXPORT SimpleJob * rename(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
Rename a file or directory.
Definition: simplejob.cpp:363
bool isValid() const const
const T & value() const const
void slotError(int, const QString &)
Definition: simplejob.cpp:240
QString number(int n, int base)
void setErrorText(const QString &errorText)
CaseInsensitive
bool doKill() override
Abort job.
Definition: simplejob.cpp:40
Q_EMITQ_EMIT
KIOCORE_EXPORT SimpleJob * setModificationTime(const QUrl &url, const QDateTime &mtime)
Changes the modification time on a file or directory.
Definition: simplejob.cpp:356
QString scheme() const const
qulonglong filesize_t
64-bit file size
Definition: global.h:39
KIOCORE_EXPORT SimpleJob * http_update_cache(const QUrl &url, bool no_cache, const QDateTime &expireDate)
HTTP cache update.
Definition: simplejob.cpp:405
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
Q_SCRIPTABLE Q_NOREPLY void start()
bool hasNext() const const
virtual void slotWarning(const QString &)
Definition: simplejob.cpp:252
const QUrl & url() const
Returns the SimpleJob's URL.
Definition: simplejob.cpp:70
bool kill(KillVerbosity verbosity=Quietly)
static void updateInternalMetaData(SimpleJob *job)
Updates the internal metadata from job.
Definition: scheduler.cpp:847
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void warning(KJob *job, const QString &plain, const QString &rich=QString())
KIOCORE_EXPORT SimpleJob * unmount(const QString &point, JobFlags flags=DefaultFlags)
Unmount filesystem.
Definition: simplejob.cpp:393
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
Mount filesystem.
Definition: simplejob.cpp:383
static void removeWorkerOnHold()
Removes any worker that might have been put on hold.
Definition: scheduler.cpp:824
virtual void slotFinished()
Called when the worker marks the job as finished.
Definition: simplejob.cpp:200
qulonglong toULongLong(bool *ok) const const
static void removeOnHold()
Discard suspended worker.
Definition: simplejob.cpp:87
RemoveFilename
virtual void putOnHold()
Abort job.
Definition: simplejob.cpp:75
virtual void slotMetaData(const KIO::MetaData &_metaData)
MetaData from the worker is received.
Definition: simplejob.cpp:302
KIOCORE_EXPORT ChmodJob * chmod(const KFileItemList &lstItems, int permissions, int mask, const QString &newOwner, const QString &newGroup, bool recursive, JobFlags flags=DefaultFlags)
Creates a job that changes permissions/ownership on several files or directories, optionally recursiv...
Definition: chmodjob.cpp:288
QString errorText() const
KIOCORE_NO_EXPORT SimpleJob(SimpleJobPrivate &dd)
Creates a new simple job.
Definition: simplejob.cpp:20
bool doResume() override
Resume this job.
Definition: job.cpp:186
KIOCORE_EXPORT SimpleJob * special(const QUrl &url, const QByteArray &data, JobFlags flags=DefaultFlags)
Execute any command that is specific to one worker (protocol).
Definition: simplejob.cpp:377
bool isRedirectionHandlingEnabled() const
Returns true when redirections are handled internally, the default.
Definition: simplejob.cpp:92
qint64 toMSecsSinceEpoch() const const
bool doResume() override
Resume this job.
Definition: simplejob.cpp:61
bool doKill() override
Abort this job.
Definition: job.cpp:164
static QStringList slaveHandlesNotify(const QString &protocol)
Returns the list of notification types the kioslave implementing this protocol will produce on its ow...
static void putWorkerOnHold(KIO::SimpleJob *job, const QUrl &url)
Puts a worker on notice.
Definition: scheduler.cpp:812
QMapIterator::Item next()
void setRedirectionHandlingEnabled(bool handle)
Set handle to false to prevent the internal handling of redirections.
Definition: simplejob.cpp:97
QString fromLatin1(const char *str, int size)
const Key & key() const const
void storeSSLSessionFromJob(const QUrl &m_redirectionURL)
Allow jobs that inherit SimpleJob and are aware of redirections to store the SSL session used.
Definition: simplejob.cpp:324
QUrl adjusted(QUrl::FormattingOptions options) const const
A namespace for KIO globals.
KIOCORE_EXPORT SimpleJob * rmdir(const QUrl &url)
Removes a single directory.
Definition: simplejob.cpp:336
static void doJob(SimpleJob *job)
Register job with the scheduler.
Definition: scheduler.cpp:770
bool doSuspend() override
Suspend this job.
Definition: job.cpp:175
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition: job_base.h:275
void emitResult()
static void cancelJob(SimpleJob *job)
Stop the execution of a job.
Definition: scheduler.cpp:795
int error() const
KIOCORE_EXPORT SimpleJob * symlink(const QString &target, const QUrl &dest, JobFlags flags=DefaultFlags)
Create or move a symlink.
Definition: simplejob.cpp:370
bool doSuspend() override
Suspend this job.
Definition: simplejob.cpp:52
bool hasSubjobs() const
void clear()
void setError(int errorCode)
QString message
Q_D(Todo)
KIOCORE_EXPORT SimpleJob * chown(const QUrl &url, const QString &owner, const QString &group)
Changes ownership and group of a file or directory.
Definition: simplejob.cpp:350
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Nov 30 2023 03:52:32 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.