more work on shared imap folders and acl, sharing tab of folder properties r=sspitzer, sr=mscott 112096

This commit is contained in:
bienvenu%netscape.com 2002-01-27 02:06:46 +00:00
Родитель dec940b55c
Коммит 2af45b6107
17 изменённых файлов: 1800 добавлений и 719 удалений

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

@ -62,8 +62,6 @@ public:
NS_IMETHOD ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights) = 0;
NS_IMETHOD AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights) = 0;
NS_IMETHOD RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights) = 0;
NS_IMETHOD FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,

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

@ -43,31 +43,34 @@ interface nsIMsgMailNewsUrl;
[scriptable, uuid(8ec49a08-5cb0-11d3-a52c-0060b0fc04b7)]
interface nsIImapServerSink : nsISupports {
void possibleImapMailbox(in string folderPath, in wchar hierarchyDelim, in long boxFlags);
void discoveryDone();
void onlineFolderDelete(in string aFolderName);
void onlineFolderCreateFailed(in string aFolderName);
void onlineFolderRename(in nsIMsgWindow msgWindow, in string oldName, in string newName);
void folderIsNoSelect(in string aFolderName, out boolean aResult);
void setFolderAdminURL(in string aFolderName, in string adminUrl);
/* returns true if it's a new mailbox */
boolean possibleImapMailbox(in string folderPath, in wchar hierarchyDelim, in long boxFlags);
boolean folderNeedsACLInitialized(in string folderPath);
void addFolderRights(in string folderPath, in string userName, in string rights);
void discoveryDone();
void onlineFolderDelete(in string aFolderName);
void onlineFolderCreateFailed(in string aFolderName);
void onlineFolderRename(in nsIMsgWindow msgWindow, in string oldName, in string newName);
void folderIsNoSelect(in string aFolderName, out boolean aResult);
void setFolderAdminURL(in string aFolderName, in string adminUrl);
boolean folderVerifiedOnline(in string aFolderName);
void subscribeUpgradeFinished(in boolean bringUpSubscribeUI);
void subscribeUpgradeFinished(in boolean bringUpSubscribeUI);
void setCapability(in unsigned long capability);
void loadNextQueuedUrl(out boolean urlRun);
void setCapability(in unsigned long capability);
void loadNextQueuedUrl(out boolean urlRun);
void getImapStringByID(in long aMsgId, out wstring aString);
void getImapStringByID(in long aMsgId, out wstring aString);
void formatStringWithHostNameByID(in long aMsgId, out wstring aString);
void fEAlert(in wstring aString, in nsIMsgWindow aMsgWindow);
void fEAlertFromServer(in string aString, in nsIMsgWindow aMsgWindow);
void commitNamespaces();
void promptForPassword(out string aString, in nsIMsgWindow aMsgWindow);
attribute boolean userAuthenticated;
void setMailServerUrls(in string manageMailAccount, in string manageLists, in string manageFilters);
/* this is a bogus method on this interface but i need it until misc. sink is scriptable.. */
void RemoveChannelFromUrl(in nsIMsgMailNewsUrl aUrl, in unsigned long statusCode);
readonly attribute string arbitraryHeaders;
readonly attribute boolean shouldDownloadArbitraryHeaders;
void fEAlert(in wstring aString, in nsIMsgWindow aMsgWindow);
void fEAlertFromServer(in string aString, in nsIMsgWindow aMsgWindow);
void commitNamespaces();
void promptForPassword(out string aString, in nsIMsgWindow aMsgWindow);
attribute boolean userAuthenticated;
void setMailServerUrls(in string manageMailAccount, in string manageLists, in string manageFilters);
/* this is a bogus method on this interface but i need it until misc. sink is scriptable.. */
void RemoveChannelFromUrl(in nsIMsgMailNewsUrl aUrl, in unsigned long statusCode);
readonly attribute string arbitraryHeaders;
readonly attribute boolean shouldDownloadArbitraryHeaders;
};

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

@ -41,6 +41,18 @@
interface nsIMsgWindow;
interface nsIImapIncomingServer;
// this is a simple interface which allows the imap folder to update some values
// that the folder props js code will use to update the sharing tab in the folder props.
[scriptable, uuid(239472a2-6e8f-46f0-9507-887998da49e5)]
interface nsIMsgImapFolderProps : nsISupports {
void setFolderType(in wstring folderType);
void setFolderTypeDescription(in wstring folderTypeDescription);
void setFolderPermissions(in wstring permissions);
};
[scriptable, uuid(FBFEBE79-C1DD-11d2-8A40-0060B0FC04D2)]
interface nsIMsgImapMailFolder : nsISupports {
void removeSubFolder(in nsIMsgFolder folder);
@ -59,12 +71,18 @@ 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 fillInFolderProps(in nsIMsgImapFolderProps aFolderProps);
void resetNamespaceReferences();
void folderPrivileges(in nsIMsgWindow aWindow);
nsIMsgImapMailFolder findOnlineSubFolder(in string onlineName);
void addFolderRights(in string userName, in string rights);
attribute boolean verifiedAsOnlineFolder;
attribute boolean explicitlyVerify;
attribute wchar hierarchyDelimiter;
attribute long boxFlags;
attribute string onlineName;
attribute unsigned long aclFlags;
readonly attribute boolean canIOpenThisFolder;
readonly attribute boolean hasAdminUrl;
};

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

@ -339,7 +339,7 @@
## @name IMAP_OTHER_USERS_FOLDER_TYPE_DESCRIPTION
## @loc None
5072=This is a mail folder shared by the user '%S'."
5072=This is a mail folder shared by the user '%S'.
## @name IMAP_ACL_FULL_RIGHTS
## @loc None
@ -367,7 +367,7 @@
## @name IMAP_ACL_POST_RIGHT
## @loc None
5079=Post"
5079=Post
## @name IMAP_ACL_CREATE_RIGHT
## @loc None

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

