diff --git a/src/messaging/IMAPMessage.cpp b/src/messaging/IMAPMessage.cpp index 72f9ce31..d5ede663 100644 --- a/src/messaging/IMAPMessage.cpp +++ b/src/messaging/IMAPMessage.cpp @@ -32,31 +32,12 @@ namespace vmime { namespace messaging { -// -// IMAPheader -// - - -class IMAPheader : public header -{ -public: - - IMAPheader() - { - } - - void parse(const string& str) - { - header::parse(str); - } -}; - - - // // IMAPpart // +class IMAPstructure; + class IMAPpart : public part { private: @@ -75,7 +56,13 @@ public: const int getSize() const { return (m_size); } const int getNumber() const { return (m_number); } - const header& getHeader() const; + const header& getHeader() const + { + if (m_header == NULL) + throw exceptions::unfetched_object(); + else + return (*m_header); + } static IMAPpart* create(IMAPpart* parent, const int number, const IMAPParser::body* body) @@ -87,19 +74,19 @@ public: } - IMAPheader& getOrCreateHeader() + header& getOrCreateHeader() { if (m_header != NULL) return (*m_header); else - return (*(m_header = new IMAPheader())); + return (*(m_header = new header())); } private: IMAPstructure* m_structure; IMAPpart* m_parent; - IMAPheader* m_header; + header* m_header; int m_number; int m_size; @@ -112,7 +99,6 @@ private: // IMAPstructure // - class IMAPstructure : public structure { private: @@ -213,15 +199,6 @@ IMAPpart::IMAPpart(IMAPpart* parent, const int number, const IMAPParser::body_ty } -const class header& IMAPpart::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return (*m_header); -} - - const class structure& IMAPpart::getStructure() const { if (m_structure != NULL) @@ -297,7 +274,7 @@ IMAPMessage::~IMAPMessage() if (m_folder) m_folder->unregisterMessage(this); - delete dynamic_cast (m_header); + delete dynamic_cast (m_header); } @@ -674,7 +651,7 @@ void IMAPMessage::processFetchResponse (*it)->section()->section_text1()->type() == IMAPParser::section_text::HEADER_FIELDS) { - IMAPheader tempHeader; + header tempHeader; tempHeader.parse((*it)->nstring()->value()); vmime::header& hdr = getOrCreateHeader(); @@ -706,12 +683,12 @@ void IMAPMessage::processFetchResponse } -IMAPheader& IMAPMessage::getOrCreateHeader() +header& IMAPMessage::getOrCreateHeader() { if (m_header != NULL) return (*m_header); else - return (*(m_header = new IMAPheader())); + return (*(m_header = new header())); } diff --git a/src/messaging/IMAPMessage.hpp b/src/messaging/IMAPMessage.hpp index 0bf874b9..430a0fbd 100644 --- a/src/messaging/IMAPMessage.hpp +++ b/src/messaging/IMAPMessage.hpp @@ -30,10 +30,6 @@ namespace vmime { namespace messaging { -class IMAPheader; -class IMAPstructure; - - /** IMAP message implementation. */ @@ -83,7 +79,7 @@ private: void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest); - IMAPheader& getOrCreateHeader(); + header& getOrCreateHeader(); void onFolderClosed(); @@ -96,8 +92,8 @@ private: bool m_expunged; uid m_uid; - class IMAPheader* m_header; - class IMAPstructure* m_structure; + header* m_header; + structure* m_structure; }; diff --git a/src/messaging/maildirFolder.cpp b/src/messaging/maildirFolder.cpp index c5c1054a..854e7dfb 100644 --- a/src/messaging/maildirFolder.cpp +++ b/src/messaging/maildirFolder.cpp @@ -276,7 +276,7 @@ void maildirFolder::scanFolder() while (nit->hasMoreElements()) { utility::auto_ptr file = nit->nextElement(); - newMessageFilenames.push_back(file->fullPath().getLastComponent()); + newMessageFilenames.push_back(file->getFullPath().getLastComponent()); } // Current messages (cur/) @@ -286,7 +286,7 @@ void maildirFolder::scanFolder() while (cit->hasMoreElements()) { utility::auto_ptr file = cit->nextElement(); - curMessageFilenames.push_back(file->fullPath().getLastComponent()); + curMessageFilenames.push_back(file->getFullPath().getLastComponent()); } // Update/delete existing messages (found in previous scan) @@ -465,7 +465,7 @@ void maildirFolder::listFolders(std::vector & list, const bool recursiv if (maildirUtils::isSubfolderDirectory(*file)) { - const utility::path subPath = m_path / file->fullPath().getLastComponent(); + const utility::path subPath = m_path / file->getFullPath().getLastComponent(); maildirFolder* subFolder = new maildirFolder(subPath, m_store); list.push_back(subFolder); diff --git a/src/messaging/maildirMessage.cpp b/src/messaging/maildirMessage.cpp index 12ac8cdf..e87b73ab 100644 --- a/src/messaging/maildirMessage.cpp +++ b/src/messaging/maildirMessage.cpp @@ -29,9 +29,154 @@ 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_expunged(false), m_header(NULL), m_structure(NULL) { m_folder->registerMessage(this); } @@ -79,19 +224,28 @@ const bool maildirMessage::isExpunged() const const structure& maildirMessage::getStructure() const { - // TODO + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return (*m_structure); } structure& maildirMessage::getStructure() { - // TODO + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return (*m_structure); } const header& maildirMessage::getHeader() const { - // TODO + if (m_header == NULL) + throw exceptions::unfetched_object(); + + return (*m_header); } @@ -143,21 +297,93 @@ void maildirMessage::fetch(maildirFolder* folder, const int options) const utility::file::path path = folder->getMessageFSPath(m_num); utility::auto_ptr file = fsf->create(path); - /* - TODO: FETCH_ENVELOPE - TODO: FETCH_STRUCTURE - TODO: FETCH_CONTENT_INFO - TODO: FETCH_FULL_HEADER - */ - if (options & folder::FETCH_FLAGS) m_flags = maildirUtils::extractFlags(path.getLastComponent()); if (options & folder::FETCH_SIZE) - m_size = file->length(); + 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())); } diff --git a/src/messaging/maildirMessage.hpp b/src/messaging/maildirMessage.hpp index 0b543bc2..f487b32d 100644 --- a/src/messaging/maildirMessage.hpp +++ b/src/messaging/maildirMessage.hpp @@ -75,6 +75,8 @@ private: void onFolderClosed(); + header& getOrCreateHeader(); + maildirFolder* m_folder; @@ -83,6 +85,9 @@ private: int m_flags; bool m_expunged; uid m_uid; + + header* m_header; + structure* m_structure; }; diff --git a/src/messaging/maildirUtils.cpp b/src/messaging/maildirUtils.cpp index 4cf40c9c..e620ce0a 100644 --- a/src/messaging/maildirUtils.cpp +++ b/src/messaging/maildirUtils.cpp @@ -75,8 +75,8 @@ const bool maildirUtils::isSubfolderDirectory(const utility::file& file) // A directory which name does not start with '.' // is listed as a sub-folder... if (file.isDirectory() && - file.fullPath().getLastComponent().getBuffer().length() >= 1 && - file.fullPath().getLastComponent().getBuffer()[0] != '.') + file.getFullPath().getLastComponent().getBuffer().length() >= 1 && + file.getFullPath().getLastComponent().getBuffer()[0] != '.') { return (true); } diff --git a/src/messaging/message.hpp b/src/messaging/message.hpp index 825e1021..fb6cfed1 100644 --- a/src/messaging/message.hpp +++ b/src/messaging/message.hpp @@ -120,10 +120,10 @@ protected: structure() { } structure(const structure&) { } - virtual ~structure() { } - public: + virtual ~structure() { } + /** Return the part at the specified position. * * @param x position