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)
277 q->startElapsedTimer();
278 JobPrivate::emitTransferring(q, m_url);
279 q->connect(worker, &WorkerInterface::data, q, &TransferJob::slotData);
281 if (m_outgoingDataSource) {
282 if (m_extraFlags & JobPrivate::EF_TransferJobAsync) {
283 auto dataReqFunc = [
this]() {
284 slotDataReqFromDevice();
287 auto ioClosedFunc = [
this]() {
288 slotIODeviceClosed();
294 if (m_closedBeforeStart) {
296 }
else if (m_outgoingDataSource->bytesAvailable() > 0) {
300 q->connect(worker, &WorkerInterface::dataReq, q, [
this]() {
301 slotDataReqFromDevice();
305 q->connect(worker, &WorkerInterface::dataReq, q, &TransferJob::slotDataReq);
308 q->connect(worker, &WorkerInterface::redirection, q, &TransferJob::slotRedirection);
310 q->connect(worker, &WorkerInterface::mimeType, q, &TransferJob::slotMimetype);
312 q->connect(worker, &WorkerInterface::canResume, q, [q](
KIO::filesize_t offset) {
313 Q_EMIT q->canResume(q, offset);
316 if (worker->suspended()) {
317 m_mimetype = QStringLiteral(
"unknown");
322 SimpleJobPrivate::start(worker);
323 if (m_internalSuspended) {
328void TransferJobPrivate::slotDataReqFromDevice()
335 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
337 if (m_outgoingDataSource) {
338 dataForWorker.
resize(MAX_READ_BUF_SIZE);
341 qint64 bytesRead = m_outgoingDataSource->read(dataForWorker.
data(), MAX_READ_BUF_SIZE);
342 if (bytesRead >= 0) {
343 dataForWorker.
resize(bytesRead);
345 dataForWorker.
clear();
347 done = ((bytesRead == -1) || (bytesRead == 0 && m_outgoingDataSource->atEnd() && !m_outgoingDataSource->isSequential()));
351 Q_EMIT q->dataReq(q, dataForWorker);
352 if (!done && (m_extraFlags & JobPrivate::EF_TransferJobAsync)) {
357 q->sendAsyncData(dataForWorker);
360void TransferJobPrivate::slotIODeviceClosedBeforeStart()
362 m_closedBeforeStart =
true;
365void TransferJobPrivate::slotIODeviceClosed()
368 const QByteArray remainder = m_outgoingDataSource->readAll();
370 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
371 q->sendAsyncData(remainder);
374 m_extraFlags |= JobPrivate::EF_TransferJobNeedData;
390 if (reload == Reload) {
391 job->
addMetaData(QStringLiteral(
"cache"), QStringLiteral(
"reload"));
396#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)