Working on 'maildir' implementation.

This commit is contained in:
Vincent Richard 2004-12-15 22:17:03 +00:00
parent 50a6a9cdfa
commit 78b3909d9b
7 changed files with 269 additions and 65 deletions

View File

@ -32,31 +32,12 @@ namespace vmime {
namespace messaging { namespace messaging {
//
// IMAPheader
//
class IMAPheader : public header
{
public:
IMAPheader()
{
}
void parse(const string& str)
{
header::parse(str);
}
};
// //
// IMAPpart // IMAPpart
// //
class IMAPstructure;
class IMAPpart : public part class IMAPpart : public part
{ {
private: private:
@ -75,7 +56,13 @@ public:
const int getSize() const { return (m_size); } const int getSize() const { return (m_size); }
const int getNumber() const { return (m_number); } 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) 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) if (m_header != NULL)
return (*m_header); return (*m_header);
else else
return (*(m_header = new IMAPheader())); return (*(m_header = new header()));
} }
private: private:
IMAPstructure* m_structure; IMAPstructure* m_structure;
IMAPpart* m_parent; IMAPpart* m_parent;
IMAPheader* m_header; header* m_header;
int m_number; int m_number;
int m_size; int m_size;
@ -112,7 +99,6 @@ private:
// IMAPstructure // IMAPstructure
// //
class IMAPstructure : public structure class IMAPstructure : public structure
{ {
private: 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 const class structure& IMAPpart::getStructure() const
{ {
if (m_structure != NULL) if (m_structure != NULL)
@ -297,7 +274,7 @@ IMAPMessage::~IMAPMessage()
if (m_folder) if (m_folder)
m_folder->unregisterMessage(this); m_folder->unregisterMessage(this);
delete dynamic_cast <IMAPheader*>(m_header); delete dynamic_cast <header*>(m_header);
} }
@ -674,7 +651,7 @@ void IMAPMessage::processFetchResponse
(*it)->section()->section_text1()->type() (*it)->section()->section_text1()->type()
== IMAPParser::section_text::HEADER_FIELDS) == IMAPParser::section_text::HEADER_FIELDS)
{ {
IMAPheader tempHeader; header tempHeader;
tempHeader.parse((*it)->nstring()->value()); tempHeader.parse((*it)->nstring()->value());
vmime::header& hdr = getOrCreateHeader(); vmime::header& hdr = getOrCreateHeader();
@ -706,12 +683,12 @@ void IMAPMessage::processFetchResponse
} }
IMAPheader& IMAPMessage::getOrCreateHeader() header& IMAPMessage::getOrCreateHeader()
{ {
if (m_header != NULL) if (m_header != NULL)
return (*m_header); return (*m_header);
else else
return (*(m_header = new IMAPheader())); return (*(m_header = new header()));
} }

View File

@ -30,10 +30,6 @@ namespace vmime {
namespace messaging { namespace messaging {
class IMAPheader;
class IMAPstructure;
/** IMAP message implementation. /** IMAP message implementation.
*/ */
@ -83,7 +79,7 @@ private:
void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest); void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest);
IMAPheader& getOrCreateHeader(); header& getOrCreateHeader();
void onFolderClosed(); void onFolderClosed();
@ -96,8 +92,8 @@ private:
bool m_expunged; bool m_expunged;
uid m_uid; uid m_uid;
class IMAPheader* m_header; header* m_header;
class IMAPstructure* m_structure; structure* m_structure;
}; };

View File

