File indexing completed on 2024-12-22 04:57:55

0001 /*
0002     SPDX-FileCopyrightText: 2016 Stefan Stäglich <sstaeglich@kdemail.net>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "tomboyitemuploadjob.h"
0008 #include "debug.h"
0009 #include <KLocalizedString>
0010 #include <QJsonArray>
0011 #include <QJsonDocument>
0012 #include <QJsonObject>
0013 #include <QUuid>
0014 
0015 TomboyItemUploadJob::TomboyItemUploadJob(const Akonadi::Item &item, JobType jobType, QNetworkAccessManager *manager, QObject *parent)
0016     : TomboyJobBase(manager, parent)
0017     , mSourceItem(item)
0018     , mJobType(jobType)
0019 {
0020     mSourceItem = Akonadi::Item(item);
0021     if (item.hasPayload<KMime::Message::Ptr>()) {
0022         mNoteContent = item.payload<KMime::Message::Ptr>();
0023     }
0024 
0025     mRemoteRevision = item.parentCollection().remoteRevision().toInt();
0026 
0027     // Create random remote id if adding new item
0028     if (jobType == JobType::AddItem) {
0029         mSourceItem.setRemoteId(QUuid::createUuid().toString());
0030     }
0031 }
0032 
0033 Akonadi::Item TomboyItemUploadJob::item() const
0034 {
0035     return mSourceItem;
0036 }
0037 
0038 JobType TomboyItemUploadJob::jobType() const
0039 {
0040     return mJobType;
0041 }
0042 
0043 void TomboyItemUploadJob::start()
0044 {
0045     // Convert note to JSON
0046     QJsonObject jsonNote;
0047     jsonNote[QLatin1StringView("guid")] = mSourceItem.remoteId();
0048     switch (mJobType) {
0049     case JobType::DeleteItem:
0050         jsonNote[QLatin1StringView("command")] = QStringLiteral("delete");
0051         break;
0052     case JobType::AddItem:
0053         jsonNote[QLatin1StringView("create-date")] = getCurrentISOTime();
0054         // Missing break is intended
0055         [[fallthrough]];
0056     case JobType::ModifyItem:
0057         jsonNote[QLatin1StringView("title")] = mNoteContent->headerByType("subject")->asUnicodeString();
0058         jsonNote[QLatin1StringView("note-content")] = mNoteContent->mainBodyPart()->decodedText();
0059         jsonNote[QLatin1StringView("note-content-version")] = QStringLiteral("1");
0060         jsonNote[QLatin1StringView("last-change-date")] = getCurrentISOTime();
0061     }
0062 
0063     // Create the full JSON object
0064     QJsonArray noteChanges;
0065     noteChanges.append(jsonNote);
0066     QJsonObject postJson;
0067     postJson[QLatin1StringView("note-changes")] = noteChanges;
0068     postJson[QLatin1StringView("latest-sync-revision")] = QString::number(++mRemoteRevision);
0069     QJsonDocument postData;
0070     postData.setObject(postJson);
0071 
0072     // Network request
0073     QNetworkRequest request = QNetworkRequest(QUrl(mContentURL));
0074     request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json; boundary=7d44e178b0439"));
0075     request.setHeader(QNetworkRequest::ContentLengthHeader, postData.toJson().length());
0076     mReply = mRequestor->put(request, QList<O0RequestParameter>(), postData.toJson());
0077     connect(mReply, &QNetworkReply::finished, this, &TomboyItemUploadJob::onRequestFinished);
0078     qCDebug(TOMBOYNOTESRESOURCE_LOG) << "TomboyItemUploadJob: Start network request";
0079 }
0080 
0081 void TomboyItemUploadJob::onRequestFinished()
0082 {
0083     checkReplyError();
0084     if (error() != TomboyJobError::NoError) {
0085         setErrorText(mReply->errorString());
0086         emitResult();
0087         return;
0088     }
0089     qCDebug(TOMBOYNOTESRESOURCE_LOG) << "TomboyItemUploadJob: Network request finished. No error occurred";
0090 
0091     // Parse received data as JSON
0092     const QJsonDocument document = QJsonDocument::fromJson(mReply->readAll(), nullptr);
0093 
0094     const QJsonObject jo = document.object();
0095     const QJsonArray notes = jo[QLatin1StringView("notes")].toArray();
0096 
0097     // Check if server status is as expected
0098     bool found = false;
0099     for (const auto &note : notes) {
0100         found = (note.toObject()[QLatin1StringView("guid")].toString() == mSourceItem.remoteId());
0101         if (found) {
0102             break;
0103         }
0104     }
0105     if (mJobType == JobType::DeleteItem && found) {
0106         setError(TomboyJobError::PermanentError);
0107         setErrorText(i18n("Sync error. Server status not as expected."));
0108         emitResult();
0109         return;
0110     }
0111     if (mJobType != JobType::DeleteItem && !found) {
0112         setError(TomboyJobError::PermanentError);
0113         setErrorText(i18n("Sync error. Server status not as expected."));
0114         emitResult();
0115         return;
0116     }
0117 
0118     setError(TomboyJobError::NoError);
0119     emitResult();
0120 }
0121 
0122 QString TomboyItemUploadJob::getCurrentISOTime() const
0123 {
0124     QDateTime local = QDateTime::currentDateTime();
0125     QDateTime utc = local.toUTC();
0126     utc.setTimeSpec(Qt::LocalTime);
0127     int utcOffset = utc.secsTo(local);
0128     local.setOffsetFromUtc(utcOffset);
0129 
0130     return local.toString(Qt::ISODate);
0131 }
0132 
0133 #include "moc_tomboyitemuploadjob.cpp"