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

0001 /*
0002     SPDX-FileCopyrightText: 2015-2017 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ewssyncfolderhierarchyrequest.h"
0008 
0009 #include <memory>
0010 
0011 #include <QXmlStreamWriter>
0012 
0013 #include "ewsclient_debug.h"
0014 #include "ewsxml.h"
0015 
0016 enum SyncFolderHierarchyResponseElementType {
0017     SyncFolderHierarchyResponseElementInvalid = -1,
0018     SyncState,
0019     IncludesLastFolderInRange,
0020     Changes,
0021 };
0022 
0023 enum SyncFolderHierarchyChangeElementType {
0024     SyncFolderHierarchyChangeElementInvalid = -1,
0025     Folder,
0026     FolderId,
0027     IsRead,
0028 };
0029 
0030 class EwsSyncFolderHierarchyRequest::Response : public EwsRequest::Response
0031 {
0032 public:
0033     Response(QXmlStreamReader &reader);
0034 
0035     static bool changeReader(QXmlStreamReader &reader, QVariant &val);
0036 
0037     EwsSyncFolderHierarchyRequest::Change::List mChanges;
0038     bool mIncludesLastFolder;
0039     QString mSyncState;
0040 };
0041 
0042 EwsSyncFolderHierarchyRequest::EwsSyncFolderHierarchyRequest(EwsClient &client, QObject *parent)
0043     : EwsRequest(client, parent)
0044     , mIncludesLastItem(false)
0045 {
0046     qRegisterMetaType<EwsSyncFolderHierarchyRequest::Change::List>();
0047     qRegisterMetaType<EwsFolder>();
0048 }
0049 
0050 EwsSyncFolderHierarchyRequest::~EwsSyncFolderHierarchyRequest() = default;
0051 
0052 void EwsSyncFolderHierarchyRequest::setFolderId(const EwsId &id)
0053 {
0054     mFolderId = id;
0055 }
0056 
0057 void EwsSyncFolderHierarchyRequest::setFolderShape(const EwsFolderShape &shape)
0058 {
0059     mShape = shape;
0060 }
0061 
0062 void EwsSyncFolderHierarchyRequest::setSyncState(const QString &state)
0063 {
0064     mSyncState = state;
0065 }
0066 
0067 void EwsSyncFolderHierarchyRequest::start()
0068 {
0069     QString reqString;
0070     QXmlStreamWriter writer(&reqString);
0071 
0072     startSoapDocument(writer);
0073 
0074     writer.writeStartElement(ewsMsgNsUri, QStringLiteral("SyncFolderHierarchy"));
0075 
0076     mShape.write(writer);
0077 
0078     writer.writeStartElement(ewsMsgNsUri, QStringLiteral("SyncFolderId"));
0079     mFolderId.writeFolderIds(writer);
0080     writer.writeEndElement();
0081 
0082     if (!mSyncState.isNull()) {
0083         writer.writeTextElement(ewsMsgNsUri, QStringLiteral("SyncState"), mSyncState);
0084     }
0085 
0086     writer.writeEndElement();
0087 
0088     endSoapDocument(writer);
0089 
0090     qCDebug(EWSCLI_PROTO_LOG) << reqString;
0091 
0092     if (EWSCLI_REQUEST_LOG().isDebugEnabled()) {
0093         QString st = mSyncState.isNull() ? QStringLiteral("none") : QString::number(qHash(mSyncState), 36);
0094         qCDebugNCS(EWSCLI_REQUEST_LOG) << QStringLiteral("Starting SyncFolderHierarchy request (folder: ") << mFolderId
0095                                        << QStringLiteral(", state: %1").arg(st);
0096     }
0097 
0098     prepare(reqString);
0099 
0100     doSend();
0101 }
0102 
0103 bool EwsSyncFolderHierarchyRequest::parseResult(QXmlStreamReader &reader)
0104 {
0105     return parseResponseMessage(reader, QStringLiteral("SyncFolderHierarchy"), [this](QXmlStreamReader &reader) {
0106         return parseItemsResponse(reader);
0107     });
0108 }
0109 
0110 bool EwsSyncFolderHierarchyRequest::parseItemsResponse(QXmlStreamReader &reader)
0111 {
0112     QScopedPointer<EwsSyncFolderHierarchyRequest::Response> resp(new EwsSyncFolderHierarchyRequest::Response(reader));
0113     if (resp->responseClass() == EwsResponseUnknown) {
0114         return false;
0115     }
0116 
0117     mChanges = resp->mChanges;
0118     mSyncState = resp->mSyncState;
0119     mIncludesLastItem = resp->mIncludesLastFolder;
0120 
0121     if (EWSCLI_REQUEST_LOG().isDebugEnabled()) {
0122         if (resp->isSuccess()) {
0123             qCDebugNC(EWSCLI_REQUEST_LOG)
0124                 << QStringLiteral("Got SyncFolderHierarchy response (%1 changes, state: %3)").arg(mChanges.size()).arg(qHash(mSyncState), 0, 36);
0125         } else {
0126             qCDebugNC(EWSCLI_REQUEST_LOG) << QStringLiteral("Got SyncFolderHierarchy response - %1").arg(resp->responseMessage());
0127         }
0128     }
0129 
0130     return true;
0131 }
0132 
0133 EwsSyncFolderHierarchyRequest::Response::Response(QXmlStreamReader &reader)
0134     : EwsRequest::Response(reader)
0135 {
0136     if (mClass == EwsResponseParseError) {
0137         return;
0138     }
0139 
0140     static const QList<EwsXml<SyncFolderHierarchyResponseElementType>::Item> items = {
0141         {SyncState, QStringLiteral("SyncState"), &ewsXmlTextReader},
0142         {IncludesLastFolderInRange, QStringLiteral("IncludesLastFolderInRange"), &ewsXmlBoolReader},
0143         {Changes, QStringLiteral("Changes"), &EwsSyncFolderHierarchyRequest::Response::changeReader},
0144     };
0145     static const EwsXml<SyncFolderHierarchyResponseElementType> staticReader(items);
0146 
0147     EwsXml<SyncFolderHierarchyResponseElementType> ewsReader(staticReader);
0148 
0149     if (!ewsReader.readItems(reader, ewsMsgNsUri, [this](QXmlStreamReader &reader, const QString &) {
0150             if (!readResponseElement(reader)) {
0151                 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid response element."));
0152                 return false;
0153             }
0154             return true;
0155         })) {
0156         mClass = EwsResponseParseError;
0157         return;
0158     }
0159 
0160     QHash<SyncFolderHierarchyResponseElementType, QVariant> values = ewsReader.values();
0161 
0162     mSyncState = values[SyncState].toString();
0163     mIncludesLastFolder = values[IncludesLastFolderInRange].toBool();
0164     mChanges = values[Changes].value<Change::List>();
0165 }
0166 
0167 bool EwsSyncFolderHierarchyRequest::Response::changeReader(QXmlStreamReader &reader, QVariant &val)
0168 {
0169     Change::List changes;
0170     QString elmName(reader.name().toString());
0171 
0172     while (reader.readNextStartElement()) {
0173         Change change(reader);
0174         if (!change.isValid()) {
0175             qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element").arg(elmName);
0176             return false;
0177         }
0178         changes.append(change);
0179     }
0180 
0181     val = QVariant::fromValue<Change::List>(changes);
0182     return true;
0183 }
0184 
0185 EwsSyncFolderHierarchyRequest::Change::Change(QXmlStreamReader &reader)
0186 {
0187     static const QList<EwsXml<SyncFolderHierarchyChangeElementType>::Item> items = {
0188         {Folder, QStringLiteral("Folder"), &ewsXmlFolderReader},
0189         {Folder, QStringLiteral("CalendarFolder"), &ewsXmlFolderReader},
0190         {Folder, QStringLiteral("ContactsFolder"), &ewsXmlFolderReader},
0191         {Folder, QStringLiteral("SearchFolder"), &ewsXmlFolderReader},
0192         {Folder, QStringLiteral("TasksFolder"), &ewsXmlFolderReader},
0193         {FolderId, QStringLiteral("FolderId"), &ewsXmlIdReader},
0194         {IsRead, QStringLiteral("IsRead"), &ewsXmlBoolReader},
0195     };
0196     static const EwsXml<SyncFolderHierarchyChangeElementType> staticReader(items);
0197 
0198     EwsXml<SyncFolderHierarchyChangeElementType> ewsReader(staticReader);
0199 
0200     if (reader.name() == QLatin1StringView("Create")) {
0201         mType = Create;
0202     } else if (reader.name() == QLatin1StringView("Update")) {
0203         mType = Update;
0204     } else if (reader.name() == QLatin1StringView("Delete")) {
0205         mType = Delete;
0206     }
0207     if (!ewsReader.readItems(reader, ewsTypeNsUri)) {
0208         return;
0209     }
0210 
0211     QHash<SyncFolderHierarchyChangeElementType, QVariant> values = ewsReader.values();
0212 
0213     switch (mType) {
0214     case Create:
0215     case Update:
0216         mFolder = values[Folder].value<EwsFolder>();
0217         mId = mFolder[EwsFolderFieldFolderId].value<EwsId>();
0218         break;
0219     case Delete:
0220         mId = values[FolderId].value<EwsId>();
0221         break;
0222     default:
0223         break;
0224     }
0225 }
0226 
0227 #include "moc_ewssyncfolderhierarchyrequest.cpp"