aboutsummaryrefslogtreecommitdiffstats
path: root/src/messaging/imap/IMAPMessage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/messaging/imap/IMAPMessage.cpp')
-rw-r--r--src/messaging/imap/IMAPMessage.cpp859
1 files changed, 0 insertions, 859 deletions
diff --git a/src/messaging/imap/IMAPMessage.cpp b/src/messaging/imap/IMAPMessage.cpp
deleted file mode 100644
index ba77251b..00000000
--- a/src/messaging/imap/IMAPMessage.cpp
+++ /dev/null
@@ -1,859 +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/imap/IMAPParser.hpp"
-#include "vmime/messaging/imap/IMAPMessage.hpp"
-#include "vmime/messaging/imap/IMAPFolder.hpp"
-#include "vmime/messaging/imap/IMAPStore.hpp"
-#include "vmime/messaging/imap/IMAPConnection.hpp"
-#include "vmime/messaging/imap/IMAPUtils.hpp"
-
-#include <sstream>
-#include <iterator>
-
-
-namespace vmime {
-namespace messaging {
-namespace imap {
-
-
-//
-// IMAPpart
-//
-
-class IMAPstructure;
-
-class IMAPpart : public part
-{
-private:
-
- friend class vmime::creator;
-
- IMAPpart(weak_ref <IMAPpart> parent, const int number, const IMAPParser::body_type_mpart* mpart);
- IMAPpart(weak_ref <IMAPpart> parent, const int number, const IMAPParser::body_type_1part* part);
-
-public:
-
- const structure& getStructure() const;
- structure& getStructure();
-
- weak_ref <const IMAPpart> 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);
- }
-
-
- static ref <IMAPpart> create
- (weak_ref <IMAPpart> parent, const int number, const IMAPParser::body* body)
- {
- if (body->body_type_mpart())
- return vmime::create <IMAPpart>(parent, number, body->body_type_mpart());
- else
- return vmime::create <IMAPpart>(parent, number, body->body_type_1part());
- }
-
-
- header& getOrCreateHeader()
- {
- if (m_header != NULL)
- return (*m_header);
- else
- return (*(m_header = vmime::create <header>()));
- }
-
-private:
-
- ref <IMAPstructure> m_structure;
- weak_ref <IMAPpart> m_parent;
- ref <header> m_header;
-
- int m_number;
- int m_size;
- mediaType m_mediaType;
-};
-
-
-
-//
-// IMAPstructure
-//
-
-class IMAPstructure : public structure
-{
-private:
-
- IMAPstructure()
- {
- }
-
-public:
-
- IMAPstructure(const IMAPParser::body* body)
- {
- m_parts.push_back(IMAPpart::create(NULL, 1, body));
- }
-
- IMAPstructure(weak_ref <IMAPpart> parent, const std::vector <IMAPParser::body*>& list)
- {
- int number = 1;
-
- for (std::vector <IMAPParser::body*>::const_iterator
- it = list.begin() ; it != list.end() ; ++it, ++number)
- {
- m_parts.push_back(IMAPpart::create(parent, number, *it));
- }
- }
-
-
- 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 IMAPstructure* emptyStructure()
- {
- return (&m_emptyStructure);
- }
-
-private:
-
- static IMAPstructure m_emptyStructure;
-
- std::vector <ref <IMAPpart> > m_parts;
-};
-
-
-IMAPstructure IMAPstructure::m_emptyStructure;
-
-
-
-IMAPpart::IMAPpart(weak_ref <IMAPpart> parent, const int number, const IMAPParser::body_type_mpart* mpart)
- : m_parent(parent), m_header(NULL), m_number(number), m_size(0)
-{
- m_mediaType = vmime::mediaType
- ("multipart", mpart->media_subtype()->value());
-
- m_structure = vmime::create <IMAPstructure>
- (thisWeakRef().dynamicCast <IMAPpart>(), mpart->list());
-}
-
-
-IMAPpart::IMAPpart(weak_ref <IMAPpart> parent, const int number, const IMAPParser::body_type_1part* part)
- : m_parent(parent), m_header(NULL), m_number(number), m_size(0)
-{
- if (part->body_type_text())
- {
- m_mediaType = vmime::mediaType
- ("text", part->body_type_text()->
- media_text()->media_subtype()->value());
-
- m_size = part->body_type_text()->body_fields()->body_fld_octets()->value();
- }
- else if (part->body_type_msg())
- {
- m_mediaType = vmime::mediaType
- ("message", part->body_type_msg()->
- media_message()->media_subtype()->value());
- }
- else
- {
- m_mediaType = vmime::mediaType
- (part->body_type_basic()->media_basic()->media_type()->value(),
- part->body_type_basic()->media_basic()->media_subtype()->value());
-
- m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value();
- }
-
- m_structure = NULL;
-}
-
-
-const class structure& IMAPpart::getStructure() const
-{
- if (m_structure != NULL)
- return (*m_structure);
- else
- return (*IMAPstructure::emptyStructure());
-}
-
-
-class structure& IMAPpart::getStructure()
-{
- if (m_structure != NULL)
- return (*m_structure);
- else
- return (*IMAPstructure::emptyStructure());
-}
-
-
-
-#ifndef VMIME_BUILDING_DOC
-
-//
-// IMAPMessage_literalHandler
-//
-
-class IMAPMessage_literalHandler : public IMAPParser::literalHandler
-{
-public:
-
- IMAPMessage_literalHandler(utility::outputStream& os, utility::progressionListener* progress)
- : m_os(os), m_progress(progress)
- {
- }
-
- target* targetFor(const IMAPParser::component& comp, const int /* data */)
- {
- if (typeid(comp) == typeid(IMAPParser::msg_att_item))
- {
- const int type = static_cast
- <const IMAPParser::msg_att_item&>(comp).type();
-
- if (type == IMAPParser::msg_att_item::BODY_SECTION ||
- type == IMAPParser::msg_att_item::RFC822_TEXT)
- {
- return new targetStream(m_progress, m_os);
- }
- }
-
- return (NULL);
- }
-
-private:
-
- utility::outputStream& m_os;
- utility::progressionListener* m_progress;
-};
-
-#endif // VMIME_BUILDING_DOC
-
-
-
-//
-// IMAPMessage
-//
-
-
-IMAPMessage::IMAPMessage(IMAPFolder* 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);
-}
-
-
-IMAPMessage::~IMAPMessage()
-{
- if (m_folder)
- m_folder->unregisterMessage(this);
-}
-
-
-void IMAPMessage::onFolderClosed()
-{
- m_folder = NULL;
-}
-
-
-const int IMAPMessage::getNumber() const
-{
- return (m_num);
-}
-
-
-const message::uid IMAPMessage::getUniqueId() const
-{
- return (m_uid);
-}
-
-
-const int IMAPMessage::getSize() const
-{
- if (m_size == -1)
- throw exceptions::unfetched_object();
-
- return (m_size);
-}
-
-
-const bool IMAPMessage::isExpunged() const
-{
- return (m_expunged);
-}
-
-
-const int IMAPMessage::getFlags() const
-{
- if (m_flags == FLAG_UNDEFINED)
- throw exceptions::unfetched_object();
-
- return (m_flags);
-}
-
-
-const structure& IMAPMessage::getStructure() const
-{
- if (m_structure == NULL)
- throw exceptions::unfetched_object();
-
- return (*m_structure);
-}
-
-
-structure& IMAPMessage::getStructure()
-{
- if (m_structure == NULL)
- throw exceptions::unfetched_object();
-
- return (*m_structure);
-}
-
-
-ref <const header> IMAPMessage::getHeader() const
-{
- if (m_header == NULL)
- throw exceptions::unfetched_object();
-
- return (m_header);
-}
-
-
-void IMAPMessage::extract(utility::outputStream& os, utility::progressionListener* progress,
- const int start, const int length, const bool peek) const
-{
- if (!m_folder)
- throw exceptions::folder_not_found();
-
- extract(NULL, os, progress, start, length, false, peek);
-}
-
-
-void IMAPMessage::extractPart
- (const part& p, utility::outputStream& os, utility::progressionListener* progress,
- const int start, const int length, const bool peek) const
-{
- if (!m_folder)
- throw exceptions::folder_not_found();
-
- extract(&p, os, progress, start, length, false, peek);
-}
-
-
-void IMAPMessage::fetchPartHeader(part& p)
-{
- if (!m_folder)
- throw exceptions::folder_not_found();
-
- std::ostringstream oss;
- utility::outputStreamAdapter ossAdapter(oss);
-
- extract(&p, ossAdapter, NULL, 0, -1, true, true);
-
- static_cast <IMAPpart&>(p).getOrCreateHeader().parse(oss.str());
-}
-
-
-void IMAPMessage::extract(const part* p, utility::outputStream& os,
- utility::progressionListener* progress, const int start,
- const int length, const bool headerOnly, const bool peek) const
-{
- IMAPMessage_literalHandler literalHandler(os, progress);
-
- // Construct section identifier
- std::ostringstream section;
-
- if (p != NULL)
- {
- weak_ref <const IMAPpart> currentPart = static_cast <const IMAPpart*>(p);
- std::vector <int> numbers;
-
- numbers.push_back(currentPart->getNumber());
- currentPart = currentPart->getParent();
-
- while (currentPart != NULL)
- {
- numbers.push_back(currentPart->getNumber());
- currentPart = currentPart->getParent();
- }
-
- numbers.erase(numbers.end() - 1);
-
- for (std::vector <int>::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it)
- {
- if (it != numbers.rbegin()) section << ".";
- section << *it;
- }
- }
-
- // Build the request text
- std::ostringstream command;
-
- command << "FETCH " << m_num << " BODY";
- if (peek) command << ".PEEK";
- command << "[";
- command << section.str();
- if (headerOnly) command << ".MIME"; // "MIME" not "HEADER" for parts
- command << "]";
-
- if (start != 0 || length != -1)
- command << "<" << start << "." << length << ">";
-
- // Send the request
- m_folder->m_connection->send(true, command.str(), true);
-
- // Get the response
- utility::auto_ptr <IMAPParser::response> resp
- (m_folder->m_connection->readResponse(&literalHandler));
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("FETCH",
- m_folder->m_connection->getParser()->lastLine(), "bad response");
- }
-
-
- if (!headerOnly)
- {
- // TODO: update the flags (eg. flag "\Seen" may have been set)
- }
-}
-
-
-void IMAPMessage::fetch(IMAPFolder* folder, const int options)
-{
- if (m_folder != folder)
- throw exceptions::folder_not_found();
-
- // TODO: optimization: send the request for multiple
- // messages at the same time (FETCH x:y)
-
- // Example:
- // C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
- // S: * 2 FETCH ....
- // S: * 3 FETCH ....
- // S: * 4 FETCH ....
- // S: A654 OK FETCH completed
-
- std::vector <string> items;
-
- if (options & folder::FETCH_SIZE)
- items.push_back("RFC822.SIZE");
-
- if (options & folder::FETCH_FLAGS)
- items.push_back("FLAGS");
-
- if (options & folder::FETCH_STRUCTURE)
- items.push_back("BODYSTRUCTURE");
-
- if (options & folder::FETCH_UID)
- items.push_back("UID");
-
- if (options & folder::FETCH_FULL_HEADER)
- items.push_back("RFC822.HEADER");
- else
- {
- if (options & folder::FETCH_ENVELOPE)
- items.push_back("ENVELOPE");
-
- std::vector <string> headerFields;
-
- if (options & folder::FETCH_CONTENT_INFO)
- headerFields.push_back("CONTENT_TYPE");
-
- if (options & folder::FETCH_IMPORTANCE)
- {
- headerFields.push_back("IMPORTANCE");
- headerFields.push_back("X-PRIORITY");
- }
-
- if (!headerFields.empty())
- {
- string list;
-
- for (std::vector <string>::iterator it = headerFields.begin() ;
- it != headerFields.end() ; ++it)
- {
- if (it != headerFields.begin())
- list += " ";
-
- list += *it;
- }
-
- items.push_back("BODY[HEADER.FIELDS (" + list + ")]");
- }
- }
-
- // Build the request text
- std::ostringstream command;
- command << "FETCH " << m_num << " (";
-
- for (std::vector <string>::const_iterator it = items.begin() ;
- it != items.end() ; ++it)
- {
- if (it != items.begin()) command << " ";
- command << *it;
- }
-
- command << ")";
-
- // Send the request
- m_folder->m_connection->send(true, command.str(), true);
-
- // Get the response
- utility::auto_ptr <IMAPParser::response> resp(m_folder->m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("FETCH",
- m_folder->m_connection->getParser()->lastLine(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("FETCH",
- m_folder->m_connection->getParser()->lastLine(), "invalid response");
- }
-
- const IMAPParser::message_data* messageData =
- (*it)->response_data()->message_data();
-
- // We are only interested in responses of type "FETCH"
- if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
- continue;
-
- if (static_cast <int>(messageData->number()) != m_num)
- continue;
-
- // Process fetch response for this message
- processFetchResponse(options, messageData->msg_att());
- }
-}
-
-
-void IMAPMessage::processFetchResponse
- (const int options, const IMAPParser::msg_att* msgAtt)
-{
- // Get message attributes
- const std::vector <IMAPParser::msg_att_item*> atts =
- msgAtt->items();
-
- int flags = 0;
-
- for (std::vector <IMAPParser::msg_att_item*>::const_iterator
- it = atts.begin() ; it != atts.end() ; ++it)
- {
- switch ((*it)->type())
- {
- case IMAPParser::msg_att_item::FLAGS:
- {
- flags |= IMAPUtils::messageFlagsFromFlags((*it)->flag_list());
- break;
- }
- case IMAPParser::msg_att_item::UID:
- {
- std::ostringstream oss;
- oss << m_folder->m_uidValidity << ":" << (*it)->unique_id()->value();
-
- m_uid = oss.str();
- break;
- }
- case IMAPParser::msg_att_item::ENVELOPE:
- {
- if (!(options & folder::FETCH_FULL_HEADER))
- {
- const IMAPParser::envelope* env = (*it)->envelope();
- ref <vmime::header> hdr = getOrCreateHeader();
-
- // Date
- hdr->Date()->setValue(env->env_date()->value());
-
- // Subject
- text subject;
- text::decodeAndUnfold(env->env_subject()->value(), &subject);
-
- hdr->Subject()->setValue(subject);
-
- // From
- mailboxList from;
- convertAddressList(*(env->env_from()), from);
-
- if (!from.isEmpty())
- hdr->From()->setValue(*(from.getMailboxAt(0)));
-
- // To
- mailboxList to;
- convertAddressList(*(env->env_to()), to);
-
- hdr->To()->setValue(to);
-
- // Sender
- mailboxList sender;
- convertAddressList(*(env->env_sender()), sender);
-
- if (!sender.isEmpty())
- hdr->Sender()->setValue(*(sender.getMailboxAt(0)));
-
- // Reply-to
- mailboxList replyTo;
- convertAddressList(*(env->env_reply_to()), replyTo);
-
- if (!replyTo.isEmpty())
- hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0)));
-
- // Cc
- mailboxList cc;
- convertAddressList(*(env->env_cc()), cc);
-
- if (!cc.isEmpty())
- hdr->Cc()->setValue(cc);
-
- // Bcc
- mailboxList bcc;
- convertAddressList(*(env->env_bcc()), bcc);
-
- if (!bcc.isEmpty())
- hdr->Bcc()->setValue(bcc);
- }
-
- break;
- }
- case IMAPParser::msg_att_item::BODY_STRUCTURE:
- {
- m_structure = vmime::create <IMAPstructure>((*it)->body());
- break;
- }
- case IMAPParser::msg_att_item::RFC822_HEADER:
- {
- getOrCreateHeader()->parse((*it)->nstring()->value());
- break;
- }
- case IMAPParser::msg_att_item::RFC822_SIZE:
- {
- m_size = (*it)->number()->value();
- break;
- }
- case IMAPParser::msg_att_item::BODY_SECTION:
- {
- if (!(options & folder::FETCH_FULL_HEADER))
- {
- if ((*it)->section()->section_text1() &&
- (*it)->section()->section_text1()->type()
- == IMAPParser::section_text::HEADER_FIELDS)
- {
- header tempHeader;
- tempHeader.parse((*it)->nstring()->value());
-
- vmime::header& hdr = *getOrCreateHeader();
- std::vector <ref <headerField> > fields = tempHeader.getFieldList();
-
- for (std::vector <ref <headerField> >::const_iterator jt = fields.begin() ;
- jt != fields.end() ; ++jt)
- {
- hdr.appendField((*jt)->clone().dynamicCast <headerField>());
- }
- }
- }
-
- break;
- }
- case IMAPParser::msg_att_item::INTERNALDATE:
- case IMAPParser::msg_att_item::RFC822:
- case IMAPParser::msg_att_item::RFC822_TEXT:
- case IMAPParser::msg_att_item::BODY:
- {
- break;
- }
-
- }
- }
-
- if (options & folder::FETCH_FLAGS)
- m_flags = flags;
-}
-
-
-ref <header> IMAPMessage::getOrCreateHeader()
-{
- if (m_header != NULL)
- return (m_header);
- else
- return (m_header = vmime::create <header>());
-}
-
-
-void IMAPMessage::convertAddressList
- (const IMAPParser::address_list& src, mailboxList& dest)
-{
- for (std::vector <IMAPParser::address*>::const_iterator
- it = src.addresses().begin() ; it != src.addresses().end() ; ++it)
- {
- const IMAPParser::address& addr = **it;
-
- text name;
- text::decodeAndUnfold(addr.addr_name()->value(), &name);
-
- string email = addr.addr_mailbox()->value()
- + "@" + addr.addr_host()->value();
-
- dest.appendMailbox(vmime::create <mailbox>(name, email));
- }
-}
-
-
-void IMAPMessage::setFlags(const int flags, const int mode)
-{
- if (!m_folder)
- throw exceptions::folder_not_found();
- else if (m_folder->m_mode == folder::MODE_READ_ONLY)
- throw exceptions::illegal_state("Folder is read-only");
-
- // Build the request text
- std::ostringstream command;
- command << "STORE " << m_num;
-
- switch (mode)
- {
- case FLAG_MODE_ADD: command << " +FLAGS"; break;
- case FLAG_MODE_REMOVE: command << " -FLAGS"; break;
- default:
- case FLAG_MODE_SET: command << " FLAGS"; break;
- }
-
- if (m_flags == FLAG_UNDEFINED) // Update local flags only if they
- command << ".SILENT "; // have been fetched previously
- else
- command << " ";
-
- std::vector <string> flagList;
-
- if (flags & FLAG_REPLIED) flagList.push_back("\\Answered");
- if (flags & FLAG_MARKED) flagList.push_back("\\Flagged");
- if (flags & FLAG_DELETED) flagList.push_back("\\Deleted");
- if (flags & FLAG_SEEN) flagList.push_back("\\Seen");
-
- if (!flagList.empty())
- {
- command << "(";
-
- if (flagList.size() >= 2)
- {
- std::copy(flagList.begin(), flagList.end() - 1,
- std::ostream_iterator <string>(command, " "));
- }
-
- command << *(flagList.end() - 1) << ")";
-
- // Send the request
- m_folder->m_connection->send(true, command.str(), true);
-
- // Get the response
- utility::auto_ptr <IMAPParser::response> resp(m_folder->m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("STORE",
- m_folder->m_connection->getParser()->lastLine(), "bad response");
- }
-
- // Update the local flags for this message
- if (m_flags != FLAG_UNDEFINED)
- {
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- int newFlags = 0;
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- continue;
-
- const IMAPParser::message_data* messageData =
- (*it)->response_data()->message_data();
-
- // We are only interested in responses of type "FETCH"
- if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
- continue;
-
- // Get message attributes
- const std::vector <IMAPParser::msg_att_item*> atts =
- messageData->msg_att()->items();
-
- for (std::vector <IMAPParser::msg_att_item*>::const_iterator
- it = atts.begin() ; it != atts.end() ; ++it)
- {
- if ((*it)->type() == IMAPParser::msg_att_item::FLAGS)
- newFlags |= IMAPUtils::messageFlagsFromFlags((*it)->flag_list());
- }
- }
-
- m_flags = newFlags;
- }
-
- // Notify message flags changed
- std::vector <int> nums;
- nums.push_back(m_num);
-
- events::messageChangedEvent event
- (m_folder->thisRef().dynamicCast <folder>(),
- events::messageChangedEvent::TYPE_FLAGS, nums);
-
- for (std::list <IMAPFolder*>::iterator it = m_folder->m_store->m_folders.begin() ;
- it != m_folder->m_store->m_folders.end() ; ++it)
- {
- if ((*it)->getFullPath() == m_folder->m_path)
- (*it)->notifyMessageChanged(event);
- }
- }
-}
-
-
-} // imap
-} // messaging
-} // vmime