add support for local folders under imap servers, also fix problem with offline sync playback r=naving,sr=sspitzer 15865

This commit is contained in:
bienvenu%netscape.com 2001-03-22 14:38:00 +00:00
Родитель 644a509198
Коммит ae3941d951
9 изменённых файлов: 237 добавлений и 18 удалений

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

@ -65,6 +65,8 @@ interface nsIImapIncomingServer : nsISupports {
attribute boolean aOLMailboxView;
attribute boolean storeReadMailInPFC;
attribute boolean storeSentMailInPFC;
boolean getIsPFC(in string folderName);
nsIMsgFolder getPFC(in boolean createIfMissing);
void GetImapConnectionAndLoadUrl(in nsIEventQueue aClientEventQueue,
in nsIImapUrl aImapUrl,
in nsISupports aConsumer);

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

@ -44,7 +44,7 @@ interface nsIMsgImapMailFolder : nsISupports {
void replayOfflineMoveCopy(out nsMsgKey keys, in long numKeys, in boolean isMove, in nsIMsgFolder aDstFolder,
in nsIUrlListener aUrlListener, in nsIMsgWindow aWindow);
void playbackOfflineFolderCreate(in wstring folderName, in nsIMsgWindow aWindow, out nsIURI url);
void liteSelect(in nsIUrlListener aUrlListener);
attribute boolean verifiedAsOnlineFolder;
attribute boolean explicitlyVerify;
attribute wchar hierarchyDelimiter;

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

@ -333,4 +333,16 @@
## @name IMAP_MAILBOX_ALREADY_EXISTS
## @loc None
5061=The mailbox already exists.
5061=The mailbox already exists.
## @name IMAP_PERSONAL_FILING_CABINET
## @loc None
5062=Personal Filing Cabinet
## @name IMAP_PFC_READ_MAIL
## @loc None
5063=Read Mail
## @name IMAP_PFC_SENT_MAIL
## @loc None
5064=Sent Mail

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

@ -68,6 +68,7 @@
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsImapUrl.h"
#include "nsFileStream.h"
#include "nsITimer.h"
static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
@ -103,6 +104,7 @@ nsImapIncomingServer::nsImapIncomingServer()
mDoingSubscribeDialog = PR_FALSE;
mDoingLsub = PR_FALSE;
m_canHaveFilters = PR_TRUE;
m_readPFCName = PR_FALSE;
}
nsImapIncomingServer::~nsImapIncomingServer()
@ -709,6 +711,9 @@ nsImapIncomingServer::CreateImapConnection(nsIEventQueue *aEventQueue,
}
else // cannot get anyone to handle the url queue it
{
#ifdef DEBUG_bienvenu
NS_ASSERTION(PR_FALSE, "no one will handle this, I don't think");
#endif
// queue the url
}
@ -902,33 +907,126 @@ nsImapIncomingServer::CloseCachedConnections()
return rv;
}
#define PFC_NAME "Personal Filing Cabinet"
NS_IMETHODIMP nsImapIncomingServer::GetReadMailPFC(PRBool createIfMissing, nsIMsgFolder **aFolder)
const char *nsImapIncomingServer::GetPFCName()
{
if (!m_readPFCName)
{
if(NS_SUCCEEDED(GetStringBundle()))
{
nsXPIDLString pfcName;
nsresult res = m_stringBundle->GetStringFromID(IMAP_PERSONAL_FILING_CABINET, getter_Copies(pfcName));
if (NS_SUCCEEDED(res))
m_pfcName = NS_ConvertUCS2toUTF8(pfcName).get();
}
m_readPFCName = PR_TRUE;
}
return m_pfcName.get();
}
NS_IMETHODIMP nsImapIncomingServer::GetIsPFC(const char *folderName, PRBool *result)
{
NS_ENSURE_ARG(result);
NS_ENSURE_ARG(folderName);
*result = !nsCRT::strcmp(GetPFCName(), folderName);
return NS_OK;
}
NS_IMETHODIMP nsImapIncomingServer::GetPFC(PRBool createIfMissing, nsIMsgFolder **pfcFolder)
{
NS_ENSURE_ARG_POINTER(aFolder);
nsCOMPtr<nsIFolder> rootFolder;
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
{
nsCOMPtr <nsIFolder> pfcParent;
rootFolder->FindSubFolder(PFC_NAME, getter_AddRefs(pfcParent));
if (!pfcParent && createIfMissing)
nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(rootFolder);
nsCOMPtr <nsIMsgFolder> pfcParent;
nsXPIDLCString serverUri;
rv = GetServerURI(getter_Copies(serverUri));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString folderUri(serverUri);
folderUri.ReplaceSubstring("imap://", "mailbox://");
folderUri.Append("/");
folderUri.Append(GetPFCName());
rootMsgFolder->GetChildWithURI(folderUri, PR_FALSE, pfcFolder);
if (!*pfcFolder && createIfMissing)
{
// get the URI from the incoming server
nsCOMPtr<nsIRDFResource> res;
nsCOMPtr<nsIFileSpec> pfcFileSpec;
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
rv = rdf->GetResource((const char *)folderUri, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgFolder> parentToCreate = do_QueryInterface(res, &rv);
NS_ENSURE_SUCCESS(rv, rv);
parentToCreate->SetParent(rootFolder);
parentToCreate->GetPath(getter_AddRefs(pfcFileSpec));
nsFileSpec path;
pfcFileSpec->GetFileSpec(&path);
nsOutputFileStream outputStream(path, PR_WRONLY | PR_CREATE_FILE, 00600);
// can't call CreateStorageIfMissing because our parent is an imap folder
// and that would create an imap folder.
// parentToCreate->CreateStorageIfMissing(nsnull);
*pfcFolder = parentToCreate;
rootFolder->NotifyItemAdded(rootFolder, parentToCreate, "folderView");
nsCOMPtr <nsISupports> supports = do_QueryInterface(parentToCreate);
NS_ASSERTION(supports, "couldn't get isupports from imap folder");
if (supports)
rootFolder->AppendElement(supports);
NS_IF_ADDREF(*pfcFolder);
}
}
return rv;
}
nsresult nsImapIncomingServer::GetPFCForStringId(PRBool createIfMissing, PRInt32 stringId, nsIMsgFolder **aFolder)
{
NS_ENSURE_ARG_POINTER(aFolder);
nsCOMPtr <nsIMsgFolder> pfcParent;
nsresult rv = GetPFC(createIfMissing, getter_AddRefs(pfcParent));
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLCString pfcURI;
pfcParent->GetURI(getter_Copies(pfcURI));
rv = GetStringBundle();
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLString pfcName;
rv = m_stringBundle->GetStringFromID(stringId, getter_Copies(pfcName));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString pfcMailUri(pfcURI);
// pfcMailUri.Append(".sbd");
pfcMailUri.Append("/");
pfcMailUri.AppendWithConversion(pfcName.get());
pfcParent->GetChildWithURI(pfcMailUri, PR_FALSE, aFolder);
if (!*aFolder && createIfMissing)
{
// get the URI from the incoming server
nsCOMPtr<nsIRDFResource> res;
NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv);
rv = rdf->GetResource((const char *)pfcMailUri, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgFolder> parentToCreate = do_QueryInterface(res, &rv);
NS_ENSURE_SUCCESS(rv, rv);
parentToCreate->SetParent(pfcParent);
parentToCreate->CreateStorageIfMissing(nsnull);
*aFolder = parentToCreate;
NS_IF_ADDREF(*aFolder);
}
return rv;
}
NS_IMETHODIMP nsImapIncomingServer::GetReadMailPFC(PRBool createIfMissing, nsIMsgFolder **aFolder)
{
NS_ENSURE_ARG_POINTER(aFolder);
return GetPFCForStringId(createIfMissing, IMAP_PFC_READ_MAIL, aFolder);
}
NS_IMETHODIMP nsImapIncomingServer::GetSentMailPFC(PRBool createIfMissing, nsIMsgFolder **aFolder)
{
NS_ENSURE_ARG_POINTER(aFolder);
nsCOMPtr<nsIFolder> rootFolder;
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
return NS_ERROR_NOT_IMPLEMENTED;
return GetPFCForStringId(createIfMissing, IMAP_PFC_SENT_MAIL, aFolder);
}
// nsIImapServerSink impl

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

@ -76,6 +76,8 @@ protected:
PRBool AllDescendentsAreNoSelect(nsIFolder *parentFolder);
nsresult GetStringBundle();
const char *GetPFCName();
nsresult GetPFCForStringId(PRBool createIfMissing, PRInt32 stringId, nsIMsgFolder **aFolder);
private:
nsresult SetDelimiterFromHierarchyDelimiter();
nsresult SubscribeToFolder(const PRUnichar *aName, PRBool subscribe);
@ -93,6 +95,8 @@ private:
nsVoidArray m_urlConsumers;
PRUint32 m_capability;
nsCString m_manageMailAccountUrl;
PRBool m_readPFCName;
nsCString m_pfcName;
PRBool m_waitingForConnectionInfo;
PRInt32 m_redirectedLogonRetries;
nsCOMPtr<nsIMsgLogonRedirector> m_logonRedirector;

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

@ -351,12 +351,27 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
if (NS_SUCCEEDED(GetServer(getter_AddRefs(server))) && server)
imapServer = do_QueryInterface(server);
PRBool isServer;
rv = GetIsServer(&isServer);
char *folderName;
for (nsDirectoryIterator dir(path, PR_FALSE); dir.Exists(); dir++)
{
nsFileSpec currentFolderPath = dir.Spec();
folderName = currentFolderPath.GetLeafName();
currentFolderNameStr.AssignWithConversion(folderName);
if (isServer && imapServer)
{
PRBool isPFC;
imapServer->GetIsPFC(folderName, &isPFC);
if (isPFC)
{
nsCOMPtr <nsIMsgFolder> pfcFolder;
imapServer->GetPFC(PR_TRUE, getter_AddRefs(pfcFolder));
continue;
}
// should check if this is the PFC
}
if (nsShouldIgnoreFile(currentFolderNameStr))
{
PL_strfree(folderName);
@ -458,6 +473,7 @@ NS_IMETHODIMP nsImapMailFolder::GetSubFolders(nsIEnumerator* *result)
if(NS_FAILED(rv)) return rv;
m_initialized = PR_TRUE; // need to set this here to avoid infinite recursion from CreateSubfolders.
// we have to treat the root folder specially, because it's name
// doesn't end with .sbd
@ -483,7 +499,6 @@ NS_IMETHODIMP nsImapMailFolder::GetSubFolders(nsIEnumerator* *result)
UpdateSummaryTotals(PR_FALSE);
if (NS_FAILED(rv)) return rv;
m_initialized = PR_TRUE; // XXX do this on failure too?
}
rv = mSubFolders->Enumerate(result);
return rv;
@ -2846,6 +2861,15 @@ NS_IMETHODIMP nsImapMailFolder::StoreImapFlags(PRInt32 flags, PRBool addFlags, n
return rv;
}
NS_IMETHODIMP nsImapMailFolder::LiteSelect(nsIUrlListener *aUrlListener)
{
nsresult rv;
NS_WITH_SERVICE(nsIImapService, imapService, kCImapService, &rv);
if (NS_SUCCEEDED(rv))
rv = imapService->LiteSelectFolder(m_eventQueue, this, aUrlListener, nsnull);
return rv;
}
nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
const char *destFolderUri,
@ -5206,6 +5230,75 @@ NS_IMETHODIMP nsImapMailFolder::SetFolderVerifiedOnline(PRBool bVal)
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::ShouldStoreMsgOffline(nsMsgKey msgKey, PRBool *result)
{
// check if we're storing mail we read in the inbox in a personal filing cabinet.
// if not, just use base class implementation.
if (mFlags & MSG_FOLDER_FLAG_INBOX)
{
PRBool hasMsgOffline = PR_FALSE;
HasMsgOffline(msgKey, &hasMsgOffline);
if (hasMsgOffline)
{
*result = PR_FALSE;
return NS_OK;
}
nsCOMPtr<nsIImapIncomingServer> imapServer;
nsresult rv = GetImapIncomingServer(getter_AddRefs(imapServer));
if (NS_SUCCEEDED(rv) && imapServer)
{
PRBool storeReadMailInPFC;
imapServer->GetStoreReadMailInPFC(&storeReadMailInPFC);
if (storeReadMailInPFC)
{
*result = PR_TRUE;
return NS_OK;
}
}
}
return nsMsgDBFolder::ShouldStoreMsgOffline(msgKey, result);
}
nsresult nsImapMailFolder::GetOfflineStoreOutputStream(nsIOutputStream **outputStream)
{
// check if we're storing mail we read in the inbox in a personal filing cabinet.
// if not, just use base class implementation.
if (mFlags & MSG_FOLDER_FLAG_INBOX)
{
nsCOMPtr<nsIImapIncomingServer> imapServer;
nsresult rv = GetImapIncomingServer(getter_AddRefs(imapServer));
if (NS_SUCCEEDED(rv) && imapServer)
{
PRBool storeReadMailInPFC;
imapServer->GetStoreReadMailInPFC(&storeReadMailInPFC);
if (storeReadMailInPFC)
{
nsresult rv = NS_ERROR_NULL_POINTER;
nsCOMPtr <nsIMsgFolder> outputPFC;
imapServer->GetReadMailPFC(PR_TRUE, getter_AddRefs(outputPFC));
if (outputPFC)
{
nsCOMPtr <nsIFileSpec> outputPFCPath;
outputPFC->GetPath(getter_AddRefs(outputPFCPath));
nsCOMPtr<nsISupports> supports;
nsFileSpec fileSpec;
outputPFCPath->GetFileSpec(&fileSpec);
rv = NS_NewIOFileStream(getter_AddRefs(supports), fileSpec, PR_WRONLY | PR_CREATE_FILE, 00700);
supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void **) outputStream);
nsCOMPtr <nsIRandomAccessStore> randomStore = do_QueryInterface(supports);
if (randomStore)
randomStore->Seek(PR_SEEK_END, 0);
}
return rv;
}
}
}
return nsMsgDBFolder::GetOfflineStoreOutputStream(outputStream);
}
NS_IMETHODIMP nsImapMailFolder::PerformExpand(nsIMsgWindow *aMsgWindow)
{
nsresult rv;

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

@ -186,6 +186,7 @@ public:
NS_IMETHOD DownloadMessagesForOffline(nsISupportsArray *messages, nsIMsgWindow *msgWindow);
NS_IMETHOD DownloadAllForOffline(nsIUrlListener *listener, nsIMsgWindow *msgWindow);
NS_IMETHOD ShouldStoreMsgOffline(nsMsgKey msgKey, PRBool *result);
// nsIMsgImapMailFolder methods
NS_DECL_NSIMSGIMAPMAILFOLDER
@ -306,6 +307,8 @@ protected:
nsresult GetDatabase(nsIMsgWindow *aMsgWindow);
virtual const char *GetIncomingServerType() {return "imap";}
virtual nsresult GetOfflineStoreOutputStream(nsIOutputStream **outputStream);
nsresult GetBodysToDownload(nsMsgKeyArray *keysOfMessagesToDownload);
// Uber message copy service
nsresult CopyMessagesWithStream(nsIMsgFolder* srcFolder,

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

@ -575,8 +575,11 @@ nsresult nsImapOfflineSync::ProcessNextOperation()
{
// there are operations to playback so check uid validity
SetCurrentUIDValidity(0); // force initial invalid state
// ### do a lite select here and hook ourselves up as a listener.
return NS_OK; // this is asynch, we have to return as be called again by the OfflineOpExitFunction
// do a lite select here and hook ourselves up as a listener.
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_currentFolder, &rv);
if (imapFolder)
rv = imapFolder->LiteSelect(this);
return rv; // this is async, we have to return as be called again by the OnStopRunningUrl
}
}
}

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

@ -93,4 +93,8 @@ NS_END_EXTERN_C
#define IMAP_HTML_NO_CACHED_BODY_TITLE 5059
#define IMAP_HTML_NO_CACHED_BODY_BODY 5060
#define IMAP_MAILBOX_ALREADY_EXISTS 5061
#define IMAP_PERSONAL_FILING_CABINET 5062
#define IMAP_PFC_READ_MAIL 5063
#define IMAP_PFC_SENT_MAIL 5064
#endif /* _nsImapStringBundle_H__ */