[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdepim-runtime/KDE/4.11] resources/imap: Close IMAP mailbox before deleting it
From: Dan_Vrátil <dvratil () redhat ! com>
Date: 2013-10-24 11:52:38
Message-ID: E1VZJSw-0007Y4-BC () scm ! kde ! org
[Download RAW message or body]
Git commit 4b23d9be3559c06cb65c25fa67cca2da426dcd47 by Dan Vrátil.
Committed on 24/10/2013 at 11:46.
Pushed by dvratil into branch 'KDE/4.11'.
Close IMAP mailbox before deleting it
Some IMAP servers don't allow deleting a currently SELECTed
mailbox, so we close it before DELETEing it.
REVIEW: 112786
BUG: 324932
FIXED-IN: 4.11.3
M +70 -47 resources/imap/removecollectionrecursivetask.cpp
M +5 -1 resources/imap/removecollectionrecursivetask.h
M +29 -1 resources/imap/removecollectiontask.cpp
M +5 -0 resources/imap/removecollectiontask.h
http://commits.kde.org/kdepim-runtime/4b23d9be3559c06cb65c25fa67cca2da426dcd47
diff --git a/resources/imap/removecollectionrecursivetask.cpp \
b/resources/imap/removecollectionrecursivetask.cpp index aa74a73..b689628 100644
--- a/resources/imap/removecollectionrecursivetask.cpp
+++ b/resources/imap/removecollectionrecursivetask.cpp
@@ -26,11 +26,14 @@
#include <kimap/expungejob.h>
#include <kimap/selectjob.h>
#include <kimap/storejob.h>
+#include <kimap/closejob.h>
#include <klocale.h>
+Q_DECLARE_METATYPE( KIMAP::DeleteJob* )
+
RemoveCollectionRecursiveTask::RemoveCollectionRecursiveTask( \
ResourceStateInterface::Ptr resource, QObject *parent ) : ResourceTask( \
CancelIfNoSession, resource, parent ),
- mSession( 0 ), mRunningDeleteJobs( 0 ), mFolderFound( false )
+ mSession( 0 ), mFolderFound( false )
{
}
@@ -59,14 +62,14 @@ void RemoveCollectionRecursiveTask::onMailBoxesReceived( const \
QList< KIMAP::Mai
// We have to delete the deepest-nested folders first, so
// we use a map here that has the level of nesting as key.
- QMap<int, QList<KIMAP::MailBoxDescriptor> > foldersToDelete;
+ QMultiMap<int, KIMAP::MailBoxDescriptor > foldersToDelete;
for ( int i = 0; i < descriptors.size(); ++i ) {
const KIMAP::MailBoxDescriptor descriptor = descriptors[ i ];
if ( descriptor.name == mailBox || descriptor.name.startsWith( mailBox + \
descriptor.separator ) ) { // a sub folder to delete
const QStringList pathParts = descriptor.name.split( descriptor.separator );
- foldersToDelete[ pathParts.count() ].append( descriptor );
+ foldersToDelete.insert( pathParts.count(), descriptor );
}
}
@@ -77,43 +80,67 @@ void RemoveCollectionRecursiveTask::onMailBoxesReceived( const \
QList< KIMAP::Mai mFolderFound = true;
// Now start the actual deletion work
- QMapIterator<int, QList<KIMAP::MailBoxDescriptor> > it( foldersToDelete );
- it.toBack(); // we start with largest nesting value first
- while ( it.hasPrevious() ) {
- it.previous();
-
- foreach ( const KIMAP::MailBoxDescriptor &descriptor, it.value() ) {
- // first select the mailbox
- KIMAP::SelectJob *selectJob = new KIMAP::SelectJob( mSession );
- selectJob->setMailBox( descriptor.name );
- connect( selectJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
- selectJob->start();
-
- // mark all items as deleted
- KIMAP::ImapSet allItems;
- allItems.add( KIMAP::ImapInterval( 1, 0 ) ); // means 1:*
- KIMAP::StoreJob *storeJob = new KIMAP::StoreJob( mSession );
- storeJob->setSequenceSet( allItems );
- storeJob->setFlags( KIMAP::MessageFlags() << Akonadi::MessageFlags::Deleted );
- storeJob->setMode( KIMAP::StoreJob::AppendFlags );
- connect( storeJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
- storeJob->start();
-
- // expunge the mailbox
- KIMAP::ExpungeJob *expungeJob = new KIMAP::ExpungeJob( mSession );
- connect( expungeJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
- expungeJob->start();
-
- // finally delete the mailbox
- KIMAP::DeleteJob *deleteJob = new KIMAP::DeleteJob( mSession );
- deleteJob->setMailBox( descriptor.name );
- connect( deleteJob, SIGNAL(result(KJob*)), SLOT(onDeleteJobDone(KJob*)) );
- mRunningDeleteJobs++;
- deleteJob->start();
- }
+ mFolderIterator.reset( new QMapIterator<int, KIMAP::MailBoxDescriptor >( \
foldersToDelete ) ); + mFolderIterator->toBack(); // we start with largest nesting \
value first +
+ deleteNextMailbox();
+}
+
+void RemoveCollectionRecursiveTask::deleteNextMailbox()
+{
+ if ( !mFolderIterator->hasPrevious() ) {
+ changeProcessed(); // finish the job
+ return;
}
+
+ mFolderIterator->previous();
+ const KIMAP::MailBoxDescriptor &descriptor = mFolderIterator->value();
+ kDebug() << descriptor.name;
+
+ // first select the mailbox
+ KIMAP::SelectJob *selectJob = new KIMAP::SelectJob( mSession );
+ selectJob->setMailBox( descriptor.name );
+ connect( selectJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
+ selectJob->start();
+
+ // mark all items as deleted
+ KIMAP::ImapSet allItems;
+ allItems.add( KIMAP::ImapInterval( 1, 0 ) ); // means 1:*
+ KIMAP::StoreJob *storeJob = new KIMAP::StoreJob( mSession );
+ storeJob->setSequenceSet( allItems );
+ storeJob->setFlags( KIMAP::MessageFlags() << Akonadi::MessageFlags::Deleted );
+ storeJob->setMode( KIMAP::StoreJob::AppendFlags );
+ connect( storeJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
+ storeJob->start();
+
+ // expunge the mailbox
+ KIMAP::ExpungeJob *expungeJob = new KIMAP::ExpungeJob( mSession );
+ connect( expungeJob, SIGNAL(result(KJob*)), SLOT(onJobDone(KJob*)) );
+ expungeJob->start();
+
+ // Close the mailbox - some servers refuse to delete an opened mailbox
+ KIMAP::CloseJob *closeJob = new KIMAP::CloseJob( mSession );
+ closeJob->setProperty( "folderDescriptor", descriptor.name );
+ connect( closeJob, SIGNAL(result(KJob*)), SLOT(onCloseJobDone(KJob*)) );
+ closeJob->start();
}
+void RemoveCollectionRecursiveTask::onCloseJobDone( KJob* job )
+{
+ if ( job->error() ) {
+ changeProcessed();
+ kDebug( 5327 ) << "Failed to close the folder, resync the folder tree";
+ emitWarning( i18n( "Failed to delete the folder, restoring folder list." ) );
+ synchronizeCollectionTree();
+ } else {
+ KIMAP::DeleteJob *deleteJob = new KIMAP::DeleteJob( mSession );
+ deleteJob->setMailBox( job->property( "folderDescriptor" ).toString() );
+ connect( deleteJob, SIGNAL(result(KJob*)), SLOT(onDeleteJobDone(KJob*)) );
+ deleteJob->start();
+ }
+}
+
+
void RemoveCollectionRecursiveTask::onDeleteJobDone( KJob* job )
{
if ( job->error() ) {
@@ -123,27 +150,23 @@ void RemoveCollectionRecursiveTask::onDeleteJobDone( KJob* job \
)
emitWarning( i18n( "Failed to delete the folder, restoring folder list." ) );
synchronizeCollectionTree();
} else {
- mRunningDeleteJobs--;
-
- if ( mRunningDeleteJobs == 0 ) {
- changeProcessed(); // finished job
- }
+ deleteNextMailbox();
}
}
void RemoveCollectionRecursiveTask::onJobDone( KJob* job )
{
- if ( job->error() ) {
+ if ( job->error() ) {
changeProcessed();
kDebug( 5327 ) << "Failed to delete the folder, resync the folder tree";
emitWarning( i18n( "Failed to delete the folder, restoring folder list." ) );
synchronizeCollectionTree();
} else if ( !mFolderFound ) {
- changeProcessed();
- kDebug( 5327 ) << "Failed to find the folder to be deleted, resync the folder \
tree";
- emitWarning( i18n( "Failed to find the folder to be deleted, restoring folder \
list." ) );
- synchronizeCollectionTree();
+ changeProcessed();
+ kDebug( 5327 ) << "Failed to find the folder to be deleted, resync the folder \
tree"; + emitWarning( i18n( "Failed to find the folder to be deleted, restoring \
folder list." ) ); + synchronizeCollectionTree();
}
}
diff --git a/resources/imap/removecollectionrecursivetask.h \
b/resources/imap/removecollectionrecursivetask.h index b42c4e6..d759c8c 100644
--- a/resources/imap/removecollectionrecursivetask.h
+++ b/resources/imap/removecollectionrecursivetask.h
@@ -37,6 +37,7 @@ public:
private slots:
void onMailBoxesReceived( const QList<KIMAP::MailBoxDescriptor> &descriptors,
const QList< QList<QByteArray> > &flags );
+ void onCloseJobDone( KJob *job );
void onDeleteJobDone( KJob *job );
void onJobDone( KJob *job );
@@ -44,9 +45,12 @@ protected:
virtual void doStart( KIMAP::Session *session );
private:
+ void deleteNextMailbox();
+
KIMAP::Session *mSession;
- uint mRunningDeleteJobs;
bool mFolderFound;
+
+ QScopedPointer< QMapIterator<int, KIMAP::MailBoxDescriptor > > mFolderIterator;
};
#endif
diff --git a/resources/imap/removecollectiontask.cpp \
b/resources/imap/removecollectiontask.cpp index b258fb1..6ebf6d7 100644
--- a/resources/imap/removecollectiontask.cpp
+++ b/resources/imap/removecollectiontask.cpp
@@ -25,6 +25,7 @@
#include <KDE/KLocale>
#include <kimap/deletejob.h>
+#include <kimap/closejob.h>
#include <kimap/session.h>
RemoveCollectionTask::RemoveCollectionTask( ResourceStateInterface::Ptr resource, \
QObject *parent ) @@ -39,8 +40,35 @@ RemoveCollectionTask::~RemoveCollectionTask()
void RemoveCollectionTask::doStart( KIMAP::Session *session )
{
- const QString mailBox = mailBoxForCollection( collection() );
+ // Some IMAP servers don't allow deleting an opened mailbox, so make sure
+ // it's not opened (https://bugs.kde.org/show_bug.cgi?id=324932)
+ if ( session->selectedMailBox() != mailBoxForCollection( collection() ) ) {
+ doDelete( session );
+ return;
+ }
+
+ KIMAP::CloseJob *close = new KIMAP::CloseJob( session );
+ connect( close, SIGNAL(result(KJob*)),
+ this, SLOT(onCloseDone(KJob*)) );
+ close->start();
+}
+
+void RemoveCollectionTask::onCloseDone( KJob *job )
+{
+ if ( job->error() ) {
+ changeProcessed();
+ kDebug( 5327 ) << "Failed to delete the folder, resync the folder tree";
+ emitWarning( i18n( "Failed to delete the folder, restoring folder list." ) );
+ synchronizeCollectionTree();
+ } else {
+ KIMAP::CloseJob *close = dynamic_cast<KIMAP::CloseJob*>( job );
+ doDelete( close->session() );
+ }
+}
+void RemoveCollectionTask::doDelete( KIMAP::Session *session )
+{
+ const QString mailBox = mailBoxForCollection( collection() );
KIMAP::DeleteJob *job = new KIMAP::DeleteJob( session );
job->setMailBox( mailBox );
diff --git a/resources/imap/removecollectiontask.h \
b/resources/imap/removecollectiontask.h index 48335d3..a9949d6 100644
--- a/resources/imap/removecollectiontask.h
+++ b/resources/imap/removecollectiontask.h
@@ -33,10 +33,15 @@ public:
virtual ~RemoveCollectionTask();
private slots:
+ void onCloseDone(KJob*);
void onDeleteDone( KJob *job );
protected:
virtual void doStart( KIMAP::Session *session );
+
+private:
+ void doDelete( KIMAP::Session *session );
+
};
#endif
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic