* Copyright 2007-2011, Haiku, Inc. All rights reserved.
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
Glue code for reading/writing messages directly from the protocols but
present a BPositionIO interface to the caller, while caching the data
read/written in a slave file.
*/
#include "MessageIO.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
BMailMessageIO::BMailMessageIO(POP3Protocol* protocol, BPositionIO* dumpTo,
int32 messageID)
:
fSlave(dumpTo),
fMessageID(messageID),
fProtocol(protocol),
fSize(0),
fState(READ_HEADER_NEXT)
{
}
BMailMessageIO::~BMailMessageIO()
{
}
ssize_t
BMailMessageIO::ReadAt(off_t pos, void* buffer, size_t amountToRead)
{
char lastBytes[5];
off_t oldPosition = fSlave->Position();
while (pos + amountToRead > fSize) {
if (fState >= ALL_READING_DONE)
break;
switch (fState) {
case READ_HEADER_NEXT:
{
fSlave->SetSize(0);
fSlave->Seek(0,SEEK_SET);
status_t status = fProtocol->GetHeader(fMessageID, fSlave);
if (status != B_OK)
return status;
fSlave->Seek(-4, SEEK_END);
strcpy(lastBytes, "xxxx");
fSlave->Read(lastBytes, 4);
if (strcmp(lastBytes, "\r\n\r\n") != 0) {
if (strcmp(lastBytes + 2, "\r\n") == 0)
fSlave->Write("\r\n", 2);
else
fSlave->Write("\r\n\r\n", 4);
}
fState = READ_BODY_NEXT;
break;
}
case READ_BODY_NEXT:
{
fSlave->SetSize(0);
fSlave->Seek(0,SEEK_SET);
status_t status = fProtocol->Retrieve(fMessageID, fSlave);
if (status < 0)
return status;
fState = ALL_READING_DONE;
break;
}
default:
return -1;
}
_ResetSize();
}
if (oldPosition < (off_t)fSize)
fSlave->Seek (oldPosition, SEEK_SET);
else
fSlave->Seek (0, SEEK_END);
return fSlave->ReadAt(pos, buffer, amountToRead);
}
ssize_t
BMailMessageIO::WriteAt(off_t pos, const void* buffer, size_t amountToWrite)
{
ssize_t bytesWritten = fSlave->WriteAt(pos, buffer, amountToWrite);
_ResetSize();
return bytesWritten;
}
off_t
BMailMessageIO::Seek(off_t position, uint32 seekMode)
{
if (seekMode == SEEK_END && fState != ALL_READING_DONE) {
char tempBuffer;
fState = READ_BODY_NEXT;
ssize_t bytesRead = ReadAt(fSize + 1, &tempBuffer, sizeof(tempBuffer));
if (bytesRead < 0)
return bytesRead;
}
return fSlave->Seek(position, seekMode);
}
off_t
BMailMessageIO::Position() const
{
return fSlave->Position();
}
void
BMailMessageIO::_ResetSize()
{
off_t old = fSlave->Position();
fSlave->Seek(0,SEEK_END);
fSize = fSlave->Position();
fSlave->Seek(old,SEEK_SET);
}