File indexing completed on 2025-02-16 04:50:11

0001 /*
0002     SPDX-FileCopyrightText: 2015-2020 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QSet>
0010 #include <QString>
0011 #include <QTimer>
0012 
0013 #include "ewsid.h"
0014 
0015 class EwsClient;
0016 class KJob;
0017 class EwsEventRequestBase;
0018 class EwsSettings;
0019 
0020 /**
0021  *  @brief  Mailbox update subscription manager class
0022  *
0023  *  This class is responsible for retrieving update notifications from the Exchange server.
0024  *
0025  *  The Exchange server has the ability to incrementally inform the client about changes made to
0026  *  selected folders in the mailbox. Each update informs about creation, modification or removal
0027  *  of an item or folder. Additionally Exchange has the ability to notify about free/busy status
0028  *  updates.
0029  *
0030  *  Notifications can be delivered in 3 ways:
0031  *   - pull (i.e. polling) - the client needs to periodically question the server.
0032  *   - push - the server issues a callback connection to the client with events (not supported)
0033  *   - streaming - a combination of pull and push, where the client makes the connection, but the
0034  *                 server keeps it open for a specified period of time and keeps delivering events
0035  *                 over this connection (supported since Exchange 2010 SP2).
0036  *
0037  *  The responsibility of this class is to retrieve and act upon change events from the Exchange
0038  *  server. The current implementation is simplified:
0039  *   - when an item update is received the folder containing the update is asked to synchronize
0040  *     itself.
0041  *   - when a folder update is received a full collection tree sync is performed.
0042  *
0043  *  The above implementation has a major drawback in that operations performed by the resource
0044  *  itself are also notified back as update events. This means that when for ex. an item is deleted
0045  *  it is removed from Akonadi database, but subsequently a delete event is received which will try
0046  *  to delete an item that has already been deleted from Akonadi.
0047  */
0048 class EwsSubscriptionManager : public QObject
0049 {
0050     Q_OBJECT
0051 public:
0052     EwsSubscriptionManager(EwsClient &client, const EwsId &rootId, EwsSettings *settings, QObject *parent);
0053     ~EwsSubscriptionManager() override;
0054     void start();
0055 Q_SIGNALS:
0056     void foldersModified(EwsId::List folders);
0057     void folderTreeModified();
0058     void fullSyncRequested();
0059     void connectionError();
0060 
0061 private:
0062     void subscribeRequestFinished(KJob *job);
0063     void verifySubFoldersRequestFinished(KJob *job);
0064     void getEventsRequestFinished(KJob *job);
0065     void streamingEventsReceived(KJob *job);
0066     void getEvents();
0067     void streamingConnectionTimeout();
0068 
0069 private:
0070     void cancelSubscription();
0071     void setupSubscription();
0072     void setupSubscriptionReq(const EwsId::List &ids);
0073     void reset();
0074     void resetSubscription();
0075     void processEvents(EwsEventRequestBase *req, bool finished);
0076 
0077     EwsClient &mEwsClient;
0078     QTimer mPollTimer;
0079     EwsId mMsgRootId;
0080 
0081     QSet<EwsId> mUpdatedFolderIds;
0082     bool mFolderTreeChanged;
0083     bool mStreamingEvents;
0084     QTimer mStreamingTimer;
0085     EwsEventRequestBase *mEventReq = nullptr;
0086     EwsSettings *mSettings = nullptr;
0087 };