зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
644a509198
Коммит
ae3941d951
|
@ -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__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче