9#include "transferjob.h"
13#include <kurlauthorized.h>
17static const int MAX_READ_BUF_SIZE = (64 * 1024);
19TransferJob::TransferJob(TransferJobPrivate &dd)
23 if (d->m_command == CMD_PUT) {
24 d->m_extraFlags |= JobPrivate::EF_TransferJobDataSent;
27 if (d->m_outgoingDataSource) {
29 d->slotIODeviceClosedBeforeStart();
34TransferJob::~TransferJob()
39void TransferJob::slotData(
const QByteArray &_data)
42 if (d->m_command == CMD_GET && !d->m_isMimetypeEmitted) {
43 qCWarning(KIO_CORE) <<
"mimeType() not emitted when sending first data!; job URL =" << d->m_url <<
"data size =" << _data.
size();
46 d->m_isMimetypeEmitted =
true;
48 if (d->m_redirectionURL.isEmpty() || !d->m_redirectionURL.isValid() ||
error()) {
59void TransferJob::slotRedirection(
const QUrl &url)
64 qCWarning(KIO_CORE) <<
"Redirection from" << d->m_url <<
"to" <<
url <<
"REJECTED!";
71 if (d->m_redirectionList.count(
url) > 5) {
76 d->m_redirectionURL =
url;
77 d->m_redirectionList.append(
url);
80 addMetaData(QStringLiteral(
"ssl_was_in_use"), sslInUse);
82 addMetaData(QStringLiteral(
"ssl_was_in_use"), QStringLiteral(
"FALSE"));
89void TransferJob::slotFinished()
94 if (!d->m_redirectionURL.isEmpty() && d->m_redirectionURL.isValid()) {
101 d->m_command = CMD_GET;
102 d->m_outgoingMetaData.remove(QStringLiteral(
"content-type"));
105 if (d->m_redirectionHandlingEnabled) {
110 d->staticData.truncate(0);
111 d->m_incomingMetaData.clear();
113 addMetaData(QStringLiteral(
"cache"), QStringLiteral(
"refresh"));
115 d->m_internalSuspended =
false;
119 switch (d->m_command) {
123 d->m_packedArgs.truncate(0);
125 stream << d->m_redirectionURL;
132 istream >> dummyUrl >> iOverwrite >> iResume >> permissions;
133 d->m_packedArgs.truncate(0);
135 stream << d->m_redirectionURL << iOverwrite << iResume << permissions;
140 istream >> specialcmd;
141 if (specialcmd == 1) {
142 d->m_outgoingMetaData.remove(QStringLiteral(
"content-type"));
143 addMetaData(QStringLiteral(
"cache"), QStringLiteral(
"reload"));
144 d->m_packedArgs.truncate(0);
146 stream << d->m_redirectionURL;
147 d->m_command = CMD_GET;
152 d->restartAfterRedirection(&d->m_redirectionURL);
164 d->m_extraFlags |= JobPrivate::EF_TransferJobAsync;
166 d->m_extraFlags &= ~JobPrivate::EF_TransferJobAsync;
173 if (d->m_extraFlags & JobPrivate::EF_TransferJobNeedData) {
175 d->m_worker->send(MSG_DATA, dataForWorker);
177 if (d->m_extraFlags & JobPrivate::EF_TransferJobDataSent) {
183 d->m_extraFlags &= ~JobPrivate::EF_TransferJobNeedData;
188 return d_func()->m_mimetype;
193 return d_func()->m_redirectionURL;
197void TransferJob::slotDataReq()
202 d->m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
204 if (!d->staticData.isEmpty()) {
205 dataForWorker = d->staticData;
206 d->staticData.
clear();
210 if (d->m_extraFlags & JobPrivate::EF_TransferJobAsync) {
215 static const int max_size = 14 * 1024 * 1024;
216 if (dataForWorker.
size() > max_size) {
219 d->staticData =
QByteArray(dataForWorker.
data() + max_size, dataForWorker.
size() - max_size);
226void TransferJob::slotMimetype(
const QString &type)
229 d->m_mimetype =
type;
230 if (d->m_command == CMD_GET && d->m_isMimetypeEmitted) {
231 qCWarning(KIO_CORE) <<
"mimetype() emitted again, or after sending first data!; job URL =" << d->m_url;
233 d->m_isMimetypeEmitted =
true;
237void TransferJobPrivate::internalSuspend()
239 m_internalSuspended =
true;
245void TransferJobPrivate::internalResume()
247 m_internalSuspended =
false;
248 if (m_worker && !q_func()->isSuspended()) {
259 if (d->m_internalSuspended) {
260 d->internalSuspend();
265#if KIOCORE_ENABLE_DEPRECATED_SINCE(6, 3)
272void TransferJobPrivate::start(Worker *worker)
276 JobPrivate::emitTransferring(q, m_url);
277 q->connect(worker, &WorkerInterface::data, q, &TransferJob::slotData);
279 if (m_outgoingDataSource) {
280 if (m_extraFlags & JobPrivate::EF_TransferJobAsync) {
281 auto dataReqFunc = [
this]() {
282 slotDataReqFromDevice();
285 auto ioClosedFunc = [
this]() {
286 slotIODeviceClosed();
292 if (m_closedBeforeStart) {
294 }
else if (m_outgoingDataSource->bytesAvailable() > 0) {
298 q->connect(worker, &WorkerInterface::dataReq, q, [
this]() {
299 slotDataReqFromDevice();
303 q->connect(worker, &WorkerInterface::dataReq, q, &TransferJob::slotDataReq);
306 q->connect(worker, &WorkerInterface::redirection, q, &TransferJob::slotRedirection);
308 q->connect(worker, &WorkerInterface::mimeType, q, &TransferJob::slotMimetype);
310 q->connect(worker, &WorkerInterface::canResume, q, [q](
KIO::filesize_t offset) {
311 Q_EMIT q->canResume(q, offset);
314 if (worker->suspended()) {
315 m_mimetype = QStringLiteral(
"unknown");
320 SimpleJobPrivate::start(worker);
321 if (m_internalSuspended) {
326void TransferJobPrivate::slotDataReqFromDevice()
333 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
335 if (m_outgoingDataSource) {
336 dataForWorker.
resize(MAX_READ_BUF_SIZE);
339 qint64 bytesRead = m_outgoingDataSource->read(dataForWorker.
data(), MAX_READ_BUF_SIZE);
340 if (bytesRead >= 0) {
341 dataForWorker.
resize(bytesRead);
343 dataForWorker.
clear();
345 done = ((bytesRead == -1) || (bytesRead == 0 && m_outgoingDataSource->atEnd() && !m_outgoingDataSource->isSequential()));
349 Q_EMIT q->dataReq(q, dataForWorker);
350 if (!done && (m_extraFlags & JobPrivate::EF_TransferJobAsync)) {
355 q->sendAsyncData(dataForWorker);
358void TransferJobPrivate::slotIODeviceClosedBeforeStart()
360 m_closedBeforeStart =
true;
363void TransferJobPrivate::slotIODeviceClosed()
366 const QByteArray remainder = m_outgoingDataSource->readAll();
368 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
369 q->sendAsyncData(remainder);
372 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
388 if (reload == Reload) {
389 job->
addMetaData(QStringLiteral(
"cache"), QStringLiteral(
"reload"));
394#include "moc_transferjob.cpp"
QString queryMetaData(const QString &key)
Query meta data received from the worker.
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the worker.
A simple job (one url and one command).
virtual void slotFinished()
Called when the worker marks the job as finished.
bool doResume() override
Resume this job.
const QUrl & url() const
Returns the SimpleJob's URL.
The transfer job pumps data into and/or out of a KIO worker.
void mimeTypeFound(KIO::Job *job, const QString &mimeType)
MIME type determined.
void dataReq(KIO::Job *job, QByteArray &data)
Request for data.
bool doResume() override
Reimplemented for internal reasons.
void redirection(KIO::Job *job, const QUrl &url)
Signals a redirection.
void permanentRedirection(KIO::Job *job, const QUrl &fromUrl, const QUrl &toUrl)
Signals a permanent redirection.
void sendAsyncData(const QByteArray &data)
Provide data to the job when async data is enabled.
QUrl redirectUrl() const
After the job has finished, it will return the final url in case a redirection has happened.
QString mimetype() const
Call this in the slot connected to result, and only after making sure no error happened.
void data(KIO::Job *job, const QByteArray &data)
Data from the worker has arrived.
bool isErrorPage() const
Checks whether we got an error page.
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file to be created (by KIO::put) Note that some KIO workers might i...
void setTotalSize(KIO::filesize_t bytes)
Set the total size of data that we are going to send in a put job.
void setAsyncDataEnabled(bool enabled)
Enable the async data mode.
void setErrorText(const QString &errorText)
Q_SCRIPTABLE qulonglong processedAmount(Unit unit) const
void setError(int errorCode)
void setProcessedAmount(Unit unit, qulonglong amount)
Type type(const QSqlDatabase &db)
A namespace for KIO globals.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (means: read).
qulonglong filesize_t
64-bit file size
bool authorizeUrlAction(const QString &action, const QUrl &baseURL, const QUrl &destURL)
Returns whether a certain URL related action is authorized.
bool isEmpty() const const
void resize(qsizetype newSize, char c)
qsizetype size() const const
void truncate(qsizetype pos)
QString toString(QStringView format, QCalendar cal) const const
void readChannelFinished()
bool disconnect(const QMetaObject::Connection &connection)
bool isNull() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)