Working on 'maildir' implementation.
This commit is contained in:
parent
4a6741ab2b
commit
1ece98b08f
@ -490,202 +490,22 @@ void maildirFolder::rename(const folder::path& newPath)
|
||||
|
||||
void maildirFolder::deleteMessage(const int num)
|
||||
{
|
||||
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");
|
||||
|
||||
if (m_messageInfos[num].type == messageInfos::TYPE_DELETED)
|
||||
return;
|
||||
|
||||
// Mark message as deleted
|
||||
try
|
||||
{
|
||||
utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory();
|
||||
|
||||
utility::file::path curDirPath = maildirUtils::getFolderFSPath
|
||||
(m_store, m_path, maildirUtils::FOLDER_PATH_CUR);
|
||||
|
||||
const utility::file::path::component path = m_messageInfos[num].path;
|
||||
utility::auto_ptr <utility::file> file = fsf->create(curDirPath / path);
|
||||
|
||||
const utility::file::path::component newPath = maildirUtils::buildFilename
|
||||
(maildirUtils::extractId(path),
|
||||
maildirUtils::extractFlags(path) | message::FLAG_DELETED);
|
||||
|
||||
file->rename(curDirPath / newPath);
|
||||
|
||||
m_messageInfos[num].type = messageInfos::TYPE_DELETED;
|
||||
m_messageInfos[num].path = newPath;
|
||||
}
|
||||
catch (exceptions::filesystem_exception& e)
|
||||
{
|
||||
// Ignore (not important)
|
||||
}
|
||||
|
||||
// Update local flags
|
||||
for (std::vector <maildirMessage*>::iterator it =
|
||||
m_messages.begin() ; it != m_messages.end() ; ++it)
|
||||
{
|
||||
if ((*it)->getNumber() == num &&
|
||||
(*it)->m_flags != message::FLAG_UNDEFINED)
|
||||
{
|
||||
(*it)->m_flags |= message::FLAG_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify message flags changed
|
||||
std::vector <int> nums;
|
||||
nums.push_back(num);
|
||||
|
||||
events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, nums);
|
||||
|
||||
notifyMessageChanged(event);
|
||||
// Mark messages as deleted
|
||||
setMessageFlags(num, num, message::FLAG_MODE_ADD, message::FLAG_DELETED);
|
||||
}
|
||||
|
||||
|
||||
void maildirFolder::deleteMessages(const int from, const int to)
|
||||
{
|
||||
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");
|
||||
|
||||
const int to2 = (to == -1) ? m_messageCount : to;
|
||||
const int count = to - from + 1;
|
||||
|
||||
// Mark messages as deleted
|
||||
utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory();
|
||||
|
||||
utility::file::path curDirPath = maildirUtils::getFolderFSPath
|
||||
(m_store, m_path, maildirUtils::FOLDER_PATH_CUR);
|
||||
|
||||
for (int i = from ; i <= to2 ; ++i)
|
||||
{
|
||||
if (m_messageInfos[i].type != messageInfos::TYPE_DELETED)
|
||||
{
|
||||
try
|
||||
{
|
||||
const utility::file::path::component path = m_messageInfos[i].path;
|
||||
utility::auto_ptr <utility::file> file = fsf->create(curDirPath / path);
|
||||
|
||||
const utility::file::path::component newPath = maildirUtils::buildFilename
|
||||
(maildirUtils::extractId(path),
|
||||
maildirUtils::extractFlags(path) | message::FLAG_DELETED);
|
||||
|
||||
file->rename(curDirPath / newPath);
|
||||
|
||||
m_messageInfos[i].type = messageInfos::TYPE_DELETED;
|
||||
m_messageInfos[i].path = newPath;
|
||||
}
|
||||
catch (exceptions::filesystem_exception& e)
|
||||
{
|
||||
// Ignore (not important)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update local flags
|
||||
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 |= message::FLAG_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify message flags changed
|
||||
std::vector <int> nums;
|
||||
nums.resize(count);
|
||||
|
||||
for (int i = from, j = 0 ; i <= to2 ; ++i, ++j)
|
||||
nums[j] = i;
|
||||
|
||||
events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, nums);
|
||||
|
||||
notifyMessageChanged(event);
|
||||
setMessageFlags(from, to, message::FLAG_MODE_ADD, message::FLAG_DELETED);
|
||||
}
|
||||
|
||||
|
||||
void maildirFolder::deleteMessages(const std::vector <int>& nums)
|
||||
{
|
||||
if (nums.empty())
|
||||
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");
|
||||
|
||||
// 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());
|
||||
|
||||
// Mark messages as deleted
|
||||
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 =
|
||||
list.begin() ; it != list.end() ; ++it)
|
||||
{
|
||||
const int num = *it;
|
||||
|
||||
if (m_messageInfos[num].type != messageInfos::TYPE_DELETED)
|
||||
{
|
||||
try
|
||||
{
|
||||
const utility::file::path::component path = m_messageInfos[num].path;
|
||||
utility::auto_ptr <utility::file> file = fsf->create
|
||||
(curDirPath / m_messageInfos[num].path);
|
||||
|
||||
const utility::file::path::component newPath = maildirUtils::buildFilename
|
||||
(maildirUtils::extractId(path),
|
||||
maildirUtils::extractFlags(path) | message::FLAG_DELETED);
|
||||
|
||||
file->rename(curDirPath / newPath);
|
||||
|
||||
m_messageInfos[num].type = messageInfos::TYPE_DELETED;
|
||||
m_messageInfos[num].path = newPath;
|
||||
}
|
||||
catch (exceptions::filesystem_exception& e)
|
||||
{
|
||||
// Ignore (not important)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update local flags
|
||||
for (std::vector <maildirMessage*>::iterator it =
|
||||
m_messages.begin() ; it != m_messages.end() ; ++it)
|
||||
{
|
||||
if (std::binary_search(list.begin(), list.end(), (*it)->getNumber()))
|
||||
{
|
||||
if ((*it)->m_flags != message::FLAG_UNDEFINED)
|
||||
(*it)->m_flags |= message::FLAG_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify message flags changed
|
||||
events::messageChangedEvent event(this, events::messageChangedEvent::TYPE_FLAGS, list);
|
||||
|
||||
notifyMessageChanged(event);
|
||||
setMessageFlags(nums, message::FLAG_MODE_ADD, message::FLAG_DELETED);
|
||||
}
|
||||
|
||||
|
||||
@ -859,7 +679,7 @@ void maildirFolder::setMessageFlagsImpl
|
||||
for (std::vector <int>::const_iterator it =
|
||||
nums.begin() ; it != nums.end() ; ++it)
|
||||
{
|
||||
const int num = *it;
|
||||
const int num = *it - 1;
|
||||
|
||||
try
|
||||
{
|
||||
@ -971,6 +791,8 @@ void maildirFolder::status(int& count, int& unseen)
|
||||
if ((*it)->getFullPath() == m_path)
|
||||
{
|
||||
(*it)->m_messageCount = count;
|
||||
(*it)->m_unreadMessageCount = unseen;
|
||||
|
||||
(*it)->notifyMessageCount(event);
|
||||
|
||||
(*it)->scanFolder();
|
||||
@ -982,7 +804,67 @@ void maildirFolder::status(int& count, int& unseen)
|
||||
|
||||
void maildirFolder::expunge()
|
||||
{
|
||||
// TODO
|
||||
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
|
||||
{
|
||||
utility::auto_ptr <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);
|
||||
}
|
||||
|
||||
// Notify message expunged
|
||||
events::messageCountEvent event(this, events::messageCountEvent::TYPE_REMOVED, nums);
|
||||
|
||||
m_messageCount -= nums.size();
|
||||
m_unreadMessageCount -= unreadCount;
|
||||
|
||||
notifyMessageCount(event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,6 +126,7 @@ private:
|
||||
|
||||
void onClose();
|
||||
|
||||
void deleteMessagesImpl(const std::vector <int>& nums);
|
||||
void setMessageFlagsImpl(const std::vector <int>& nums, const int flags, const int mode);
|
||||
|
||||
|
||||
|
@ -30,7 +30,8 @@ namespace messaging {
|
||||
|
||||
|
||||
maildirMessage::maildirMessage(maildirFolder* folder, const int num)
|
||||
: m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED)
|
||||
: m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED),
|
||||
m_expunged(false)
|
||||
{
|
||||
m_folder->registerMessage(this);
|
||||
}
|
||||
@ -57,7 +58,7 @@ const int maildirMessage::getNumber() const
|
||||
|
||||
const message::uid maildirMessage::getUniqueId() const
|
||||
{
|
||||
// TODO
|
||||
return (m_uid);
|
||||
}
|
||||
|
||||
|
||||
@ -72,7 +73,7 @@ const int maildirMessage::getSize() const
|
||||
|
||||
const bool maildirMessage::isExpunged() const
|
||||
{
|
||||
// TODO
|
||||
return (m_expunged);
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +106,10 @@ const int maildirMessage::getFlags() const
|
||||
|
||||
void maildirMessage::setFlags(const int flags, const int mode)
|
||||
{
|
||||
// TODO
|
||||
if (!m_folder)
|
||||
throw exceptions::folder_not_found();
|
||||
|
||||
m_folder->setMessageFlags(m_num, m_num, flags, mode);
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +148,6 @@ void maildirMessage::fetch(maildirFolder* folder, const int options)
|
||||
TODO: FETCH_STRUCTURE
|
||||
TODO: FETCH_CONTENT_INFO
|
||||
TODO: FETCH_FULL_HEADER
|
||||
TODO: FETCH_UID
|
||||
*/
|
||||
|
||||
if (options & folder::FETCH_FLAGS)
|
||||
@ -152,6 +155,9 @@ void maildirMessage::fetch(maildirFolder* folder, const int options)
|
||||
|
||||
if (options & folder::FETCH_SIZE)
|
||||
m_size = file->length();
|
||||
|
||||
if (options & folder::FETCH_UID)
|
||||
m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,6 +81,8 @@ private:
|
||||
int m_num;
|
||||
int m_size;
|
||||
int m_flags;
|
||||
bool m_expunged;
|
||||
uid m_uid;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user