File indexing completed on 2023-09-24 04:08:44
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 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "statjob.h" 0010 0011 #include "job_p.h" 0012 #include "scheduler.h" 0013 #include "slave.h" 0014 #include <KProtocolInfo> 0015 #include <QTimer> 0016 #include <kurlauthorized.h> 0017 0018 using namespace KIO; 0019 0020 class KIO::StatJobPrivate : public SimpleJobPrivate 0021 { 0022 public: 0023 inline StatJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs) 0024 : SimpleJobPrivate(url, command, packedArgs) 0025 , m_bSource(true) 0026 , m_details(KIO::StatDefaultDetails) 0027 { 0028 } 0029 0030 UDSEntry m_statResult; 0031 QUrl m_redirectionURL; 0032 bool m_bSource; 0033 KIO::StatDetails m_details; 0034 void slotStatEntry(const KIO::UDSEntry &entry); 0035 void slotRedirection(const QUrl &url); 0036 0037 /** 0038 * @internal 0039 * Called by the scheduler when a @p slave gets to 0040 * work on this job. 0041 * @param slave the slave that starts working on this job 0042 */ 0043 void start(Slave *slave) override; 0044 0045 Q_DECLARE_PUBLIC(StatJob) 0046 0047 static inline StatJob *newJob(const QUrl &url, int command, const QByteArray &packedArgs, JobFlags flags) 0048 { 0049 StatJob *job = new StatJob(*new StatJobPrivate(url, command, packedArgs)); 0050 job->setUiDelegate(KIO::createDefaultJobUiDelegate()); 0051 if (!(flags & HideProgressInfo)) { 0052 job->setFinishedNotificationHidden(); 0053 KIO::getJobTracker()->registerJob(job); 0054 emitStating(job, url); 0055 } 0056 return job; 0057 } 0058 }; 0059 0060 StatJob::StatJob(StatJobPrivate &dd) 0061 : SimpleJob(dd) 0062 { 0063 setTotalAmount(Items, 1); 0064 } 0065 0066 StatJob::~StatJob() 0067 { 0068 } 0069 0070 #if KIOCORE_BUILD_DEPRECATED_SINCE(4, 0) 0071 void StatJob::setSide(bool source) 0072 { 0073 d_func()->m_bSource = source; 0074 } 0075 #endif 0076 0077 void StatJob::setSide(StatSide side) 0078 { 0079 d_func()->m_bSource = side == SourceSide; 0080 } 0081 0082 void StatJob::setDetails(KIO::StatDetails details) 0083 { 0084 d_func()->m_details = details; 0085 } 0086 0087 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 69) 0088 void StatJob::setDetails(short int details) 0089 { 0090 // for backward compatibility 0091 d_func()->m_details = detailsToStatDetails(details); 0092 } 0093 0094 void StatJob::setDetails(KIO::StatDetail detail) 0095 { 0096 d_func()->m_details = detail; 0097 } 0098 0099 KIO::StatDetails KIO::detailsToStatDetails(int details) 0100 { 0101 KIO::StatDetails detailsFlag = KIO::StatBasic; 0102 if (details > 0) { 0103 detailsFlag |= KIO::StatUser | KIO::StatTime; 0104 } 0105 if (details > 1) { 0106 detailsFlag |= KIO::StatResolveSymlink | KIO::StatAcl; 0107 } 0108 if (details > 2) { 0109 detailsFlag |= KIO::StatInode; 0110 } 0111 return detailsFlag; 0112 } 0113 #endif 0114 0115 const UDSEntry &StatJob::statResult() const 0116 { 0117 return d_func()->m_statResult; 0118 } 0119 0120 QUrl StatJob::mostLocalUrl() const 0121 { 0122 const QUrl _url = url(); 0123 0124 if (_url.isLocalFile()) { 0125 return _url; 0126 } 0127 0128 const UDSEntry &udsEntry = d_func()->m_statResult; 0129 const QString path = udsEntry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH); 0130 0131 if (path.isEmpty()) { // Return url as-is 0132 return _url; 0133 } 0134 0135 const QString protoClass = KProtocolInfo::protocolClass(_url.scheme()); 0136 if (protoClass != QLatin1String(":local")) { // UDS_LOCAL_PATH was set but wrong Class 0137 qCWarning(KIO_CORE) << "The protocol Class of the url that was being stat'ed" << _url << ", is" << protoClass 0138 << ", however UDS_LOCAL_PATH was set; if you use UDS_LOCAL_PATH, the protocolClass" 0139 " should be :local, see KProtocolInfo API docs for more details."; 0140 return _url; 0141 } 0142 0143 return QUrl::fromLocalFile(path); 0144 } 0145 0146 void StatJobPrivate::start(Slave *slave) 0147 { 0148 Q_Q(StatJob); 0149 m_outgoingMetaData.insert(QStringLiteral("statSide"), m_bSource ? QStringLiteral("source") : QStringLiteral("dest")); 0150 m_outgoingMetaData.insert(QStringLiteral("statDetails"), QString::number(m_details)); 0151 0152 q->connect(slave, &KIO::SlaveInterface::statEntry, q, [this](const KIO::UDSEntry &entry) { 0153 slotStatEntry(entry); 0154 }); 0155 q->connect(slave, &KIO::SlaveInterface::redirection, q, [this](const QUrl &url) { 0156 slotRedirection(url); 0157 }); 0158 0159 SimpleJobPrivate::start(slave); 0160 } 0161 0162 void StatJobPrivate::slotStatEntry(const KIO::UDSEntry &entry) 0163 { 0164 // qCDebug(KIO_CORE); 0165 m_statResult = entry; 0166 } 0167 0168 // Worker got a redirection request 0169 void StatJobPrivate::slotRedirection(const QUrl &url) 0170 { 0171 Q_Q(StatJob); 0172 // qCDebug(KIO_CORE) << m_url << "->" << url; 0173 if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("redirect"), m_url, url)) { 0174 qCWarning(KIO_CORE) << "Redirection from" << m_url << "to" << url << "REJECTED!"; 0175 q->setError(ERR_ACCESS_DENIED); 0176 q->setErrorText(url.toDisplayString()); 0177 return; 0178 } 0179 m_redirectionURL = url; // We'll remember that when the job finishes 0180 // Tell the user that we haven't finished yet 0181 Q_EMIT q->redirection(q, m_redirectionURL); 0182 } 0183 0184 void StatJob::slotFinished() 0185 { 0186 Q_D(StatJob); 0187 0188 if (!d->m_redirectionURL.isEmpty() && d->m_redirectionURL.isValid()) { 0189 // qCDebug(KIO_CORE) << "StatJob: Redirection to " << m_redirectionURL; 0190 if (queryMetaData(QStringLiteral("permanent-redirect")) == QLatin1String("true")) { 0191 Q_EMIT permanentRedirection(this, d->m_url, d->m_redirectionURL); 0192 } 0193 0194 if (d->m_redirectionHandlingEnabled) { 0195 d->m_packedArgs.truncate(0); 0196 QDataStream stream(&d->m_packedArgs, QIODevice::WriteOnly); 0197 stream << d->m_redirectionURL; 0198 0199 d->restartAfterRedirection(&d->m_redirectionURL); 0200 return; 0201 } 0202 } 0203 0204 // Return worker to the scheduler 0205 SimpleJob::slotFinished(); 0206 } 0207 0208 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101) 0209 void StatJob::slotMetaData(const KIO::MetaData &_metaData) 0210 { 0211 SimpleJob::slotMetaData(_metaData); 0212 } 0213 #endif 0214 0215 StatJob *KIO::stat(const QUrl &url, JobFlags flags) 0216 { 0217 // Assume sideIsSource. Gets are more common than puts. 0218 return statDetails(url, StatJob::SourceSide, KIO::StatDefaultDetails, flags); 0219 } 0220 0221 static bool isUrlValid(const QUrl &url) 0222 { 0223 if (!url.isValid()) { 0224 qCWarning(KIO_CORE) << "Invalid url:" << url << ", cancelling job."; 0225 return false; 0226 } 0227 0228 if (url.isLocalFile()) { 0229 qCWarning(KIO_CORE) << "Url" << url << "already represents a local file, cancelling job."; 0230 return false; 0231 } 0232 0233 if (KProtocolInfo::protocolClass(url.scheme()) != QLatin1String(":local")) { 0234 qCWarning(KIO_CORE) << "Protocol Class of url" << url << ", isn't ':local', cancelling job."; 0235 return false; 0236 } 0237 0238 return true; 0239 } 0240 0241 StatJob *KIO::mostLocalUrl(const QUrl &url, JobFlags flags) 0242 { 0243 StatJob *job = statDetails(url, StatJob::SourceSide, KIO::StatDefaultDetails, flags); 0244 if (!isUrlValid(url)) { 0245 QTimer::singleShot(0, job, &StatJob::slotFinished); 0246 Scheduler::cancelJob(job); // deletes the worker if not 0 0247 } 0248 return job; 0249 } 0250 0251 #if KIOCORE_BUILD_DEPRECATED_SINCE(4, 0) 0252 StatJob *KIO::stat(const QUrl &url, bool sideIsSource, short int details, JobFlags flags) 0253 { 0254 // qCDebug(KIO_CORE) << "stat" << url; 0255 KIO_ARGS << url; 0256 StatJob *job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags); 0257 job->setSide(sideIsSource ? StatJob::SourceSide : StatJob::DestinationSide); 0258 job->setDetails(details); 0259 return job; 0260 } 0261 #endif 0262 0263 StatJob *KIO::statDetails(const QUrl &url, KIO::StatJob::StatSide side, KIO::StatDetails details, JobFlags flags) 0264 { 0265 // TODO KF6: rename to stat 0266 // qCDebug(KIO_CORE) << "stat" << url; 0267 KIO_ARGS << url; 0268 StatJob *job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags); 0269 job->setSide(side); 0270 job->setDetails(details); 0271 return job; 0272 } 0273 0274 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 69) 0275 StatJob *KIO::stat(const QUrl &url, KIO::StatJob::StatSide side, short int details, JobFlags flags) 0276 { 0277 // qCDebug(KIO_CORE) << "stat" << url; 0278 KIO_ARGS << url; 0279 StatJob *job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags); 0280 job->setSide(side); 0281 job->setDetails(details); 0282 return job; 0283 } 0284 #endif 0285 0286 #include "moc_statjob.cpp"