File indexing completed on 2025-01-05 04:50:01
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 "ewseventrequestbase.h" 0008 #include "ewsclient_debug.h" 0009 #include "ewsxml.h" 0010 0011 enum NotificationElementType { 0012 InvalidNotificationElement = -1, 0013 SubscriptionId, 0014 PreviousWatermark, 0015 MoreEvents, 0016 Events, 0017 }; 0018 typedef EwsXml<NotificationElementType> NotificationReader; 0019 0020 enum EventElementType { 0021 InvalidEventElement = -1, 0022 Watermark, 0023 Timestamp, 0024 ItemId, 0025 FolderId, 0026 ParentFolderId, 0027 OldItemId, 0028 OldFolderId, 0029 OldParentFolderId, 0030 UnreadCount, 0031 }; 0032 typedef EwsXml<EventElementType> EventReader; 0033 0034 EwsEventRequestBase::EwsEventRequestBase(EwsClient &client, const QString &reqName, QObject *parent) 0035 : EwsRequest(client, parent) 0036 , mReqName(reqName) 0037 { 0038 qRegisterMetaType<EwsEventRequestBase::Event::List>(); 0039 } 0040 0041 EwsEventRequestBase::~EwsEventRequestBase() 0042 { 0043 } 0044 0045 bool EwsEventRequestBase::parseResult(QXmlStreamReader &reader) 0046 { 0047 return parseResponseMessage(reader, mReqName, [this](QXmlStreamReader &reader) { 0048 return parseNotificationsResponse(reader); 0049 }); 0050 } 0051 0052 bool EwsEventRequestBase::parseNotificationsResponse(QXmlStreamReader &reader) 0053 { 0054 Response resp(reader); 0055 if (resp.responseClass() == EwsResponseUnknown) { 0056 return false; 0057 } 0058 0059 if (EWSCLI_REQUEST_LOG().isDebugEnabled()) { 0060 if (resp.isSuccess()) { 0061 int numEv = 0; 0062 const auto notifications = resp.notifications(); 0063 for (const Notification &nfy : notifications) { 0064 numEv += nfy.events().size(); 0065 } 0066 qCDebugNC(EWSCLI_REQUEST_LOG) 0067 << QStringLiteral("Got %1 response (%2 notifications, %3 events)").arg(mReqName).arg(resp.notifications().size()).arg(numEv); 0068 } else { 0069 qCDebug(EWSCLI_REQUEST_LOG) << QStringLiteral("Got %1 response - %2").arg(mReqName, resp.responseMessage()); 0070 } 0071 } 0072 0073 mResponses.append(resp); 0074 return true; 0075 } 0076 0077 EwsEventRequestBase::Response::Response(QXmlStreamReader &reader) 0078 : EwsRequest::Response(reader) 0079 { 0080 if (mClass == EwsResponseParseError) { 0081 return; 0082 } 0083 0084 while (reader.readNextStartElement()) { 0085 if (reader.namespaceUri() != ewsMsgNsUri && reader.namespaceUri() != ewsTypeNsUri) { 0086 setErrorMsg(QStringLiteral("Unexpected namespace in %1 element: %2").arg(QStringLiteral("ResponseMessage"), reader.namespaceUri().toString())); 0087 return; 0088 } 0089 0090 if (reader.name() == QLatin1StringView("Notification")) { 0091 Notification nfy(reader); 0092 if (!nfy.isValid()) { 0093 setErrorMsg(QStringLiteral("Failed to process notification.")); 0094 reader.skipCurrentElement(); 0095 return; 0096 } 0097 mNotifications.append(nfy); 0098 } else if (reader.name() == QLatin1StringView("Notifications")) { 0099 while (reader.readNextStartElement()) { 0100 if (reader.name() == QLatin1StringView("Notification")) { 0101 Notification nfy(reader); 0102 if (!nfy.isValid()) { 0103 setErrorMsg(QStringLiteral("Failed to process notification.")); 0104 reader.skipCurrentElement(); 0105 return; 0106 } 0107 mNotifications.append(nfy); 0108 } else { 0109 setErrorMsg(QStringLiteral("Failed to read EWS request - expected Notification inside Notifications")); 0110 } 0111 } 0112 } else if (reader.name() == QLatin1StringView("ConnectionStatus")) { 0113 reader.skipCurrentElement(); 0114 } else if (!readResponseElement(reader)) { 0115 setErrorMsg(QStringLiteral("Failed to read EWS request - invalid response element '%1'").arg(reader.name().toString())); 0116 return; 0117 } 0118 } 0119 } 0120 0121 EwsEventRequestBase::Notification::Notification(QXmlStreamReader &reader) 0122 { 0123 static const QList<NotificationReader::Item> items = { 0124 {SubscriptionId, QStringLiteral("SubscriptionId"), &ewsXmlTextReader}, 0125 {PreviousWatermark, QStringLiteral("PreviousWatermark"), &ewsXmlTextReader}, 0126 {MoreEvents, QStringLiteral("MoreEvents"), &ewsXmlBoolReader}, 0127 {Events, QStringLiteral("CopiedEvent"), &eventsReader}, 0128 {Events, QStringLiteral("CreatedEvent"), &eventsReader}, 0129 {Events, QStringLiteral("DeletedEvent"), &eventsReader}, 0130 {Events, QStringLiteral("ModifiedEvent"), &eventsReader}, 0131 {Events, QStringLiteral("MovedEvent"), &eventsReader}, 0132 {Events, QStringLiteral("NewMailEvent"), &eventsReader}, 0133 {Events, QStringLiteral("FreeBusyChangeEvent"), &eventsReader}, 0134 {Events, QStringLiteral("StatusEvent"), &eventsReader}, 0135 }; 0136 static const NotificationReader staticReader(items); 0137 0138 NotificationReader ewsreader(staticReader); 0139 0140 if (!ewsreader.readItems(reader, ewsTypeNsUri)) { 0141 return; 0142 } 0143 0144 QHash<NotificationElementType, QVariant> values = ewsreader.values(); 0145 0146 mSubscriptionId = values[SubscriptionId].toString(); 0147 mWatermark = values[PreviousWatermark].toString(); 0148 mMoreEvents = values[MoreEvents].toBool(); 0149 mEvents = values[Events].value<Event::List>(); 0150 } 0151 0152 bool EwsEventRequestBase::Notification::eventsReader(QXmlStreamReader &reader, QVariant &val) 0153 { 0154 Event::List events = val.value<Event::List>(); 0155 const QString elmName(reader.name().toString()); 0156 0157 Event event(reader); 0158 if (!event.isValid()) { 0159 qCWarningNC(EWSCLI_LOG) << QStringLiteral("Failed to read %1 element").arg(elmName); 0160 return false; 0161 } 0162 0163 events.append(event); 0164 0165 val = QVariant::fromValue<Event::List>(events); 0166 return true; 0167 } 0168 0169 EwsEventRequestBase::Event::Event(QXmlStreamReader &reader) 0170 : mType(EwsUnknownEvent) 0171 { 0172 static const QList<EventReader::Item> items = { 0173 {Watermark, QStringLiteral("Watermark"), &ewsXmlTextReader}, 0174 {Timestamp, QStringLiteral("TimeStamp"), &ewsXmlDateTimeReader}, 0175 {FolderId, QStringLiteral("FolderId"), &ewsXmlIdReader}, 0176 {ItemId, QStringLiteral("ItemId"), &ewsXmlIdReader}, 0177 {ParentFolderId, QStringLiteral("ParentFolderId"), &ewsXmlIdReader}, 0178 {OldFolderId, QStringLiteral("OldFolderId"), &ewsXmlIdReader}, 0179 {OldItemId, QStringLiteral("OldItemId"), &ewsXmlIdReader}, 0180 {OldParentFolderId, QStringLiteral("OldParentFolderId"), &ewsXmlIdReader}, 0181 {UnreadCount, QStringLiteral("UnreadCount"), &ewsXmlUIntReader}, 0182 }; 0183 static const EventReader staticReader(items); 0184 0185 EventReader ewsreader(staticReader); 0186 const QStringView elmName = reader.name(); 0187 if (elmName == QLatin1StringView("CopiedEvent")) { 0188 mType = EwsCopiedEvent; 0189 } else if (elmName == QLatin1StringView("CreatedEvent")) { 0190 mType = EwsCreatedEvent; 0191 } else if (elmName == QLatin1StringView("DeletedEvent")) { 0192 mType = EwsDeletedEvent; 0193 } else if (elmName == QLatin1StringView("ModifiedEvent")) { 0194 mType = EwsModifiedEvent; 0195 } else if (elmName == QLatin1StringView("MovedEvent")) { 0196 mType = EwsMovedEvent; 0197 } else if (elmName == QLatin1StringView("NewMailEvent")) { 0198 mType = EwsNewMailEvent; 0199 } else if (elmName == QLatin1StringView("StatusEvent")) { 0200 mType = EwsStatusEvent; 0201 } else if (elmName == QLatin1StringView("FreeBusyChangedEvent")) { 0202 mType = EwsFreeBusyChangedEvent; 0203 } else { 0204 qCWarning(EWSCLI_LOG) << QStringLiteral("Unknown notification event type: %1").arg(elmName.toString()); 0205 return; 0206 } 0207 0208 if (!ewsreader.readItems(reader, ewsTypeNsUri)) { 0209 mType = EwsUnknownEvent; 0210 return; 0211 } 0212 0213 QHash<EventElementType, QVariant> values = ewsreader.values(); 0214 0215 mWatermark = values[Watermark].toString(); 0216 mTimestamp = values[Timestamp].toDateTime(); 0217 if (values.contains(ItemId)) { 0218 mId = values[ItemId].value<EwsId>(); 0219 mOldId = values[OldItemId].value<EwsId>(); 0220 mIsFolder = false; 0221 } else { 0222 mId = values[FolderId].value<EwsId>(); 0223 mOldId = values[OldFolderId].value<EwsId>(); 0224 mIsFolder = true; 0225 } 0226 mParentFolderId = values[ParentFolderId].value<EwsId>(); 0227 mOldParentFolderId = values[OldParentFolderId].value<EwsId>(); 0228 mUnreadCount = values[UnreadCount].toUInt(); 0229 0230 if (mType == EwsStatusEvent) { 0231 qCDebugNCS(EWSCLI_LOG) << QStringLiteral(" %1").arg(elmName.toString()); 0232 } else { 0233 qCDebugNCS(EWSCLI_LOG) << QStringLiteral(" %1, %2, parent: ").arg(elmName.toString()).arg(mIsFolder ? 'F' : 'I') << mParentFolderId 0234 << QStringLiteral(", id: ") << mId; 0235 } 0236 } 0237 0238 bool EwsEventRequestBase::Response::operator==(const Response &other) const 0239 { 0240 return mNotifications == other.mNotifications; 0241 } 0242 0243 bool EwsEventRequestBase::Notification::operator==(const Notification &other) const 0244 { 0245 return (mSubscriptionId == other.mSubscriptionId) && (mWatermark == other.mWatermark) && (mMoreEvents == other.mMoreEvents) && (mEvents == other.mEvents); 0246 } 0247 0248 bool EwsEventRequestBase::Event::operator==(const Event &other) const 0249 { 0250 return (mType == other.mType) && (mWatermark == other.mWatermark) && (mTimestamp == other.mTimestamp) && (mId == other.mId) 0251 && (mParentFolderId == other.mParentFolderId) && (mUnreadCount == other.mUnreadCount) && (mOldId == other.mOldId) 0252 && (mOldParentFolderId == other.mOldParentFolderId) && (mIsFolder == other.mIsFolder); 0253 } 0254 0255 #include "moc_ewseventrequestbase.cpp"