summaryrefslogtreecommitdiffstats
path: root/libmail/mboxgetmessage.C
diff options
context:
space:
mode:
Diffstat (limited to 'libmail/mboxgetmessage.C')
-rw-r--r--libmail/mboxgetmessage.C195
1 files changed, 195 insertions, 0 deletions
diff --git a/libmail/mboxgetmessage.C b/libmail/mboxgetmessage.C
new file mode 100644
index 0000000..dfd775b
--- /dev/null
+++ b/libmail/mboxgetmessage.C
@@ -0,0 +1,195 @@
+/*
+** Copyright 2002-2006, Double Precision Inc.
+**
+** See COPYING for distribution information.
+*/
+#include "libmail_config.h"
+
+#include "mboxgetmessage.H"
+#include "file.H"
+#include "rfc2045/rfc2045.h"
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+using namespace std;
+
+mail::mbox::GenericGetMessageTask::GenericGetMessageTask(mail::mbox &mboxAccount,
+ mail::callback
+ &callbackArg,
+ string uidArg,
+ size_t
+ messageNumberArg,
+ bool peekArg,
+ int *fdretArg,
+ struct rfc2045
+ **structretArg)
+ : LockTask(mboxAccount, callbackArg),
+ uid(uidArg),
+ messageNumber(messageNumberArg),
+ peek(peekArg),
+ fdret(fdretArg),
+ structret(structretArg),
+
+ tempFp(NULL),
+ tempStruct(NULL)
+{
+}
+
+mail::mbox::GenericGetMessageTask::~GenericGetMessageTask()
+{
+ // tempFp/tempStruct should be null, if all's well. If not, clean up
+ // after outselves.
+
+ if (tempFp)
+ fclose(tempFp);
+
+ if (tempStruct)
+ rfc2045_free(tempStruct);
+}
+
+bool mail::mbox::GenericGetMessageTask::locked(mail::file &file)
+{
+ if (!mboxAccount.verifyUid(uid, messageNumber, callback))
+ {
+ done();
+ return true;
+ }
+
+ mail::ptr<mail::mbox> me= &mboxAccount;
+
+ size_t realMsgNum=mboxAccount.uidmap.find(uid)->second;
+
+ off_t startingPos=mboxAccount.folderMessageIndex[realMsgNum]
+ .startingPos;
+
+ if (fseek(file, startingPos, SEEK_SET) < 0 ||
+ (tempFp=tmpfile()) == NULL ||
+ (tempStruct=rfc2045_alloc()) == NULL)
+ {
+ fail(strerror(errno));
+ return true;
+ }
+
+ off_t endingPos=0;
+
+ if (realMsgNum + 1 >= mboxAccount.folderMessageIndex.size())
+ {
+ struct stat stat_buf;
+
+ if (fstat(fileno(static_cast<FILE *>(file)), &stat_buf) < 0)
+ endingPos=stat_buf.st_size;
+ }
+ else
+ endingPos=mboxAccount.folderMessageIndex[realMsgNum+1]
+ .startingPos;
+
+ if (endingPos >= startingPos)
+ endingPos -= startingPos;
+ else
+ endingPos=0;
+
+ off_t nextUpdatePos=startingPos;
+
+ bool firstLine=true;
+
+ while (!feof(file) && !me.isDestroyed())
+ {
+ off_t pos=file.tell();
+
+ // Progress update every 10K
+ if (pos >= nextUpdatePos)
+ {
+ nextUpdatePos=pos + 10000;
+
+ callback.reportProgress(pos - startingPos, endingPos,
+ 0, 1);
+ }
+
+ string line=file.getline();
+
+ if (line.size() == 0 && feof(file))
+ break;
+
+ if (strncmp(line.c_str(), "From ", 5) == 0)
+ {
+ if (firstLine)
+ continue;
+
+ break;
+ }
+
+ if (firstLine)
+ {
+ firstLine=false;
+
+ if (mail::mboxMagicTag(line,
+ mboxAccount.keywordHashtable)
+ .good())
+ continue; // Ignore magic tag line.
+ }
+
+ const char *p=line.c_str();
+
+ if (*p == '>')
+ {
+ while (*p == '>')
+ p++;
+
+ if (strncmp(p, "From ", 5) == 0)
+ line=line.substr(1);
+ }
+
+ line += "\n";
+
+ if (fwrite(&line[0], line.size(), 1, tempFp) != 1)
+ ; // Ignore gcc warning
+
+ rfc2045_parse(tempStruct, &line[0], line.size());
+ }
+
+ if (fflush(tempFp) < 0 || ferror(tempFp) < 0)
+ {
+ fail(strerror(errno));
+ return true;
+ }
+
+ mboxAccount.cachedMessageUid="";
+ if (mboxAccount.cachedMessageFp)
+ fclose(mboxAccount.cachedMessageFp);
+ if (mboxAccount.cachedMessageRfcp)
+ rfc2045_free(mboxAccount.cachedMessageRfcp);
+
+ mboxAccount.cachedMessageFp=NULL;
+ mboxAccount.cachedMessageRfcp=NULL;
+
+ mboxAccount.cachedMessageUid=uid;
+ mboxAccount.cachedMessageFp=tempFp;
+ mboxAccount.cachedMessageRfcp=tempStruct;
+
+ fcntl(fileno(tempFp), F_SETFD, FD_CLOEXEC);
+
+ tempFp=NULL;
+ tempStruct=NULL;
+
+ if (fdret)
+ *fdret=fileno(mboxAccount.cachedMessageFp);
+ if (structret)
+ *structret=mboxAccount.cachedMessageRfcp;
+
+ if (mboxAccount.currentFolderCallback && !peek &&
+ mboxAccount.index[messageNumber].unread)
+ {
+ mboxAccount.index[messageNumber].unread=false;
+ mboxAccount.folderDirty=true;
+ mboxAccount.currentFolderCallback->messageChanged(messageNumber);
+ }
+
+ callback.success("OK");
+ done();
+ return true;
+}
+