File indexing completed on 2024-03-24 03:58:03
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 "worker_p.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 worker gets to 0040 * work on this job. 0041 * @param worker the worker that starts working on this job 0042 */ 0043 void start(Worker *worker) 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 void StatJob::setSide(StatSide side) 0071 { 0072 d_func()->m_bSource = side == SourceSide; 0073 } 0074 0075 void StatJob::setDetails(KIO::StatDetails details) 0076 { 0077 d_func()->m_details = details; 0078 } 0079 0080 const UDSEntry &StatJob::statResult() const 0081 { 0082 return d_func()->m_statResult; 0083 } 0084 0085 QUrl StatJob::mostLocalUrl() const 0086 { 0087 const QUrl _url = url(); 0088 0089 if (_url.isLocalFile()) { 0090 return _url; 0091 } 0092 0093 const UDSEntry &udsEntry = d_func()->m_statResult; 0094 const QString path = udsEntry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH); 0095 0096 if (path.isEmpty()) { // Return url as-is 0097 return _url; 0098 } 0099 0100 const QString protoClass = KProtocolInfo::protocolClass(_url.scheme()); 0101 if (protoClass != QLatin1String(":local")) { // UDS_LOCAL_PATH was set but wrong Class 0102 qCWarning(KIO_CORE) << "The protocol Class of the url that was being stat'ed" << _url << ", is" << protoClass 0103 << ", however UDS_LOCAL_PATH was set; if you use UDS_LOCAL_PATH, the protocolClass" 0104 " should be :local, see KProtocolInfo API docs for more details."; 0105 return _url; 0106 } 0107 0108 return QUrl::fromLocalFile(path); 0109 } 0110 0111 void StatJobPrivate::start(Worker *worker) 0112 { 0113 Q_Q(StatJob); 0114 m_outgoingMetaData.insert(QStringLiteral("statSide"), m_bSource ? QStringLiteral("source") : QStringLiteral("dest")); 0115 m_outgoingMetaData.insert(QStringLiteral("details"), QString::number(m_details)); 0116 0117 q->connect(worker, &KIO::WorkerInterface::statEntry, q, [this](const KIO::UDSEntry &entry) { 0118 slotStatEntry(entry); 0119 }); 0120 q->connect(worker, &KIO::WorkerInterface::redirection, q, [this](const QUrl &url) { 0121 slotRedirection(url); 0122 }); 0123 0124 SimpleJobPrivate::start(worker); 0125 } 0126 0127 void StatJobPrivate::slotStatEntry(const KIO::UDSEntry &entry) 0128 { 0129 // qCDebug(KIO_CORE); 0130 m_statResult = entry; 0131 } 0132 0133 // Worker got a redirection request 0134 void StatJobPrivate::slotRedirection(const QUrl &url) 0135 { 0136 Q_Q(StatJob); 0137 // qCDebug(KIO_CORE) << m_url << "->" << url; 0138 if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("redirect"), m_url, url)) { 0139 qCWarning(KIO_CORE) << "Redirection from" << m_url << "to" << url << "REJECTED!"; 0140 q->setError(ERR_ACCESS_DENIED); 0141 q->setErrorText(url.toDisplayString()); 0142 return; 0143 } 0144 m_redirectionURL = url; // We'll remember that when the job finishes 0145 // Tell the user that we haven't finished yet 0146 Q_EMIT q->redirection(q, m_redirectionURL); 0147 } 0148 0149 void StatJob::slotFinished() 0150 { 0151 Q_D(StatJob); 0152 0153 if (!d->m_redirectionURL.isEmpty() && d->m_redirectionURL.isValid()) { 0154 // qCDebug(KIO_CORE) << "StatJob: Redirection to " << m_redirectionURL; 0155 if (queryMetaData(QStringLiteral("permanent-redirect")) == QLatin1String("true")) { 0156 Q_EMIT permanentRedirection(this, d->m_url, d->m_redirectionURL); 0157 } 0158 0159 if (d->m_redirectionHandlingEnabled) { 0160 d->m_packedArgs.truncate(0); 0161 QDataStream stream(&d->m_packedArgs, QIODevice::WriteOnly); 0162 stream << d->m_redirectionURL; 0163 0164 d->restartAfterRedirection(&d->m_redirectionURL); 0165 return; 0166 } 0167 } 0168 0169 // Return worker to the scheduler 0170 SimpleJob::slotFinished(); 0171 } 0172 0173 static bool isUrlValid(const QUrl &url) 0174 { 0175 if (!url.isValid()) { 0176 qCWarning(KIO_CORE) << "Invalid url:" << url << ", cancelling job."; 0177 return false; 0178 } 0179 0180 if (url.isLocalFile()) { 0181 qCWarning(KIO_CORE) << "Url" << url << "already represents a local file, cancelling job."; 0182 return false; 0183 } 0184 0185 if (KProtocolInfo::protocolClass(url.scheme()) != QLatin1String(":local")) { 0186 qCWarning(KIO_CORE) << "Protocol Class of url" << url << ", isn't ':local', cancelling job."; 0187 return false; 0188 } 0189 0190 return true; 0191 } 0192 0193 StatJob *KIO::mostLocalUrl(const QUrl &url, JobFlags flags) 0194 { 0195 StatJob *job = stat(url, StatJob::SourceSide, KIO::StatDefaultDetails, flags); 0196 if (!isUrlValid(url)) { 0197 QTimer::singleShot(0, job, &StatJob::slotFinished); 0198 Scheduler::cancelJob(job); // deletes the worker if not 0 0199 } 0200 return job; 0201 } 0202 0203 StatJob *KIO::stat(const QUrl &url, JobFlags flags) 0204 { 0205 // Assume SourceSide. Gets are more common than puts. 0206 return stat(url, StatJob::SourceSide, KIO::StatDefaultDetails, flags); 0207 } 0208 0209 StatJob *KIO::stat(const QUrl &url, KIO::StatJob::StatSide side, KIO::StatDetails details, JobFlags flags) 0210 { 0211 // qCDebug(KIO_CORE) << "stat" << url; 0212 KIO_ARGS << url; 0213 StatJob *job = StatJobPrivate::newJob(url, CMD_STAT, packedArgs, flags); 0214 job->setSide(side); 0215 job->setDetails(details); 0216 return job; 0217 } 0218 0219 #include "moc_statjob.cpp"