KIO

simplejob.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org>
4 SPDX-FileCopyrightText: 2000-2013 David Faure <faure@kde.org>
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 "worker_p.h"
14#include <QDebug>
15#include <QTimer>
16#include <kdirnotify.h>
17
18using namespace KIO;
19
20SimpleJob::SimpleJob(SimpleJobPrivate &dd)
21 : Job(dd)
22{
23 d_func()->simpleJobInit();
24}
25
26void 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
37 Scheduler::doJob(q);
38}
39
41{
43 if ((d->m_extraFlags & JobPrivate::EF_KillCalled) == 0) {
44 d->m_extraFlags |= JobPrivate::EF_KillCalled;
45 Scheduler::cancelJob(this); // deletes the worker if not 0
46 } else {
47 qCWarning(KIO_CORE) << this << "killed twice, this is overkill";
48 }
49 return Job::doKill();
50}
51
53{
55 if (d->m_worker) {
56 d->m_worker->suspend();
57 }
58 return Job::doSuspend();
59}
60
62{
64 if (d->m_worker) {
65 d->m_worker->resume();
66 }
67 return Job::doResume();
68}
69
70const QUrl &SimpleJob::url() const
71{
72 return d_func()->m_url;
73}
74
76{
78 Q_ASSERT(d->m_worker);
79 if (d->m_worker) {
80 Scheduler::putWorkerOnHold(this, d->m_url);
81 }
82 // we should now be disassociated from the worker
83 Q_ASSERT(!d->m_worker);
84 kill(Quietly);
85}
86
88{
89 Scheduler::removeWorkerOnHold();
90}
91
93{
94 return d_func()->m_redirectionHandlingEnabled;
95}
96
98{
100 d->m_redirectionHandlingEnabled = handle;
101}
102
103SimpleJob::~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
113void SimpleJobPrivate::start(Worker *worker)
114{
115 Q_Q(SimpleJob);
116 m_worker = worker;
117
118 // Worker::setJob can send us SSL metadata if there is a persistent connection
119 QObject::connect(worker, &Worker::metaData, q, &SimpleJob::slotMetaData);
120
121 worker->setJob(q);
122
123 QObject::connect(worker, &Worker::error, q, &SimpleJob::slotError);
124
125 QObject::connect(worker, &Worker::warning, q, &SimpleJob::slotWarning);
126
127 QObject::connect(worker, &Worker::finished, q, &SimpleJob::slotFinished);
128
129 QObject::connect(worker, &Worker::infoMessage, q, [this](const QString &message) {
130 _k_slotWorkerInfoMessage(message);
131 });
132
133 QObject::connect(worker, &Worker::connected, q, [this]() {
134 slotConnected();
135 });
136
137 QObject::connect(worker, &Worker::privilegeOperationRequested, q, [this]() {
138 slotPrivilegeOperationRequested();
139 });
140
141 if ((m_extraFlags & EF_TransferJobDataSent) == 0) { // this is a "get" job
142 QObject::connect(worker, &Worker::totalSize, q, [this](KIO::filesize_t size) {
143 slotTotalSize(size);
144 });
145
146 QObject::connect(worker, &Worker::processedSize, q, [this](KIO::filesize_t size) {
147 slotProcessedSize(size);
148 });
149
150 QObject::connect(worker, &Worker::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 worker->send(CMD_META_DATA, packedArgs);
172 }
173
174 worker->send(m_command, m_packedArgs);
175 if (q->isSuspended()) {
176 worker->suspend();
177 }
178}
179
180void SimpleJobPrivate::workerDone()
181{
182 Q_Q(SimpleJob);
183 if (m_worker) {
184 if (m_command == CMD_OPEN) {
185 m_worker->send(CMD_CLOSE);
186 }
187 q->disconnect(m_worker); // Remove all signals between worker and job
188 }
189 // only finish a job once; Scheduler::jobFinished() resets schedSerial to zero.
190 if (m_schedSerial) {
191 Scheduler::jobFinished(q, m_worker);
192 }
193}
194
196{
197 Q_D(SimpleJob);
198 // Return worker to the scheduler
199 d->workerDone();
200
201 if (!hasSubjobs()) {
202 if (!error() && (d->m_command == CMD_MKDIR || d->m_command == CMD_RENAME)) {
203 if (d->m_command == CMD_MKDIR) {
205#ifndef KIO_ANDROID_STUB
206 org::kde::KDirNotify::emitFilesAdded(urlDir);
207#endif
208 } else { /*if ( m_command == CMD_RENAME )*/
209 QUrl src;
210 QUrl dst;
211 QDataStream str(d->m_packedArgs);
212 str >> src >> dst;
213 if (src.adjusted(QUrl::RemoveFilename) == dst.adjusted(QUrl::RemoveFilename) // For the user, moving isn't
214 // renaming. Only renaming is.
215 ) {
216#ifndef KIO_ANDROID_STUB
217 org::kde::KDirNotify::emitFileRenamed(src, dst);
218#endif
219 }
220
221#ifndef KIO_ANDROID_STUB
222 org::kde::KDirNotify::emitFileMoved(src, dst);
223#endif
224 if (d->m_uiDelegateExtension) {
225 d->m_uiDelegateExtension->updateUrlInClipboard(src, dst);
226 }
227 }
228 }
229 emitResult();
230 }
231}
232
233void SimpleJob::slotError(int err, const QString &errorText)
234{
235 Q_D(SimpleJob);
236 setError(err);
238 if ((error() == ERR_UNKNOWN_HOST) && d->m_url.host().isEmpty()) {
240 }
241 // error terminates the job
242 slotFinished();
243}
244
245void SimpleJob::slotWarning(const QString &errorText)
246{
247 Q_EMIT warning(this, errorText);
248}
249
250void SimpleJobPrivate::_k_slotWorkerInfoMessage(const QString &msg)
251{
252 Q_EMIT q_func()->infoMessage(q_func(), msg);
253}
254
255void SimpleJobPrivate::slotConnected()
256{
257 Q_EMIT q_func()->connected(q_func());
258}
259
260void SimpleJobPrivate::slotTotalSize(KIO::filesize_t size)
261{
262 Q_Q(SimpleJob);
263 if (size != q->totalAmount(KJob::Bytes)) {
264 q->setTotalAmount(KJob::Bytes, size);
265 }
266}
267
268void SimpleJobPrivate::slotProcessedSize(KIO::filesize_t size)
269{
270 Q_Q(SimpleJob);
271 // qDebug() << KIO::number(size);
272 q->setProcessedAmount(KJob::Bytes, size);
273}
274
275void SimpleJobPrivate::slotSpeed(unsigned long speed)
276{
277 // qDebug() << speed;
278 q_func()->emitSpeed(speed);
279}
280
281void SimpleJobPrivate::restartAfterRedirection(QUrl *redirectionUrl)
282{
283 Q_Q(SimpleJob);
284 // Return worker to the scheduler while we still have the old URL in place; the scheduler
285 // requires a job URL to stay invariant while the job is running.
286 workerDone();
287
288 m_url = *redirectionUrl;
289 redirectionUrl->clear();
290 if ((m_extraFlags & EF_KillCalled) == 0) {
291 Scheduler::doJob(q);
292 }
293}
294
296{
297 Q_D(SimpleJob);
298 QMapIterator<QString, QString> it(_metaData);
299 while (it.hasNext()) {
300 it.next();
301 if (it.key().startsWith(QLatin1String("{internal~"), Qt::CaseInsensitive)) {
302 d->m_internalMetaData.insert(it.key(), it.value());
303 } else {
304 d->m_incomingMetaData.insert(it.key(), it.value());
305 }
306 }
307
308 // Update the internal meta-data values as soon as possible. Waiting until
309 // the KIO worker is finished has unintended consequences if the client starts
310 // a new connection without waiting for the KIO worker to finish.
311 if (!d->m_internalMetaData.isEmpty()) {
312 Scheduler::updateInternalMetaData(this);
313 }
314}
315
316void SimpleJobPrivate::slotPrivilegeOperationRequested()
317{
318 m_worker->send(MSG_PRIVILEGE_EXEC, privilegeOperationData());
319}
320
321//////////
323{
324 // qDebug() << "rmdir " << url;
325 KIO_ARGS << url << qint8(false); // isFile is false
326 return SimpleJobPrivate::newJob(url, CMD_DEL, packedArgs);
327}
328
329SimpleJob *KIO::chmod(const QUrl &url, int permissions)
330{
331 // qDebug() << "chmod " << url;
332 KIO_ARGS << url << permissions;
333 return SimpleJobPrivate::newJob(url, CMD_CHMOD, packedArgs);
334}
335
336SimpleJob *KIO::chown(const QUrl &url, const QString &owner, const QString &group)
337{
338 KIO_ARGS << url << owner << group;
339 return SimpleJobPrivate::newJob(url, CMD_CHOWN, packedArgs);
340}
341
343{
344 // qDebug() << "setModificationTime " << url << " " << mtime;
345 KIO_ARGS << url << mtime;
346 return SimpleJobPrivate::newJobNoUi(url, CMD_SETMODIFICATIONTIME, packedArgs);
347}
348
349SimpleJob *KIO::rename(const QUrl &src, const QUrl &dest, JobFlags flags)
350{
351 // qDebug() << "rename " << src << " " << dest;
352 KIO_ARGS << src << dest << (qint8)(flags & Overwrite);
353 return SimpleJobPrivate::newJob(src, CMD_RENAME, packedArgs, flags);
354}
355
356SimpleJob *KIO::symlink(const QString &target, const QUrl &dest, JobFlags flags)
357{
358 // qDebug() << "symlink target=" << target << " " << dest;
359 KIO_ARGS << target << dest << (qint8)(flags & Overwrite);
360 return SimpleJobPrivate::newJob(dest, CMD_SYMLINK, packedArgs, flags);
361}
362
363SimpleJob *KIO::special(const QUrl &url, const QByteArray &data, JobFlags flags)
364{
365 // qDebug() << "special " << url;
366 return SimpleJobPrivate::newJob(url, CMD_SPECIAL, data, flags);
367}
368
369SimpleJob *KIO::mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags)
370{
371 KIO_ARGS << int(1) << qint8(ro ? 1 : 0) << QString::fromLatin1(fstype) << dev << point;
372 SimpleJob *job = special(QUrl(QStringLiteral("file:///")), packedArgs, flags);
373 if (!(flags & HideProgressInfo)) {
374 KIO::JobPrivate::emitMounting(job, dev, point);
375 }
376 return job;
377}
378
380{
381 KIO_ARGS << int(2) << point;
382 SimpleJob *job = special(QUrl(QStringLiteral("file:///")), packedArgs, flags);
383 if (!(flags & HideProgressInfo)) {
384 KIO::JobPrivate::emitUnmounting(job, point);
385 }
386 return job;
387}
388
389//////////
390
391SimpleJob *KIO::http_update_cache(const QUrl &url, bool no_cache, const QDateTime &expireDate)
392{
393 Q_ASSERT(url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"));
394 // Send http update_cache command (2)
395 KIO_ARGS << (int)2 << url << no_cache << qlonglong(expireDate.toMSecsSinceEpoch() / 1000);
396 return SimpleJobPrivate::newJob(url, CMD_SPECIAL, packedArgs);
397}
398
399#include "moc_simplejob.cpp"
bool hasSubjobs() const
The base class for all jobs.
Definition job_base.h:45
bool doKill() override
Abort this job.
Definition job.cpp:157
bool doSuspend() override
Suspend this job.
Definition job.cpp:168
bool doResume() override
Resume this job.
Definition job.cpp:179
MetaData is a simple map of key/value strings.
Definition metadata.h:23
A simple job (one url and one command).
Definition simplejob.h:27
void slotError(int, const QString &)
static void removeOnHold()
Discard suspended worker.
Definition simplejob.cpp:87
void setRedirectionHandlingEnabled(bool handle)
Set handle to false to prevent the internal handling of redirections.
Definition simplejob.cpp:97
virtual void putOnHold()
Abort job.
Definition simplejob.cpp:75
bool doSuspend() override
Suspend this job.
Definition simplejob.cpp:52
virtual void slotWarning(const QString &)
virtual void slotFinished()
Called when the worker marks the job as finished.
KIOCORE_NO_EXPORT SimpleJob(SimpleJobPrivate &dd)
Creates a new simple job.
Definition simplejob.cpp:20
bool doResume() override
Resume this job.
Definition simplejob.cpp:61
bool isRedirectionHandlingEnabled() const
Returns true when redirections are handled internally, the default.
Definition simplejob.cpp:92
const QUrl & url() const
Returns the SimpleJob's URL.
Definition simplejob.cpp:70
virtual void slotMetaData(const KIO::MetaData &_metaData)
MetaData from the worker is received.
bool doKill() override
Abort job.
Definition simplejob.cpp:40
void setErrorText(const QString &errorText)
void emitResult()
int error() const
void warning(KJob *job, const QString &message)
void setError(int errorCode)
QString errorText() const
bool kill(KJob::KillVerbosity verbosity=KJob::Quietly)
A namespace for KIO globals.
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
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
Mount filesystem.
KIOCORE_EXPORT SimpleJob * rmdir(const QUrl &url)
Removes a single directory.
KIOCORE_EXPORT SimpleJob * http_update_cache(const QUrl &url, bool no_cache, const QDateTime &expireDate)
HTTP cache update.
KIOCORE_EXPORT SimpleJob * rename(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
Rename a file or directory.
KIOCORE_EXPORT SimpleJob * special(const QUrl &url, const QByteArray &data, JobFlags flags=DefaultFlags)
Execute any command that is specific to one worker (protocol).
KIOCORE_EXPORT SimpleJob * unmount(const QString &point, JobFlags flags=DefaultFlags)
Unmount filesystem.
KIOCORE_EXPORT SimpleJob * symlink(const QString &target, const QUrl &dest, JobFlags flags=DefaultFlags)
Create or move a symlink.
KIOCORE_EXPORT SimpleJob * setModificationTime(const QUrl &url, const QDateTime &mtime)
Changes the modification time on a file or directory.
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition job_base.h:251
@ Overwrite
When set, automatically overwrite the destination if it exists already.
Definition job_base.h:267
KIOCORE_EXPORT SimpleJob * chown(const QUrl &url, const QString &owner, const QString &group)
Changes ownership and group of a file or directory.
qulonglong filesize_t
64-bit file size
Definition global.h:35
qint64 toMSecsSinceEpoch() const const
bool hasNext() const const
const Key & key() const const
const T & value() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLatin1(QByteArrayView str)
QString number(double n, char format, int precision)
CaseInsensitive
RemoveFilename
QUrl adjusted(FormattingOptions options) const const
void clear()
QString scheme() const const
bool isValid() const const
qulonglong toULongLong(bool *ok) const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:51 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.