Warning, file /network/ruqola/src/rocketchatrestapi-qt/uploadfilejob.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002    SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "uploadfilejob.h"
0008 #include "restapimethod.h"
0009 #include "rocketchatqtrestapi_debug.h"
0010 #include <KLocalizedString>
0011 #include <QFile>
0012 #include <QHttpMultiPart>
0013 #include <QJsonDocument>
0014 #include <QJsonObject>
0015 #include <QMimeDatabase>
0016 #include <QNetworkReply>
0017 
0018 using namespace RocketChatRestApi;
0019 
0020 UploadFileJob::UploadFileJob(QObject *parent)
0021     : RestApiAbstractJob(parent)
0022 {
0023 }
0024 
0025 UploadFileJob::~UploadFileJob() = default;
0026 
0027 bool UploadFileJob::canStart() const
0028 {
0029     if (!RestApiAbstractJob::canStart()) {
0030         return false;
0031     }
0032     if (mUploadFileInfo.roomId.isEmpty()) {
0033         qCWarning(ROCKETCHATQTRESTAPI_LOG) << "UploadFileJob : RoomId not defined";
0034         return false;
0035     }
0036     if (!mUploadFileInfo.filenameUrl.isLocalFile()) {
0037         // shouldn't be too hard, just use KIO::storedGet
0038         qCWarning(ROCKETCHATQTRESTAPI_LOG) << "Uploading remote files is not supported yet";
0039         return false;
0040     }
0041     return true;
0042 }
0043 
0044 bool UploadFileJob::start()
0045 {
0046     if (!canStart()) {
0047         deleteLater();
0048         return false;
0049     }
0050     const QString fileNameAsLocalFile = mUploadFileInfo.filenameUrl.toLocalFile();
0051     auto file = new QFile(fileNameAsLocalFile);
0052     if (!file->open(QIODevice::ReadOnly)) {
0053         qCWarning(ROCKETCHATQTRESTAPI_LOG) << " Impossible to open filename " << mUploadFileInfo.filenameUrl;
0054         Q_EMIT failed(i18n("File not found \'%1\'", fileNameAsLocalFile));
0055         delete file;
0056         deleteLater();
0057         return false;
0058     }
0059     QMimeDatabase db;
0060     const QMimeType mimeType = db.mimeTypeForFile(fileNameAsLocalFile);
0061 
0062     auto multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
0063 
0064     QHttpPart filePart;
0065     filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mimeType.name()));
0066     const QString filePartInfo = QStringLiteral("form-data; name=\"file\"; filename=\"%1\"")
0067                                      .arg(mUploadFileInfo.fileName.isEmpty() ? mUploadFileInfo.filenameUrl.fileName() : mUploadFileInfo.fileName);
0068     filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(filePartInfo));
0069 
0070     filePart.setBodyDevice(file);
0071     file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
0072     multiPart->append(filePart);
0073 
0074     QHttpPart msgPart;
0075     msgPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"msg\"")));
0076     msgPart.setBody(mUploadFileInfo.messageText.toUtf8());
0077     multiPart->append(msgPart);
0078 
0079     if (!mUploadFileInfo.threadMessageId.isEmpty()) {
0080         QHttpPart msgPart;
0081         msgPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"tmid\"")));
0082         msgPart.setBody(mUploadFileInfo.threadMessageId.toUtf8());
0083         multiPart->append(msgPart);
0084     }
0085 
0086     QHttpPart descriptionPart;
0087     descriptionPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"description\"")));
0088     descriptionPart.setBody(mUploadFileInfo.description.toUtf8());
0089     multiPart->append(descriptionPart);
0090     mReply = networkAccessManager()->post(request(), multiPart);
0091     connect(mReply, &QNetworkReply::uploadProgress, this, &UploadFileJob::slotUploadProgress);
0092     connect(mReply, &QNetworkReply::finished, this, &UploadFileJob::slotUploadFinished);
0093     multiPart->setParent(mReply); // delete the multiPart with the reply
0094     // TODO signal error ?
0095     addStartRestApiInfo("UploadFileJob::start");
0096     return true;
0097 }
0098 
0099 void UploadFileJob::slotUploadProgress(qint64 bytesSent, qint64 bytesTotal)
0100 {
0101     UploadFileJob::UploadStatusInfo info;
0102     info.bytesSent = bytesSent;
0103     info.bytesTotal = bytesTotal;
0104     info.fileName = mUploadFileInfo.filenameUrl.fileName();
0105     Q_EMIT uploadProgress(info);
0106 }
0107 
0108 QNetworkRequest UploadFileJob::request() const
0109 {
0110     const QUrl url = mRestApiMethod->generateUrl(RestApiUtil::RestApiUrlType::RoomsUpload, mUploadFileInfo.roomId);
0111     QNetworkRequest request(url);
0112     addAuthRawHeader(request);
0113     addRequestAttribute(request, false);
0114 
0115     return request;
0116 }
0117 
0118 void UploadFileJob::abort()
0119 {
0120     if (mReply) {
0121         mReply->abort();
0122     }
0123     deleteLater();
0124 }
0125 
0126 void UploadFileJob::slotUploadFinished()
0127 {
0128     auto reply = mReply;
0129     if (reply) {
0130         const QJsonDocument replyJson = convertToJsonDocument(reply);
0131         const QJsonObject replyObject = replyJson.object();
0132         if (replyObject.value(QLatin1String("success")).toBool()) {
0133             addLoggerInfo(QByteArrayLiteral("UploadFileJob: success: ") + replyJson.toJson(QJsonDocument::Indented));
0134         } else {
0135             if (reply->error() != QNetworkReply::NoError) {
0136                 if (mReply->error() == QNetworkReply::NetworkSessionFailedError) {
0137                     qCWarning(ROCKETCHATQTRESTAPI_LOG) << metaObject()->className() << "NetworkSessionFailedError. Connection loss?";
0138                     deleteLater();
0139                     return;
0140                 }
0141                 // TODO verify it !
0142                 Q_EMIT failed(mReply->errorString() + QLatin1Char('\n') + errorStr(replyObject));
0143             } else {
0144                 emitFailedMessage(reply->errorString(), replyObject);
0145                 addLoggerWarning(QByteArrayLiteral("UploadFileJob: Problem: ") + replyJson.toJson(QJsonDocument::Indented));
0146             }
0147         }
0148         reply->deleteLater();
0149     }
0150     Q_EMIT uploadFinished();
0151     deleteLater();
0152 }
0153 
0154 UploadFileJob::UploadFileInfo UploadFileJob::uploadFileInfo() const
0155 {
0156     return mUploadFileInfo;
0157 }
0158 
0159 void UploadFileJob::setUploadFileInfo(const UploadFileInfo &uploadFileInfo)
0160 {
0161     mUploadFileInfo = uploadFileInfo;
0162 }
0163 
0164 bool UploadFileJob::requireHttpAuthentication() const
0165 {
0166     return true;
0167 }
0168 
0169 bool UploadFileJob::UploadFileInfo::isValid() const
0170 {
0171     return !roomId.isEmpty() && !filenameUrl.isEmpty();
0172 }
0173 
0174 #include "moc_uploadfilejob.cpp"