Back to index

lightning-sunbird  0.9+nobinonly
nsDBFolderInfo.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "msgCore.h"
00040 #include "nsDBFolderInfo.h"
00041 #include "nsMsgDatabase.h"
00042 #include "nsMsgFolderFlags.h"
00043 #include "nsIPrefService.h"
00044 #include "nsIPrefBranch.h"
00045 #include "nsIPrefBranch2.h"
00046 #include "nsIPrefLocalizedString.h"
00047 #include "nsIObserver.h"
00048 #include "nsIObserverService.h"
00049 #include "nsIMsgDBView.h"
00050 #include "nsReadableUtils.h"
00051 #include "nsISupportsObsolete.h"
00052 
00053 static const char *kDBFolderInfoScope = "ns:msg:db:row:scope:dbfolderinfo:all";
00054 static const char *kDBFolderInfoTableKind = "ns:msg:db:table:kind:dbfolderinfo";
00055 
00056 struct mdbOid gDBFolderInfoOID;
00057 
00058 static const char * kNumMessagesColumnName ="numMsgs";
00059 // have to leave this as numNewMsgs even though it's numUnread Msgs
00060 static const char * kNumUnreadMessagesColumnName = "numNewMsgs"; 
00061 static const char * kFlagsColumnName = "flags";
00062 static const char * kFolderSizeColumnName = "folderSize";
00063 static const char * kExpungedBytesColumnName = "expungedBytes";
00064 static const char * kFolderDateColumnName = "folderDate";
00065 static const char * kHighWaterMessageKeyColumnName = "highWaterKey";
00066 
00067 static const char * kImapUidValidityColumnName = "UIDValidity";
00068 static const char * kTotalPendingMessagesColumnName = "totPendingMsgs";
00069 static const char * kUnreadPendingMessagesColumnName = "unreadPendingMsgs";
00070 static const char * kMailboxNameColumnName = "mailboxName";
00071 static const char * kKnownArtsSetColumnName = "knownArts";
00072 static const char * kExpiredMarkColumnName = "expiredMark";
00073 static const char * kVersionColumnName = "version";
00074 static const char * kCharacterSetColumnName = "charSet";
00075 static const char * kCharacterSetOverrideColumnName = "charSetOverride";
00076 static const char * kLocaleColumnName = "locale";
00077 
00078 
00079 #define kMAILNEWS_VIEW_DEFAULT_CHARSET        "mailnews.view_default_charset"
00080 #define kMAILNEWS_DEFAULT_CHARSET_OVERRIDE    "mailnews.force_charset_override"
00081 static char * gDefaultCharacterSet = NULL;
00082 static PRBool     gDefaultCharacterOverride;
00083 static nsIObserver *gFolderCharsetObserver = nsnull;
00084 static PRBool     gInitializeObserver = PR_FALSE;
00085 static PRBool     gReleaseObserver = PR_FALSE;
00086 
00087 // observer for charset related preference notification
00088 class nsFolderCharsetObserver : public nsIObserver {
00089 
00090 public:
00091   NS_DECL_ISUPPORTS
00092   NS_DECL_NSIOBSERVER
00093 
00094   nsFolderCharsetObserver() { }
00095   virtual ~nsFolderCharsetObserver() {}
00096 };
00097 
00098 NS_IMPL_ISUPPORTS1(nsFolderCharsetObserver, nsIObserver)
00099 
00100 NS_IMETHODIMP nsFolderCharsetObserver::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
00101 {
00102   nsresult rv;
00103 
00104   nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00105   if (NS_FAILED(rv)) return rv;
00106 
00107   nsCOMPtr<nsIPrefBranch> prefBranch;
00108   rv = prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
00109   NS_ENSURE_SUCCESS(rv, rv);
00110 
00111   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
00112   {
00113     nsDependentString prefName(someData);
00114     
00115     if (prefName.EqualsLiteral(kMAILNEWS_VIEW_DEFAULT_CHARSET))
00116     {
00117       nsCOMPtr<nsIPrefLocalizedString> pls;
00118       rv = prefBranch->GetComplexValue(kMAILNEWS_VIEW_DEFAULT_CHARSET,
00119                       NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
00120       if (NS_SUCCEEDED(rv)) 
00121       {
00122         nsXPIDLString ucsval;
00123         pls->ToString(getter_Copies(ucsval));
00124         if (ucsval)
00125         {
00126           if (gDefaultCharacterSet)
00127             nsMemory::Free(gDefaultCharacterSet); 
00128           gDefaultCharacterSet = ToNewCString(ucsval);
00129         }
00130       }
00131     }
00132     else if (prefName.EqualsLiteral(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE))
00133     {
00134       rv = prefBranch->GetBoolPref(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, &gDefaultCharacterOverride);
00135     }
00136   }
00137   else if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
00138   {
00139     nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(prefBranch);
00140     if (pbi) 
00141     {
00142       rv = pbi->RemoveObserver(kMAILNEWS_VIEW_DEFAULT_CHARSET, this);
00143       rv = pbi->RemoveObserver(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, this);
00144     }
00145     gReleaseObserver = PR_TRUE;   // set true to release observer
00146   }
00147 
00148   return rv;
00149 }
00150 
00151 
00152 NS_IMPL_ADDREF(nsDBFolderInfo)
00153 NS_IMPL_RELEASE(nsDBFolderInfo)
00154 
00155 NS_IMETHODIMP
00156 nsDBFolderInfo::QueryInterface(REFNSIID iid, void** result)
00157 {
00158   if (! result)
00159     return NS_ERROR_NULL_POINTER;
00160   
00161   *result = nsnull;
00162   if(iid.Equals(NS_GET_IID(nsIDBFolderInfo)) ||
00163     iid.Equals(NS_GET_IID(nsISupports))) 
00164   {
00165     *result = NS_STATIC_CAST(nsIDBFolderInfo*, this);
00166     AddRef();
00167     return NS_OK;
00168   }
00169   return NS_NOINTERFACE;
00170 }
00171 
00172 
00173 nsDBFolderInfo::nsDBFolderInfo(nsMsgDatabase *mdb)
00174                   : m_flags(0),
00175                     m_expiredMark(0),
00176                     m_expiredMarkColumnToken(0)
00177 {
00178   m_mdbTable = NULL;
00179   m_mdbRow = NULL;
00180   m_version = 1;                   // for upgrading...
00181   m_IMAPHierarchySeparator = 0;    // imap path separator
00182   // mail only (for now)
00183   m_folderSize = 0;
00184   m_folderDate = 0;
00185   m_expungedBytes = 0;      // sum of size of deleted messages in folder
00186   m_highWaterMessageKey = 0;
00187   
00188   m_numUnreadMessages = 0;
00189   m_numMessages = 0;
00190   // IMAP only
00191   m_ImapUidValidity = 0;
00192   m_totalPendingMessages =0;
00193   m_unreadPendingMessages = 0;
00194   
00195   m_mdbTokensInitialized = PR_FALSE;
00196   m_charSetOverride = PR_FALSE;
00197   
00198   if (!gInitializeObserver)
00199   {
00200     gInitializeObserver = PR_TRUE;
00201     nsresult rv;
00202     nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00203     nsCOMPtr<nsIPrefBranch> prefBranch;
00204     if (NS_SUCCEEDED(rv))
00205     {
00206       rv = prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
00207     }
00208     if (NS_SUCCEEDED(rv))
00209     {
00210       nsCOMPtr<nsIPrefLocalizedString> pls;
00211       rv = prefBranch->GetComplexValue(kMAILNEWS_VIEW_DEFAULT_CHARSET,
00212         NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
00213       if (NS_SUCCEEDED(rv)) 
00214       {
00215         nsXPIDLString ucsval;
00216         pls->ToString(getter_Copies(ucsval));
00217         if (ucsval)
00218         {
00219           if (gDefaultCharacterSet)
00220             nsMemory::Free(gDefaultCharacterSet);
00221           gDefaultCharacterSet = ToNewCString(ucsval);
00222         }
00223       }
00224       rv = prefBranch->GetBoolPref(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, &gDefaultCharacterOverride);
00225       
00226       gFolderCharsetObserver = new nsFolderCharsetObserver();
00227       NS_ASSERTION(gFolderCharsetObserver, "failed to create observer");
00228       
00229       // register prefs callbacks
00230       if (gFolderCharsetObserver)
00231       {
00232         NS_ADDREF(gFolderCharsetObserver);
00233         nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(prefBranch);
00234         if (pbi) {
00235           rv = pbi->AddObserver(kMAILNEWS_VIEW_DEFAULT_CHARSET, gFolderCharsetObserver, PR_FALSE);
00236           rv = pbi->AddObserver(kMAILNEWS_DEFAULT_CHARSET_OVERRIDE, gFolderCharsetObserver, PR_FALSE);
00237         }
00238         
00239         // also register for shutdown
00240         nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
00241         if (NS_SUCCEEDED(rv))
00242         {
00243           rv = observerService->AddObserver(gFolderCharsetObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
00244         }
00245       }
00246     }
00247   }
00248   
00249   m_mdb = mdb;
00250   if (mdb)
00251   {
00252     mdb_err err;
00253     
00254     //        mdb->AddRef();
00255     err = m_mdb->GetStore()->StringToToken(mdb->GetEnv(), kDBFolderInfoScope, &m_rowScopeToken); 
00256     if (err == NS_OK)
00257     {
00258       err = m_mdb->GetStore()->StringToToken(mdb->GetEnv(), kDBFolderInfoTableKind, &m_tableKindToken); 
00259       if (err == NS_OK)
00260       {
00261         gDBFolderInfoOID.mOid_Scope = m_rowScopeToken;
00262         gDBFolderInfoOID.mOid_Id = 1;
00263       }
00264     }
00265     InitMDBInfo();
00266   }
00267 }
00268 
00269 nsDBFolderInfo::~nsDBFolderInfo()
00270 {
00271   // nsMsgDatabase strictly owns nsDBFolderInfo, so don't ref-count db.
00272   ReleaseExternalReferences();
00273 }
00274 
00275 // Release any objects we're holding onto. This needs to be safe
00276 // to call multiple times.
00277 void nsDBFolderInfo::ReleaseExternalReferences()
00278 {
00279   if (gReleaseObserver && gFolderCharsetObserver) 
00280   {
00281     NS_IF_RELEASE(gFolderCharsetObserver);
00282   
00283     // this can be called many times
00284     if (gDefaultCharacterSet)
00285     {
00286       nsMemory::Free(gDefaultCharacterSet);
00287       gDefaultCharacterSet = NULL; // free doesn't null out our ptr.
00288     }
00289   }
00290   
00291   if (m_mdb)
00292   {
00293     if (m_mdbTable)
00294     {
00295       NS_RELEASE(m_mdbTable);
00296       m_mdbTable = nsnull;
00297     }
00298     if (m_mdbRow)
00299     {
00300       NS_RELEASE(m_mdbRow);
00301       m_mdbRow = nsnull;
00302     }
00303     m_mdb = nsnull;
00304   }
00305 }
00306 
00307 // this routine sets up a new db to know about the dbFolderInfo stuff...
00308 nsresult nsDBFolderInfo::AddToNewMDB()
00309 {
00310   nsresult ret = NS_OK;
00311   if (m_mdb && m_mdb->GetStore())
00312   {
00313     nsIMdbStore *store = m_mdb->GetStore();
00314     // create the unique table for the dbFolderInfo.
00315     mdb_err err = store->NewTable(m_mdb->GetEnv(), m_rowScopeToken, 
00316       m_tableKindToken, PR_TRUE, nsnull, &m_mdbTable);
00317     
00318     // make sure the oid of the table is 1.
00319     struct mdbOid folderInfoTableOID;
00320     folderInfoTableOID.mOid_Id = 1;
00321     folderInfoTableOID.mOid_Scope = m_rowScopeToken;
00322     
00323     //        m_mdbTable->BecomeContent(m_mdb->GetEnv(), &folderInfoTableOID);
00324     
00325     // create the singleton row for the dbFolderInfo.
00326     err  = store->NewRowWithOid(m_mdb->GetEnv(),
00327       &gDBFolderInfoOID, &m_mdbRow);
00328     
00329     // add the row to the singleton table.
00330     if (m_mdbRow && NS_SUCCEEDED(err))
00331     {
00332       err = m_mdbTable->AddRow(m_mdb->GetEnv(), m_mdbRow);
00333     }
00334     
00335     ret = err;       // what are we going to do about mdb_err's?
00336   }
00337   return ret;
00338 }
00339 
00340 nsresult nsDBFolderInfo::InitFromExistingDB()
00341 {
00342   nsresult ret = NS_OK;
00343   if (m_mdb && m_mdb->GetStore())
00344   {
00345     nsIMdbStore *store = m_mdb->GetStore();
00346     if (store)
00347     {
00348       mdb_pos        rowPos;
00349       mdb_count outTableCount; // current number of such tables
00350       mdb_bool mustBeUnique; // whether port can hold only one of these
00351       mdb_bool hasOid;
00352       ret = store->GetTableKind(m_mdb->GetEnv(), m_rowScopeToken, m_tableKindToken, &outTableCount, 
00353         &mustBeUnique, &m_mdbTable);
00354       //                    NS_ASSERTION(mustBeUnique && outTableCount == 1, "only one global db info allowed");
00355       
00356       if (m_mdbTable)
00357       {
00358         // find singleton row for global info.
00359         ret = m_mdbTable->HasOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &hasOid);
00360         if (ret == NS_OK)
00361         {
00362           nsIMdbTableRowCursor *rowCursor;
00363           rowPos = -1;
00364           ret= m_mdbTable->GetTableRowCursor(m_mdb->GetEnv(), rowPos, &rowCursor);
00365           if (ret == NS_OK)
00366           {
00367             ret = rowCursor->NextRow(m_mdb->GetEnv(), &m_mdbRow, &rowPos);
00368             NS_RELEASE(rowCursor);
00369             if (!m_mdbRow)
00370               ret = NS_ERROR_FAILURE;
00371             if (ret == NS_OK)
00372               LoadMemberVariables();
00373           }
00374         }
00375       }
00376       else
00377         ret = NS_ERROR_FAILURE;
00378     }
00379   }
00380   return ret;
00381 }
00382 
00383 nsresult nsDBFolderInfo::InitMDBInfo()
00384 {
00385   nsresult ret = NS_OK;
00386   if (!m_mdbTokensInitialized && m_mdb && m_mdb->GetStore())
00387   {
00388     nsIMdbStore *store = m_mdb->GetStore();
00389     nsIMdbEnv *env = m_mdb->GetEnv();
00390     
00391     store->StringToToken(env,  kNumMessagesColumnName, &m_numMessagesColumnToken);
00392     store->StringToToken(env,  kNumUnreadMessagesColumnName, &m_numUnreadMessagesColumnToken);
00393     store->StringToToken(env,  kFlagsColumnName, &m_flagsColumnToken);
00394     store->StringToToken(env,  kFolderSizeColumnName, &m_folderSizeColumnToken);
00395     store->StringToToken(env,  kExpungedBytesColumnName, &m_expungedBytesColumnToken);
00396     store->StringToToken(env,  kFolderDateColumnName, &m_folderDateColumnToken);
00397     
00398     store->StringToToken(env,  kHighWaterMessageKeyColumnName, &m_highWaterMessageKeyColumnToken);
00399     store->StringToToken(env,  kMailboxNameColumnName, &m_mailboxNameColumnToken);
00400     
00401     store->StringToToken(env,  kImapUidValidityColumnName, &m_imapUidValidityColumnToken);
00402     store->StringToToken(env,  kTotalPendingMessagesColumnName, &m_totalPendingMessagesColumnToken);
00403     store->StringToToken(env,  kUnreadPendingMessagesColumnName, &m_unreadPendingMessagesColumnToken);
00404     store->StringToToken(env,  kExpiredMarkColumnName, &m_expiredMarkColumnToken);
00405     store->StringToToken(env,  kVersionColumnName, &m_versionColumnToken);
00406     m_mdbTokensInitialized  = PR_TRUE;
00407   }
00408   return ret;
00409 }
00410 
00411 nsresult nsDBFolderInfo::LoadMemberVariables()
00412 {
00413   nsresult ret = NS_OK;
00414   // it's really not an error for these properties to not exist...
00415   GetInt32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
00416   GetInt32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages);
00417   GetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
00418   GetInt32PropertyWithToken(m_folderSizeColumnToken, m_folderSize);
00419   GetInt32PropertyWithToken(m_folderDateColumnToken, (PRInt32 &) m_folderDate);
00420   GetInt32PropertyWithToken(m_imapUidValidityColumnToken, m_ImapUidValidity);
00421   GetInt32PropertyWithToken(m_expiredMarkColumnToken, (PRInt32 &) m_expiredMark);
00422   GetInt32PropertyWithToken(m_expungedBytesColumnToken, (PRInt32 &) m_expungedBytes);
00423   GetInt32PropertyWithToken(m_highWaterMessageKeyColumnToken, (PRInt32 &) m_highWaterMessageKey);
00424   PRInt32 version;
00425   
00426   GetInt32PropertyWithToken(m_versionColumnToken, version);
00427   m_version = (PRUint16) version;
00428   m_charSetOverride = gDefaultCharacterOverride;
00429   PRUint32 propertyValue;
00430   nsresult rv = GetUint32Property(kCharacterSetOverrideColumnName, gDefaultCharacterOverride, &propertyValue);
00431   if (NS_SUCCEEDED(rv))
00432     m_charSetOverride = propertyValue;
00433 
00434   nsXPIDLCString charSet;
00435   if (NS_SUCCEEDED(m_mdb->GetProperty(m_mdbRow, kCharacterSetColumnName, getter_Copies(charSet))))
00436     m_charSet = charSet;
00437 
00438   return ret;
00439 }
00440 
00441 NS_IMETHODIMP nsDBFolderInfo::SetVersion(PRUint32 version)
00442 {
00443        m_version = version; 
00444        return SetUint32PropertyWithToken(m_versionColumnToken, (PRUint32) m_version);
00445 }
00446 
00447 NS_IMETHODIMP nsDBFolderInfo::GetVersion(PRUint32 *version)
00448 {
00449        *version = m_version; 
00450        return NS_OK;
00451 }
00452 
00453 
00454 NS_IMETHODIMP nsDBFolderInfo::SetHighWater(nsMsgKey highWater, PRBool force)
00455 {
00456        if (force || m_highWaterMessageKey < highWater)
00457               m_highWaterMessageKey = highWater;
00458 
00459        return NS_OK;
00460 }
00461 
00462 NS_IMETHODIMP nsDBFolderInfo::SetHighWater(nsMsgKey highWater)
00463 {
00464   return SetHighWater(highWater, PR_TRUE);
00465 }
00466 
00467 
00468 NS_IMETHODIMP
00469 nsDBFolderInfo::GetFolderSize(PRUint32 *size)
00470 {
00471   if (!size) 
00472     return NS_ERROR_NULL_POINTER;
00473   *size = m_folderSize;
00474   return NS_OK;
00475 }
00476 
00477 NS_IMETHODIMP nsDBFolderInfo::SetFolderSize(PRUint32 size)
00478 {
00479   m_folderSize = size;
00480   return SetUint32PropertyWithToken(m_folderSizeColumnToken, m_folderSize);
00481 }
00482 
00483 NS_IMETHODIMP
00484 nsDBFolderInfo::GetFolderDate(PRUint32 *folderDate)
00485 {
00486   if (!folderDate) 
00487     return NS_ERROR_NULL_POINTER;
00488   *folderDate = m_folderDate;
00489   return NS_OK;
00490 }
00491 
00492 NS_IMETHODIMP nsDBFolderInfo::SetFolderDate(PRUint32 folderDate)
00493 {
00494   m_folderDate = folderDate;
00495   return SetUint32PropertyWithToken(m_folderDateColumnToken, folderDate);
00496 }
00497 
00498 
00499 NS_IMETHODIMP nsDBFolderInfo::GetHighWater(nsMsgKey *result) 
00500 {
00501   *result = m_highWaterMessageKey;
00502   return NS_OK;
00503 }
00504 
00505 NS_IMETHODIMP nsDBFolderInfo::SetExpiredMark(nsMsgKey expiredKey)
00506 {
00507   m_expiredMark = expiredKey;
00508   return SetUint32PropertyWithToken(m_expiredMarkColumnToken, expiredKey);
00509 }
00510 
00511 NS_IMETHODIMP nsDBFolderInfo::GetExpiredMark(nsMsgKey *result) 
00512 {
00513   *result = m_expiredMark;
00514   return NS_OK;
00515 }
00516 
00517 NS_IMETHODIMP
00518 nsDBFolderInfo::ChangeExpungedBytes(PRInt32 delta)
00519 {
00520     return SetExpungedBytes(m_expungedBytes + delta);
00521 }
00522 
00523 NS_IMETHODIMP nsDBFolderInfo::SetMailboxName(const nsAString &newBoxName)
00524 {
00525   return SetPropertyWithToken(m_mailboxNameColumnToken, newBoxName);
00526 }
00527 
00528 NS_IMETHODIMP nsDBFolderInfo::GetMailboxName(nsAString &boxName)
00529 {
00530   return GetPropertyWithToken(m_mailboxNameColumnToken, boxName);
00531 }
00532 
00533 NS_IMETHODIMP nsDBFolderInfo::ChangeNumUnreadMessages(PRInt32 delta)
00534 {
00535   m_numUnreadMessages += delta;
00536   // m_numUnreadMessages can never be set to negative.
00537   if (m_numUnreadMessages < 0)
00538   {
00539 #ifdef DEBUG_bienvenu1
00540      NS_ASSERTION(PR_FALSE, "Hardcoded assertion");
00541 #endif
00542       m_numUnreadMessages = 0;
00543   }
00544   return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages);
00545 }
00546 
00547 NS_IMETHODIMP nsDBFolderInfo::ChangeNumMessages(PRInt32 delta)
00548 {
00549   m_numMessages += delta;
00550   // m_numMessages can never be set to negative.
00551   if (m_numMessages < 0)
00552   {
00553 #ifdef DEBUG_bienvenu
00554     NS_ASSERTION(PR_FALSE, "num messages can't be < 0");
00555 #endif
00556     m_numMessages = 0;
00557   }
00558   return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
00559 }
00560 
00561 
00562 NS_IMETHODIMP nsDBFolderInfo::GetNumUnreadMessages(PRInt32 *result) 
00563 {
00564   *result = m_numUnreadMessages;
00565   return NS_OK;
00566 }
00567 
00568 NS_IMETHODIMP nsDBFolderInfo::SetNumUnreadMessages(PRInt32 numUnreadMessages) 
00569 {
00570   m_numUnreadMessages = numUnreadMessages;
00571   return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken, m_numUnreadMessages);
00572 }
00573 
00574 NS_IMETHODIMP nsDBFolderInfo::GetNumMessages(PRInt32 *result) 
00575 {
00576   *result = m_numMessages;
00577   return NS_OK;
00578 }
00579 
00580 NS_IMETHODIMP nsDBFolderInfo::SetNumMessages(PRInt32 numMessages) 
00581 {
00582   m_numMessages = numMessages;
00583   return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
00584 }
00585 
00586 NS_IMETHODIMP nsDBFolderInfo::GetExpungedBytes(PRInt32 *result) 
00587 {
00588   *result = m_expungedBytes;
00589   return NS_OK;
00590 }
00591 
00592 NS_IMETHODIMP nsDBFolderInfo::SetExpungedBytes(PRInt32 expungedBytes) 
00593 {
00594   m_expungedBytes = expungedBytes;
00595   return SetUint32PropertyWithToken(m_expungedBytesColumnToken, m_expungedBytes);
00596 }
00597 
00598 
00599 NS_IMETHODIMP nsDBFolderInfo::GetFlags(PRInt32 *result)
00600 {
00601   *result = m_flags;
00602   return NS_OK;
00603 }
00604 
00605 NS_IMETHODIMP nsDBFolderInfo::SetFlags(PRInt32 flags)
00606 {
00607   nsresult ret = NS_OK;
00608   
00609   if (m_flags != flags)
00610   {
00611     NS_ASSERTION((m_flags & MSG_FOLDER_FLAG_INBOX) == 0 || (flags & MSG_FOLDER_FLAG_INBOX) != 0, "lost inbox flag");
00612     m_flags = flags; 
00613     ret = SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
00614   }
00615   return ret;
00616 }
00617 
00618 NS_IMETHODIMP nsDBFolderInfo::OrFlags(PRInt32 flags, PRInt32 *result)
00619 {
00620   m_flags |= flags;
00621   *result = m_flags;
00622   return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
00623 }
00624 
00625 NS_IMETHODIMP nsDBFolderInfo::AndFlags(PRInt32 flags, PRInt32 *result)
00626 {
00627   m_flags &= flags;
00628   *result = m_flags;
00629   return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
00630 }
00631 
00632 NS_IMETHODIMP nsDBFolderInfo::GetImapUidValidity(PRInt32 *result) 
00633 {
00634   *result = m_ImapUidValidity;
00635   return NS_OK;
00636 }
00637 
00638 NS_IMETHODIMP nsDBFolderInfo::SetImapUidValidity(PRInt32 uidValidity) 
00639 {
00640   m_ImapUidValidity = uidValidity;
00641   return SetUint32PropertyWithToken(m_imapUidValidityColumnToken, m_ImapUidValidity);
00642 }
00643 
00644 PRBool nsDBFolderInfo::TestFlag(PRInt32 flags)
00645 {
00646   return (m_flags & flags) != 0;
00647 }
00648 
00649 NS_IMETHODIMP
00650 nsDBFolderInfo::GetCharacterSet(nsACString &result, PRBool *usedDefault) 
00651 {
00652   *usedDefault = PR_FALSE;
00653 
00654   nsXPIDLCString val;
00655   nsresult rv = GetCharPtrProperty(kCharacterSetColumnName, getter_Copies(val));
00656   result = val;
00657   
00658   if (NS_SUCCEEDED(rv) && result.IsEmpty())
00659   {
00660     result = gDefaultCharacterSet;
00661     *usedDefault = PR_TRUE;
00662   }
00663   
00664   return rv;
00665 }
00666 
00667 nsresult nsDBFolderInfo::GetConstCharPtrCharacterSet(const char**result)
00668 {
00669   if (!m_charSet.IsEmpty())
00670     *result = m_charSet.get();
00671   else
00672     *result = gDefaultCharacterSet;
00673   return NS_OK;
00674 }
00675 
00676 NS_IMETHODIMP
00677 nsDBFolderInfo::GetCharPtrCharacterSet(char **result)
00678 {
00679   *result = ToNewCString(m_charSet);
00680 
00681   if ((*result == nsnull || **result == '\0'))
00682   {
00683     PR_Free(*result);
00684     *result = strdup(gDefaultCharacterSet);
00685   }
00686 
00687   return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00688 }
00689 
00690 NS_IMETHODIMP nsDBFolderInfo::SetCharacterSet(const char *charSet) 
00691 {
00692   m_charSet.Assign(charSet);
00693   return SetCharPtrProperty(kCharacterSetColumnName, charSet);
00694 }
00695 
00696 NS_IMETHODIMP nsDBFolderInfo::GetCharacterSetOverride(PRBool *characterSetOverride) 
00697 {
00698   *characterSetOverride = m_charSetOverride;
00699   return NS_OK;
00700 }
00701 
00702 NS_IMETHODIMP nsDBFolderInfo::SetCharacterSetOverride(PRBool characterSetOverride) 
00703 {
00704   m_charSetOverride = characterSetOverride;
00705   return SetUint32Property(kCharacterSetOverrideColumnName, characterSetOverride);
00706 }
00707 
00708 NS_IMETHODIMP
00709 nsDBFolderInfo::GetLocale(nsAString &result) 
00710 {
00711   GetProperty(kLocaleColumnName, result);
00712   return NS_OK;
00713 }
00714 
00715 NS_IMETHODIMP nsDBFolderInfo::SetLocale(const nsAString &locale) 
00716 {
00717   return SetProperty(kLocaleColumnName, locale);
00718 }
00719 
00720 
00721 NS_IMETHODIMP nsDBFolderInfo::GetIMAPHierarchySeparator(PRUnichar *hierarchySeparator) 
00722 {
00723   if (!hierarchySeparator)
00724     return NS_ERROR_NULL_POINTER;
00725   *hierarchySeparator = m_IMAPHierarchySeparator;
00726   return NS_OK;
00727 }
00728 
00729 NS_IMETHODIMP nsDBFolderInfo::SetIMAPHierarchySeparator(PRUnichar hierarchySeparator) 
00730 {
00731   m_IMAPHierarchySeparator = hierarchySeparator; 
00732   return NS_OK;
00733 }
00734 
00735 NS_IMETHODIMP
00736 nsDBFolderInfo::GetImapTotalPendingMessages(PRInt32 *result) 
00737 {
00738   if (!result)
00739     return NS_ERROR_NULL_POINTER;
00740   *result = m_totalPendingMessages;
00741   return NS_OK;
00742 }
00743 
00744 void nsDBFolderInfo::ChangeImapTotalPendingMessages(PRInt32 delta)
00745 {
00746   m_totalPendingMessages+=delta;
00747   SetInt32PropertyWithToken(m_totalPendingMessagesColumnToken, m_totalPendingMessages);
00748 }
00749 
00750 NS_IMETHODIMP
00751 nsDBFolderInfo::GetImapUnreadPendingMessages(PRInt32 *result) 
00752 {
00753   if (!result) 
00754     return NS_ERROR_NULL_POINTER;
00755   *result = m_unreadPendingMessages;
00756   return NS_OK;
00757 }
00758 
00759 NS_IMETHODIMP nsDBFolderInfo::SetImapUnreadPendingMessages(PRInt32 numUnreadPendingMessages) 
00760 {
00761   m_unreadPendingMessages = numUnreadPendingMessages;
00762   return SetUint32PropertyWithToken(m_unreadPendingMessagesColumnToken, m_unreadPendingMessages);
00763 }
00764 
00765 NS_IMETHODIMP nsDBFolderInfo::SetImapTotalPendingMessages(PRInt32 numTotalPendingMessages) 
00766 {
00767   m_totalPendingMessages = numTotalPendingMessages;
00768   return SetUint32PropertyWithToken(m_totalPendingMessagesColumnToken, m_totalPendingMessages);
00769 }
00770 
00771 
00772 
00773 void nsDBFolderInfo::ChangeImapUnreadPendingMessages(PRInt32 delta) 
00774 {
00775   m_unreadPendingMessages+=delta;
00776   SetInt32PropertyWithToken(m_unreadPendingMessagesColumnToken, m_unreadPendingMessages);
00777 }
00778 
00779 /* attribute nsMsgViewTypeValue viewType; */
00780 NS_IMETHODIMP nsDBFolderInfo::GetViewType(nsMsgViewTypeValue *aViewType)
00781 {
00782   PRUint32 viewTypeValue;
00783   nsresult rv = GetUint32Property("viewType", nsMsgViewType::eShowAllThreads, &viewTypeValue);
00784   *aViewType = viewTypeValue;
00785   return rv;
00786 }
00787 NS_IMETHODIMP nsDBFolderInfo::SetViewType(nsMsgViewTypeValue aViewType)
00788 {
00789   return SetUint32Property("viewType", aViewType);
00790 }
00791 
00792 /* attribute nsMsgViewFlagsTypeValue viewFlags; */
00793 NS_IMETHODIMP nsDBFolderInfo::GetViewFlags(nsMsgViewFlagsTypeValue *aViewFlags)
00794 {
00795   nsMsgViewFlagsTypeValue defaultViewFlags;
00796   nsresult rv = m_mdb->GetDefaultViewFlags(&defaultViewFlags);
00797   NS_ENSURE_SUCCESS(rv,rv);
00798 
00799   PRUint32 viewFlagsValue;
00800   rv = GetUint32Property("viewFlags", defaultViewFlags, &viewFlagsValue);
00801   *aViewFlags = viewFlagsValue;
00802   return rv;
00803 }
00804 NS_IMETHODIMP nsDBFolderInfo::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)
00805 {
00806   return SetUint32Property("viewFlags", aViewFlags);
00807 }
00808 
00809 /* attribute nsMsgViewSortTypeValue sortType; */
00810 NS_IMETHODIMP nsDBFolderInfo::GetSortType(nsMsgViewSortTypeValue *aSortType)
00811 {
00812   nsMsgViewSortTypeValue defaultSortType;
00813   nsresult rv = m_mdb->GetDefaultSortType(&defaultSortType);
00814   NS_ENSURE_SUCCESS(rv,rv);
00815 
00816   PRUint32 sortTypeValue;
00817   rv = GetUint32Property("sortType", defaultSortType, &sortTypeValue);
00818   *aSortType = sortTypeValue;
00819   return rv;
00820 }
00821 NS_IMETHODIMP nsDBFolderInfo::SetSortType(nsMsgViewSortTypeValue aSortType)
00822 {
00823   return SetUint32Property("sortType", aSortType);
00824 }
00825 
00826 /* attribute nsMsgViewSortOrderValue sortOrder; */
00827 NS_IMETHODIMP nsDBFolderInfo::GetSortOrder(nsMsgViewSortOrderValue *aSortOrder)
00828 {
00829   nsMsgViewSortOrderValue defaultSortOrder;
00830   nsresult rv = m_mdb->GetDefaultSortOrder(&defaultSortOrder);
00831   NS_ENSURE_SUCCESS(rv,rv);
00832 
00833   PRUint32 sortOrderValue;
00834   rv = GetUint32Property("sortOrder", defaultSortOrder, &sortOrderValue);
00835   *aSortOrder = sortOrderValue;
00836   return rv;
00837 }
00838 
00839 NS_IMETHODIMP nsDBFolderInfo::SetSortOrder(nsMsgViewSortOrderValue aSortOrder)
00840 {
00841   return SetUint32Property("sortOrder", aSortOrder);
00842 }
00843 
00844 
00845 NS_IMETHODIMP nsDBFolderInfo::SetKnownArtsSet(const char *newsArtSet)
00846 {
00847   return m_mdb->SetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet);
00848 }
00849 
00850 NS_IMETHODIMP nsDBFolderInfo::GetKnownArtsSet(char **newsArtSet)
00851 {
00852   return m_mdb->GetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet);
00853 }
00854 
00855 // get arbitrary property, aka row cell value.
00856 NS_IMETHODIMP nsDBFolderInfo::GetProperty(const char *propertyName, nsAString &resultProperty)
00857 {
00858   return m_mdb->GetPropertyAsNSString(m_mdbRow, propertyName, resultProperty);
00859 }
00860 
00861 NS_IMETHODIMP nsDBFolderInfo::SetCharPtrProperty(const char *aPropertyName, const char *aPropertyValue)
00862 {
00863   return m_mdb->SetProperty(m_mdbRow, aPropertyName, aPropertyValue);
00864 }
00865 
00866 // Caller must PR_Free resultProperty.
00867 NS_IMETHODIMP nsDBFolderInfo::GetCharPtrProperty(const char *propertyName, char **resultProperty)
00868 {
00869   return m_mdb->GetProperty(m_mdbRow, propertyName, resultProperty);
00870 }
00871 
00872 
00873 NS_IMETHODIMP nsDBFolderInfo::SetUint32Property(const char *propertyName, PRUint32 propertyValue)
00874 {
00875   return m_mdb->SetUint32Property(m_mdbRow, propertyName, propertyValue);
00876 }
00877 
00878 NS_IMETHODIMP nsDBFolderInfo::SetProperty(const char *propertyName, const nsAString &propertyStr)
00879 {
00880   return m_mdb->SetPropertyFromNSString(m_mdbRow, propertyName, propertyStr);
00881 }
00882 
00883 nsresult nsDBFolderInfo::SetPropertyWithToken(mdb_token aProperty, const nsAString &propertyStr)
00884 {
00885   return m_mdb->SetNSStringPropertyWithToken(m_mdbRow, aProperty, propertyStr);
00886 }
00887 
00888 nsresult  nsDBFolderInfo::SetUint32PropertyWithToken(mdb_token aProperty, PRUint32 propertyValue)
00889 {
00890   return m_mdb->UInt32ToRowCellColumn(m_mdbRow, aProperty, propertyValue);
00891 }
00892 
00893 nsresult  nsDBFolderInfo::SetInt32PropertyWithToken(mdb_token aProperty, PRInt32 propertyValue)
00894 {
00895   nsAutoString propertyStr;
00896   propertyStr.AppendInt(propertyValue, 16);
00897   return SetPropertyWithToken(aProperty, propertyStr);
00898 }
00899 
00900 nsresult nsDBFolderInfo::GetPropertyWithToken(mdb_token aProperty, nsAString &resultProperty)
00901 {
00902   return m_mdb->RowCellColumnTonsString(m_mdbRow, aProperty, resultProperty);
00903 }
00904 
00905 nsresult nsDBFolderInfo::GetUint32PropertyWithToken(mdb_token aProperty, PRUint32 &propertyValue, PRUint32 defaultValue)
00906 {
00907   return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty, propertyValue, defaultValue);
00908 }
00909 
00910 nsresult nsDBFolderInfo::GetInt32PropertyWithToken(mdb_token aProperty, PRInt32 &propertyValue, PRInt32 defaultValue)
00911 {
00912   return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty, (PRUint32 &) propertyValue, defaultValue);
00913 }
00914 
00915 NS_IMETHODIMP nsDBFolderInfo::GetUint32Property(const char *propertyName, PRUint32 defaultValue, PRUint32 *propertyValue)
00916 {
00917   return m_mdb->GetUint32Property(m_mdbRow, propertyName, propertyValue, defaultValue);
00918 }
00919 
00920 NS_IMETHODIMP nsDBFolderInfo::GetBooleanProperty(const char *propertyName, PRBool defaultValue, PRBool *propertyValue)
00921 {
00922   PRUint32 defaultUint32Value = (defaultValue) ? 1 : 0;
00923   PRUint32 returnValue;
00924   nsresult rv = m_mdb->GetUint32Property(m_mdbRow, propertyName, &returnValue, defaultUint32Value);
00925   *propertyValue = (returnValue != 0);
00926   return rv;
00927 }
00928 NS_IMETHODIMP nsDBFolderInfo::SetBooleanProperty(const char *propertyName, PRBool propertyValue)
00929 {
00930   return m_mdb->SetUint32Property(m_mdbRow, propertyName, propertyValue ? 1 : 0);
00931 }
00932 
00933 NS_IMETHODIMP nsDBFolderInfo::GetFolderName(char **folderName)
00934 {
00935   return GetCharPtrProperty("folderName", folderName);
00936 }
00937 
00938 NS_IMETHODIMP nsDBFolderInfo::SetFolderName(const char *folderName)
00939 {
00940   return SetCharPtrProperty("folderName", folderName);
00941 }
00942 
00943 class nsTransferDBFolderInfo : public nsDBFolderInfo
00944 {
00945 public:
00946   nsTransferDBFolderInfo();
00947   virtual ~nsTransferDBFolderInfo();
00948   // parallel arrays of properties and values
00949   nsCStringArray m_properties;
00950   nsCStringArray m_values;
00951 };
00952 
00953 nsTransferDBFolderInfo::nsTransferDBFolderInfo() : nsDBFolderInfo(nsnull)
00954 {
00955 }
00956 
00957 nsTransferDBFolderInfo::~nsTransferDBFolderInfo()
00958 {
00959 }
00960 
00961 /* void GetTransferInfo (out nsIDBFolderInfo transferInfo); */
00962 NS_IMETHODIMP nsDBFolderInfo::GetTransferInfo(nsIDBFolderInfo **transferInfo)
00963 {
00964   NS_ENSURE_ARG_POINTER(transferInfo);
00965 
00966   nsTransferDBFolderInfo *newInfo = new nsTransferDBFolderInfo;
00967   *transferInfo = newInfo;
00968   NS_ADDREF(newInfo);
00969   
00970   mdb_count numCells;
00971   mdbYarn cellYarn;
00972   mdb_column cellColumn;
00973   char columnName[100];
00974   mdbYarn cellName = { columnName, 0, sizeof(columnName), 0, 0, nsnull };
00975 
00976   NS_ASSERTION(m_mdbRow, "null row in getTransferInfo");
00977   m_mdbRow->GetCount(m_mdb->GetEnv(), &numCells);
00978   // iterate over the cells in the dbfolderinfo remembering attribute names and values.
00979   for (mdb_count cellIndex = 0; cellIndex < numCells; cellIndex++)
00980   {
00981     mdb_err err = m_mdbRow->SeekCellYarn(m_mdb->GetEnv(), cellIndex, &cellColumn, nsnull);
00982     if (!err)
00983     {
00984       err = m_mdbRow->AliasCellYarn(m_mdb->GetEnv(), cellColumn, &cellYarn);
00985       if (!err)
00986       {
00987         m_mdb->GetStore()->TokenToString(m_mdb->GetEnv(), cellColumn, &cellName);
00988         newInfo->m_values.AppendCString(Substring((const char *)cellYarn.mYarn_Buf, 
00989                                           (const char *) cellYarn.mYarn_Buf + cellYarn.mYarn_Fill));
00990         newInfo->m_properties.AppendCString(Substring((const char *) cellName.mYarn_Buf, 
00991                                           (const char *) cellName.mYarn_Buf + cellName.mYarn_Fill));
00992       }
00993     }
00994   }
00995   
00996   return NS_OK;
00997 }
00998 
00999 
01000 /* void InitFromTransferInfo (in nsIDBFolderInfo transferInfo); */
01001 NS_IMETHODIMP nsDBFolderInfo::InitFromTransferInfo(nsIDBFolderInfo *aTransferInfo)
01002 {
01003   NS_ENSURE_ARG(aTransferInfo);
01004 
01005   nsTransferDBFolderInfo *transferInfo = NS_STATIC_CAST(nsTransferDBFolderInfo *, aTransferInfo);
01006 
01007   for (PRInt32 i = 0; i < transferInfo->m_values.Count(); i++)
01008     SetCharPtrProperty(transferInfo->m_properties[i]->get(), transferInfo->m_values[i]->get());
01009 
01010   LoadMemberVariables();
01011   return NS_OK;
01012 }
01013