зеркало из https://github.com/mozilla/pjs.git
fix msf file names for imap folders with illegal characters, r=mscott 20324
This commit is contained in:
Родитель
7a9b108c96
Коммит
5eb045931d
|
@ -275,7 +275,7 @@ interface nsIMsgFolder : nsIFolder {
|
|||
/**
|
||||
* local path of this folder
|
||||
*/
|
||||
readonly attribute nsIFileSpec path;
|
||||
attribute nsIFileSpec path;
|
||||
|
||||
void markMessagesRead(in nsISupportsArray messages, in boolean markRead);
|
||||
void markAllMessagesRead();
|
||||
|
|
|
@ -30,6 +30,18 @@
|
|||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgMailNewsUrl.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(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
||||
|
@ -320,6 +332,111 @@ nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFla
|
|||
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
|
||||
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
||||
{
|
||||
|
@ -607,3 +724,4 @@ nsMsgDBFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ protected:
|
|||
nsresult ReadFromFolderCache(nsIMsgFolderCacheElement *element);
|
||||
nsresult OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
||||
nsIDBChangeListener * aInstigator, PRBool added, PRBool doFlat, PRBool doThread);
|
||||
nsresult CreatePlatformLeafNameForDisk(const char *userLeafName, nsFileSpec &baseDir, char **resultName);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
||||
|
|
|
@ -1733,8 +1733,13 @@ nsMsgFolder::GetPath(nsIFileSpec * *aPath)
|
|||
|
||||
nsCOMPtr<nsIFileSpec> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ public:
|
|||
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
|
||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase * *aMsgDatabase);
|
||||
NS_IMETHOD GetPath(nsIFileSpec * *aPath);
|
||||
NS_IMETHOD SetPath(nsIFileSpec * aPath);
|
||||
NS_IMETHOD MarkMessagesRead(nsISupportsArray *messages, PRBool markRead);
|
||||
NS_IMETHOD MarkAllMessagesRead(void);
|
||||
NS_IMETHOD MarkMessagesFlagged(nsISupportsArray *messages, PRBool markFlagged);
|
||||
|
|
|
@ -289,7 +289,7 @@ static PRUint32 StringHash(const char *ubuf)
|
|||
|
||||
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
|
||||
{
|
||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||
#if defined(XP_OS2)
|
||||
const PRUint32 MAX_LEN = 8;
|
||||
#elif defined(XP_MAC)
|
||||
const PRUint32 MAX_LEN = 25;
|
||||
|
|
|
@ -176,6 +176,19 @@ NS_IMETHODIMP nsImapMailFolder::GetPath(nsIFileSpec** aPathName)
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -314,6 +327,14 @@ nsresult nsImapMailFolder::CreateSubFolders(nsFileSpec &path)
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return rv;
|
||||
|
@ -544,9 +565,10 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
|
|||
return parentFolder->CreateClientSubfolderInfo(nsCAutoString(leafName));
|
||||
}
|
||||
|
||||
// if we get here, it's really a leaf, and "this" is the parent.
|
||||
folderNameStr = leafName;
|
||||
|
||||
path += folderNameStr;
|
||||
// path += folderNameStr;
|
||||
|
||||
// Create an empty database for this mail folder, set its name from the user
|
||||
nsCOMPtr<nsIMsgDatabase> mailDBFactory;
|
||||
|
@ -557,6 +579,12 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName
|
|||
{
|
||||
nsCOMPtr<nsIMsgDatabase> unusedDB;
|
||||
nsCOMPtr <nsIFileSpec> dbFileSpec;
|
||||
|
||||
nsXPIDLCString uniqueLeafName;
|
||||
|
||||
rv = CreatePlatformLeafNameForDisk(folderName, path, getter_Copies(uniqueLeafName));
|
||||
path.SetLeafName(uniqueLeafName);
|
||||
|
||||
NS_NewFileSpecWithSpec(path, getter_AddRefs(dbFileSpec));
|
||||
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
|
||||
rv = AddSubfolder(&folderNameStr, getter_AddRefs(child));
|
||||
if (NS_SUCCEEDED(rv) && child)
|
||||
child->SetPath(dbFileSpec);
|
||||
|
||||
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(child);
|
||||
if (imapFolder)
|
||||
|
|
|
@ -164,6 +164,7 @@ public:
|
|||
NS_IMETHOD GetNewMessages(nsIMsgWindow *aWindow);
|
||||
|
||||
NS_IMETHOD GetPath(nsIFileSpec** aPathName);
|
||||
NS_IMETHOD SetPath(nsIFileSpec * aPath);
|
||||
|
||||
// nsIMsgImapMailFolder methods
|
||||
NS_DECL_NSIMSGIMAPMAILFOLDER
|
||||
|
@ -314,7 +315,7 @@ protected:
|
|||
nsresult BuildIdsAndKeyArray(nsISupportsArray* messages,
|
||||
nsCString& msgIds, nsMsgKeyArray& keyArray);
|
||||
|
||||
nsNativeFileSpec *m_pathName;
|
||||
nsFileSpec *m_pathName;
|
||||
PRBool m_initialized;
|
||||
PRBool m_haveDiscoveredAllFolders;
|
||||
PRBool m_haveReadNameFromDB;
|
||||
|
|
Загрузка…
Ссылка в новой задаче