1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
2 
3    This file is part of the Trojita Qt IMAP e-mail client,
4    http://trojita.flaska.net/
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of
9    the License or (at your option) version 3 or any later version
10    accepted by the membership of KDE e.V. (or its successor approved
11    by the membership of KDE e.V.), which shall act as a proxy
12    defined in Section 14 of version 3 of the license.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #ifndef IMAP_OBTAINSYNCHRONIZEDMAILBOXTASK_H
24 #define IMAP_OBTAINSYNCHRONIZEDMAILBOXTASK_H
25 
26 #include "ImapTask.h"
27 #include <QModelIndex>
28 #include "../Model/Model.h"
29 
30 namespace Imap
31 {
32 namespace Mailbox
33 {
34 
35 class UnSelectTask;
36 
37 /** @short Create a synchronized connection to the IMAP server
38 
39 Upon creation, this class will obtain a connection to the IMAP
40 server (either by creating new one, or simply stealing one from
41 an already established one, open a mailbox, fully synchronize it
42 and when all of the above is done, simply declare itself completed.
43 */
44 class ObtainSynchronizedMailboxTask : public ImapTask
45 {
46     Q_OBJECT
47 public:
48     ObtainSynchronizedMailboxTask(Model *model, const QModelIndex &mailboxIndex, ImapTask *parentTask, KeepMailboxOpenTask *keepTask);
49     virtual void perform();
50     virtual bool handleStateHelper(const Imap::Responses::State *const resp);
51     virtual bool handleNumberResponse(const Imap::Responses::NumberResponse *const resp);
52     virtual bool handleFlags(const Imap::Responses::Flags *const resp);
53     virtual bool handleSearch(const Imap::Responses::Search *const resp);
54     virtual bool handleESearch(const Imap::Responses::ESearch *const resp);
55     virtual bool handleFetch(const Imap::Responses::Fetch *const resp);
56     virtual bool handleVanished(const Imap::Responses::Vanished *const resp);
57     virtual bool handleEnabled(const Responses::Enabled * const resp);
58 
59     typedef enum { UID_SYNC_ALL, UID_SYNC_ONLY_NEW } UidSyncingMode;
60 
61     virtual void addDependentTask(ImapTask *task);
62 
63     virtual QString debugIdentification() const;
64     virtual QVariant taskData(const int role) const;
needsMailbox()65     virtual bool needsMailbox() const {return false;}
66 
67 private:
68     void finalizeSelect();
69     void fullMboxSync(TreeItemMailbox *mailbox, TreeItemMsgList *list);
70     void syncNoNewNoDeletions(TreeItemMailbox *mailbox, TreeItemMsgList *list);
71     void syncOnlyAdditions(TreeItemMailbox *mailbox, TreeItemMsgList *list);
72     void syncGeneric(TreeItemMailbox *mailbox, TreeItemMsgList *list);
73 
74     void applyUids(TreeItemMailbox *mailbox);
75     void finalizeSearch();
76 
77     void syncUids(TreeItemMailbox *mailbox, const uint lowestUidToQuery=0);
78     void syncFlags(TreeItemMailbox *mailbox);
79     void updateHighestKnownUid(TreeItemMailbox *mailbox, const TreeItemMsgList *list) const;
80 
81     void notifyInterestingMessages(TreeItemMailbox *mailbox);
82 
83     bool handleResponseCodeInsideState(const Imap::Responses::State *const resp);
84 
85     /** @short Check current mailbox for validty, and take an evasive action if it disappeared
86 
87       There's a problem when going online after an outage, where the underlying TreeItemMailbox could disappear.
88       This function checks the index for validity, and queues a fake "unselect" task just to make sure that
89       we get out of that mailbox as soon as possible. This task will also die() in such situation.
90 
91       See issue #88 for details.
92 
93       @returns true if the current response shall be consumed
94     */
95     bool dieIfInvalidMailbox();
96 
97 private slots:
98     /** @short We're now out of that mailbox, hurray! */
99     void slotUnSelectCompleted();
100 
101     void signalSyncFailure(const QString &message);
102 
103 private:
104     ImapTask *conn;
105     QPersistentModelIndex mailboxIndex;
106     CommandHandle selectCmd;
107     CommandHandle uidSyncingCmd;
108     CommandHandle flagsCmd;
109     QList<CommandHandle> newArrivalsFetch;
110     Imap::Mailbox::MailboxSyncingProgress status;
111     UidSyncingMode uidSyncingMode;
112     Imap::Uids uidMap;
113     uint firstUnknownUidOffset;
114     SyncState oldSyncState;
115     bool m_usingQresync;
116 
117     /** @short An UNSELECT task, if active */
118     UnSelectTask *unSelectTask;
119 
120     /** @short The KeepMailboxOpenTask for which we're working */
121     KeepMailboxOpenTask *keepTaskChild;
122 
123     friend class KeepMailboxOpenTask; // needs access to conn because it wants to re-use its parser, yay
124 };
125 
126 }
127 }
128 
129 #endif // IMAP_OBTAINSYNCHRONIZEDMAILBOXTASK_H
130