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"