File indexing completed on 2024-11-24 04:44:33

0001 /*
0002    SPDX-FileCopyrightText: 2010 Thomas McGuire <mcguire@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #pragma once
0008 
0009 class KJob;
0010 #include <Akonadi/ResourceBase>
0011 #include <KMime/Message>
0012 #include <QSet>
0013 
0014 #include "settings.h"
0015 
0016 class DeleteJob;
0017 
0018 namespace Akonadi
0019 {
0020 class ItemCreateJob;
0021 }
0022 class POPSession;
0023 class QTimer;
0024 namespace QKeychain
0025 {
0026 class Job;
0027 }
0028 class POP3Resource : public Akonadi::ResourceBase, public Akonadi::AgentBase::Observer
0029 {
0030     Q_OBJECT
0031 
0032 public:
0033     explicit POP3Resource(const QString &id);
0034     ~POP3Resource() override;
0035 
0036     void clearCachedPassword();
0037 
0038     void cleanup() override;
0039 
0040 protected:
0041     using ResourceBase::retrieveItems; // Suppress -Woverload-virtual
0042 
0043 protected Q_SLOTS:
0044     void retrieveCollections() override;
0045     void retrieveItems(const Akonadi::Collection &col) override;
0046     bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts) override;
0047     bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts) override;
0048 
0049 protected:
0050     void aboutToQuit() override;
0051     void doSetOnline(bool online) override;
0052 
0053 private Q_SLOTS:
0054 
0055     void slotAbortRequested();
0056     void intervalCheckTriggered();
0057     void configurationChanged();
0058 
0059     // For state FetchTargetCollection
0060     void targetCollectionFetchJobFinished(KJob *job);
0061     void localFolderRequestJobFinished(KJob *job);
0062 
0063     // For state Precommand
0064     void precommandResult(KJob *job);
0065 
0066     // For state RequestPassword
0067     void walletOpenedForLoading(QKeychain::Job *baseJob);
0068 
0069     // For state Login
0070     void loginJobResult(KJob *job);
0071 
0072     // For state List
0073     void listJobResult(KJob *job);
0074 
0075     // For state UIDList
0076     void uidListJobResult(KJob *job);
0077 
0078     // For state Download
0079     void messageFinished(int messageId, KMime::Message::Ptr message);
0080     void fetchJobResult(KJob *job);
0081     void messageDownloadProgress(KJob *job, KJob::Unit unit, qulonglong totalBytes);
0082 
0083     // For state Save
0084     void itemCreateJobResult(KJob *job);
0085 
0086     // For state Delete
0087     void deleteJobResult(KJob *job);
0088 
0089     // For state Quit
0090     void quitJobResult(KJob *job);
0091 
0092 private:
0093     enum State {
0094         Idle,
0095         FetchTargetCollection,
0096         Precommand,
0097         RequestPassword,
0098         Connect,
0099         Login,
0100         List,
0101         UIDList,
0102         Download,
0103         Save,
0104         Quit,
0105         SavePassword,
0106         CheckRemovingMessage
0107     };
0108 
0109     void resetState();
0110     void doStateStep();
0111     void advanceState(State nextState);
0112     void cancelSync(const QString &errorMessage, bool error = true);
0113     void saveSeenUIDList();
0114     QList<int> shouldDeleteId(int downloadedId) const;
0115     int idToTime(int id) const;
0116     int idOfOldestMessage(const QSet<int> &idList) const;
0117     void startMailCheck();
0118     void updateIntervalTimer();
0119     void showPasswordDialog(const QString &queryText);
0120     QString buildLabelForPasswordDialog(const QString &detailedError) const;
0121     void checkRemovingMessageFromServer();
0122     void finish();
0123 
0124     bool shouldAdvanceToQuitState() const;
0125 
0126     State mState;
0127     Akonadi::Collection mTargetCollection;
0128     POPSession *mPopSession = nullptr;
0129     bool mAskAgain = false;
0130     QTimer *mIntervalTimer = nullptr;
0131     bool mIntervalCheckInProgress = false;
0132     QString mPassword;
0133     bool mSavePassword = false;
0134     bool mTestLocalInbox = false;
0135 
0136     // Maps IDs on the server to message sizes on the server
0137     QMap<int, int> mIdsToSizeMap;
0138 
0139     // Maps IDs on the server to UIDs on the server.
0140     // This can be empty, if the server doesn't support UIDL
0141     QMap<int, QString> mIdsToUidsMap;
0142 
0143     // Maps UIDs on the server to IDs on the server.
0144     // This can be empty, if the server doesn't support UIDL
0145     QMap<QString, int> mUidsToIdsMap;
0146 
0147     // Whether we actually received a valid UID list from the server
0148     bool mUidListValid;
0149 
0150     // IDs of messages that we have successfully downloaded. This does _not_ mean
0151     // that the messages corresponding to the IDs are stored in Akonadi yet
0152     QList<int> mDownloadedIDs;
0153 
0154     // IDs of messages that we want to download and that we have started the
0155     // FetchJob with. After the FetchJob, this should be empty, except if there
0156     // was some error
0157     QList<int> mIdsToDownload;
0158 
0159     // After downloading a message, we store it in Akonadi by using an ItemCreateJob.
0160     // This map stores the currently running ItemCreateJob's and their corresponding
0161     // POP3 IDs.
0162     // When an ItemCreateJob finished, it is removed from this map.
0163     // The Save state waits until this map becomes empty.
0164     QMap<Akonadi::ItemCreateJob *, int> mPendingCreateJobs;
0165 
0166     // List of message IDs that were successfully stored in Akonadi
0167     QList<int> mIDsStored;
0168 
0169     // List of message IDs that were successfully deleted
0170     QList<int> mDeletedIDs;
0171 
0172     // List of message IDs that we want to delete with the next delete job
0173     QList<int> mIdsWaitingToDelete;
0174 
0175     // List of message IDs that we want to keep on the server
0176     mutable QSet<int> mIdsToSave;
0177     mutable bool mIdsToSaveValid;
0178 
0179     // Current deletion job in process
0180     DeleteJob *mDeleteJob = nullptr;
0181 
0182     Settings mSettings;
0183 };