From a4251085d24e870104e1b3bf76c66ba71a69a78b Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Wed, 22 Dec 2004 11:01:17 +0000 Subject: [PATCH] Done rename() operation on 'maildir' + fixed some bugs/limitations in maildir/IMAP. --- src/messaging/IMAPFolder.cpp | 8 ++- src/messaging/maildirFolder.cpp | 111 ++++++++++++++++++++++++++------ src/messaging/maildirStore.cpp | 20 +++++- 3 files changed, 116 insertions(+), 23 deletions(-) diff --git a/src/messaging/IMAPFolder.cpp b/src/messaging/IMAPFolder.cpp index 5ae268a2..4a3cc5fb 100644 --- a/src/messaging/IMAPFolder.cpp +++ b/src/messaging/IMAPFolder.cpp @@ -323,6 +323,8 @@ void IMAPFolder::create(const int type) throw exceptions::illegal_state("Folder is open"); else if (exists()) throw exceptions::illegal_state("Folder already exists"); + else if (!m_store->isValidFolderName(m_name)) + throw exceptions::invalid_folder_name(); // Emit the "CREATE" command // @@ -1258,10 +1260,12 @@ void IMAPFolder::rename(const folder::path& newPath) { if (!m_store) throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder open"); + else if (m_path.isEmpty() || newPath.isEmpty()) + throw exceptions::illegal_operation("Cannot rename root folder"); else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") throw exceptions::illegal_operation("Cannot rename 'INBOX' folder"); + else if (!m_store->isValidFolderName(newPath.getLastComponent())) + throw exceptions::invalid_folder_name(); // Build the request text std::ostringstream command; diff --git a/src/messaging/maildirFolder.cpp b/src/messaging/maildirFolder.cpp index fb511785..c92fe85f 100644 --- a/src/messaging/maildirFolder.cpp +++ b/src/messaging/maildirFolder.cpp @@ -124,7 +124,7 @@ void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) else if (isOpen()) throw exceptions::illegal_state("Folder is already open"); else if (!exists()) - throw exceptions::illegal_state("Folder already exists"); + throw exceptions::illegal_state("Folder does not exist"); scanFolder(); @@ -141,6 +141,9 @@ void maildirFolder::close(const bool expunge) if (!isOpen()) throw exceptions::illegal_state("Folder not open"); + if (expunge) + this->expunge(); + m_open = false; m_mode = -1; @@ -176,7 +179,7 @@ void maildirFolder::unregisterMessage(maildirMessage* msg) } -void maildirFolder::create(const int type) +void maildirFolder::create(const int /* type */) { if (!m_store) throw exceptions::illegal_state("Store disconnected"); @@ -184,21 +187,8 @@ void maildirFolder::create(const int type) throw exceptions::illegal_state("Folder is open"); else if (exists()) throw exceptions::illegal_state("Folder already exists"); - - // Folder name cannot start with '.' - if (!m_path.isEmpty()) - { - const path::component& comp = m_path.getLastComponent(); - - const int length = comp.getBuffer().length(); - int pos = 0; - - while ((pos < length) && (comp.getBuffer()[pos] == '.')) - ++pos; - - if (pos != 0) - throw exceptions::invalid_folder_name("Name cannot start with '.'"); - } + else if (!m_store->isValidFolderName(m_name)) + throw exceptions::invalid_folder_name(); // Create directory on file system try @@ -521,7 +511,92 @@ void maildirFolder::listFolders(std::vector & list, const bool recursiv void maildirFolder::rename(const folder::path& newPath) { - // TODO + if (!m_store) + throw exceptions::illegal_state("Store disconnected"); + else if (m_path.isEmpty() || newPath.isEmpty()) + throw exceptions::illegal_operation("Cannot rename root folder"); + else if (!m_store->isValidFolderName(newPath.getLastComponent())) + throw exceptions::invalid_folder_name(); + + // Rename the directory on the file system + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); + + utility::auto_ptr rootDir = fsf->create + (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); + utility::auto_ptr contDir = fsf->create + (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); + + try + { + const utility::file::path newRootPath = + maildirUtils::getFolderFSPath(m_store, newPath, maildirUtils::FOLDER_PATH_ROOT); + const utility::file::path newContPath = + maildirUtils::getFolderFSPath(m_store, newPath, maildirUtils::FOLDER_PATH_CONTAINER); + + rootDir->rename(newRootPath); + + // Container directory may not exist, so ignore error when trying to rename it + try + { + contDir->rename(newContPath); + } + catch (exceptions::filesystem_exception& e) + { + // Ignore + } + } + catch (exceptions::filesystem_exception& e) + { + // Revert to old location + const utility::file::path rootPath = + maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT); + const utility::file::path contPath = + maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER); + + try + { + rootDir->rename(rootPath); + contDir->rename(contPath); + } + catch (exceptions::filesystem_exception& e) + { + // Ignore + } + + throw exceptions::command_error("RENAME", "", "", e); + } + + // Notify folder renamed + folder::path oldPath(m_path); + + m_path = newPath; + m_name = newPath.getLastComponent(); + + events::folderEvent event(this, events::folderEvent::TYPE_RENAMED, oldPath, newPath); + notifyFolder(event); + + // Notify folders with the same path + for (std::list ::iterator it = m_store->m_folders.begin() ; + it != m_store->m_folders.end() ; ++it) + { + if ((*it) != this && (*it)->getFullPath() == oldPath) + { + (*it)->m_path = newPath; + (*it)->m_name = newPath.getLastComponent(); + + events::folderEvent event(*it, events::folderEvent::TYPE_RENAMED, oldPath, newPath); + (*it)->notifyFolder(event); + } + else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) + { + folder::path oldPath((*it)->m_path); + + (*it)->m_path.renameParent(oldPath, newPath); + + events::folderEvent event(*it, events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + (*it)->notifyFolder(event); + } + } } diff --git a/src/messaging/maildirStore.cpp b/src/messaging/maildirStore.cpp index 2f737622..3434321f 100644 --- a/src/messaging/maildirStore.cpp +++ b/src/messaging/maildirStore.cpp @@ -77,9 +77,23 @@ folder* maildirStore::getFolder(const folder::path& path) const bool maildirStore::isValidFolderName(const folder::path::component& name) { - return (platformDependant::getHandler()-> - getFileSystemFactory()->isValidPathComponent(name) && - name.getBuffer().find_first_of(".") == string::npos); + if (!platformDependant::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) + return false; + + const string& buf = name.getBuffer(); + + // Name cannot start/end with spaces + if (stringUtils::trim(buf) != name.getBuffer()) + return false; + + // Name cannot start with '.' + const int length = buf.length(); + int pos = 0; + + while ((pos < length) && (buf[pos] == '.')) + ++pos; + + return (pos == 0); }