зеркало из https://github.com/mozilla/gecko-dev.git
fix msf file names for imap folders with illegal characters, r=mscott 20324
This commit is contained in:
Родитель
89a342ce1e
Коммит
b4e61f2f13
|
@ -275,7 +275,7 @@ interface nsIMsgFolder : nsIFolder {
|
||||||
/**
|
/**
|
||||||
* local path of this folder
|
* local path of this folder
|
||||||
*/
|
*/
|
||||||
readonly attribute nsIFileSpec path;
|
attribute nsIFileSpec path;
|
||||||
|
|
||||||
void markMessagesRead(in nsISupportsArray messages, in boolean markRead);
|
void markMessagesRead(in nsISupportsArray messages, in boolean markRead);
|
||||||
void markAllMessagesRead();
|
void markAllMessagesRead();
|
||||||
|
|
|
@ -30,6 +30,18 @@
|
||||||
#include "nsMsgBaseCID.h"
|
#include "nsMsgBaseCID.h"
|
||||||
#include "nsIMsgMailNewsUrl.h"
|
#include "nsIMsgMailNewsUrl.h"
|
||||||
#include "nsIMsgAccountManager.h"
|
#include "nsIMsgAccountManager.h"
|
||||||
|
#include "nsXPIDLString.h"
|
||||||
|
|
||||||
|
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||||
|
#define MAX_FILE_LENGTH_WITHOUT_EXTENSION 8
|
||||||
|
#elif defined(XP_MAC)
|
||||||
|
#define MAX_FILE_LENGTH_WITHOUT_EXTENSION 26
|
||||||
|
#elif defined(XP_WIN32)
|
||||||
|
#define MAX_FILE_LENGTH_WITHOUT_EXTENSION 256
|
||||||
|
#else
|
||||||
|
#define MAX_FILE_LENGTH_WITHOUT_EXTENSION 32000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||||
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
||||||
|
@ -320,6 +332,111 @@ nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFla
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// path coming in is the root path without the leaf name,
|
||||||
|
// on the way out, it's the whole path.
|
||||||
|
nsresult nsMsgDBFolder::CreatePlatformLeafNameForDisk(const char *userLeafName, nsFileSpec &path, char **resultName)
|
||||||
|
{
|
||||||
|
const int charLimit = MAX_FILE_LENGTH_WITHOUT_EXTENSION; // set on platform specific basis
|
||||||
|
#if XP_MAC
|
||||||
|
nsCAutoString illegalChars = ":";
|
||||||
|
#elif defined(XP_WIN16) || defined(XP_OS2)
|
||||||
|
nsCAutoString illegalChars = "\"/\\[]:;=,|?<>*$. ";
|
||||||
|
#elif defined(XP_WIN32)
|
||||||
|
nsCAutoString illegalChars = "\"/\\[]:;=,|?<>*$";
|
||||||
|
#else // UNIX
|
||||||
|
nsCAutoString illegalChars = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!resultName || !userLeafName)
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
*resultName = nsnull;
|
||||||
|
|
||||||
|
// mangledLeaf is the new leaf name.
|
||||||
|
// If userLeafName (a) contains all legal characters
|
||||||
|
// (b) is within the valid length for the given platform
|
||||||
|
// (c) does not already exist on the disk
|
||||||
|
// then we simply return nsCRT::strdup(userLeafName)
|
||||||
|
// Otherwise we mangle it
|
||||||
|
|
||||||
|
// leafLength is the length of mangledLeaf which we will return
|
||||||
|
// if userLeafName is greater than the maximum allowed for this
|
||||||
|
// platform, then we truncate and mangle it. Otherwise leave it alone.
|
||||||
|
PRInt32 leafLength;
|
||||||
|
|
||||||
|
// mangledPath is the entire path to the newly mangled leaf name
|
||||||
|
nsCAutoString mangledLeaf = userLeafName;
|
||||||
|
|
||||||
|
PRInt32 illegalCharacterIndex = mangledLeaf.FindCharInSet(illegalChars);
|
||||||
|
|
||||||
|
PRBool exists;
|
||||||
|
|
||||||
|
if (illegalCharacterIndex == kNotFound)
|
||||||
|
{
|
||||||
|
path += (const char *) mangledLeaf;
|
||||||
|
if (!path.Exists())
|
||||||
|
{
|
||||||
|
// if there are no illegal characters
|
||||||
|
// and the file doesn't already exist, then don't do anything to the string
|
||||||
|
// Note that this might be truncated to charLength, but if so, the file still
|
||||||
|
// does not exist, so we are OK.
|
||||||
|
*resultName = mangledLeaf.ToNewCString();
|
||||||
|
return (*resultName) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
// First, replace all illegal characters with '_'
|
||||||
|
mangledLeaf.ReplaceChar(illegalChars, '_');
|
||||||
|
|
||||||
|
path += (const char *) mangledLeaf;
|
||||||
|
}
|
||||||
|
// if we are here, then any of the following may apply:
|
||||||
|
// (a) there were illegal characters
|
||||||
|
// (b) the file already existed
|
||||||
|
|
||||||
|
// Now, we have to loop until we find a filename that doesn't already
|
||||||
|
// exist on the disk
|
||||||
|
PRBool nameSpaceExhausted = FALSE;
|
||||||
|
nsXPIDLCString leafName;
|
||||||
|
|
||||||
|
path.SetLeafName(mangledLeaf.GetBuffer());
|
||||||
|
exists = path.Exists();
|
||||||
|
leafLength = mangledLeaf.Length();
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
if (leafLength >= 2)
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 2, 'A');
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 1, 'A'); // leafLength must be at least 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nameSpaceExhausted && path.Exists())
|
||||||
|
{
|
||||||
|
if (leafLength >= 2)
|
||||||
|
{
|
||||||
|
PRUnichar lastChar = mangledLeaf.CharAt(leafLength - 1);
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 1, ++lastChar);
|
||||||
|
if (lastChar > 'Z')
|
||||||
|
{
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 1,'A');
|
||||||
|
PRUnichar nextToLastChar = mangledLeaf.CharAt(leafLength - 2);
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 2, nextToLastChar + 1);
|
||||||
|
nameSpaceExhausted = (nextToLastChar == 'Z');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PRUnichar lastChar = mangledLeaf.CharAt(leafLength - 1);
|
||||||
|
mangledLeaf.SetCharAt(leafLength - 1, ++lastChar);
|
||||||
|
nameSpaceExhausted = (lastChar == 'Z');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*resultName = mangledLeaf.ToNewCString();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
||||||
{
|
{
|
||||||
|
@ -607,3 +724,4 @@ nsMsgDBFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ protected:
|
||||||
nsresult ReadFromFolderCache(nsIMsgFolderCacheElement *element);
|
nsresult ReadFromFolderCache(nsIMsgFolderCacheElement *element);
|
||||||
nsresult OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
nsresult OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
||||||
nsIDBChangeListener * aInstigator, PRBool added, PRBool doFlat, PRBool doThread);
|
nsIDBChangeListener * aInstigator, PRBool added, PRBool doFlat, PRBool doThread);
|
||||||
|
nsresult CreatePlatformLeafNameForDisk(const char *userLeafName, nsFileSpec &baseDir, char **resultName);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
||||||
|
|
|
@ -1733,8 +1733,13 @@ nsMsgFolder::GetPath(nsIFileSpec * *aPath)
|
||||||
|
|
||||||
nsCOMPtr<nsIFileSpec> path;
|
nsCOMPtr<nsIFileSpec> path;
|
||||||
rv = server->GetLocalPath(getter_AddRefs(path));
|
rv = server->GetLocalPath(getter_AddRefs(path));
|
||||||
if (NS_FAILED(rv)) return rv;
|
return rv;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsMsgFolder::SetPath(nsIFileSpec * /* aPath */)
|
||||||
|
{
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ public:
|
||||||
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
|
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
|
||||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase * *aMsgDatabase);
|
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase * *aMsgDatabase);
|
||||||
NS_IMETHOD GetPath(nsIFileSpec * *aPath);
|
NS_IMETHOD GetPath(nsIFileSpec * *aPath);
|
||||||
|
NS_IMETHOD SetPath(nsIFileSpec * aPath);
|
||||||
NS_IMETHOD MarkMessagesRead(nsISupportsArray *messages, PRBool markRead);
|
NS_IMETHOD MarkMessagesRead(nsISupportsArray *messages, PRBool markRead);
|
||||||
NS_IMETHOD MarkAllMessagesRead(void);
|
NS_IMETHOD MarkAllMessagesRead(void);
|
||||||
NS_IMETHOD MarkMessagesFlagged(nsISupportsArray *messages, PRBool markFlagged);
|
NS_IMETHOD MarkMessagesFlagged(nsISupportsArray *messages, PRBool markFlagged);
|
||||||
|
|
|
@ -289,7 +289,7 @@ static PRUint32 StringHash(const char *ubuf)
|
||||||
|
|
||||||
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
|
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
|
||||||
{
|
{
|
||||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
#if defined(XP_OS2)
|
||||||
const PRUint32 MAX_LEN = 8;
|
const PRUint32 MAX_LEN = 8;
|
||||||
#elif defined(XP_MAC)
|
#elif defined(XP_MAC)
|
||||||
const PRUint32 MAX_LEN = 25;
|
const PRUint32 MAX_LEN = 25;
|
||||||
|
|
|
@ -176,6 +176,19 @@ NS_IMETHODIMP nsImapMailFolder::GetPath(nsIFileSpec** aPathName)
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
NS_IMETHODIMP nsImapMailFolder::SetPath(nsIFileSpec * aPathName)
|
||||||
|
{
|
||||||
|
if (!aPathName)
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
if (! m_pathName)
|
||||||
|
{
|
||||||
|
m_pathName = new nsFileSpec("");
|
||||||
|
if (! m_pathName)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
return aPathName->GetFileSpec(m_pathName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsImapMailFolder::Enumerate(nsIEnumerator* *result)
|
NS_IMETHODIMP nsImapMailFolder::Enumerate(nsIEnumerator* *result)
|
||||||
{
|
{
|
||||||
|
@ -314,6 +327,14 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSubfolder(¤tFolderNameStr, getter_AddRefs(child));
|
AddSubfolder(¤tFolderNameStr, getter_AddRefs(child));
|
||||||
|
// make the imap folder remember the file spec it was created with.
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
nsCOMPtr <nsIFileSpec> msfFileSpec;
|
||||||
|
nsresult rv = NS_NewFileSpecWithSpec(currentFolderPath, getter_AddRefs(msfFileSpec));
|
||||||
|
if (NS_SUCCEEDED(rv) && msfFileSpec)
|
||||||
|
child->SetPath(msfFileSpec);
|
||||||
|
}
|
||||||
PL_strfree(folderName);
|
PL_strfree(folderName);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -544,9 +565,10 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
|
||||||
return parentFolder->CreateClientSubfolderInfo(nsCAutoString(leafName));
|
return parentFolder->CreateClientSubfolderInfo(nsCAutoString(leafName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we get here, it's really a leaf, and "this" is the parent.
|
||||||
folderNameStr = leafName;
|
folderNameStr = leafName;
|
||||||
|
|
||||||
path += folderNameStr;
|
// path += folderNameStr;
|
||||||
|
|
||||||
// Create an empty database for this mail folder, set its name from the user
|
// Create an empty database for this mail folder, set its name from the user
|
||||||
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
|
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
|
||||||
|
@ -557,6 +579,12 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIMsgDatabase> unusedDB;
|
nsCOMPtr<nsIMsgDatabase> unusedDB;
|
||||||
nsCOMPtr <nsIFileSpec> dbFileSpec;
|
nsCOMPtr <nsIFileSpec> dbFileSpec;
|
||||||
|
|
||||||
|
nsXPIDLCString uniqueLeafName;
|
||||||
|
|
||||||
|
rv = CreatePlatformLeafNameForDisk(folderName, path, getter_Copies(uniqueLeafName));
|
||||||
|
path.SetLeafName(uniqueLeafName);
|
||||||
|
|
||||||
NS_NewFileSpecWithSpec(path, getter_AddRefs(dbFileSpec));
|
NS_NewFileSpecWithSpec(path, getter_AddRefs(dbFileSpec));
|
||||||
rv = mailDBFactory->Open(dbFileSpec, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
|
rv = mailDBFactory->Open(dbFileSpec, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(unusedDB));
|
||||||
|
|
||||||
|
@ -573,6 +601,8 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
|
||||||
|
|
||||||
//Now let's create the actual new folder
|
//Now let's create the actual new folder
|
||||||
rv = AddSubfolder(&folderNameStr, getter_AddRefs(child));
|
rv = AddSubfolder(&folderNameStr, getter_AddRefs(child));
|
||||||
|
if (NS_SUCCEEDED(rv) && child)
|
||||||
|
child->SetPath(dbFileSpec);
|
||||||
|
|
||||||
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
|
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
|
||||||
if (imapFolder)
|
if (imapFolder)
|
||||||
|
|
|
@ -164,6 +164,7 @@ public:
|
||||||
NS_IMETHOD GetNewMessages(nsIMsgWindow *aWindow);
|
NS_IMETHOD GetNewMessages(nsIMsgWindow *aWindow);
|
||||||
|
|
||||||
NS_IMETHOD GetPath(nsIFileSpec** aPathName);
|
NS_IMETHOD GetPath(nsIFileSpec** aPathName);
|
||||||
|
NS_IMETHOD SetPath(nsIFileSpec * aPath);
|
||||||
|
|
||||||
// nsIMsgImapMailFolder methods
|
// nsIMsgImapMailFolder methods
|
||||||
NS_DECL_NSIMSGIMAPMAILFOLDER
|
NS_DECL_NSIMSGIMAPMAILFOLDER
|
||||||
|
@ -314,7 +315,7 @@ protected:
|
||||||
nsresult BuildIdsAndKeyArray(nsISupportsArray* messages,
|
nsresult BuildIdsAndKeyArray(nsISupportsArray* messages,
|
||||||
nsCString& msgIds, nsMsgKeyArray& keyArray);
|
nsCString& msgIds, nsMsgKeyArray& keyArray);
|
||||||
|
|
||||||
nsNativeFileSpec *m_pathName;
|
nsFileSpec *m_pathName;
|
||||||
PRBool m_initialized;
|
PRBool m_initialized;
|
||||||
PRBool m_haveDiscoveredAllFolders;
|
PRBool m_haveDiscoveredAllFolders;
|
||||||
PRBool m_haveReadNameFromDB;
|
PRBool m_haveReadNameFromDB;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче