📄 maildirfolder.cpp
字号:
//// VMime library (http://www.vmime.org)// Copyright (C) 2002-2008 Vincent Richard <vincent@vincent-richard.net>//// 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.,// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.//// Linking this library statically or dynamically with other modules is making// a combined work based on this library. Thus, the terms and conditions of// the GNU General Public License cover the whole combination.//#include "vmime/net/maildir/maildirFolder.hpp"#include "vmime/net/maildir/maildirStore.hpp"#include "vmime/net/maildir/maildirMessage.hpp"#include "vmime/net/maildir/maildirUtils.hpp"#include "vmime/net/maildir/maildirFormat.hpp"#include "vmime/utility/smartPtr.hpp"#include "vmime/message.hpp"#include "vmime/exception.hpp"#include "vmime/platform.hpp"namespace vmime {namespace net {namespace maildir {maildirFolder::maildirFolder(const folder::path& path, 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){ store->registerFolder(this);}maildirFolder::~maildirFolder(){ ref <maildirStore> store = m_store.acquire(); if (store) { if (m_open) close(false); store->unregisterFolder(this); } else if (m_open) { close(false); }}void maildirFolder::onStoreDisconnected(){ m_store = NULL;}int maildirFolder::getMode() const{ if (!isOpen()) throw exceptions::illegal_state("Folder not open"); return (m_mode);}int maildirFolder::getType(){ if (m_path.isEmpty()) return (TYPE_CONTAINS_FOLDERS); else return (TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES);}int maildirFolder::getFlags(){ int flags = 0; if (m_store.acquire()->getFormat()->folderHasSubfolders(m_path)) flags |= FLAG_CHILDREN; // Contains at least one sub-folder 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 */){ ref <maildirStore> store = m_store.acquire(); if (!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){ ref <maildirStore> store = m_store.acquire(); if (!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 */){ ref <maildirStore> store = m_store.acquire(); if (!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 (!store->isValidFolderName(m_name)) throw exceptions::invalid_folder_name(); // Create directory on file system try { store->getFormat()->createFolder(m_path); } 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);}void maildirFolder::destroy(){ ref <maildirStore> store = m_store.acquire(); if (!store) throw exceptions::illegal_state("Store disconnected"); else if (isOpen()) throw exceptions::illegal_state("Folder is open"); // Delete folder try { store->getFormat()->destroyFolder(m_path); } catch (std::exception&) { // Ignore exception: anyway, we can't recover from this... } // Notify folder deleted events::folderEvent event (thisRef().dynamicCast <folder>(), events::folderEvent::TYPE_DELETED, m_path, m_path); notifyFolder(event);}bool maildirFolder::exists(){ ref <maildirStore> store = m_store.acquire(); return store->getFormat()->folderExists(m_path);}bool maildirFolder::isOpen() const{ return (m_open);}void maildirFolder::scanFolder(){ ref <maildirStore> store = m_store.acquire(); try { m_messageCount = 0; m_unreadMessageCount = 0; utility::fileSystemFactory* fsf = platform::getHandler()->getFileSystemFactory(); utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath (m_path, maildirFormat::NEW_DIRECTORY); ref <utility::file> newDir = fsf->create(newDirPath); utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath (m_path, maildirFormat::CUR_DIRECTORY); 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; if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) msgInfos.type = messageInfos::TYPE_DELETED; else 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; if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) msgInfos.type = messageInfos::TYPE_DELETED; else 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> (thisRef().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; ref <maildirFolder> thisFolder = thisRef().dynamicCast <maildirFolder>(); for (int i = from ; i <= to2 ; ++i) v.push_back(vmime::create <maildirMessage>(thisFolder, 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; ref <maildirFolder> thisFolder = thisRef().dynamicCast <maildirFolder>(); for (std::vector <int>::const_iterator it = nums.begin() ; it != nums.end() ; ++it) v.push_back(vmime::create <maildirMessage>(thisFolder, *it)); return (v);}int maildirFolder::getMessageCount(){ return (m_messageCount);}ref <folder> maildirFolder::getFolder(const folder::path::component& name){ ref <maildirStore> store = m_store.acquire(); if (!store)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -