diff options
Diffstat (limited to 'src/messaging/maildir')
-rw-r--r-- | src/messaging/maildir/maildirFolder.cpp | 1387 | ||||
-rw-r--r-- | src/messaging/maildir/maildirMessage.cpp | 505 | ||||
-rw-r--r-- | src/messaging/maildir/maildirStore.cpp | 250 | ||||
-rw-r--r-- | src/messaging/maildir/maildirUtils.cpp | 208 |
4 files changed, 0 insertions, 2350 deletions
diff --git a/src/messaging/maildir/maildirFolder.cpp b/src/messaging/maildir/maildirFolder.cpp deleted file mode 100644 index e7a4e2f8..00000000 --- a/src/messaging/maildir/maildirFolder.cpp +++ /dev/null @@ -1,1387 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 Vincent Richard <[email protected]> -// -// 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; either version 2 of -// the License, or (at your option) any later version. -// -// 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., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#include "vmime/messaging/maildir/maildirFolder.hpp" - -#include "vmime/messaging/maildir/maildirStore.hpp" -#include "vmime/messaging/maildir/maildirMessage.hpp" -#include "vmime/messaging/maildir/maildirUtils.hpp" - -#include "vmime/utility/smartPtr.hpp" - -#include "vmime/message.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platformDependant.hpp" - - -namespace vmime { -namespace messaging { -namespace maildir { - - -maildirFolder::maildirFolder(const folder::path& path, weak_ref <maildirStore> store) - : m_store(store), m_path(path), - m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false), m_unreadMessageCount(0), m_messageCount(0) -{ - m_store->registerFolder(this); -} - - -maildirFolder::~maildirFolder() -{ - if (m_store) - { - if (m_open) - close(false); - - m_store->unregisterFolder(this); - } - else if (m_open) - { - close(false); - } -} - - -void maildirFolder::onStoreDisconnected() -{ - m_store = NULL; -} - - -const int maildirFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -const int maildirFolder::getType() -{ - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else - return (TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES); -} - - -const int maildirFolder::getFlags() -{ - int flags = 0; - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - ref <utility::file> rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); - - ref <utility::fileIterator> it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - ref <utility::file> file = it->nextElement(); - - if (maildirUtils::isSubfolderDirectory(*file)) - { - flags |= FLAG_CHILDREN; // Contains at least one sub-folder - break; - } - } - - return (flags); -} - - -const folder::path::component maildirFolder::getName() const -{ - return (m_name); -} - - -const folder::path maildirFolder::getFullPath() const -{ - return (m_path); -} - - -void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder is already open"); - else if (!exists()) - throw exceptions::illegal_state("Folder does not exist"); - - scanFolder(); - - m_open = true; - m_mode = mode; -} - - -void maildirFolder::close(const bool expunge) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (expunge) - this->expunge(); - - m_open = false; - m_mode = -1; - - onClose(); -} - - -void maildirFolder::onClose() -{ - for (std::vector <maildirMessage*>::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { - (*it)->onFolderClosed(); - } - - m_messages.clear(); -} - - -void maildirFolder::registerMessage(maildirMessage* msg) -{ - m_messages.push_back(msg); -} - - -void maildirFolder::unregisterMessage(maildirMessage* msg) -{ - std::vector <maildirMessage*>::iterator it = - std::find(m_messages.begin(), m_messages.end(), msg); - - if (it != m_messages.end()) - m_messages.erase(it); -} - - -void maildirFolder::create(const int /* type */) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - 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(); - - // Create directory on file system - try - { - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - if (!fsf->isValidPath(maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT))) - throw exceptions::invalid_folder_name(); - - ref <utility::file> rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); - - ref <utility::file> newDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_NEW)); - ref <utility::file> tmpDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_TMP)); - ref <utility::file> curDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CUR)); - - rootDir->createDirectory(true); - - newDir->createDirectory(false); - tmpDir->createDirectory(false); - curDir->createDirectory(false); - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::command_error("CREATE", "", "File system exception", e); - } - - // Notify folder created - events::folderEvent event - (thisRef().dynamicCast <folder>(), - events::folderEvent::TYPE_CREATED, m_path, m_path); - - notifyFolder(event); -} - - -const bool maildirFolder::exists() -{ - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - ref <utility::file> rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); - - ref <utility::file> newDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_NEW)); - ref <utility::file> tmpDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_TMP)); - ref <utility::file> curDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CUR)); - - return (rootDir->exists() && rootDir->isDirectory() && - newDir->exists() && newDir->isDirectory() && - tmpDir->exists() && tmpDir->isDirectory() && - curDir->exists() && curDir->isDirectory()); -} - - -const bool maildirFolder::isOpen() const -{ - return (m_open); -} - - -void maildirFolder::scanFolder() -{ - try - { - m_messageCount = 0; - m_unreadMessageCount = 0; - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path newDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_NEW); - ref <utility::file> newDir = fsf->create(newDirPath); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - ref <utility::file> curDir = fsf->create(curDirPath); - - // New received messages (new/) - ref <utility::fileIterator> nit = newDir->getFiles(); - std::vector <utility::file::path::component> newMessageFilenames; - - while (nit->hasMoreElements()) - { - ref <utility::file> file = nit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - newMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Current messages (cur/) - ref <utility::fileIterator> cit = curDir->getFiles(); - std::vector <utility::file::path::component> curMessageFilenames; - - while (cit->hasMoreElements()) - { - ref <utility::file> file = cit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - curMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Update/delete existing messages (found in previous scan) - for (unsigned int i = 0 ; i < m_messageInfos.size() ; ++i) - { - messageInfos& msgInfos = m_messageInfos[i]; - - // NOTE: the flags may have changed (eg. moving from 'new' to 'cur' - // may imply the 'S' flag) and so the filename. That's why we use - // "maildirUtils::messageIdComparator" to compare only the 'unique' - // portion of the filename... - - if (msgInfos.type == messageInfos::TYPE_CUR) - { - const std::vector <utility::file::path::component>::iterator pos = - std::find_if(curMessageFilenames.begin(), curMessageFilenames.end(), - maildirUtils::messageIdComparator(msgInfos.path)); - - // If we cannot find this message in the 'cur' directory, - // it means it has been deleted (and expunged). - if (pos == curMessageFilenames.end()) - { - msgInfos.type = messageInfos::TYPE_DELETED; - } - // Otherwise, update its information. - else - { - msgInfos.path = *pos; - curMessageFilenames.erase(pos); - } - } - } - - m_messageInfos.reserve(m_messageInfos.size() - + newMessageFilenames.size() + curMessageFilenames.size()); - - // Add new messages from 'new': we are responsible to move the files - // from the 'new' directory to the 'cur' directory, and append them - // to our message list. - for (std::vector <utility::file::path::component>::const_iterator - it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) - { - const utility::file::path::component newFilename = - maildirUtils::buildFilename(maildirUtils::extractId(*it), 0); - - // Move messages from 'new' to 'cur' - ref <utility::file> file = fsf->create(newDirPath / *it); - file->rename(curDirPath / newFilename); - - // Append to message list - messageInfos msgInfos; - msgInfos.path = newFilename; - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - } - - // Add new messages from 'cur': the files have already been moved - // from 'new' to 'cur'. Just append them to our message list. - for (std::vector <utility::file::path::component>::const_iterator - it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) - { - // Append to message list - messageInfos msgInfos; - msgInfos.path = *it; - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - } - - // Update message count - int unreadMessageCount = 0; - - for (std::vector <messageInfos>::const_iterator - it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) - { - if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) - ++unreadMessageCount; - } - - m_unreadMessageCount = unreadMessageCount; - m_messageCount = m_messageInfos.size(); - } - catch (exceptions::filesystem_exception&) - { - // Should not happen... - } -} - - -ref <message> maildirFolder::getMessage(const int num) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (num < 1 || num > m_messageCount) - throw exceptions::message_not_found(); - - return vmime::create <maildirMessage> - (thisWeakRef().dynamicCast <maildirFolder>(), num); -} - - -std::vector <ref <message> > maildirFolder::getMessages(const int from, const int to) -{ - const int to2 = (to == -1 ? m_messageCount : to); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (to2 < from || from < 1 || to2 < 1 || from > m_messageCount || to2 > m_messageCount) - throw exceptions::message_not_found(); - - std::vector <ref <message> > v; - - for (int i = from ; i <= to2 ; ++i) - { - v.push_back(vmime::create <maildirMessage> - (thisWeakRef().dynamicCast <maildirFolder>(), i)); - } - - return (v); -} - - -std::vector <ref <message> > maildirFolder::getMessages(const std::vector <int>& nums) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - std::vector <ref <message> > v; - - for (std::vector <int>::const_iterator it = nums.begin() ; it != nums.end() ; ++it) - { - v.push_back(vmime::create <maildirMessage> - (thisWeakRef().dynamicCast <maildirFolder>(), *it)); - } - - return (v); -} - - -const int maildirFolder::getMessageCount() -{ - return (m_messageCount); -} - - -ref <folder> maildirFolder::getFolder(const folder::path::component& name) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - return vmime::create <maildirFolder>(m_path / name, m_store); -} - - -std::vector <ref <folder> > maildirFolder::getFolders(const bool recursive) -{ - if (!isOpen() && !m_store) - throw exceptions::illegal_state("Store disconnected"); - - std::vector <ref <folder> > list; - - listFolders(list, recursive); - - return (list); -} - - -void maildirFolder::listFolders(std::vector <ref <folder> >& list, const bool recursive) -{ - try - { - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - ref <utility::file> rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, - m_path.isEmpty() ? maildirUtils::FOLDER_PATH_ROOT - : maildirUtils::FOLDER_PATH_CONTAINER)); - - if (rootDir->exists()) - { - ref <utility::fileIterator> it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - ref <utility::file> file = it->nextElement(); - - if (maildirUtils::isSubfolderDirectory(*file)) - { - const utility::path subPath = - m_path / file->getFullPath().getLastComponent(); - - ref <maildirFolder> subFolder = - vmime::create <maildirFolder>(subPath, m_store); - - list.push_back(subFolder); - - if (recursive) - subFolder->listFolders(list, true); - } - } - } - else - { - // No sub-folder - } - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::command_error("LIST", "", "", e); - } -} - - -void maildirFolder::rename(const folder::path& newPath) -{ - 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(); - - ref <utility::file> rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); - ref <utility::file> 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 - (thisRef().dynamicCast <folder>(), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - notifyFolder(event); - - // Notify folders with the same path - for (std::list <maildirFolder*>::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)->thisRef().dynamicCast <folder>(), - 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)->thisRef().dynamicCast <folder>(), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); - - (*it)->notifyFolder(event); - } - } -} - - -void maildirFolder::deleteMessage(const int num) -{ - // Mark messages as deleted - setMessageFlags(num, num, message::FLAG_MODE_ADD, message::FLAG_DELETED); -} - - -void maildirFolder::deleteMessages(const int from, const int to) -{ - // Mark messages as deleted - setMessageFlags(from, to, message::FLAG_MODE_ADD, message::FLAG_DELETED); -} - - -void maildirFolder::deleteMessages(const std::vector <int>& nums) -{ - // Mark messages as deleted - setMessageFlags(nums, message::FLAG_MODE_ADD, message::FLAG_DELETED); -} - - -void maildirFolder::setMessageFlags - (const int from, const int to, const int flags, const int mode) -{ - if (from < 1 || (to < from && to != -1)) - throw exceptions::invalid_argument(); - - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Construct the list of message numbers - const int to2 = (to == -1) ? m_messageCount : to; - const int count = to - from + 1; - - std::vector <int> nums; - nums.resize(count); - - for (int i = from, j = 0 ; i <= to2 ; ++i, ++j) - nums[j] = i; - - // Change message flags - setMessageFlagsImpl(nums, flags, mode); - - // Update local flags - switch (mode) - { - case message::FLAG_MODE_ADD: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; - } - } - - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; - } - } - - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->getNumber() >= from && (*it)->getNumber() <= to2 && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; - } - } - - break; - } - - } - - // Notify message flags changed - events::messageChangedEvent event - (thisRef().dynamicCast <folder>(), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); - - // TODO: notify other folders with the same path -} - - -void maildirFolder::setMessageFlags - (const std::vector <int>& nums, const int flags, const int mode) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Sort the list of message numbers - std::vector <int> list; - - list.resize(nums.size()); - std::copy(nums.begin(), nums.end(), list.begin()); - - std::sort(list.begin(), list.end()); - - // Change message flags - setMessageFlagsImpl(list, flags, mode); - - // Update local flags - switch (mode) - { - case message::FLAG_MODE_ADD: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; - } - } - - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; - } - } - - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; - } - } - - break; - } - - } - - // Notify message flags changed - events::messageChangedEvent event - (thisRef().dynamicCast <folder>(), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); - - // TODO: notify other folders with the same path -} - - -void maildirFolder::setMessageFlagsImpl - (const std::vector <int>& nums, const int flags, const int mode) -{ - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - for (std::vector <int>::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int num = *it - 1; - - try - { - const utility::file::path::component path = m_messageInfos[num].path; - ref <utility::file> file = fsf->create(curDirPath / path); - - int newFlags = maildirUtils::extractFlags(path); - - switch (mode) - { - case message::FLAG_MODE_ADD: newFlags |= flags; break; - case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break; - default: - case message::FLAG_MODE_SET: newFlags = flags; break; - } - - const utility::file::path::component newPath = maildirUtils::buildFilename - (maildirUtils::extractId(path), newFlags); - - file->rename(curDirPath / newPath); - - if (flags & message::FLAG_DELETED) - m_messageInfos[num].type = messageInfos::TYPE_DELETED; - else - m_messageInfos[num].type = messageInfos::TYPE_CUR; - - m_messageInfos[num].path = newPath; - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not important) - } - } -} - - -void maildirFolder::addMessage(ref <vmime::message> msg, const int flags, - vmime::datetime* date, utility::progressionListener* progress) -{ - std::ostringstream oss; - utility::outputStreamAdapter ossAdapter(oss); - - msg->generate(ossAdapter); - - const std::string& str = oss.str(); - utility::inputStreamStringAdapter strAdapter(str); - - addMessage(strAdapter, str.length(), flags, date, progress); -} - - -void maildirFolder::addMessage(utility::inputStream& is, const int size, - const int flags, vmime::datetime* /* date */, utility::progressionListener* progress) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path tmpDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_TMP); - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), - ((flags == message::FLAG_UNDEFINED) ? 0 : flags)); - - try - { - ref <utility::file> tmpDir = fsf->create(tmpDirPath); - tmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - ref <utility::file> curDir = fsf->create(curDirPath); - curDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - // Actually add the message - copyMessageImpl(tmpDirPath, curDirPath, filename, is, size, progress); - - // Append the message to the cache list - messageInfos msgInfos; - msgInfos.path = filename; - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - m_messageCount++; - - if ((flags == message::FLAG_UNDEFINED) || !(flags & message::FLAG_SEEN)) - m_unreadMessageCount++; - - // Notification - std::vector <int> nums; - nums.push_back(m_messageCount); - - events::messageCountEvent event - (thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list <maildirFolder*>::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - events::messageCountEvent event - ((*it)->thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, - const utility::file::path& curDirPath, const utility::file::path::component& filename, - utility::inputStream& is, const utility::stream::size_type size, - utility::progressionListener* progress) -{ - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - ref <utility::file> file = fsf->create(tmpDirPath / filename); - - if (progress) - progress->start(size); - - // First, write the message into 'tmp'... - try - { - file->createFile(); - - ref <utility::fileWriter> fw = file->getFileWriter(); - ref <utility::outputStream> os = fw->getOutputStream(); - - utility::stream::value_type buffer[65536]; - utility::stream::size_type total = 0; - - while (!is.eof()) - { - const utility::stream::size_type read = is.read(buffer, sizeof(buffer)); - - if (read != 0) - { - os->write(buffer, read); - total += read; - } - - if (progress) - progress->progress(total, size); - } - } - catch (exception& e) - { - if (progress) - progress->stop(size); - - // Delete temporary file - try - { - ref <utility::file> file = fsf->create(tmpDirPath / filename); - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - - throw exceptions::command_error("ADD", "", "", e); - } - - // ...then, move it to 'cur' - try - { - file->rename(curDirPath / filename); - } - catch (exception& e) - { - if (progress) - progress->stop(size); - - // Delete temporary file - try - { - ref <utility::file> file = fsf->create(tmpDirPath / filename); - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - - throw exceptions::command_error("ADD", "", "", e); - } - - if (progress) - progress->stop(size); -} - - -void maildirFolder::copyMessage(const folder::path& dest, const int num) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - copyMessages(dest, num, num); -} - - -void maildirFolder::copyMessages(const folder::path& dest, const int from, const int to) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (from < 1 || (to < from && to != -1)) - throw exceptions::invalid_argument(); - - // Construct the list of message numbers - const int to2 = (to == -1) ? m_messageCount : to; - const int count = to - from + 1; - - std::vector <int> nums; - nums.resize(count); - - for (int i = from, j = 0 ; i <= to2 ; ++i, ++j) - nums[j] = i; - - // Copy messages - copyMessagesImpl(dest, nums); -} - - -void maildirFolder::copyMessages(const folder::path& dest, const std::vector <int>& nums) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Copy messages - copyMessagesImpl(dest, nums); -} - - -void maildirFolder::copyMessagesImpl(const folder::path& dest, const std::vector <int>& nums) -{ - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - utility::file::path destCurDirPath = maildirUtils::getFolderFSPath - (m_store, dest, maildirUtils::FOLDER_PATH_CUR); - utility::file::path destTmpDirPath = maildirUtils::getFolderFSPath - (m_store, dest, maildirUtils::FOLDER_PATH_TMP); - - // Create destination directories - try - { - ref <utility::file> destTmpDir = fsf->create(destTmpDirPath); - destTmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - ref <utility::file> destCurDir = fsf->create(destCurDirPath); - destCurDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - // Copy messages - try - { - for (std::vector <int>::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int num = *it; - const messageInfos& msg = m_messageInfos[num - 1]; - const int flags = maildirUtils::extractFlags(msg.path); - - const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), flags); - - ref <utility::file> file = fsf->create(curDirPath / msg.path); - ref <utility::fileReader> fr = file->getFileReader(); - ref <utility::inputStream> is = fr->getInputStream(); - - copyMessageImpl(destTmpDirPath, destCurDirPath, - filename, *is, file->getLength(), NULL); - } - } - catch (exception& e) - { - notifyMessagesCopied(dest); - throw exceptions::command_error("COPY", "", "", e); - } - - notifyMessagesCopied(dest); -} - - -void maildirFolder::notifyMessagesCopied(const folder::path& dest) -{ - for (std::list <maildirFolder*>::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == dest) - { - // We only need to update the first folder we found as calling - // status() will notify all the folders with the same path. - int count, unseen; - (*it)->status(count, unseen); - - return; - } - } -} - - -void maildirFolder::status(int& count, int& unseen) -{ - const int oldCount = m_messageCount; - - scanFolder(); - - count = m_messageCount; - unseen = m_unreadMessageCount; - - // Notify message count changed (new messages) - if (count > oldCount) - { - std::vector <int> nums; - nums.reserve(count - oldCount); - - for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) - nums[j] = i; - - events::messageCountEvent event - (thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list <maildirFolder*>::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - events::messageCountEvent event - ((*it)->thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } - } -} - - -void maildirFolder::expunge() -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - std::vector <int> nums; - int unreadCount = 0; - - for (int num = 1 ; num <= m_messageCount ; ++num) - { - messageInfos& infos = m_messageInfos[num - 1]; - - if (infos.type == messageInfos::TYPE_DELETED) - { - nums.push_back(num); - - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->m_num == num) - (*it)->m_expunged = true; - else if ((*it)->m_num > num) - (*it)->m_num--; - } - - if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) - ++unreadCount; - - // Delete file from file system - try - { - ref <utility::file> file = fsf->create(curDirPath / infos.path); - file->remove(); - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not important) - } - } - } - - if (!nums.empty()) - { - for (int i = nums.size() - 1 ; i >= 0 ; --i) - m_messageInfos.erase(m_messageInfos.begin() + i); - } - - m_messageCount -= nums.size(); - m_unreadMessageCount -= unreadCount; - - // Notify message expunged - events::messageCountEvent event - (thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_REMOVED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list <maildirFolder*>::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - events::messageCountEvent event - ((*it)->thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_REMOVED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -ref <folder> maildirFolder::getParent() -{ - if (m_path.isEmpty()) - return NULL; - else - return vmime::create <maildirFolder>(m_path.getParent(), m_store); -} - - -weak_ref <const store> maildirFolder::getStore() const -{ - return (m_store); -} - - -weak_ref <store> maildirFolder::getStore() -{ - return (m_store); -} - - -void maildirFolder::fetchMessages(std::vector <ref <message> >& msg, - const int options, utility::progressionListener* progress) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - const int total = msg.size(); - int current = 0; - - if (progress) - progress->start(total); - - weak_ref <maildirFolder> _this = thisWeakRef().dynamicCast <maildirFolder>(); - - for (std::vector <ref <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - (*it).dynamicCast <maildirMessage>()->fetch(_this, options); - - if (progress) - progress->progress(++current, total); - } - - if (progress) - progress->stop(total); -} - - -void maildirFolder::fetchMessage(ref <message> msg, const int options) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - msg.dynamicCast <maildirMessage>()->fetch - (thisWeakRef().dynamicCast <maildirFolder>(), options); -} - - -const int maildirFolder::getFetchCapabilities() const -{ - return (FETCH_ENVELOPE | FETCH_STRUCTURE | FETCH_CONTENT_INFO | - FETCH_FLAGS | FETCH_SIZE | FETCH_FULL_HEADER | FETCH_UID | - FETCH_IMPORTANCE); -} - - -const utility::file::path maildirFolder::getMessageFSPath(const int number) const -{ - utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); - - return (curDirPath / m_messageInfos[number - 1].path); -} - - -} // maildir -} // messaging -} // vmime diff --git a/src/messaging/maildir/maildirMessage.cpp b/src/messaging/maildir/maildirMessage.cpp deleted file mode 100644 index e2393774..00000000 --- a/src/messaging/maildir/maildirMessage.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 Vincent Richard <[email protected]> -// -// 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; either version 2 of -// the License, or (at your option) any later version. -// -// 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., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#include "vmime/messaging/maildir/maildirMessage.hpp" -#include "vmime/messaging/maildir/maildirFolder.hpp" -#include "vmime/messaging/maildir/maildirUtils.hpp" -#include "vmime/messaging/maildir/maildirStore.hpp" - -#include "vmime/message.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platformDependant.hpp" - - -namespace vmime { -namespace messaging { -namespace maildir { - - -// -// maildirPart -// - -class maildirStructure; - -class maildirPart : public part -{ -public: - - maildirPart(weak_ref <maildirPart> parent, const int number, const bodyPart& part); - ~maildirPart(); - - - const structure& getStructure() const; - structure& getStructure(); - - weak_ref <const maildirPart> getParent() const { return (m_parent); } - - const mediaType& getType() const { return (m_mediaType); } - const int getSize() const { return (m_size); } - const int getNumber() const { return (m_number); } - - const header& getHeader() const - { - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return (*m_header); - } - - header& getOrCreateHeader() - { - if (m_header != NULL) - return (*m_header); - else - return (*(m_header = vmime::create <header>())); - } - - const int getHeaderParsedOffset() const { return (m_headerParsedOffset); } - const int getHeaderParsedLength() const { return (m_headerParsedLength); } - - const int getBodyParsedOffset() const { return (m_bodyParsedOffset); } - const int getBodyParsedLength() const { return (m_bodyParsedLength); } - -private: - - ref <maildirStructure> m_structure; - weak_ref <maildirPart> m_parent; - ref <header> m_header; - - int m_number; - int m_size; - mediaType m_mediaType; - - int m_headerParsedOffset; - int m_headerParsedLength; - - int m_bodyParsedOffset; - int m_bodyParsedLength; -}; - - - -// -// maildirStructure -// - -class maildirStructure : public structure -{ -private: - - maildirStructure() - { - } - -public: - - maildirStructure(weak_ref <maildirPart> parent, const bodyPart& part) - { - m_parts.push_back(vmime::create <maildirPart>(parent, 1, part)); - } - - maildirStructure(weak_ref <maildirPart> parent, const std::vector <ref <const vmime::bodyPart> >& list) - { - int number = 1; - - for (unsigned int i = 0 ; i < list.size() ; ++i) - m_parts.push_back(vmime::create <maildirPart>(parent, number, *list[i])); - } - - - const part& operator[](const int x) const - { - return (*m_parts[x - 1]); - } - - part& operator[](const int x) - { - return (*m_parts[x - 1]); - } - - const int getCount() const - { - return (m_parts.size()); - } - - - static maildirStructure* emptyStructure() - { - return (&m_emptyStructure); - } - -private: - - static maildirStructure m_emptyStructure; - - std::vector <ref <maildirPart> > m_parts; -}; - - -maildirStructure maildirStructure::m_emptyStructure; - - - -maildirPart::maildirPart(weak_ref <maildirPart> parent, const int number, const bodyPart& part) - : m_parent(parent), m_header(NULL), m_number(number) -{ - if (part.getBody()->getPartList().size() == 0) - m_structure = NULL; - else - { - m_structure = vmime::create <maildirStructure> - (thisWeakRef().dynamicCast <maildirPart>(), - part.getBody()->getPartList()); - } - - m_headerParsedOffset = part.getHeader()->getParsedOffset(); - m_headerParsedLength = part.getHeader()->getParsedLength(); - - m_bodyParsedOffset = part.getBody()->getParsedOffset(); - m_bodyParsedLength = part.getBody()->getParsedLength(); - - m_size = part.getBody()->getContents()->getLength(); - - m_mediaType = part.getBody()->getContentType(); -} - - -maildirPart::~maildirPart() -{ -} - - -const structure& maildirPart::getStructure() const -{ - if (m_structure != NULL) - return (*m_structure); - else - return (*maildirStructure::emptyStructure()); -} - - -structure& maildirPart::getStructure() -{ - if (m_structure != NULL) - return (*m_structure); - else - return (*maildirStructure::emptyStructure()); -} - - - -// -// maildirMessage -// - -maildirMessage::maildirMessage(weak_ref <maildirFolder> folder, const int num) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_structure(NULL) -{ - m_folder->registerMessage(this); -} - - -maildirMessage::~maildirMessage() -{ - if (m_folder) - m_folder->unregisterMessage(this); -} - - -void maildirMessage::onFolderClosed() -{ - m_folder = NULL; -} - - -const int maildirMessage::getNumber() const -{ - return (m_num); -} - - -const message::uid maildirMessage::getUniqueId() const -{ - return (m_uid); -} - - -const int maildirMessage::getSize() const -{ - if (m_size == -1) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -const bool maildirMessage::isExpunged() const -{ - return (m_expunged); -} - - -const structure& maildirMessage::getStructure() const -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return (*m_structure); -} - - -structure& maildirMessage::getStructure() -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return (*m_structure); -} - - -ref <const header> maildirMessage::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - - return (m_header); -} - - -const int maildirMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) - throw exceptions::unfetched_object(); - - return (m_flags); -} - - -void maildirMessage::setFlags(const int flags, const int mode) -{ - if (!m_folder) - throw exceptions::folder_not_found(); - - m_folder->setMessageFlags(m_num, m_num, flags, mode); -} - - -void maildirMessage::extract(utility::outputStream& os, - utility::progressionListener* progress, const int start, - const int length, const bool peek) const -{ - extractImpl(os, progress, 0, m_size, start, length, peek); -} - - -void maildirMessage::extractPart(const part& p, utility::outputStream& os, - utility::progressionListener* progress, const int start, - const int length, const bool peek) const -{ - const maildirPart& mp = dynamic_cast <const maildirPart&>(p); - - extractImpl(os, progress, mp.getBodyParsedOffset(), mp.getBodyParsedLength(), - start, length, peek); -} - - -void maildirMessage::extractImpl(utility::outputStream& os, utility::progressionListener* progress, - const int start, const int length, const int partialStart, const int partialLength, - const bool /* peek */) const -{ - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - const utility::file::path path = m_folder->getMessageFSPath(m_num); - ref <utility::file> file = fsf->create(path); - - ref <utility::fileReader> reader = file->getFileReader(); - ref <utility::inputStream> is = reader->getInputStream(); - - is->skip(start + partialStart); - - utility::stream::value_type buffer[8192]; - utility::stream::size_type remaining = (partialLength == -1 ? length - : std::min(partialLength, length)); - - const int total = remaining; - int current = 0; - - if (progress) - progress->start(total); - - while (!is->eof() && remaining > 0) - { - const utility::stream::size_type read = - is->read(buffer, std::min(remaining, sizeof(buffer))); - - remaining -= read; - current += read; - - os.write(buffer, read); - - if (progress) - progress->progress(current, total); - } - - if (progress) - progress->stop(total); - - // TODO: mark as read unless 'peek' is set -} - - -void maildirMessage::fetchPartHeader(part& p) -{ - maildirPart& mp = dynamic_cast <maildirPart&>(p); - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - const utility::file::path path = m_folder->getMessageFSPath(m_num); - ref <utility::file> file = fsf->create(path); - - ref <utility::fileReader> reader = file->getFileReader(); - ref <utility::inputStream> is = reader->getInputStream(); - - is->skip(mp.getHeaderParsedOffset()); - - utility::stream::value_type buffer[1024]; - utility::stream::size_type remaining = mp.getHeaderParsedLength(); - - string contents; - contents.reserve(remaining); - - while (!is->eof() && remaining > 0) - { - const utility::stream::size_type read = - is->read(buffer, std::min(remaining, sizeof(buffer))); - - remaining -= read; - - contents.append(buffer, read); - } - - mp.getOrCreateHeader().parse(contents); -} - - -void maildirMessage::fetch(weak_ref <maildirFolder> folder, const int options) -{ - if (m_folder != folder) - throw exceptions::folder_not_found(); - - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - ref <utility::file> file = fsf->create(path); - - if (options & folder::FETCH_FLAGS) - m_flags = maildirUtils::extractFlags(path.getLastComponent()); - - if (options & folder::FETCH_SIZE) - m_size = file->getLength(); - - if (options & folder::FETCH_UID) - m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer(); - - if (options & (folder::FETCH_ENVELOPE | folder::FETCH_CONTENT_INFO | - folder::FETCH_FULL_HEADER | folder::FETCH_STRUCTURE | - folder::FETCH_IMPORTANCE)) - { - string contents; - - ref <utility::fileReader> reader = file->getFileReader(); - ref <utility::inputStream> is = reader->getInputStream(); - - // Need whole message contents for structure - if (options & folder::FETCH_STRUCTURE) - { - utility::stream::value_type buffer[16384]; - - contents.reserve(file->getLength()); - - while (!is->eof()) - { - const utility::stream::size_type read = is->read(buffer, sizeof(buffer)); - contents.append(buffer, read); - } - } - // Need only header - else - { - utility::stream::value_type buffer[1024]; - - contents.reserve(4096); - - while (!is->eof()) - { - const utility::stream::size_type read = is->read(buffer, sizeof(buffer)); - contents.append(buffer, read); - - const string::size_type sep1 = contents.rfind("\r\n\r\n"); - const string::size_type sep2 = contents.rfind("\n\n"); - - if (sep1 != string::npos) - { - contents.erase(contents.begin() + sep1 + 4, contents.end()); - break; - } - else if (sep2 != string::npos) - { - contents.erase(contents.begin() + sep2 + 2, contents.end()); - break; - } - } - } - - vmime::message msg; - msg.parse(contents); - - // Extract structure - if (options & folder::FETCH_STRUCTURE) - { - m_structure = vmime::create <maildirStructure>(null, msg); - } - - // Extract some header fields or whole header - if (options & (folder::FETCH_ENVELOPE | - folder::FETCH_CONTENT_INFO | - folder::FETCH_FULL_HEADER | - folder::FETCH_IMPORTANCE)) - { - getOrCreateHeader()->copyFrom(*(msg.getHeader())); - } - } -} - - -ref <header> maildirMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = vmime::create <header>()); -} - - -} // maildir -} // messaging -} // vmime diff --git a/src/messaging/maildir/maildirStore.cpp b/src/messaging/maildir/maildirStore.cpp deleted file mode 100644 index ccbd35a4..00000000 --- a/src/messaging/maildir/maildirStore.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 Vincent Richard <[email protected]> -// -// 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; either version 2 of -// the License, or (at your option) any later version. -// -// 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., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#include "vmime/messaging/maildir/maildirStore.hpp" - -#include "vmime/messaging/maildir/maildirFolder.hpp" - -#include "vmime/utility/smartPtr.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platformDependant.hpp" - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (sm_infos.getPropertyValue <type>(getSession(), sm_infos.getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop)) - - -namespace vmime { -namespace messaging { -namespace maildir { - - -maildirStore::maildirStore(ref <session> sess, ref <authenticator> auth) - : store(sess, getInfosInstance(), auth), m_connected(false) -{ -} - - -maildirStore::~maildirStore() -{ - if (isConnected()) - disconnect(); -} - - -const string maildirStore::getProtocolName() const -{ - return "maildir"; -} - - -ref <folder> maildirStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <maildirFolder>(folder::path(), - thisWeakRef().dynamicCast <maildirStore>()); -} - - -ref <folder> maildirStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <maildirFolder>(folder::path::component("inbox"), - thisWeakRef().dynamicCast <maildirStore>()); -} - - -ref <folder> maildirStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <maildirFolder>(path, - thisWeakRef().dynamicCast <maildirStore>()); -} - - -const bool maildirStore::isValidFolderName(const folder::path::component& name) const -{ - if (!platformDependant::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) - return false; - - const string& buf = name.getBuffer(); - - // Name cannot start/end with spaces - if (utility::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); -} - - -void maildirStore::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - // Get root directory - utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - - m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH)); - - ref <utility::file> rootDir = fsf->create(m_fsPath); - - // Try to create the root directory if it does not exist - if (!(rootDir->exists() && rootDir->isDirectory())) - { - try - { - rootDir->createDirectory(); - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::connection_error("Cannot create root directory.", e); - } - } - - m_connected = true; -} - - -const bool maildirStore::isConnected() const -{ - return (m_connected); -} - - -void maildirStore::disconnect() -{ - for (std::list <maildirFolder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - (*it)->onStoreDisconnected(); - } - - m_folders.clear(); - - m_connected = false; -} - - -void maildirStore::noop() -{ - // Nothing to do. -} - - -void maildirStore::registerFolder(maildirFolder* folder) -{ - m_folders.push_back(folder); -} - - -void maildirStore::unregisterFolder(maildirFolder* folder) -{ - std::list <maildirFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); -} - - -const utility::path& maildirStore::getFileSystemPath() const -{ - return (m_fsPath); -} - - -const int maildirStore::getCapabilities() const -{ - return (CAPABILITY_CREATE_FOLDER | - CAPABILITY_RENAME_FOLDER | - CAPABILITY_ADD_MESSAGE | - CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | - CAPABILITY_PARTIAL_FETCH | - CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); -} - - - - -// Service infos - -maildirStore::_infos maildirStore::sm_infos; - - -const serviceInfos& maildirStore::getInfosInstance() -{ - return (sm_infos); -} - - -const serviceInfos& maildirStore::getInfos() const -{ - return (sm_infos); -} - - -const string maildirStore::_infos::getPropertyPrefix() const -{ - return "store.maildir."; -} - - -const maildirStore::_infos::props& maildirStore::_infos::getProperties() const -{ - static props p = - { - property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED) - }; - - return p; -} - - -const std::vector <serviceInfos::property> maildirStore::_infos::getAvailableProperties() const -{ - std::vector <property> list; - const props& p = getProperties(); - - // Maildir-specific properties - list.push_back(p.PROPERTY_SERVER_ROOTPATH); - - return (list); -} - - -} // maildir -} // messaging -} // vmime diff --git a/src/messaging/maildir/maildirUtils.cpp b/src/messaging/maildir/maildirUtils.cpp deleted file mode 100644 index 9e411cd6..00000000 --- a/src/messaging/maildir/maildirUtils.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2005 Vincent Richard <[email protected]> -// -// 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; either version 2 of -// the License, or (at your option) any later version. -// -// 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., 675 Mass Ave, Cambridge, MA 02139, USA. -// - -#include "vmime/messaging/maildir/maildirUtils.hpp" -#include "vmime/messaging/maildir/maildirStore.hpp" - -#include "vmime/utility/random.hpp" - - -namespace vmime { -namespace messaging { -namespace maildir { - - -const vmime::word maildirUtils::TMP_DIR("tmp", vmime::charset(vmime::charsets::US_ASCII)); // ensure reliable delivery (not to be listed) -const vmime::word maildirUtils::CUR_DIR("cur", vmime::charset(vmime::charsets::US_ASCII)); // no longer new messages -const vmime::word maildirUtils::NEW_DIR("new", vmime::charset(vmime::charsets::US_ASCII)); // unread messages - - -const utility::file::path maildirUtils::getFolderFSPath - (weak_ref <maildirStore> store, const utility::path& folderPath, const FolderFSPathMode mode) -{ - // Root path - utility::file::path path(store->getFileSystemPath()); - - const int count = (mode == FOLDER_PATH_CONTAINER - ? folderPath.getSize() : folderPath.getSize() - 1); - - // Parent folders - for (int i = 0 ; i < count ; ++i) - { - utility::file::path::component comp(folderPath[i]); - - // TODO: may not work with all encodings... - comp.setBuffer("." + comp.getBuffer() + ".directory"); - - path /= comp; - } - - // Last component - if (folderPath.getSize() != 0 && - mode != FOLDER_PATH_CONTAINER) - { - path /= folderPath.getLastComponent(); - - switch (mode) - { - case FOLDER_PATH_ROOT: break; // Nothing to do - case FOLDER_PATH_NEW: path /= NEW_DIR; break; - case FOLDER_PATH_CUR: path /= CUR_DIR; break; - case FOLDER_PATH_TMP: path /= TMP_DIR; break; - case FOLDER_PATH_CONTAINER: break; // Can't happen... - } - } - - return (path); -} - - -const bool maildirUtils::isSubfolderDirectory(const utility::file& file) -{ - // A directory which name does not start with '.' - // is listed as a sub-folder... - if (file.isDirectory() && - file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { - return (true); - } - - return (false); -} - - -const bool maildirUtils::isMessageFile(const utility::file& file) -{ - // Ignore files which name begins with '.' - if (file.isFile() && - file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { - return (true); - } - - return (false); -} - - -const utility::file::path::component maildirUtils::extractId - (const utility::file::path::component& filename) -{ - string::size_type sep = filename.getBuffer().rfind(':'); - if (sep == string::npos) return (filename); - - return (utility::path::component - (string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep))); -} - - -const int maildirUtils::extractFlags(const utility::file::path::component& comp) -{ - string::size_type sep = comp.getBuffer().rfind(':'); - if (sep == string::npos) return (0); - - const string flagsString(comp.getBuffer().begin() + sep + 1, comp.getBuffer().end()); - const string::size_type count = flagsString.length(); - - int flags = 0; - - for (string::size_type i = 0 ; i < count ; ++i) - { - switch (flagsString[i]) - { - case 'R': case 'r': flags |= message::FLAG_REPLIED; break; - case 'S': case 's': flags |= message::FLAG_SEEN; break; - case 'T': case 't': flags |= message::FLAG_DELETED; break; - case 'F': case 'f': flags |= message::FLAG_MARKED; break; - case 'P': case 'p': flags |= message::FLAG_PASSED; break; - } - } - - return (flags); -} - - -const utility::file::path::component maildirUtils::buildFlags(const int flags) -{ - string str; - str.reserve(8); - - str += "2,"; - - if (flags & message::FLAG_MARKED) str += "F"; - if (flags & message::FLAG_PASSED) str += "P"; - if (flags & message::FLAG_REPLIED) str += "R"; - if (flags & message::FLAG_SEEN) str += "S"; - if (flags & message::FLAG_DELETED) str += "T"; - - return (utility::file::path::component(str)); -} - - -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, const int flags) -{ - return (buildFilename(id, buildFlags(flags))); -} - - -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, const utility::file::path::component& flags) -{ - return (utility::path::component(id.getBuffer() + ":" + flags.getBuffer())); -} - - -const utility::file::path::component maildirUtils::generateId() -{ - std::ostringstream oss; - - oss << utility::random::getTime(); - oss << "."; - oss << utility::random::getProcess(); - oss << "."; - oss << utility::random::getString(6); - - return (utility::file::path::component(oss.str())); -} - - - -// -// messageIdComparator -// - -maildirUtils::messageIdComparator::messageIdComparator - (const utility::file::path::component& comp) - : m_comp(maildirUtils::extractId(comp)) -{ -} - - -const bool maildirUtils::messageIdComparator::operator() - (const utility::file::path::component& other) const -{ - return (m_comp == maildirUtils::extractId(other)); -} - - -} // maildir -} // messaging -} // vmime |