[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