@ -276,7 +276,7 @@ void maildirFolder::scanFolder()
while (nit->hasMoreElements()) while (nit->hasMoreElements())
{ {
utility::auto_ptr <utility::file> file = nit->nextElement(); utility::auto_ptr <utility::file> file = nit->nextElement();
newMessageFilenames.push_back(file->fullPath().getLastComponent()); newMessageFilenames.push_back(file->getFullPath().getLastComponent());
} }
// Current messages (cur/) // Current messages (cur/)
@ -286,7 +286,7 @@ void maildirFolder::scanFolder()
while (cit->hasMoreElements()) while (cit->hasMoreElements())
{ {
utility::auto_ptr <utility::file> file = cit->nextElement(); utility::auto_ptr <utility::file> file = cit->nextElement();
curMessageFilenames.push_back(file->fullPath().getLastComponent()); curMessageFilenames.push_back(file->getFullPath().getLastComponent());
} }
// Update/delete existing messages (found in previous scan) // Update/delete existing messages (found in previous scan)
@ -465,7 +465,7 @@ void maildirFolder::listFolders(std::vector <folder*>& list, const bool recursiv
if (maildirUtils::isSubfolderDirectory(*file)) 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); maildirFolder* subFolder = new maildirFolder(subPath, m_store);
list.push_back(subFolder); list.push_back(subFolder);

View File

@ -29,9 +29,154 @@ namespace vmime {
namespace messaging { 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 <maildirPart*> 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) 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_expunged(false), m_header(NULL), m_structure(NULL)
{ {
m_folder->registerMessage(this); m_folder->registerMessage(this);
} }
@ -79,19 +224,28 @@ const bool maildirMessage::isExpunged() const
const structure& maildirMessage::getStructure() const const structure& maildirMessage::getStructure() const
{ {
// TODO if (m_structure == NULL)
throw exceptions::unfetched_object();
return (*m_structure);
} }
structure& maildirMessage::getStructure() structure& maildirMessage::getStructure()
{ {
// TODO if (m_structure == NULL)
throw exceptions::unfetched_object();
return (*m_structure);
} }
const header& maildirMessage::getHeader() const 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); const utility::file::path path = folder->getMessageFSPath(m_num);
utility::auto_ptr <utility::file> file = fsf->create(path); utility::auto_ptr <utility::file> file = fsf->create(path);
/*
TODO: FETCH_ENVELOPE
TODO: FETCH_STRUCTURE
TODO: FETCH_CONTENT_INFO
TODO: FETCH_FULL_HEADER
*/
if (options & folder::FETCH_FLAGS) if (options & folder::FETCH_FLAGS)
m_flags = maildirUtils::extractFlags(path.getLastComponent()); m_flags = maildirUtils::extractFlags(path.getLastComponent());
if (options & folder::FETCH_SIZE) if (options & folder::FETCH_SIZE)
m_size = file->length(); m_size = file->getLength();
if (options & folder::FETCH_UID) if (options & folder::FETCH_UID)
m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer(); 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 <utility::fileReader> reader = file->getFileReader();
utility::auto_ptr <utility::inputStream> 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()));
} }

View File

@ -75,6 +75,8 @@ private:
void onFolderClosed(); void onFolderClosed();
header& getOrCreateHeader();
maildirFolder* m_folder; maildirFolder* m_folder;
@ -83,6 +85,9 @@ private:
int m_flags; int m_flags;
bool m_expunged; bool m_expunged;
uid m_uid; uid m_uid;
header* m_header;
structure* m_structure;
}; };

View File

@ -75,8 +75,8 @@ const bool maildirUtils::isSubfolderDirectory(const utility::file& file)
// A directory which name does not start with '.' // A directory which name does not start with '.'
// is listed as a sub-folder... // is listed as a sub-folder...
if (file.isDirectory() && if (file.isDirectory() &&
file.fullPath().getLastComponent().getBuffer().length() >= 1 && file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
file.fullPath().getLastComponent().getBuffer()[0] != '.') file.getFullPath().getLastComponent().getBuffer()[0] != '.')
{ {
return (true); return (true);
} }

View File

@ -120,10 +120,10 @@ protected:
structure() { } structure() { }
structure(const structure&) { } structure(const structure&) { }
virtual ~structure() { }
public: public:
virtual ~structure() { }
/** Return the part at the specified position. /** Return the part at the specified position.
* *
* @param x position * @param x position