1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org>
4 SPDX-FileCopyrightText: 2000-2009 David Faure <faure@kde.org>
5 SPDX-FileCopyrightText: 2000-2009 Waldo Bastian <bastian@kde.org>
6 SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org>
7 SPDX-FileCopyrightText: 2013 Dawit Alemayehu <adawit@kde.org>
8
9 SPDX-License-Identifier: LGPL-2.0-or-later
10*/
11
12#ifndef KIO_JOB_P_H
13#define KIO_JOB_P_H
14
15#include "commands_p.h"
16#include "global.h"
17#include "jobtracker.h"
18#include "kiocoredebug.h"
19#include "simplejob.h"
20#include "transferjob.h"
21#include "worker_p.h"
22#include <KJobTrackerInterface>
23#include <QDataStream>
24#include <QPointer>
25#include <QUrl>
26#include <kio/jobuidelegateextension.h>
27#include <kio/jobuidelegatefactory.h>
28
29/* clang-format off */
30#define KIO_ARGS \
31 QByteArray packedArgs; \
32 QDataStream stream(&packedArgs, QIODevice::WriteOnly); \
33 stream
34/* clang-format on */
35
36namespace KIO
37{
38static constexpr filesize_t invalidFilesize = static_cast<KIO::filesize_t>(-1);
39
40// Exported for KIOWidgets jobs
41class KIOCORE_EXPORT JobPrivate
42{
43public:
44 JobPrivate()
45 : m_parentJob(nullptr)
46 , m_extraFlags(0)
47 , m_uiDelegateExtension(KIO::defaultJobUiDelegateExtension())
48 , m_privilegeExecutionEnabled(false)
49 {
50 }
51
52 virtual ~JobPrivate();
53
54 /**
55 * Some extra storage space for jobs that don't have their own
56 * private d pointer.
57 */
58 enum {
59 EF_TransferJobAsync = (1 << 0),
60 EF_TransferJobNeedData = (1 << 1),
61 EF_TransferJobDataSent = (1 << 2),
62 EF_ListJobUnrestricted = (1 << 3),
63 EF_KillCalled = (1 << 4),
64 };
65
66 enum FileOperationType {
67 ChangeAttr, // chmod(), chown(), setModificationTime()
68 Copy,
69 Delete,
70 MkDir,
71 Move,
72 Rename,
73 Symlink,
74 Transfer, // put() and get()
75 Other, // if other file operation set message, title inside the job.
76 };
77
78 // Maybe we could use the QObject parent/child mechanism instead
79 // (requires a new ctor, and moving the ctor code to some init()).
80 Job *m_parentJob;
81 int m_extraFlags;
82 MetaData m_incomingMetaData;
83 MetaData m_internalMetaData;
84 MetaData m_outgoingMetaData;
85 JobUiDelegateExtension *m_uiDelegateExtension;
86 Job *q_ptr;
87 // For privilege operation
88 bool m_privilegeExecutionEnabled;
89 QString m_title, m_message;
90 FileOperationType m_operationType;
91
92 QByteArray privilegeOperationData();
93 void slotSpeed(KJob *job, unsigned long speed);
94
95 static void emitMoving(KIO::Job *, const QUrl &src, const QUrl &dest);
96 static void emitRenaming(KIO::Job *, const QUrl &src, const QUrl &dest);
97 static void emitCopying(KIO::Job *, const QUrl &src, const QUrl &dest);
98 static void emitCreatingDir(KIO::Job *, const QUrl &dir);
99 static void emitDeleting(KIO::Job *, const QUrl &url);
100 static void emitStating(KIO::Job *, const QUrl &url);
101 static void emitTransferring(KIO::Job *, const QUrl &url);
102 static void emitMounting(KIO::Job *, const QString &dev, const QString &point);
103 static void emitUnmounting(KIO::Job *, const QString &point);
104
105 Q_DECLARE_PUBLIC(Job)
106};
107
108class SimpleJobPrivate : public JobPrivate
109{
110public:
111 /**
112 * Creates a new simple job.
113 * @param url the url of the job
114 * @param command the command of the job
115 * @param packedArgs the arguments
116 */
117 SimpleJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs)
118 : m_worker(nullptr)
119 , m_packedArgs(packedArgs)
120 , m_url(url)
121 , m_command(command)
122 , m_schedSerial(0)
123 , m_redirectionHandlingEnabled(true)
124 {
125 }
126
127 QPointer<Worker> m_worker;
128 QByteArray m_packedArgs;
129 QUrl m_url;
130 int m_command;
131
132 // for use in KIO::Scheduler
133 //
134 // There are two kinds of protocol:
135 // (1) The protocol of the url
136 // (2) The actual protocol that the KIO worker uses.
137 //
138 // These two often match, but not necessarily. Most notably, they don't
139 // match when doing ftp via a proxy.
140 // In that case (1) is ftp, but (2) is http.
141 //
142 // JobData::protocol stores (2) while Job::url().protocol() returns (1).
143 // The ProtocolInfoDict is indexed with (2).
144 //
145 // We schedule workers based on (2) but tell the worker about (1) via
146 // Worker::setProtocol().
147 QString m_protocol;
148 QStringList m_proxyList;
149 int m_schedSerial;
150 bool m_redirectionHandlingEnabled;
151
152 void simpleJobInit();
153
154 /**
155 * Called on a worker's connected signal.
156 * @see connected()
157 */
158 void slotConnected();
159 /**
160 * Forward signal from the worker.
161 * @param data_size the processed size in bytes
162 * @see processedSize()
163 */
164 void slotProcessedSize(KIO::filesize_t data_size);
165 /**
166 * Forward signal from the worker.
167 * @param speed the speed in bytes/s
168 * @see speed()
169 */
170 void slotSpeed(unsigned long speed);
171 /**
172 * Forward signal from the worker.
173 * Can also be called by the parent job, when it knows the size.
174 * @param data_size the total size
175 */
176 void slotTotalSize(KIO::filesize_t data_size);
177
178 /**
179 * Called on a worker's info message.
180 * @param s the info message
181 * @see infoMessage()
182 */
183 void _k_slotWorkerInfoMessage(const QString &s);
184
185 /**
186 * Called when privilegeOperationRequested() is emitted by worker.
187 */
188 void slotPrivilegeOperationRequested();
189
190 /**
191 * @internal
192 * Called by the scheduler when a worker gets to
193 * work on this job.
194 **/
195 virtual void start(KIO::Worker *worker);
196
197 /**
198 * @internal
199 * Called to detach a worker from a job.
200 **/
201 void workerDone();
202
203 /**
204 * Called by subclasses to restart the job after a redirection was signalled.
205 * The m_redirectionURL data member can appear in several subclasses, so we have it
206 * passed in. The regular URL will be set to the redirection URL which is then cleared.
207 */
208 void restartAfterRedirection(QUrl *redirectionUrl);
209
210 Q_DECLARE_PUBLIC(SimpleJob)
211
212 static inline SimpleJobPrivate *get(KIO::SimpleJob *job)
213 {
214 return job->d_func();
215 }
216 static inline SimpleJob *newJobNoUi(const QUrl &url, int command, const QByteArray &packedArgs)
217 {
218 SimpleJob *job = new SimpleJob(*new SimpleJobPrivate(url, command, packedArgs));
219 return job;
220 }
221 static inline SimpleJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, JobFlags flags = HideProgressInfo)
222 {
223 SimpleJob *job = new SimpleJob(*new SimpleJobPrivate(url, command, packedArgs));
224 job->setUiDelegate(KIO::createDefaultJobUiDelegate());
225 if (!(flags & HideProgressInfo)) {
226 KIO::getJobTracker()->registerJob(job);
227 }
228 if (!(flags & NoPrivilegeExecution)) {
229 job->d_func()->m_privilegeExecutionEnabled = true;
230 // Only delete, rename and symlink operation accept JobFlags.
231 FileOperationType opType;
232 switch (command) {
233 case CMD_DEL:
234 opType = Delete;
235 break;
236 case CMD_RENAME:
237 opType = Rename;
238 break;
239 case CMD_SYMLINK:
240 opType = Symlink;
241 break;
242 default:
243 return job;
244 }
245 job->d_func()->m_operationType = opType;
246 }
247 return job;
248 }
249};
250
251class TransferJobPrivate : public SimpleJobPrivate
252{
253public:
254 inline TransferJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs, const QByteArray &_staticData)
255 : SimpleJobPrivate(url, command, packedArgs)
256 , m_internalSuspended(false)
257 , m_errorPage(false)
258 , staticData(_staticData)
259 , m_isMimetypeEmitted(false)
260 , m_closedBeforeStart(false)
261 {
262 }
263
264 inline TransferJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice)
265 : SimpleJobPrivate(url, command, packedArgs)
266 , m_internalSuspended(false)
267 , m_errorPage(false)
268 , m_isMimetypeEmitted(false)
269 , m_closedBeforeStart(false)
270 , m_outgoingDataSource(QPointer<QIODevice>(ioDevice))
271 {
272 }
273
274 bool m_internalSuspended;
275 bool m_errorPage;
276 QByteArray staticData;
277 QUrl m_redirectionURL;
278 QList<QUrl> m_redirectionList;
279 QString m_mimetype;
280 bool m_isMimetypeEmitted;
281 bool m_closedBeforeStart;
282 QPointer<QIODevice> m_outgoingDataSource;
283 QMetaObject::Connection m_readChannelFinishedConnection;
284
285 /**
286 * Flow control. Suspend data processing from the worker.
287 */
288 void internalSuspend();
289 /**
290 * Flow control. Resume data processing from the worker.
291 */
292 void internalResume();
293 /**
294 * @internal
295 * Called by the scheduler when a worker gets to
296 * work on this job.
297 * @param worker the worker that works on the job
298 */
299 void start(KIO::Worker *worker) override;
300 /**
301 * @internal
302 * Called when the KIO worker needs the data to send the server. This slot
303 * is invoked when the data is to be sent is read from a QIODevice rather
304 * instead of a QByteArray buffer.
305 */
306 virtual void slotDataReqFromDevice();
307 void slotIODeviceClosed();
308 void slotIODeviceClosedBeforeStart();
309 void slotPostRedirection();
310
311 Q_DECLARE_PUBLIC(TransferJob)
312 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, const QByteArray &_staticData, JobFlags flags)
313 {
314 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, _staticData));
315 job->setUiDelegate(KIO::createDefaultJobUiDelegate());
316 if (!(flags & HideProgressInfo)) {
317 job->setFinishedNotificationHidden();
318 KIO::getJobTracker()->registerJob(job);
319 }
320 if (!(flags & NoPrivilegeExecution)) {
321 job->d_func()->m_privilegeExecutionEnabled = true;
322 job->d_func()->m_operationType = Transfer;
323 }
324 return job;
325 }
326
327 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice, JobFlags flags)
328 {
329 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, ioDevice));
330 job->setUiDelegate(KIO::createDefaultJobUiDelegate());
331 if (!(flags & HideProgressInfo)) {
332 job->setFinishedNotificationHidden();
333 KIO::getJobTracker()->registerJob(job);
334 }
335 if (!(flags & NoPrivilegeExecution)) {
336 job->d_func()->m_privilegeExecutionEnabled = true;
337 job->d_func()->m_operationType = Transfer;
338 }
339 return job;
340 }
341};
342
343class DirectCopyJobPrivate;
344/**
345 * @internal
346 * Used for direct copy from or to the local filesystem (i.e.\ WorkerBase::copy())
347 */
348class DirectCopyJob : public SimpleJob
349{
350 Q_OBJECT
351
352public:
353 DirectCopyJob(const QUrl &url, const QByteArray &packedArgs);
354 ~DirectCopyJob() override;
355
356public Q_SLOTS:
357 void slotCanResume(KIO::filesize_t offset);
358
359Q_SIGNALS:
360 /**
361 * @internal
362 * Emitted if the job found an existing partial file
363 * and supports resuming. Used by FileCopyJob.
364 */
365 void canResume(KIO::Job *job, KIO::filesize_t offset);
366
367private:
368 Q_DECLARE_PRIVATE(DirectCopyJob)
369};
370}
371
372#endif
373

source code of kio/src/core/job_p.h