fix problem downloading message with inline images multiple times 93298 uploading messages to certain imap servers 72928 implement privileges command for imap folder sharing r=sspitzer, sr=mscott

This commit is contained in:
bienvenu%netscape.com 2002-01-10 02:46:40 +00:00
Родитель ed26a5d45e
Коммит 0c6619abe1
6 изменённых файлов: 203 добавлений и 60 удалений

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

@ -97,5 +97,5 @@ interface nsIImapMailFolderSink : nsISupports {
void releaseUrl();
void closeMockChannel(in nsIImapMockChannel aChannel);
void setUrlState(in nsIImapProtocol aProtocol, in nsIMsgMailNewsUrl aUrl, in boolean isRunning, in nsresult status);
void releaseUrlCacheEntry(in nsIMsgMailNewsUrl aUrl);
};

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

@ -40,6 +40,7 @@
#include "nsIImapUrl.idl"
interface nsIFileSpec;
interface nsIMsgMailNewsUrl;
[scriptable, uuid(5a53b814-68b1-11d3-a53e-0060b0fc04b7)]
@ -70,4 +71,5 @@ interface nsIImapMessageSink : nsISupports {
void GetMessageSizeFromDB(in string id, in boolean idIsUid, out unsigned long size);
void SetContentModified(in nsIImapUrl aImapUrl, in nsImapContentModifiedType modified);
void SetImageCacheSessionForUrl(in nsIMsgMailNewsUrl aMailUrl);
};

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

@ -59,6 +59,8 @@ interface nsIMsgImapMailFolder : nsISupports {
in nsIUrlListener aUrlListener, in nsIMsgWindow aWindow);
void playbackOfflineFolderCreate(in wstring folderName, in nsIMsgWindow aWindow, out nsIURI url);
void liteSelect(in nsIUrlListener aUrlListener);
void folderPrivileges(in nsIMsgWindow aWindow);
attribute boolean verifiedAsOnlineFolder;
attribute boolean explicitlyVerify;
attribute wchar hierarchyDelimiter;

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

