File indexing completed on 2024-09-08 12:18:36
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 "kiocoredebug.h" 0018 #include "simplejob.h" 0019 #include "slave.h" 0020 #include "transferjob.h" 0021 #include <KJobTrackerInterface> 0022 #include <QDataStream> 0023 #include <QPointer> 0024 #include <QUrl> 0025 #include <kio/jobuidelegateextension.h> 0026 #include <kio/jobuidelegatefactory.h> 0027 0028 /* clang-format off */ 0029 #define KIO_ARGS \ 0030 QByteArray packedArgs; \ 0031 QDataStream stream(&packedArgs, QIODevice::WriteOnly); \ 0032 stream 0033 /* clang-format on */ 0034 0035 namespace KIO 0036 { 0037 static constexpr filesize_t invalidFilesize = static_cast<KIO::filesize_t>(-1); 0038 0039 // Exported for KIOWidgets jobs 0040 class KIOCORE_EXPORT JobPrivate 0041 { 0042 public: 0043 JobPrivate() 0044 : m_parentJob(nullptr) 0045 , m_extraFlags(0) 0046 , m_uiDelegateExtension(KIO::defaultJobUiDelegateExtension()) 0047 , m_privilegeExecutionEnabled(false) 0048 { 0049 } 0050 0051 virtual ~JobPrivate(); 0052 0053 /** 0054 * Some extra storage space for jobs that don't have their own 0055 * private d pointer. 0056 */ 0057 enum { 0058 EF_TransferJobAsync = (1 << 0), 0059 EF_TransferJobNeedData = (1 << 1), 0060 EF_TransferJobDataSent = (1 << 2), 0061 EF_ListJobUnrestricted = (1 << 3), 0062 EF_KillCalled = (1 << 4), 0063 }; 0064 0065 enum FileOperationType { 0066 ChangeAttr, // chmod(), chown(), setModificationTime() 0067 Copy, 0068 Delete, 0069 MkDir, 0070 Move, 0071 Rename, 0072 Symlink, 0073 Transfer, // put() and get() 0074 Other, // if other file operation set message, title inside the job. 0075 }; 0076 0077 // Maybe we could use the QObject parent/child mechanism instead 0078 // (requires a new ctor, and moving the ctor code to some init()). 0079 Job *m_parentJob; 0080 int m_extraFlags; 0081 MetaData m_incomingMetaData; 0082 MetaData m_internalMetaData; 0083 MetaData m_outgoingMetaData; 0084 JobUiDelegateExtension *m_uiDelegateExtension; 0085 Job *q_ptr; 0086 // For privilege operation 0087 bool m_privilegeExecutionEnabled; 0088 QString m_title, m_message; 0089 FileOperationType m_operationType; 0090 0091 QByteArray privilegeOperationData(); 0092 void slotSpeed(KJob *job, unsigned long speed); 0093 0094 static void emitMoving(KIO::Job *, const QUrl &src, const QUrl &dest); 0095 static void emitRenaming(KIO::Job *, const QUrl &src, const QUrl &dest); 0096 static void emitCopying(KIO::Job *, const QUrl &src, const QUrl &dest); 0097 static void emitCreatingDir(KIO::Job *, const QUrl &dir); 0098 static void emitDeleting(KIO::Job *, const QUrl &url); 0099 static void emitStating(KIO::Job *, const QUrl &url); 0100 static void emitTransferring(KIO::Job *, const QUrl &url); 0101 static void emitMounting(KIO::Job *, const QString &dev, const QString &point); 0102 static void emitUnmounting(KIO::Job *, const QString &point); 0103 0104 Q_DECLARE_PUBLIC(Job) 0105 }; 0106 0107 class SimpleJobPrivate : public JobPrivate 0108 { 0109 public: 0110 /** 0111 * Creates a new simple job. 0112 * @param url the url of the job 0113 * @param command the command of the job 0114 * @param packedArgs the arguments 0115 */ 0116 SimpleJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs) 0117 : m_slave(nullptr) 0118 , m_packedArgs(packedArgs) 0119 , m_url(url) 0120 , m_command(command) 0121 , m_schedSerial(0) 0122 , m_redirectionHandlingEnabled(true) 0123 { 0124 } 0125 0126 QPointer<Slave> m_slave; 0127 QByteArray m_packedArgs; 0128 QUrl m_url; 0129 QUrl m_subUrl; // TODO KF6 remove 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 // Slave::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 slave's connected signal. 0156 * @see connected() 0157 */ 0158 void slotConnected(); 0159 /** 0160 * Forward signal from the slave. 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 slave. 0167 * @param speed the speed in bytes/s 0168 * @see speed() 0169 */ 0170 void slotSpeed(unsigned long speed); 0171 /** 0172 * Forward signal from the slave 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 slave's info message. 0180 * @param s the info message 0181 * @see infoMessage() 0182 */ 0183 void _k_slotSlaveInfoMessage(const QString &s); 0184 0185 /** 0186 * Called when privilegeOperationRequested() is emitted by slave. 0187 */ 0188 void slotPrivilegeOperationRequested(); 0189 0190 /** 0191 * @internal 0192 * Called by the scheduler when a slave gets to 0193 * work on this job. 0194 **/ 0195 virtual void start(KIO::Slave *slave); 0196 0197 /** 0198 * @internal 0199 * Called to detach a slave from a job. 0200 **/ 0201 void slaveDone(); 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 , m_subJob(nullptr) 0262 { 0263 } 0264 0265 inline TransferJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice) 0266 : SimpleJobPrivate(url, command, packedArgs) 0267 , m_internalSuspended(false) 0268 , m_errorPage(false) 0269 , m_isMimetypeEmitted(false) 0270 , m_closedBeforeStart(false) 0271 , m_subJob(nullptr) 0272 , m_outgoingDataSource(QPointer<QIODevice>(ioDevice)) 0273 { 0274 } 0275 0276 bool m_internalSuspended; 0277 bool m_errorPage; 0278 QByteArray staticData; 0279 QUrl m_redirectionURL; 0280 QList<QUrl> m_redirectionList; 0281 QString m_mimetype; 0282 bool m_isMimetypeEmitted; 0283 bool m_closedBeforeStart; 0284 TransferJob *m_subJob; 0285 QPointer<QIODevice> m_outgoingDataSource; 0286 QMetaObject::Connection m_readChannelFinishedConnection; 0287 0288 /** 0289 * Flow control. Suspend data processing from the slave. 0290 */ 0291 void internalSuspend(); 0292 /** 0293 * Flow control. Resume data processing from the slave. 0294 */ 0295 void internalResume(); 0296 /** 0297 * @internal 0298 * Called by the scheduler when a slave gets to 0299 * work on this job. 0300 * @param slave the slave that works on the job 0301 */ 0302 void start(KIO::Slave *slave) override; 0303 /** 0304 * @internal 0305 * Called when the KIO worker needs the data to send the server. This slot 0306 * is invoked when the data is to be sent is read from a QIODevice rather 0307 * instead of a QByteArray buffer. 0308 */ 0309 virtual void slotDataReqFromDevice(); 0310 void slotIODeviceClosed(); 0311 void slotIODeviceClosedBeforeStart(); 0312 void slotPostRedirection(); 0313 void slotNeedSubUrlData(); 0314 void slotSubUrlData(KIO::Job *, const QByteArray &); 0315 0316 Q_DECLARE_PUBLIC(TransferJob) 0317 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, const QByteArray &_staticData, JobFlags flags) 0318 { 0319 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, _staticData)); 0320 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0321 if (!(flags & HideProgressInfo)) { 0322 job->setFinishedNotificationHidden(); 0323 KIO::getJobTracker()->registerJob(job); 0324 } 0325 if (!(flags & NoPrivilegeExecution)) { 0326 job->d_func()->m_privilegeExecutionEnabled = true; 0327 job->d_func()->m_operationType = Transfer; 0328 } 0329 return job; 0330 } 0331 0332 static inline TransferJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, QIODevice *ioDevice, JobFlags flags) 0333 { 0334 TransferJob *job = new TransferJob(*new TransferJobPrivate(url, command, packedArgs, ioDevice)); 0335 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0336 if (!(flags & HideProgressInfo)) { 0337 job->setFinishedNotificationHidden(); 0338 KIO::getJobTracker()->registerJob(job); 0339 } 0340 if (!(flags & NoPrivilegeExecution)) { 0341 job->d_func()->m_privilegeExecutionEnabled = true; 0342 job->d_func()->m_operationType = Transfer; 0343 } 0344 return job; 0345 } 0346 }; 0347 0348 class DirectCopyJobPrivate; 0349 /** 0350 * @internal 0351 * Used for direct copy from or to the local filesystem (i.e.\ WorkerBase::copy()) 0352 */ 0353 class DirectCopyJob : public SimpleJob 0354 { 0355 Q_OBJECT 0356 0357 public: 0358 DirectCopyJob(const QUrl &url, const QByteArray &packedArgs); 0359 ~DirectCopyJob() override; 0360 0361 public Q_SLOTS: 0362 void slotCanResume(KIO::filesize_t offset); 0363 0364 Q_SIGNALS: 0365 /** 0366 * @internal 0367 * Emitted if the job found an existing partial file 0368 * and supports resuming. Used by FileCopyJob. 0369 */ 0370 void canResume(KIO::Job *job, KIO::filesize_t offset); 0371 0372 private: 0373 Q_DECLARE_PRIVATE(DirectCopyJob) 0374 }; 0375 } 0376 0377 #endif