File indexing completed on 2024-12-01 03:40:38
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org> 0004 SPDX-FileCopyrightText: 2000-2009 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2000-2009 Waldo Bastian <bastian@kde.org> 0006 SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org> 0007 SPDX-FileCopyrightText: 2013 Dawit Alemayehu <adawit@kde.org> 0008 0009 SPDX-License-Identifier: LGPL-2.0-or-later 0010 */ 0011 0012 #ifndef KIO_JOB_P_H 0013 #define KIO_JOB_P_H 0014 0015 #include "commands_p.h" 0016 #include "global.h" 0017 #include "jobtracker.h" 0018 #include "kiocoredebug.h" 0019 #include "simplejob.h" 0020 #include "transferjob.h" 0021 #include "worker_p.h" 0022 #include <KJobTrackerInterface> 0023 #include <QDataStream> 0024 #include <QPointer> 0025 #include <QUrl> 0026 #include <kio/jobuidelegateextension.h> 0027 #include <kio/jobuidelegatefactory.h> 0028 0029 /* clang-format off */ 0030 #define KIO_ARGS \ 0031 QByteArray packedArgs; \ 0032 QDataStream stream(&packedArgs, QIODevice::WriteOnly); \ 0033 stream 0034 /* clang-format on */ 0035 0036 namespace KIO 0037 { 0038 static constexpr filesize_t invalidFilesize = static_cast<KIO::filesize_t>(-1); 0039 0040 // Exported for KIOWidgets jobs 0041 class KIOCORE_EXPORT JobPrivate 0042 { 0043 public: 0044 JobPrivate() 0045 : m_parentJob(nullptr) 0046 , m_extraFlags(0) 0047 , m_uiDelegateExtension(KIO::defaultJobUiDelegateExtension()) 0048 , m_privilegeExecutionEnabled(false) 0049 { 0050 } 0051 0052 virtual ~JobPrivate(); 0053 0054 /** 0055 * Some extra storage space for jobs that don't have their own 0056 * private d pointer. 0057 */ 0058 enum { 0059 EF_TransferJobAsync = (1 << 0), 0060 EF_TransferJobNeedData = (1 << 1), 0061 EF_TransferJobDataSent = (1 << 2), 0062 EF_ListJobUnrestricted = (1 << 3), 0063 EF_KillCalled = (1 << 4), 0064 }; 0065 0066 enum FileOperationType { 0067 ChangeAttr, // chmod(), chown(), setModificationTime() 0068 Copy, 0069 Delete, 0070 MkDir, 0071 Move, 0072 Rename, 0073 Symlink, 0074 Transfer, // put() and get() 0075 Other, // if other file operation set message, title inside the job. 0076 }; 0077 0078 // Maybe we could use the QObject parent/child mechanism instead 0079 // (requires a new ctor, and moving the ctor code to some init()). 0080 Job *m_parentJob; 0081 int m_extraFlags; 0082 MetaData m_incomingMetaData; 0083 MetaData m_internalMetaData; 0084 MetaData m_outgoingMetaData; 0085 JobUiDelegateExtension *m_uiDelegateExtension; 0086 Job *q_ptr; 0087 // For privilege operation 0088 bool m_privilegeExecutionEnabled; 0089 QString m_title, m_message; 0090 FileOperationType m_operationType; 0091 0092 QByteArray privilegeOperationData(); 0093 void slotSpeed(KJob *job, unsigned long speed); 0094 0095 static void emitMoving(KIO::Job *, const QUrl &src, const QUrl &dest); 0096 static void emitRenaming(KIO::Job *, const QUrl &src, const QUrl &dest); 0097 static void emitCopying(KIO::Job *, const QUrl &src, const QUrl &dest); 0098 static void emitCreatingDir(KIO::Job *, const QUrl &dir); 0099 static void emitDeleting(KIO::Job *, const QUrl &url); 0100 static void emitStating(KIO::Job *, const QUrl &url); 0101 static void emitTransferring(KIO::Job *, const QUrl &url); 0102 static void emitMounting(KIO::Job *, const QString &dev, const QString &point); 0103 static void emitUnmounting(KIO::Job *, const QString &point); 0104 0105 Q_DECLARE_PUBLIC(Job) 0106 }; 0107 0108 class SimpleJobPrivate : public JobPrivate 0109 { 0110 public: 0111 /** 0112 * Creates a new simple job. 0113 * @param url the url of the job 0114 * @param command the command of the job 0115 * @param packedArgs the arguments 0116 */ 0117 SimpleJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs) 0118 : m_worker(nullptr) 0119 , m_packedArgs(packedArgs) 0120 , m_url(url) 0121 , m_command(command) 0122 , m_schedSerial(0) 0123 , m_redirectionHandlingEnabled(true) 0124 { 0125 } 0126 0127 QPointer<Worker> m_worker; 0128 QByteArray m_packedArgs; 0129 QUrl m_url; 0130 int m_command; 0131 0132 // for use in KIO::Scheduler 0133 // 0134 // There are two kinds of protocol: 0135 // (1) The protocol of the url 0136 // (2) The actual protocol that the KIO worker uses. 0137 // 0138 // These two often match, but not necessarily. Most notably, they don't 0139 // match when doing ftp via a proxy. 0140 // In that case (1) is ftp, but (2) is http. 0141 // 0142 // JobData::protocol stores (2) while Job::url().protocol() returns (1). 0143 // The ProtocolInfoDict is indexed with (2). 0144 // 0145 // We schedule workers based on (2) but tell the worker about (1) via 0146 // Worker::setProtocol(). 0147 QString m_protocol; 0148 QStringList m_proxyList; 0149 int m_schedSerial; 0150 bool m_redirectionHandlingEnabled; 0151 0152 void simpleJobInit(); 0153 0154 /** 0155 * Called on a worker's connected signal. 0156 * @see connected() 0157 */ 0158 void slotConnected(); 0159 /** 0160 * Forward signal from the worker. 0161 * @param data_size the processed size in bytes 0162 * @see processedSize() 0163 */ 0164 void slotProcessedSize(KIO::filesize_t data_size); 0165 /** 0166 * Forward signal from the worker. 0167 * @param speed the speed in bytes/s 0168 * @see speed() 0169 */ 0170 void slotSpeed(unsigned long speed); 0171 /** 0172 * Forward signal from the worker. 0173 * Can also be called by the parent job, when it knows the size. 0174 * @param data_size the total size 0175 */ 0176 void slotTotalSize(KIO::filesize_t data_size); 0177 0178 /** 0179 * Called on a worker's info message. 0180 * @param s the info message 0181 * @see infoMessage() 0182 */ 0183 void _k_slotWorkerInfoMessage(const QString &s); 0184 0185 /** 0186 * Called when privilegeOperationRequested() is emitted by worker. 0187 */ 0188 void slotPrivilegeOperationRequested(); 0189 0190 /** 0191 * @internal 0192 * Called by the scheduler when a worker gets to 0193 * work on this job. 0194 **/ 0195 virtual void start(KIO::Worker *worker); 0196 0197 /** 0198 * @internal 0199 * Called to detach a worker from a job. 0200 **/ 0201 void workerDone(); 0202 0203 /** 0204 * Called by subclasses to restart the job after a redirection was signalled. 0205 * The m_redirectionURL data member can appear in several subclasses, so we have it 0206 * passed in. The regular URL will be set to the redirection URL which is then cleared. 0207 */ 0208 void restartAfterRedirection(QUrl *redirectionUrl); 0209 0210 Q_DECLARE_PUBLIC(SimpleJob) 0211 0212 static inline SimpleJobPrivate *get(KIO::SimpleJob *job) 0213 { 0214 return job->d_func(); 0215 } 0216 static inline SimpleJob *newJobNoUi(const QUrl &url, int command, const QByteArray &packedArgs) 0217 { 0218 SimpleJob *job = new SimpleJob(*new SimpleJobPrivate(url, command, packedArgs)); 0219 return job; 0220 } 0221 static inline SimpleJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, JobFlags flags = HideProgressInfo) 0222 { 0223 SimpleJob *job = new SimpleJob(*new SimpleJobPrivate(url, command, packedArgs)); 0224 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0225 if (!(flags & HideProgressInfo)) { 0226 KIO::getJobTracker()->registerJob(job); 0227 } 0228 if (!(flags & NoPrivilegeExecution)) { 0229 job->d_func()->m_privilegeExecutionEnabled = true; 0230 // Only delete, rename and symlink operation accept JobFlags. 0231 FileOperationType opType; 0232 switch (command) { 0233 case CMD_DEL: 0234 opType = Delete; 0235 break; 0236 case CMD_RENAME: 0237 opType = Rename; 0238 break; 0239 case CMD_SYMLINK: 0240 opType = Symlink; 0241 break; 0242 default: 0243 return job; 0244 } 0245 job->d_func()->m_operationType = opType; 0246 } 0247 return job; 0248 } 0249 }; 0250 0251 class TransferJobPrivate : public SimpleJobPrivate 0252 { 0253 public: 0254 inline TransferJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs, const QByteArray &_staticData) 0255 : SimpleJobPrivate(url, command, packedArgs) 0256 , m_internalSuspended(false) 0257 , m_errorPage(false) 0258 , staticData(_staticData) 0259 , m_isMimetypeEmitted(false) 0260 , m_closedBeforeStart(false) 0261 { 0262 } 0263 0264 inline TransferJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice) 0265 : SimpleJobPrivate(url, command, packedArgs) 0266 , m_internalSuspended(false) 0267 , m_errorPage(false) 0268 , m_isMimetypeEmitted(false) 0269 , m_closedBeforeStart(false) 0270 , m_outgoingDataSource(QPointer<QIODevice>(ioDevice)) 0271 { 0272 } 0273 0274 bool m_internalSuspended; 0275 bool m_errorPage; 0276 QByteArray staticData; 0277 QUrl m_redirectionURL; 0278 QList<QUrl> m_redirectionList; 0279 QString m_mimetype; 0280 bool m_isMimetypeEmitted; 0281 bool m_closedBeforeStart; 0282 QPointer<QIODevice> m_outgoingDataSource; 0283 QMetaObject::Connection m_readChannelFinishedConnection; 0284 0285 /** 0286 * Flow control. Suspend data processing from the worker. 0287 */ 0288 void internalSuspend(); 0289 /** 0290 * Flow control. Resume data processing from the worker. 0291 */ 0292 void internalResume(); 0293 /** 0294 * @internal 0295 * Called by the scheduler when a worker gets to 0296 * work on this job. 0297 * @param worker the worker that works on the job 0298 */ 0299 void start(KIO::Worker *worker) override; 0300 /** 0301 * @internal 0302 * Called when the KIO worker needs the data to send the server. This slot 0303 * is invoked when the data is to be sent is read from a QIODevice rather 0304 * instead of a QByteArray buffer. 0305 */ 0306 virtual void slotDataReqFromDevice(); 0307 void slotIODeviceClosed(); 0308 void slotIODeviceClosedBeforeStart(); 0309 void slotPostRedirection(); 0310 0311 Q_DECLARE_PUBLIC(TransferJob) 0312 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, const QByteArray &_staticData, JobFlags flags) 0313 { 0314 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, _staticData)); 0315 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0316 if (!(flags & HideProgressInfo)) { 0317 job->setFinishedNotificationHidden(); 0318 KIO::getJobTracker()->registerJob(job); 0319 } 0320 if (!(flags & NoPrivilegeExecution)) { 0321 job->d_func()->m_privilegeExecutionEnabled = true; 0322 job->d_func()->m_operationType = Transfer; 0323 } 0324 return job; 0325 } 0326 0327 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice, JobFlags flags) 0328 { 0329 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, ioDevice)); 0330 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0331 if (!(flags & HideProgressInfo)) { 0332 job->setFinishedNotificationHidden(); 0333 KIO::getJobTracker()->registerJob(job); 0334 } 0335 if (!(flags & NoPrivilegeExecution)) { 0336 job->d_func()->m_privilegeExecutionEnabled = true; 0337 job->d_func()->m_operationType = Transfer; 0338 } 0339 return job; 0340 } 0341 }; 0342 0343 class DirectCopyJobPrivate; 0344 /** 0345 * @internal 0346 * Used for direct copy from or to the local filesystem (i.e.\ WorkerBase::copy()) 0347 */ 0348 class DirectCopyJob : public SimpleJob 0349 { 0350 Q_OBJECT 0351 0352 public: 0353 DirectCopyJob(const QUrl &url, const QByteArray &packedArgs); 0354 ~DirectCopyJob() override; 0355 0356 public Q_SLOTS: 0357 void slotCanResume(KIO::filesize_t offset); 0358 0359 Q_SIGNALS: 0360 /** 0361 * @internal 0362 * Emitted if the job found an existing partial file 0363 * and supports resuming. Used by FileCopyJob. 0364 */ 0365 void canResume(KIO::Job *job, KIO::filesize_t offset); 0366 0367 private: 0368 Q_DECLARE_PRIVATE(DirectCopyJob) 0369 }; 0370 } 0371 0372 #endif