@ -68,6 +68,7 @@
#include "nsTextFormatter.h"
#include "nsIPref.h"
#include "nsMsgUtf7Utils.h"
#include "nsICacheSession.h"
#include "nsIMsgFilter.h"
#include "nsImapMoveCoalescer.h"
@ -91,6 +92,8 @@
#include "nsIMsgAccountManager.h"
#include "nsQuickSort.h"
#include "nsIImapMockChannel.h"
#include "nsIWebNavigation.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
@ -3016,6 +3019,32 @@ NS_IMETHODIMP nsImapMailFolder::LiteSelect(nsIUrlListener *aUrlListener)
return rv;
}
NS_IMETHODIMP nsImapMailFolder::FolderPrivileges(nsIMsgWindow *window)
{
nsCOMPtr<nsIImapIncomingServer> imapServer;
nsresult rv = GetImapIncomingServer(getter_AddRefs(imapServer));
if (window && NS_SUCCEEDED(rv) && imapServer)
{
nsXPIDLCString manageMailAccountUrl;
rv = imapServer->GetManageMailAccountUrl(getter_Copies(manageMailAccountUrl));
if (NS_SUCCEEDED(rv) && manageMailAccountUrl.Length())
{
nsCOMPtr <nsIDocShell> docShell;
rv = window->GetRootDocShell(getter_AddRefs(docShell));
if (NS_SUCCEEDED(rv) && docShell)
{
nsCOMPtr<nsIURI> uri;
if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(uri), manageMailAccountUrl.get())))
return rv;
rv = docShell->LoadURI(uri, nsnull, nsIWebNavigation::LOAD_FLAGS_IS_LINK);
}
}
}
return rv;
}
nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
const char *destFolderUri,
@ -3570,6 +3599,14 @@ nsImapMailFolder::CloseMockChannel(nsIImapMockChannel * aChannel)
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::ReleaseUrlCacheEntry(nsIMsgMailNewsUrl *aUrl)
{
if (aUrl)
aUrl->SetMemCacheEntry(nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::BeginMessageUpload()
{
@ -3837,6 +3874,21 @@ nsImapMailFolder::SetContentModified(nsIImapUrl *aImapUrl, nsImapContentModified
return aImapUrl->SetContentModified(modified);
}
NS_IMETHODIMP
nsImapMailFolder::SetImageCacheSessionForUrl(nsIMsgMailNewsUrl *mailurl)
{
nsresult rv;
nsCOMPtr<nsIImapService> imapService = do_GetService(kCImapService, &rv);
if (imapService)
{
nsCOMPtr<nsICacheSession> cacheSession;
rv = imapService->GetCacheSession(getter_AddRefs(cacheSession));
if (NS_SUCCEEDED(rv) && cacheSession)
rv = mailurl->SetImageCacheSession(cacheSession);
}
return rv;
}
NS_IMETHODIMP nsImapMailFolder::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;

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

@ -1537,8 +1537,8 @@ NS_IMETHODIMP nsImapProtocol::CanHandleUrl(nsIImapUrl * aImapUrl,
aImapUrl->GetRequiredImapState(&imapState);
// OK, this is a bit of a hack - we're going to pretend that
// a delete or rename folder url requires a selected state connection on
// the folder to be deleted. This isn't technically true,
// these types of urls requires a selected state connection on
// the folder in question. This isn't technically true,
// but we would much rather use that connection for several reasons,
// one is that some UW servers require us to use that connection
// the other is that we don't want to leave a connection dangling in
@ -1547,7 +1547,9 @@ NS_IMETHODIMP nsImapProtocol::CanHandleUrl(nsIImapUrl * aImapUrl,
// we'll fall back to the first free connection.
PRBool isSelectedStateUrl = imapState == nsIImapUrl::nsImapSelectedState
|| actionForProposedUrl == nsIImapUrl::nsImapDeleteFolder || actionForProposedUrl == nsIImapUrl::nsImapRenameFolder
|| actionForProposedUrl == nsIImapUrl::nsImapMoveFolderHierarchy;
|| actionForProposedUrl == nsIImapUrl::nsImapMoveFolderHierarchy
|| actionForProposedUrl == nsIImapUrl::nsImapAppendDraftFromFile
|| actionForProposedUrl == nsIImapUrl::nsImapAppendMsgFromFile ;
nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(aImapUrl);
nsCOMPtr<nsIMsgIncomingServer> server;
@ -1870,7 +1872,13 @@ void nsImapProtocol::ProcessSelectedStateURL()
nsCOMPtr<nsIMsgMailNewsUrl> mailurl = do_QueryInterface(m_runningUrl);
if (mailurl)
{
mailurl->SetAddToMemoryCache(PR_FALSE);
// need to proxy this over to the ui thread
if (m_imapMessageSink)
m_imapMessageSink->SetImageCacheSessionForUrl(mailurl);
}
SetContentModified(modType); // This will be looked at by the cache
if (bMessageIdsAreUids)
{
@ -4789,8 +4797,6 @@ void nsImapProtocol::UploadMessageFromFile (nsIFileSpec* fileSpec,
{ // *** code me to search for the newly appended message
// go to selected state
AutoSubscribeToMailboxIfNecessary(mailboxName);
SelectMailbox(mailboxName);
nsCString messageId;
rv = m_imapExtensionSink->GetMessageId(this, &messageId,
m_runningUrl);
@ -4798,32 +4804,42 @@ void nsImapProtocol::UploadMessageFromFile (nsIFileSpec* fileSpec,
if (NS_SUCCEEDED(rv) && messageId.Length() > 0 &&
GetServerStateParser().LastCommandSuccessful())
{
command = "SEARCH SEEN HEADER Message-ID ";
command.Append(messageId);
// Clean up result sequence before issuing the cmd.
GetServerStateParser().ResetSearchResultSequence();
Search(command.get(), PR_TRUE, PR_FALSE);
// if the appended to folder isn't selected in the connection,
// select it.
if (GetServerStateParser().GetSelectedMailboxName() &&
PL_strcmp(GetServerStateParser().GetSelectedMailboxName(),
mailboxName))
SelectMailbox(mailboxName);
if (GetServerStateParser().LastCommandSuccessful())
{
nsMsgKey newkey = nsMsgKey_None;
nsImapSearchResultIterator *searchResult =
GetServerStateParser().CreateSearchResultIterator();
newkey = searchResult->GetNextMessageNumber();
delete searchResult;
if (newkey != nsMsgKey_None)
command = "SEARCH SEEN HEADER Message-ID ";
command.Append(messageId);
// Clean up result sequence before issuing the cmd.
GetServerStateParser().ResetSearchResultSequence();
Search(command.get(), PR_TRUE, PR_FALSE);
if (GetServerStateParser().LastCommandSuccessful())
{
m_imapExtensionSink->SetAppendMsgUid
(this, newkey, m_runningUrl);
WaitForFEEventCompletion();
nsMsgKey newkey = nsMsgKey_None;
nsImapSearchResultIterator *searchResult =
GetServerStateParser().CreateSearchResultIterator();
newkey = searchResult->GetNextMessageNumber();
delete searchResult;
if (newkey != nsMsgKey_None)
{
m_imapExtensionSink->SetAppendMsgUid
(this, newkey, m_runningUrl);
WaitForFEEventCompletion();
}
}
}
}
}
}
}
}
}
done:
PR_FREEIF(dataBuffer);
fileSpec->CloseStream();
@ -6367,7 +6383,6 @@ void nsImapProtocol::ProcessAuthenticatedStateURL()
void nsImapProtocol::ProcessAfterAuthenticated()
{
// mscott: ignore admin url stuff for now...
// if we're a netscape server, and we haven't got the admin url, get it
PRBool hasAdminUrl = PR_TRUE;
@ -6839,6 +6854,7 @@ nsImapMockChannel::nsImapMockChannel()
mLoadFlags = 0;
mChannelClosed = PR_FALSE;
mReadingFromCache = PR_FALSE;
mTryingToReadPart = PR_FALSE;
}
nsImapMockChannel::~nsImapMockChannel()
@ -6875,6 +6891,23 @@ NS_IMETHODIMP nsImapMockChannel::Close()
m_channelListener = nsnull;
mCacheRequest = nsnull;
if (mTryingToReadPart)
{
// clear mem cache entry on imap part url in case it's holding
// onto last reference in mem cache. Need to do this on ui thread
nsresult rv;
nsCOMPtr <nsIImapUrl> imapUrl = do_QueryInterface(m_url, &rv);
if (imapUrl)
{
nsCOMPtr <nsIImapMailFolderSink> folderSink;
rv = imapUrl->GetImapMailFolderSink(getter_AddRefs(folderSink));
if (folderSink)
{
nsCOMPtr <nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(m_url);
rv = folderSink->ReleaseUrlCacheEntry(mailUrl);
}
}
}
m_url = nsnull;
mChannelClosed = PR_TRUE;
@ -6992,6 +7025,19 @@ nsImapMockChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, nsCache
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
mailnewsUrl->SetMemCacheEntry(entry);
if (mTryingToReadPart && access & nsICache::ACCESS_WRITE && !(access & nsICache::ACCESS_READ))
{
#ifdef DEBUG_bienvenu
nsXPIDLCString entryKey;
entry->GetKey(getter_Copies(entryKey));
printf("dooming %s with access %ld\n", entryKey.get(), access);
#endif
entry->Doom();
// whoops, we're looking for a part, but didn't find it. Fall back to fetching the whole msg.
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
SetupPartExtractorListener(imapUrl, m_channelListener);
return OpenCacheEntry();
}
// if we have write access then insert a "stream T" into the flow so data
// gets written to both
if (access & nsICache::ACCESS_WRITE && !(access & nsICache::ACCESS_READ))
@ -7040,13 +7086,32 @@ nsresult nsImapMockChannel::OpenCacheEntry()
rv = imapService->GetCacheSession(getter_AddRefs(cacheSession));
NS_ENSURE_SUCCESS(rv, rv);
// we're going to need to extend this logic for the case where we're looking
// for a part. If we're looking for a part, we need to first ask for the part.
// if that comes back with a writeable cache entry, we need to doom it right
// away and not use it, and turn around and ask for a cache entry for the whole
// message, if that's available. But it seems like we shouldn't write into that
// cache entry if we just fetch that part - though we're doing that now. Maybe
// we never try to download just a single part from imap because our mime parser
// can't handle that, though I would think saving a single part as a file wouldn't
// need to go through mime...
// Open a cache entry with key = url
nsXPIDLCString urlSpec;
m_url->GetSpec(getter_Copies(urlSpec));
// for now, truncate of the query part so we don't duplicate urls in the cache...
char * anchor = PL_strrchr(urlSpec, '?');
if (anchor)
*anchor = '\0';
{
// if we were trying to read a part, we failed - fall back and look for whole msg
if (mTryingToReadPart)
{
mTryingToReadPart = PR_FALSE;
*anchor = '\0';
}
else
mTryingToReadPart = PR_TRUE;
}
return cacheSession->AsyncOpenCacheEntry(urlSpec, nsICache::ACCESS_READ_WRITE, this);
}
@ -7056,48 +7121,66 @@ nsresult nsImapMockChannel::ReadFromMemCache(nsICacheEntryDescriptor *entry)
PRUint32 annotationLength = 0;
nsXPIDLCString annotation;
nsXPIDLCString entryKey;
nsXPIDLCString contentType;
nsresult rv = NS_OK;
PRBool shouldUseCacheEntry = PR_FALSE;
rv = entry->GetMetaDataElement("ContentModified", getter_Copies(annotation));
if (NS_SUCCEEDED(rv) && (annotation.get()))
entry->GetKey(getter_Copies(entryKey));
// if we have a part, then we should use the cache entry.
if (entryKey.FindChar('?') != kNotFound)
{
annotationLength = nsCRT::strlen(annotation.get());
if (annotationLength == nsCRT::strlen("Not Modified") && !nsCRT::strncmp(annotation, "Not Modified", annotationLength))
entry->GetMetaDataElement("contentType", getter_Copies(contentType));
if (contentType.Length() > 0)
SetContentType(contentType);
shouldUseCacheEntry = PR_TRUE;
}
else
{
// otherwise, we have the whole msg, and we should make sure the content isn't modified.
rv = entry->GetMetaDataElement("ContentModified", getter_Copies(annotation));
if (NS_SUCCEEDED(rv) && (annotation.get()))
{
nsCOMPtr<nsITransport> cacheTransport;
rv = entry->GetTransport(getter_AddRefs(cacheTransport));
if (NS_SUCCEEDED(rv))
annotationLength = nsCRT::strlen(annotation.get());
if (annotationLength == nsCRT::strlen("Not Modified") && !nsCRT::strncmp(annotation, "Not Modified", annotationLength))
shouldUseCacheEntry = PR_TRUE;
}
}
if (shouldUseCacheEntry)
{
nsCOMPtr<nsITransport> cacheTransport;
rv = entry->GetTransport(getter_AddRefs(cacheTransport));
if (NS_SUCCEEDED(rv))
{
// 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 = cacheTransport->AsyncRead(cacheListener, m_channelContext, 0, PRUint32(-1), 0, getter_AddRefs(mCacheRequest));
NS_RELEASE(cacheListener);
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
{
// 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 = cacheTransport->AsyncRead(cacheListener, m_channelContext, 0, PRUint32(-1), 0, getter_AddRefs(mCacheRequest));
NS_RELEASE(cacheListener);
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
{
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
// 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);
// 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);
// and force the url to remove its reference on the mock channel...this is to solve
// a nasty reference counting problem...
imapUrl->SetMockChannel(nsnull);
// and force the url to remove its reference on the mock channel...this is to solve
// a nasty reference counting problem...
imapUrl->SetMockChannel(nsnull);
// be sure to set the cache entry's security info status as our security info status...
nsCOMPtr<nsISupports> securityInfo;
entry->GetSecurityInfo(getter_AddRefs(securityInfo));
SetSecurityInfo(securityInfo);
return NS_OK;
} // if AsyncRead succeeded.
} // if get transport succeeded
} // if contnet is not modified
else
rv = NS_ERROR_FAILURE; // content is modified so return an error so we try to open it the old fashioned way
} // if we got an annotation
// be sure to set the cache entry's security info status as our security info status...
nsCOMPtr<nsISupports> securityInfo;
entry->GetSecurityInfo(getter_AddRefs(securityInfo));
SetSecurityInfo(securityInfo);
return NS_OK;
} // if AsyncRead succeeded.
} // if get transport succeeded
} // if contnet is not modified
else
rv = NS_ERROR_FAILURE; // content is modified so return an error so we try to open it the old fashioned way
return rv;
}
@ -7146,6 +7229,9 @@ PRBool nsImapMockChannel::ReadFromLocalCache()
if (useLocalCache)
{
nsXPIDLCString messageIdString;
SetupPartExtractorListener(imapUrl, m_channelListener);
imapUrl->CreateListOfMessageIdsString(getter_Copies(messageIdString));
nsCOMPtr <nsIMsgFolder> folder;
rv = imapUrl->GetImapFolder(getter_AddRefs(folder));
@ -7208,7 +7294,6 @@ NS_IMETHODIMP nsImapMockChannel::AsyncOpen(nsIStreamListener *listener, nsISuppo
m_channelListener = listener;
nsCOMPtr<nsIImapUrl> imapUrl (do_QueryInterface(m_url));
SetupPartExtractorListener(imapUrl, m_channelListener);
if (ReadFromLocalCache())
{
@ -7226,6 +7311,7 @@ NS_IMETHODIMP nsImapMockChannel::AsyncOpen(nsIStreamListener *listener, nsISuppo
if (NS_SUCCEEDED(rv))
return rv;
}
SetupPartExtractorListener(imapUrl, m_channelListener);
// if for some reason open cache entry failed then just default to opening an imap connection for the url
return ReadFromImapConnection();
}

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

@ -639,6 +639,7 @@ protected:
PRBool mChannelClosed;
PRBool mReadingFromCache;
PRBool mTryingToReadPart;
// cache related helper methods
nsresult OpenCacheEntry(); // makes a request to the cache service for a cache entry for a url
PRBool ReadFromLocalCache(); // attempts to read the url out of our local (offline) cache....