summaryrefslogtreecommitdiffstats
path: root/kmail/kmfoldercachedimap.h
diff options
context:
space:
mode:
Diffstat (limited to 'kmail/kmfoldercachedimap.h')
-rw-r--r--kmail/kmfoldercachedimap.h567
1 files changed, 567 insertions, 0 deletions
diff --git a/kmail/kmfoldercachedimap.h b/kmail/kmfoldercachedimap.h
new file mode 100644
index 00000000..1ef82a3a
--- /dev/null
+++ b/kmail/kmfoldercachedimap.h
@@ -0,0 +1,567 @@
+/*
+ * kmfoldercachedimap.cpp
+ *
+ * Copyright (c) 2002-2004 Bo Thorsen <bo@sonofthor.dk>
+ * Copyright (c) 2002-2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of this program with any edition of
+ * the Qt library by Trolltech AS, Norway (or with modified versions
+ * of Qt that use the same license as Qt), and distribute linked
+ * combinations including the two. You must obey the GNU General
+ * Public License in all respects for all of the code used other than
+ * Qt. If you modify this file, you may extend this exception to
+ * your version of the file, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from
+ * your version.
+ */
+
+#ifndef kmfoldercachedimap_h
+#define kmfoldercachedimap_h
+
+#include <kdialogbase.h>
+#include <kstandarddirs.h>
+#include <qvaluelist.h>
+#include <qvaluevector.h>
+#include <qptrlist.h>
+#include <qdialog.h>
+
+#include "kmfoldermaildir.h"
+#include "kmfolderimap.h"
+#include "kmacctcachedimap.h"
+#include "kmfoldertype.h"
+#include "folderjob.h"
+#include "cachedimapjob.h"
+#include "quotajobs.h"
+
+using KMail::FolderJob;
+using KMail::QuotaInfo;
+class KMCommand;
+
+class QComboBox;
+class QRadioButton;
+
+namespace KMail {
+ class AttachmentStrategy;
+ class ImapAccountBase;
+ struct ACLListEntry;
+}
+using KMail::AttachmentStrategy;
+
+class DImapTroubleShootDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ enum SelectedOperation {
+ None = -1,
+ ReindexCurrent = 0,
+ ReindexRecursive = 1,
+ ReindexAll = 2,
+ RefreshCache
+ };
+
+ DImapTroubleShootDialog( QWidget* parent=0, const char* name=0 );
+
+ static int run();
+
+private slots:
+ void slotDone();
+
+private:
+ QRadioButton *mIndexButton, *mCacheButton;
+ QComboBox *mIndexScope;
+ int rc;
+};
+
+class KMFolderCachedImap : public KMFolderMaildir
+{
+ Q_OBJECT
+
+public:
+ static QString cacheLocation() {
+ return locateLocal("data", "kmail/dimap" );
+ }
+
+ /** Usually a parent is given. But in some cases there is no
+ fitting parent object available. Then the name of the folder
+ is used as the absolute path to the folder file. */
+ KMFolderCachedImap(KMFolder* folder, const char* name=0);
+ virtual ~KMFolderCachedImap();
+
+ /** @reimpl */
+ void reallyDoClose(const char* owner);
+
+ /** Initialize this storage from another one. Used when creating a child folder */
+ void initializeFrom( KMFolderCachedImap* parent );
+
+ virtual void readConfig();
+ virtual void writeConfig();
+
+ void writeConfigKeysWhichShouldNotGetOverwrittenByReadConfig();
+
+ /** Returns the type of this folder */
+ virtual KMFolderType folderType() const { return KMFolderTypeCachedImap; }
+
+ /** @reimpl */
+ virtual int create();
+
+ /** Remove this folder */
+ virtual void remove();
+
+ /** Synchronize this folder and it's subfolders with the server */
+ virtual void serverSync( bool recurse );
+
+ /** Force the sync state to be done. */
+ void resetSyncState( );
+
+ /** Block this folder from generating alarms, even if the annotations
+ * on it say otherwise. Used to override alarms for read-only folders.
+ * (Only useful for resource folders) */
+ void setAlarmsBlocked( bool blocked );
+ /** Should alarms for this folder be blocked? (Only useful for resource folders) */
+ bool alarmsBlocked() const;
+
+ void checkUidValidity();
+
+ enum imapState { imapNoInformation=0, imapInProgress=1, imapFinished=2 };
+
+ virtual imapState getContentState() { return mContentState; }
+ virtual void setContentState(imapState state) { mContentState = state; }
+
+ virtual imapState getSubfolderState() { return mSubfolderState; }
+ virtual void setSubfolderState(imapState state);
+
+ /** The path to the imap folder on the server */
+ void setImapPath(const QString &path);
+ QString imapPath() const { return mImapPath; }
+
+ /** The highest UID in the folder */
+ void setLastUid( ulong uid );
+ ulong lastUid();
+
+ /** Find message by UID. Returns NULL if it doesn't exist */
+ KMMsgBase* findByUID( ulong uid );
+
+ /** The uidvalidity of the last update */
+ void setUidValidity(const QString &validity) { mUidValidity = validity; }
+ QString uidValidity() const { return mUidValidity; }
+
+ /** Forget which mails are considered locally present. Needed when uidvalidity
+ * changes. */
+ void clearUidMap() { uidMap.clear(); }
+
+ /** The imap account associated with this folder */
+ void setAccount(KMAcctCachedImap *acct);
+ KMAcctCachedImap* account() const;
+
+ /** Returns the filename of the uidcache file */
+ QString uidCacheLocation() const;
+
+ /** Read the uidValitidy and lastUid values from disk */
+ int readUidCache();
+
+ /** Write the uidValitidy and lastUid values to disk */
+ int writeUidCache();
+
+ /** Current progress status (between 0 and 100) */
+ int progress() const { return mProgress; }
+
+ /* Reimplemented from KMFolder. Moving is not supported, so aParent must be 0 */
+ virtual int rename(const QString& aName, KMFolderDir *aParent=0);
+
+ /**
+ * Reimplemented from KMFolderMaildir
+ * This deletes the message permanently, also from the server. For this, rememberDeletion() is
+ * called, so that the message can be deleted from the server on the next sync.
+ */
+ virtual KMMessage* take(int idx);
+
+ /**
+ * Like take(), only that the deletion is not remembered, i.e. the message will not be deleted
+ * from the server.
+ * Calling this can cause inconsistencies, so make sure you re-add the message later!
+ */
+ void takeTemporarily( int idx );
+
+ /* Reimplemented from KMFolderMaildir */
+ virtual int addMsg(KMMessage* msg, int* index_return = 0);
+ /* internal version that doesn't remove the X-UID header */
+ virtual int addMsgInternal(KMMessage* msg, bool, int* index_return = 0);
+ virtual int addMsgKeepUID(KMMessage* msg, int* index_return = 0) {
+ return addMsgInternal(msg, false, index_return);
+ }
+
+ /* Reimplemented from KMFolderMaildir */
+ virtual void removeMsg(int i, bool imapQuiet = false);
+ virtual void removeMsg(QPtrList<KMMessage> msgList, bool imapQuiet = false)
+ { FolderStorage::removeMsg(msgList, imapQuiet); }
+
+ /// Is the folder readonly?
+ bool isReadOnly() const { return KMFolderMaildir::isReadOnly() || mReadOnly; }
+
+
+ /**
+ * Emit the folderComplete signal
+ */
+ void sendFolderComplete(bool success)
+ { emit folderComplete(this, success); }
+
+ /**
+ * The silentUpload can be set to remove the folder upload error dialog
+ */
+ void setSilentUpload( bool silent ) { mSilentUpload = silent; }
+ bool silentUpload() { return mSilentUpload; }
+
+ virtual int createIndexFromContents() {
+ const int result = KMFolderMaildir::createIndexFromContents();
+ reloadUidMap();
+ return result;
+ }
+
+ int createIndexFromContentsRecursive();
+
+ //virtual void holdSyncs( bool hold ) { mHoldSyncs = hold; }
+
+ /**
+ * List a directory and add the contents to kmfoldermgr
+ * It uses a ListJob to get the folders
+ * returns false if the connection failed
+ */
+ virtual bool listDirectory();
+
+ virtual void listNamespaces();
+
+ /** Return the trash folder. */
+ KMFolder* trashFolder() const;
+
+ /**
+ * The user's rights on this folder - see bitfield in ACLJobs namespace.
+ * @return 0 when not known yet, -1 if there was an error fetching them
+ */
+ int userRights() const { return mUserRights; }
+
+ /// Set the user's rights on this folder - called by getUserRights
+ void setUserRights( unsigned int userRights );
+
+ /**
+ * The quota information for this folder.
+ * @return an invalid info if we haven't synced yet, or the server
+ * doesn't support quota. The difference can be figured out by
+ * asking the account whether it supports quota. If we have
+ * synced, the account supports quota, but there is no quota
+ * on the folder, the return info will be valid, but empty.
+ * @see QuotaInfo::isEmpty(), QuotaInfo::isValid()
+ */
+ const QuotaInfo quotaInfo() const { return mQuotaInfo; }
+ void setQuotaInfo( const QuotaInfo & );
+
+ /// Return the list of ACL for this folder
+ typedef QValueVector<KMail::ACLListEntry> ACLList;
+ const ACLList& aclList() const { return mACLList; }
+
+ /// Set the list of ACL for this folder (for FolderDiaACLTab)
+ void setACLList( const ACLList& arr );
+
+ // Reimplemented so the mStatusChangedLocally bool can be set
+ virtual void setStatus( int id, KMMsgStatus status, bool toggle );
+ virtual void setStatus( QValueList<int>& ids, KMMsgStatus status, bool toggle );
+
+ QString annotationFolderType() const { return mAnnotationFolderType; }
+
+ // For kmailicalifaceimpl only
+ void updateAnnotationFolderType();
+
+ /// Free-busy and alarms relevance of this folder, i.e. for whom should
+ /// events in this calendar lead to "busy" periods in their freebusy lists,
+ /// and who should get alarms for the incidences in this folder.
+ /// Applies to Calendar and Task folders only.
+ ///
+ /// IncForNobody: not relevant for free-busy and alarms to anybody
+ /// IncForAdmins: apply to persons with admin permissions on this calendar
+ /// IncForReaders: apply to all readers of this calendar
+ enum IncidencesFor { IncForNobody, IncForAdmins, IncForReaders };
+
+ IncidencesFor incidencesFor() const { return mIncidencesFor; }
+ /// For the folder properties dialog
+ void setIncidencesFor( IncidencesFor incfor );
+
+ /** Returns true if this folder can be moved */
+ virtual bool isMoveable() const;
+
+ /**
+ * List of namespaces that need to be queried
+ * Is set by the account for the root folder when the listing starts
+ */
+ QStringList namespacesToList() { return mNamespacesToList; }
+ void setNamespacesToList( QStringList list ) { mNamespacesToList = list; }
+
+ /**
+ * Specify an imap path that is used to create the folder on the server
+ * Otherwise the parent folder is used to construct the path
+ */
+ const QString& imapPathForCreation() { return mImapPathCreation; }
+ void setImapPathForCreation( const QString& path ) { mImapPathCreation = path; }
+
+ /** \reimp */
+ bool isCloseToQuota() const;
+
+ /** Flags that can be permanently stored on the server. */
+ int permanentFlags() const { return mPermanentFlags; }
+
+
+ QString folderAttributes() const { return mFolderAttributes; }
+
+protected slots:
+ void slotGetMessagesData(KIO::Job * job, const QByteArray & data);
+ void getMessagesResult(KMail::FolderJob *, bool lastSet);
+ void slotGetLastMessagesResult(KMail::FolderJob *);
+ void slotProgress(unsigned long done, unsigned long total);
+ void slotPutProgress( unsigned long, unsigned long );
+
+ //virtual void slotCheckValidityResult(KIO::Job * job);
+ void slotSubFolderComplete(KMFolderCachedImap*, bool);
+
+ // Connected to the imap account
+ void slotConnectionResult( int errorCode, const QString& errorMsg );
+
+ void slotCheckUidValidityResult( KMail::FolderJob* job );
+ void slotPermanentFlags( int flags );
+ void slotTestAnnotationResult(KIO::Job *job);
+ void slotGetAnnotationResult( KIO::Job* );
+ void slotMultiUrlGetAnnotationResult( KIO::Job* );
+ void slotSetAnnotationResult(KIO::Job *job);
+ void slotReceivedUserRights( KMFolder* );
+ void slotReceivedACL( KMFolder*, KIO::Job*, const KMail::ACLList& );
+
+ void slotMultiSetACLResult(KIO::Job *);
+ void slotACLChanged( const QString&, int );
+ void slotAnnotationResult(const QString& entry, const QString& value, bool found);
+ void slotAnnotationChanged( const QString& entry, const QString& attribute, const QString& value );
+ void slotDeleteMessagesResult(KMail::FolderJob *);
+ void slotImapStatusChanged(KMFolder* folder, const QString&, bool);
+ void slotStorageQuotaResult( const QuotaInfo& );
+ void slotQuotaResult( KIO::Job* job );
+
+protected:
+ /* returns true if there were messages to delete
+ on the server */
+ bool deleteMessages();
+ void listMessages();
+ void uploadNewMessages();
+ void uploadFlags();
+ void uploadSeenFlags();
+ void createNewFolders();
+
+ void listDirectory2();
+ void createFoldersNewOnServerAndFinishListing( const QValueVector<int> foldersNewOnServer );
+
+
+ /** Utility methods for syncing. Finds new messages
+ in the local cache that must be uploaded */
+ virtual QValueList<unsigned long> findNewMessages();
+ /** Utility methods for syncing. Finds new subfolders
+ in the local cache that must be created in the server */
+ virtual QValueList<KMFolderCachedImap*> findNewFolders();
+
+ /** This returns false if we have subfolders. Otherwise it returns ::canRemoveFolder() */
+ virtual bool canRemoveFolder() const;
+
+ /** Reimplemented from KMFolder */
+ virtual FolderJob* doCreateJob( KMMessage *msg, FolderJob::JobType jt, KMFolder *folder,
+ QString partSpecifier, const AttachmentStrategy *as ) const;
+ virtual FolderJob* doCreateJob( QPtrList<KMMessage>& msgList, const QString& sets,
+ FolderJob::JobType jt, KMFolder *folder ) const;
+
+ virtual void timerEvent( QTimerEvent* );
+
+ /* update progress status */
+ void newState( int progress, const QString& syncStatus );
+
+ /** See if there is a better parent then this folder */
+ KMFolderCachedImap* findParent( const QString& path, const QString& name );
+
+
+
+public slots:
+ /**
+ * Add the data a KIO::Job retrieves to the buffer
+ */
+ void slotSimpleData(KIO::Job * job, const QByteArray & data);
+
+ /**
+ * Troubleshoot the IMAP cache
+ */
+ void slotTroubleshoot();
+
+ /**
+ * Connected to ListJob::receivedFolders
+ * creates/removes folders
+ */
+ void slotListResult( const QStringList&, const QStringList&,
+ const QStringList&, const QStringList&, const ImapAccountBase::jobData& );
+
+ /**
+ * Connected to ListJob::receivedFolders
+ * creates namespace folders
+ */
+ void slotCheckNamespace( const QStringList&, const QStringList&,
+ const QStringList&, const QStringList&, const ImapAccountBase::jobData& );
+
+private slots:
+ void serverSyncInternal();
+ void slotIncreaseProgress();
+ void slotUpdateLastUid();
+ void slotFolderDeletionOnServerFinished();
+ void slotRescueDone( KMCommand* command );
+
+signals:
+ void folderComplete(KMFolderCachedImap *folder, bool success);
+ void listComplete( KMFolderCachedImap* );
+
+ /** emitted when we enter the state "state" and
+ have to process "number" items (for example messages
+ */
+ void syncState( int state, int number );
+
+private:
+ void setReadOnly( bool readOnly );
+ QString state2String( int state ) const;
+ void rememberDeletion( int );
+ /** Rescue not yet synced messages to a lost+found folder in case
+ syncing is not possible because the folder has been deleted on the
+ server or write access to this folder has been revoked.
+ */
+ KMCommand* rescueUnsyncedMessages();
+ /** Recursive helper function calling the above method. */
+ void rescueUnsyncedMessagesAndDeleteFolder( KMFolder *folder, bool root = true );
+
+ /** State variable for the synchronization mechanism */
+ enum {
+ SYNC_STATE_INITIAL,
+ SYNC_STATE_TEST_ANNOTATIONS,
+ SYNC_STATE_PUT_MESSAGES,
+ SYNC_STATE_UPLOAD_FLAGS,
+ SYNC_STATE_CREATE_SUBFOLDERS,
+ SYNC_STATE_LIST_NAMESPACES,
+ SYNC_STATE_LIST_SUBFOLDERS,
+ SYNC_STATE_LIST_SUBFOLDERS2,
+ SYNC_STATE_DELETE_SUBFOLDERS,
+ SYNC_STATE_LIST_MESSAGES,
+ SYNC_STATE_DELETE_MESSAGES,
+ SYNC_STATE_EXPUNGE_MESSAGES,
+ SYNC_STATE_GET_MESSAGES,
+ SYNC_STATE_HANDLE_INBOX,
+ SYNC_STATE_GET_USERRIGHTS,
+ SYNC_STATE_GET_ANNOTATIONS,
+ SYNC_STATE_SET_ANNOTATIONS,
+ SYNC_STATE_GET_ACLS,
+ SYNC_STATE_SET_ACLS,
+ SYNC_STATE_GET_QUOTA,
+ SYNC_STATE_FIND_SUBFOLDERS,
+ SYNC_STATE_SYNC_SUBFOLDERS,
+ SYNC_STATE_CHECK_UIDVALIDITY,
+ SYNC_STATE_RENAME_FOLDER
+ } mSyncState;
+
+ int mProgress;
+ int mStatusFlagsJobs;
+
+ QString mUidValidity;
+ QString mImapPath;
+ imapState mContentState, mSubfolderState;
+ QStringList mSubfolderNames, mSubfolderPaths,
+ mSubfolderMimeTypes, mSubfolderAttributes;
+ QString mFolderAttributes;
+ QString mAnnotationFolderType;
+ IncidencesFor mIncidencesFor;
+
+ bool mHasInbox;
+ bool mIsSelected;
+ bool mCheckFlags;
+ bool mReadOnly;
+ mutable QGuardedPtr<KMAcctCachedImap> mAccount;
+
+ QIntDict<int> uidsOnServer;
+ QValueList<ulong> uidsForDeletionOnServer;
+ QValueList<KMail::CachedImapJob::MsgForDownload> mMsgsForDownload;
+ QValueList<ulong> mUidsForDownload;
+ QStringList foldersForDeletionOnServer;
+
+ QValueList<KMFolderCachedImap*> mSubfoldersForSync;
+ KMFolderCachedImap* mCurrentSubfolder;
+
+ /** Mapping uid -> index
+ Keep updated in addMsg, take and removeMsg. This is used to lookup
+ whether a mail is present locally or not. */
+ QMap<ulong,int> uidMap;
+ bool uidMapDirty;
+ void reloadUidMap();
+ int uidWriteTimer;
+
+ /** This is the last uid that we have seen from the server on the last
+ sync. It is crucially important that this is correct at all times
+ and not bumped up permaturely, as it is the watermark which is used
+ to discern message which are not present locally, because they were
+ deleted locally and now need to be deleted from the server,
+ from those which are new and need to be downloaded. Sucessfull
+ downloading of all pending mail from the server sets this. Between
+ invocations it is stored on disk in the uidcache file. It must not
+ change during a sync. */
+ ulong mLastUid;
+ /** The highest id encountered while syncing. Once the sync process has
+ successfully downloaded all pending mail and deleted on the server
+ all messages that were removed locally, this will become the new
+ mLastUid. See above for details. */
+ ulong mTentativeHighestUid;
+
+ /** Used to determine whether listing messages yielded a sensible result.
+ * Only then is the deletion o messages (which relies on succesful
+ * listing) attempted, during the sync. */
+ bool mFoundAnIMAPDigest;
+
+ int mUserRights, mOldUserRights;
+ ACLList mACLList;
+
+ bool mSilentUpload;
+ bool mFolderRemoved;
+ //bool mHoldSyncs;
+ bool mRecurse;
+ /** Set to true by setStatus. Indicates that the client has changed
+ the status of at least one mail. The mail flags will therefore be
+ uploaded to the server, overwriting the server's notion of the status
+ of the mails in this folder. */
+ bool mStatusChangedLocally;
+ /// Set to true when the foldertype annotation needs to be set on the next sync
+ bool mAnnotationFolderTypeChanged;
+ /// Set to true when the "incidences-for" annotation needs to be set on the next sync
+ bool mIncidencesForChanged;
+
+ QStringList mNamespacesToList;
+ int mNamespacesToCheck;
+ bool mPersonalNamespacesCheckDone;
+ QString mImapPathCreation;
+
+ QuotaInfo mQuotaInfo;
+ QMap<ulong,void*> mDeletedUIDsSinceLastSync;
+ bool mAlarmsBlocked;
+
+ QValueList<KMFolder*> mToBeDeletedAfterRescue;
+ int mRescueCommandCount;
+
+ int mPermanentFlags;
+};
+
+#endif /*kmfoldercachedimap_h*/