From 6933fb8a30cf17ae90394fca5114b8e600ef2cfd Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 23 Apr 2006 08:48:19 +0000 Subject: [PATCH] Folder deletion. --- ChangeLog | 5 ++++ src/net/imap/IMAPFolder.cpp | 37 ++++++++++++++++++++++++++ src/net/maildir/maildirFolder.cpp | 36 +++++++++++++++++++++++++ src/net/maildir/maildirUtils.cpp | 41 +++++++++++++++++++++++++++++ src/net/pop3/POP3Folder.cpp | 6 +++++ vmime/net/folder.hpp | 31 ++++++++++++++++++++++ vmime/net/imap/IMAPFolder.hpp | 2 ++ vmime/net/maildir/maildirFolder.hpp | 2 ++ vmime/net/maildir/maildirUtils.hpp | 6 +++++ vmime/net/pop3/POP3Folder.hpp | 2 ++ 10 files changed, 168 insertions(+) diff --git a/ChangeLog b/ChangeLog index e9d59b68..e7a0ebc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,11 @@ VERSION 0.8.1cvs ================ +2006-04-23 Vincent Richard + + * Added vmime::net::folder::destroy() to delete folders on IMAP and + maildir stores. + 2006-04-18 Vincent Richard * Renamed 'byte' to 'byte_t' to fix compilation problems on Fedora diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp index 0179620b..09d33b68 100644 --- a/src/net/imap/IMAPFolder.cpp +++ b/src/net/imap/IMAPFolder.cpp @@ -371,6 +371,43 @@ void IMAPFolder::create(const int type) } +void IMAPFolder::destroy() +{ + ref store = m_store.acquire(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + if (isOpen()) + throw exceptions::illegal_state("Folder is open"); + + const string mailbox = IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath()); + + std::ostringstream oss; + oss << "DELETE " << IMAPUtils::quoteString(mailbox); + + m_connection->send(true, oss.str(), true); + + + utility::auto_ptr resp(m_connection->readResponse()); + + if (resp->isBad() || resp->response_done()->response_tagged()-> + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) + { + throw exceptions::command_error("DELETE", + m_connection->getParser()->lastLine(), "bad response"); + } + + // Notify folder deleted + events::folderEvent event + (thisRef().dynamicCast (), + events::folderEvent::TYPE_DELETED, m_path, m_path); + + notifyFolder(event); +} + + const bool IMAPFolder::exists() { ref store = m_store.acquire(); diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp index 7e596382..dc89f131 100644 --- a/src/net/maildir/maildirFolder.cpp +++ b/src/net/maildir/maildirFolder.cpp @@ -242,6 +242,42 @@ void maildirFolder::create(const int /* type */) } +void maildirFolder::destroy() +{ + ref store = m_store.acquire(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (isOpen()) + throw exceptions::illegal_state("Folder is open"); + + // Delete 'folder' and '.folder.directory' directories + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); + + ref rootDir = fsf->create + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT)); + ref contDir = fsf->create + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); + + try + { + maildirUtils::recursiveFSDelete(rootDir); + maildirUtils::recursiveFSDelete(contDir); + } + catch (std::exception&) + { + // Ignore exception: anyway, we can't recover from this... + } + + // Notify folder deleted + events::folderEvent event + (thisRef().dynamicCast (), + events::folderEvent::TYPE_DELETED, m_path, m_path); + + notifyFolder(event); +} + + const bool maildirFolder::exists() { ref store = m_store.acquire(); diff --git a/src/net/maildir/maildirUtils.cpp b/src/net/maildir/maildirUtils.cpp index c0594a31..00a9a7b1 100644 --- a/src/net/maildir/maildirUtils.cpp +++ b/src/net/maildir/maildirUtils.cpp @@ -22,6 +22,9 @@ #include "vmime/utility/random.hpp" +#include "vmime/exception.hpp" +#include "vmime/platformDependant.hpp" + namespace vmime { namespace net { @@ -212,6 +215,44 @@ const utility::file::path::component maildirUtils::generateId() } +void maildirUtils::recursiveFSDelete(ref dir) +{ + ref files = dir->getFiles(); + + // First, delete files and subdirectories in this directory + while (files->hasMoreElements()) + { + ref file = files->nextElement(); + + if (file->isDirectory()) + { + maildirUtils::recursiveFSDelete(file); + } + else + { + try + { + file->remove(); + } + catch (exceptions::filesystem_exception&) + { + // Ignore + } + } + } + + // Then, delete this (empty) directory + try + { + dir->remove(); + } + catch (exceptions::filesystem_exception&) + { + // Ignore + } +} + + // // messageIdComparator diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp index 657e1bdd..7ef4aa12 100644 --- a/src/net/pop3/POP3Folder.cpp +++ b/src/net/pop3/POP3Folder.cpp @@ -184,6 +184,12 @@ void POP3Folder::create(const int /* type */) } +void POP3Folder::destroy() +{ + throw exceptions::operation_not_supported(); +} + + const bool POP3Folder::exists() { ref store = m_store.acquire(); diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp index 5edba493..a6427c85 100644 --- a/vmime/net/folder.hpp +++ b/vmime/net/folder.hpp @@ -132,18 +132,21 @@ public: * is not available, a more restricted mode will be selected automatically. * If set to true and if the requested mode is not available, the opening * will fail. + * @throw net_exception if an error occurs */ virtual void open(const int mode, bool failIfModeIsNotAvailable = false) = 0; /** Close this folder. * * @param expunge if set to true, deleted messages are expunged + * @throw net_exception if an error occurs */ virtual void close(const bool expunge) = 0; /** Create this folder. * * @param type folder type (see folder::Types) + * @throw net_exception if an error occurs */ virtual void create(const int type) = 0; @@ -153,6 +156,13 @@ public: */ virtual const bool exists() = 0; + /** Delete this folder. + * The folder should be closed before attempting to delete it. + * + * @throw net_exception if an error occurs + */ + virtual void destroy() = 0; + /** Test whether this folder is open. * * @return true if the folder is open, false otherwise @@ -163,6 +173,7 @@ public: * * @param num message sequence number * @return a new object referencing the specified message + * @throw net_exception if an error occurs */ virtual ref getMessage(const int num) = 0; @@ -171,6 +182,7 @@ public: * @param from sequence number of the first message to get * @param to sequence number of the last message to get * @return new objects referencing the specified messages + * @throw net_exception if an error occurs */ virtual std::vector > getMessages(const int from = 1, const int to = -1) = 0; @@ -178,6 +190,7 @@ public: * * @param nums sequence numbers of the messages to delete * @return new objects referencing the specified messages + * @throw net_exception if an error occurs */ virtual std::vector > getMessages(const std::vector & nums) = 0; @@ -191,6 +204,7 @@ public: * * @param name sub-folder name * @return a new object referencing the specified folder + * @throw net_exception if an error occurs */ virtual ref getFolder(const folder::path::component& name) = 0; @@ -199,18 +213,21 @@ public: * @param recursive if set to true, all the descendant are returned. * If set to false, only the direct children are returned. * @return list of sub-folders + * @throw net_exception if an error occurs */ virtual std::vector > getFolders(const bool recursive = false) = 0; /** Rename (move) this folder to another location. * * @param newPath new path of the folder + * @throw net_exception if an error occurs */ virtual void rename(const folder::path& newPath) = 0; /** Remove a message in this folder. * * @param num sequence number of the message to delete + * @throw net_exception if an error occurs */ virtual void deleteMessage(const int num) = 0; @@ -218,12 +235,14 @@ public: * * @param from sequence number of the first message to delete * @param to sequence number of the last message to delete + * @throw net_exception if an error occurs */ virtual void deleteMessages(const int from = 1, const int to = -1) = 0; /** Remove one or more messages from this folder. * * @param nums sequence numbers of the messages to delete + * @throw net_exception if an error occurs */ virtual void deleteMessages(const std::vector & nums) = 0; @@ -233,6 +252,7 @@ public: * @param to sequence number of the last message to modify * @param flags set of flags (see message::Flags) * @param mode indicate how to treat old and new flags (see message::FlagsModes) + * @throw net_exception if an error occurs */ virtual void setMessageFlags(const int from, const int to, const int flags, const int mode = message::FLAG_MODE_SET) = 0; @@ -241,6 +261,7 @@ public: * @param nums sequence numbers of the messages to modify * @param flags set of flags (see message::Flags) * @param mode indicate how to treat old and new flags (see message::FlagsModes) + * @throw net_exception if an error occurs */ virtual void setMessageFlags(const std::vector & nums, const int flags, const int mode = message::FLAG_MODE_SET) = 0; @@ -250,6 +271,7 @@ public: * @param flags flags for the new message * @param date date/time for the new message (if NULL, the current time is used) * @param progress progress listener, or NULL if not used + * @throw net_exception if an error occurs */ virtual void addMessage(ref msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL) = 0; @@ -260,6 +282,7 @@ public: * @param flags flags for the new message * @param date date/time for the new message (if NULL, the current time is used) * @param progress progress listener, or NULL if not used + * @throw net_exception if an error occurs */ virtual void addMessage(utility::inputStream& is, const int size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL) = 0; @@ -267,6 +290,7 @@ public: * * @param dest destination folder path * @param num sequence number of the message to copy + * @throw net_exception if an error occurs */ virtual void copyMessage(const folder::path& dest, const int num) = 0; @@ -275,6 +299,7 @@ public: * @param dest destination folder path * @param from sequence number of the first message to copy * @param to sequence number of the last message to copy + * @throw net_exception if an error occurs */ virtual void copyMessages(const folder::path& dest, const int from = 1, const int to = -1) = 0; @@ -282,6 +307,7 @@ public: * * @param dest destination folder path * @param nums sequence numbers of the messages to copy + * @throw net_exception if an error occurs */ virtual void copyMessages(const folder::path& dest, const std::vector & nums) = 0; @@ -289,10 +315,13 @@ public: * * @param count will receive the number of messages in the folder * @param unseen will receive the number of unseen messages in the folder + * @throw net_exception if an error occurs */ virtual void status(int& count, int& unseen) = 0; /** Expunge deleted messages. + * + * @throw net_exception if an error occurs */ virtual void expunge() = 0; @@ -335,6 +364,7 @@ public: * @param msg list of message sequence numbers * @param options objects to fetch (combination of folder::FetchOptions flags) * @param progress progress listener, or NULL if not used + * @throw net_exception if an error occurs */ virtual void fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress = NULL) = 0; @@ -342,6 +372,7 @@ public: * * @param msg the message * @param options objects to fetch (combination of folder::FetchOptions flags) + * @throw net_exception if an error occurs */ virtual void fetchMessage(ref msg, const int options) = 0; diff --git a/vmime/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp index 5662c349..2ad695f0 100644 --- a/vmime/net/imap/IMAPFolder.hpp +++ b/vmime/net/imap/IMAPFolder.hpp @@ -77,6 +77,8 @@ public: const bool exists(); + void destroy(); + const bool isOpen() const; ref getMessage(const int num); diff --git a/vmime/net/maildir/maildirFolder.hpp b/vmime/net/maildir/maildirFolder.hpp index 1e073b47..d7a7d3be 100644 --- a/vmime/net/maildir/maildirFolder.hpp +++ b/vmime/net/maildir/maildirFolder.hpp @@ -78,6 +78,8 @@ public: const bool exists(); + void destroy(); + const bool isOpen() const; ref getMessage(const int num); diff --git a/vmime/net/maildir/maildirUtils.hpp b/vmime/net/maildir/maildirUtils.hpp index 94484bd5..4f163bd5 100644 --- a/vmime/net/maildir/maildirUtils.hpp +++ b/vmime/net/maildir/maildirUtils.hpp @@ -148,6 +148,12 @@ public: */ static const utility::file::path::component generateId(); + /** Recursively delete a directory on the file system. + * + * @param dir directory to delete + */ + static void recursiveFSDelete(ref dir); + private: static const vmime::word TMP_DIR; diff --git a/vmime/net/pop3/POP3Folder.hpp b/vmime/net/pop3/POP3Folder.hpp index 28a63c93..386f9ae7 100644 --- a/vmime/net/pop3/POP3Folder.hpp +++ b/vmime/net/pop3/POP3Folder.hpp @@ -76,6 +76,8 @@ public: const bool exists(); + void destroy(); + const bool isOpen() const; ref getMessage(const int num);