@ -611,84 +611,84 @@ nsresult nsIMAPHostSessionList::SetNamespacesPrefForHost(nsIImapIncomingServer *
// Make sure this is running in the Mozilla thread when called
NS_IMETHODIMP nsIMAPHostSessionList::CommitNamespacesForHost(nsIImapIncomingServer *aHost)
{
char * serverKey = nsnull;
if (!aHost)
return NS_ERROR_NULL_POINTER;
nsCOMPtr <nsIMsgIncomingServer> incomingServer = do_QueryInterface(aHost);
if (!incomingServer)
return NS_ERROR_NULL_POINTER;
nsresult rv = incomingServer->GetKey(&serverKey);
if (NS_FAILED(rv)) return rv;
PR_EnterMonitor(gCachedHostInfoMonitor);
nsIMAPHostInfo *host = FindHost(serverKey);
if (host)
{
host->fGotNamespaces = PR_TRUE; // so we only issue NAMESPACE once per host per session.
EIMAPNamespaceType type = kPersonalNamespace;
for (int i = 1; i <= 3; i++)
{
switch(i)
{
case 1:
type = kPersonalNamespace;
break;
case 2:
type = kPublicNamespace;
break;
case 3:
type = kOtherUsersNamespace;
break;
default:
type = kPersonalNamespace;
break;
}
int32 numInNS = host->fNamespaceList->GetNumberOfNamespaces(type);
if (numInNS == 0)
{
SetNamespacesPrefForHost(aHost, type, NULL);
}
else if (numInNS >= 1)
{
char *pref = PR_smprintf("");
for (int count = 1; count <= numInNS; count++)
{
nsIMAPNamespace *ns = host->fNamespaceList->GetNamespaceNumber(count, type);
if (ns)
{
if (count > 1)
{
// append the comma
char *tempPref = PR_smprintf("%s,",pref);
PR_FREEIF(pref);
pref = tempPref;
}
char *tempPref = PR_smprintf("%s\"%s\"",pref,ns->GetPrefix());
PR_FREEIF(pref);
pref = tempPref;
}
}
if (pref)
{
SetNamespacesPrefForHost(aHost, type, pref);
PR_Free(pref);
}
}
}
// clear, but don't delete the entries in, the temp namespace list
host->fTempNamespaceList->ClearNamespaces(PR_TRUE, PR_TRUE, PR_FALSE);
// Now reset all of libmsg's namespace references.
// Did I mention this needs to be running in the mozilla thread?
aHost->ResetNamespaceReferences();
}
PR_FREEIF(serverKey);
PR_ExitMonitor(gCachedHostInfoMonitor);
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
char * serverKey = nsnull;
if (!aHost)
return NS_ERROR_NULL_POINTER;
nsCOMPtr <nsIMsgIncomingServer> incomingServer = do_QueryInterface(aHost);
if (!incomingServer)
return NS_ERROR_NULL_POINTER;
nsresult rv = incomingServer->GetKey(&serverKey);
if (NS_FAILED(rv)) return rv;
PR_EnterMonitor(gCachedHostInfoMonitor);
nsIMAPHostInfo *host = FindHost(serverKey);
if (host)
{
host->fGotNamespaces = PR_TRUE; // so we only issue NAMESPACE once per host per session.
EIMAPNamespaceType type = kPersonalNamespace;
for (int i = 1; i <= 3; i++)
{
switch(i)
{
case 1:
type = kPersonalNamespace;
break;
case 2:
type = kPublicNamespace;
break;
case 3:
type = kOtherUsersNamespace;
break;
default:
type = kPersonalNamespace;
break;
}
int32 numInNS = host->fNamespaceList->GetNumberOfNamespaces(type);
if (numInNS == 0)
{
SetNamespacesPrefForHost(aHost, type, NULL);
}
else if (numInNS >= 1)
{
char *pref = PR_smprintf("");
for (int count = 1; count <= numInNS; count++)
{
nsIMAPNamespace *ns = host->fNamespaceList->GetNamespaceNumber(count, type);
if (ns)
{
if (count > 1)
{
// append the comma
char *tempPref = PR_smprintf("%s,",pref);
PR_FREEIF(pref);
pref = tempPref;
}
char *tempPref = PR_smprintf("%s\"%s\"",pref,ns->GetPrefix());
PR_FREEIF(pref);
pref = tempPref;
}
}
if (pref)
{
SetNamespacesPrefForHost(aHost, type, pref);
PR_Free(pref);
}
}
}
// clear, but don't delete the entries in, the temp namespace list
host->fTempNamespaceList->ClearNamespaces(PR_TRUE, PR_TRUE, PR_FALSE);
// Now reset all of libmsg's namespace references.
// Did I mention this needs to be running in the mozilla thread?
aHost->ResetNamespaceReferences();
}
PR_FREEIF(serverKey);
PR_ExitMonitor(gCachedHostInfoMonitor);
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
}
NS_IMETHODIMP nsIMAPHostSessionList::FlushUncommittedNamespacesForHost(const char *serverKey, PRBool &result)
@ -753,18 +753,18 @@ NS_IMETHODIMP nsIMAPHostSessionList::SetShouldAlwaysListInboxForHost(const char
NS_IMETHODIMP nsIMAPHostSessionList::SetNamespaceHierarchyDelimiterFromMailboxForHost(const char *serverKey, const char *boxName, char delimiter)
{
PR_EnterMonitor(gCachedHostInfoMonitor);
nsIMAPHostInfo *host = FindHost(serverKey);
if (host)
{
nsIMAPNamespace *ns = host->fNamespaceList->GetNamespaceForMailbox(boxName);
if (ns && !ns->GetIsDelimiterFilledIn())
{
ns->SetDelimiter(delimiter);
}
}
PR_ExitMonitor(gCachedHostInfoMonitor);
return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
PR_EnterMonitor(gCachedHostInfoMonitor);
nsIMAPHostInfo *host = FindHost(serverKey);
if (host)
{
nsIMAPNamespace *ns = host->fNamespaceList->GetNamespaceForMailbox(boxName);
if (ns && !ns->GetIsDelimiterFilledIn())
{
ns->SetDelimiter(delimiter, PR_TRUE);
}
}
PR_ExitMonitor(gCachedHostInfoMonitor);
return (host) ? NS_OK : NS_ERROR_ILLEGAL_VALUE ;
}
NS_IMETHODIMP nsIMAPHostSessionList::AddShellToCacheForHost(const char *serverKey, nsIMAPBodyShell *shell)

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

@ -41,11 +41,13 @@
#include "nsIMAPNamespace.h"
#include "nsImapProtocol.h"
#include "nsIMAPGenericParser.h"
#include "nsMsgImapCID.h"
#include "nsImapUrl.h"
#include "nsString.h"
//////////////////// nsIMAPNamespace /////////////////////////////////////////////////////////////
static NS_DEFINE_CID(kCImapHostSessionListCID, NS_IIMAPHOSTSESSIONLIST_CID);
nsIMAPNamespace::nsIMAPNamespace(EIMAPNamespaceType type, const char *prefix, char delimiter, PRBool from_prefs)
{
@ -62,10 +64,10 @@ nsIMAPNamespace::~nsIMAPNamespace()
PR_FREEIF(m_prefix);
}
void nsIMAPNamespace::SetDelimiter(char delimiter)
void nsIMAPNamespace::SetDelimiter(char delimiter, PRBool delimiterFilledIn)
{
m_delimiter = delimiter;
m_delimiterFilledIn = PR_TRUE;
m_delimiter = delimiter;
m_delimiterFilledIn = delimiterFilledIn;
}
// returns -1 if this box is not part of this namespace,
@ -345,62 +347,270 @@ nsresult nsIMAPNamespaceList::SerializeNamespaces(char **prefixes, int len, nsCS
*/
int nsIMAPNamespaceList::UnserializeNamespaces(const char *str, char **prefixes, int len)
{
if (!str)
return 0;
if (!prefixes)
{
if (str[0] != '"')
return 1;
else
{
int count = 0;
char *ourstr = PL_strdup(str);
char *origOurStr = ourstr;
if (ourstr)
{
char *token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
while (token != nsnull)
{
token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
count++;
}
PR_Free(origOurStr);
}
return count;
}
}
else
{
if ((str[0] != '"') && (len >= 1))
{
prefixes[0] = PL_strdup(str);
return 1;
}
else
{
int count = 0;
char *ourstr = PL_strdup(str);
char *origOurStr = ourstr;
if (ourstr)
{
char *token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
while ((count < len) && (token != nsnull))
{
char *current = PL_strdup(token), *where = current;
if (where[0] == '"')
where++;
if (where[PL_strlen(where)-1] == '"')
where[PL_strlen(where)-1] = 0;
prefixes[count] = PL_strdup(where);
PR_FREEIF(current);
token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
count++;
}
PR_Free(origOurStr);
}
return count;
}
}
if (!str)
return 0;
if (!prefixes)
{
if (str[0] != '"')
return 1;
else
{
int count = 0;
char *ourstr = PL_strdup(str);
char *origOurStr = ourstr;
if (ourstr)
{
char *token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
while (token != nsnull)
{
token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
count++;
}
PR_Free(origOurStr);
}
return count;
}
}
else
{
if ((str[0] != '"') && (len >= 1))
{
prefixes[0] = PL_strdup(str);
return 1;
}
else
{
int count = 0;
char *ourstr = PL_strdup(str);
char *origOurStr = ourstr;
if (ourstr)
{
char *token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
while ((count < len) && (token != nsnull))
{
char *current = PL_strdup(token), *where = current;
if (where[0] == '"')
where++;
if (where[PL_strlen(where)-1] == '"')
where[PL_strlen(where)-1] = 0;
prefixes[count] = PL_strdup(where);
PR_FREEIF(current);
token = nsCRT::strtok( ourstr, SERIALIZER_SEPARATORS, &ourstr );
count++;
}
PR_Free(origOurStr);
}
return count;
}
}
}
char *nsIMAPNamespaceList::AllocateCanonicalFolderName(const char *onlineFolderName, char delimiter)
{
char *canonicalPath = nsnull;
if (delimiter)
canonicalPath = nsImapUrl::ReplaceCharsInCopiedString(onlineFolderName, delimiter , '/');
else
canonicalPath = strdup(onlineFolderName);
// eat any escape characters for escaped dir separators
if (canonicalPath)
{
char *currentEscapeSequence = strstr(canonicalPath, "\\/");
while (currentEscapeSequence)
{
strcpy(currentEscapeSequence, currentEscapeSequence+1);
currentEscapeSequence = strstr(currentEscapeSequence+1, "\\/");
}
}
return canonicalPath;
}
/*
GetFolderNameWithoutNamespace takes as input a folder name
in canonical form, and the namespace for the given folder. It returns an allocated
string of the folder's path with the namespace string stripped out. For instance,
when passed the folder Folders/a/b where the namespace is "Folders/", it will return
"a/b". Similarly, if the folder name is "#news/comp/mail/imap" in canonical form,
with a real delimiter of "." and a namespace of "#news.", it will return "comp/mail/imap".
The return value is always in canonical form.
*/
char* nsIMAPNamespaceList::GetFolderNameWithoutNamespace(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName)
{
NS_ASSERTION(canonicalFolderName, "null folder name");
#ifdef DEBUG
NS_ASSERTION(namespaceForFolder || !PL_strcasecmp(canonicalFolderName, "INBOX"), "need namespace or INBOX");
#endif
char *retFolderName = nsnull;
if (!PL_strcasecmp(canonicalFolderName, "INBOX"))
return strdup(canonicalFolderName);
// convert the canonical path to the online path
char *convertedFolderName = nsIMAPNamespaceList::AllocateServerFolderName(canonicalFolderName, namespaceForFolder->GetDelimiter());
if (convertedFolderName)
{
char *beginFolderPath = nsnull;
if (strlen(convertedFolderName) <= strlen(namespaceForFolder->GetPrefix()))
beginFolderPath = convertedFolderName;
else
beginFolderPath = convertedFolderName + strlen(namespaceForFolder->GetPrefix());
NS_ASSERTION(beginFolderPath, "empty folder path");
retFolderName = nsIMAPNamespaceList::AllocateCanonicalFolderName(beginFolderPath, namespaceForFolder->GetDelimiter());
PR_Free(convertedFolderName);
}
NS_ASSERTION(retFolderName, "returning null folder name");
return retFolderName;
}
nsIMAPNamespace* nsIMAPNamespaceList::GetNamespaceForFolder(const char *hostName,
const char *canonicalFolderName,
char delimiter)
{
if (!hostName || !canonicalFolderName)
return nsnull;
nsIMAPNamespace *resultNamespace = nsnull;
nsresult rv;
char *convertedFolderName = nsIMAPNamespaceList::AllocateServerFolderName(canonicalFolderName, delimiter);
if (convertedFolderName)
{
nsCOMPtr<nsIImapHostSessionList> hostSessionList =
do_GetService(kCImapHostSessionListCID, &rv);
if (NS_FAILED(rv))
return nsnull;
hostSessionList->GetNamespaceForMailboxForHost(hostName, convertedFolderName, resultNamespace);
PR_Free(convertedFolderName);
}
else
{
NS_ASSERTION(PR_FALSE, "couldn't get converted folder name");
}
return resultNamespace;
}
/* static */
char *nsIMAPNamespaceList::AllocateServerFolderName(const char *canonicalFolderName, char delimiter)
{
if (delimiter)
return nsImapUrl::ReplaceCharsInCopiedString(canonicalFolderName, '/', delimiter);
else
return nsCRT::strdup(canonicalFolderName);
}
/*
GetFolderOwnerNameFromPath takes as inputs a folder name
in canonical form, and a namespace for that folder.
The namespace MUST be of type kOtherUsersNamespace, hence the folder MUST be
owned by another user. This function extracts the folder owner's name from the
canonical name of the folder, and returns an allocated copy of that owner's name
*/
/* static */
char *nsIMAPNamespaceList::GetFolderOwnerNameFromPath(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName)
{
if (!namespaceForFolder || !canonicalFolderName)
{
NS_ASSERTION(PR_FALSE,"null namespace or canonical folder name");
return nsnull;
}
char *rv = nsnull;
// convert the canonical path to the online path
char *convertedFolderName = AllocateServerFolderName(canonicalFolderName, namespaceForFolder->GetDelimiter());
if (convertedFolderName)
{
#ifdef DEBUG
NS_ASSERTION(strlen(convertedFolderName) > strlen(namespaceForFolder->GetPrefix()), "server folder name invalid");
#endif
if (strlen(convertedFolderName) > strlen(namespaceForFolder->GetPrefix()))
{
char *owner = convertedFolderName + strlen(namespaceForFolder->GetPrefix());
NS_ASSERTION(owner, "couldn't find folder owner");
char *nextDelimiter = strchr(owner, namespaceForFolder->GetDelimiter());
// if !nextDelimiter, then the path is of the form Shared/Users/chrisf (no subfolder)
if (nextDelimiter)
{
*nextDelimiter = 0;
}
rv = strdup(owner);
}
PR_Free(convertedFolderName);
}
else
{
NS_ASSERTION(PR_FALSE, "couldn't allocate server folder name");
}
return rv;
}
/*
GetFolderIsNamespace returns TRUE if the given folder is the folder representing
a namespace.
*/
PRBool nsIMAPNamespaceList::GetFolderIsNamespace(const char *hostName,
const char *canonicalFolderName,
char delimiter,nsIMAPNamespace *namespaceForFolder)
{
NS_ASSERTION(namespaceForFolder, "null namespace");
PRBool rv = PR_FALSE;
const char *prefix = namespaceForFolder->GetPrefix();
NS_ASSERTION(prefix, "namespace has no prefix");
if (!prefix || !*prefix) // empty namespace prefix
return PR_FALSE;
char *convertedFolderName = AllocateServerFolderName(canonicalFolderName, delimiter);
if (convertedFolderName)
{
PRBool lastCharIsDelimiter = (prefix[strlen(prefix) - 1] == delimiter);
if (lastCharIsDelimiter)
{
rv = ((strncmp(convertedFolderName, prefix, strlen(convertedFolderName)) == 0) &&
(strlen(convertedFolderName) == strlen(prefix) - 1));
}
else
{
rv = (strcmp(convertedFolderName, prefix) == 0);
}
PR_FREEIF(convertedFolderName);
}
else
{
NS_ASSERTION(PR_FALSE, "couldn't allocate server folder name");
}
return rv;
}
/*
SuggestHierarchySeparatorForNamespace takes a namespace from libmsg
and a hierarchy delimiter. If the namespace has not been filled in from
online NAMESPACE command yet, it fills in the suggested delimiter to be
used from then on (until it is overridden by an online response).
*/
void nsIMAPNamespaceList::SuggestHierarchySeparatorForNamespace(nsIMAPNamespace *namespaceForFolder, char delimiterFromFolder)
{
NS_ASSERTION(namespaceForFolder, "need namespace");
if (namespaceForFolder && !namespaceForFolder->GetIsDelimiterFilledIn())
namespaceForFolder->SetDelimiter(delimiterFromFolder, PR_FALSE);
}

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

@ -40,30 +40,30 @@
class nsIMAPNamespace
{
public:
nsIMAPNamespace(EIMAPNamespaceType type, const char *prefix, char delimiter, PRBool from_prefs);
~nsIMAPNamespace();
EIMAPNamespaceType GetType() { return m_namespaceType; }
const char * GetPrefix() { return m_prefix; }
char GetDelimiter() { return m_delimiter; }
void SetDelimiter(char delimiter);
PRBool GetIsDelimiterFilledIn() { return m_delimiterFilledIn; }
PRBool GetIsNamespaceFromPrefs() { return m_fromPrefs; }
// returns -1 if this box is not part of this namespace,
// or the length of the prefix if it is part of this namespace
int MailboxMatchesNamespace(const char *boxname);
nsIMAPNamespace(EIMAPNamespaceType type, const char *prefix, char delimiter, PRBool from_prefs);
~nsIMAPNamespace();
EIMAPNamespaceType GetType() { return m_namespaceType; }
const char * GetPrefix() { return m_prefix; }
char GetDelimiter() { return m_delimiter; }
void SetDelimiter(char delimiter, PRBool delimiterFilledIn);
PRBool GetIsDelimiterFilledIn() { return m_delimiterFilledIn; }
PRBool GetIsNamespaceFromPrefs() { return m_fromPrefs; }
// returns -1 if this box is not part of this namespace,
// or the length of the prefix if it is part of this namespace
int MailboxMatchesNamespace(const char *boxname);
protected:
EIMAPNamespaceType m_namespaceType;
char *m_prefix;
char m_delimiter;
PRBool m_fromPrefs;
PRBool m_delimiterFilledIn;
EIMAPNamespaceType m_namespaceType;
char *m_prefix;
char m_delimiter;
PRBool m_fromPrefs;
PRBool m_delimiterFilledIn;
};
@ -71,30 +71,41 @@ protected:
class nsIMAPNamespaceList
{
public:
~nsIMAPNamespaceList();
static nsIMAPNamespaceList *CreatensIMAPNamespaceList();
nsresult InitFromString(const char *nameSpaceString, EIMAPNamespaceType nstype);
nsresult OutputToString(nsCString &OutputString);
int UnserializeNamespaces(const char *str, char **prefixes, int len);
nsresult SerializeNamespaces(char **prefixes, int len, nsCString &serializedNamespace);
void ClearNamespaces(PRBool deleteFromPrefsNamespaces, PRBool deleteServerAdvertisedNamespaces, PRBool reallyDelete);
int GetNumberOfNamespaces();
int GetNumberOfNamespaces(EIMAPNamespaceType);
nsIMAPNamespace *GetNamespaceNumber(int nodeIndex);
nsIMAPNamespace *GetNamespaceNumber(int nodeIndex, EIMAPNamespaceType);
nsIMAPNamespace *GetDefaultNamespaceOfType(EIMAPNamespaceType type);
int AddNewNamespace(nsIMAPNamespace *ns);
nsIMAPNamespace *GetNamespaceForMailbox(const char *boxname);
~nsIMAPNamespaceList();
static nsIMAPNamespaceList *CreatensIMAPNamespaceList();
nsresult InitFromString(const char *nameSpaceString, EIMAPNamespaceType nstype);
nsresult OutputToString(nsCString &OutputString);
int UnserializeNamespaces(const char *str, char **prefixes, int len);
nsresult SerializeNamespaces(char **prefixes, int len, nsCString &serializedNamespace);
void ClearNamespaces(PRBool deleteFromPrefsNamespaces, PRBool deleteServerAdvertisedNamespaces, PRBool reallyDelete);
int GetNumberOfNamespaces();
int GetNumberOfNamespaces(EIMAPNamespaceType);
nsIMAPNamespace *GetNamespaceNumber(int nodeIndex);
nsIMAPNamespace *GetNamespaceNumber(int nodeIndex, EIMAPNamespaceType);
nsIMAPNamespace *GetDefaultNamespaceOfType(EIMAPNamespaceType type);
int AddNewNamespace(nsIMAPNamespace *ns);
nsIMAPNamespace *GetNamespaceForMailbox(const char *boxname);
static nsIMAPNamespace* GetNamespaceForFolder(const char *hostName,
const char *canonicalFolderName,
char delimiter);
static PRBool GetFolderIsNamespace(const char *hostName,
const char *canonicalFolderName,
char delimiter,nsIMAPNamespace *namespaceForFolder);
static char* GetFolderNameWithoutNamespace(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName);
static char *AllocateServerFolderName(const char *canonicalFolderName, char delimiter);
static char *GetFolderOwnerNameFromPath(nsIMAPNamespace *namespaceForFolder, const char *canonicalFolderName);
static char *AllocateCanonicalFolderName(const char *onlineFolderName, char delimiter);
static void SuggestHierarchySeparatorForNamespace(nsIMAPNamespace *namespaceForFolder, char delimiterFromFolder);
protected:
nsIMAPNamespaceList(); // use CreatensIMAPNamespaceList to create one
nsVoidArray m_NamespaceList;
nsIMAPNamespaceList(); // use CreatensIMAPNamespaceList to create one
nsVoidArray m_NamespaceList;
};

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

@ -89,7 +89,6 @@
#include "nsITimer.h"
#include "nsMsgUtils.h"
static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
@ -1061,7 +1060,9 @@ NS_IMETHODIMP nsImapIncomingServer::GetSentMailPFC(PRBool createIfMissing, nsIMs
}
// nsIImapServerSink impl
NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath, PRUnichar hierarchyDelimiter, PRInt32 boxFlags)
// aNewFolder will not be set if we're listing for the subscribe UI, since that's the way 4.x worked.
NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath, PRUnichar hierarchyDelimiter,
PRInt32 boxFlags, PRBool *aNewFolder)
{
// folderPath is in canonical format, i.e., hierarchy separator has been replaced with '/'
nsresult rv;
@ -1071,8 +1072,9 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
nsCOMPtr<nsIMsgFolder> aFolder;
PRBool explicitlyVerify = PR_FALSE;
if (!folderPath || !*folderPath) return NS_ERROR_NULL_POINTER;
if (!folderPath || !*folderPath || !aNewFolder) return NS_ERROR_NULL_POINTER;
*aNewFolder = PR_FALSE;
nsCOMPtr<nsIFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
@ -1142,79 +1144,82 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
nsXPIDLCString serverUri;
GetServerURI(getter_Copies(serverUri));
uri.Assign(serverUri);
PRInt32 leafPos = folderName.RFindChar('/');
nsCAutoString parentName(folderName);
nsCAutoString parentUri(uri);
if (leafPos > 0)
{
// If there is a hierarchy, there is a parent.
// Don't strip off slash if it's the first character
parentName.Truncate(leafPos);
folderName.Cut(0, leafPos + 1); // get rid of the parent name
haveParent = PR_TRUE;
parentUri.Append('/');
parentUri.Append(parentName);
uri.Assign(serverUri);
PRInt32 leafPos = folderName.RFindChar('/');
nsCAutoString parentName(folderName);
nsCAutoString parentUri(uri);
if (leafPos > 0)
{
// If there is a hierarchy, there is a parent.
// Don't strip off slash if it's the first character
parentName.Truncate(leafPos);
folderName.Cut(0, leafPos + 1); // get rid of the parent name
haveParent = PR_TRUE;
parentUri.Append('/');
parentUri.Append(parentName);
}
if (nsCRT::strcasecmp("INBOX", folderPath) == 0 &&
hierarchyDelimiter == kOnlineHierarchySeparatorNil)
{
hierarchyDelimiter = '/'; // set to default in this case (as in 4.x)
hostFolder->SetHierarchyDelimiter(hierarchyDelimiter);
}
// Check to see if we need to ignore this folder (like AOL's 'RECYCLE_OUT').
PRBool hideFolder;
rv = HideFolderName(dupFolderPath.get(), &hideFolder);
if (hideFolder)
return NS_OK;
nsCOMPtr <nsIMsgFolder> child;
// nsCString possibleName(aSpec->allocatedPathName);
uri.Append('/');
uri.Append(dupFolderPath);
PRBool caseInsensitive = (nsCRT::strcasecmp("INBOX", dupFolderPath.get()) == 0);
a_nsIFolder->GetChildWithURI(uri.get(), PR_TRUE, caseInsensitive, getter_AddRefs(child));
// if we couldn't find this folder by URI, tell the imap code it's a new folder to us
*aNewFolder = !child;
if (child)
found = PR_TRUE;
if (!found)
{
// trying to find/discover the parent
if (haveParent)
{
nsCOMPtr <nsIMsgFolder> parent;
PRBool parentIsNew;
caseInsensitive = (nsCRT::strcasecmp("INBOX", parentName.get()) == 0);
a_nsIFolder->GetChildWithURI(parentUri.get(), PR_TRUE, caseInsensitive, getter_AddRefs(parent));
if (!parent /* || parentFolder->GetFolderNeedsAdded()*/)
{
PossibleImapMailbox(parentName.get(), hierarchyDelimiter, kNoselect | // be defensive
((boxFlags & //only inherit certain flags from the child
(kPublicMailbox | kOtherUsersMailbox | kPersonalMailbox))), &parentIsNew);
}
}
if (nsCRT::strcasecmp("INBOX", folderPath) == 0 &&
hierarchyDelimiter == kOnlineHierarchySeparatorNil)
hostFolder->CreateClientSubfolderInfo(dupFolderPath.get(), hierarchyDelimiter,boxFlags);
caseInsensitive = (nsCRT::strcasecmp("INBOX", dupFolderPath.get())== 0);
a_nsIFolder->GetChildWithURI(uri.get(), PR_TRUE, caseInsensitive , getter_AddRefs(child));
}
if (child)
{
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
if (imapFolder)
{
hierarchyDelimiter = '/'; // set to default in this case (as in 4.x)
hostFolder->SetHierarchyDelimiter(hierarchyDelimiter);
}
// Check to see if we need to ignore this folder (like AOL's 'RECYCLE_OUT').
PRBool hideFolder;
rv = HideFolderName(dupFolderPath.get(), &hideFolder);
if (hideFolder)
return NS_OK;
nsCOMPtr <nsIMsgFolder> child;
// nsCString possibleName(aSpec->allocatedPathName);
uri.Append('/');
uri.Append(dupFolderPath);
PRBool caseInsensitive = (nsCRT::strcasecmp("INBOX", dupFolderPath.get()) == 0);
a_nsIFolder->GetChildWithURI(uri.get(), PR_TRUE, caseInsensitive, getter_AddRefs(child));
if (child)
found = PR_TRUE;
if (!found)
{
// trying to find/discover the parent
if (haveParent)
{
nsCOMPtr <nsIMsgFolder> parent;
caseInsensitive = (nsCRT::strcasecmp("INBOX", parentName.get()) == 0);
a_nsIFolder->GetChildWithURI(parentUri.get(), PR_TRUE, caseInsensitive, getter_AddRefs(parent));
if (!parent /* || parentFolder->GetFolderNeedsAdded()*/)
{
PossibleImapMailbox(parentName.get(), hierarchyDelimiter, kNoselect | // be defensive
((boxFlags & //only inherit certain flags from the child
(kPublicMailbox | kOtherUsersMailbox | kPersonalMailbox))));
}
}
hostFolder->CreateClientSubfolderInfo(dupFolderPath.get(), hierarchyDelimiter,boxFlags);
caseInsensitive = (nsCRT::strcasecmp("INBOX", dupFolderPath.get())== 0);
a_nsIFolder->GetChildWithURI(uri.get(), PR_TRUE, caseInsensitive , getter_AddRefs(child));
}
if (child)
{
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
if (imapFolder)
{
PRBool isAOLServer = PR_FALSE;
GetIsAOLServer(&isAOLServer);
nsXPIDLCString onlineName;
nsXPIDLString unicodeName;
imapFolder->SetVerifiedAsOnlineFolder(PR_TRUE);
@ -1241,14 +1246,14 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
dupFolderPath.ReplaceChar('/', hierarchyDelimiter);
if (hierarchyDelimiter != '/')
nsImapUrl::UnescapeSlashes(NS_CONST_CAST(char*, dupFolderPath.get()));
if (! (onlineName.get()) || nsCRT::strlen(onlineName.get()) == 0
|| nsCRT::strcmp(onlineName.get(), dupFolderPath.get()))
imapFolder->SetOnlineName(dupFolderPath.get());
|| nsCRT::strcmp(onlineName.get(), dupFolderPath.get()))
imapFolder->SetOnlineName(dupFolderPath.get());
if (hierarchyDelimiter != '/')
nsImapUrl::UnescapeSlashes(NS_CONST_CAST(char*, folderName.get()));
if (NS_SUCCEEDED(CreatePRUnicharStringFromUTF7(folderName.get(), getter_Copies(unicodeName))))
child->SetName(unicodeName);
if (NS_SUCCEEDED(CreatePRUnicharStringFromUTF7(folderName.get(), getter_Copies(unicodeName))))
child->SetName(unicodeName);
// Call ConvertFolderName() and HideFolderName() to do special folder name
// mapping and hiding, if configured to do so. For example, need to hide AOL's
// 'RECYCLE_OUT' & convert a few AOL folder names. Regular imap accounts
@ -1272,6 +1277,48 @@ NS_IMETHODIMP nsImapIncomingServer::PossibleImapMailbox(const char *folderPath,
return NS_OK;
}
NS_IMETHODIMP nsImapIncomingServer::AddFolderRights(const char *mailboxName, const char *userName, const char *rights)
{
nsCOMPtr <nsIFolder> rootFolder;
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
if(NS_SUCCEEDED(rv) && rootFolder)
{
nsCOMPtr <nsIMsgImapMailFolder> imapRoot = do_QueryInterface(rootFolder);
if (imapRoot)
{
nsCOMPtr <nsIMsgImapMailFolder> foundFolder;
rv = imapRoot->FindOnlineSubFolder(mailboxName, getter_AddRefs(foundFolder));
if (NS_SUCCEEDED(rv) && foundFolder)
return foundFolder->AddFolderRights(userName, rights);
}
}
return rv;
}
NS_IMETHODIMP nsImapIncomingServer::FolderNeedsACLInitialized(const char *folderPath, PRBool *aNeedsACLInitialized)
{
NS_ENSURE_ARG_POINTER(aNeedsACLInitialized);
nsCOMPtr <nsIFolder> rootFolder;
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
if(NS_SUCCEEDED(rv) && rootFolder)
{
nsCOMPtr <nsIMsgImapMailFolder> imapRoot = do_QueryInterface(rootFolder);
if (imapRoot)
{
nsCOMPtr <nsIMsgImapMailFolder> foundFolder;
rv = imapRoot->FindOnlineSubFolder(folderPath, getter_AddRefs(foundFolder));
if (NS_SUCCEEDED(rv) && foundFolder)
{
nsCOMPtr <nsIImapMailFolderSink> folderSink = do_QueryInterface(foundFolder);
if (folderSink)
return folderSink->GetFolderNeedsACLListed(aNeedsACLInitialized);
}
}
}
*aNeedsACLInitialized = PR_FALSE; // maybe we want to say TRUE here...
return NS_OK;
}
NS_IMETHODIMP nsImapIncomingServer::GetRedirectorType(char **redirectorType)
{
nsresult rv;
@ -2048,23 +2095,24 @@ nsresult nsImapIncomingServer::GetStringBundle()
NS_IMETHODIMP nsImapIncomingServer::GetImapStringByID(PRInt32 aMsgId, PRUnichar **aString)
{
nsresult res = NS_OK;
nsresult res = NS_OK;
GetStringBundle();
if (m_stringBundle)
{
if (m_stringBundle)
{
res = m_stringBundle->GetStringFromID(aMsgId, aString);
if (NS_SUCCEEDED(res))
return res;
}
nsAutoString resultString(NS_LITERAL_STRING("String ID "));
resultString.AppendInt(aMsgId);
*aString = ToNewUnicode(resultString);
*aString = ToNewUnicode(resultString);
return NS_OK;
}
}
NS_IMETHODIMP nsImapIncomingServer::FormatStringWithHostNameByID(PRInt32 aMsgId, PRUnichar **aString)
{
{
nsresult res = NS_OK;
GetStringBundle();
@ -2080,11 +2128,11 @@ NS_IMETHODIMP nsImapIncomingServer::FormatStringWithHostNameByID(PRInt32 aMsgId
res = m_stringBundle->FormatStringFromID(aMsgId, params, 1, aString);
if (NS_SUCCEEDED(res))
return res;
}
}
}
}
nsAutoString resultString(NS_LITERAL_STRING("String ID "));
resultString.AppendInt(aMsgId);
*aString = ToNewUnicode(resultString);
*aString = ToNewUnicode(resultString);
return NS_OK;
}
@ -2255,101 +2303,50 @@ NS_IMETHODIMP nsImapIncomingServer::CommitNamespaces()
NS_IMETHODIMP nsImapIncomingServer::PseudoInterruptMsgLoad(nsIImapUrl *aImapUrl, PRBool *interrupted)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIImapProtocol> connection;
nsresult rv = NS_OK;
nsCOMPtr<nsIImapProtocol> connection;
PR_CEnterMonitor(this);
// iterate through the connection cache for a connection that is loading
// a message in this folder and should be pseudo-interrupted.
PRUint32 cnt;
// iterate through the connection cache for a connection that is loading
// a message in this folder and should be pseudo-interrupted.
PRUint32 cnt;
nsCOMPtr<nsISupports> aSupport;
rv = m_connectionCache->Count(&cnt);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < cnt; i++)
{
aSupport = getter_AddRefs(m_connectionCache->ElementAt(i));
connection = do_QueryInterface(aSupport);
if (connection)
rv = connection->PseudoInterruptMsgLoad(aImapUrl, interrupted);
}
if (connection)
rv = connection->PseudoInterruptMsgLoad(aImapUrl, interrupted);
}
PR_CExitMonitor(this);
return rv;
return rv;
}
NS_IMETHODIMP nsImapIncomingServer::ResetNamespaceReferences()
{
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr <nsIFolder> rootFolder;
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
{
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(rootFolder);
if (imapFolder)
rv = imapFolder->ResetNamespaceReferences();
}
return rv;
}
#if FINISHED_PORTED_NAMESPACE_STUFF
int numberOfChildren = GetNumSubFolders();
for (int childIndex = 0; childIndex < numberOfChildren; childIndex++)
{
MSG_IMAPFolderInfoMail *currentChild = (MSG_IMAPFolderInfoMail *) GetSubFolder(childIndex);
currentChild->ResetNamespaceReferences();
}
//void MSG_IMAPFolderInfoMail::InitializeFolderCreatedOffline()
//{
// TIMAPNamespace *ns = IMAPNS_GetNamespaceForFolder(m_host->GetHostName(), GetOnlineName(), '/');
// SetOnlineHierarchySeparator(IMAPNS_GetDelimiterForNamespace(ns));
//}
void MSG_IMAPFolderInfoMail::SetFolderIsNamespace(XP_Bool isNamespace)
{
m_folderIsNamespace = isNamespace;
}
void MSG_IMAPFolderInfoMail::InitializeFolderCreatedOffline()
{
TIMAPNamespace *ns = IMAPNS_GetNamespaceForFolder(m_host->GetHostName(), GetOnlineName(), '/');
SetOnlineHierarchySeparator(IMAPNS_GetDelimiterForNamespace(ns));
}
TIMAPNamespace *MSG_IMAPFolderInfoMail::GetNamespaceForFolder()
{
if (!m_namespace)
{
#ifdef DEBUG_bienvenu
// Make sure this isn't causing us to open the database
PR_ASSERT(m_OnlineHierSeparator != kOnlineHierarchySeparatorUnknown);
#endif
m_namespace = IMAPNS_GetNamespaceForFolder(m_host->GetHostName(), GetOnlineName(), GetOnlineHierarchySeparator());
PR_ASSERT(m_namespace);
if (m_namespace)
{
IMAPNS_SuggestHierarchySeparatorForNamespace(m_namespace, GetOnlineHierarchySeparator());
m_folderIsNamespace = IMAPNS_GetFolderIsNamespace(m_host->GetHostName(), GetOnlineName(), GetOnlineHierarchySeparator(), m_namespace);
}
}
return m_namespace;
}
void MSG_IMAPFolderInfoMail::SetNamespaceForFolder(TIMAPNamespace *ns)
{
#ifdef DEBUG_bienvenu
NS_ASSERTION(ns, "null namespace");
#endif
m_namespace = ns;
}
void MSG_IMAPFolderInfoMail::ResetNamespaceReferences()
{
// this
m_namespace = IMAPNS_GetNamespaceForFolder(GetHostName(), GetOnlineName(), GetOnlineHierarchySeparator());
NS_ASSERTION(m_namespace, "resetting null namespace");
if (m_namespace)
m_folderIsNamespace = IMAPNS_GetFolderIsNamespace(GetHostName(), GetOnlineName(), GetOnlineHierarchySeparator(), m_namespace);
else
m_folderIsNamespace = PR_FALSE;
// children
int numberOfChildren = GetNumSubFolders();
for (int childIndex = 0; childIndex < numberOfChildren; childIndex++)
{
MSG_IMAPFolderInfoMail *currentChild = (MSG_IMAPFolderInfoMail *) GetSubFolder(childIndex);
currentChild->ResetNamespaceReferences();
}
}
#endif //FINISHED_PORTED_NAMESPACE_STUFF
NS_IMPL_GETSET(nsImapIncomingServer, UserAuthenticated, PRBool, m_userAuthenticated);

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

@ -94,6 +94,8 @@
#include "nsIImapMockChannel.h"
#include "nsIWebNavigation.h"
#include "nsNetUtil.h"
#include "nsIMAPNamespace.h"
#include "nsHashtable.h"
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
@ -212,6 +214,8 @@ nsImapMailFolder::nsImapMailFolder() :
m_uidValidity = 0;
m_hierarchyDelimiter = kOnlineHierarchySeparatorUnknown;
m_pathName = nsnull;
m_folderACL = nsnull;
m_namespace = nsnull;
}
nsImapMailFolder::~nsImapMailFolder()
@ -223,6 +227,7 @@ nsImapMailFolder::~nsImapMailFolder()
if (m_moveCoalescer)
delete m_moveCoalescer;
delete m_pathName;
delete m_folderACL;
}
NS_IMPL_ADDREF_INHERITED(nsImapMailFolder, nsMsgDBFolder)
@ -1949,7 +1954,7 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsISupportsArray *messages,
else
{
EnableNotifications(allMessageCountNotifications, PR_FALSE); //"remove it immediately" model
mDatabase->DeleteMessages(&srcKeyArray,NULL);
mDatabase->DeleteMessages(&srcKeyArray,nsnull);
EnableNotifications(allMessageCountNotifications, PR_TRUE);
NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom);
}
@ -2358,7 +2363,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
// It would be nice to notify RDF or whoever of a mass delete here.
if (mDatabase) {
mDatabase->DeleteMessages(&keysToDelete,NULL);
mDatabase->DeleteMessages(&keysToDelete,nsnull);
total = keysToDelete.GetSize();
}
}
@ -2382,7 +2387,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(
{
// let the imap libnet module know that we don't need headers
if (aProtocol)
aProtocol->NotifyHdrsToDownload(NULL, 0);
aProtocol->NotifyHdrsToDownload(nsnull, 0);
PRBool gettingNewMessages;
GetGettingNewMessages(&gettingNewMessages);
if (gettingNewMessages)
@ -3013,15 +3018,132 @@ NS_IMETHODIMP nsImapMailFolder::LiteSelect(nsIUrlListener *aUrlListener)
return rv;
}
NS_IMETHODIMP nsImapMailFolder::FolderPrivileges(nsIMsgWindow *window)
nsresult nsImapMailFolder::GetFolderOwnerUserName(char **userName)
{
if ((mFlags & MSG_FOLDER_FLAG_IMAP_PERSONAL) ||
!(mFlags & (MSG_FOLDER_FLAG_IMAP_PUBLIC | MSG_FOLDER_FLAG_IMAP_OTHER_USER)))
{
// this is one of our personal mail folders
// return our username on this host
nsCOMPtr<nsIMsgIncomingServer> server;
nsresult rv = GetServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server)
return server->GetUsername(userName);
else
return rv;
}
// the only other type of owner is if it's in the other users' namespace
if (!(mFlags & MSG_FOLDER_FLAG_IMAP_OTHER_USER))
return NS_OK;
if (!m_ownerUserName.Length())
{
nsXPIDLCString onlineName;
GetOnlineName(getter_Copies(onlineName));
m_ownerUserName = nsIMAPNamespaceList::GetFolderOwnerNameFromPath(GetNamespaceForFolder(), onlineName.get());
}
*userName = (m_ownerUserName.Length()) ? ToNewCString(m_ownerUserName) : nsnull;
return NS_OK;
}
// returns the online folder name, with the other users' namespace and his username
// stripped out
nsresult nsImapMailFolder::GetOwnersOnlineFolderName(char **retName)
{
nsXPIDLCString onlineName;
GetOnlineName(getter_Copies(onlineName));
if (mFlags & MSG_FOLDER_FLAG_IMAP_OTHER_USER)
{
nsXPIDLCString user;
GetFolderOwnerUserName(getter_Copies(user));
if (onlineName.Length() && user.Length())
{
const char *where = PL_strstr(onlineName.get(), user.get());
NS_ASSERTION(where, "user name not in online name");
if (where)
{
const char *relativeFolder = where + strlen(user) + 1;
if (!relativeFolder) // root of this user's personal namespace
{
*retName = strdup("");
return NS_OK;
}
else
{
*retName = strdup(relativeFolder);
return NS_OK;
}
}
}
*retName = strdup(onlineName.get());
return NS_OK;
}
else if (!(mFlags & MSG_FOLDER_FLAG_IMAP_PUBLIC))
{
// We own this folder.
*retName = nsIMAPNamespaceList::GetFolderNameWithoutNamespace(GetNamespaceForFolder(), onlineName);
}
else
*retName = strdup(onlineName.get());
return NS_OK;
}
nsIMAPNamespace *nsImapMailFolder::GetNamespaceForFolder()
{
if (!m_namespace)
{
#ifdef DEBUG_bienvenu
// Make sure this isn't causing us to open the database
NS_ASSERTION(m_hierarchyDelimiter != kOnlineHierarchySeparatorUnknown, "haven't set hierarchy delimiter");
#endif
nsXPIDLCString serverKey;
nsXPIDLCString onlineName;
GetServerKey(getter_Copies(serverKey));
GetOnlineName(getter_Copies(onlineName));
PRUnichar hierarchyDelimiter;
GetHierarchyDelimiter(&hierarchyDelimiter);
m_namespace = nsIMAPNamespaceList::GetNamespaceForFolder(serverKey.get(), onlineName.get(), (char) hierarchyDelimiter);
NS_ASSERTION(m_namespace, "didn't get namespace for folder");
if (m_namespace)
{
nsIMAPNamespaceList::SuggestHierarchySeparatorForNamespace(m_namespace, (char) hierarchyDelimiter);
m_folderIsNamespace = nsIMAPNamespaceList::GetFolderIsNamespace(serverKey.get(), onlineName.get(), (char) hierarchyDelimiter, m_namespace);
}
}
return m_namespace;
}
void nsImapMailFolder::SetNamespaceForFolder(nsIMAPNamespace *ns)
{
#ifdef DEBUG_bienvenu
NS_ASSERTION(ns, "null namespace");
#endif
m_namespace = ns;
}
nsresult nsImapMailFolder::GetServerAdminUrl(char **aAdminUrl)
{
nsCOMPtr<nsIImapIncomingServer> imapServer;
nsresult rv = GetImapIncomingServer(getter_AddRefs(imapServer));
if (window && NS_SUCCEEDED(rv) && imapServer)
if (NS_SUCCEEDED(rv) && imapServer)
rv = imapServer->GetManageMailAccountUrl(aAdminUrl);
return rv;
}
NS_IMETHODIMP nsImapMailFolder::FolderPrivileges(nsIMsgWindow *window)
{
nsresult rv = NS_ERROR_NULL_POINTER; // if no window...
if (window)
{
nsXPIDLCString manageMailAccountUrl;
rv = imapServer->GetManageMailAccountUrl(getter_Copies(manageMailAccountUrl));
rv = GetServerAdminUrl(getter_Copies(manageMailAccountUrl));
if (NS_SUCCEEDED(rv) && manageMailAccountUrl.Length())
{
nsCOMPtr <nsIDocShell> docShell;
@ -3039,6 +3161,15 @@ NS_IMETHODIMP nsImapMailFolder::FolderPrivileges(nsIMsgWindow *window)
return rv;
}
NS_IMETHODIMP nsImapMailFolder::GetHasAdminUrl(PRBool *aBool)
{
NS_ENSURE_ARG_POINTER(aBool);
nsXPIDLCString manageMailAccountUrl;
nsresult rv = GetServerAdminUrl(getter_Copies(manageMailAccountUrl));
*aBool = (NS_SUCCEEDED(rv) && manageMailAccountUrl.Length());
return rv;
}
nsresult nsImapMailFolder::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
nsIMsgDatabase *sourceDB,
const char *destFolderUri,
@ -3225,7 +3356,7 @@ void nsImapMailFolder::PrepareToAddHeadersToMailDB(nsIImapProtocol* aProtocol, c
SetParseMailboxState(new ParseIMAPMailboxState(m_master, m_host, this,
urlQueue,
boxSpec->flagState));
boxSpec->flagState = NULL; // adopted by ParseIMAPMailboxState
boxSpec->flagState = nsnull; // adopted by ParseIMAPMailboxState
GetParseMailboxState()->SetPane(url_pane);
GetParseMailboxState()->SetDB(mailDB);
@ -3241,12 +3372,12 @@ void nsImapMailFolder::PrepareToAddHeadersToMailDB(nsIImapProtocol* aProtocol, c
aProtocol->NotifyHdrsToDownload(theKeys, total /*keysToFetch.GetSize() */);
// now, tell it we don't need any bodies.
if (aProtocol)
aProtocol->NotifyBodysToDownload(NULL, 0);
aProtocol->NotifyBodysToDownload(nsnull, 0);
}
else
{
if (aProtocol)
aProtocol->NotifyHdrsToDownload(NULL, 0);
aProtocol->NotifyHdrsToDownload(nsnull, 0);
}
}
}
@ -3546,7 +3677,7 @@ nsImapMailFolder::OnlineCopyCompleted(nsIImapProtocol *aProtocol, ImapOnlineCopy
char *keyTokenString = nsCRT::strdup(messageIds);
ParseUidString(keyTokenString, affectedMessages);
if (mDatabase)
mDatabase->DeleteMessages(&affectedMessages,NULL);
mDatabase->DeleteMessages(&affectedMessages,nsnull);
nsCRT::free(keyTokenString);
return rv;
}
@ -3667,7 +3798,7 @@ nsImapMailFolder::NotifyMessageDeleted(const char *onlineFolderName,PRBool delet
if (deleteAllMsgs)
{
#ifdef HAVE_PORT
TNeoFolderInfoTransfer *originalInfo = NULL;
TNeoFolderInfoTransfer *originalInfo = nsnull;
nsIMsgDatabase *folderDB;
if (ImapMailDB::Open(GetPathname(), PR_FALSE, &folderDB, GetMaster(), &wasCreated) == eSUCCESS)
{
@ -4195,28 +4326,45 @@ NS_IMETHODIMP
nsImapMailFolder::ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
SetFolderNeedsACLListed(PR_FALSE);
delete m_folderACL;
m_folderACL = new nsMsgIMAPFolderACL(this);
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
nsImapMailFolder::AddFolderRights(const char *userName, const char *rights)
{
return NS_ERROR_FAILURE;
SetFolderNeedsACLListed(PR_FALSE);
GetFolderACL()->SetFolderRightsForUser(userName, rights);
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
if (GetFolderACL()->GetIsFolderShared())
{
SetFlag(MSG_FOLDER_FLAG_PERSONAL_SHARED);
}
else
{
ClearFlag(MSG_FOLDER_FLAG_PERSONAL_SHARED);
}
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
return NS_ERROR_FAILURE;
PRBool noSelect;
GetFlag(MSG_FOLDER_FLAG_IMAP_NOSELECT, &noSelect);
return (m_folderNeedsACLListed &&
!GetFolderIsNamespace() &&
!noSelect);
}
NS_IMETHODIMP
@ -4459,7 +4607,7 @@ nsImapMailFolder::HeaderFetchCompleted(nsIImapProtocol* aProtocol)
aProtocol->NotifyBodysToDownload(keysToDownload.GetArray(), keysToDownload.GetSize());
}
else
aProtocol->NotifyBodysToDownload(NULL, 0/*keysToFetch.GetSize() */);
aProtocol->NotifyBodysToDownload(nsnull, 0/*keysToFetch.GetSize() */);
}
return NS_OK;
}
@ -4495,6 +4643,502 @@ nsImapMailFolder::LiteSelectUIDValidity(nsIImapProtocol* aProtocol,
return NS_OK;
}
NS_IMETHODIMP
nsImapMailFolder::FillInFolderProps(nsIMsgImapFolderProps *aFolderProps)
{
NS_ENSURE_ARG(aFolderProps);
PRUint32 folderTypeStringID;
PRUint32 folderTypeDescStringID = 0;
nsXPIDLString folderType;
nsXPIDLString folderTypeDesc;
nsCOMPtr<nsIStringBundle> bundle;
nsresult rv = IMAPGetStringBundle(getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
if (mFlags & MSG_FOLDER_FLAG_IMAP_PUBLIC)
{
folderTypeStringID = IMAP_PUBLIC_FOLDER_TYPE_NAME;
folderTypeDescStringID = IMAP_PUBLIC_FOLDER_TYPE_DESCRIPTION;
}
else if (mFlags & MSG_FOLDER_FLAG_IMAP_OTHER_USER)
{
folderTypeStringID = IMAP_OTHER_USERS_FOLDER_TYPE_NAME;
nsXPIDLCString owner;
nsXPIDLString uniOwner;
GetFolderOwnerUserName(getter_Copies(owner));
if (!owner.Length())
{
rv = IMAPGetStringByID(folderTypeStringID, getter_Copies(uniOwner));
// Another user's folder, for which we couldn't find an owner name
NS_ASSERTION(PR_FALSE, "couldn't get owner name for other user's folder");
}
else
{
// is this right? It doesn't leak, does it?
uniOwner.Assign(NS_ConvertASCIItoUCS2(owner.get()));
}
const PRUnichar *params[] = { uniOwner.get() };
rv = bundle->FormatStringFromID(IMAP_OTHER_USERS_FOLDER_TYPE_DESCRIPTION, params, 1, getter_Copies(folderTypeDesc));
}
// personal folder - 4.x distinguished between shared and not personal folders,
// but put up the same folder type, so we don't need to distinguish here, I guess.
// else if (GetFolderACL()->GetIsFolderShared())
// folderTypeStringID = IMAP_PERSONAL_SHARED_FOLDER_TYPE_NAME;
else
{
folderTypeStringID = IMAP_PERSONAL_SHARED_FOLDER_TYPE_NAME;
folderTypeDescStringID = IMAP_PERSONAL_SHARED_FOLDER_TYPE_DESCRIPTION;
}
rv = IMAPGetStringByID(folderTypeStringID, getter_Copies(folderType));
if (NS_SUCCEEDED(rv))
aFolderProps->SetFolderType(folderType);
if (!folderTypeDesc.Length() && folderTypeDescStringID != 0)
rv = IMAPGetStringByID(folderTypeDescStringID, getter_Copies(folderTypeDesc));
if (folderTypeDesc.Length())
aFolderProps->SetFolderTypeDescription(folderTypeDesc.get());
nsXPIDLString rightsString;
rv = CreateACLRightsStringForFolder(getter_Copies(rightsString));
if (NS_SUCCEEDED(rv))
aFolderProps->SetFolderPermissions(rightsString.get());
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::SetAclFlags(PRUint32 aclFlags)
{
nsCOMPtr<nsIDBFolderInfo> dbFolderInfo;
nsresult rv = GetDatabase(nsnull);
if (mDatabase)
{
rv = mDatabase->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
if (NS_SUCCEEDED(rv) && dbFolderInfo)
dbFolderInfo->SetUint32Property("aclFlags", aclFlags);
}
return rv;
}
NS_IMETHODIMP nsImapMailFolder::GetAclFlags(PRUint32 *aclFlags)
{
NS_ENSURE_ARG_POINTER(aclFlags);
nsCOMPtr<nsIDBFolderInfo> dbFolderInfo;
nsresult rv = GetDatabase(nsnull);
if (mDatabase)
{
rv = mDatabase->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
if (NS_SUCCEEDED(rv) && dbFolderInfo)
rv = dbFolderInfo->GetUint32Property("aclFlags", aclFlags, 0);
}
return rv;
}
NS_IMETHODIMP nsImapMailFolder::GetCanIOpenThisFolder(PRBool *aBool)
{
NS_ENSURE_ARG_POINTER(aBool);
PRBool noSelect;
GetFlag(MSG_FOLDER_FLAG_IMAP_NOSELECT, &noSelect);
*aBool = (noSelect) ? PR_FALSE : GetFolderACL()->GetCanIReadFolder();
return NS_OK;
}
///////// nsMsgIMAPFolderACL class ///////////////////////////////
// This string is defined in the ACL RFC to be "anyone"
#define IMAP_ACL_ANYONE_STRING "anyone"
static int
imap_hash_strcmp (const void *a, const void *b)
{
return strcmp ((const char *) a, (const char *) b);
}
/* static */PRBool nsMsgIMAPFolderACL::FreeHashRights(nsHashKey *aKey, void *aData,
void *closure)
{
PR_FREEIF(aData);
return PR_TRUE;
}
nsMsgIMAPFolderACL::nsMsgIMAPFolderACL(nsImapMailFolder *folder)
{
NS_ASSERTION(folder, "need folder");
m_folder = folder;
m_rightsHash = new nsHashtable(24);
m_aclCount = 0;
BuildInitialACLFromCache();
}
nsMsgIMAPFolderACL::~nsMsgIMAPFolderACL()
{
m_rightsHash->Reset(FreeHashRights, nsnull);
delete m_rightsHash;
}
// We cache most of our own rights in the MSG_FOLDER_PREF_* flags
void nsMsgIMAPFolderACL::BuildInitialACLFromCache()
{
nsCAutoString myrights;
PRUint32 startingFlags;
m_folder->GetAclFlags(&startingFlags);
if (startingFlags & IMAP_ACL_READ_FLAG)
myrights += "r";
if (startingFlags & IMAP_ACL_STORE_SEEN_FLAG)
myrights += "s";
if (startingFlags & IMAP_ACL_WRITE_FLAG)
myrights += "w";
if (startingFlags & IMAP_ACL_INSERT_FLAG)
myrights += "i";
if (startingFlags & IMAP_ACL_POST_FLAG)
myrights += "p";
if (startingFlags & IMAP_ACL_CREATE_SUBFOLDER_FLAG)
myrights +="c";
if (startingFlags & IMAP_ACL_DELETE_FLAG)
myrights += "d";
if (startingFlags & IMAP_ACL_ADMINISTER_FLAG)
myrights += "a";
if (myrights.Length())
SetFolderRightsForUser(nsnull, myrights.get());
}
void nsMsgIMAPFolderACL::UpdateACLCache()
{
PRUint32 startingFlags = 0;
m_folder->GetAclFlags(&startingFlags);
if (GetCanIReadFolder())
startingFlags |= IMAP_ACL_READ_FLAG;
else
startingFlags &= ~IMAP_ACL_READ_FLAG;
if (GetCanIStoreSeenInFolder())
startingFlags |= IMAP_ACL_STORE_SEEN_FLAG;
else
startingFlags &= ~IMAP_ACL_STORE_SEEN_FLAG;
if (GetCanIWriteFolder())
startingFlags |= IMAP_ACL_WRITE_FLAG;
else
startingFlags &= ~IMAP_ACL_WRITE_FLAG;
if (GetCanIInsertInFolder())
startingFlags |= IMAP_ACL_INSERT_FLAG;
else
startingFlags &= ~IMAP_ACL_INSERT_FLAG;
if (GetCanIPostToFolder())
startingFlags |= IMAP_ACL_POST_FLAG;
else
startingFlags &= ~IMAP_ACL_POST_FLAG;
if (GetCanICreateSubfolder())
startingFlags |= IMAP_ACL_CREATE_SUBFOLDER_FLAG;
else
startingFlags &= ~IMAP_ACL_CREATE_SUBFOLDER_FLAG;
if (GetCanIDeleteInFolder())
startingFlags |= IMAP_ACL_DELETE_FLAG;
else
startingFlags &= ~IMAP_ACL_DELETE_FLAG;
if (GetCanIAdministerFolder())
startingFlags |= IMAP_ACL_ADMINISTER_FLAG;
else
startingFlags &= ~IMAP_ACL_ADMINISTER_FLAG;
m_folder->SetAclFlags(startingFlags);
}
PRBool nsMsgIMAPFolderACL::SetFolderRightsForUser(const char *userName, const char *rights)
{
PRBool rv = PR_FALSE;
nsXPIDLCString myUserName;
m_folder->GetUsername(getter_Copies(myUserName));
char *ourUserName = nsnull;
if (!userName)
ourUserName = strdup(myUserName.get());
else
ourUserName = strdup(userName);
char *rightsWeOwn = strdup(rights);
nsCStringKey hashKey(ourUserName);
if (rightsWeOwn && ourUserName)
{
char *oldValue = (char *) m_rightsHash->Get(&hashKey);
if (oldValue)
{
PR_FREEIF(oldValue);
m_rightsHash->Remove(&hashKey);
m_aclCount--;
NS_ASSERTION(m_aclCount >= 0, "acl count can't go negative");
}
m_aclCount++;
rv = (m_rightsHash->Put(&hashKey, rightsWeOwn) == 0);
}
if (ourUserName &&
(!strcmp(ourUserName, myUserName) || !strcmp(ourUserName, IMAP_ACL_ANYONE_STRING)))
{
// if this is setting an ACL for me, cache it in the folder pref flags
UpdateACLCache();
}
return rv;
}
const char *nsMsgIMAPFolderACL::GetRightsStringForUser(const char *inUserName)
{
nsXPIDLCString userName;
userName.Assign(inUserName);
if (!userName.Length())
m_folder->GetUsername(getter_Copies(userName));
nsCStringKey userKey(userName.get());
return (const char *)m_rightsHash->Get(&userKey);
}
// First looks for individual user; then looks for 'anyone' if the user isn't found.
// Returns defaultIfNotFound, if neither are found.
PRBool nsMsgIMAPFolderACL::GetFlagSetInRightsForUser(const char *userName, char flag, PRBool defaultIfNotFound)
{
const char *flags = GetRightsStringForUser(userName);
if (!flags)
{
const char *anyoneFlags = GetRightsStringForUser(IMAP_ACL_ANYONE_STRING);
if (!anyoneFlags)
return defaultIfNotFound;
else
return (strchr(anyoneFlags, flag) != nsnull);
}
else
return (strchr(flags, flag) != nsnull);
}
PRBool nsMsgIMAPFolderACL::GetCanUserLookupFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'l', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserReadFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'r', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserStoreSeenInFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 's', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserWriteFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'w', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserInsertInFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'i', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserPostToFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'p', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserCreateSubfolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'c', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserDeleteInFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'd', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanUserAdministerFolder(const char *userName)
{
return GetFlagSetInRightsForUser(userName, 'a', PR_FALSE);
}
PRBool nsMsgIMAPFolderACL::GetCanILookupFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'l', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIReadFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'r', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIStoreSeenInFolder()
{
return GetFlagSetInRightsForUser(nsnull, 's', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIWriteFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'w', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIInsertInFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'i', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIPostToFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'p', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanICreateSubfolder()
{
return GetFlagSetInRightsForUser(nsnull, 'c', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIDeleteInFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'd', PR_TRUE);
}
PRBool nsMsgIMAPFolderACL::GetCanIAdministerFolder()
{
return GetFlagSetInRightsForUser(nsnull, 'a', PR_TRUE);
}
// We use this to see if the ACLs think a folder is shared or not.
// We will define "Shared" in 5.0 to mean:
// At least one user other than the currently authenticated user has at least one
// explicitly-listed ACL right on that folder.
PRBool nsMsgIMAPFolderACL::GetIsFolderShared()
{
// If we have more than one ACL count for this folder, which means that someone
// other than ourself has rights on it, then it is "shared."
if (m_aclCount > 1)
return PR_TRUE;
// Or, if "anyone" has rights to it, it is shared.
nsCStringKey hashKey(IMAP_ACL_ANYONE_STRING);
const char *anyonesRights = (const char *)m_rightsHash->Get(&hashKey);
return (anyonesRights != nsnull);
}
PRBool nsMsgIMAPFolderACL::GetDoIHaveFullRightsForFolder()
{
return (GetCanIReadFolder() &&
GetCanIWriteFolder() &&
GetCanIInsertInFolder() &&
GetCanIAdministerFolder() &&
GetCanICreateSubfolder() &&
GetCanIDeleteInFolder() &&
GetCanILookupFolder() &&
GetCanIStoreSeenInFolder() &&
GetCanIPostToFolder());
}
// Returns a newly allocated string describing these rights
nsresult nsMsgIMAPFolderACL::CreateACLRightsString(PRUnichar **rightsString)
{
nsAutoString rights;
nsXPIDLString curRight;
nsCOMPtr<nsIStringBundle> bundle;
nsresult rv = IMAPGetStringBundle(getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
if (GetDoIHaveFullRightsForFolder())
{
return bundle->GetStringFromID(IMAP_ACL_FULL_RIGHTS, rightsString);
}
else
{
if (GetCanIReadFolder())
{
bundle->GetStringFromID(IMAP_ACL_READ_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIWriteFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_WRITE_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIInsertInFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_INSERT_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanILookupFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_LOOKUP_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIStoreSeenInFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_SEEN_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIDeleteInFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_DELETE_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanICreateSubfolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_CREATE_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIPostToFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_POST_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
if (GetCanIAdministerFolder())
{
if (rights.Length()) rights += NS_LITERAL_STRING(", ");
bundle->GetStringFromID(IMAP_ACL_ADMINISTER_RIGHT, getter_Copies(curRight));
rights.Append(curRight);
}
}
*rightsString = ToNewUnicode(rights);
return rv;
}
#ifdef WE_HAVE_NS_YET
PRBool MSG_IsFolderACLInitialized(const char *folderName, const char *hostName)
{
MSG_IMAPFolderInfoMail *fi = master->FindImapMailFolder(hostName, folderName, nsnull, PR_FALSE);
if (fi)
return ((fi->GetFolderPrefFlags() & MSG_FOLDER_PREF_IMAP_ACL_RETRIEVED) ||
fi->GetFolderIsNamespace() ||
fi->GetFolderIsNoSelect()); // If a namespace or \Noselect, treat it as if initialized
else
{
NS_ASSERTION(PR_FALSE, "no folder");
return PR_TRUE; // If we can't find the folder, we don't want to get ACLs for it
}
}
#endif
NS_IMETHODIMP nsImapMailFolder::GetPath(nsIFileSpec ** aPathName)
{
nsresult rv;
@ -5456,7 +6100,7 @@ nsImapMailFolder::CopyStreamMessage(nsIMsgDBHdr* message,
nsCOMPtr<nsICopyMessageStreamListener> copyStreamListener;
rv = nsComponentManager::CreateInstance(kCopyMessageStreamListenerCID,
NULL, NS_GET_IID(nsICopyMessageStreamListener),
nsnull, NS_GET_IID(nsICopyMessageStreamListener),
getter_AddRefs(copyStreamListener));
if(NS_FAILED(rv))
return rv;
@ -5616,10 +6260,28 @@ NS_IMETHODIMP nsImapMailFolder::SetFolderNeedsSubscribing(PRBool bVal)
return NS_OK;
}
nsMsgIMAPFolderACL * nsImapMailFolder::GetFolderACL()
{
if (!m_folderACL)
m_folderACL = new nsMsgIMAPFolderACL(this);
return m_folderACL;
}
nsresult nsImapMailFolder::CreateACLRightsStringForFolder(PRUnichar **rightsString)
{
NS_ENSURE_ARG_POINTER(rightsString);
GetFolderACL(); // lazy create
if (m_folderACL)
{
return m_folderACL->CreateACLRightsString(rightsString);
}
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsImapMailFolder::GetFolderNeedsACLListed(PRBool *bVal)
{
if (!bVal)
return NS_ERROR_NULL_POINTER;
NS_ENSURE_ARG_POINTER(bVal);
// *** jt -- come back later; still need to worry about if the folder
// itself is a namespace
*bVal = (m_folderNeedsACLListed && !(mFlags &
@ -5634,6 +6296,125 @@ NS_IMETHODIMP nsImapMailFolder::SetFolderNeedsACLListed(PRBool bVal)
return NS_OK;
}
PRBool nsImapMailFolder::GetFolderIsNamespace()
{
if (!m_namespace)
{
#ifdef DEBUG_bienvenu
// Make sure this isn't causing us to open the database
NS_ASSERTION(m_hierarchyDelimiter != kOnlineHierarchySeparatorUnknown, "hierarchy delimiter not set");
#endif
nsXPIDLCString hostName;
nsXPIDLCString onlineName;
GetHostname(getter_Copies(hostName));
GetOnlineName(getter_Copies(onlineName));
PRUnichar hierarchyDelimiter;
GetHierarchyDelimiter(&hierarchyDelimiter);
nsresult rv;
nsCOMPtr<nsIImapHostSessionList> hostSession =
do_GetService(kCImapHostSessionList, &rv);
if (NS_SUCCEEDED(rv) && hostSession)
{
m_namespace = nsIMAPNamespaceList::GetNamespaceForFolder(hostName.get(), onlineName.get(), (char) hierarchyDelimiter);
if (m_namespace == nsnull)
{
if (mFlags & MSG_FOLDER_FLAG_IMAP_OTHER_USER)
{
rv = hostSession->GetDefaultNamespaceOfTypeForHost(hostName.get(), kOtherUsersNamespace, m_namespace);
}
else if (mFlags & MSG_FOLDER_FLAG_IMAP_PUBLIC)
{
rv = hostSession->GetDefaultNamespaceOfTypeForHost(hostName.get(), kPublicNamespace, m_namespace);
}
else
{
rv = hostSession->GetDefaultNamespaceOfTypeForHost(hostName.get(), kPersonalNamespace, m_namespace);
}
}
NS_ASSERTION(m_namespace, "failed to get namespace");
if (m_namespace)
{
nsIMAPNamespaceList::SuggestHierarchySeparatorForNamespace(m_namespace, (char) hierarchyDelimiter);
m_folderIsNamespace = nsIMAPNamespaceList::GetFolderIsNamespace(hostName.get(), onlineName.get(), (char) hierarchyDelimiter, m_namespace);
}
}
}
return m_folderIsNamespace;
}
NS_IMETHODIMP nsImapMailFolder::SetFolderIsNamespace(PRBool isNamespace)
{
m_folderIsNamespace = isNamespace;
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::ResetNamespaceReferences()
{
nsXPIDLCString serverKey;
nsXPIDLCString onlineName;
GetServerKey(getter_Copies(serverKey));
GetOnlineName(getter_Copies(onlineName));
PRUnichar hierarchyDelimiter;
GetHierarchyDelimiter(&hierarchyDelimiter);
m_namespace = nsIMAPNamespaceList::GetNamespaceForFolder(serverKey.get(), onlineName.get(), (char) hierarchyDelimiter);
NS_ASSERTION(m_namespace, "resetting null namespace");
if (m_namespace)
m_folderIsNamespace = nsIMAPNamespaceList::GetFolderIsNamespace(serverKey.get(), onlineName.get(), (char) hierarchyDelimiter, m_namespace);
else
m_folderIsNamespace = PR_FALSE;
nsCOMPtr<nsIEnumerator> aEnumerator;
GetSubFolders(getter_AddRefs(aEnumerator));
if (!aEnumerator)
return NS_OK;
nsCOMPtr<nsISupports> aSupport;
nsresult rv = aEnumerator->First();
while (NS_SUCCEEDED(rv))
{
rv = aEnumerator->CurrentItem(getter_AddRefs(aSupport));
nsCOMPtr<nsIMsgImapMailFolder> folder = do_QueryInterface(aSupport, &rv);
if (NS_FAILED(rv)) return rv;
folder->ResetNamespaceReferences();
rv = aEnumerator->Next();
}
return rv;
}
NS_IMETHODIMP nsImapMailFolder::FindOnlineSubFolder(const char *targetOnlineName, nsIMsgImapMailFolder **aResultFolder)
{
nsresult rv = NS_OK;
nsXPIDLCString onlineName;
GetOnlineName(getter_Copies(onlineName));
if (onlineName.Equals(targetOnlineName))
{
return QueryInterface(NS_GET_IID(nsIMsgImapMailFolder), (void **) aResultFolder);
}
nsCOMPtr<nsIEnumerator> aEnumerator;
GetSubFolders(getter_AddRefs(aEnumerator));
if (!aEnumerator)
return NS_OK;
nsCOMPtr<nsISupports> aSupport;
rv = aEnumerator->First();
while (NS_SUCCEEDED(rv))
{
rv = aEnumerator->CurrentItem(getter_AddRefs(aSupport));
nsCOMPtr<nsIMsgImapMailFolder> folder = do_QueryInterface(aSupport, &rv);
if (NS_FAILED(rv)) return rv;
rv = folder->FindOnlineSubFolder(targetOnlineName, aResultFolder);
if (*aResultFolder)
return rv;
rv = aEnumerator->Next();
}
return rv;
}
NS_IMETHODIMP nsImapMailFolder::GetFolderNeedsAdded(PRBool *bVal)
{
if (!bVal)

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

@ -60,8 +60,8 @@
#include "nsIImapMailFolderSink.h"
#include "nsIImapServerSink.h"
class nsImapMoveCoalescer;
class nsHashtable;
class nsHashKey;
#define COPY_BUFFER_SIZE 16384
/* b64534f0-3d53-11d3-ac2a-00805f8ac968 */
@ -107,6 +107,86 @@ public:
PRBool m_allowUndo;
};
// ACLs for this folder.
// Generally, we will try to always query this class when performing
// an operation on the folder.
// If the server doesn't support ACLs, none of this data will be filled in.
// Therefore, we can assume that if we look up ourselves and don't find
// any info (and also look up "anyone") then we have full rights, that is, ACLs don't exist.
class nsImapMailFolder;
#define IMAP_ACL_READ_FLAG 0x0000001 /* SELECT, CHECK, FETCH, PARTIAL, SEARCH, COPY from folder */
#define IMAP_ACL_STORE_SEEN_FLAG 0x0000002 /* STORE SEEN flag */
#define IMAP_ACL_WRITE_FLAG 0x0000004 /* STORE flags other than SEEN and DELETED */
#define IMAP_ACL_INSERT_FLAG 0x0000008 /* APPEND, COPY into folder */
#define IMAP_ACL_POST_FLAG 0x0000010 /* Can I send mail to the submission address for folder? */
#define IMAP_ACL_CREATE_SUBFOLDER_FLAG 0x0000020 /* Can I CREATE a subfolder of this folder? */
#define IMAP_ACL_DELETE_FLAG 0x0000040 /* STORE DELETED flag, perform EXPUNGE */
#define IMAP_ACL_ADMINISTER_FLAG 0x0000080 /* perform SETACL */
#define IMAP_ACL_RETRIEVED_FLAG 0x0000100 /* ACL info for this folder has been initialized */
class nsMsgIMAPFolderACL
{
public:
nsMsgIMAPFolderACL(nsImapMailFolder *folder);
~nsMsgIMAPFolderACL();
PRBool SetFolderRightsForUser(const char *userName, const char *rights);
public:
// generic for any user, although we might not use them in
// DO NOT use these for looking up information about the currently authenticated user.
// (There are some different checks and defaults we do).
// Instead, use the functions below, GetICan....()
PRBool GetCanUserLookupFolder(const char *userName); // Is folder visible to LIST/LSUB?
PRBool GetCanUserReadFolder(const char *userName); // SELECT, CHECK, FETCH, PARTIAL, SEARCH, COPY from folder?
PRBool GetCanUserStoreSeenInFolder(const char *userName); // STORE SEEN flag?
PRBool GetCanUserWriteFolder(const char *userName); // STORE flags other than SEEN and DELETED?
PRBool GetCanUserInsertInFolder(const char *userName); // APPEND, COPY into folder?
PRBool GetCanUserPostToFolder(const char *userName); // Can I send mail to the submission address for folder?
PRBool GetCanUserCreateSubfolder(const char *userName); // Can I CREATE a subfolder of this folder?
PRBool GetCanUserDeleteInFolder(const char *userName); // STORE DELETED flag, perform EXPUNGE?
PRBool GetCanUserAdministerFolder(const char *userName); // perform SETACL?
// Functions to find out rights for the currently authenticated user.
PRBool GetCanILookupFolder(); // Is folder visible to LIST/LSUB?
PRBool GetCanIReadFolder(); // SELECT, CHECK, FETCH, PARTIAL, SEARCH, COPY from folder?
PRBool GetCanIStoreSeenInFolder(); // STORE SEEN flag?
PRBool GetCanIWriteFolder(); // STORE flags other than SEEN and DELETED?
PRBool GetCanIInsertInFolder(); // APPEND, COPY into folder?
PRBool GetCanIPostToFolder(); // Can I send mail to the submission address for folder?
PRBool GetCanICreateSubfolder(); // Can I CREATE a subfolder of this folder?
PRBool GetCanIDeleteInFolder(); // STORE DELETED flag, perform EXPUNGE?
PRBool GetCanIAdministerFolder(); // perform SETACL?
PRBool GetDoIHaveFullRightsForFolder(); // Returns TRUE if I have full rights on this folder (all of the above return TRUE)
PRBool GetIsFolderShared(); // We use this to see if the ACLs think a folder is shared or not.
// We will define "Shared" in 5.0 to mean:
// At least one user other than the currently authenticated user has at least one
// explicitly-listed ACL right on that folder.
// Returns a newly allocated string describing these rights
nsresult CreateACLRightsString(PRUnichar **rightsString);
protected:
const char *GetRightsStringForUser(const char *userName);
PRBool GetFlagSetInRightsForUser(const char *userName, char flag, PRBool defaultIfNotFound);
void BuildInitialACLFromCache();
void UpdateACLCache();
static PRBool FreeHashRights(nsHashKey *aKey, void *aData, void *closure);
protected:
nsHashtable *m_rightsHash; // Hash table, mapping username strings to rights strings.
nsImapMailFolder *m_folder;
PRInt32 m_aclCount;
};
class nsImapMailFolder : public nsMsgDBFolder,
public nsIMsgImapMailFolder,
public nsIImapMailFolderSink,
@ -227,8 +307,6 @@ public:
NS_IMETHOD ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,
@ -317,6 +395,17 @@ protected:
nsresult GetDatabase(nsIMsgWindow *aMsgWindow);
virtual const char *GetIncomingServerType() {return "imap";}
nsresult GetFolderOwnerUserName(char **userName);
nsresult GetOwnersOnlineFolderName(char **onlineName);
nsIMAPNamespace *GetNamespaceForFolder();
void SetNamespaceForFolder(nsIMAPNamespace *ns);
PRBool GetFolderIsNamespace();
// ### TODO if this is supposed to be a method of an interface, which interface, and who will call it?
NS_IMETHODIMP SetFolderIsNamespace(PRBool isNamespace);
nsresult GetServerAdminUrl(char **aAdminUrl);
nsMsgIMAPFolderACL * GetFolderACL();
nsresult CreateACLRightsStringForFolder(PRUnichar **rightsString);
nsresult GetBodysToDownload(nsMsgKeyArray *keysOfMessagesToDownload);
// Uber message copy service
@ -371,16 +460,23 @@ protected:
nsCOMPtr<nsMsgTxn> m_pendingUndoTxn;
nsCOMPtr<nsImapMailCopyState> m_copyState;
PRMonitor *m_appendMsgMonitor;
PRBool m_verifiedAsOnlineFolder;
PRBool m_explicitlyVerify; // whether or not we need to explicitly verify this through LIST
PRUnichar m_hierarchyDelimiter;
PRInt32 m_boxFlags;
nsCString m_onlineFolderName;
nsFileSpec *m_pathName;
PRUnichar m_hierarchyDelimiter;
PRInt32 m_boxFlags;
nsCString m_onlineFolderName;
nsFileSpec *m_pathName;
nsCString m_ownerUserName; // username of the "other user," as in
// "Other Users' Mailboxes"
PRBool m_folderNeedsSubscribing;
PRBool m_folderNeedsAdded;
PRBool m_folderNeedsACLListed;
nsIMAPNamespace *m_namespace; // Opaque pointer to the IMAP namespace for this folder
// Use libnet accessors for various namespace functionality
PRPackedBool m_verifiedAsOnlineFolder;
PRPackedBool m_explicitlyVerify; // whether or not we need to explicitly verify this through LIST
PRPackedBool m_folderIsNamespace;
PRPackedBool m_folderNeedsSubscribing;
PRPackedBool m_folderNeedsAdded;
PRPackedBool m_folderNeedsACLListed;
nsMsgIMAPFolderACL *m_folderACL;
nsCOMPtr<nsIMsgMailNewsUrl> mUrlToRelease;
@ -389,4 +485,6 @@ protected:
PRBool m_downloadingFolderForOfflineUse;
};
#endif

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

@ -3682,10 +3682,9 @@ void nsImapProtocol::AddFolderRightsForUser(const char *mailboxName, const char
aclRightsInfo->mailboxName && aclRightsInfo->rights &&
userName ? (aclRightsInfo->userName != NULL) : PR_TRUE)
{
if (m_imapExtensionSink)
if (m_imapServerSink)
{
m_imapExtensionSink->AddFolderRights(this, aclRightsInfo);
WaitForFEEventCompletion();
m_imapServerSink->AddFolderRights(mailboxName, userName, rights);
}
}
PR_FREEIF(aclRightsInfo->hostName);
@ -3871,64 +3870,64 @@ nsImapProtocol::DiscoverMailboxSpec(nsImapMailboxSpec * adoptedBoxSpec)
{
// IMAP_LoadTrashFolderName(); **** needs to work on localization issues
nsIMAPNamespace *ns = nsnull;
NS_ASSERTION (m_hostSessionList, "fatal null host session list");
if (!m_hostSessionList) return;
m_hostSessionList->GetDefaultNamespaceOfTypeForHost(
GetImapServerKey(), kPersonalNamespace, ns);
NS_ASSERTION (m_hostSessionList, "fatal null host session list");
if (!m_hostSessionList) return;
m_hostSessionList->GetDefaultNamespaceOfTypeForHost(
GetImapServerKey(), kPersonalNamespace, ns);
const char *nsPrefix = ns ? ns->GetPrefix() : 0;
nsCString canonicalSubDir;
if (nsPrefix)
{
PRUnichar slash = '/';
PRUnichar slash = '/';
canonicalSubDir = nsPrefix;
if (canonicalSubDir.Length() && canonicalSubDir.Last() == slash)
canonicalSubDir.SetLength((PRUint32) canonicalSubDir.Length()-1);
canonicalSubDir.SetLength((PRUint32) canonicalSubDir.Length()-1);
}
switch (m_hierarchyNameState)
{
case kListingForCreate:
case kNoOperationInProgress:
case kDiscoverTrashFolderInProgress:
case kListingForInfoAndDiscovery:
case kListingForCreate:
case kNoOperationInProgress:
case kDiscoverTrashFolderInProgress:
case kListingForInfoAndDiscovery:
{
if (canonicalSubDir.Length() &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
canonicalSubDir.get()))
m_onlineBaseFolderExists = PR_TRUE;
if (ns && nsPrefix) // if no personal namespace, there can be no Trash folder
if (canonicalSubDir.Length() &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
canonicalSubDir.get()))
m_onlineBaseFolderExists = PR_TRUE;
if (ns && nsPrefix) // if no personal namespace, there can be no Trash folder
{
PRBool onlineTrashFolderExists = PR_FALSE;
if (m_hostSessionList)
m_hostSessionList->GetOnlineTrashFolderExistsForHost(
GetImapServerKey(), onlineTrashFolderExists);
PRBool onlineTrashFolderExists = PR_FALSE;
if (m_hostSessionList)
m_hostSessionList->GetOnlineTrashFolderExistsForHost(
GetImapServerKey(), onlineTrashFolderExists);
if (GetDeleteIsMoveToTrash() && // don't set the Trash flag
// if not using the Trash model
!onlineTrashFolderExists &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
kImapTrashFolderName))
// if not using the Trash model
!onlineTrashFolderExists &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
kImapTrashFolderName))
{
PRBool trashExists = PR_FALSE;
nsCString trashMatch;
trashMatch = nsPrefix;
trashMatch += kImapTrashFolderName;
nsCString trashMatch;
trashMatch = nsPrefix;
trashMatch += kImapTrashFolderName;
{
char *serverTrashName = nsnull;
m_runningUrl->AllocateCanonicalPath(
trashMatch.get(),
ns->GetDelimiter(), &serverTrashName);
m_runningUrl->AllocateCanonicalPath(
trashMatch.get(),
ns->GetDelimiter(), &serverTrashName);
if (serverTrashName)
{
if (!PL_strcasecmp(nsPrefix, "INBOX.")) // need to special-case this because it should be case-insensitive
{
#ifdef DEBUG
NS_ASSERTION (PL_strlen(serverTrashName) > 6,
"Oops.. less that 6");
"Oops.. less that 6");
#endif
trashExists = ((PL_strlen(serverTrashName) > 6 /* nsCRT::strlen("INBOX.") */) &&
(PL_strlen(adoptedBoxSpec->allocatedPathName) > 6 /* nsCRT::strlen("INBOX.") */) &&
@ -3939,70 +3938,75 @@ nsImapProtocol::DiscoverMailboxSpec(nsImapMailboxSpec * adoptedBoxSpec)
{
trashExists = (PL_strcmp(serverTrashName, adoptedBoxSpec->allocatedPathName) == 0);
}
if (m_hostSessionList)
m_hostSessionList->
SetOnlineTrashFolderExistsForHost(
GetImapServerKey(), trashExists);
if (m_hostSessionList)
m_hostSessionList->
SetOnlineTrashFolderExistsForHost(
GetImapServerKey(), trashExists);
PR_Free(serverTrashName);
}
}
if (trashExists)
adoptedBoxSpec->box_flags |= kImapTrash;
adoptedBoxSpec->box_flags |= kImapTrash;
}
}
// Discover the folder (shuttle over to libmsg, yay)
// Do this only if the folder name is not empty (i.e. the root)
if (adoptedBoxSpec->allocatedPathName &&
*adoptedBoxSpec->allocatedPathName)
*adoptedBoxSpec->allocatedPathName)
{
nsCString boxNameCopy;
nsCString boxNameCopy;
boxNameCopy = adoptedBoxSpec->allocatedPathName;
if (m_hierarchyNameState == kListingForCreate)
adoptedBoxSpec->box_flags |= kNewlyCreatedFolder;
if (m_imapServerSink)
{
m_imapServerSink->PossibleImapMailbox(boxNameCopy.get(),
adoptedBoxSpec->hierarchySeparator,
adoptedBoxSpec->box_flags);
PRBool useSubscription = PR_FALSE;
if (m_hostSessionList)
m_hostSessionList->GetHostIsUsingSubscription(
GetImapServerKey(),
useSubscription);
if (m_imapServerSink)
{
PRBool newFolder;
m_imapServerSink->PossibleImapMailbox(boxNameCopy.get(),
adoptedBoxSpec->hierarchySeparator,
adoptedBoxSpec->box_flags, &newFolder);
// if it's a new folder to the server sink, setting discovery status to
// eContinueNew will cause us to get the ACL for the new folder.
if (newFolder)
SetMailboxDiscoveryStatus(eContinueNew);
PRBool useSubscription = PR_FALSE;
if (m_hostSessionList)
m_hostSessionList->GetHostIsUsingSubscription(
GetImapServerKey(),
useSubscription);
if ((GetMailboxDiscoveryStatus() != eContinue) &&
(GetMailboxDiscoveryStatus() != eContinueNew) &&
(GetMailboxDiscoveryStatus() != eListMyChildren))
{
SetConnectionStatus(-1);
SetConnectionStatus(-1);
}
else if (boxNameCopy.Length() &&
(GetMailboxDiscoveryStatus() ==
eListMyChildren) &&
(!useSubscription || GetSubscribingNow()))
(GetMailboxDiscoveryStatus() ==
eListMyChildren) &&
(!useSubscription || GetSubscribingNow()))
{
NS_ASSERTION (PR_FALSE,
"we should never get here anymore");
SetMailboxDiscoveryStatus(eContinue);
"we should never get here anymore");
SetMailboxDiscoveryStatus(eContinue);
}
else if (GetMailboxDiscoveryStatus() == eContinueNew)
{
if (m_hierarchyNameState ==
kListingForInfoAndDiscovery &&
boxNameCopy.Length() &&
!(adoptedBoxSpec->box_flags & kNameSpace))
kListingForInfoAndDiscovery &&
boxNameCopy.Length() &&
!(adoptedBoxSpec->box_flags & kNameSpace))
{
// remember the info here also
nsIMAPMailboxInfo *mb = new
nsIMAPMailboxInfo(boxNameCopy.get(),
adoptedBoxSpec->hierarchySeparator);
m_listedMailboxList.AppendElement((void*) mb);
nsIMAPMailboxInfo(boxNameCopy.get(),
adoptedBoxSpec->hierarchySeparator);
m_listedMailboxList.AppendElement((void*) mb);
}
SetMailboxDiscoveryStatus(eContinue);
}
@ -4012,45 +4016,45 @@ nsImapProtocol::DiscoverMailboxSpec(nsImapMailboxSpec * adoptedBoxSpec)
NS_IF_RELEASE( adoptedBoxSpec);
break;
case kDiscoverBaseFolderInProgress:
{
if (canonicalSubDir.Length() &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
canonicalSubDir.get()))
m_onlineBaseFolderExists = PR_TRUE;
}
break;
{
if (canonicalSubDir.Length() &&
PL_strstr(adoptedBoxSpec->allocatedPathName,
canonicalSubDir.get()))
m_onlineBaseFolderExists = PR_TRUE;
}
break;
case kDeleteSubFoldersInProgress:
{
NS_ASSERTION(m_deletableChildren,
"Oops .. null m_deletableChildren\n");
m_deletableChildren->AppendElement((void*)
nsCRT::strdup(adoptedBoxSpec->allocatedPathName));
PR_FREEIF(adoptedBoxSpec->hostName);
NS_IF_RELEASE( adoptedBoxSpec);
}
break;
case kListingForInfoOnly:
{
//UpdateProgressWindowForUpgrade(adoptedBoxSpec->allocatedPathName);
ProgressEventFunctionUsingIdWithString(IMAP_DISCOVERING_MAILBOX,
adoptedBoxSpec->allocatedPathName);
nsIMAPMailboxInfo *mb = new
nsIMAPMailboxInfo(adoptedBoxSpec->allocatedPathName,
adoptedBoxSpec->hierarchySeparator);
m_listedMailboxList.AppendElement((void*) mb);
PR_FREEIF(adoptedBoxSpec->allocatedPathName);
NS_IF_RELEASE(adoptedBoxSpec);
}
break;
case kDiscoveringNamespacesOnly:
{
PR_FREEIF(adoptedBoxSpec->allocatedPathName);
NS_IF_RELEASE(adoptedBoxSpec);
}
break;
{
NS_ASSERTION(m_deletableChildren,
"Oops .. null m_deletableChildren\n");
m_deletableChildren->AppendElement((void*)
nsCRT::strdup(adoptedBoxSpec->allocatedPathName));
PR_FREEIF(adoptedBoxSpec->hostName);
NS_IF_RELEASE( adoptedBoxSpec);
}
break;
case kListingForInfoOnly:
{
//UpdateProgressWindowForUpgrade(adoptedBoxSpec->allocatedPathName);
ProgressEventFunctionUsingIdWithString(IMAP_DISCOVERING_MAILBOX,
adoptedBoxSpec->allocatedPathName);
nsIMAPMailboxInfo *mb = new
nsIMAPMailboxInfo(adoptedBoxSpec->allocatedPathName,
adoptedBoxSpec->hierarchySeparator);
m_listedMailboxList.AppendElement((void*) mb);
PR_FREEIF(adoptedBoxSpec->allocatedPathName);
NS_IF_RELEASE(adoptedBoxSpec);
}
break;
case kDiscoveringNamespacesOnly:
{
PR_FREEIF(adoptedBoxSpec->allocatedPathName);
NS_IF_RELEASE(adoptedBoxSpec);
}
break;
default:
NS_ASSERTION (PR_FALSE, "we aren't supposed to be here");
break;
NS_ASSERTION (PR_FALSE, "we aren't supposed to be here");
break;
}
}
@ -4974,27 +4978,72 @@ void nsImapProtocol::RefreshACLForFolderIfNecessary(const char *mailboxName)
m_imapMailFolderSink->GetFolderNeedsACLListed(&m_folderNeedsACLRefreshed);
if (m_folderNeedsACLRefreshed)
{
OnRefreshACLForFolder(mailboxName);
RefreshACLForFolder(mailboxName);
m_folderNeedsACLRefreshed = PR_FALSE;
}
}
}
void nsImapProtocol::OnRefreshACLForFolder(const char *mailboxName)
void nsImapProtocol::RefreshACLForFolder(const char *mailboxName)
{
IncrementCommandTagNumber();
nsIMAPNamespace *ns = nsnull;
m_hostSessionList->GetNamespaceForMailboxForHost(GetImapServerKey(), mailboxName, ns);
if (ns)
{
switch (ns->GetType())
{
case kPersonalNamespace:
// It's a personal folder, most likely.
// I find it hard to imagine a server that supports ACL that doesn't support NAMESPACE,
// so most likely we KNOW that this is a personal, rather than the default, namespace.
// First, clear what we have.
ClearAllFolderRights(mailboxName, ns);
// Now, get the new one.
GetACLForFolder(mailboxName);
// We're all done, refresh the icon/flags for this folder
#ifdef REFRESHING_VIEW
RefreshFolderACLView(mailboxName, ns);
#endif
break;
default:
// We know it's a public folder or other user's folder.
// We only want our own rights
// First, clear what we have
ClearAllFolderRights(mailboxName, ns);
// Now, get the new one.
GetMyRightsForFolder(mailboxName);
// We're all done, refresh the icon/flags for this folder
#ifdef REFRESHING_VIEW
RefreshFolderACLView(mailboxName, ns);
#endif
break;
}
}
else
{
// no namespace, not even default... can this happen?
NS_ASSERTION(PR_FALSE, "couldn't get namespace");
}
}
void nsImapProtocol::GetACLForFolder(const char *mailboxName)
{
IncrementCommandTagNumber();
nsCString command(GetServerCommandTag());
char *escapedName = CreateEscapedMailboxName(mailboxName);
command.Append(" getacl \"");
char *escapedName = CreateEscapedMailboxName(mailboxName);
command.Append(" getacl \"");
command.Append(escapedName);
command.Append("\"" CRLF);
nsMemory::Free(escapedName);
nsMemory::Free(escapedName);
nsresult rv = SendData(command.get());
if (NS_SUCCEEDED(rv))
ParseIMAPandCheckForNewMail();
nsresult rv = SendData(command.get());
if (NS_SUCCEEDED(rv))
ParseIMAPandCheckForNewMail();
}
void nsImapProtocol::OnRefreshAllACLs()
@ -5017,7 +5066,7 @@ void nsImapProtocol::OnRefreshAllACLs()
mb->GetDelimiter(), &onlineName);
if (onlineName)
{
OnRefreshACLForFolder(onlineName);
RefreshACLForFolder(onlineName);
nsCRT::free(onlineName);
}
PercentProgressUpdateEvent(NULL, count, total);
@ -5150,20 +5199,20 @@ void nsImapProtocol::MailboxData()
void nsImapProtocol::GetMyRightsForFolder(const char *mailboxName)
{
IncrementCommandTagNumber();
IncrementCommandTagNumber();
nsCString command(GetServerCommandTag());
char *escapedName = CreateEscapedMailboxName(mailboxName);
char *escapedName = CreateEscapedMailboxName(mailboxName);
command.Append(" myrights \"");
command.Append(escapedName);
command.Append("\"" CRLF);
nsMemory::Free(escapedName);
nsMemory::Free(escapedName);
nsresult rv = SendData(command.get());
if (NS_SUCCEEDED(rv))
ParseIMAPandCheckForNewMail();
nsresult rv = SendData(command.get());
if (NS_SUCCEEDED(rv))
ParseIMAPandCheckForNewMail();
}
void nsImapProtocol::OnStatusForFolder(const char *mailboxName)
@ -5859,7 +5908,7 @@ void nsImapProtocol::DiscoverMailboxList()
m_runningUrl->AllocateServerPath(mb->GetMailboxName(), mb->GetDelimiter(), &onlineName);
if (onlineName)
{
OnRefreshACLForFolder(onlineName);
RefreshACLForFolder(onlineName);
PR_Free(onlineName);
}
}
@ -5879,8 +5928,7 @@ PRBool nsImapProtocol::FolderNeedsACLInitialized(const char *folderName)
char *name = PL_strdup(folderName);
if (!name)
return PR_FALSE;
// mscott - big hack...where do we get a IMAPACLRights object from??????
// m_imapServerSink->FolderNeedsACLInitialized(name, nsnull);
m_imapServerSink->FolderNeedsACLInitialized(name, &rv);
PR_Free(name);
return rv;
@ -6341,7 +6389,7 @@ void nsImapProtocol::ProcessAuthenticatedStateURL()
break;
case nsIImapUrl::nsImapRefreshACL:
sourceMailbox = OnCreateServerSourceFolderPathString();
OnRefreshACLForFolder(sourceMailbox);
RefreshACLForFolder(sourceMailbox);
break;
case nsIImapUrl::nsImapRefreshAllACLs:
OnRefreshAllACLs();

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

@ -483,7 +483,8 @@ private:
void OnSubscribe(const char * aSourceMailbox);
void OnUnsubscribe(const char * aSourceMailbox);
void RefreshACLForFolderIfNecessary(const char * mailboxName);
void OnRefreshACLForFolder(const char * aSourceMailbox);
void RefreshACLForFolder(const char * aSourceMailbox);
void GetACLForFolder(const char *aMailboxName);
void OnRefreshAllACLs();
void OnListFolder(const char * aSourceMailbox, PRBool aBool);
void OnStatusForFolder(const char * sourceMailbox);

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

@ -169,36 +169,6 @@ nsImapExtensionSinkProxy::ClearFolderRights(nsIImapProtocol* aProtocol,
return res;
}
NS_IMETHODIMP
nsImapExtensionSinkProxy::AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
{
nsresult res = NS_OK;
NS_PRECONDITION (aclRights, "Oops... null aclRights");
if(!aclRights)
return NS_ERROR_NULL_POINTER;
NS_ASSERTION (m_protocol == aProtocol, "Ooh ooh, wrong protocol");
if (PR_GetCurrentThread() == m_thread)
{
AddFolderRightsProxyEvent *ev =
new AddFolderRightsProxyEvent(this, aclRights);
if(nsnull == ev)
res = NS_ERROR_OUT_OF_MEMORY;
else
{
ev->SetNotifyCompletion(PR_TRUE);
ev->PostEvent(m_eventQueue);
}
}
else
{
res = m_realImapExtensionSink->AddFolderRights(aProtocol, aclRights);
aProtocol->NotifyFEEventCompletion();
}
return res;
}
NS_IMETHODIMP
nsImapExtensionSinkProxy::RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights)
@ -693,49 +663,6 @@ ClearFolderRightsProxyEvent::HandleEvent()
return res;
}
AddFolderRightsProxyEvent::AddFolderRightsProxyEvent(
nsImapExtensionSinkProxy* aProxy, nsIMAPACLRightsInfo* aclRights) :
nsImapExtensionSinkProxyEvent(aProxy)
{
NS_ASSERTION (aclRights, "Oops... a null acl rights info");
if (aclRights)
{
m_aclRightsInfo.hostName = PL_strdup(aclRights->hostName);
m_aclRightsInfo.mailboxName = PL_strdup(aclRights->mailboxName);
m_aclRightsInfo.userName = PL_strdup(aclRights->userName);
m_aclRightsInfo.rights = PL_strdup(aclRights->rights);
}
else
{
m_aclRightsInfo.hostName = nsnull;
m_aclRightsInfo.mailboxName = nsnull;
m_aclRightsInfo.userName = nsnull;
m_aclRightsInfo.rights = nsnull;
}
}
AddFolderRightsProxyEvent::~AddFolderRightsProxyEvent()
{
if (m_aclRightsInfo.hostName)
PL_strfree(m_aclRightsInfo.hostName);
if (m_aclRightsInfo.mailboxName)
PL_strfree(m_aclRightsInfo.mailboxName);
if (m_aclRightsInfo.userName)
PL_strfree(m_aclRightsInfo.userName);
if (m_aclRightsInfo.rights)
PL_strfree(m_aclRightsInfo.rights);
}
NS_IMETHODIMP
AddFolderRightsProxyEvent::HandleEvent()
{
nsresult res = m_proxy->m_realImapExtensionSink->AddFolderRights(
m_proxy->m_protocol, &m_aclRightsInfo);
if (m_notifyCompletion)
m_proxy->m_protocol->NotifyFEEventCompletion();
return res;
}
RefreshFolderRightsProxyEvent::RefreshFolderRightsProxyEvent(
nsImapExtensionSinkProxy* aProxy, nsIMAPACLRightsInfo* aclRights) :
nsImapExtensionSinkProxyEvent(aProxy)

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

@ -81,8 +81,6 @@ public:
NS_IMETHOD ClearFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD AddFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD RefreshFolderRights(nsIImapProtocol* aProtocol,
nsIMAPACLRightsInfo* aclRights);
NS_IMETHOD FolderNeedsACLInitialized(nsIImapProtocol* aProtocol,
@ -169,15 +167,6 @@ struct ClearFolderRightsProxyEvent : nsImapExtensionSinkProxyEvent
nsIMAPACLRightsInfo m_aclRightsInfo;
};
struct AddFolderRightsProxyEvent : nsImapExtensionSinkProxyEvent
{
AddFolderRightsProxyEvent(nsImapExtensionSinkProxy* aProxy,
nsIMAPACLRightsInfo* aclRights);
virtual ~AddFolderRightsProxyEvent();
NS_IMETHOD HandleEvent();
nsIMAPACLRightsInfo m_aclRightsInfo;
};
struct RefreshFolderRightsProxyEvent : nsImapExtensionSinkProxyEvent
{
RefreshFolderRightsProxyEvent(nsImapExtensionSinkProxy* aProxy,

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

@ -2223,43 +2223,43 @@ void nsImapServerResponseParser::myrights_data()
void nsImapServerResponseParser::acl_data()
{
fNextToken = GetNextToken();
if (ContinueParse() && !at_end_of_line())
{
char *mailboxName = CreateAstring(); // PL_strdup(fNextToken);
if (mailboxName && ContinueParse())
{
fNextToken = GetNextToken();
while (ContinueParse() && !at_end_of_line())
{
char *userName = CreateAstring(); // PL_strdup(fNextToken);
if (userName && ContinueParse())
{
fNextToken = GetNextToken();
if (ContinueParse())
{
char *rights = CreateAstring(); // PL_strdup(fNextToken);
if (rights)
{
fServerConnection.AddFolderRightsForUser(mailboxName, userName, rights);
PR_Free(rights);
}
else
HandleMemoryFailure();
if (ContinueParse())
fNextToken = GetNextToken();
}
PR_Free(userName);
}
else
HandleMemoryFailure();
}
PR_Free(mailboxName);
}
else
HandleMemoryFailure();
}
fNextToken = GetNextToken();
if (ContinueParse() && !at_end_of_line())
{
char *mailboxName = CreateAstring(); // PL_strdup(fNextToken);
if (mailboxName && ContinueParse())
{
fNextToken = GetNextToken();
while (ContinueParse() && !at_end_of_line())
{
char *userName = CreateAstring(); // PL_strdup(fNextToken);
if (userName && ContinueParse())
{
fNextToken = GetNextToken();
if (ContinueParse())
{
char *rights = CreateAstring(); // PL_strdup(fNextToken);
if (rights)
{
fServerConnection.AddFolderRightsForUser(mailboxName, userName, rights);
PR_Free(rights);
}
else
HandleMemoryFailure();
if (ContinueParse())
fNextToken = GetNextToken();
}
PR_Free(userName);
}
else
HandleMemoryFailure();
}
PR_Free(mailboxName);
}
else
HandleMemoryFailure();
}
}

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

@ -373,62 +373,62 @@ nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue,
nsIMsgWindow *aMsgWindow,
nsIURI ** aURL)
{
// create a protocol instance to handle the request.
// NOTE: once we start working with multiple connections, this step will be much more complicated...but for now
// just create a connection and process the request.
// create a protocol instance to handle the request.
// NOTE: once we start working with multiple connections, this step will be much more complicated...but for now
// just create a connection and process the request.
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
"Oops ... null pointer");
"Oops ... null pointer");
if (!aImapMailFolder || !aClientEventQueue)
return NS_ERROR_NULL_POINTER;
return NS_ERROR_NULL_POINTER;
if (WeAreOffline())
return NS_MSG_ERROR_OFFLINE;
PRBool noSelect = PR_FALSE;
aImapMailFolder->GetFlag(MSG_FOLDER_FLAG_IMAP_NOSELECT, &noSelect);
if (noSelect) return NS_OK;
nsCOMPtr<nsIImapUrl> imapUrl;
nsCAutoString urlSpec;
nsresult rv;
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aImapMailFolder, aUrlListener, urlSpec, hierarchySeparator);
if (NS_SUCCEEDED(rv) && imapUrl)
{
// nsImapUrl::SetSpec() will set the imap action properly
// rv = imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
PRBool canOpenThisFolder = PR_TRUE;
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(aImapMailFolder);
if (imapFolder)
imapFolder->GetCanIOpenThisFolder(&canOpenThisFolder);
if (!canOpenThisFolder) return NS_OK;
nsCOMPtr<nsIImapUrl> imapUrl;
nsCAutoString urlSpec;
nsresult rv;
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aImapMailFolder, aUrlListener, urlSpec, hierarchySeparator);
if (NS_SUCCEEDED(rv) && imapUrl)
{
// nsImapUrl::SetSpec() will set the imap action properly
// rv = imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
// if no msg window, we won't put up error messages (this is almost certainly a biff-inspired get new msgs)
if (!aMsgWindow)
mailNewsUrl->SetSuppressErrorMsgs(PR_TRUE);
mailNewsUrl->SetMsgWindow(aMsgWindow);
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
imapUrl->AddChannelToLoadGroup();
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
if (NS_SUCCEEDED(rv))
{
mailNewsUrl->SetMsgWindow(aMsgWindow);
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
imapUrl->AddChannelToLoadGroup();
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
if (NS_SUCCEEDED(rv))
{
nsXPIDLCString folderName;
GetFolderName(aImapMailFolder, getter_Copies(folderName));
urlSpec.Append("/select>");
urlSpec.AppendWithConversion(hierarchySeparator);
urlSpec.Append("/select>");
urlSpec.AppendWithConversion(hierarchySeparator);
urlSpec.Append((const char *) folderName);
rv = mailNewsUrl->SetSpec(urlSpec.get());
if (NS_SUCCEEDED(rv))
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
imapUrl,
nsnull,
aURL);
}
} // if we have a url to run....
return rv;
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
imapUrl,
nsnull,
aURL);
}
} // if we have a url to run....
return rv;
}
// lite select, used to verify UIDVALIDITY while going on/offline

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

@ -83,6 +83,7 @@ public:
static nsresult ConvertToCanonicalFormat(const char *folderName, char onlineDelimiter, char **resultingCanonicalPath);
static nsresult EscapeSlashes(const char *sourcePath, char **resultPath);
static nsresult UnescapeSlashes(char *path);
static char * ReplaceCharsInCopiedString(const char *stringToCopy, char oldChar, char newChar);
protected:
virtual nsresult ParseUrl();
@ -93,7 +94,6 @@ protected:
// handle the imap specific parsing
void ParseImapPart(char *imapPartOfUrl);
static char * ReplaceCharsInCopiedString(const char *stringToCopy, char oldChar, char newChar);
void ParseFolderPath(char **resultingCanonicalPath);
void ParseSearchCriteriaString();
void ParseChildDiscoveryDepth();