diff options
Diffstat (limited to 'mailnews/db/msgdb/src/nsDBFolderInfo.cpp')
-rw-r--r-- | mailnews/db/msgdb/src/nsDBFolderInfo.cpp | 977 |
1 files changed, 977 insertions, 0 deletions
diff --git a/mailnews/db/msgdb/src/nsDBFolderInfo.cpp b/mailnews/db/msgdb/src/nsDBFolderInfo.cpp new file mode 100644 index 000000000..0260738d0 --- /dev/null +++ b/mailnews/db/msgdb/src/nsDBFolderInfo.cpp @@ -0,0 +1,977 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "msgCore.h" +#include "nsDBFolderInfo.h" +#include "nsMsgDatabase.h" +#include "nsMsgFolderFlags.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIPrefLocalizedString.h" +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsIMsgDBView.h" +#include "nsServiceManagerUtils.h" +#include "nsImapCore.h" +#include "mozilla/Services.h" + +static const char *kDBFolderInfoScope = "ns:msg:db:row:scope:dbfolderinfo:all"; +static const char *kDBFolderInfoTableKind = "ns:msg:db:table:kind:dbfolderinfo"; + +struct mdbOid gDBFolderInfoOID; + +static const char * kNumMessagesColumnName ="numMsgs"; +// have to leave this as numNewMsgs even though it's numUnread Msgs +static const char * kNumUnreadMessagesColumnName = "numNewMsgs"; +static const char * kFlagsColumnName = "flags"; +static const char * kFolderSizeColumnName = "folderSize"; +static const char * kExpungedBytesColumnName = "expungedBytes"; +static const char * kFolderDateColumnName = "folderDate"; +static const char * kHighWaterMessageKeyColumnName = "highWaterKey"; + +static const char * kImapUidValidityColumnName = "UIDValidity"; +static const char * kTotalPendingMessagesColumnName = "totPendingMsgs"; +static const char * kUnreadPendingMessagesColumnName = "unreadPendingMsgs"; +static const char * kMailboxNameColumnName = "mailboxName"; +static const char * kKnownArtsSetColumnName = "knownArts"; +static const char * kExpiredMarkColumnName = "expiredMark"; +static const char * kVersionColumnName = "version"; +static const char * kCharacterSetColumnName = "charSet"; +static const char * kCharacterSetOverrideColumnName = "charSetOverride"; +static const char * kLocaleColumnName = "locale"; + + +#define kMAILNEWS_VIEW_DEFAULT_CHARSET "mailnews.view_default_charset" +#define kMAILNEWS_DEFAULT_CHARSET_OVERRIDE "mailnews.force_charset_override" +static nsCString* gDefaultCharacterSet = nullptr; +static bool gDefaultCharacterOverride; +static nsIObserver *gFolderCharsetObserver = nullptr; + +// observer for charset related preference notification +class nsFolderCharsetObserver : public nsIObserver { + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + nsFolderCharsetObserver() { } +private: + virtual ~nsFolderCharsetObserver() {} +}; + +NS_IMPL_ISUPPORTS(nsFolderCharsetObserver, nsIObserver) + +NS_IMETHODIMP nsFolderCharsetObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData) +{ + nsresult rv; + + nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIPrefBranch> prefBranch; + rv = prefs->GetBranch(nullptr, getter_AddRefs(prefBranch)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) + { + nsDependentString prefName(someData); + + if (prefName.EqualsLiteral(kMAILNEWS_VIEW_DEFAULT_CHARSET)) + { + nsCOMPtr<nsIPrefLocalizedString> pls; + rv = prefBranch->GetComplexValue(kMAILNEWS_VIEW_DEFAULT_CHARSET, + NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls)); + if (NS_SUCCEEDED(rv)) + { + nsString ucsval; + pls->ToString(getter_Copies(ucsval)); + if (!ucsval.IsEmpty()) + { + if (gDefaultCharacterSet) + CopyUTF16toUTF8(ucsval, *gDefaultCharacterSet); + } + } + } + else if (prefName.EqualsLiteral(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE)) + { + rv = prefBranch->GetBoolPref(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, &gDefaultCharacterOverride); + } + } + else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) + { + rv = prefBranch->RemoveObserver(kMAILNEWS_VIEW_DEFAULT_CHARSET, this); + rv = prefBranch->RemoveObserver(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, this); + NS_IF_RELEASE(gFolderCharsetObserver); + delete gDefaultCharacterSet; + gDefaultCharacterSet = nullptr; + } + return rv; +} + + +NS_IMPL_ADDREF(nsDBFolderInfo) +NS_IMPL_RELEASE(nsDBFolderInfo) + +NS_IMETHODIMP +nsDBFolderInfo::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = nullptr; + if(iid.Equals(NS_GET_IID(nsIDBFolderInfo)) || + iid.Equals(NS_GET_IID(nsISupports))) + { + *result = static_cast<nsIDBFolderInfo*>(this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + +nsDBFolderInfo::nsDBFolderInfo(nsMsgDatabase *mdb) + : m_flags(0), + m_expiredMark(0), + m_expiredMarkColumnToken(0) +{ + m_mdbTable = NULL; + m_mdbRow = NULL; + m_version = 1; // for upgrading... + m_IMAPHierarchySeparator = 0; // imap path separator + // mail only (for now) + m_folderSize = 0; + m_folderDate = 0; + m_expungedBytes = 0; // sum of size of deleted messages in folder + m_highWaterMessageKey = 0; + + m_numUnreadMessages = 0; + m_numMessages = 0; + // IMAP only + m_ImapUidValidity = kUidUnknown; + m_totalPendingMessages =0; + m_unreadPendingMessages = 0; + + m_mdbTokensInitialized = false; + m_charSetOverride = false; + + if (!gFolderCharsetObserver) + { + nsresult rv; + nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + nsCOMPtr<nsIPrefBranch> prefBranch; + if (NS_SUCCEEDED(rv)) + { + rv = prefs->GetBranch(nullptr, getter_AddRefs(prefBranch)); + } + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr<nsIPrefLocalizedString> pls; + rv = prefBranch->GetComplexValue(kMAILNEWS_VIEW_DEFAULT_CHARSET, + NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls)); + if (NS_SUCCEEDED(rv)) + { + nsString ucsval; + pls->ToString(getter_Copies(ucsval)); + if (!ucsval.IsEmpty()) + { + if (!gDefaultCharacterSet) + gDefaultCharacterSet = new nsCString; + + if (gDefaultCharacterSet) + CopyUTF16toUTF8(ucsval, *gDefaultCharacterSet); + } + } + rv = prefBranch->GetBoolPref(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, &gDefaultCharacterOverride); + + gFolderCharsetObserver = new nsFolderCharsetObserver(); + NS_ASSERTION(gFolderCharsetObserver, "failed to create observer"); + + // register prefs callbacks + if (gFolderCharsetObserver) + { + NS_ADDREF(gFolderCharsetObserver); + rv = prefBranch->AddObserver(kMAILNEWS_VIEW_DEFAULT_CHARSET, gFolderCharsetObserver, false); + rv = prefBranch->AddObserver(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, gFolderCharsetObserver, false); + + // also register for shutdown + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) + { + rv = observerService->AddObserver(gFolderCharsetObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + } + } + } + } + + m_mdb = mdb; + if (mdb) + { + nsresult err; + + // mdb->AddRef(); + err = m_mdb->GetStore()->StringToToken(mdb->GetEnv(), kDBFolderInfoScope, &m_rowScopeToken); + if (NS_SUCCEEDED(err)) + { + err = m_mdb->GetStore()->StringToToken(mdb->GetEnv(), kDBFolderInfoTableKind, &m_tableKindToken); + if (NS_SUCCEEDED(err)) + { + gDBFolderInfoOID.mOid_Scope = m_rowScopeToken; + gDBFolderInfoOID.mOid_Id = 1; + } + } + InitMDBInfo(); + } +} + +nsDBFolderInfo::~nsDBFolderInfo() +{ + // nsMsgDatabase strictly owns nsDBFolderInfo, so don't ref-count db. + ReleaseExternalReferences(); +} + +// Release any objects we're holding onto. This needs to be safe +// to call multiple times. +void nsDBFolderInfo::ReleaseExternalReferences() +{ + if (m_mdb) + { + if (m_mdbTable) + { + NS_RELEASE(m_mdbTable); + m_mdbTable = nullptr; + } + if (m_mdbRow) + { + NS_RELEASE(m_mdbRow); + m_mdbRow = nullptr; + } + m_mdb = nullptr; + } +} + +// this routine sets up a new db to know about the dbFolderInfo stuff... +nsresult nsDBFolderInfo::AddToNewMDB() +{ + nsresult ret = NS_OK; + if (m_mdb && m_mdb->GetStore()) + { + nsIMdbStore *store = m_mdb->GetStore(); + // create the unique table for the dbFolderInfo. + nsresult err = store->NewTable(m_mdb->GetEnv(), m_rowScopeToken, + m_tableKindToken, true, nullptr, &m_mdbTable); + + // create the singleton row for the dbFolderInfo. + err = store->NewRowWithOid(m_mdb->GetEnv(), + &gDBFolderInfoOID, &m_mdbRow); + + // add the row to the singleton table. + if (m_mdbRow && NS_SUCCEEDED(err)) + err = m_mdbTable->AddRow(m_mdb->GetEnv(), m_mdbRow); + + ret = err; // what are we going to do about nsresult's? + } + return ret; +} + +nsresult nsDBFolderInfo::InitFromExistingDB() +{ + nsresult ret = NS_OK; + if (m_mdb && m_mdb->GetStore()) + { + nsIMdbStore *store = m_mdb->GetStore(); + if (store) + { + mdb_pos rowPos; + mdb_count outTableCount; // current number of such tables + mdb_bool mustBeUnique; // whether port can hold only one of these + mdb_bool hasOid; + ret = store->GetTableKind(m_mdb->GetEnv(), m_rowScopeToken, m_tableKindToken, &outTableCount, + &mustBeUnique, &m_mdbTable); + // NS_ASSERTION(mustBeUnique && outTableCount == 1, "only one global db info allowed"); + + if (m_mdbTable) + { + // find singleton row for global info. + ret = m_mdbTable->HasOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &hasOid); + if (NS_SUCCEEDED(ret)) + { + nsIMdbTableRowCursor *rowCursor; + rowPos = -1; + ret= m_mdbTable->GetTableRowCursor(m_mdb->GetEnv(), rowPos, &rowCursor); + if (NS_SUCCEEDED(ret)) + { + ret = rowCursor->NextRow(m_mdb->GetEnv(), &m_mdbRow, &rowPos); + NS_RELEASE(rowCursor); + if (!m_mdbRow) + ret = NS_ERROR_FAILURE; + if (NS_SUCCEEDED(ret)) + LoadMemberVariables(); + } + } + } + else + ret = NS_ERROR_FAILURE; + } + } + return ret; +} + +nsresult nsDBFolderInfo::InitMDBInfo() +{ + nsresult ret = NS_OK; + if (!m_mdbTokensInitialized && m_mdb && m_mdb->GetStore()) + { + nsIMdbStore *store = m_mdb->GetStore(); + nsIMdbEnv *env = m_mdb->GetEnv(); + + store->StringToToken(env, kNumMessagesColumnName, &m_numMessagesColumnToken); + store->StringToToken(env, kNumUnreadMessagesColumnName, &m_numUnreadMessagesColumnToken); + store->StringToToken(env, kFlagsColumnName, &m_flagsColumnToken); + store->StringToToken(env, kFolderSizeColumnName, &m_folderSizeColumnToken); + store->StringToToken(env, kExpungedBytesColumnName, &m_expungedBytesColumnToken); + store->StringToToken(env, kFolderDateColumnName, &m_folderDateColumnToken); + + store->StringToToken(env, kHighWaterMessageKeyColumnName, &m_highWaterMessageKeyColumnToken); + store->StringToToken(env, kMailboxNameColumnName, &m_mailboxNameColumnToken); + + store->StringToToken(env, kImapUidValidityColumnName, &m_imapUidValidityColumnToken); + store->StringToToken(env, kTotalPendingMessagesColumnName, &m_totalPendingMessagesColumnToken); + store->StringToToken(env, kUnreadPendingMessagesColumnName, &m_unreadPendingMessagesColumnToken); + store->StringToToken(env, kExpiredMarkColumnName, &m_expiredMarkColumnToken); + store->StringToToken(env, kVersionColumnName, &m_versionColumnToken); + m_mdbTokensInitialized = true; + } + + return ret; +} + +nsresult nsDBFolderInfo::LoadMemberVariables() +{ + // it's really not an error for these properties to not exist... + GetInt32PropertyWithToken(m_numMessagesColumnToken, m_numMessages); + GetInt32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages); + GetInt32PropertyWithToken(m_flagsColumnToken, m_flags); + GetInt64PropertyWithToken(m_folderSizeColumnToken, m_folderSize); + GetUint32PropertyWithToken(m_folderDateColumnToken, m_folderDate); + GetInt32PropertyWithToken(m_imapUidValidityColumnToken, m_ImapUidValidity, kUidUnknown); + GetUint32PropertyWithToken(m_expiredMarkColumnToken, m_expiredMark); + GetInt64PropertyWithToken(m_expungedBytesColumnToken, m_expungedBytes); + GetUint32PropertyWithToken(m_highWaterMessageKeyColumnToken, m_highWaterMessageKey); + int32_t version; + + GetInt32PropertyWithToken(m_versionColumnToken, version); + m_version = (uint16_t) version; + m_charSetOverride = gDefaultCharacterOverride; + uint32_t propertyValue; + nsresult rv = GetUint32Property(kCharacterSetOverrideColumnName, gDefaultCharacterOverride, &propertyValue); + if (NS_SUCCEEDED(rv)) + m_charSetOverride = propertyValue; + + m_mdb->GetProperty(m_mdbRow, kCharacterSetColumnName, getter_Copies(m_charSet)); + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetVersion(uint32_t version) +{ + m_version = version; + return SetUint32PropertyWithToken(m_versionColumnToken, (uint32_t) m_version); +} + +NS_IMETHODIMP nsDBFolderInfo::GetVersion(uint32_t *version) +{ + *version = m_version; + return NS_OK; +} + + +nsresult nsDBFolderInfo::AdjustHighWater(nsMsgKey highWater, bool force) +{ + if (force || m_highWaterMessageKey < highWater) + { + m_highWaterMessageKey = highWater; + SetUint32PropertyWithToken(m_highWaterMessageKeyColumnToken, highWater); + } + + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetHighWater(nsMsgKey highWater) +{ + return AdjustHighWater(highWater, true); +} + +NS_IMETHODIMP nsDBFolderInfo::OnKeyAdded(nsMsgKey aNewKey) +{ + return AdjustHighWater(aNewKey, false); +} + +NS_IMETHODIMP +nsDBFolderInfo::GetFolderSize(int64_t *size) +{ + NS_ENSURE_ARG_POINTER(size); + *size = m_folderSize; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetFolderSize(int64_t size) +{ + m_folderSize = size; + return SetInt64Property(kFolderSizeColumnName, m_folderSize); +} + +NS_IMETHODIMP +nsDBFolderInfo::GetFolderDate(uint32_t *folderDate) +{ + NS_ENSURE_ARG_POINTER(folderDate); + *folderDate = m_folderDate; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetFolderDate(uint32_t folderDate) +{ + m_folderDate = folderDate; + return SetUint32PropertyWithToken(m_folderDateColumnToken, folderDate); +} + +NS_IMETHODIMP nsDBFolderInfo::GetHighWater(nsMsgKey *result) +{ + // Sanity check highwater - if it gets too big, other code + // can fail. Look through last 100 messages to recalculate + // the highwater mark. + *result = m_highWaterMessageKey; + if (m_highWaterMessageKey > 0xFFFFFF00 && m_mdb) + { + nsCOMPtr <nsISimpleEnumerator> hdrs; + nsresult rv = m_mdb->ReverseEnumerateMessages(getter_AddRefs(hdrs)); + if (NS_FAILED(rv)) + return rv; + bool hasMore = false; + nsCOMPtr<nsIMsgDBHdr> pHeader; + nsMsgKey recalculatedHighWater = 1; + int32_t i = 0; + while(i++ < 100 && NS_SUCCEEDED(rv = hdrs->HasMoreElements(&hasMore)) + && hasMore) + { + nsCOMPtr<nsISupports> supports; + (void) hdrs->GetNext(getter_AddRefs(supports)); + pHeader = do_QueryInterface(supports); + if (pHeader) + { + nsMsgKey msgKey; + pHeader->GetMessageKey(&msgKey); + if (msgKey > recalculatedHighWater) + recalculatedHighWater = msgKey; + } + } + NS_ASSERTION(m_highWaterMessageKey >= recalculatedHighWater, + "highwater incorrect"); + m_highWaterMessageKey = recalculatedHighWater; + } + *result = m_highWaterMessageKey; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetExpiredMark(nsMsgKey expiredKey) +{ + m_expiredMark = expiredKey; + return SetUint32PropertyWithToken(m_expiredMarkColumnToken, expiredKey); +} + +NS_IMETHODIMP nsDBFolderInfo::GetExpiredMark(nsMsgKey *result) +{ + *result = m_expiredMark; + return NS_OK; +} + +// The size of the argument depends on the maximum size of a single message +NS_IMETHODIMP nsDBFolderInfo::ChangeExpungedBytes(int32_t delta) +{ + return SetExpungedBytes(m_expungedBytes + delta); +} + +NS_IMETHODIMP nsDBFolderInfo::SetMailboxName(const nsAString &newBoxName) +{ + return SetPropertyWithToken(m_mailboxNameColumnToken, newBoxName); +} + +NS_IMETHODIMP nsDBFolderInfo::GetMailboxName(nsAString &boxName) +{ + return GetPropertyWithToken(m_mailboxNameColumnToken, boxName); +} + +NS_IMETHODIMP nsDBFolderInfo::ChangeNumUnreadMessages(int32_t delta) +{ + m_numUnreadMessages += delta; + // m_numUnreadMessages can never be set to negative. + if (m_numUnreadMessages < 0) + { +#ifdef DEBUG_bienvenu1 + NS_ASSERTION(false, "Hardcoded assertion"); +#endif + m_numUnreadMessages = 0; + } + return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages); +} + +NS_IMETHODIMP nsDBFolderInfo::ChangeNumMessages(int32_t delta) +{ + m_numMessages += delta; + // m_numMessages can never be set to negative. + if (m_numMessages < 0) + { +#ifdef DEBUG_bienvenu + NS_ASSERTION(false, "num messages can't be < 0"); +#endif + m_numMessages = 0; + } + return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages); +} + + +NS_IMETHODIMP nsDBFolderInfo::GetNumUnreadMessages(int32_t *result) +{ + *result = m_numUnreadMessages; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetNumUnreadMessages(int32_t numUnreadMessages) +{ + m_numUnreadMessages = numUnreadMessages; + return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages); +} + +NS_IMETHODIMP nsDBFolderInfo::GetNumMessages(int32_t *result) +{ + *result = m_numMessages; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetNumMessages(int32_t numMessages) +{ + m_numMessages = numMessages; + return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages); +} + +NS_IMETHODIMP nsDBFolderInfo::GetExpungedBytes(int64_t *result) +{ + *result = m_expungedBytes; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetExpungedBytes(int64_t expungedBytes) +{ + m_expungedBytes = expungedBytes; + return SetInt64PropertyWithToken(m_expungedBytesColumnToken, m_expungedBytes); +} + + +NS_IMETHODIMP nsDBFolderInfo::GetFlags(int32_t *result) +{ + *result = m_flags; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetFlags(int32_t flags) +{ + nsresult ret = NS_OK; + + if (m_flags != flags) + { + NS_ASSERTION((m_flags & nsMsgFolderFlags::Inbox) == 0 || (flags & nsMsgFolderFlags::Inbox) != 0, "lost inbox flag"); + m_flags = flags; + ret = SetInt32PropertyWithToken(m_flagsColumnToken, m_flags); + } + return ret; +} + +NS_IMETHODIMP nsDBFolderInfo::OrFlags(int32_t flags, int32_t *result) +{ + m_flags |= flags; + *result = m_flags; + return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags); +} + +NS_IMETHODIMP nsDBFolderInfo::AndFlags(int32_t flags, int32_t *result) +{ + m_flags &= flags; + *result = m_flags; + return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags); +} + +NS_IMETHODIMP nsDBFolderInfo::GetImapUidValidity(int32_t *result) +{ + *result = m_ImapUidValidity; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetImapUidValidity(int32_t uidValidity) +{ + m_ImapUidValidity = uidValidity; + return SetUint32PropertyWithToken(m_imapUidValidityColumnToken, m_ImapUidValidity); +} + +bool nsDBFolderInfo::TestFlag(int32_t flags) +{ + return (m_flags & flags) != 0; +} + +NS_IMETHODIMP +nsDBFolderInfo::GetCharacterSet(nsACString &result) +{ + if (!m_charSet.IsEmpty()) + result.Assign(m_charSet); + else if (gDefaultCharacterSet) + result.Assign(*gDefaultCharacterSet); + else + result.Truncate(); + + return NS_OK; +} + +NS_IMETHODIMP +nsDBFolderInfo::GetEffectiveCharacterSet(nsACString &result) +{ + result.Truncate(); + if (NS_FAILED(GetCharProperty(kCharacterSetColumnName, result)) || + (result.IsEmpty() && gDefaultCharacterSet)) + result = *gDefaultCharacterSet; + + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetCharacterSet(const nsACString &charSet) +{ + m_charSet.Assign(charSet); + return SetCharProperty(kCharacterSetColumnName, charSet); +} + +NS_IMETHODIMP nsDBFolderInfo::GetCharacterSetOverride(bool *characterSetOverride) +{ + NS_ENSURE_ARG_POINTER(characterSetOverride); + *characterSetOverride = m_charSetOverride; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetCharacterSetOverride(bool characterSetOverride) +{ + m_charSetOverride = characterSetOverride; + return SetUint32Property(kCharacterSetOverrideColumnName, characterSetOverride); +} + +NS_IMETHODIMP +nsDBFolderInfo::GetLocale(nsAString &result) +{ + GetProperty(kLocaleColumnName, result); + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetLocale(const nsAString &locale) +{ + return SetProperty(kLocaleColumnName, locale); +} + +NS_IMETHODIMP +nsDBFolderInfo::GetImapTotalPendingMessages(int32_t *result) +{ + NS_ENSURE_ARG_POINTER(result); + *result = m_totalPendingMessages; + return NS_OK; +} + +void nsDBFolderInfo::ChangeImapTotalPendingMessages(int32_t delta) +{ + m_totalPendingMessages+=delta; + SetInt32PropertyWithToken(m_totalPendingMessagesColumnToken, m_totalPendingMessages); +} + +NS_IMETHODIMP +nsDBFolderInfo::GetImapUnreadPendingMessages(int32_t *result) +{ + NS_ENSURE_ARG_POINTER(result); + *result = m_unreadPendingMessages; + return NS_OK; +} + +NS_IMETHODIMP nsDBFolderInfo::SetImapUnreadPendingMessages(int32_t numUnreadPendingMessages) +{ + m_unreadPendingMessages = numUnreadPendingMessages; + return SetUint32PropertyWithToken(m_unreadPendingMessagesColumnToken, m_unreadPendingMessages); +} + +NS_IMETHODIMP nsDBFolderInfo::SetImapTotalPendingMessages(int32_t numTotalPendingMessages) +{ + m_totalPendingMessages = numTotalPendingMessages; + return SetUint32PropertyWithToken(m_totalPendingMessagesColumnToken, m_totalPendingMessages); +} + +void nsDBFolderInfo::ChangeImapUnreadPendingMessages(int32_t delta) +{ + m_unreadPendingMessages+=delta; + SetInt32PropertyWithToken(m_unreadPendingMessagesColumnToken, m_unreadPendingMessages); +} + +/* attribute nsMsgViewTypeValue viewType; */ +NS_IMETHODIMP nsDBFolderInfo::GetViewType(nsMsgViewTypeValue *aViewType) +{ + uint32_t viewTypeValue; + nsresult rv = GetUint32Property("viewType", nsMsgViewType::eShowAllThreads, &viewTypeValue); + *aViewType = viewTypeValue; + return rv; +} +NS_IMETHODIMP nsDBFolderInfo::SetViewType(nsMsgViewTypeValue aViewType) +{ + return SetUint32Property("viewType", aViewType); +} + +/* attribute nsMsgViewFlagsTypeValue viewFlags; */ +NS_IMETHODIMP nsDBFolderInfo::GetViewFlags(nsMsgViewFlagsTypeValue *aViewFlags) +{ + nsMsgViewFlagsTypeValue defaultViewFlags; + nsresult rv = m_mdb->GetDefaultViewFlags(&defaultViewFlags); + NS_ENSURE_SUCCESS(rv,rv); + + uint32_t viewFlagsValue; + rv = GetUint32Property("viewFlags", defaultViewFlags, &viewFlagsValue); + *aViewFlags = viewFlagsValue; + return rv; +} +NS_IMETHODIMP nsDBFolderInfo::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags) +{ + return SetUint32Property("viewFlags", aViewFlags); +} + +/* attribute nsMsgViewSortTypeValue sortType; */ +NS_IMETHODIMP nsDBFolderInfo::GetSortType(nsMsgViewSortTypeValue *aSortType) +{ + nsMsgViewSortTypeValue defaultSortType; + nsresult rv = m_mdb->GetDefaultSortType(&defaultSortType); + NS_ENSURE_SUCCESS(rv,rv); + + uint32_t sortTypeValue; + rv = GetUint32Property("sortType", defaultSortType, &sortTypeValue); + *aSortType = sortTypeValue; + return rv; +} +NS_IMETHODIMP nsDBFolderInfo::SetSortType(nsMsgViewSortTypeValue aSortType) +{ + return SetUint32Property("sortType", aSortType); +} + +/* attribute nsMsgViewSortOrderValue sortOrder; */ +NS_IMETHODIMP nsDBFolderInfo::GetSortOrder(nsMsgViewSortOrderValue *aSortOrder) +{ + nsMsgViewSortOrderValue defaultSortOrder; + nsresult rv = m_mdb->GetDefaultSortOrder(&defaultSortOrder); + NS_ENSURE_SUCCESS(rv,rv); + + uint32_t sortOrderValue; + rv = GetUint32Property("sortOrder", defaultSortOrder, &sortOrderValue); + *aSortOrder = sortOrderValue; + return rv; +} + +NS_IMETHODIMP nsDBFolderInfo::SetSortOrder(nsMsgViewSortOrderValue aSortOrder) +{ + return SetUint32Property("sortOrder", aSortOrder); +} + +NS_IMETHODIMP nsDBFolderInfo::SetKnownArtsSet(const char *newsArtSet) +{ + return m_mdb->SetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet); +} + +NS_IMETHODIMP nsDBFolderInfo::GetKnownArtsSet(char **newsArtSet) +{ + return m_mdb->GetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet); +} + +// get arbitrary property, aka row cell value. +NS_IMETHODIMP nsDBFolderInfo::GetProperty(const char *propertyName, nsAString &resultProperty) +{ + return m_mdb->GetPropertyAsNSString(m_mdbRow, propertyName, resultProperty); +} + +NS_IMETHODIMP nsDBFolderInfo::SetCharProperty(const char *aPropertyName, + const nsACString &aPropertyValue) +{ + return m_mdb->SetProperty(m_mdbRow, aPropertyName, + nsCString(aPropertyValue).get()); +} + +NS_IMETHODIMP nsDBFolderInfo::GetCharProperty(const char *propertyName, + nsACString &resultProperty) +{ + nsCString result; + nsresult rv = m_mdb->GetProperty(m_mdbRow, propertyName, getter_Copies(result)); + if (NS_SUCCEEDED(rv)) + resultProperty.Assign(result); + return rv; +} + +NS_IMETHODIMP nsDBFolderInfo::SetUint32Property(const char *propertyName, uint32_t propertyValue) +{ + return m_mdb->SetUint32Property(m_mdbRow, propertyName, propertyValue); +} + +NS_IMETHODIMP nsDBFolderInfo::SetInt64Property(const char *propertyName, int64_t propertyValue) +{ + return m_mdb->SetUint64Property(m_mdbRow, propertyName, (uint64_t) propertyValue); +} + +NS_IMETHODIMP nsDBFolderInfo::SetProperty(const char *propertyName, const nsAString &propertyStr) +{ + return m_mdb->SetPropertyFromNSString(m_mdbRow, propertyName, propertyStr); +} + +nsresult nsDBFolderInfo::SetPropertyWithToken(mdb_token aProperty, const nsAString &propertyStr) +{ + return m_mdb->SetNSStringPropertyWithToken(m_mdbRow, aProperty, propertyStr); +} + +nsresult nsDBFolderInfo::SetUint32PropertyWithToken(mdb_token aProperty, uint32_t propertyValue) +{ + return m_mdb->UInt32ToRowCellColumn(m_mdbRow, aProperty, propertyValue); +} + +nsresult nsDBFolderInfo::SetInt64PropertyWithToken(mdb_token aProperty, int64_t propertyValue) +{ + return m_mdb->UInt64ToRowCellColumn(m_mdbRow, aProperty, (uint64_t) propertyValue); +} + +nsresult nsDBFolderInfo::SetInt32PropertyWithToken(mdb_token aProperty, int32_t propertyValue) +{ + nsAutoString propertyStr; + propertyStr.AppendInt(propertyValue, 16); + return SetPropertyWithToken(aProperty, propertyStr); +} + +nsresult nsDBFolderInfo::GetPropertyWithToken(mdb_token aProperty, nsAString &resultProperty) +{ + return m_mdb->RowCellColumnTonsString(m_mdbRow, aProperty, resultProperty); +} + +nsresult nsDBFolderInfo::GetUint32PropertyWithToken(mdb_token aProperty, uint32_t &propertyValue, uint32_t defaultValue) +{ + return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty, propertyValue, defaultValue); +} + +nsresult nsDBFolderInfo::GetInt32PropertyWithToken(mdb_token aProperty, int32_t &propertyValue, int32_t defaultValue) +{ + return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty, (uint32_t &) propertyValue, defaultValue); +} + +NS_IMETHODIMP nsDBFolderInfo::GetUint32Property(const char *propertyName, uint32_t defaultValue, uint32_t *propertyValue) +{ + return m_mdb->GetUint32Property(m_mdbRow, propertyName, propertyValue, defaultValue); +} + +NS_IMETHODIMP nsDBFolderInfo::GetInt64Property(const char *propertyName, int64_t defaultValue, int64_t *propertyValue) +{ + return m_mdb->GetUint64Property(m_mdbRow, propertyName, (uint64_t *) &propertyValue, defaultValue); +} + +nsresult nsDBFolderInfo::GetInt64PropertyWithToken(mdb_token aProperty, + int64_t &propertyValue, + int64_t defaultValue) +{ + return m_mdb->RowCellColumnToUInt64(m_mdbRow, aProperty, (uint64_t *) &propertyValue, defaultValue); +} + +NS_IMETHODIMP nsDBFolderInfo::GetBooleanProperty(const char *propertyName, bool defaultValue, bool *propertyValue) +{ + uint32_t defaultUint32Value = (defaultValue) ? 1 : 0; + uint32_t returnValue; + nsresult rv = m_mdb->GetUint32Property(m_mdbRow, propertyName, &returnValue, defaultUint32Value); + *propertyValue = (returnValue != 0); + return rv; +} +NS_IMETHODIMP nsDBFolderInfo::SetBooleanProperty(const char *propertyName, bool propertyValue) +{ + return m_mdb->SetUint32Property(m_mdbRow, propertyName, propertyValue ? 1 : 0); +} + +NS_IMETHODIMP nsDBFolderInfo::GetFolderName(nsACString &folderName) +{ + return GetCharProperty("folderName", folderName); +} + +NS_IMETHODIMP nsDBFolderInfo::SetFolderName(const nsACString &folderName) +{ + return SetCharProperty("folderName", folderName); +} + +class nsTransferDBFolderInfo : public nsDBFolderInfo +{ +public: + nsTransferDBFolderInfo(); + virtual ~nsTransferDBFolderInfo(); + // parallel arrays of properties and values + nsTArray<nsCString> m_properties; + nsTArray<nsCString> m_values; +}; + +nsTransferDBFolderInfo::nsTransferDBFolderInfo() : nsDBFolderInfo(nullptr) +{ +} + +nsTransferDBFolderInfo::~nsTransferDBFolderInfo() +{ +} + +/* void GetTransferInfo (out nsIDBFolderInfo transferInfo); */ +NS_IMETHODIMP nsDBFolderInfo::GetTransferInfo(nsIDBFolderInfo **transferInfo) +{ + NS_ENSURE_ARG_POINTER(transferInfo); + + nsTransferDBFolderInfo *newInfo = new nsTransferDBFolderInfo; + *transferInfo = newInfo; + NS_ADDREF(newInfo); + + mdb_count numCells; + mdbYarn cellYarn; + mdb_column cellColumn; + char columnName[100]; + mdbYarn cellName = { columnName, 0, sizeof(columnName), 0, 0, nullptr }; + + NS_ASSERTION(m_mdbRow, "null row in getTransferInfo"); + m_mdbRow->GetCount(m_mdb->GetEnv(), &numCells); + // iterate over the cells in the dbfolderinfo remembering attribute names and values. + for (mdb_count cellIndex = 0; cellIndex < numCells; cellIndex++) + { + nsresult err = m_mdbRow->SeekCellYarn(m_mdb->GetEnv(), cellIndex, &cellColumn, nullptr); + if (NS_SUCCEEDED(err)) + { + err = m_mdbRow->AliasCellYarn(m_mdb->GetEnv(), cellColumn, &cellYarn); + if (NS_SUCCEEDED(err)) + { + m_mdb->GetStore()->TokenToString(m_mdb->GetEnv(), cellColumn, &cellName); + newInfo->m_values.AppendElement(Substring((const char *)cellYarn.mYarn_Buf, + (const char *) cellYarn.mYarn_Buf + cellYarn.mYarn_Fill)); + newInfo->m_properties.AppendElement(Substring((const char *) cellName.mYarn_Buf, + (const char *) cellName.mYarn_Buf + cellName.mYarn_Fill)); + } + } + } + + return NS_OK; +} + + +/* void InitFromTransferInfo (in nsIDBFolderInfo transferInfo); */ +NS_IMETHODIMP nsDBFolderInfo::InitFromTransferInfo(nsIDBFolderInfo *aTransferInfo) +{ + NS_ENSURE_ARG(aTransferInfo); + + nsTransferDBFolderInfo *transferInfo = static_cast<nsTransferDBFolderInfo *>(aTransferInfo); + + for (uint32_t i = 0; i < transferInfo->m_values.Length(); i++) + SetCharProperty(transferInfo->m_properties[i].get(), transferInfo->m_values[i]); + + LoadMemberVariables(); + return NS_OK; +} + |