fixes for hierarchy delimiter handling, multiple fetches of imap messages to retrieve inline attachments, crash in morkRowObject::CloseRowObject r=mscott 52260, 59376 58691

This commit is contained in:
bienvenu%netscape.com 2000-11-13 22:35:50 +00:00
Родитель bb8b2a822e
Коммит 68e1cad16c
7 изменённых файлов: 125 добавлений и 98 удалений

Просмотреть файл

@ -22,6 +22,7 @@
#include "nsISupports.idl"
#include "MailNewsTypes2.idl"
#include "nsIImapUrl.idl"
interface nsIFileSpec;
@ -50,4 +51,5 @@ interface nsIImapMessageSink : nsISupports {
void GetMessageSizeFromDB(in string id, in boolean idIsUid, out unsigned long size);
void SetContentModified(in nsIImapUrl aImapUrl, in nsImapContentModifiedType modified);
};

Просмотреть файл

@ -463,6 +463,7 @@ nsImapIncomingServer::LoadNextQueuedUrl(PRBool *aResult)
aSupport(getter_AddRefs(m_urlQueue->ElementAt(0)));
nsCOMPtr<nsIImapUrl>
aImapUrl(do_QueryInterface(aSupport, &rv));
nsCOMPtr<nsIMsgMailNewsUrl> aMailNewsUrl(do_QueryInterface(aSupport, &rv));
if (aImapUrl)
{
@ -479,22 +480,10 @@ nsImapIncomingServer::LoadNextQueuedUrl(PRBool *aResult)
mockChannel->Close(); // try closing it to get channel listener nulled out.
nsCOMPtr<nsINetDataCacheManager> cacheManager = do_GetService(NS_NETWORK_CACHE_MANAGER_CONTRACTID, &res);
if (NS_SUCCEEDED(res) && cacheManager)
if (aMailNewsUrl)
{
nsCOMPtr<nsICachedNetData> cacheEntry;
// Retrieve an existing cache entry or create a new one if none exists for the
// given URL.
nsXPIDLCString urlCString;
// eventually we are going to want to use the url spec - the query/ref part 'cause that doesn't
// distinguish urls.......
url->GetSpec(getter_Copies(urlCString));
// for now, truncate of the query part so we don't duplicate urls in the cache...
char * anchor = PL_strrchr(urlCString, '?');
if (anchor)
*anchor = '\0';
res = cacheManager->GetCachedNetData(urlCString, 0, 0, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE,
getter_AddRefs(cacheEntry));
res = aMailNewsUrl->GetMemCacheEntry(getter_AddRefs(cacheEntry));
if (NS_SUCCEEDED(res) && cacheEntry)
cacheEntry->Delete();
}
@ -917,7 +906,7 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
}
nsCAutoString dupFolderPath(folderPath);
if (dupFolderPath.Last() == '/')
if (dupFolderPath.Last() == hierarchyDelimiter)
{
dupFolderPath.SetLength(dupFolderPath.Length()-1);
// *** this is what we did in 4.x in order to list uw folder only
@ -934,7 +923,7 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
uri.Assign(serverUri);
PRInt32 leafPos = folderName.RFindChar('/');
PRInt32 leafPos = folderName.RFindChar(hierarchyDelimiter);
nsCAutoString parentName(folderName);
nsCAutoString parentUri(uri);

Просмотреть файл

@ -326,13 +326,16 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
// take the full unicode folder name and find the unicode leaf name.
currentFolderNameStr.Assign(unicodeName);
PRInt32 leafPos = currentFolderNameStr.RFindChar('/');
PRUnichar delimiter = 0;
GetHierarchyDelimiter(&delimiter);
PRInt32 leafPos = currentFolderNameStr.RFindChar(delimiter);
if (leafPos > 0)
currentFolderNameStr.Cut(0, leafPos + 1);
// take the utf7 full online name, and determine the utf7 leaf name
utf7LeafName.AssignWithConversion(onlineFullUtf7Name);
leafPos = utf7LeafName.RFindChar('/');
leafPos = utf7LeafName.RFindChar(delimiter);
if (leafPos > 0)
utf7LeafName.Cut(0, leafPos + 1);
}
@ -567,7 +570,7 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
nsAutoString leafName; leafName.AssignWithConversion(folderName);
nsAutoString folderNameStr;
nsAutoString parentName = leafName;
PRInt32 folderStart = leafName.FindChar('/');
PRInt32 folderStart = leafName.FindChar(hierarchyDelimiter);
if (folderStart > 0)
{
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
@ -626,11 +629,11 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
//need to set the folder name
nsCOMPtr <nsIDBFolderInfo> folderInfo;
rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo));
if(NS_SUCCEEDED(rv))
{
// if(NS_SUCCEEDED(rv))
// {
// ### DMB used to be leafNameFromUser?
folderInfo->SetMailboxName(&folderNameStr);
}
// folderInfo->SetMailboxName(&folderNameStr);
// }
//Now let's create the actual new folder
rv = AddSubfolderWithPath(&folderNameStr, dbFileSpec, getter_AddRefs(child));
@ -646,7 +649,15 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
onlineName.AppendWithConversion(folderNameStr);
imapFolder->SetVerifiedAsOnlineFolder(PR_TRUE);
imapFolder->SetOnlineName(onlineName.GetBuffer());
imapFolder->SetHierarchyDelimiter(hierarchyDelimiter);
imapFolder->SetHierarchyDelimiter(hierarchyDelimiter);
// store the online name as the mailbox name in the db folder info
// I don't think anyone uses the mailbox name, so we'll use it
// to restore the online name when blowing away an imap db.
if (folderInfo)
{
nsAutoString unicodeOnlineName; unicodeOnlineName.AssignWithConversion(onlineName);
folderInfo->SetMailboxName(&unicodeOnlineName);
}
}
unusedDB->SetSummaryValid(PR_TRUE);
@ -785,6 +796,7 @@ NS_IMETHODIMP nsImapMailFolder::GetHierarchyDelimiter(PRUnichar *aHierarchyDelim
{
if (!aHierarchyDelimiter)
return NS_ERROR_NULL_POINTER;
ReadDBFolderInfo(PR_FALSE); // update cache first.
*aHierarchyDelimiter = m_hierarchyDelimiter;
return NS_OK;
}
@ -1366,7 +1378,7 @@ NS_IMETHODIMP nsImapMailFolder::SetOnlineName(const char * aOnlineFolderName)
nsCOMPtr<nsIDBFolderInfo> folderInfo;
m_onlineFolderName = aOnlineFolderName;
rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
if(NS_SUCCEEDED(rv))
if(NS_SUCCEEDED(rv) && folderInfo)
{
nsAutoString onlineName; onlineName.AssignWithConversion(aOnlineFolderName);
rv = folderInfo->SetProperty("onlineName", &onlineName);
@ -1397,6 +1409,7 @@ nsImapMailFolder::GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgDatab
nsresult openErr=NS_ERROR_UNEXPECTED;
if(!db || !folderInfo)
return NS_ERROR_NULL_POINTER; //ducarroz: should we use NS_ERROR_INVALID_ARG?
nsresult rv;
openErr = GetDatabase(nsnull);
@ -1414,19 +1427,22 @@ nsImapMailFolder::GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgDatab
m_onlineFolderName.Assign(onlineName);
else
{
char *uri = nsnull;
nsresult rv = GetURI(&uri);
if (NS_FAILED(rv)) return rv;
char * hostname = nsnull;
rv = GetHostname(&hostname);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString name;
rv = nsImapURI2FullName(kImapRootURI, hostname, uri, getter_Copies(name));
m_onlineFolderName.Assign(name);
nsAutoString autoOnlineName; autoOnlineName.AssignWithConversion(name);
nsAutoString autoOnlineName;
// autoOnlineName.AssignWithConversion(name);
(*folderInfo)->GetMailboxName(&autoOnlineName);
if (autoOnlineName.Length() == 0)
{
nsXPIDLCString uri;
rv = GetURI(getter_Copies(uri));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString hostname;
rv = GetHostname(getter_Copies(hostname));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString name;
rv = nsImapURI2FullName(kImapRootURI, hostname, uri, getter_Copies(name));
m_onlineFolderName.Assign(name);
}
rv = (*folderInfo)->SetProperty("onlineName", &autoOnlineName);
PR_FREEIF(uri);
PR_FREEIF(hostname);
}
}
}
@ -1855,6 +1871,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
if (mDatabase)
{
dbFolderInfo = null_nsCOMPtr();
NotifyStoreClosedAllHeaders();
mDatabase->ForceClosed();
}
mDatabase = null_nsCOMPtr();
@ -3289,6 +3306,12 @@ nsImapMailFolder::GetMessageSizeFromDB(const char *id, PRBool idIsUid, PRUint32
return rv;
}
NS_IMETHODIMP
nsImapMailFolder::SetContentModified(nsIImapUrl *aImapUrl, nsImapContentModifiedType modified)
{
return aImapUrl->SetContentModified(modified);
}
NS_IMETHODIMP
nsImapMailFolder::OnStartRunningUrl(nsIURI *aUrl)
{

Просмотреть файл

@ -59,8 +59,6 @@
#include "nsIDNSService.h"
// for the memory cache...
#include "nsINetDataCacheManager.h"
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsCOMPtr.h"
@ -3527,8 +3525,8 @@ PRBool nsImapProtocol::GetActive()
void nsImapProtocol::SetContentModified(IMAP_ContentModifiedType modified)
{
if (m_runningUrl)
m_runningUrl->SetContentModified(modified);
if (m_runningUrl && m_imapMessageSink)
m_imapMessageSink->SetContentModified(m_runningUrl, modified);
}
@ -6809,38 +6807,23 @@ NS_IMETHODIMP nsImapMockChannel::AsyncRead(nsIStreamListener *listener, nsISuppo
// look to see if this url should be added to the memory cache..
PRBool useMemoryCache = PR_FALSE;
mailnewsUrl->GetAddToMemoryCache(&useMemoryCache);
nsCOMPtr<nsINetDataCacheManager> cacheManager = do_GetService(NS_NETWORK_CACHE_MANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && cacheManager)
rv = mailnewsUrl->GetMemCacheEntry(getter_AddRefs(cacheEntry));
if (NS_SUCCEEDED(rv) && cacheEntry)
{
// Retrieve an existing cache entry or create a new one if none exists for the
// given URL.
nsXPIDLCString urlCString;
// eventually we are going to want to use the url spec - the query/ref part 'cause that doesn't
// distinguish urls.......
m_url->GetSpec(getter_Copies(urlCString));
// for now, truncate of the query part so we don't duplicate urls in the cache...
char * anchor = PL_strrchr(urlCString, '?');
if (anchor)
*anchor = '\0';
rv = cacheManager->GetCachedNetData(urlCString, 0, 0, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE,
getter_AddRefs(cacheEntry));
if (NS_SUCCEEDED(rv) && cacheEntry)
PRBool updateInProgress;
cacheEntry->GetPartialFlag(&partialFlag);
cacheEntry->GetUpdateInProgress(&updateInProgress);
cacheEntry->GetStoredContentLength(&contentLength);
// only try to update the cache entry if it isn't being used.
// We always want to try to write to the cache entry if we can
if (!updateInProgress)
{
PRBool updateInProgress;
cacheEntry->GetPartialFlag(&partialFlag);
cacheEntry->GetUpdateInProgress(&updateInProgress);
cacheEntry->GetStoredContentLength(&contentLength);
// only try to update the cache entry if it isn't being used.
// and we want to write to the memory cache.
if (!updateInProgress && useMemoryCache)
{
// now we need to figure out if the entry is new / or partially unfinished...
// this determines if we are going to USE the cache entry for reading the data
// vs. if we need to write data into the cache entry...
if (!contentLength || partialFlag)
// we're going to fill up this cache entry,
rv = cacheEntry->InterceptAsyncRead(listener, 0, getter_AddRefs(m_channelListener));
}
// now we need to figure out if the entry is new / or partially unfinished...
// this determines if we are going to USE the cache entry for reading the data
// vs. if we need to write data into the cache entry...
if (!contentLength || partialFlag)
// we're going to fill up this cache entry,
rv = cacheEntry->InterceptAsyncRead(listener, 0, getter_AddRefs(m_channelListener));
}
}
@ -6866,32 +6849,40 @@ NS_IMETHODIMP nsImapMockChannel::AsyncRead(nsIStreamListener *listener, nsISuppo
// to really load the msg with a protocol connection...
if (cacheEntry && contentLength > 0 && !partialFlag)
{
nsCOMPtr<nsIChannel> cacheChannel;
rv = cacheEntry->NewChannel(m_loadGroup, getter_AddRefs(cacheChannel));
if (NS_SUCCEEDED(rv))
PRUint32 annotationLength = 0;
char *annotation = nsnull;
rv = cacheEntry->GetAnnotation("ContentModified", &annotationLength, &annotation);
if (NS_SUCCEEDED(rv) && annotationLength == nsCRT::strlen("Not Modified")
&& annotation && !nsCRT::strncmp(annotation, "Not Modified", annotationLength))
{
// turn around and make our ref on m_url an owning ref...and force the url to remove
// its reference on the mock channel...this is a complicated texas two step to solve
// a nasty reference counting problem...
NS_IF_ADDREF(m_url);
mOwningRefToUrl = PR_TRUE;
imapUrl->SetMockChannel(nsnull);
// if we are going to read from the cache, then create a mock stream listener class and use it
nsImapCacheStreamListener * cacheListener = new nsImapCacheStreamListener();
NS_ADDREF(cacheListener);
cacheListener->Init(m_channelListener, NS_STATIC_CAST(nsIChannel *, this));
rv = cacheChannel->AsyncRead(cacheListener, m_channelContext);
NS_RELEASE(cacheListener);
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
nsCOMPtr<nsIChannel> cacheChannel;
rv = cacheEntry->NewChannel(m_loadGroup, getter_AddRefs(cacheChannel));
if (NS_SUCCEEDED(rv))
{
// if the msg is unread, we should mark it read on the server. This lets
// the code running this url we're loading from the cache, if it cares.
imapUrl->SetMsgLoadingFromCache(PR_TRUE);
return rv;
}
}
// turn around and make our ref on m_url an owning ref...and force the url to remove
// its reference on the mock channel...this is a complicated texas two step to solve
// a nasty reference counting problem...
NS_IF_ADDREF(m_url);
mOwningRefToUrl = PR_TRUE;
imapUrl->SetMockChannel(nsnull);
// if we are going to read from the cache, then create a mock stream listener class and use it
nsImapCacheStreamListener * cacheListener = new nsImapCacheStreamListener();
NS_ADDREF(cacheListener);
cacheListener->Init(m_channelListener, NS_STATIC_CAST(nsIChannel *, this));
rv = cacheChannel->AsyncRead(cacheListener, m_channelContext);
NS_RELEASE(cacheListener);
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
{
// if the msg is unread, we should mark it read on the server. This lets
// the code running this url we're loading from the cache, if it cares.
imapUrl->SetMsgLoadingFromCache(PR_TRUE);
return rv;
}
}
}
}
// okay, add the mock channel to the load group..

Просмотреть файл

@ -42,7 +42,7 @@
#include "nsXPIDLString.h"
#include "nsAutoLock.h"
#include "nsIMAPNamespace.h"
#include "nsICachedNetData.h"
// rdf stuff is needed to get the charset from the imap folder associated with the url.
#include "nsIRDFService.h"
#include "rdf.h"
@ -893,6 +893,28 @@ NS_IMETHODIMP nsImapUrl::SetAllowContentChange(PRBool allowContentChange)
NS_IMETHODIMP nsImapUrl::SetContentModified(nsImapContentModifiedType contentModified)
{
m_contentModified = contentModified;
nsCOMPtr<nsICachedNetData> cacheEntry;
nsresult res = GetMemCacheEntry(getter_AddRefs(cacheEntry));
if (NS_SUCCEEDED(res) && cacheEntry)
{
const char *contentModifiedAnnotation = "";
switch (m_contentModified)
{
case IMAP_CONTENT_NOT_MODIFIED:
contentModifiedAnnotation = "Not Modified";
break;
case IMAP_CONTENT_MODIFIED_VIEW_INLINE:
contentModifiedAnnotation = "Modified View Inline";
break;
case IMAP_CONTENT_MODIFIED_VIEW_AS_LINKS:
NS_ASSERTION(PR_FALSE, "we're not using this anymore!");
break;
case IMAP_CONTENT_FORCE_CONTENT_NOT_MODIFIED:
contentModifiedAnnotation = "Force Content Not Modified";
break;
}
cacheEntry->SetAnnotation("ContentModified", nsCRT::strlen(contentModifiedAnnotation), contentModifiedAnnotation);
}
return NS_OK;
}

Просмотреть файл

@ -159,7 +159,7 @@ nsImapURI2Path(const char* rootURI, const char* uriStr, nsFileSpec& pathResult)
}
nsresult
nsImapURI2FullName(const char* rootURI, const char* hostname, char* uriStr,
nsImapURI2FullName(const char* rootURI, const char* hostname, const char* uriStr,
char **name)
{
nsAutoString uri; uri.AssignWithConversion(uriStr);

Просмотреть файл

@ -35,7 +35,7 @@ nsImapURI2Path(const char* rootURI, const char* uriStr,
nsFileSpec& pathResult);
extern nsresult
nsImapURI2FullName(const char* rootURI, const char* hostname, char* uriStr,
nsImapURI2FullName(const char* rootURI, const char* hostname, const char* uriStr,
char **name);
extern nsresult