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"