1999-05-10 21:47:07 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1999-05-10 21:47:07 +00:00
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1999-05-10 21:47:07 +00:00
|
|
|
*
|
1999-11-06 03:43:54 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-05-10 21:47:07 +00:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 03:43:54 +00:00
|
|
|
* Copyright (C) 1999 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1999-05-10 21:47:07 +00:00
|
|
|
*/
|
|
|
|
|
1999-08-07 02:30:11 +00:00
|
|
|
#include "msgCore.h"
|
|
|
|
#include "nsIMessage.h"
|
1999-05-10 21:47:07 +00:00
|
|
|
#include "nsMsgDBFolder.h"
|
|
|
|
#include "nsMsgFolderFlags.h"
|
1999-06-03 22:56:14 +00:00
|
|
|
#include "nsIPref.h"
|
1999-07-17 03:26:24 +00:00
|
|
|
#include "nsIMsgFolderCache.h"
|
|
|
|
#include "nsIMsgFolderCacheElement.h"
|
|
|
|
#include "nsMsgBaseCID.h"
|
1999-09-15 00:59:03 +00:00
|
|
|
#include "nsIMsgMailNewsUrl.h"
|
1999-11-10 00:41:52 +00:00
|
|
|
#include "nsIMsgAccountManager.h"
|
1999-12-07 05:51:53 +00:00
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
|
1999-12-17 03:05:04 +00:00
|
|
|
#if defined(XP_OS2)
|
1999-12-07 05:51:53 +00:00
|
|
|
#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
|
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
|
1999-06-03 22:56:14 +00:00
|
|
|
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
1999-11-10 00:41:52 +00:00
|
|
|
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
1999-06-03 22:56:14 +00:00
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
NS_IMPL_ADDREF_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsMsgDBFolder::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
|
|
{
|
|
|
|
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
|
|
|
*aInstancePtr = nsnull;
|
1999-07-01 00:16:39 +00:00
|
|
|
if (aIID.Equals(nsCOMTypeInfo<nsIDBChangeListener>::GetIID()))
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
|
|
|
*aInstancePtr = NS_STATIC_CAST(nsIDBChangeListener*, this);
|
|
|
|
}
|
1999-09-15 00:59:03 +00:00
|
|
|
else if (aIID.Equals(nsCOMTypeInfo<nsIUrlListener>::GetIID()))
|
|
|
|
{
|
|
|
|
*aInstancePtr = NS_STATIC_CAST(nsIUrlListener*, this);
|
|
|
|
}
|
1999-05-10 21:47:07 +00:00
|
|
|
|
|
|
|
if(*aInstancePtr)
|
|
|
|
{
|
|
|
|
AddRef();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-11-24 00:39:26 +00:00
|
|
|
return nsMsgFolder::QueryInterface(aIID, aInstancePtr);
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsMsgDBFolder::nsMsgDBFolder(void)
|
1999-09-17 23:12:44 +00:00
|
|
|
: mCharset(""), mAddListener(PR_TRUE)
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
nsMsgDBFolder::~nsMsgDBFolder(void)
|
1999-11-14 20:36:22 +00:00
|
|
|
{
|
|
|
|
//shutdown but don't shutdown children.
|
|
|
|
Shutdown(PR_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsMsgDBFolder::Shutdown(PRBool shutdownChildren)
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
|
|
|
if(mDatabase)
|
1999-05-13 23:19:14 +00:00
|
|
|
{
|
|
|
|
mDatabase->RemoveListener(this);
|
1999-05-10 21:47:07 +00:00
|
|
|
mDatabase->Close(PR_TRUE);
|
1999-11-14 20:36:22 +00:00
|
|
|
mDatabase = null_nsCOMPtr();
|
|
|
|
|
1999-05-13 23:19:14 +00:00
|
|
|
}
|
1999-11-14 20:36:22 +00:00
|
|
|
|
|
|
|
if(shutdownChildren)
|
|
|
|
{
|
|
|
|
PRUint32 count;
|
|
|
|
nsresult rv = mSubFolders->Count(&count);
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISupports> childFolderSupports = getter_AddRefs(mSubFolders->ElementAt(i));
|
|
|
|
if(childFolderSupports)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIFolder> childFolder = do_QueryInterface(childFolderSupports);
|
|
|
|
if(childFolder)
|
|
|
|
childFolder->Shutdown(PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
|
1999-09-17 23:12:44 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::StartFolderLoading(void)
|
|
|
|
{
|
|
|
|
if(mDatabase)
|
|
|
|
mDatabase->RemoveListener(this);
|
|
|
|
mAddListener = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsMsgDBFolder::EndFolderLoading(void)
|
|
|
|
{
|
|
|
|
if(mDatabase)
|
|
|
|
mDatabase->AddListener(this);
|
|
|
|
mAddListener = PR_TRUE;
|
1999-11-18 04:31:01 +00:00
|
|
|
UpdateSummaryTotals(PR_TRUE);
|
1999-09-17 23:12:44 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-08-26 04:41:07 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::GetThreads(nsISimpleEnumerator** threadEnumerator)
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
|
|
|
nsresult rv = GetDatabase();
|
|
|
|
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
return mDatabase->EnumerateThreads(threadEnumerator);
|
|
|
|
else
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread)
|
|
|
|
{
|
|
|
|
nsresult rv = GetDatabase();
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
|
|
|
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
rv = mDatabase->GetThreadContainingMsgHdr(msgDBHdr, thread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::HasMessage(nsIMessage *message, PRBool *hasMessage)
|
|
|
|
{
|
|
|
|
if(!hasMessage)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsresult rv = GetDatabase();
|
|
|
|
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMsgDBHdr> msgDBHdr, msgDBHdrForKey;
|
|
|
|
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
|
|
|
nsMsgKey key;
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
rv = msgDBHdr->GetMessageKey(&key);
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
rv = mDatabase->ContainsKey(key, hasMessage);
|
|
|
|
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
1999-06-03 22:56:14 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP nsMsgDBFolder::GetCharset(PRUnichar * *aCharset)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if(!aCharset)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
if(mCharset == "")
|
|
|
|
{
|
|
|
|
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
|
|
|
|
|
|
|
char *prefCharset = nsnull;
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
rv = prefs->CopyCharPref("intl.character_set_name", &prefCharset);
|
|
|
|
}
|
|
|
|
|
2000-01-05 02:55:17 +00:00
|
|
|
nsAutoString prefCharsetStr;
|
1999-06-03 22:56:14 +00:00
|
|
|
if(prefCharset)
|
|
|
|
{
|
|
|
|
prefCharsetStr = prefCharset;
|
|
|
|
PR_Free(prefCharset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prefCharsetStr = "us-ascii";
|
|
|
|
}
|
|
|
|
*aCharset = prefCharsetStr.ToNewUnicode();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*aCharset = mCharset.ToNewUnicode();
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-09-19 23:46:35 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::SetCharset(const PRUnichar * aCharset)
|
1999-06-03 22:56:14 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
|
|
|
nsCOMPtr<nsIMsgDatabase> db;
|
|
|
|
rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
2000-01-05 02:55:17 +00:00
|
|
|
nsAutoString charset(aCharset);
|
1999-06-14 02:20:41 +00:00
|
|
|
rv = folderInfo->SetCharacterSet(&charset);
|
1999-07-13 18:52:56 +00:00
|
|
|
db->Commit(nsMsgDBCommitType::kLargeCommit);
|
1999-06-03 22:56:14 +00:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
nsresult nsMsgDBFolder::ReadDBFolderInfo(PRBool force)
|
|
|
|
{
|
|
|
|
// Since it turns out to be pretty expensive to open and close
|
|
|
|
// the DBs all the time, if we have to open it once, get everything
|
|
|
|
// we might need while we're here
|
|
|
|
|
1999-07-17 03:26:24 +00:00
|
|
|
nsresult result;
|
|
|
|
|
2000-01-27 02:48:22 +00:00
|
|
|
// don't need to reload from cache if we've already read from cache,
|
|
|
|
// and, we might get stale info, so don't do it.
|
|
|
|
if (!(mPrefFlags & MSG_FOLDER_PREF_CACHED))
|
1999-07-17 03:26:24 +00:00
|
|
|
{
|
2000-01-27 02:48:22 +00:00
|
|
|
nsCOMPtr <nsIMsgFolderCache> folderCache;
|
1999-07-17 03:26:24 +00:00
|
|
|
|
2000-01-27 02:48:22 +00:00
|
|
|
NS_WITH_SERVICE(nsIMsgAccountManager, accountMgr, kMsgAccountManagerCID, &result);
|
|
|
|
if(NS_SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
result = accountMgr->GetFolderCache(getter_AddRefs(folderCache));
|
|
|
|
if (NS_SUCCEEDED(result) && folderCache)
|
1999-07-17 03:26:24 +00:00
|
|
|
{
|
2000-01-27 02:48:22 +00:00
|
|
|
nsCOMPtr <nsIFileSpec> path;
|
|
|
|
GetPath(getter_AddRefs(path));
|
|
|
|
nsXPIDLCString persistentPath;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && path)
|
1999-07-17 03:26:24 +00:00
|
|
|
{
|
2000-01-27 02:48:22 +00:00
|
|
|
path->GetPersistentDescriptorString(getter_Copies(persistentPath));
|
|
|
|
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
|
|
|
result = folderCache->GetCacheElement(persistentPath, PR_FALSE, getter_AddRefs(cacheElement));
|
|
|
|
if (NS_SUCCEEDED(result) && cacheElement)
|
|
|
|
{
|
|
|
|
result = ReadFromFolderCacheElem(cacheElement);
|
|
|
|
}
|
1999-07-17 03:26:24 +00:00
|
|
|
}
|
|
|
|
|
2000-01-27 02:48:22 +00:00
|
|
|
}
|
1999-07-17 03:26:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// if (m_master->InitFolderFromCache (this))
|
|
|
|
// return err;
|
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
if (force || !(mPrefFlags & MSG_FOLDER_PREF_CACHED))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
|
|
|
nsCOMPtr<nsIMsgDatabase> db;
|
1999-06-03 22:56:14 +00:00
|
|
|
result = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
|
|
|
if(NS_SUCCEEDED(result))
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
1999-09-08 03:08:27 +00:00
|
|
|
mIsCachable = PR_TRUE;
|
1999-05-10 21:47:07 +00:00
|
|
|
if (folderInfo)
|
|
|
|
{
|
|
|
|
|
|
|
|
folderInfo->GetFlags(&mPrefFlags);
|
|
|
|
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
|
|
|
folderInfo->SetFlags(mPrefFlags);
|
|
|
|
|
|
|
|
folderInfo->GetNumMessages(&mNumTotalMessages);
|
|
|
|
folderInfo->GetNumNewMessages(&mNumUnreadMessages);
|
|
|
|
|
|
|
|
//These should be put in IMAP folder only.
|
|
|
|
//folderInfo->GetImapTotalPendingMessages(&mNumPendingTotalMessages);
|
|
|
|
//folderInfo->GetImapUnreadPendingMessages(&mNumPendingUnreadMessages);
|
|
|
|
|
1999-06-14 02:20:41 +00:00
|
|
|
folderInfo->GetCharacterSet(&mCharset);
|
1999-05-10 21:47:07 +00:00
|
|
|
|
1999-08-11 03:44:32 +00:00
|
|
|
if (db) {
|
|
|
|
PRBool hasnew;
|
|
|
|
nsresult rv;
|
|
|
|
rv = db->HasNew(&hasnew);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!hasnew && mNumPendingUnreadMessages <= 0) {
|
|
|
|
ClearFlag(MSG_FOLDER_FLAG_GOT_NEW);
|
|
|
|
}
|
|
|
|
}
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2000-01-05 15:14:13 +00:00
|
|
|
folderInfo = null_nsCOMPtr();
|
1999-05-10 21:47:07 +00:00
|
|
|
if (db)
|
|
|
|
db->Close(PR_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
1999-05-14 21:03:26 +00:00
|
|
|
nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
PRUint32 changedFlags = oldFlags ^ newFlags;
|
|
|
|
if((changedFlags & MSG_FLAG_READ) || (changedFlags & MSG_FLAG_REPLIED)
|
1999-08-24 21:47:22 +00:00
|
|
|
|| (changedFlags & MSG_FLAG_FORWARDED)|| (changedFlags & MSG_FLAG_NEW))
|
1999-05-14 21:03:26 +00:00
|
|
|
{
|
2000-01-14 09:01:39 +00:00
|
|
|
rv = NotifyPropertyFlagChanged(item, kStatusAtom, oldFlags, newFlags);
|
1999-05-14 21:03:26 +00:00
|
|
|
}
|
1999-08-24 21:47:22 +00:00
|
|
|
else if((changedFlags & MSG_FLAG_MARKED))
|
|
|
|
{
|
2000-01-14 09:01:39 +00:00
|
|
|
rv = NotifyPropertyFlagChanged(item, kFlaggedAtom, oldFlags, newFlags);
|
1999-08-24 21:47:22 +00:00
|
|
|
}
|
|
|
|
return rv;
|
1999-05-14 21:03:26 +00:00
|
|
|
}
|
|
|
|
|
1999-12-07 05:51:53 +00:00
|
|
|
// 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)
|
|
|
|
{
|
1999-12-21 23:11:17 +00:00
|
|
|
#if 0
|
1999-12-07 05:51:53 +00:00
|
|
|
const int charLimit = MAX_FILE_LENGTH_WITHOUT_EXTENSION; // set on platform specific basis
|
1999-12-21 23:11:17 +00:00
|
|
|
#endif
|
|
|
|
#if defined(XP_MAC)
|
1999-12-07 05:51:53 +00:00
|
|
|
nsCAutoString illegalChars = ":";
|
1999-12-17 03:05:04 +00:00
|
|
|
#elif defined(XP_OS2)
|
1999-12-07 05:51:53 +00:00
|
|
|
nsCAutoString illegalChars = "\"/\\[]:;=,|?<>*$. ";
|
|
|
|
#elif defined(XP_WIN32)
|
|
|
|
nsCAutoString illegalChars = "\"/\\[]:;=,|?<>*$";
|
1999-12-21 23:11:17 +00:00
|
|
|
#else // UNIX (what about beos?)
|
1999-12-07 05:51:53 +00:00
|
|
|
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)
|
1999-12-07 23:04:24 +00:00
|
|
|
mangledLeaf.SetCharAt('A', leafLength - 2);
|
|
|
|
mangledLeaf.SetCharAt('A', leafLength - 1); // leafLength must be at least 1
|
1999-12-07 05:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (!nameSpaceExhausted && path.Exists())
|
|
|
|
{
|
|
|
|
if (leafLength >= 2)
|
|
|
|
{
|
|
|
|
PRUnichar lastChar = mangledLeaf.CharAt(leafLength - 1);
|
1999-12-07 23:04:24 +00:00
|
|
|
mangledLeaf.SetCharAt(++lastChar,leafLength - 1);
|
1999-12-07 05:51:53 +00:00
|
|
|
if (lastChar > 'Z')
|
|
|
|
{
|
1999-12-07 23:04:24 +00:00
|
|
|
mangledLeaf.SetCharAt('A',leafLength - 1);
|
1999-12-07 05:51:53 +00:00
|
|
|
PRUnichar nextToLastChar = mangledLeaf.CharAt(leafLength - 2);
|
1999-12-07 23:04:24 +00:00
|
|
|
mangledLeaf.SetCharAt(nextToLastChar + 1, leafLength - 2);
|
1999-12-07 05:51:53 +00:00
|
|
|
nameSpaceExhausted = (nextToLastChar == 'Z');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PRUnichar lastChar = mangledLeaf.CharAt(leafLength - 1);
|
1999-12-07 23:04:24 +00:00
|
|
|
mangledLeaf.SetCharAt(++lastChar, leafLength - 1);
|
1999-12-07 05:51:53 +00:00
|
|
|
nameSpaceExhausted = (lastChar == 'Z');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*resultName = mangledLeaf.ToNewCString();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-06-21 22:56:18 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
|
|
|
{
|
|
|
|
if (!aMsgDatabase || !mDatabase)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aMsgDatabase = mDatabase;
|
|
|
|
NS_ADDREF(*aMsgDatabase);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-13 23:19:14 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags,
|
1999-05-10 21:47:07 +00:00
|
|
|
nsIDBChangeListener * aInstigator)
|
|
|
|
{
|
1999-05-14 00:45:25 +00:00
|
|
|
nsCOMPtr<nsIMsgDBHdr> pMsgDBHdr;
|
|
|
|
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
|
1999-07-01 22:13:13 +00:00
|
|
|
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
|
1999-05-14 00:45:25 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMessage> message;
|
|
|
|
rv = CreateMessageFromMsgDBHdr(pMsgDBHdr, getter_AddRefs(message));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message, &rv));
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
{
|
1999-05-14 21:03:26 +00:00
|
|
|
SendFlagNotifications(msgSupports, aOldFlags, aNewFlags);
|
1999-05-14 00:45:25 +00:00
|
|
|
}
|
1999-07-17 20:33:15 +00:00
|
|
|
UpdateSummaryTotals(PR_TRUE);
|
1999-05-14 00:45:25 +00:00
|
|
|
}
|
|
|
|
}
|
1999-05-10 21:47:07 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-09-16 21:07:56 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags,
|
1999-05-10 21:47:07 +00:00
|
|
|
nsIDBChangeListener * aInstigator)
|
|
|
|
{
|
1999-11-11 00:23:29 +00:00
|
|
|
//Do both flat and thread notifications
|
|
|
|
return OnKeyAddedOrDeleted(aKeyChanged, aParentKey, aFlags, aInstigator, PR_FALSE, PR_TRUE, PR_TRUE);
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
|
1999-09-16 21:07:56 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
1999-05-10 21:47:07 +00:00
|
|
|
nsIDBChangeListener * aInstigator)
|
|
|
|
{
|
1999-11-11 00:23:29 +00:00
|
|
|
//Do both flat and thread notifications
|
|
|
|
return OnKeyAddedOrDeleted(aKeyChanged, aParentKey, aFlags, aInstigator, PR_TRUE, PR_TRUE, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsMsgDBFolder::OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
|
|
|
nsIDBChangeListener * aInstigator, PRBool added, PRBool doFlat, PRBool doThread)
|
|
|
|
{
|
1999-05-10 21:47:07 +00:00
|
|
|
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
1999-11-11 00:23:29 +00:00
|
|
|
nsCOMPtr<nsIMsgDBHdr> parentDBHdr;
|
|
|
|
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgDBHdr));
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
rv = mDatabase->GetMsgHdrForKey(aParentKey, getter_AddRefs(parentDBHdr));
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if(msgDBHdr)
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMessage> message;
|
|
|
|
rv = CreateMessageFromMsgDBHdr(msgDBHdr, getter_AddRefs(message));
|
1999-11-11 00:23:29 +00:00
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message));
|
|
|
|
nsCOMPtr<nsISupports> folderSupports;
|
|
|
|
rv = QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), getter_AddRefs(folderSupports));
|
|
|
|
if(msgSupports && NS_SUCCEEDED(rv) && doFlat)
|
|
|
|
{
|
|
|
|
if(added)
|
|
|
|
NotifyItemAdded(folderSupports, msgSupports, "flatMessageView");
|
|
|
|
else
|
|
|
|
NotifyItemDeleted(folderSupports, msgSupports, "flatMessageView");
|
|
|
|
}
|
|
|
|
if(doThread)
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
1999-11-11 00:23:29 +00:00
|
|
|
if(parentDBHdr)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMessage> parentMessage;
|
|
|
|
rv = CreateMessageFromMsgDBHdr(parentDBHdr, getter_AddRefs(parentMessage));
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> parentSupports(do_QueryInterface(parentMessage));
|
|
|
|
if(msgSupports && NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
if(added)
|
|
|
|
NotifyItemAdded(parentSupports, msgSupports, "threadMessageView");
|
|
|
|
else
|
|
|
|
NotifyItemDeleted(parentSupports, msgSupports, "threadMessageView");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//if there's not a header then in threaded view the folder is the parent.
|
|
|
|
else
|
1999-05-10 21:47:07 +00:00
|
|
|
{
|
1999-11-11 00:23:29 +00:00
|
|
|
if(msgSupports && folderSupports)
|
|
|
|
{
|
|
|
|
if(added)
|
|
|
|
NotifyItemAdded(folderSupports, msgSupports, "threadMessageView");
|
|
|
|
else
|
|
|
|
NotifyItemDeleted(folderSupports, msgSupports, "threadMessageView");
|
|
|
|
}
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-11 00:23:29 +00:00
|
|
|
UpdateSummaryTotals(PR_TRUE);
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
1999-11-11 00:23:29 +00:00
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
}
|
|
|
|
|
1999-11-11 00:23:29 +00:00
|
|
|
|
1999-07-21 03:00:49 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::OnParentChanged(nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent,
|
|
|
|
nsIDBChangeListener * aInstigator)
|
|
|
|
{
|
1999-11-11 00:23:29 +00:00
|
|
|
//In reality we probably want to just change the parent because otherwise we will lose things like
|
|
|
|
//selection.
|
|
|
|
|
|
|
|
//First delete the child from the old threadParent
|
|
|
|
OnKeyAddedOrDeleted(aKeyChanged, oldParent, 0, aInstigator, PR_FALSE, PR_FALSE, PR_TRUE);
|
|
|
|
//Then add it to the new threadParent
|
|
|
|
OnKeyAddedOrDeleted(aKeyChanged, newParent, 0, aInstigator, PR_TRUE, PR_FALSE, PR_TRUE);
|
1999-07-21 03:00:49 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-10 21:47:07 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *
|
|
|
|
instigator)
|
|
|
|
{
|
|
|
|
if (mDatabase)
|
|
|
|
{
|
|
|
|
mDatabase->RemoveListener(this);
|
|
|
|
mDatabase = null_nsCOMPtr();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-07-17 03:26:24 +00:00
|
|
|
|
1999-09-13 21:36:02 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::ManyHeadersToDownload(PRBool *retval)
|
|
|
|
{
|
|
|
|
PRInt32 numTotalMessages;
|
|
|
|
|
|
|
|
if (!retval)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (!mDatabase)
|
|
|
|
*retval = PR_TRUE;
|
|
|
|
else if (NS_SUCCEEDED(GetTotalMessages(PR_FALSE, &numTotalMessages)) && numTotalMessages <= 0)
|
|
|
|
*retval = PR_TRUE;
|
|
|
|
else
|
|
|
|
*retval = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-12-17 03:05:04 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::ReadFromFolderCacheElem(nsIMsgFolderCacheElement *element)
|
1999-07-17 03:26:24 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
char *charset;
|
|
|
|
|
|
|
|
element->GetInt32Property("flags", &mPrefFlags);
|
|
|
|
element->GetInt32Property("totalMsgs", &mNumTotalMessages);
|
|
|
|
element->GetInt32Property("totalUnreadMsgs", &mNumUnreadMessages);
|
|
|
|
|
|
|
|
element->GetStringProperty("charset", &charset);
|
|
|
|
|
1999-08-07 02:30:11 +00:00
|
|
|
#ifdef DEBUG_bienvenu1
|
1999-07-21 03:00:49 +00:00
|
|
|
char *uri;
|
|
|
|
|
|
|
|
GetURI(&uri);
|
|
|
|
printf("read total %ld for %s\n", mNumTotalMessages, uri);
|
|
|
|
PR_Free(uri);
|
|
|
|
#endif
|
1999-07-17 03:26:24 +00:00
|
|
|
mCharset = charset;
|
|
|
|
PR_FREEIF(charset);
|
|
|
|
|
|
|
|
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-17 20:33:15 +00:00
|
|
|
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
|
|
|
{
|
|
|
|
nsCOMPtr <nsIEnumerator> aEnumerator;
|
|
|
|
|
|
|
|
nsresult rv = GetSubFolders(getter_AddRefs(aEnumerator));
|
|
|
|
if(NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (folderCache)
|
|
|
|
{
|
|
|
|
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
2000-01-26 06:05:42 +00:00
|
|
|
nsCOMPtr <nsIFileSpec> path;
|
|
|
|
rv = GetPath(getter_AddRefs(path));
|
|
|
|
nsXPIDLCString persistentPath;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && path)
|
|
|
|
{
|
|
|
|
path->GetPersistentDescriptorString(getter_Copies(persistentPath));
|
|
|
|
rv = folderCache->GetCacheElement(persistentPath, PR_TRUE, getter_AddRefs(cacheElement));
|
|
|
|
if (NS_SUCCEEDED(rv) && cacheElement)
|
|
|
|
rv = WriteToFolderCacheElem(cacheElement);
|
|
|
|
}
|
1999-07-17 20:33:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> aItem;
|
|
|
|
|
|
|
|
rv = aEnumerator->First();
|
1999-09-12 21:36:51 +00:00
|
|
|
if (!NS_SUCCEEDED(rv))
|
|
|
|
return NS_OK; // it's OK, there are no sub-folders.
|
|
|
|
|
1999-07-17 20:33:15 +00:00
|
|
|
while(NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
rv = aEnumerator->CurrentItem(getter_AddRefs(aItem));
|
|
|
|
if (NS_FAILED(rv)) break;
|
|
|
|
nsCOMPtr<nsIMsgFolder> aMsgFolder(do_QueryInterface(aItem, &rv));
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
if (folderCache)
|
1999-09-12 21:36:51 +00:00
|
|
|
{
|
1999-07-17 20:33:15 +00:00
|
|
|
rv = aMsgFolder->WriteToFolderCache(folderCache);
|
1999-09-12 21:36:51 +00:00
|
|
|
if (!NS_SUCCEEDED(rv))
|
|
|
|
break;
|
|
|
|
}
|
1999-07-17 20:33:15 +00:00
|
|
|
}
|
|
|
|
rv = aEnumerator->Next();
|
1999-09-12 21:36:51 +00:00
|
|
|
if (!NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
rv = NS_OK;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-17 20:33:15 +00:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCacheElem(nsIMsgFolderCacheElement *element)
|
1999-07-17 03:26:24 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
element->SetInt32Property("flags", mPrefFlags);
|
|
|
|
element->SetInt32Property("totalMsgs", mNumTotalMessages);
|
|
|
|
element->SetInt32Property("totalUnreadMsgs", mNumUnreadMessages);
|
|
|
|
|
1999-08-05 05:13:15 +00:00
|
|
|
element->SetStringProperty("charset", (const char *) nsCAutoString(mCharset));
|
1999-07-17 03:26:24 +00:00
|
|
|
|
1999-08-07 02:30:11 +00:00
|
|
|
#ifdef DEBUG_bienvenu1
|
1999-07-21 03:00:49 +00:00
|
|
|
char *uri;
|
|
|
|
|
|
|
|
GetURI(&uri);
|
|
|
|
printf("writing total %ld for %s\n", mNumTotalMessages, uri);
|
|
|
|
PR_Free(uri);
|
|
|
|
#endif
|
1999-07-17 03:26:24 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-24 21:10:53 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::MarkAllMessagesRead(void)
|
|
|
|
{
|
|
|
|
nsresult rv = GetDatabase();
|
|
|
|
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
return mDatabase->MarkAllRead(nsnull);
|
|
|
|
|
1999-07-25 23:07:18 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-09-15 00:59:03 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::OnStartRunningUrl(nsIURI *aUrl)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aUrl, "just a sanity check");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMsgDBFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aUrl, "just a sanity check");
|
|
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(aUrl);
|
|
|
|
if (mailUrl)
|
|
|
|
{
|
|
|
|
PRBool updatingFolder = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(mailUrl->GetUpdatingFolder(&updatingFolder)) && updatingFolder)
|
|
|
|
{
|
1999-09-16 21:07:56 +00:00
|
|
|
NotifyFolderLoaded();
|
1999-09-15 00:59:03 +00:00
|
|
|
}
|
1999-11-22 23:32:48 +00:00
|
|
|
|
|
|
|
// be sure to remove ourselves as a url listener
|
|
|
|
mailUrl->UnRegisterListener(this);
|
1999-09-15 00:59:03 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-12-07 05:51:53 +00:00
|
|
|
|