File indexing completed on 2024-12-22 04:57:04
0001 /* 0002 SPDX-FileCopyrightText: 2015-2016 Krzysztof Nowicki <krissn@op.pl> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ewsupdateitemrequest.h" 0008 #include "ewsclient_debug.h" 0009 0010 static const QList<QString> conflictResolutionNames = { 0011 QStringLiteral("NeverOverwrite"), 0012 QStringLiteral("AutoResolve"), 0013 QStringLiteral("AlwaysOverwrite"), 0014 }; 0015 0016 static const QList<QString> messageDispositionNames = { 0017 QStringLiteral("SaveOnly"), 0018 QStringLiteral("SendOnly"), 0019 QStringLiteral("SendAndSaveCopy"), 0020 }; 0021 0022 static const QList<QString> meetingDispositionNames = { 0023 QStringLiteral("SendToNone"), 0024 QStringLiteral("SendOnlyToAll"), 0025 QStringLiteral("SendOnlyToChanged"), 0026 QStringLiteral("SendToAllAndSaveCopy"), 0027 QStringLiteral("SendToChangedAndSaveCopy"), 0028 }; 0029 0030 static const QList<QString> updateTypeElementNames = { 0031 QStringLiteral("AppendToItemField"), 0032 QStringLiteral("SetItemField"), 0033 QStringLiteral("DeleteItemField"), 0034 }; 0035 0036 EwsUpdateItemRequest::EwsUpdateItemRequest(EwsClient &client, QObject *parent) 0037 : EwsRequest(client, parent) 0038 , mMessageDisp(EwsDispSaveOnly) 0039 , mConflictResol(EwsResolAlwaysOverwrite) 0040 , mMeetingDisp(EwsMeetingDispUnspecified) 0041 { 0042 } 0043 0044 EwsUpdateItemRequest::~EwsUpdateItemRequest() = default; 0045 0046 void EwsUpdateItemRequest::start() 0047 { 0048 QString reqString; 0049 QXmlStreamWriter writer(&reqString); 0050 0051 startSoapDocument(writer); 0052 0053 writer.writeStartElement(ewsMsgNsUri, QStringLiteral("UpdateItem")); 0054 0055 writer.writeAttribute(QStringLiteral("ConflictResolution"), conflictResolutionNames[mConflictResol]); 0056 0057 writer.writeAttribute(QStringLiteral("MessageDisposition"), messageDispositionNames[mMessageDisp]); 0058 0059 if (mMeetingDisp != EwsMeetingDispUnspecified) { 0060 writer.writeAttribute(QStringLiteral("SendMeetingInvitationsOrCancellations"), meetingDispositionNames[mMeetingDisp]); 0061 } 0062 0063 if (mSavedFolderId.type() != EwsId::Unspecified) { 0064 writer.writeStartElement(ewsMsgNsUri, QStringLiteral("SavedItemFolderId")); 0065 mSavedFolderId.writeFolderIds(writer); 0066 writer.writeEndElement(); 0067 } 0068 0069 writer.writeStartElement(ewsMsgNsUri, QStringLiteral("ItemChanges")); 0070 for (const ItemChange &ch : std::as_const(mChanges)) { 0071 ch.write(writer); 0072 } 0073 writer.writeEndElement(); 0074 0075 writer.writeEndElement(); 0076 0077 endSoapDocument(writer); 0078 0079 qCDebugNC(EWSCLI_REQUEST_LOG) << QStringLiteral("Starting UpdateItem request (%1 changes)").arg(mChanges.size()); 0080 0081 qCDebug(EWSCLI_PROTO_LOG) << reqString; 0082 0083 prepare(reqString); 0084 0085 doSend(); 0086 } 0087 0088 bool EwsUpdateItemRequest::parseResult(QXmlStreamReader &reader) 0089 { 0090 mResponses.reserve(mChanges.size()); 0091 return parseResponseMessage(reader, QStringLiteral("UpdateItem"), [this](QXmlStreamReader &reader) { 0092 return parseItemsResponse(reader); 0093 }); 0094 } 0095 0096 bool EwsUpdateItemRequest::parseItemsResponse(QXmlStreamReader &reader) 0097 { 0098 Response resp(reader); 0099 if (resp.responseClass() == EwsResponseUnknown) { 0100 return false; 0101 } 0102 0103 if (EWSCLI_REQUEST_LOG().isDebugEnabled()) { 0104 if (resp.isSuccess()) { 0105 qCDebugNC(EWSCLI_REQUEST_LOG) << QStringLiteral("Got UpdateItem response - OK"); 0106 } else { 0107 qCDebugNC(EWSCLI_REQUEST_LOG) << QStringLiteral("Got UpdateItem response - %1").arg(resp.responseMessage()); 0108 } 0109 } 0110 0111 mResponses.append(resp); 0112 return true; 0113 } 0114 0115 EwsUpdateItemRequest::Response::Response(QXmlStreamReader &reader) 0116 : EwsRequest::Response(reader) 0117 , mConflictCount(0) 0118 { 0119 if (mClass == EwsResponseParseError) { 0120 return; 0121 } 0122 0123 while (reader.readNextStartElement()) { 0124 if (reader.namespaceUri() != ewsMsgNsUri && reader.namespaceUri() != ewsTypeNsUri) { 0125 setErrorMsg(QStringLiteral("Unexpected namespace in %1 element: %2").arg(QStringLiteral("ResponseMessage"), reader.namespaceUri().toString())); 0126 return; 0127 } 0128 0129 if (reader.name() == QLatin1StringView("Items")) { 0130 if (reader.readNextStartElement()) { 0131 EwsItem item(reader); 0132 if (!item.isValid()) { 0133 return; 0134 } 0135 mId = item[EwsItemFieldItemId].value<EwsId>(); 0136 } 0137 0138 // Finish the Items element. 0139 reader.skipCurrentElement(); 0140 } else if (reader.name() == QLatin1StringView("ConflictResults")) { 0141 if (!reader.readNextStartElement()) { 0142 setErrorMsg(QStringLiteral("Failed to read EWS request - expected a %1 element inside %2 element.") 0143 .arg(QStringLiteral("Value"), QStringLiteral("ConflictResults"))); 0144 return; 0145 } 0146 0147 if (reader.name() != QLatin1StringView("Count")) { 0148 setErrorMsg(QStringLiteral("Failed to read EWS request - expected a %1 element inside %2 element.") 0149 .arg(QStringLiteral("Count"), QStringLiteral("ConflictResults"))); 0150 return; 0151 } 0152 0153 bool ok; 0154 mConflictCount = reader.readElementText().toUInt(&ok); 0155 0156 if (!ok) { 0157 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid %1 element.").arg(QStringLiteral("ConflictResults/Value"))); 0158 } 0159 // Finish the Value element. 0160 reader.skipCurrentElement(); 0161 } else if (!readResponseElement(reader)) { 0162 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid response element %1.").arg(reader.name().toString())); 0163 return; 0164 } 0165 } 0166 } 0167 0168 bool EwsUpdateItemRequest::Update::write(QXmlStreamWriter &writer, EwsItemType itemType) const 0169 { 0170 bool retVal = true; 0171 0172 writer.writeStartElement(ewsTypeNsUri, updateTypeElementNames[mType]); 0173 0174 mField.write(writer); 0175 0176 if (mType != Delete) { 0177 writer.writeStartElement(ewsTypeNsUri, ewsItemTypeNames[itemType]); 0178 retVal = mField.writeWithValue(writer, mValue); 0179 writer.writeEndElement(); 0180 } 0181 0182 writer.writeEndElement(); 0183 0184 return retVal; 0185 } 0186 0187 bool EwsUpdateItemRequest::ItemChange::write(QXmlStreamWriter &writer) const 0188 { 0189 bool retVal = true; 0190 0191 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("ItemChange")); 0192 0193 mId.writeItemIds(writer); 0194 0195 writer.writeStartElement(ewsTypeNsUri, QStringLiteral("Updates")); 0196 0197 for (const QSharedPointer<const Update> &upd : std::as_const(mUpdates)) { 0198 if (!upd->write(writer, mType)) { 0199 retVal = false; 0200 break; 0201 } 0202 } 0203 0204 writer.writeEndElement(); 0205 0206 writer.writeEndElement(); 0207 0208 return retVal; 0209 } 0210 0211 #include "moc_ewsupdateitemrequest.cpp"