Bug 239583 - mail lost when getting fetchmailed messages.
r=bienvenu@nventure.com, sr=mscott@mozilla.org, a=chofmann@mozilla.org
This commit is contained in:
Родитель
70c823a320
Коммит
6207840361
|
@ -70,6 +70,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "prlog.h"
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
|
@ -178,10 +182,9 @@ PRBool ObtainSpoolLock(const char *spoolnameStr,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// Create nsFileSpec and nsILocalFile for the spool.mozlock file
|
||||
nsFileSpec tmplocspec(mozlockstr.get());
|
||||
// Create nsILocalFile for the spool.mozlock file
|
||||
nsCOMPtr<nsILocalFile> tmplocfile;
|
||||
rv = NS_FileSpecToIFile(&tmplocspec, getter_AddRefs(tmplocfile));
|
||||
rv = NS_NewNativeLocalFile(mozlockstr, PR_TRUE, getter_AddRefs(tmplocfile));
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
// THOUGHT: hmm, perhaps use MakeUnique to generate us a unique mozlock?
|
||||
|
@ -189,7 +192,7 @@ PRBool ObtainSpoolLock(const char *spoolnameStr,
|
|||
|
||||
// step 1: create SPOOLNAME.mozlock
|
||||
rv = tmplocfile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
|
||||
if ( NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
// can't create our .mozlock file... game over already
|
||||
LOG(("Failed to create file %s\n", mozlockstr.get()));
|
||||
return PR_FALSE;
|
||||
|
@ -203,19 +206,17 @@ PRBool ObtainSpoolLock(const char *spoolnameStr,
|
|||
int retry_count = 0;
|
||||
|
||||
do {
|
||||
link_result =
|
||||
link(mozlockstr.get(),lockstr.get());
|
||||
link_result = link(mozlockstr.get(),lockstr.get());
|
||||
|
||||
retry_count++;
|
||||
LOG(("Attempt %d of %d to create lock file", retry_count, seconds));
|
||||
|
||||
if ((seconds > 0) &&
|
||||
(link_result == -1)) {
|
||||
if (seconds > 0 && link_result == -1) {
|
||||
// pause 1sec, waiting for .lock to go away
|
||||
PRIntervalTime sleepTime = 1000; // 1 second
|
||||
PR_Sleep(sleepTime);
|
||||
}
|
||||
} while ((link_result == -1) && (retry_count < seconds));
|
||||
} while (link_result == -1 && retry_count < seconds);
|
||||
LOG(("Link result: %d", link_result));
|
||||
|
||||
// step 3: remove .mozlock file, in any case
|
||||
|
@ -245,10 +246,9 @@ PRBool YieldSpoolLock(const char *spoolnameStr)
|
|||
|
||||
nsresult rv;
|
||||
|
||||
// Create nsFileSpec and nsILocalFile for the spool.lock file
|
||||
nsFileSpec locklocspec(lockstr.get());
|
||||
// Create nsILocalFile for the spool.lock file
|
||||
nsCOMPtr<nsILocalFile> locklocfile;
|
||||
rv = NS_FileSpecToIFile(&locklocspec, getter_AddRefs(locklocfile));
|
||||
rv = NS_NewNativeLocalFile(lockstr, PR_TRUE, getter_AddRefs(locklocfile));
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
|
@ -271,6 +271,48 @@ PRBool YieldSpoolLock(const char *spoolnameStr)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
LocateSpoolFile(nsACString & spoolPath)
|
||||
{
|
||||
PRBool isFile;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsILocalFile> spoolFile;
|
||||
rv = NS_NewNativeLocalFile(nsCString(), PR_TRUE, getter_AddRefs(spoolFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char * mailEnv = PR_GetEnv("MAIL");
|
||||
char * userEnv = PR_GetEnv("USER");
|
||||
if (!userEnv)
|
||||
userEnv = PR_GetEnv("USERNAME");
|
||||
|
||||
if (mailEnv) {
|
||||
rv = spoolFile->InitWithNativePath(nsDependentCString(mailEnv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = spoolFile->IsFile(&isFile);
|
||||
if (NS_SUCCEEDED(rv) && isFile)
|
||||
spoolPath = mailEnv;
|
||||
}
|
||||
else if (userEnv) {
|
||||
// Try to build the mailbox path from the username and a number
|
||||
// of guessed spool directory paths.
|
||||
nsCAutoString tmpPath;
|
||||
PRUint32 i;
|
||||
for (i = 0; i < NUM_DEFAULT_SPOOL_PATHS; i++) {
|
||||
tmpPath = gDefaultSpoolPaths[i];
|
||||
tmpPath += userEnv;
|
||||
rv = spoolFile->InitWithNativePath(tmpPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = spoolFile->IsFile(&isFile);
|
||||
if (NS_SUCCEEDED(rv) && isFile) {
|
||||
spoolPath = tmpPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMovemailService::GetNewMail(nsIMsgWindow *aMsgWindow,
|
||||
|
@ -287,196 +329,137 @@ nsMovemailService::GetNewMail(nsIMsgWindow *aMsgWindow,
|
|||
if (!in_server)
|
||||
return NS_MSG_INVALID_OR_MISSING_SERVER;
|
||||
mMsgWindow = aMsgWindow;
|
||||
nsCAutoString wholeboxname;
|
||||
|
||||
// Attempt to locate the mail spool file
|
||||
nsCAutoString spoolPath;
|
||||
rv = LocateSpoolFile(spoolPath);
|
||||
if (NS_FAILED(rv) || spoolPath.IsEmpty()) {
|
||||
Error(MOVEMAIL_SPOOL_FILE_NOT_FOUND, nsnull, 0);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Create an input stream for the spool file
|
||||
nsCOMPtr<nsILocalFile> spoolFile;
|
||||
rv = NS_NewNativeLocalFile(spoolPath, PR_TRUE, getter_AddRefs(spoolFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIInputStream> spoolInputStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(spoolInputStream), spoolFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
const PRUnichar *params[] = {
|
||||
NS_ConvertUTF8toUCS2(spoolPath).get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_OPEN_SPOOL_FILE, params, 1);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get a line input interface for the spool file
|
||||
nsCOMPtr<nsILineInputStream> lineInputStream =
|
||||
do_QueryInterface(spoolInputStream, &rv);
|
||||
if (!lineInputStream)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> mailDirectory;
|
||||
rv = in_server->GetLocalPath(getter_AddRefs(mailDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsFileSpec fileSpec;
|
||||
mailDirectory->GetFileSpec(&fileSpec);
|
||||
fileSpec += "Inbox";
|
||||
nsIOFileStream outFileStream(fileSpec);
|
||||
outFileStream.seek(fileSpec.GetFileSize());
|
||||
nsCOMPtr<nsIMsgFolder> serverFolder;
|
||||
nsCOMPtr<nsIMsgFolder> inbox;
|
||||
nsCOMPtr<nsIMsgFolder> rootMsgFolder;
|
||||
|
||||
// create a new mail parser
|
||||
nsRefPtr<nsParseNewMailState> newMailParser = new nsParseNewMailState;
|
||||
if (newMailParser == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = in_server->GetRootFolder(getter_AddRefs(serverFolder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rootMsgFolder = do_QueryInterface(serverFolder, &rv);
|
||||
if (!rootMsgFolder)
|
||||
return rv;
|
||||
PRUint32 numFolders;
|
||||
rv = rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, 1,
|
||||
&numFolders,
|
||||
getter_AddRefs(inbox));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = newMailParser->Init(serverFolder, inbox,
|
||||
fileSpec, &outFileStream, nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
in_server->SetServerBusy(PR_TRUE);
|
||||
|
||||
// FUN STUFF starts here
|
||||
{
|
||||
// we now quest for the mail spool file...
|
||||
nsFileSpec spoolFileSpec;
|
||||
PRBool foundSpoolFile = PR_FALSE;
|
||||
|
||||
// If $(MAIL) is set then we have things easy.
|
||||
char * mailEnv = PR_GetEnv("MAIL");
|
||||
char * userEnv = PR_GetEnv("USER");
|
||||
if (!userEnv)
|
||||
userEnv = PR_GetEnv("USERNAME");
|
||||
|
||||
if (mailEnv) {
|
||||
wholeboxname = mailEnv;
|
||||
spoolFileSpec = wholeboxname.get();
|
||||
foundSpoolFile = (spoolFileSpec.Valid() && spoolFileSpec.IsFile());
|
||||
} else if (userEnv) {
|
||||
// Otherwise try to build the mailbox path from the
|
||||
// username and a number of guessed spool directory
|
||||
// paths.
|
||||
int i;
|
||||
for (i = 0; i < NUM_DEFAULT_SPOOL_PATHS && !foundSpoolFile; i++) {
|
||||
wholeboxname = gDefaultSpoolPaths[i];
|
||||
wholeboxname += userEnv;
|
||||
spoolFileSpec = wholeboxname.get();
|
||||
foundSpoolFile = (spoolFileSpec.Valid() && spoolFileSpec.IsFile());
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSpoolFile) {
|
||||
Error(MOVEMAIL_SPOOL_FILE_NOT_FOUND, nsnull, 0);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsInputFileStream spoolfile(spoolFileSpec);
|
||||
if (!spoolfile.is_open() || spoolfile.failed()) {
|
||||
const PRUnichar *params[] = {
|
||||
NS_ConvertUTF8toUCS2(wholeboxname).get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_OPEN_SPOOL_FILE, params, 1);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Try and obtain the lock for the spool file
|
||||
if (!ObtainSpoolLock(wholeboxname.get(), 5)) {
|
||||
nsAutoString lockFile = NS_ConvertUTF8toUCS2(wholeboxname);
|
||||
lockFile += NS_LITERAL_STRING(".lock");
|
||||
const PRUnichar *params[] = {
|
||||
lockFile.get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_CREATE_LOCK, params, 1);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Try and obtain the lock for the spool file
|
||||
if (!ObtainSpoolLock(spoolPath.get(), 5)) {
|
||||
nsAutoString lockFile = NS_ConvertUTF8toUCS2(spoolPath);
|
||||
lockFile += NS_LITERAL_STRING(".lock");
|
||||
const PRUnichar *params[] = {
|
||||
lockFile.get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_CREATE_LOCK, params, 1);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#define READBUFSIZE 4096
|
||||
char * buffer = (char*)PR_CALLOC(READBUFSIZE);
|
||||
nsParseNewMailState *newMailParser = nsnull;
|
||||
if (!buffer)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else {
|
||||
nsCOMPtr<nsIFileSpec> mailDirectory;
|
||||
rv = in_server->GetLocalPath(getter_AddRefs(mailDirectory));
|
||||
if (NS_FAILED(rv))
|
||||
goto freebuff_and_unlock;
|
||||
|
||||
nsFileSpec fileSpec;
|
||||
mailDirectory->GetFileSpec(&fileSpec);
|
||||
fileSpec += "Inbox";
|
||||
nsIOFileStream outFileStream(fileSpec);
|
||||
outFileStream.seek(fileSpec.GetFileSize());
|
||||
|
||||
// create a new mail parser
|
||||
newMailParser = new nsParseNewMailState;
|
||||
NS_IF_ADDREF(newMailParser);
|
||||
if (newMailParser == nsnull) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto freebuff_and_unlock;
|
||||
}
|
||||
|
||||
nsCOMPtr <nsIMsgFolder> serverFolder;
|
||||
rv = in_server->GetRootFolder(getter_AddRefs(serverFolder));
|
||||
// MIDDLE of the FUN : consume the mailbox data.
|
||||
PRBool isMore = PR_TRUE;
|
||||
nsAutoString bufferUnicode;
|
||||
nsCAutoString buffer;
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
goto freebuff_and_unlock;
|
||||
|
||||
nsCOMPtr<nsIMsgFolder> inbox;
|
||||
nsCOMPtr<nsIMsgFolder> rootMsgFolder = do_QueryInterface(serverFolder);
|
||||
if (!rootMsgFolder)
|
||||
goto freebuff_and_unlock;
|
||||
PRUint32 numFolders;
|
||||
rv = rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, 1,
|
||||
&numFolders,
|
||||
getter_AddRefs(inbox));
|
||||
if (NS_FAILED(rv))
|
||||
goto freebuff_and_unlock;
|
||||
rv = newMailParser->Init(serverFolder, inbox,
|
||||
fileSpec, &outFileStream, nsnull);
|
||||
if (NS_FAILED(rv))
|
||||
goto freebuff_and_unlock;
|
||||
|
||||
|
||||
// MIDDLE of the FUN : consume the mailbox data.
|
||||
{
|
||||
int numlines = 0;
|
||||
while (isMore &&
|
||||
NS_SUCCEEDED(lineInputStream->ReadLine(bufferUnicode, &isMore)))
|
||||
{
|
||||
CopyUCS2toASCII(bufferUnicode, buffer);
|
||||
|
||||
// main parsing loop
|
||||
while (!spoolfile.eof() &&
|
||||
!spoolfile.failed() &&
|
||||
spoolfile.is_open())
|
||||
{
|
||||
spoolfile.readline(buffer,
|
||||
READBUFSIZE-(1+PL_strlen(MSG_LINEBREAK)));
|
||||
|
||||
// 'From' lines delimit messages
|
||||
if ((numlines>0) &&
|
||||
nsCRT::strncmp(buffer, "From ", 5) == 0) {
|
||||
numlines = 0;
|
||||
}
|
||||
|
||||
// If first string is empty and we're now at EOF
|
||||
// (or, alternatively, we got a 'From' line and
|
||||
// then the file mysteriously ended) then abort
|
||||
// parsing.
|
||||
if (numlines == 0 && !*buffer && spoolfile.eof()) {
|
||||
LOG(("Empty spool file"));
|
||||
break; // end the parsing loop right here
|
||||
}
|
||||
|
||||
PL_strcpy(&buffer[PL_strlen(buffer)], MSG_LINEBREAK);
|
||||
|
||||
newMailParser->HandleLine(buffer, PL_strlen(buffer));
|
||||
outFileStream << buffer;
|
||||
|
||||
numlines++;
|
||||
|
||||
if (numlines == 1 && !spoolfile.eof()) {
|
||||
PL_strcpy(buffer, "X-Mozilla-Status: 8000"
|
||||
MSG_LINEBREAK);
|
||||
newMailParser->HandleLine(buffer,
|
||||
PL_strlen(buffer));
|
||||
outFileStream << buffer;
|
||||
PL_strcpy(buffer, "X-Mozilla-Status2: 00000000"
|
||||
MSG_LINEBREAK);
|
||||
newMailParser->HandleLine(buffer,
|
||||
PL_strlen(buffer));
|
||||
outFileStream << buffer;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// END
|
||||
outFileStream.flush(); // try this.
|
||||
newMailParser->OnStopRequest(nsnull, nsnull, NS_OK);
|
||||
newMailParser->SetDBFolderStream(nsnull); // stream is going away
|
||||
if (outFileStream.is_open())
|
||||
outFileStream.close();
|
||||
|
||||
// truncate the spool file here.
|
||||
nsFileSpec filespecForTrunc(wholeboxname.get());
|
||||
rv = filespecForTrunc.Truncate(0);
|
||||
if (NS_FAILED(rv)) {
|
||||
const PRUnichar *params[] = {
|
||||
NS_ConvertUTF8toUCS2(wholeboxname).get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_TRUNCATE_SPOOL_FILE, params, 1);
|
||||
}
|
||||
|
||||
if (spoolfile.is_open())
|
||||
spoolfile.close();
|
||||
// If first string is empty and we're now at EOF then abort parsing.
|
||||
if (buffer.IsEmpty() && !isMore) {
|
||||
LOG(("Empty spool file"));
|
||||
break;
|
||||
}
|
||||
|
||||
freebuff_and_unlock:
|
||||
PR_Free(buffer);
|
||||
NS_IF_RELEASE(newMailParser);
|
||||
if (!YieldSpoolLock(wholeboxname.get())) {
|
||||
nsAutoString spoolLock = NS_ConvertUTF8toUCS2(wholeboxname);
|
||||
spoolLock += NS_LITERAL_STRING(".lock");
|
||||
const PRUnichar *params[] = {
|
||||
spoolLock.get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_DELETE_LOCK, params, 1);
|
||||
buffer += MSG_LINEBREAK;
|
||||
|
||||
newMailParser->HandleLine(buffer.BeginWriting(), buffer.Length());
|
||||
outFileStream << buffer.get();
|
||||
|
||||
// 'From' lines delimit messages
|
||||
if (isMore && !PL_strncasecmp(buffer.get(), "From ", 5)) {
|
||||
buffer = NS_LITERAL_CSTRING("X-Mozilla-Status: 8000" MSG_LINEBREAK);
|
||||
newMailParser->HandleLine(buffer.BeginWriting(), buffer.Length());
|
||||
outFileStream << buffer.get();
|
||||
buffer = NS_LITERAL_CSTRING("X-Mozilla-Status2: 00000000" MSG_LINEBREAK);
|
||||
newMailParser->HandleLine(buffer.BeginWriting(), buffer.Length());
|
||||
outFileStream << buffer.get();
|
||||
}
|
||||
}
|
||||
|
||||
outFileStream.flush();
|
||||
newMailParser->OnStopRequest(nsnull, nsnull, NS_OK);
|
||||
newMailParser->SetDBFolderStream(nsnull); // stream is going away
|
||||
if (outFileStream.is_open())
|
||||
outFileStream.close();
|
||||
|
||||
// Truncate the spool file
|
||||
rv = spoolFile->SetFileSize(0);
|
||||
if (NS_FAILED(rv)) {
|
||||
const PRUnichar *params[] = {
|
||||
NS_ConvertUTF8toUCS2(spoolPath).get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_TRUNCATE_SPOOL_FILE, params, 1);
|
||||
}
|
||||
|
||||
if (!YieldSpoolLock(spoolPath.get())) {
|
||||
nsAutoString spoolLock = NS_ConvertUTF8toUCS2(spoolPath);
|
||||
spoolLock += NS_LITERAL_STRING(".lock");
|
||||
const PRUnichar *params[] = {
|
||||
spoolLock.get()
|
||||
};
|
||||
Error(MOVEMAIL_CANT_DELETE_LOCK, params, 1);
|
||||
}
|
||||
|
||||
in_server->SetServerBusy(PR_FALSE);
|
||||
|
||||
LOG(("GetNewMail returning rv=%d", rv));
|
||||
|
@ -522,7 +505,7 @@ nsMovemailService::GetDefaultLocalPath(nsIFileSpec ** aResult)
|
|||
rv = localFile->Exists(&exists);
|
||||
if (NS_SUCCEEDED(rv) && !exists)
|
||||
rv = localFile->Create(nsIFile::DIRECTORY_TYPE, 0775);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Make the resulting nsIFileSpec
|
||||
// TODO: Convert arg to nsILocalFile and avoid this
|
||||
|
|
Загрузка…
Ссылка в новой задаче