// // VMime library (http://vmime.sourceforge.net) // Copyright (C) 2002-2004 Vincent Richard // // 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 "maildirMessage.hpp" #include "maildirFolder.hpp" #include "maildirUtils.hpp" #include "../exception.hpp" #include "../platformDependant.hpp" namespace vmime { namespace messaging { // // maildirPart // class maildirStructure; class maildirPart : public part { public: maildirPart(maildirPart* parent, const int number, const bodyPart& part); const structure& getStructure() const; structure& getStructure(); 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 = new header())); } private: maildirStructure* m_structure; maildirPart* m_parent; 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(maildirPart* parent, const bodyPart& part) { int number = 1; const body* bdy = part.getBody(); for (int i = 0 ; i < bdy->getPartCount() ; ++i, ++number) m_parts.push_back(new maildirPart(parent, number, *bdy->getPartAt(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 m_parts; }; maildirStructure maildirStructure::m_emptyStructure; maildirPart::maildirPart(maildirPart* parent, const int number, const bodyPart& part) : m_parent(parent), m_number(number) { m_structure = new maildirStructure(this, part); m_headerParsedOffset = part.getHeader()->getParsedOffset(); m_headerParsedLength = part.getHeader()->getParsedLength(); m_bodyParsedOffset = part.getBody()->getParsedOffset(); m_bodyParsedLength = part.getBody()->getParsedLength(); } const structure& maildirPart::getStructure() const { return (*m_structure); } structure& maildirPart::getStructure() { return (*m_structure); } // // maildirMessage // maildirMessage::maildirMessage(maildirFolder* folder, const int num) : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), m_expunged(false), m_header(NULL), 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); } 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, progressionListener* progress, const int start, const int length) const { // TODO } void maildirMessage::extractPart(const part& p, utility::outputStream& os, progressionListener* progress, const int start, const int length) const { // TODO } void maildirMessage::fetchPartHeader(part& p) { // TODO } void maildirMessage::fetch(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); utility::auto_ptr 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)) { string contents; utility::auto_ptr reader = file->getFileReader(); utility::auto_ptr 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) { if (m_structure) delete (m_structure); m_structure = new maildirStructure(NULL, msg); } // Extract some header fields or whole header if (options & (folder::FETCH_ENVELOPE | folder::FETCH_CONTENT_INFO | folder::FETCH_FULL_HEADER)) { getOrCreateHeader().copyFrom(*(msg.getHeader())); } } } header& maildirMessage::getOrCreateHeader() { if (m_header != NULL) return (*m_header); else return (*(m_header = new header())); } } // messaging } // vmime