diff options
Diffstat (limited to 'src/messaging/pop3')
-rw-r--r-- | src/messaging/pop3/POP3Folder.cpp | 826 | ||||
-rw-r--r-- | src/messaging/pop3/POP3Message.cpp | 213 | ||||
-rw-r--r-- | src/messaging/pop3/POP3Store.cpp | 630 |
3 files changed, 0 insertions, 1669 deletions
diff --git a/src/messaging/pop3/POP3Folder.cpp b/src/messaging/pop3/POP3Folder.cpp deleted file mode 100644 index ec2c9d52..00000000 --- a/src/messaging/pop3/POP3Folder.cpp +++ /dev/null @@ -1,826 +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/pop3/POP3Folder.hpp" - -#include "vmime/messaging/pop3/POP3Store.hpp" -#include "vmime/messaging/pop3/POP3Message.hpp" - -#include "vmime/exception.hpp" - - -namespace vmime { -namespace messaging { -namespace pop3 { - - -POP3Folder::POP3Folder(const folder::path& path, POP3Store* store) - : m_store(store), m_path(path), - m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false) -{ - m_store->registerFolder(this); -} - - -POP3Folder::~POP3Folder() -{ - if (m_store) - { - if (m_open) - close(false); - - m_store->unregisterFolder(this); - } - else if (m_open) - { - onClose(); - } -} - - -const int POP3Folder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -const int POP3Folder::getType() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - return (TYPE_CONTAINS_MESSAGES); - else - throw exceptions::folder_not_found(); -} - - -const int POP3Folder::getFlags() -{ - return (0); -} - - -const folder::path::component POP3Folder::getName() const -{ - return (m_name); -} - - -const folder::path POP3Folder::getFullPath() const -{ - return (m_path); -} - - -void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - if (m_path.isEmpty()) - { - if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) - throw exceptions::operation_not_supported(); - - m_open = true; - m_mode = mode; - - m_messageCount = 0; - } - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - { - m_store->sendRequest("STAT"); - - string response; - m_store->readResponse(response, false); - - if (!m_store->isSuccessResponse(response)) - throw exceptions::command_error("STAT", response); - - m_store->stripResponseCode(response, response); - - std::istringstream iss(response); - iss >> m_messageCount; - - if (iss.fail()) - throw exceptions::invalid_response("STAT", response); - - m_open = true; - m_mode = mode; - } - else - { - throw exceptions::folder_not_found(); - } -} - -void POP3Folder::close(const bool expunge) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (!expunge) - { - m_store->sendRequest("RSET"); - - string response; - m_store->readResponse(response, false); - } - - m_open = false; - m_mode = -1; - - onClose(); -} - - -void POP3Folder::onClose() -{ - for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) - (*it).first->onFolderClosed(); - - m_messages.clear(); -} - - -void POP3Folder::create(const int /* type */) -{ - throw exceptions::operation_not_supported(); -} - - -const bool POP3Folder::exists() -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - return (m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")); -} - - -const bool POP3Folder::isOpen() const -{ - return (m_open); -} - - -ref <message> POP3Folder::getMessage(const int num) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (num < 1 || num > m_messageCount) - throw exceptions::message_not_found(); - - return vmime::create <POP3Message>(this, num); -} - - -std::vector <ref <message> > POP3Folder::getMessages(const int from, const int to) -{ - const int to2 = (to == -1 ? m_messageCount : to); - - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else 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 <POP3Message>(this, i)); - - return (v); -} - - -std::vector <ref <message> > POP3Folder::getMessages(const std::vector <int>& nums) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else 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) - { - if (*it < 1|| *it > m_messageCount) - throw exceptions::message_not_found(); - - v.push_back(vmime::create <POP3Message>(this, *it)); - } - - return (v); -} - - -const int POP3Folder::getMessageCount() -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_messageCount); -} - - -ref <folder> POP3Folder::getFolder(const folder::path::component& name) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - return vmime::create <POP3Folder>(m_path / name, m_store); -} - - -std::vector <ref <folder> > POP3Folder::getFolders(const bool /* recursive */) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - - if (m_path.isEmpty()) - { - std::vector <ref <folder> > v; - v.push_back(vmime::create <POP3Folder>(folder::path::component("INBOX"), m_store)); - return (v); - } - else - { - std::vector <ref <folder> > v; - return (v); - } -} - - -void POP3Folder::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); - - for (std::vector <ref <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - (*it).dynamicCast <POP3Message>()->fetch(this, options); - - if (progress) - progress->progress(++current, total); - } - - if (options & FETCH_SIZE) - { - // Send the "LIST" command - std::ostringstream command; - command << "LIST"; - - m_store->sendRequest(command.str()); - - // Get the response - string response; - m_store->readResponse(response, true, NULL); - - if (m_store->isSuccessResponse(response)) - { - m_store->stripFirstLine(response, response, NULL); - - // C: LIST - // S: +OK - // S: 1 47548 - // S: 2 12653 - // S: . - std::map <int, string> result; - parseMultiListOrUidlResponse(response, result); - - for (std::vector <ref <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - ref <POP3Message> m = (*it).dynamicCast <POP3Message>(); - - std::map <int, string>::const_iterator x = result.find(m->m_num); - - if (x != result.end()) - { - int size = 0; - - std::istringstream iss((*x).second); - iss >> size; - - m->m_size = size; - } - } - } - - } - - if (options & FETCH_UID) - { - // Send the "UIDL" command - std::ostringstream command; - command << "UIDL"; - - m_store->sendRequest(command.str()); - - // Get the response - string response; - m_store->readResponse(response, true, NULL); - - if (m_store->isSuccessResponse(response)) - { - m_store->stripFirstLine(response, response, NULL); - - // C: UIDL - // S: +OK - // S: 1 whqtswO00WBw418f9t5JxYwZ - // S: 2 QhdPYR:00WBw1Ph7x7 - // S: . - std::map <int, string> result; - parseMultiListOrUidlResponse(response, result); - - for (std::vector <ref <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - ref <POP3Message> m = (*it).dynamicCast <POP3Message>(); - - std::map <int, string>::const_iterator x = result.find(m->m_num); - - if (x != result.end()) - m->m_uid = (*x).second; - } - } - } - - if (progress) - progress->stop(total); -} - - -void POP3Folder::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 <POP3Message>()->fetch(this, options); - - if (options & FETCH_SIZE) - { - // Send the "LIST" command - std::ostringstream command; - command << "LIST " << msg->getNumber(); - - m_store->sendRequest(command.str()); - - // Get the response - string response; - m_store->readResponse(response, false, NULL); - - if (m_store->isSuccessResponse(response)) - { - m_store->stripResponseCode(response, response); - - // C: LIST 2 - // S: +OK 2 4242 - string::iterator it = response.begin(); - - while (it != response.end() && (*it == ' ' || *it == '\t')) ++it; - while (it != response.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != response.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != response.end()) - { - int size = 0; - - std::istringstream iss(string(it, response.end())); - iss >> size; - - msg.dynamicCast <POP3Message>()->m_size = size; - } - } - } - - if (options & FETCH_UID) - { - // Send the "UIDL" command - std::ostringstream command; - command << "UIDL " << msg->getNumber(); - - m_store->sendRequest(command.str()); - - // Get the response - string response; - m_store->readResponse(response, false, NULL); - - if (m_store->isSuccessResponse(response)) - { - m_store->stripResponseCode(response, response); - - // C: UIDL 2 - // S: +OK 2 QhdPYR:00WBw1Ph7x7 - string::iterator it = response.begin(); - - while (it != response.end() && (*it == ' ' || *it == '\t')) ++it; - while (it != response.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != response.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != response.end()) - { - msg.dynamicCast <POP3Message>()->m_uid = - string(it, response.end()); - } - } - } -} - - -const int POP3Folder::getFetchCapabilities() const -{ - return (FETCH_ENVELOPE | FETCH_CONTENT_INFO | - FETCH_SIZE | FETCH_FULL_HEADER | FETCH_UID | - FETCH_IMPORTANCE); -} - - -ref <folder> POP3Folder::getParent() -{ - if (m_path.isEmpty()) - return NULL; - else - return vmime::create <POP3Folder>(m_path.getParent(), m_store); -} - - -weak_ref <const store> POP3Folder::getStore() const -{ - return (m_store); -} - - -weak_ref <store> POP3Folder::getStore() -{ - return (m_store); -} - - -void POP3Folder::registerMessage(POP3Message* msg) -{ - m_messages.insert(MessageMap::value_type(msg, msg->getNumber())); -} - - -void POP3Folder::unregisterMessage(POP3Message* msg) -{ - m_messages.erase(msg); -} - - -void POP3Folder::onStoreDisconnected() -{ - m_store = NULL; -} - - -void POP3Folder::deleteMessage(const int num) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - std::ostringstream command; - command << "DELE " << num; - - m_store->sendRequest(command.str()); - - string response; - m_store->readResponse(response, false); - - if (!m_store->isSuccessResponse(response)) - throw exceptions::command_error("DELE", response); - - // Update local flags - for (std::map <POP3Message*, int>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - POP3Message* msg = (*it).first; - - if (msg->getNumber() == num) - msg->m_deleted = true; - } - - // Notify message flags changed - std::vector <int> nums; - nums.push_back(num); - - events::messageChangedEvent event - (thisRef().dynamicCast <folder>(), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); -} - - -void POP3Folder::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"); - - const int to2 = (to == -1 ? m_messageCount : to); - - for (int i = from ; i <= to2 ; ++i) - { - std::ostringstream command; - command << "DELE " << i; - - m_store->sendRequest(command.str()); - - string response; - m_store->readResponse(response, false); - - if (!m_store->isSuccessResponse(response)) - throw exceptions::command_error("DELE", response); - } - - // Update local flags - for (std::map <POP3Message*, int>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - POP3Message* msg = (*it).first; - - if (msg->getNumber() >= from && msg->getNumber() <= to2) - msg->m_deleted = true; - } - - // Notify message flags changed - std::vector <int> nums; - - for (int i = from ; i <= to2 ; ++i) - nums.push_back(i); - - events::messageChangedEvent event - (thisRef().dynamicCast <folder>(), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); -} - - -void POP3Folder::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"); - - for (std::vector <int>::const_iterator - it = nums.begin() ; it != nums.end() ; ++it) - { - std::ostringstream command; - command << "DELE " << (*it); - - m_store->sendRequest(command.str()); - - string response; - m_store->readResponse(response, false); - - if (!m_store->isSuccessResponse(response)) - throw exceptions::command_error("DELE", response); - } - - // Sort message list - std::vector <int> list; - - list.resize(nums.size()); - std::copy(nums.begin(), nums.end(), list.begin()); - - std::sort(list.begin(), list.end()); - - // Update local flags - for (std::map <POP3Message*, int>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - POP3Message* msg = (*it).first; - - if (std::binary_search(list.begin(), list.end(), msg->getNumber())) - msg->m_deleted = true; - } - - // Notify message flags changed - events::messageChangedEvent event - (thisRef().dynamicCast <folder>(), - events::messageChangedEvent::TYPE_FLAGS, list); - - notifyMessageChanged(event); -} - - -void POP3Folder::setMessageFlags(const int /* from */, const int /* to */, - const int /* flags */, const int /* mode */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::setMessageFlags(const std::vector <int>& /* nums */, - const int /* flags */, const int /* mode */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::rename(const folder::path& /* newPath */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::addMessage(ref <vmime::message> /* msg */, const int /* flags */, - vmime::datetime* /* date */, utility::progressionListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::addMessage(utility::inputStream& /* is */, const int /* size */, const int /* flags */, - vmime::datetime* /* date */, utility::progressionListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::copyMessage(const folder::path& /* dest */, const int /* num */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::copyMessages(const folder::path& /* dest */, const int /* from */, const int /* to */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::copyMessages(const folder::path& /* dest */, const std::vector <int>& /* nums */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::status(int& count, int& unseen) -{ - if (!m_store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - m_store->sendRequest("STAT"); - - string response; - m_store->readResponse(response, false); - - if (!m_store->isSuccessResponse(response)) - throw exceptions::command_error("STAT", response); - - m_store->stripResponseCode(response, response); - - std::istringstream iss(response); - iss >> count; - - unseen = count; - - // Update local message count - if (m_messageCount != count) - { - const int oldCount = m_messageCount; - - m_messageCount = count; - - 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; - - // Notify message count changed - events::messageCountEvent event - (thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list <POP3Folder*>::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = count; - - events::messageCountEvent event - ((*it)->thisRef().dynamicCast <folder>(), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } - } - } -} - - -void POP3Folder::expunge() -{ - // Not supported by POP3 protocol (deleted messages are automatically - // expunged at the end of the session...). -} - - -void POP3Folder::parseMultiListOrUidlResponse(const string& response, std::map <int, string>& result) -{ - std::istringstream iss(response); - std::map <int, string> ids; - - string line; - - while (std::getline(iss, line)) - { - string::iterator it = line.begin(); - - while (it != line.end() && (*it == ' ' || *it == '\t')) - ++it; - - if (it != line.end()) - { - int number = 0; - - while (it != line.end() && (*it >= '0' && *it <= '9')) - { - number = (number * 10) + (*it - '0'); - ++it; - } - - while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != line.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != line.end()) - { - result.insert(std::map <int, string>::value_type(number, string(it, line.end()))); - } - } - } -} - - -} // pop3 -} // messaging -} // vmime diff --git a/src/messaging/pop3/POP3Message.cpp b/src/messaging/pop3/POP3Message.cpp deleted file mode 100644 index ed8999e3..00000000 --- a/src/messaging/pop3/POP3Message.cpp +++ /dev/null @@ -1,213 +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/pop3/POP3Message.hpp" -#include "vmime/messaging/pop3/POP3Folder.hpp" -#include "vmime/messaging/pop3/POP3Store.hpp" - -#include <sstream> - - -namespace vmime { -namespace messaging { -namespace pop3 { - - -POP3Message::POP3Message(POP3Folder* folder, const int num) - : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) -{ - m_folder->registerMessage(this); -} - - -POP3Message::~POP3Message() -{ - if (m_folder) - m_folder->unregisterMessage(this); -} - - -void POP3Message::onFolderClosed() -{ - m_folder = NULL; -} - - -const int POP3Message::getNumber() const -{ - return (m_num); -} - - -const message::uid POP3Message::getUniqueId() const -{ - return (m_uid); -} - - -const int POP3Message::getSize() const -{ - if (m_size == -1) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -const bool POP3Message::isExpunged() const -{ - return (false); -} - - -const int POP3Message::getFlags() const -{ - int flags = FLAG_RECENT; - - if (m_deleted) - flags |= FLAG_DELETED; - - return (flags); -} - - -const structure& POP3Message::getStructure() const -{ - throw exceptions::operation_not_supported(); -} - - -structure& POP3Message::getStructure() -{ - throw exceptions::operation_not_supported(); -} - - -ref <const header> POP3Message::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - - return (m_header); -} - - -void POP3Message::extract(utility::outputStream& os, - utility::progressionListener* progress, const int start, - const int length, const bool /* peek */) const -{ - if (!m_folder) - throw exceptions::illegal_state("Folder closed"); - else if (!m_folder->m_store) - throw exceptions::illegal_state("Store disconnected"); - - if (start != 0 && length != -1) - throw exceptions::partial_fetch_not_supported(); - - // Emit the "RETR" command - std::ostringstream oss; - oss << "RETR " << m_num; - - const_cast <POP3Folder*>(m_folder)->m_store->sendRequest(oss.str()); - - try - { - POP3Folder::MessageMap::const_iterator it = - m_folder->m_messages.find(const_cast <POP3Message*>(this)); - - const int totalSize = (it != m_folder->m_messages.end()) - ? (*it).second : 0; - - const_cast <POP3Folder*>(m_folder)->m_store-> - readResponse(os, progress, totalSize); - } - catch (exceptions::command_error& e) - { - throw exceptions::command_error("RETR", e.response()); - } -} - - -void POP3Message::extractPart - (const part& /* p */, utility::outputStream& /* os */, - utility::progressionListener* /* progress */, - const int /* start */, const int /* length */, - const bool /* peek */) const -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Message::fetchPartHeader(part& /* p */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Message::fetch(POP3Folder* folder, const int options) -{ - if (m_folder != folder) - throw exceptions::folder_not_found(); - - // FETCH_STRUCTURE and FETCH_FLAGS are not supported by POP3. - if (options & (folder::FETCH_STRUCTURE | folder::FETCH_FLAGS)) - throw exceptions::operation_not_supported(); - - // Check for the real need to fetch the full header - static const int optionsRequiringHeader = - folder::FETCH_ENVELOPE | folder::FETCH_CONTENT_INFO | - folder::FETCH_FULL_HEADER | folder::FETCH_IMPORTANCE; - - if (!(options & optionsRequiringHeader)) - return; - - // No need to differenciate between FETCH_ENVELOPE, - // FETCH_CONTENT_INFO, ... since POP3 only permits to - // retrieve the whole header and not fields in particular. - - // Emit the "TOP" command - std::ostringstream oss; - oss << "TOP " << m_num << " 0"; - - m_folder->m_store->sendRequest(oss.str()); - - try - { - string buffer; - m_folder->m_store->readResponse(buffer, true); - - m_header = vmime::create <header>(); - m_header->parse(buffer); - } - catch (exceptions::command_error& e) - { - throw exceptions::command_error("TOP", e.response()); - } -} - - -void POP3Message::setFlags(const int /* flags */, const int /* mode */) -{ - throw exceptions::operation_not_supported(); -} - - -} // pop3 -} // messaging -} // vmime diff --git a/src/messaging/pop3/POP3Store.cpp b/src/messaging/pop3/POP3Store.cpp deleted file mode 100644 index 1407df35..00000000 --- a/src/messaging/pop3/POP3Store.cpp +++ /dev/null @@ -1,630 +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/pop3/POP3Store.hpp" -#include "vmime/messaging/pop3/POP3Folder.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platformDependant.hpp" -#include "vmime/messageId.hpp" -#include "vmime/utility/md5.hpp" -#include "vmime/utility/filteredStream.hpp" - -#include <algorithm> - - -// 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 pop3 { - - -POP3Store::POP3Store(ref <session> sess, ref <authenticator> auth) - : store(sess, getInfosInstance(), auth), m_socket(NULL), - m_authentified(false), m_timeoutHandler(NULL) -{ -} - - -POP3Store::~POP3Store() -{ - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); -} - - -const string POP3Store::getProtocolName() const -{ - return "pop3"; -} - - -ref <folder> POP3Store::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <POP3Folder>(folder::path(folder::path::component("INBOX")), this); -} - - -ref <folder> POP3Store::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <POP3Folder>(folder::path(), this); -} - - -ref <folder> POP3Store::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return vmime::create <POP3Folder>(path, this); -} - - -const bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const -{ - return true; -} - - -void POP3Store::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); - const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); - - // Create the time-out handler - if (HAS_PROPERTY(PROPERTY_TIMEOUT_FACTORY)) - { - timeoutHandlerFactory* tof = platformDependant::getHandler()-> - getTimeoutHandlerFactory(GET_PROPERTY(string, PROPERTY_TIMEOUT_FACTORY)); - - m_timeoutHandler = tof->create(); - } - - // Create and connect the socket - socketFactory* sf = platformDependant::getHandler()-> - getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY)); - - m_socket = sf->create(); - m_socket->connect(address, port); - - // Connection - // - // eg: C: <connection to server> - // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <[email protected]> - - string response; - readResponse(response, false); - - if (isSuccessResponse(response)) - { - bool authentified = false; - - const authenticationInfos auth = getAuthenticator()->requestAuthInfos(); - - // Secured authentication with APOP (if requested and if available) - // - // eg: C: APOP vincent <digest> - // --- S: +OK vincent is a valid mailbox - messageId mid(response); - - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) - { - if (mid.getLeft().length() && mid.getRight().length()) - { - // <digest> is the result of MD5 applied to "<message-id>password" - sendRequest("APOP " + auth.getUsername() + " " - + utility::md5(mid.generate() + auth.getPassword()).hex()); - readResponse(response, false); - - if (isSuccessResponse(response)) - { - authentified = true; - } - else - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { - internalDisconnect(); - throw exceptions::authentication_error(response); - } - } - } - else - { - // APOP not supported - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { - // Can't fallback on basic authentification - internalDisconnect(); - throw exceptions::unsupported_option(); - } - } - } - - if (!authentified) - { - // Basic authentication - // - // eg: C: USER vincent - // --- S: +OK vincent is a valid mailbox - // - // C: PASS couic - // S: +OK vincent's maildrop has 2 messages (320 octets) - - sendRequest("USER " + auth.getUsername()); - readResponse(response, false); - - if (isSuccessResponse(response)) - { - sendRequest("PASS " + auth.getPassword()); - readResponse(response, false); - - if (!isSuccessResponse(response)) - { - internalDisconnect(); - throw exceptions::authentication_error(response); - } - } - else - { - internalDisconnect(); - throw exceptions::authentication_error(response); - } - } - } - else - { - internalDisconnect(); - throw exceptions::connection_greeting_error(response); - } - - m_authentified = true; -} - - -const bool POP3Store::isConnected() const -{ - return (m_socket && m_socket->isConnected() && m_authentified); -} - - -void POP3Store::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void POP3Store::internalDisconnect() -{ - for (std::list <POP3Folder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - (*it)->onStoreDisconnected(); - } - - m_folders.clear(); - - - sendRequest("QUIT"); - - m_socket->disconnect(); - m_socket = NULL; - - m_timeoutHandler = NULL; - - m_authentified = false; -} - - -void POP3Store::noop() -{ - m_socket->send("NOOP"); - - string response; - readResponse(response, false); - - if (!isSuccessResponse(response)) - throw exceptions::command_error("NOOP", response); -} - - -const bool POP3Store::isSuccessResponse(const string& buffer) -{ - static const string OK("+OK"); - - return (buffer.length() >= 3 && - std::equal(buffer.begin(), buffer.begin() + 3, OK.begin())); -} - - -const bool POP3Store::stripFirstLine(const string& buffer, string& result, string* firstLine) -{ - const string::size_type end = buffer.find('\n'); - - if (end != string::npos) - { - if (firstLine) *firstLine = buffer.substr(0, end); - result = buffer.substr(end + 1); - return (true); - } - else - { - result = buffer; - return (false); - } -} - - -void POP3Store::stripResponseCode(const string& buffer, string& result) -{ - const string::size_type pos = buffer.find_first_of(" \t"); - - if (pos != string::npos) - result = buffer.substr(pos + 1); - else - result = buffer; -} - - -void POP3Store::sendRequest(const string& buffer, const bool end) -{ - if (end) - m_socket->send(buffer + "\r\n"); - else - m_socket->send(buffer); -} - - -void POP3Store::readResponse(string& buffer, const bool multiLine, - utility::progressionListener* progress) -{ - bool foundTerminator = false; - int current = 0, total = 0; - - if (progress) - progress->start(total); - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - buffer.clear(); - - string::value_type last1 = '\0', last2 = '\0'; - - for ( ; !foundTerminator ; ) - { -#if 0 // not supported - // Check for possible cancellation - if (progress && progress->cancel()) - throw exceptions::operation_cancelled(); -#endif - - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - } - - // Receive data from the socket - string receiveBuffer; - m_socket->receive(receiveBuffer); - - if (receiveBuffer.empty()) // buffer is empty - { - platformDependant::getHandler()->wait(); - continue; - } - - // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - // Check for transparent characters: '\n..' becomes '\n.' - const string::value_type first = receiveBuffer[0]; - - if (first == '.' && last2 == '\n' && last1 == '.') - { - receiveBuffer.erase(receiveBuffer.begin()); - } - else if (receiveBuffer.length() >= 2 && first == '.' && - receiveBuffer[1] == '.' && last1 == '\n') - { - receiveBuffer.erase(receiveBuffer.begin()); - } - - for (string::size_type trans ; - string::npos != (trans = receiveBuffer.find("\n..")) ; ) - { - receiveBuffer.replace(trans, 3, "\n."); - } - - last1 = receiveBuffer[receiveBuffer.length() - 1]; - last2 = (receiveBuffer.length() >= 2) ? receiveBuffer[receiveBuffer.length() - 2] : 0; - - // Append the data to the response buffer - buffer += receiveBuffer; - current += receiveBuffer.length(); - - // Check for terminator string (and strip it if present) - foundTerminator = checkTerminator(buffer, multiLine); - - // Notify progression - if (progress) - { - total = std::max(total, current); - progress->progress(current, total); - } - - // If there is an error (-ERR) when executing a command that - // requires a multi-line response, the error response will - // include only one line, so we stop waiting for a multi-line - // terminator and check for a "normal" one. - if (multiLine && !foundTerminator && buffer.length() >= 4 && buffer[0] == '-') - { - foundTerminator = checkTerminator(buffer, false); - } - } - - if (progress) - progress->stop(total); -} - - -void POP3Store::readResponse(utility::outputStream& os, - utility::progressionListener* progress, const int predictedSize) -{ - int current = 0, total = predictedSize; - - string temp; - bool codeDone = false; - - if (progress) - progress->start(total); - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - utility::inputStreamSocketAdapter sis(*m_socket); - utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); - utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n"); - utility::dotFilteredInputStream dfis(sfis2); // "\n.." --> "\n." - - utility::inputStream& is = dfis; - - while (!is.eof()) - { -#if 0 // not supported - // Check for possible cancellation - if (progress && progress->cancel()) - throw exceptions::operation_cancelled(); -#endif - - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - } - - // Receive data from the socket - utility::stream::value_type buffer[65536]; - const utility::stream::size_type read = is.read(buffer, sizeof(buffer)); - - if (read == 0) // buffer is empty - { - platformDependant::getHandler()->wait(); - continue; - } - - // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - // If we don't have extracted the response code yet - if (!codeDone) - { - temp += string(buffer, read); - - string firstLine; - - if (stripFirstLine(temp, temp, &firstLine) == true) - { - if (!isSuccessResponse(firstLine)) - throw exceptions::command_error("?", firstLine); - - codeDone = true; - - os.write(temp.data(), temp.length()); - temp.clear(); - - continue; - } - } - else - { - // Inject the data into the output stream - os.write(buffer, read); - current += read; - - // Notify progression - if (progress) - { - total = std::max(total, current); - progress->progress(current, total); - } - } - } - - if (progress) - progress->stop(total); -} - - -const bool POP3Store::checkTerminator(string& buffer, const bool multiLine) -{ - // Multi-line response - if (multiLine) - { - static const string term1("\r\n.\r\n"); - static const string term2("\n.\n"); - - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } - // Normal response - else - { - static const string term1("\r\n"); - static const string term2("\n"); - - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } - - return (false); -} - - -const bool POP3Store::checkOneTerminator(string& buffer, const string& term) -{ - if (buffer.length() >= term.length() && - std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) - { - buffer.erase(buffer.end() - term.length(), buffer.end()); - return (true); - } - - return (false); -} - - -void POP3Store::registerFolder(POP3Folder* folder) -{ - m_folders.push_back(folder); -} - - -void POP3Store::unregisterFolder(POP3Folder* folder) -{ - std::list <POP3Folder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); -} - - -const int POP3Store::getCapabilities() const -{ - return (CAPABILITY_DELETE_MESSAGE); -} - - - -// Service infos - -POP3Store::_infos POP3Store::sm_infos; - - -const serviceInfos& POP3Store::getInfosInstance() -{ - return (sm_infos); -} - - -const serviceInfos& POP3Store::getInfos() const -{ - return (sm_infos); -} - - -const string POP3Store::_infos::getPropertyPrefix() const -{ - return "store.pop3."; -} - - -const POP3Store::_infos::props& POP3Store::_infos::getProperties() const -{ - static props p = - { - // POP3-specific options - property("options.apop", serviceInfos::property::TYPE_BOOL, "false"), - property("options.apop.fallback", serviceInfos::property::TYPE_BOOL, "false"), - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "110"), - property(serviceInfos::property::SERVER_SOCKETFACTORY), - - property(serviceInfos::property::TIMEOUT_FACTORY) - }; - - return p; -} - - -const std::vector <serviceInfos::property> POP3Store::_infos::getAvailableProperties() const -{ - std::vector <property> list; - const props& p = getProperties(); - - // POP3-specific options - list.push_back(p.PROPERTY_OPTIONS_APOP); - list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK); - - // Common properties - list.push_back(p.PROPERTY_AUTH_USERNAME); - list.push_back(p.PROPERTY_AUTH_PASSWORD); - - list.push_back(p.PROPERTY_SERVER_ADDRESS); - list.push_back(p.PROPERTY_SERVER_PORT); - list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY); - - list.push_back(p.PROPERTY_TIMEOUT_FACTORY); - - return (list); -} - - -} // pop3 -} // messaging -} // vmime - |