File indexing completed on 2024-12-22 04:57:01
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 "ewsfindfolderrequest.h" 0008 0009 #include <memory> 0010 0011 #include <QXmlStreamWriter> 0012 0013 #include "ewsclient_debug.h" 0014 0015 static const QString traversalTypeNames[] = { 0016 QStringLiteral("Shallow"), 0017 QStringLiteral("Deep"), 0018 QStringLiteral("SoftDeleted"), 0019 }; 0020 0021 class EwsFindFolderResponse : public EwsRequest::Response 0022 { 0023 public: 0024 EwsFindFolderResponse(QXmlStreamReader &reader); 0025 bool parseRootFolder(QXmlStreamReader &reader); 0026 EwsFolder *readFolder(QXmlStreamReader &reader); 0027 unsigned readChildFolders(EwsFolder &parent, unsigned count, QXmlStreamReader &reader); 0028 0029 QList<EwsFolder> mFolders; 0030 }; 0031 0032 EwsFindFolderRequest::EwsFindFolderRequest(EwsClient &client, QObject *parent) 0033 : EwsRequest(client, parent) 0034 , mTraversal(EwsTraversalDeep) 0035 { 0036 } 0037 0038 EwsFindFolderRequest::~EwsFindFolderRequest() 0039 { 0040 } 0041 0042 void EwsFindFolderRequest::setParentFolderId(const EwsId &id) 0043 { 0044 mParentId = id; 0045 } 0046 0047 void EwsFindFolderRequest::setFolderShape(const EwsFolderShape &shape) 0048 { 0049 mShape = shape; 0050 } 0051 0052 void EwsFindFolderRequest::start() 0053 { 0054 QString reqString; 0055 QXmlStreamWriter writer(&reqString); 0056 0057 startSoapDocument(writer); 0058 0059 writer.writeStartElement(ewsMsgNsUri, QStringLiteral("FindFolder")); 0060 writer.writeAttribute(QStringLiteral("Traversal"), traversalTypeNames[mTraversal]); 0061 0062 mShape.write(writer); 0063 0064 writer.writeStartElement(ewsMsgNsUri, QStringLiteral("ParentFolderIds")); 0065 mParentId.writeFolderIds(writer); 0066 writer.writeEndElement(); 0067 0068 writer.writeEndElement(); 0069 0070 endSoapDocument(writer); 0071 0072 qCDebug(EWSCLI_PROTO_LOG) << reqString; 0073 0074 prepare(reqString); 0075 0076 doSend(); 0077 } 0078 0079 bool EwsFindFolderRequest::parseResult(QXmlStreamReader &reader) 0080 { 0081 return parseResponseMessage(reader, QStringLiteral("FindFolder"), [this](QXmlStreamReader &reader) { 0082 return parseFoldersResponse(reader); 0083 }); 0084 } 0085 0086 bool EwsFindFolderRequest::parseFoldersResponse(QXmlStreamReader &reader) 0087 { 0088 auto resp = new EwsFindFolderResponse(reader); 0089 if (resp->responseClass() == EwsResponseUnknown) { 0090 return false; 0091 } 0092 0093 mFolders = resp->mFolders; 0094 0095 return true; 0096 } 0097 0098 EwsFindFolderResponse::EwsFindFolderResponse(QXmlStreamReader &reader) 0099 : EwsRequest::Response(reader) 0100 { 0101 while (reader.readNextStartElement()) { 0102 if (reader.namespaceUri() != ewsMsgNsUri && reader.namespaceUri() != ewsTypeNsUri) { 0103 setErrorMsg(QStringLiteral("Unexpected namespace in %1 element: %2").arg(QStringLiteral("ResponseMessage"), reader.namespaceUri().toString())); 0104 return; 0105 } 0106 0107 if (reader.name() == QLatin1StringView("RootFolder")) { 0108 if (!parseRootFolder(reader)) { 0109 return; 0110 } 0111 } else if (!readResponseElement(reader)) { 0112 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid response element.")); 0113 return; 0114 } 0115 } 0116 } 0117 0118 bool EwsFindFolderResponse::parseRootFolder(QXmlStreamReader &reader) 0119 { 0120 if (reader.namespaceUri() != ewsMsgNsUri || reader.name() != QLatin1StringView("RootFolder")) { 0121 return setErrorMsg( 0122 QStringLiteral("Failed to read EWS request - expected %1 element (got %2).").arg(QStringLiteral("RootFolder"), reader.qualifiedName().toString())); 0123 } 0124 0125 if (!reader.attributes().hasAttribute(QStringLiteral("TotalItemsInView")) || !reader.attributes().hasAttribute(QStringLiteral("TotalItemsInView"))) { 0126 return setErrorMsg(QStringLiteral("Failed to read EWS request - missing attributes of %1 element.").arg(QStringLiteral("RootFolder"))); 0127 } 0128 bool ok; 0129 unsigned totalItems = reader.attributes().value(QStringLiteral("TotalItemsInView")).toUInt(&ok); 0130 if (!ok) { 0131 return setErrorMsg(QStringLiteral("Failed to read EWS request - failed to read %1 attribute.").arg(QStringLiteral("TotalItemsInView"))); 0132 } 0133 0134 if (!reader.readNextStartElement()) { 0135 return setErrorMsg(QStringLiteral("Failed to read EWS request - expected a child element in %1 element.").arg(QStringLiteral("RootFolder"))); 0136 } 0137 0138 if (reader.namespaceUri() != ewsTypeNsUri || reader.name() != QLatin1StringView("Folders")) { 0139 return setErrorMsg( 0140 QStringLiteral("Failed to read EWS request - expected %1 element (got %2).").arg(QStringLiteral("Folders"), reader.qualifiedName().toString())); 0141 } 0142 0143 if (!reader.readNextStartElement()) { 0144 return setErrorMsg(QStringLiteral("Failed to read EWS request - expected a child element in %1 element.").arg(QStringLiteral("Folders"))); 0145 } 0146 0147 if (reader.namespaceUri() != ewsTypeNsUri) { 0148 return setErrorMsg(QStringLiteral("Failed to read EWS request - expected child element from types namespace.")); 0149 } 0150 0151 unsigned i = 0; 0152 for (i = 0; i < totalItems; ++i) { 0153 EwsFolder *folder = readFolder(reader); 0154 reader.readNextStartElement(); 0155 if (folder) { 0156 bool okInt; 0157 int childCount = (*folder)[EwsFolderFieldChildFolderCount].toUInt(&okInt); 0158 if (childCount > 0) { 0159 unsigned readCount = readChildFolders(*folder, childCount, reader); 0160 if (readCount == 0) { 0161 return false; 0162 } 0163 i += readCount; 0164 } 0165 mFolders.append(*folder); 0166 delete folder; 0167 } 0168 } 0169 0170 // Finish the Folders element 0171 reader.skipCurrentElement(); 0172 0173 // Finish the RootFolder element 0174 reader.skipCurrentElement(); 0175 0176 return true; 0177 } 0178 0179 EwsFolder *EwsFindFolderResponse::readFolder(QXmlStreamReader &reader) 0180 { 0181 EwsFolder *folder = nullptr; 0182 const QStringView readerName = reader.name(); 0183 if (readerName == QLatin1StringView("Folder") || readerName == QLatin1StringView("CalendarFolder") || readerName == QLatin1StringView("ContactsFolder") 0184 || readerName == QLatin1StringView("TasksFolder") || readerName == QLatin1StringView("SearchFolder")) { 0185 folder = new EwsFolder(reader); 0186 if (!folder->isValid()) { 0187 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid %1 element.").arg(QStringLiteral("Folder"))); 0188 delete folder; 0189 return nullptr; 0190 } 0191 QVariant dn = (*folder)[EwsFolderFieldDisplayName]; 0192 if (!dn.isNull()) { 0193 EwsClient::folderHash[(*folder)[EwsFolderFieldFolderId].value<EwsId>().id()] = dn.toString(); 0194 } 0195 } else { 0196 qCWarning(EWSCLI_LOG).noquote() << QStringLiteral("Unsupported folder type %1").arg(readerName.toString()); 0197 reader.skipCurrentElement(); 0198 } 0199 0200 return folder; 0201 } 0202 0203 unsigned EwsFindFolderResponse::readChildFolders(EwsFolder &parent, unsigned count, QXmlStreamReader &reader) 0204 { 0205 unsigned readCount = 0; 0206 for (unsigned i = 0; i < count; ++i) { 0207 EwsFolder *folder = readFolder(reader); 0208 reader.readNextStartElement(); 0209 if (folder) { 0210 bool ok; 0211 int childCount = (*folder)[EwsFolderFieldChildFolderCount].toUInt(&ok); 0212 if (ok && childCount > 0) { 0213 unsigned readCount2 = readChildFolders(*folder, childCount, reader); 0214 if (readCount2 == 0) { 0215 return false; 0216 } 0217 readCount += readCount2; 0218 } 0219 parent.addChild(*folder); 0220 } 0221 ++readCount; 0222 } 0223 return readCount; 0224 } 0225 0226 #include "moc_ewsfindfolderrequest.cpp"