fixed bug 17765 - Rename not implemented for Pop3, bug 19097 -- copying messages cause corrupted messages if the message size is greater than 4 k; r=putterman; make sure all children node were deleted when rename a folder, also rename the directory if it has subfolders; added m_leftOver to keep tracking partial completed line

This commit is contained in:
jefft%netscape.com 1999-11-19 14:39:05 +00:00
parent ae911c42cc
commit d12796ae31
4 changed files with 180 additions and 112 deletions

View File

@ -704,9 +704,44 @@ NS_IMETHODIMP nsImapMailFolder::Delete ()
NS_IMETHODIMP nsImapMailFolder::Rename (const char *newName)
{
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIFileSpec> oldPathSpec;
rv = GetPath(getter_AddRefs(oldPathSpec));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIFolder> parent;
rv = GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgFolder> parentFolder = do_QueryInterface(parent);
Shutdown(PR_TRUE);
PRUint32 cnt = 0;
nsFileSpec dirSpec;
if (mSubFolders)
mSubFolders->Count(&cnt);
if (cnt > 0)
rv = CreateDirectoryForFolder(dirSpec);
if (parentFolder)
{
SetParent(nsnull);
parentFolder->PropagateDelete(this, PR_FALSE);
}
nsFileSpec fileSpec;
oldPathSpec->GetFileSpec(&fileSpec);
nsLocalFolderSummarySpec oldSummarySpec(fileSpec);
nsCAutoString newNameStr = newName;
newNameStr += ".msf";
oldSummarySpec.Rename(newNameStr.GetBuffer());
if (NS_SUCCEEDED(rv) && cnt> 0)
{
newNameStr = newName;
newNameStr += ".sbd";
dirSpec.Rename(newNameStr.GetBuffer());
}
NS_WITH_SERVICE (nsIImapService, imapService, kCImapService, &rv);
if (NS_SUCCEEDED(rv))
rv = imapService->RenameLeaf(m_eventQueue, this, newName, this, nsnull);
rv = imapService->RenameLeaf(m_eventQueue, this, newName, this,
nsnull);
return rv;
}
@ -1622,22 +1657,34 @@ NS_IMETHODIMP nsImapMailFolder::CopyData(nsIInputStream *aIStream,
if (!m_copyState || !m_copyState->m_dataBuffer ||
!m_copyState->m_tmpFileSpec) return rv;
PRUint32 readCount, maxReadCount = FOUR_K;
PRUint32 readCount, maxReadCount = FOUR_K - m_copyState->m_leftOver;
PRInt32 writeCount;
char *start, *end;
PRUint32 linebreak_len = 0;
while (aLength > 0)
{
if (aLength < (PRInt32) maxReadCount)
maxReadCount = aLength;
rv = aIStream->Read(m_copyState->m_dataBuffer, maxReadCount,
rv = aIStream->Read(m_copyState->m_dataBuffer+m_copyState->m_leftOver,
maxReadCount,
&readCount);
if (NS_FAILED(rv)) return rv;
m_copyState->m_dataBuffer[readCount] = '\0';
m_copyState->m_dataBuffer[readCount+m_copyState->m_leftOver] = '\0';
start = m_copyState->m_dataBuffer;
end = PL_strstr(start, MSG_LINEBREAK);
end = PL_strstr(start, "\r");
if (!end)
end = PL_strstr(start, "\n");
else if (*(end+1) == LF && linebreak_len == 0)
linebreak_len = 2;
if (linebreak_len == 0) // not initialize yet
linebreak_len = 1;
if (!end)
m_copyState->m_leftOver = PL_strlen(start);
while (start && end)
{
@ -1650,10 +1697,23 @@ NS_IMETHODIMP nsImapMailFolder::CopyData(nsIInputStream *aIStream,
&writeCount);
rv = m_copyState->m_tmpFileSpec->Write(CRLF, 2, &writeCount);
}
start = end+MSG_LINEBREAK_LEN;
if (start >= m_copyState->m_dataBuffer+readCount)
start = end+linebreak_len;
if (start >=
m_copyState->m_dataBuffer+readCount+m_copyState->m_leftOver)
{
m_copyState->m_leftOver = 0;
break;
end = PL_strstr(start, MSG_LINEBREAK);
}
end = PL_strstr(start, "\r");
if (!end)
end = PL_strstr(start, "\n");
if (start && !end)
{
m_copyState->m_leftOver = PL_strlen(start);
nsCRT::memcpy(m_copyState->m_dataBuffer, start,
m_copyState->m_leftOver+1); // including null
maxReadCount = FOUR_K - m_copyState->m_leftOver;
}
}
if (NS_FAILED(rv)) return rv;
aLength -= readCount;
@ -3270,7 +3330,8 @@ nsImapMailFolder::CopyStreamMessage(nsIMessage* message,
nsImapMailCopyState::nsImapMailCopyState() : m_msgService(nsnull),
m_isMove(PR_FALSE), m_selectedState(PR_FALSE), m_curIndex(0),
m_totalCount(0), m_streamCopy(PR_FALSE), m_dataBuffer(nsnull)
m_totalCount(0), m_streamCopy(PR_FALSE), m_dataBuffer(nsnull),
m_leftOver(0)
{
NS_INIT_REFCNT();
}

View File

@ -82,6 +82,7 @@ public:
PRUint32 m_totalCount;// total count of messages we have to do
PRBool m_streamCopy;
char *m_dataBuffer; // temporary buffer for this copy operation
PRUint32 m_leftOver;
};
class nsImapMailFolder : public nsMsgDBFolder,

View File

@ -77,7 +77,7 @@ static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID);
nsLocalMailCopyState::nsLocalMailCopyState() :
m_fileStream(nsnull), m_curDstKey(0xffffffff), m_curCopyIndex(0),
m_messageService(nsnull), m_totalMsgCount(0), m_isMove(PR_FALSE),
m_dummyEnvelopeNeeded(PR_FALSE)
m_dummyEnvelopeNeeded(PR_FALSE), m_leftOver(0)
{
}
@ -233,13 +233,14 @@ nsMsgLocalMailFolder::CreateSubFolders(nsFileSpec &path)
continue;
}
AddSubfolder(currentFolderNameStr, getter_AddRefs(child));
AddSubfolder(&currentFolderNameStr, getter_AddRefs(child));
PL_strfree(folderName);
}
return rv;
}
nsresult nsMsgLocalMailFolder::AddSubfolder(nsAutoString name, nsIMsgFolder **child)
NS_IMETHODIMP nsMsgLocalMailFolder::AddSubfolder(nsAutoString *name,
nsIMsgFolder **child)
{
if(!child)
return NS_ERROR_NULL_POINTER;
@ -253,7 +254,7 @@ nsresult nsMsgLocalMailFolder::AddSubfolder(nsAutoString name, nsIMsgFolder **ch
uri.Append(mURI);
uri.Append('/');
uri.Append(name);
uri.Append(*name);
nsCOMPtr<nsIRDFResource> res;
rv = rdf->GetResource(uri, getter_AddRefs(res));
@ -272,22 +273,22 @@ nsresult nsMsgLocalMailFolder::AddSubfolder(nsAutoString name, nsIMsgFolder **ch
//Only set these is these are top level children.
if(NS_SUCCEEDED(rv) && isServer)
{
if(name.Compare("Inbox", PR_TRUE) == 0)
if(name->Compare("Inbox", PR_TRUE) == 0)
{
folder->SetFlag(MSG_FOLDER_FLAG_INBOX);
mBiffState = nsMsgBiffState_Unknown;
}
else if(name.Compare("Trash", PR_TRUE) == 0)
else if(name->Compare("Trash", PR_TRUE) == 0)
folder->SetFlag(MSG_FOLDER_FLAG_TRASH);
else if(name.Compare("Unsent Messages", PR_TRUE) == 0
|| name.Compare("Outbox", PR_TRUE) == 0)
else if(name->Compare("Unsent Messages", PR_TRUE) == 0
|| name->Compare("Outbox", PR_TRUE) == 0)
folder->SetFlag(MSG_FOLDER_FLAG_QUEUE);
//These should probably be read in from a preference. Hacking in here for the moment.
else if(name.Compare("Sent", PR_TRUE) == 0)
else if(name->Compare("Sent", PR_TRUE) == 0)
folder->SetFlag(MSG_FOLDER_FLAG_SENTMAIL);
else if(name.Compare("Drafts", PR_TRUE) == 0)
else if(name->Compare("Drafts", PR_TRUE) == 0)
folder->SetFlag(MSG_FOLDER_FLAG_DRAFTS);
else if(name.Compare("Templates", PR_TRUE) == 0)
else if(name->Compare("Templates", PR_TRUE) == 0)
folder->SetFlag(MSG_FOLDER_FLAG_TEMPLATES);
}
//at this point we must be ok and we don't want to return failure in case GetIsServer failed.
@ -659,7 +660,7 @@ nsMsgLocalMailFolder::CreateSubfolder(const char *folderName)
}
//Now let's create the actual new folder
rv = AddSubfolder(folderName, getter_AddRefs(child));
rv = AddSubfolder(&folderNameStr, getter_AddRefs(child));
unusedDB->SetSummaryValid(PR_TRUE);
unusedDB->Close(PR_TRUE);
}
@ -725,73 +726,60 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Delete()
NS_IMETHODIMP nsMsgLocalMailFolder::Rename(const char *newName)
{
#ifdef HAVE_PORT
// change the leaf name (stored separately)
nsresult status = MSG_FolderInfo::Rename (newUserLeafName);
if (status == 0) {
char *baseDir = nsCRT::strdup(m_pathName);
if (baseDir) {
char *base_slash = nsCRT::strrchr (baseDir, '/');
if (base_slash)
*base_slash = '\0';
nsCOMPtr<nsIFileSpec> oldPathSpec;
nsCOMPtr<nsIFolder> parent;
nsresult rv = GetPath(getter_AddRefs(oldPathSpec));
if (NS_FAILED(rv)) return rv;
rv = GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) return rv;
Shutdown(PR_TRUE);
nsCOMPtr<nsIMsgFolder> parentFolder = do_QueryInterface(parent);
nsCOMPtr<nsISupports> parentSupport = do_QueryInterface(parent);
nsFileSpec fileSpec;
oldPathSpec->GetFileSpec(&fileSpec);
nsLocalFolderSummarySpec oldSummarySpec(fileSpec);
nsFileSpec dirSpec;
PRUint32 cnt = 0;
if (mSubFolders)
mSubFolders->Count(&cnt);
if (cnt > 0)
rv = CreateDirectoryForFolder(dirSpec);
if (parentFolder)
{
SetParent(nsnull);
parentFolder->PropagateDelete(this, PR_FALSE);
}
char *leafNameForDisk = CreatePlatformLeafNameForDisk(newUserLeafName,m_master, baseDir);
if (!leafNameForDisk)
status = MK_OUT_OF_MEMORY;
if (0 == status) {
// calculate the new path name
char *newPath = (char*) PR_Malloc(nsCRT::strlen(m_pathName) + nsCRT::strlen(leafNameForDisk) + 1);
nsCRT::strcpy (newPath, m_pathName);
char *slash = nsCRT::strrchr (newPath, '/');
if (slash)
nsCRT::strcpy (slash + 1, leafNameForDisk);
// rename the mail summary file, if there is one
nsMsgDatabase *db = NULL;
status = CloseDatabase (m_pathName, &db);
XP_StatStruct fileStat;
if (!XP_Stat(m_pathName, &fileStat, xpMailFolderSummary))
status = XP_FileRename(m_pathName, xpMailFolderSummary, newPath, xpMailFolderSummary);
if (0 == status) {
if (db) {
if (ReopenDatabase (db, newPath) == 0) {
//need to set mailbox name
}
}
else {
MailDB *mailDb = NULL;
MailDB::Open(newPath, PR_TRUE, &mailDb, PR_TRUE);
if (mailDb) {
//need to set mailbox name
mailDb->Close();
}
}
}
// rename the mail folder file, if its local
if ((status == 0) && (GetType() == FOLDER_MAIL))
status = XP_FileRename (m_pathName, xpMailFolder, newPath, xpMailFolder);
if (status == 0) {
// rename the subdirectory if there is one
if (m_subFolders->GetSize() > 0)
status = XP_FileRename (m_pathName, xpMailSubdirectory, newPath, xpMailSubdirectory);
// tell all our children about the new pathname
if (status == 0) {
int startingAt = nsCRT::strlen (newPath) - nsCRT::strlen (leafNameForDisk) + 1; // add one for trailing '/'
status = PropagateRename (leafNameForDisk, startingAt);
}
}
nsCAutoString newNameStr = newName;
oldPathSpec->Rename(newNameStr.GetBuffer());
newNameStr += ".msf";
oldSummarySpec.Rename(newNameStr.GetBuffer());
if (NS_SUCCEEDED(rv) && cnt > 0)
{
newNameStr = newName;
newNameStr += ".sbd";
dirSpec.Rename(newNameStr.GetBuffer());
}
FREEIF(baseDir);
}
return status;
#endif
return NS_OK;
if (parentSupport)
{
nsCOMPtr<nsIMsgFolder> newFolder;
nsAutoString newFolderName = newName;
parentFolder->AddSubfolder(&newFolderName, getter_AddRefs(newFolder));
nsCOMPtr<nsISupports> newFolderSupport = do_QueryInterface(newFolder);
NotifyItemAdded(parentSupport, newFolderSupport, "folderView");
Release(); // really remove ourself from the system; since we need to
// regenerate the folder uri from the parent folder.
/***** jefft -
* Needs to find a way to reselect the new renamed folder and the
* message being selected.
*/
}
return rv;
}
NS_IMETHODIMP nsMsgLocalMailFolder::Adopt(nsIMsgFolder *srcFolder, PRUint32 *outPos)
@ -1601,46 +1589,62 @@ NS_IMETHODIMP nsMsgLocalMailFolder::CopyData(nsIInputStream *aIStream, PRInt32 a
if (!mCopyState) return NS_ERROR_OUT_OF_MEMORY;
PRUint32 readCount, maxReadCount = FOUR_K -1;
PRUint32 readCount, maxReadCount = FOUR_K - mCopyState->m_leftOver;
mCopyState->m_fileStream->seek(PR_SEEK_END, 0);
char *start, *end;
PRUint32 linebreak_len = 0;
while (aLength > 0)
{
if (aLength < (PRInt32) maxReadCount)
maxReadCount = aLength;
rv = aIStream->Read(mCopyState->m_dataBuffer, maxReadCount, &readCount);
mCopyState->m_dataBuffer[readCount] ='\0';
rv = aIStream->Read(mCopyState->m_dataBuffer + mCopyState->m_leftOver,
maxReadCount, &readCount);
mCopyState->m_dataBuffer[readCount+mCopyState->m_leftOver] ='\0';
start = mCopyState->m_dataBuffer;
end = PL_strstr(start, "\r");
if (!end)
end = PL_strstr(start, "\n");
else if (*(end+1) == LF && linebreak_len == 0)
linebreak_len = 2;
if (linebreak_len == 0) // not set yet
linebreak_len = 1;
if (!end)
mCopyState->m_leftOver = PL_strlen(start);
while (start && end)
{
char* start = mCopyState->m_dataBuffer;
char* end = nsnull;
PRUint32 linebreak_len = 1;
end = PL_strstr(mCopyState->m_dataBuffer, "\r");
if (!end)
end = PL_strstr(mCopyState->m_dataBuffer, "\n");
else if (*(end+1) == LF)
linebreak_len++;
while (start && end)
{
mCopyState->m_fileStream->write(start, end-start);
if (mCopyState->m_parseMsgState)
mCopyState->m_parseMsgState->ParseAFolderLine(start,
end-start +
linebreak_len);
*(mCopyState->m_fileStream) << MSG_LINEBREAK;
mCopyState->m_fileStream->write(start, end-start);
if (mCopyState->m_parseMsgState)
mCopyState->m_parseMsgState->ParseAFolderLine(start,
end-start +
linebreak_len);
*(mCopyState->m_fileStream) << MSG_LINEBREAK;
start = end+linebreak_len;
if (start >= &mCopyState->m_dataBuffer[readCount])
break;
if (start >=
&mCopyState->m_dataBuffer[readCount+mCopyState->m_leftOver])
{
mCopyState->m_leftOver = 0;
break;
}
end = PL_strstr(start, "\r");
if (!end)
end = PL_strstr(start, "\n");
}
end = PL_strstr(start, "\n");
if (start && !end)
{
mCopyState->m_leftOver = PL_strlen(start);
nsCRT::memcpy (mCopyState->m_dataBuffer, start,
mCopyState->m_leftOver+1);
maxReadCount = FOUR_K - mCopyState->m_leftOver;
}
}
aLength -= readCount;
}
return rv;
}

View File

@ -61,7 +61,8 @@ struct nsLocalMailCopyState
PRUint32 m_totalMsgCount;
PRBool m_isMove;
PRBool m_dummyEnvelopeNeeded;
char m_dataBuffer[FOUR_K];
char m_dataBuffer[FOUR_K+1];
PRUint32 m_leftOver;
};
class nsMsgLocalMailFolder : public nsMsgDBFolder,
@ -93,6 +94,7 @@ public:
NS_IMETHOD UpdateFolder(nsIMsgWindow *aWindow);
NS_IMETHOD CreateSubfolder(const char *folderName);
NS_IMETHOD AddSubfolder(nsAutoString *folderName, nsIMsgFolder** newFolder);
NS_IMETHOD Delete ();
NS_IMETHOD Rename (const char *newName);