File indexing completed on 2023-09-24 04:08:32
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 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "job.h" 0011 #include "job_p.h" 0012 0013 #include <time.h> 0014 0015 #include <KLocalizedString> 0016 #include <KStringHandler> 0017 0018 #include "slave.h" 0019 #include <kio/jobuidelegateextension.h> 0020 0021 using namespace KIO; 0022 0023 Job::Job() 0024 : KCompositeJob(nullptr) 0025 , d_ptr(new JobPrivate) 0026 { 0027 d_ptr->q_ptr = this; 0028 setCapabilities(KJob::Killable | KJob::Suspendable); 0029 } 0030 0031 Job::Job(JobPrivate &dd) 0032 : KCompositeJob(nullptr) 0033 , d_ptr(&dd) 0034 { 0035 d_ptr->q_ptr = this; 0036 setCapabilities(KJob::Killable | KJob::Suspendable); 0037 } 0038 0039 Job::~Job() 0040 { 0041 delete d_ptr; 0042 } 0043 0044 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 0) 0045 KJobUiDelegate *Job::ui() const 0046 { 0047 return uiDelegate(); 0048 } 0049 #endif 0050 0051 JobUiDelegateExtension *Job::uiDelegateExtension() const 0052 { 0053 Q_D(const Job); 0054 return d->m_uiDelegateExtension; 0055 } 0056 0057 void Job::setUiDelegateExtension(JobUiDelegateExtension *extension) 0058 { 0059 Q_D(Job); 0060 d->m_uiDelegateExtension = extension; 0061 } 0062 0063 bool Job::addSubjob(KJob *jobBase) 0064 { 0065 // qDebug() << "addSubjob(" << jobBase << ") this=" << this; 0066 0067 bool ok = KCompositeJob::addSubjob(jobBase); 0068 KIO::Job *job = qobject_cast<KIO::Job *>(jobBase); 0069 if (ok && job) { 0070 // Copy metadata into subjob (e.g. window-id, user-timestamp etc.) 0071 Q_D(Job); 0072 job->mergeMetaData(d->m_outgoingMetaData); 0073 0074 // Forward information from that subjob. 0075 connect(job, &KJob::speed, this, [this](KJob *job, ulong speed) { 0076 Q_UNUSED(job); 0077 emitSpeed(speed); 0078 }); 0079 job->setProperty("widget", property("widget")); // see KJobWidgets 0080 job->setProperty("window", property("window")); // see KJobWidgets 0081 job->setProperty("userTimestamp", property("userTimestamp")); // see KJobWidgets 0082 job->setUiDelegateExtension(d->m_uiDelegateExtension); 0083 } 0084 return ok; 0085 } 0086 0087 bool Job::removeSubjob(KJob *jobBase) 0088 { 0089 // qDebug() << "removeSubjob(" << jobBase << ") this=" << this << "subjobs=" << subjobs().count(); 0090 return KCompositeJob::removeSubjob(jobBase); 0091 } 0092 0093 static QString url_description_string(const QUrl &url) 0094 { 0095 return url.scheme() == QLatin1String("data") ? QStringLiteral("data:[...]") : KStringHandler::csqueeze(url.toDisplayString(QUrl::PreferLocalFile), 100); 0096 } 0097 0098 KIO::JobPrivate::~JobPrivate() 0099 { 0100 } 0101 0102 void JobPrivate::emitMoving(KIO::Job *job, const QUrl &src, const QUrl &dest) 0103 { 0104 static const QString s_title = i18nc("@title job", "Moving"); 0105 static const QString s_source = i18nc("The source of a file operation", "Source"); 0106 static const QString s_destination = i18nc("The destination of a file operation", "Destination"); 0107 Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(src)), qMakePair(s_destination, url_description_string(dest))); 0108 } 0109 0110 void JobPrivate::emitRenaming(KIO::Job *job, const QUrl &src, const QUrl &dest) 0111 { 0112 static const QString s_title = i18nc("@title job", "Renaming"); 0113 static const QString s_source = i18nc("The source of a file operation", "Source"); 0114 static const QString s_destination = i18nc("The destination of a file operation", "Destination"); 0115 Q_EMIT job->description(job, s_title, {s_source, url_description_string(src)}, {s_destination, url_description_string(dest)}); 0116 } 0117 0118 void JobPrivate::emitCopying(KIO::Job *job, const QUrl &src, const QUrl &dest) 0119 { 0120 static const QString s_title = i18nc("@title job", "Copying"); 0121 static const QString s_source = i18nc("The source of a file operation", "Source"); 0122 static const QString s_destination = i18nc("The destination of a file operation", "Destination"); 0123 Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(src)), qMakePair(s_destination, url_description_string(dest))); 0124 } 0125 0126 void JobPrivate::emitCreatingDir(KIO::Job *job, const QUrl &dir) 0127 { 0128 static const QString s_title = i18nc("@title job", "Creating directory"); 0129 static const QString s_directory = i18n("Directory"); 0130 Q_EMIT job->description(job, s_title, qMakePair(s_directory, url_description_string(dir))); 0131 } 0132 0133 void JobPrivate::emitDeleting(KIO::Job *job, const QUrl &url) 0134 { 0135 static const QString s_title = i18nc("@title job", "Deleting"); 0136 static const QString s_file = i18n("File"); 0137 Q_EMIT job->description(job, s_title, qMakePair(s_file, url_description_string(url))); 0138 } 0139 0140 void JobPrivate::emitStating(KIO::Job *job, const QUrl &url) 0141 { 0142 static const QString s_title = i18nc("@title job", "Examining"); 0143 static const QString s_file = i18n("File"); 0144 Q_EMIT job->description(job, s_title, qMakePair(s_file, url_description_string(url))); 0145 } 0146 0147 void JobPrivate::emitTransferring(KIO::Job *job, const QUrl &url) 0148 { 0149 static const QString s_title = i18nc("@title job", "Transferring"); 0150 static const QString s_source = i18nc("The source of a file operation", "Source"); 0151 Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(url))); 0152 } 0153 0154 void JobPrivate::emitMounting(KIO::Job *job, const QString &dev, const QString &point) 0155 { 0156 Q_EMIT job->description(job, i18nc("@title job", "Mounting"), qMakePair(i18n("Device"), dev), qMakePair(i18n("Mountpoint"), point)); 0157 } 0158 0159 void JobPrivate::emitUnmounting(KIO::Job *job, const QString &point) 0160 { 0161 Q_EMIT job->description(job, i18nc("@title job", "Unmounting"), qMakePair(i18n("Mountpoint"), point)); 0162 } 0163 0164 bool Job::doKill() 0165 { 0166 // kill all subjobs, without triggering their result slot 0167 for (KJob *job : subjobs()) { 0168 job->kill(KJob::Quietly); 0169 } 0170 clearSubjobs(); 0171 0172 return true; 0173 } 0174 0175 bool Job::doSuspend() 0176 { 0177 for (KJob *job : subjobs()) { 0178 if (!job->suspend()) { 0179 return false; 0180 } 0181 } 0182 0183 return true; 0184 } 0185 0186 bool Job::doResume() 0187 { 0188 for (KJob *job : subjobs()) { 0189 if (!job->resume()) { 0190 return false; 0191 } 0192 } 0193 0194 return true; 0195 } 0196 0197 // Job::errorString is implemented in job_error.cpp 0198 0199 void Job::setParentJob(Job *job) 0200 { 0201 Q_D(Job); 0202 Q_ASSERT(d->m_parentJob == nullptr); 0203 Q_ASSERT(job); 0204 d->m_parentJob = job; 0205 } 0206 0207 Job *Job::parentJob() const 0208 { 0209 return d_func()->m_parentJob; 0210 } 0211 0212 MetaData Job::metaData() const 0213 { 0214 return d_func()->m_incomingMetaData; 0215 } 0216 0217 QString Job::queryMetaData(const QString &key) 0218 { 0219 return d_func()->m_incomingMetaData.value(key, QString()); 0220 } 0221 0222 void Job::setMetaData(const KIO::MetaData &_metaData) 0223 { 0224 Q_D(Job); 0225 d->m_outgoingMetaData = _metaData; 0226 } 0227 0228 void Job::addMetaData(const QString &key, const QString &value) 0229 { 0230 d_func()->m_outgoingMetaData.insert(key, value); 0231 } 0232 0233 void Job::addMetaData(const QMap<QString, QString> &values) 0234 { 0235 Q_D(Job); 0236 for (auto it = values.cbegin(); it != values.cend(); ++it) { 0237 d->m_outgoingMetaData.insert(it.key(), it.value()); 0238 } 0239 } 0240 0241 void Job::mergeMetaData(const QMap<QString, QString> &values) 0242 { 0243 Q_D(Job); 0244 for (auto it = values.cbegin(); it != values.cend(); ++it) { 0245 // there's probably a faster way 0246 if (!d->m_outgoingMetaData.contains(it.key())) { 0247 d->m_outgoingMetaData.insert(it.key(), it.value()); 0248 } 0249 } 0250 } 0251 0252 MetaData Job::outgoingMetaData() const 0253 { 0254 return d_func()->m_outgoingMetaData; 0255 } 0256 0257 QByteArray JobPrivate::privilegeOperationData() 0258 { 0259 PrivilegeOperationStatus status = OperationNotAllowed; 0260 0261 if (m_parentJob) { 0262 QByteArray jobData = m_parentJob->d_func()->privilegeOperationData(); 0263 // Copy meta-data from parent job 0264 m_incomingMetaData.insert(QStringLiteral("TestData"), m_parentJob->queryMetaData(QStringLiteral("TestData"))); 0265 return jobData; 0266 } else { 0267 if (m_privilegeExecutionEnabled) { 0268 status = OperationAllowed; 0269 switch (m_operationType) { 0270 case ChangeAttr: 0271 m_title = i18n("Change Attribute"); 0272 m_message = i18n( 0273 "Root privileges are required to change file attributes. " 0274 "Do you want to continue?"); 0275 break; 0276 case Copy: 0277 m_title = i18n("Copy Files"); 0278 m_message = i18n( 0279 "Root privileges are required to complete the copy operation. " 0280 "Do you want to continue?"); 0281 break; 0282 case Delete: 0283 m_title = i18n("Delete Files"); 0284 m_message = i18n( 0285 "Root privileges are required to complete the delete operation. " 0286 "However, doing so may damage your system. Do you want to continue?"); 0287 break; 0288 case MkDir: 0289 m_title = i18n("Create Folder"); 0290 m_message = i18n( 0291 "Root privileges are required to create this folder. " 0292 "Do you want to continue?"); 0293 break; 0294 case Move: 0295 m_title = i18n("Move Items"); 0296 m_message = i18n( 0297 "Root privileges are required to complete the move operation. " 0298 "Do you want to continue?"); 0299 break; 0300 case Rename: 0301 m_title = i18n("Rename"); 0302 m_message = i18n( 0303 "Root privileges are required to complete renaming. " 0304 "Do you want to continue?"); 0305 break; 0306 case Symlink: 0307 m_title = i18n("Create Symlink"); 0308 m_message = i18n( 0309 "Root privileges are required to create a symlink. " 0310 "Do you want to continue?"); 0311 break; 0312 case Transfer: 0313 m_title = i18n("Transfer data"); 0314 m_message = i18n( 0315 "Root privileges are required to complete transferring data. " 0316 "Do you want to continue?"); 0317 Q_FALLTHROUGH(); 0318 default: 0319 break; 0320 } 0321 0322 if (m_outgoingMetaData.value(QStringLiteral("UnitTesting")) == QLatin1String("true")) { 0323 // Set meta-data for the top-level job 0324 m_incomingMetaData.insert(QStringLiteral("TestData"), QStringLiteral("PrivilegeOperationAllowed")); 0325 } 0326 } 0327 } 0328 0329 QByteArray parentJobData; 0330 QDataStream ds(&parentJobData, QIODevice::WriteOnly); 0331 ds << status << m_title << m_message; 0332 return parentJobData; 0333 } 0334 0335 ////////////////////////// 0336 0337 class KIO::DirectCopyJobPrivate : public KIO::SimpleJobPrivate 0338 { 0339 public: 0340 DirectCopyJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs) 0341 : SimpleJobPrivate(url, command, packedArgs) 0342 { 0343 } 0344 0345 /** 0346 * @internal 0347 * Called by the scheduler when a @p slave gets to 0348 * work on this job. 0349 * @param slave the slave that starts working on this job 0350 */ 0351 void start(Slave *slave) override; 0352 0353 Q_DECLARE_PUBLIC(DirectCopyJob) 0354 }; 0355 0356 DirectCopyJob::DirectCopyJob(const QUrl &url, const QByteArray &packedArgs) 0357 : SimpleJob(*new DirectCopyJobPrivate(url, CMD_COPY, packedArgs)) 0358 { 0359 setUiDelegate(KIO::createDefaultJobUiDelegate()); 0360 } 0361 0362 DirectCopyJob::~DirectCopyJob() 0363 { 0364 } 0365 0366 void DirectCopyJobPrivate::start(Slave *slave) 0367 { 0368 Q_Q(DirectCopyJob); 0369 q->connect(slave, &SlaveInterface::canResume, q, &DirectCopyJob::slotCanResume); 0370 SimpleJobPrivate::start(slave); 0371 } 0372 0373 void DirectCopyJob::slotCanResume(KIO::filesize_t offset) 0374 { 0375 Q_EMIT canResume(this, offset); 0376 } 0377 0378 ////////////////////////// 0379 0380 SimpleJob *KIO::file_delete(const QUrl &src, JobFlags flags) 0381 { 0382 KIO_ARGS << src << qint8(true); // isFile 0383 SimpleJob *job = SimpleJobPrivate::newJob(src, CMD_DEL, packedArgs, flags); 0384 if (job->uiDelegateExtension()) { 0385 job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::RemoveContent); 0386 } 0387 return job; 0388 } 0389 0390 ////////// 0391 //// 0392 0393 #include "moc_job_base.cpp" 0394 #include "moc_job_p.cpp"