Back to index

lightning-sunbird  0.9+nobinonly
nsMsgFolderDataSource.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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  *   David Bienvenu <bienvenu@nventure.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "msgCore.h"    // precompiled header...
00041 #include "prlog.h"
00042 
00043 #include "nsMsgFolderDataSource.h"
00044 #include "nsMsgFolderFlags.h"
00045 
00046 #include "nsMsgRDFUtils.h"
00047 
00048 #include "rdf.h"
00049 #include "nsIRDFService.h"
00050 #include "nsRDFCID.h"
00051 #include "nsIRDFNode.h"
00052 #include "nsEnumeratorUtils.h"
00053 #include "nsAdapterEnumerator.h"
00054 
00055 #include "nsString.h"
00056 #include "nsCOMPtr.h"
00057 #include "nsXPIDLString.h"
00058 #include "nsReadableUtils.h"
00059 
00060 #include "nsIMsgMailSession.h"
00061 #include "nsIMsgCopyService.h"
00062 #include "nsMsgBaseCID.h"
00063 #include "nsIInputStream.h"
00064 #include "nsIMsgHdr.h"
00065 #include "nsTraceRefcnt.h"
00066 #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
00067 #include "nsArray.h"
00068 #include "nsIPop3IncomingServer.h"
00069 #include "nsINntpIncomingServer.h"
00070 #include "nsTextFormatter.h"
00071 #include "nsIStringBundle.h"
00072 #include "nsIPrompt.h"
00073 #include "nsIMsgAccountManager.h"
00074 
00075 #define MESSENGER_STRING_URL       "chrome://messenger/locale/messenger.properties"
00076 
00077 nsIRDFResource* nsMsgFolderDataSource::kNC_Child = nsnull;
00078 nsIRDFResource* nsMsgFolderDataSource::kNC_Folder= nsnull;
00079 nsIRDFResource* nsMsgFolderDataSource::kNC_Name= nsnull;
00080 nsIRDFResource* nsMsgFolderDataSource::kNC_Open = nsnull;
00081 nsIRDFResource* nsMsgFolderDataSource::kNC_FolderTreeName= nsnull;
00082 nsIRDFResource* nsMsgFolderDataSource::kNC_FolderTreeSimpleName= nsnull;
00083 nsIRDFResource* nsMsgFolderDataSource::kNC_NameSort= nsnull;
00084 nsIRDFResource* nsMsgFolderDataSource::kNC_FolderTreeNameSort= nsnull;
00085 nsIRDFResource* nsMsgFolderDataSource::kNC_SpecialFolder= nsnull;
00086 nsIRDFResource* nsMsgFolderDataSource::kNC_ServerType = nsnull;
00087 nsIRDFResource* nsMsgFolderDataSource::kNC_IsDeferred = nsnull;
00088 nsIRDFResource* nsMsgFolderDataSource::kNC_RedirectorType = nsnull;
00089 nsIRDFResource* nsMsgFolderDataSource::kNC_CanCreateFoldersOnServer = nsnull;
00090 nsIRDFResource* nsMsgFolderDataSource::kNC_CanFileMessagesOnServer = nsnull;
00091 nsIRDFResource* nsMsgFolderDataSource::kNC_IsServer = nsnull;
00092 nsIRDFResource* nsMsgFolderDataSource::kNC_IsSecure = nsnull;
00093 nsIRDFResource* nsMsgFolderDataSource::kNC_CanSubscribe = nsnull;
00094 nsIRDFResource* nsMsgFolderDataSource::kNC_SupportsOffline = nsnull;
00095 nsIRDFResource* nsMsgFolderDataSource::kNC_CanFileMessages = nsnull;
00096 nsIRDFResource* nsMsgFolderDataSource::kNC_CanCreateSubfolders = nsnull;
00097 nsIRDFResource* nsMsgFolderDataSource::kNC_CanRename = nsnull;
00098 nsIRDFResource* nsMsgFolderDataSource::kNC_CanCompact = nsnull;
00099 nsIRDFResource* nsMsgFolderDataSource::kNC_TotalMessages= nsnull;
00100 nsIRDFResource* nsMsgFolderDataSource::kNC_TotalUnreadMessages= nsnull;
00101 nsIRDFResource* nsMsgFolderDataSource::kNC_FolderSize = nsnull;
00102 nsIRDFResource* nsMsgFolderDataSource::kNC_Charset = nsnull;
00103 nsIRDFResource* nsMsgFolderDataSource::kNC_BiffState = nsnull;
00104 nsIRDFResource* nsMsgFolderDataSource::kNC_HasUnreadMessages = nsnull;
00105 nsIRDFResource* nsMsgFolderDataSource::kNC_NewMessages = nsnull;
00106 nsIRDFResource* nsMsgFolderDataSource::kNC_SubfoldersHaveUnreadMessages = nsnull;
00107 nsIRDFResource* nsMsgFolderDataSource::kNC_NoSelect = nsnull;
00108 nsIRDFResource* nsMsgFolderDataSource::kNC_VirtualFolder = nsnull;
00109 nsIRDFResource* nsMsgFolderDataSource::kNC_InVFEditSearchScope = nsnull; 
00110 nsIRDFResource* nsMsgFolderDataSource::kNC_ImapShared = nsnull;
00111 nsIRDFResource* nsMsgFolderDataSource::kNC_Synchronize = nsnull;
00112 nsIRDFResource* nsMsgFolderDataSource::kNC_SyncDisabled = nsnull;
00113 nsIRDFResource* nsMsgFolderDataSource::kNC_CanSearchMessages = nsnull;
00114 nsIRDFResource* nsMsgFolderDataSource::kNC_UnreadFolders = nsnull;
00115 nsIRDFResource* nsMsgFolderDataSource::kNC_FavoriteFolders = nsnull;
00116 nsIRDFResource* nsMsgFolderDataSource::kNC_RecentFolders = nsnull;
00117 
00118 // commands
00119 nsIRDFResource* nsMsgFolderDataSource::kNC_Delete= nsnull;
00120 nsIRDFResource* nsMsgFolderDataSource::kNC_ReallyDelete= nsnull;
00121 nsIRDFResource* nsMsgFolderDataSource::kNC_NewFolder= nsnull;
00122 nsIRDFResource* nsMsgFolderDataSource::kNC_GetNewMessages= nsnull;
00123 nsIRDFResource* nsMsgFolderDataSource::kNC_Copy= nsnull;
00124 nsIRDFResource* nsMsgFolderDataSource::kNC_Move= nsnull;
00125 nsIRDFResource* nsMsgFolderDataSource::kNC_CopyFolder= nsnull;
00126 nsIRDFResource* nsMsgFolderDataSource::kNC_MoveFolder= nsnull;
00127 nsIRDFResource* nsMsgFolderDataSource::kNC_MarkAllMessagesRead= nsnull;
00128 nsIRDFResource* nsMsgFolderDataSource::kNC_Compact= nsnull;
00129 nsIRDFResource* nsMsgFolderDataSource::kNC_CompactAll= nsnull;
00130 nsIRDFResource* nsMsgFolderDataSource::kNC_Rename= nsnull;
00131 nsIRDFResource* nsMsgFolderDataSource::kNC_EmptyTrash= nsnull;
00132 nsIRDFResource* nsMsgFolderDataSource::kNC_DownloadFlagged= nsnull;
00133 
00134 nsrefcnt nsMsgFolderDataSource::gFolderResourceRefCnt = 0;
00135 
00136 nsIAtom * nsMsgFolderDataSource::kBiffStateAtom = nsnull;
00137 nsIAtom * nsMsgFolderDataSource::kNewMessagesAtom = nsnull;
00138 nsIAtom * nsMsgFolderDataSource::kTotalMessagesAtom = nsnull;
00139 nsIAtom * nsMsgFolderDataSource::kTotalUnreadMessagesAtom = nsnull;
00140 nsIAtom * nsMsgFolderDataSource::kFolderSizeAtom = nsnull;
00141 nsIAtom * nsMsgFolderDataSource::kNameAtom = nsnull;
00142 nsIAtom * nsMsgFolderDataSource::kSynchronizeAtom = nsnull;
00143 nsIAtom * nsMsgFolderDataSource::kOpenAtom = nsnull;
00144 nsIAtom * nsMsgFolderDataSource::kIsDeferredAtom = nsnull;
00145 nsIAtom * nsMsgFolderDataSource::kCanFileMessagesAtom = nsnull;
00146 nsIAtom * nsMsgFolderDataSource::kInVFEditSearchScopeAtom = nsnull;
00147 
00148 PRUnichar * nsMsgFolderDataSource::kKiloByteString = nsnull;
00149 PRUnichar * nsMsgFolderDataSource::kMegaByteString = nsnull;
00150 
00151 static const PRUint32 kDisplayBlankCount = 0xFFFFFFFE;
00152 static const PRUint32 kDisplayQuestionCount = 0xFFFFFFFF;
00153 
00154 nsMsgFolderDataSource::nsMsgFolderDataSource()
00155 {
00156   // one-time initialization here
00157   nsIRDFService* rdf = getRDFService();
00158   
00159   if (gFolderResourceRefCnt++ == 0) {
00160     nsresult res = NS_OK;
00161     nsCOMPtr<nsIStringBundle> sMessengerStringBundle;
00162 
00163     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CHILD),   &kNC_Child);
00164     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDER),  &kNC_Folder);
00165     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NAME),    &kNC_Name);
00166     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_OPEN),    &kNC_Open);
00167     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREENAME),    &kNC_FolderTreeName);
00168     rdf->GetResource(NS_LITERAL_CSTRING("mailnewsunreadfolders:/"),    &kNC_UnreadFolders);
00169     rdf->GetResource(NS_LITERAL_CSTRING("mailnewsfavefolders:/"),    &kNC_FavoriteFolders);
00170     rdf->GetResource(NS_LITERAL_CSTRING("mailnewsrecentfolders:/"),    &kNC_RecentFolders);
00171 
00172     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREESIMPLENAME),    &kNC_FolderTreeSimpleName);
00173     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NAME_SORT),    &kNC_NameSort);
00174     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREENAME_SORT),    &kNC_FolderTreeNameSort);
00175     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SPECIALFOLDER), &kNC_SpecialFolder);
00176     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SERVERTYPE), &kNC_ServerType);
00177     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_ISDEFERRED),&kNC_IsDeferred);
00178     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_REDIRECTORTYPE), &kNC_RedirectorType);
00179     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANCREATEFOLDERSONSERVER), &kNC_CanCreateFoldersOnServer);
00180     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANFILEMESSAGESONSERVER), &kNC_CanFileMessagesOnServer);
00181     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_ISSERVER), &kNC_IsServer);
00182     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_ISSECURE), &kNC_IsSecure);
00183     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANSUBSCRIBE), &kNC_CanSubscribe);
00184     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SUPPORTSOFFLINE), &kNC_SupportsOffline);
00185     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANFILEMESSAGES), &kNC_CanFileMessages);
00186     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANCREATESUBFOLDERS), &kNC_CanCreateSubfolders);
00187     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANRENAME), &kNC_CanRename);
00188     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANCOMPACT), &kNC_CanCompact);
00189     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_TOTALMESSAGES), &kNC_TotalMessages);
00190     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_TOTALUNREADMESSAGES), &kNC_TotalUnreadMessages);
00191     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERSIZE), &kNC_FolderSize);
00192     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CHARSET), &kNC_Charset);
00193     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_BIFFSTATE), &kNC_BiffState);
00194     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_HASUNREADMESSAGES), &kNC_HasUnreadMessages);
00195     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NEWMESSAGES), &kNC_NewMessages);
00196     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SUBFOLDERSHAVEUNREADMESSAGES), &kNC_SubfoldersHaveUnreadMessages);
00197     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NOSELECT), &kNC_NoSelect);
00198     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_VIRTUALFOLDER), &kNC_VirtualFolder);
00199     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_INVFEDITSEARCHSCOPE), &kNC_InVFEditSearchScope);    
00200     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_IMAPSHARED), &kNC_ImapShared);
00201     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SYNCHRONIZE), &kNC_Synchronize);
00202     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_SYNCDISABLED), &kNC_SyncDisabled);
00203     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANSEARCHMESSAGES), &kNC_CanSearchMessages);
00204     
00205     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_DELETE), &kNC_Delete);
00206     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_REALLY_DELETE), &kNC_ReallyDelete);
00207     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_NEWFOLDER), &kNC_NewFolder);
00208     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_GETNEWMESSAGES), &kNC_GetNewMessages);
00209     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_COPY), &kNC_Copy);
00210     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_MOVE), &kNC_Move);
00211     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_COPYFOLDER), &kNC_CopyFolder);
00212     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_MOVEFOLDER), &kNC_MoveFolder);
00213     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_MARKALLMESSAGESREAD),
00214                              &kNC_MarkAllMessagesRead);
00215     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_COMPACT), &kNC_Compact);
00216     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_COMPACTALL), &kNC_CompactAll);
00217     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_RENAME), &kNC_Rename);
00218     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_EMPTYTRASH), &kNC_EmptyTrash);
00219     rdf->GetResource(NS_LITERAL_CSTRING(NC_RDF_DOWNLOADFLAGGED), &kNC_DownloadFlagged);
00220 
00221     kTotalMessagesAtom           = NS_NewAtom("TotalMessages");
00222     kTotalUnreadMessagesAtom     = NS_NewAtom("TotalUnreadMessages");
00223     kFolderSizeAtom              = NS_NewAtom("FolderSize");
00224     kBiffStateAtom               = NS_NewAtom("BiffState");
00225     kNewMessagesAtom             = NS_NewAtom("NewMessages");
00226     kNameAtom                    = NS_NewAtom("Name");
00227     kSynchronizeAtom             = NS_NewAtom("Synchronize");
00228     kOpenAtom                    = NS_NewAtom("open");
00229     kIsDeferredAtom              = NS_NewAtom("isDeferred");
00230     kCanFileMessagesAtom         = NS_NewAtom("canFileMessages");
00231     kInVFEditSearchScopeAtom     = NS_NewAtom("inVFEditSearchScope");
00232 
00233     nsCOMPtr<nsIStringBundleService> sBundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &res);
00234 
00235     if (NS_SUCCEEDED(res) && sBundleService) 
00236       res = sBundleService->CreateBundle(MESSENGER_STRING_URL, getter_AddRefs(sMessengerStringBundle));
00237 
00238     if (NS_SUCCEEDED(res) && sMessengerStringBundle)
00239     {
00240       if (!NS_SUCCEEDED(sMessengerStringBundle->GetStringFromName(NS_LITERAL_STRING("kiloByteAbbreviation").get(), &kKiloByteString)))
00241         kKiloByteString = ToNewUnicode(NS_LITERAL_STRING("kiloByteAbbreviation"));
00242 
00243       if (!NS_SUCCEEDED(sMessengerStringBundle->GetStringFromName(NS_LITERAL_STRING("megaByteAbbreviation").get(), &kMegaByteString)))
00244         kMegaByteString = ToNewUnicode(NS_LITERAL_STRING("megaByteAbbreviation"));
00245     }
00246   }
00247   
00248   CreateLiterals(rdf);
00249   CreateArcsOutEnumerator();
00250 }
00251 
00252 nsMsgFolderDataSource::~nsMsgFolderDataSource (void)
00253 {
00254   if (--gFolderResourceRefCnt == 0)
00255   {
00256     nsrefcnt refcnt;
00257     NS_RELEASE2(kNC_Child, refcnt);
00258     NS_RELEASE2(kNC_Folder, refcnt);
00259     NS_RELEASE2(kNC_Name, refcnt);
00260     NS_RELEASE2(kNC_Open, refcnt);
00261     NS_RELEASE2(kNC_FolderTreeName, refcnt);
00262     NS_RELEASE2(kNC_FolderTreeSimpleName, refcnt);
00263     NS_RELEASE2(kNC_NameSort, refcnt);
00264     NS_RELEASE2(kNC_FolderTreeNameSort, refcnt);
00265     NS_RELEASE2(kNC_SpecialFolder, refcnt);
00266     NS_RELEASE2(kNC_ServerType, refcnt);
00267     NS_RELEASE2(kNC_IsDeferred, refcnt);
00268     NS_RELEASE2(kNC_RedirectorType, refcnt);
00269     NS_RELEASE2(kNC_CanCreateFoldersOnServer, refcnt);
00270     NS_RELEASE2(kNC_CanFileMessagesOnServer, refcnt);
00271     NS_RELEASE2(kNC_IsServer, refcnt);
00272     NS_RELEASE2(kNC_IsSecure, refcnt);
00273     NS_RELEASE2(kNC_CanSubscribe, refcnt);
00274     NS_RELEASE2(kNC_SupportsOffline, refcnt);
00275     NS_RELEASE2(kNC_CanFileMessages, refcnt);
00276     NS_RELEASE2(kNC_CanCreateSubfolders, refcnt);
00277     NS_RELEASE2(kNC_CanRename, refcnt);
00278     NS_RELEASE2(kNC_CanCompact, refcnt);
00279     NS_RELEASE2(kNC_TotalMessages, refcnt);
00280     NS_RELEASE2(kNC_TotalUnreadMessages, refcnt);
00281     NS_RELEASE2(kNC_FolderSize, refcnt);
00282     NS_RELEASE2(kNC_Charset, refcnt);
00283     NS_RELEASE2(kNC_BiffState, refcnt);
00284     NS_RELEASE2(kNC_HasUnreadMessages, refcnt);
00285     NS_RELEASE2(kNC_NewMessages, refcnt);
00286     NS_RELEASE2(kNC_SubfoldersHaveUnreadMessages, refcnt);
00287     NS_RELEASE2(kNC_NoSelect, refcnt);
00288     NS_RELEASE2(kNC_VirtualFolder, refcnt);
00289     NS_RELEASE2(kNC_InVFEditSearchScope, refcnt);
00290     NS_RELEASE2(kNC_ImapShared, refcnt);
00291     NS_RELEASE2(kNC_Synchronize, refcnt);
00292     NS_RELEASE2(kNC_SyncDisabled, refcnt);
00293     NS_RELEASE2(kNC_CanSearchMessages, refcnt);
00294     
00295     NS_RELEASE2(kNC_Delete, refcnt);
00296     NS_RELEASE2(kNC_ReallyDelete, refcnt);
00297     NS_RELEASE2(kNC_NewFolder, refcnt);
00298     NS_RELEASE2(kNC_GetNewMessages, refcnt);
00299     NS_RELEASE2(kNC_Copy, refcnt);
00300     NS_RELEASE2(kNC_Move, refcnt);
00301     NS_RELEASE2(kNC_CopyFolder, refcnt);
00302     NS_RELEASE2(kNC_MoveFolder, refcnt);
00303     NS_RELEASE2(kNC_MarkAllMessagesRead, refcnt);
00304     NS_RELEASE2(kNC_Compact, refcnt);
00305     NS_RELEASE2(kNC_CompactAll, refcnt);
00306     NS_RELEASE2(kNC_Rename, refcnt);
00307     NS_RELEASE2(kNC_EmptyTrash, refcnt);
00308     NS_RELEASE2(kNC_DownloadFlagged, refcnt);
00309     NS_RELEASE2(kNC_UnreadFolders, refcnt);
00310     NS_RELEASE2(kNC_FavoriteFolders, refcnt);
00311     NS_RELEASE2(kNC_RecentFolders, refcnt);
00312 
00313     NS_RELEASE(kTotalMessagesAtom);
00314     NS_RELEASE(kTotalUnreadMessagesAtom);
00315     NS_RELEASE(kFolderSizeAtom);
00316     NS_RELEASE(kBiffStateAtom);
00317     NS_RELEASE(kNewMessagesAtom);
00318     NS_RELEASE(kNameAtom);
00319     NS_RELEASE(kSynchronizeAtom);
00320     NS_RELEASE(kOpenAtom);
00321     NS_RELEASE(kIsDeferredAtom);
00322     NS_RELEASE(kCanFileMessagesAtom);
00323     NS_RELEASE(kInVFEditSearchScopeAtom);
00324 
00325     nsMemory::Free(kKiloByteString);
00326     nsMemory::Free(kMegaByteString);
00327   }
00328 }
00329 
00330 nsresult nsMsgFolderDataSource::CreateLiterals(nsIRDFService *rdf)
00331 {
00332   createNode(NS_LITERAL_STRING("true").get(),
00333     getter_AddRefs(kTrueLiteral), rdf);
00334   createNode(NS_LITERAL_STRING("false").get(),
00335     getter_AddRefs(kFalseLiteral), rdf);
00336 
00337   return NS_OK;
00338 }
00339 
00340 nsresult nsMsgFolderDataSource::Init()
00341 {
00342   nsresult rv;
00343   
00344   rv = nsMsgRDFDataSource::Init();
00345   if (NS_FAILED(rv))
00346     return rv;
00347 
00348   nsCOMPtr<nsIMsgMailSession> mailSession = 
00349     do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); 
00350 
00351   if(NS_SUCCEEDED(rv))
00352     mailSession->AddFolderListener(this, 
00353       nsIFolderListener::added |
00354       nsIFolderListener::removed |
00355       nsIFolderListener::intPropertyChanged |
00356       nsIFolderListener::boolPropertyChanged |
00357       nsIFolderListener::unicharPropertyChanged);
00358 
00359   return NS_OK;
00360 }
00361 
00362 void nsMsgFolderDataSource::Cleanup()
00363 {
00364   nsresult rv;
00365   if (!m_shuttingDown)
00366   {
00367     nsCOMPtr<nsIMsgMailSession> mailSession =
00368       do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
00369     
00370     if(NS_SUCCEEDED(rv))
00371       mailSession->RemoveFolderListener(this);
00372   }
00373   
00374   nsMsgRDFDataSource::Cleanup();
00375 }
00376 
00377 nsresult nsMsgFolderDataSource::CreateArcsOutEnumerator()
00378 {
00379   nsresult rv;
00380 
00381   rv = getFolderArcLabelsOut(getter_AddRefs(kFolderArcsOutArray));
00382   if(NS_FAILED(rv)) return rv;
00383 
00384   return rv;
00385 }
00386 
00387 NS_IMPL_ADDREF_INHERITED(nsMsgFolderDataSource, nsMsgRDFDataSource)
00388 NS_IMPL_RELEASE_INHERITED(nsMsgFolderDataSource, nsMsgRDFDataSource)
00389 
00390 NS_IMETHODIMP
00391 nsMsgFolderDataSource::QueryInterface(REFNSIID iid, void** result)
00392 {
00393   if (! result)
00394     return NS_ERROR_NULL_POINTER;
00395   
00396   *result = nsnull;
00397   if(iid.Equals(NS_GET_IID(nsIFolderListener)))
00398   {
00399     *result = NS_STATIC_CAST(nsIFolderListener*, this);
00400     NS_ADDREF(this);
00401     return NS_OK;
00402   }
00403   else
00404     return nsMsgRDFDataSource::QueryInterface(iid, result);
00405 }
00406 
00407  // nsIRDFDataSource methods
00408 NS_IMETHODIMP nsMsgFolderDataSource::GetURI(char* *uri)
00409 {
00410   if ((*uri = nsCRT::strdup("rdf:mailnewsfolders")) == nsnull)
00411     return NS_ERROR_OUT_OF_MEMORY;
00412   else
00413     return NS_OK;
00414 }
00415 
00416 NS_IMETHODIMP nsMsgFolderDataSource::GetSource(nsIRDFResource* property,
00417                                                nsIRDFNode* target,
00418                                                PRBool tv,
00419                                                nsIRDFResource** source /* out */)
00420 {
00421   NS_ASSERTION(PR_FALSE, "not implemented");
00422   return NS_ERROR_NOT_IMPLEMENTED;
00423 }
00424 
00425 NS_IMETHODIMP nsMsgFolderDataSource::GetTarget(nsIRDFResource* source,
00426                                                nsIRDFResource* property,
00427                                                PRBool tv,
00428                                                nsIRDFNode** target)
00429 {
00430   nsresult rv = NS_RDF_NO_VALUE;
00431 
00432   // we only have positive assertions in the mail data source.
00433   if (! tv)
00434     return NS_RDF_NO_VALUE;
00435 
00436   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source));
00437   if (folder) 
00438   {
00439     rv = createFolderNode(folder, property, target);
00440 #if 0
00441     nsXPIDLCString srcval;
00442     nsXPIDLCString propval;
00443     nsXPIDLCString targetval;
00444     source->GetValue(getter_Copies(srcval));
00445     property->GetValue(getter_Copies(propval));
00446     //    (*target)->GetValue(getter_Copies(targetval));
00447 
00448     printf("nsMsgFolderDataSource::GetTarget(%s, %s, %s, (%s))\n",
00449            (const char*)srcval,
00450            (const char*)propval, tv ? "TRUE" : "FALSE",
00451            (const char*)"");
00452 #endif
00453     
00454   }
00455   else
00456     return NS_RDF_NO_VALUE;
00457   return rv;
00458 }
00459 
00460 
00461 NS_IMETHODIMP nsMsgFolderDataSource::GetSources(nsIRDFResource* property,
00462                                                 nsIRDFNode* target,
00463                                                 PRBool tv,
00464                                                 nsISimpleEnumerator** sources)
00465 {
00466   return NS_RDF_NO_VALUE;
00467 }
00468 
00469 NS_IMETHODIMP nsMsgFolderDataSource::GetTargets(nsIRDFResource* source,
00470                                                 nsIRDFResource* property,    
00471                                                 PRBool tv,
00472                                                 nsISimpleEnumerator** targets)
00473 {
00474   nsresult rv = NS_RDF_NO_VALUE;
00475   if(!targets)
00476     return NS_ERROR_NULL_POINTER;
00477   
00478 #if 0
00479   nsXPIDLCString srcval;
00480   nsXPIDLCString propval;
00481   nsXPIDLCString targetval;
00482   source->GetValue(getter_Copies(srcval));
00483   property->GetValue(getter_Copies(propval));
00484   //    (*target)->GetValue(getter_Copies(targetval));
00485   
00486   printf("nsMsgFolderDataSource::GetTargets(%s, %s, %s, (%s))\n",
00487     (const char*)srcval,
00488     (const char*)propval, tv ? "TRUE" : "FALSE",
00489     (const char*)"");
00490 #endif
00491   *targets = nsnull;
00492   
00493   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00494   if (NS_SUCCEEDED(rv))
00495   {
00496     if ((kNC_Child == property))
00497     {
00498       nsCOMPtr<nsIEnumerator> subFolders;
00499       rv = folder->GetSubFolders(getter_AddRefs(subFolders));
00500       if(NS_SUCCEEDED(rv))
00501       {
00502         nsAdapterEnumerator* cursor =
00503           new nsAdapterEnumerator(subFolders);
00504         if (cursor == nsnull)
00505           return NS_ERROR_OUT_OF_MEMORY;
00506         NS_ADDREF(cursor);
00507         *targets = cursor;
00508         rv = NS_OK;
00509       }
00510     }
00511     else if ((kNC_Name == property) ||
00512       (kNC_Open == property) ||
00513       (kNC_FolderTreeName == property) ||
00514       (kNC_FolderTreeSimpleName == property) ||
00515       (kNC_SpecialFolder == property) ||
00516       (kNC_IsServer == property) ||
00517       (kNC_IsSecure == property) ||
00518       (kNC_CanSubscribe == property) ||
00519       (kNC_SupportsOffline == property) ||
00520       (kNC_CanFileMessages == property) ||
00521       (kNC_CanCreateSubfolders == property) ||
00522       (kNC_CanRename == property) ||
00523       (kNC_CanCompact == property) ||
00524       (kNC_ServerType == property) ||
00525       (kNC_IsDeferred == property) ||
00526       (kNC_RedirectorType == property) ||
00527       (kNC_CanCreateFoldersOnServer == property) ||
00528       (kNC_CanFileMessagesOnServer == property) ||
00529       (kNC_NoSelect == property) ||
00530       (kNC_VirtualFolder == property) ||
00531       (kNC_InVFEditSearchScope == property) ||
00532       (kNC_ImapShared == property) ||
00533       (kNC_Synchronize == property) ||
00534       (kNC_SyncDisabled == property) ||
00535       (kNC_CanSearchMessages == property))
00536     {
00537       nsSingletonEnumerator* cursor =
00538         new nsSingletonEnumerator(property);
00539       if (cursor == nsnull)
00540         return NS_ERROR_OUT_OF_MEMORY;
00541       NS_ADDREF(cursor);
00542       *targets = cursor;
00543       rv = NS_OK;
00544     }
00545   }
00546   if(!*targets)
00547   {
00548     //create empty cursor
00549     rv = NS_NewEmptyEnumerator(targets);
00550   }
00551   
00552   return rv;
00553 }
00554 
00555 NS_IMETHODIMP nsMsgFolderDataSource::Assert(nsIRDFResource* source,
00556                       nsIRDFResource* property, 
00557                       nsIRDFNode* target,
00558                       PRBool tv)
00559 {
00560   nsresult rv;
00561   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00562   //We don't handle tv = PR_FALSE at the moment.
00563   if(NS_SUCCEEDED(rv) && tv)
00564     return DoFolderAssert(folder, property, target);
00565   return NS_ERROR_FAILURE;
00566 }
00567 
00568 NS_IMETHODIMP nsMsgFolderDataSource::Unassert(nsIRDFResource* source,
00569                         nsIRDFResource* property,
00570                         nsIRDFNode* target)
00571 {
00572   nsresult rv;
00573   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00574   NS_ENSURE_SUCCESS(rv,rv);
00575   return DoFolderUnassert(folder, property, target);
00576 }
00577 
00578 
00579 NS_IMETHODIMP nsMsgFolderDataSource::HasAssertion(nsIRDFResource* source,
00580                             nsIRDFResource* property,
00581                             nsIRDFNode* target,
00582                             PRBool tv,
00583                             PRBool* hasAssertion)
00584 {
00585   nsresult rv;
00586 #if 0
00587   nsXPIDLCString sourceval;
00588   nsXPIDLCString propval;
00589   nsXPIDLCString targetval;
00590   source->GetValue(getter_Copies(sourceval));
00591   property->GetValue(getter_Copies(propval));
00592   /*  target->GetValue(getter_Copies(targetval)); */
00593   printf("HasAssertion(%s, %s, ??...)\n", (const char*)sourceval, (const char*)propval);
00594 #endif
00595   
00596   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00597   if(NS_SUCCEEDED(rv))
00598     return DoFolderHasAssertion(folder, property, target, tv, hasAssertion);
00599   else
00600     *hasAssertion = PR_FALSE;
00601   return NS_OK;
00602 }
00603 
00604 
00605 NS_IMETHODIMP 
00606 nsMsgFolderDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, PRBool *result)
00607 {
00608   nsresult rv;
00609   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(aSource, &rv));
00610   if (NS_SUCCEEDED(rv)) 
00611   {
00612     *result = (aArc == kNC_Name ||
00613       aArc == kNC_Open ||
00614       aArc == kNC_FolderTreeName ||
00615       aArc == kNC_FolderTreeSimpleName ||
00616       aArc == kNC_SpecialFolder ||
00617       aArc == kNC_ServerType ||
00618       aArc == kNC_IsDeferred ||
00619       aArc == kNC_RedirectorType ||
00620       aArc == kNC_CanCreateFoldersOnServer ||
00621       aArc == kNC_CanFileMessagesOnServer ||
00622       aArc == kNC_IsServer ||
00623       aArc == kNC_IsSecure ||
00624       aArc == kNC_CanSubscribe ||
00625       aArc == kNC_SupportsOffline ||
00626       aArc == kNC_CanFileMessages ||
00627       aArc == kNC_CanCreateSubfolders ||
00628       aArc == kNC_CanRename ||
00629       aArc == kNC_CanCompact ||
00630       aArc == kNC_TotalMessages ||
00631       aArc == kNC_TotalUnreadMessages ||
00632       aArc == kNC_FolderSize ||
00633       aArc == kNC_Charset ||
00634       aArc == kNC_BiffState ||
00635       aArc == kNC_Child ||
00636       aArc == kNC_NoSelect ||
00637       aArc == kNC_VirtualFolder ||
00638       aArc == kNC_InVFEditSearchScope ||
00639       aArc == kNC_ImapShared ||
00640       aArc == kNC_Synchronize ||
00641       aArc == kNC_SyncDisabled ||
00642       aArc == kNC_CanSearchMessages);
00643   }
00644   else 
00645   {
00646     *result = PR_FALSE;
00647   }
00648   return NS_OK;
00649 }
00650 
00651 NS_IMETHODIMP nsMsgFolderDataSource::ArcLabelsIn(nsIRDFNode* node,
00652                                                  nsISimpleEnumerator** labels)
00653 {
00654   return nsMsgRDFDataSource::ArcLabelsIn(node, labels);
00655 }
00656 
00657 NS_IMETHODIMP nsMsgFolderDataSource::ArcLabelsOut(nsIRDFResource* source,
00658                                                   nsISimpleEnumerator** labels)
00659 {
00660   nsresult rv = NS_RDF_NO_VALUE;
00661   nsCOMPtr<nsISupportsArray> arcsArray;
00662   
00663   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00664   if (NS_SUCCEEDED(rv)) 
00665   {
00666     arcsArray = kFolderArcsOutArray;
00667     rv = NS_NewArrayEnumerator(labels, arcsArray);
00668   }
00669   else 
00670   {
00671     rv = NS_NewEmptyEnumerator(labels);
00672   }
00673   
00674   return rv;
00675 }
00676 
00677 nsresult
00678 nsMsgFolderDataSource::getFolderArcLabelsOut(nsISupportsArray **arcs)
00679 {
00680   nsresult rv;
00681   rv = NS_NewISupportsArray(arcs);
00682   if(NS_FAILED(rv))
00683     return rv;
00684   
00685   (*arcs)->AppendElement(kNC_Name);
00686   (*arcs)->AppendElement(kNC_Open);
00687   (*arcs)->AppendElement(kNC_FolderTreeName);
00688   (*arcs)->AppendElement(kNC_FolderTreeSimpleName);
00689   (*arcs)->AppendElement(kNC_SpecialFolder);
00690   (*arcs)->AppendElement(kNC_ServerType);
00691   (*arcs)->AppendElement(kNC_IsDeferred);
00692   (*arcs)->AppendElement(kNC_RedirectorType);
00693   (*arcs)->AppendElement(kNC_CanCreateFoldersOnServer);
00694   (*arcs)->AppendElement(kNC_CanFileMessagesOnServer);
00695   (*arcs)->AppendElement(kNC_IsServer);
00696   (*arcs)->AppendElement(kNC_IsSecure);
00697   (*arcs)->AppendElement(kNC_CanSubscribe);
00698   (*arcs)->AppendElement(kNC_SupportsOffline);
00699   (*arcs)->AppendElement(kNC_CanFileMessages);
00700   (*arcs)->AppendElement(kNC_CanCreateSubfolders);
00701   (*arcs)->AppendElement(kNC_CanRename);
00702   (*arcs)->AppendElement(kNC_CanCompact);
00703   (*arcs)->AppendElement(kNC_TotalMessages);
00704   (*arcs)->AppendElement(kNC_TotalUnreadMessages);
00705   (*arcs)->AppendElement(kNC_FolderSize);
00706   (*arcs)->AppendElement(kNC_Charset);
00707   (*arcs)->AppendElement(kNC_BiffState);
00708   (*arcs)->AppendElement(kNC_Child);
00709   (*arcs)->AppendElement(kNC_NoSelect);
00710   (*arcs)->AppendElement(kNC_VirtualFolder);
00711   (*arcs)->AppendElement(kNC_InVFEditSearchScope);
00712   (*arcs)->AppendElement(kNC_ImapShared);
00713   (*arcs)->AppendElement(kNC_Synchronize);
00714   (*arcs)->AppendElement(kNC_SyncDisabled);
00715   (*arcs)->AppendElement(kNC_CanSearchMessages);
00716   
00717   return NS_OK;
00718 }
00719 
00720 NS_IMETHODIMP
00721 nsMsgFolderDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
00722 {
00723   NS_NOTYETIMPLEMENTED("sorry!");
00724   return NS_ERROR_NOT_IMPLEMENTED;
00725 }
00726 
00727 NS_IMETHODIMP
00728 nsMsgFolderDataSource::GetAllCmds(nsIRDFResource* source,
00729                                       nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
00730 {
00731   NS_NOTYETIMPLEMENTED("no one actually uses me");
00732   nsresult rv;
00733 
00734   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00735   if (NS_FAILED(rv)) return rv;
00736 
00737   nsCOMPtr<nsIMutableArray> cmds;
00738   NS_NewArray(getter_AddRefs(cmds));
00739   if (!cmds) return rv;
00740 
00741   cmds->AppendElement(kNC_Delete, PR_FALSE);
00742   cmds->AppendElement(kNC_ReallyDelete, PR_FALSE);
00743   cmds->AppendElement(kNC_NewFolder, PR_FALSE);
00744   cmds->AppendElement(kNC_GetNewMessages, PR_FALSE);
00745   cmds->AppendElement(kNC_Copy, PR_FALSE);
00746   cmds->AppendElement(kNC_Move, PR_FALSE);
00747   cmds->AppendElement(kNC_CopyFolder, PR_FALSE);
00748   cmds->AppendElement(kNC_MoveFolder, PR_FALSE);
00749   cmds->AppendElement(kNC_MarkAllMessagesRead, PR_FALSE);
00750   cmds->AppendElement(kNC_Compact, PR_FALSE);
00751   cmds->AppendElement(kNC_CompactAll, PR_FALSE);
00752   cmds->AppendElement(kNC_Rename, PR_FALSE);
00753   cmds->AppendElement(kNC_EmptyTrash, PR_FALSE);
00754   cmds->AppendElement(kNC_DownloadFlagged, PR_FALSE);
00755 
00756   return cmds->Enumerate(commands);
00757 }
00758 
00759 NS_IMETHODIMP
00760 nsMsgFolderDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00761                                         nsIRDFResource*   aCommand,
00762                                         nsISupportsArray/*<nsIRDFResource>*/* aArguments,
00763                                         PRBool* aResult)
00764 {
00765   nsresult rv;
00766   nsCOMPtr<nsIMsgFolder> folder;
00767 
00768   PRUint32 cnt;
00769   rv = aSources->Count(&cnt);
00770   if (NS_FAILED(rv)) return rv;
00771   for (PRUint32 i = 0; i < cnt; i++) 
00772   {
00773     folder = do_QueryElementAt(aSources, i, &rv);
00774     if (NS_SUCCEEDED(rv)) 
00775     {
00776       // we don't care about the arguments -- folder commands are always enabled
00777       if (!((aCommand == kNC_Delete) ||
00778             (aCommand == kNC_ReallyDelete) ||
00779             (aCommand == kNC_NewFolder) ||
00780             (aCommand == kNC_Copy) ||
00781             (aCommand == kNC_Move) ||
00782             (aCommand == kNC_CopyFolder) ||
00783             (aCommand == kNC_MoveFolder) ||
00784             (aCommand == kNC_GetNewMessages) ||
00785             (aCommand == kNC_MarkAllMessagesRead) ||
00786             (aCommand == kNC_Compact) || 
00787             (aCommand == kNC_CompactAll) || 
00788             (aCommand == kNC_Rename) ||
00789             (aCommand == kNC_EmptyTrash) ||
00790             (aCommand == kNC_DownloadFlagged) )) 
00791       {
00792         *aResult = PR_FALSE;
00793         return NS_OK;
00794       }
00795     }
00796   }
00797   *aResult = PR_TRUE;
00798   return NS_OK; // succeeded for all sources
00799 }
00800 
00801 NS_IMETHODIMP
00802 nsMsgFolderDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00803                                  nsIRDFResource*   aCommand,
00804                                  nsISupportsArray/*<nsIRDFResource>*/* aArguments)
00805 {
00806   nsresult rv = NS_OK;
00807   nsCOMPtr<nsISupports> supports;
00808   nsCOMPtr<nsIMsgWindow> window;
00809 
00810   // callers can pass in the msgWindow as the last element of the arguments
00811   // array. If they do, we'll use that as the msg window for progress, etc.
00812   if (aArguments)
00813   {
00814     PRUint32 numArgs;
00815     aArguments->Count(&numArgs);
00816     if (numArgs > 1)
00817       window = do_QueryElementAt(aArguments, numArgs - 1);
00818   }
00819   if (!window)
00820     window = mWindow;
00821 
00822   // XXX need to handle batching of command applied to all sources
00823 
00824   PRUint32 cnt = 0;
00825   PRUint32 i = 0;
00826 
00827   rv = aSources->Count(&cnt);
00828   if (NS_FAILED(rv)) return rv;
00829 
00830   for ( ; i < cnt; i++) 
00831   {
00832     nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(aSources, i, &rv);
00833     if (NS_SUCCEEDED(rv)) 
00834     {
00835       if ((aCommand == kNC_Delete))
00836       {
00837         rv = DoDeleteFromFolder(folder, aArguments, window, PR_FALSE);
00838       }
00839       if ((aCommand == kNC_ReallyDelete))
00840       {
00841         rv = DoDeleteFromFolder(folder, aArguments, window, PR_TRUE);
00842       }
00843       else if((aCommand == kNC_NewFolder)) 
00844       {
00845         rv = DoNewFolder(folder, aArguments, window);
00846       }
00847       else if((aCommand == kNC_GetNewMessages))
00848       {
00849         nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(aArguments, i, &rv);
00850         NS_ENSURE_SUCCESS(rv, rv);
00851         rv = server->GetNewMessages(folder, window, nsnull);
00852       }
00853       else if((aCommand == kNC_Copy))
00854       {
00855         rv = DoCopyToFolder(folder, aArguments, window, PR_FALSE);
00856       }
00857       else if((aCommand == kNC_Move))
00858       {
00859         rv = DoCopyToFolder(folder, aArguments, window, PR_TRUE);
00860       }
00861       else if((aCommand == kNC_CopyFolder))
00862       {
00863         rv = DoFolderCopyToFolder(folder, aArguments, window, PR_FALSE);
00864       }
00865       else if((aCommand == kNC_MoveFolder))
00866       {
00867         rv = DoFolderCopyToFolder(folder, aArguments, window, PR_TRUE);
00868       }
00869       else if((aCommand == kNC_MarkAllMessagesRead))
00870       {
00871         rv = folder->MarkAllMessagesRead();
00872       }
00873       else if ((aCommand == kNC_Compact))
00874       {
00875         rv = folder->Compact(nsnull, window);
00876       }
00877       else if ((aCommand == kNC_CompactAll))
00878       {
00879         rv = folder->CompactAll(nsnull, window, nsnull, PR_TRUE, nsnull);
00880       }
00881       else if ((aCommand == kNC_EmptyTrash))
00882       {
00883           rv = folder->EmptyTrash(window, nsnull);
00884       }
00885       else if ((aCommand == kNC_Rename))
00886       {
00887         nsCOMPtr<nsIRDFLiteral> literal = do_QueryElementAt(aArguments, 0, &rv);
00888         if(NS_SUCCEEDED(rv))
00889         {
00890           nsXPIDLString name;
00891           literal->GetValue(getter_Copies(name));
00892 
00893           rv = folder->Rename(name.get(), window);
00894         }
00895       }
00896     }
00897     else 
00898     {
00899       rv = NS_ERROR_NOT_IMPLEMENTED;
00900     }
00901   }
00902   //for the moment return NS_OK, because failure stops entire DoCommand process.
00903   return rv;
00904   //return NS_OK;
00905 }
00906 
00907 NS_IMETHODIMP nsMsgFolderDataSource::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
00908 {
00909   return OnItemAddedOrRemoved(parentItem, item, PR_TRUE);
00910 }
00911 
00912 NS_IMETHODIMP nsMsgFolderDataSource::OnItemRemoved(nsIRDFResource *parentItem, nsISupports *item)
00913 {
00914   return OnItemAddedOrRemoved(parentItem, item, PR_FALSE);
00915 }
00916 
00917 nsresult nsMsgFolderDataSource::OnItemAddedOrRemoved(nsIRDFResource *parentItem, nsISupports *item, PRBool added)
00918 {
00919   nsCOMPtr<nsIRDFNode> itemNode(do_QueryInterface(item));
00920   if (itemNode)
00921   {
00922     NotifyObservers(parentItem, kNC_Child, itemNode, nsnull, added, PR_FALSE);
00923   }
00924   return NS_OK;
00925 }
00926 
00927 NS_IMETHODIMP
00928 nsMsgFolderDataSource::OnItemPropertyChanged(nsIRDFResource *resource,
00929                                              nsIAtom *property,
00930                                              const char *oldValue,
00931                                              const char *newValue)
00932 
00933 {
00934   return NS_OK;
00935 }
00936 
00937 NS_IMETHODIMP
00938 nsMsgFolderDataSource::OnItemIntPropertyChanged(nsIRDFResource *resource,
00939                                                 nsIAtom *property,
00940                                                 PRInt32 oldValue,
00941                                                 PRInt32 newValue)
00942 {
00943   if (kTotalMessagesAtom == property)
00944     OnTotalMessagePropertyChanged(resource, oldValue, newValue);
00945   else if (kTotalUnreadMessagesAtom == property)
00946     OnUnreadMessagePropertyChanged(resource, oldValue, newValue);
00947   else if (kFolderSizeAtom == property)
00948     OnFolderSizePropertyChanged(resource, oldValue, newValue);
00949   else if (kBiffStateAtom == property) {
00950     // be careful about skipping if oldValue == newValue
00951     // see the comment in nsMsgFolder::SetBiffState() about filters
00952 
00953     nsCOMPtr<nsIRDFNode> biffNode;
00954     nsresult rv = createBiffStateNodeFromFlag(newValue, getter_AddRefs(biffNode));
00955     NS_ENSURE_SUCCESS(rv,rv);
00956 
00957     NotifyPropertyChanged(resource, kNC_BiffState, biffNode);
00958   }
00959   return NS_OK;
00960 }
00961 
00962 NS_IMETHODIMP
00963 nsMsgFolderDataSource::OnItemUnicharPropertyChanged(nsIRDFResource *resource,
00964                                                     nsIAtom *property,
00965                                                     const PRUnichar *oldValue,
00966                                                     const PRUnichar *newValue)
00967 {
00968   if (kNameAtom == property) 
00969   {
00970     nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(resource));
00971     if (folder) 
00972     {
00973       PRInt32 numUnread;
00974       folder->GetNumUnread(PR_FALSE, &numUnread);
00975       NotifyFolderTreeNameChanged(folder, resource, numUnread);
00976       NotifyFolderTreeSimpleNameChanged(folder, resource);
00977       NotifyFolderNameChanged(folder, resource);
00978     }
00979   }
00980   return NS_OK;
00981 }
00982 
00983 NS_IMETHODIMP
00984 nsMsgFolderDataSource::OnItemBoolPropertyChanged(nsIRDFResource *resource,
00985                                                  nsIAtom *property,
00986                                                  PRBool oldValue,
00987                                                  PRBool newValue)
00988 {
00989   if (newValue != oldValue) {
00990     nsIRDFNode* literalNode = newValue?kTrueLiteral:kFalseLiteral;
00991     nsIRDFNode* oldLiteralNode = oldValue?kTrueLiteral:kFalseLiteral;
00992     if (kNewMessagesAtom == property)
00993       NotifyPropertyChanged(resource, kNC_NewMessages, literalNode); 
00994     else if (kSynchronizeAtom == property)
00995       NotifyPropertyChanged(resource, kNC_Synchronize, literalNode); 
00996     else if (kOpenAtom == property)
00997       NotifyPropertyChanged(resource, kNC_Open, literalNode);
00998     else if (kIsDeferredAtom == property) 
00999       NotifyPropertyChanged(resource, kNC_IsDeferred, literalNode, oldLiteralNode);
01000     else if (kCanFileMessagesAtom == property)
01001       NotifyPropertyChanged(resource, kNC_CanFileMessages, literalNode, oldLiteralNode);
01002     else if (kInVFEditSearchScopeAtom == property)
01003       NotifyPropertyChanged(resource, kNC_InVFEditSearchScope, literalNode); 
01004   } 
01005 
01006   return NS_OK;
01007 }
01008 
01009 NS_IMETHODIMP
01010 nsMsgFolderDataSource::OnItemPropertyFlagChanged(nsIMsgDBHdr *item,
01011                                                  nsIAtom *property,
01012                                                  PRUint32 oldFlag,
01013                                                  PRUint32 newFlag)
01014 {
01015   return NS_OK;
01016 }
01017 
01018 NS_IMETHODIMP
01019 nsMsgFolderDataSource::OnItemEvent(nsIMsgFolder *aFolder, nsIAtom *aEvent)
01020 {
01021   return NS_OK;
01022 }
01023 
01024 
01025 nsresult nsMsgFolderDataSource::createFolderNode(nsIMsgFolder* folder,
01026                                                  nsIRDFResource* property,
01027                                                  nsIRDFNode** target)
01028 {
01029   nsresult rv = NS_RDF_NO_VALUE;
01030 
01031   if (kNC_NameSort == property)
01032     rv = createFolderNameNode(folder, target, PR_TRUE);
01033   else if(kNC_FolderTreeNameSort == property)
01034     rv = createFolderNameNode(folder, target, PR_TRUE);
01035   else if (kNC_Name == property)
01036     rv = createFolderNameNode(folder, target, PR_FALSE);
01037   else if(kNC_Open == property)
01038     rv = createFolderOpenNode(folder, target);
01039   else if (kNC_FolderTreeName == property)
01040     rv = createFolderTreeNameNode(folder, target);
01041   else if (kNC_FolderTreeSimpleName == property)
01042     rv = createFolderTreeSimpleNameNode(folder, target);
01043   else if ((kNC_SpecialFolder == property))
01044     rv = createFolderSpecialNode(folder,target);
01045   else if ((kNC_ServerType == property))
01046     rv = createFolderServerTypeNode(folder, target);
01047   else if ((kNC_IsDeferred == property))
01048     rv = createServerIsDeferredNode(folder, target);
01049   else if ((kNC_RedirectorType == property))
01050     rv = createFolderRedirectorTypeNode(folder, target);
01051   else if ((kNC_CanCreateFoldersOnServer == property))
01052     rv = createFolderCanCreateFoldersOnServerNode(folder, target);
01053   else if ((kNC_CanFileMessagesOnServer == property))
01054     rv = createFolderCanFileMessagesOnServerNode(folder, target);
01055   else if ((kNC_IsServer == property))
01056     rv = createFolderIsServerNode(folder, target);
01057   else if ((kNC_IsSecure == property))
01058     rv = createFolderIsSecureNode(folder, target);
01059   else if ((kNC_CanSubscribe == property))
01060     rv = createFolderCanSubscribeNode(folder, target);
01061   else if ((kNC_SupportsOffline == property))
01062     rv = createFolderSupportsOfflineNode(folder, target);
01063   else if ((kNC_CanFileMessages == property))
01064     rv = createFolderCanFileMessagesNode(folder, target);
01065   else if ((kNC_CanCreateSubfolders == property))
01066     rv = createFolderCanCreateSubfoldersNode(folder, target);
01067   else if ((kNC_CanRename == property))
01068     rv = createFolderCanRenameNode(folder, target);
01069   else if ((kNC_CanCompact == property))
01070     rv = createFolderCanCompactNode(folder, target);
01071   else if ((kNC_TotalMessages == property))
01072     rv = createTotalMessagesNode(folder, target);
01073   else if ((kNC_TotalUnreadMessages == property))
01074     rv = createUnreadMessagesNode(folder, target);
01075   else if ((kNC_FolderSize == property))
01076     rv = createFolderSizeNode(folder, target);
01077   else if ((kNC_Charset == property))
01078     rv = createCharsetNode(folder, target);
01079   else if ((kNC_BiffState == property))
01080     rv = createBiffStateNodeFromFolder(folder, target);
01081   else if ((kNC_HasUnreadMessages == property))
01082     rv = createHasUnreadMessagesNode(folder, PR_FALSE, target);
01083   else if ((kNC_NewMessages == property))
01084     rv = createNewMessagesNode(folder, target);
01085   else if ((kNC_SubfoldersHaveUnreadMessages == property))
01086     rv = createHasUnreadMessagesNode(folder, PR_TRUE, target);
01087   else if ((kNC_Child == property))
01088     rv = createFolderChildNode(folder, target);
01089   else if ((kNC_NoSelect == property))
01090     rv = createFolderNoSelectNode(folder, target);
01091   else if ((kNC_VirtualFolder == property))
01092     rv = createFolderVirtualNode(folder, target);
01093   else if (kNC_InVFEditSearchScope == property)
01094     rv = createInVFEditSearchScopeNode(folder, target);
01095   else if ((kNC_ImapShared == property))
01096     rv = createFolderImapSharedNode(folder, target);
01097   else if ((kNC_Synchronize == property))
01098     rv = createFolderSynchronizeNode(folder, target);
01099   else if ((kNC_SyncDisabled == property))
01100     rv = createFolderSyncDisabledNode(folder, target);
01101   else if ((kNC_CanSearchMessages == property))
01102     rv = createCanSearchMessages(folder, target);
01103 
01104 
01105   if (NS_FAILED(rv)) return NS_RDF_NO_VALUE;
01106   return rv;
01107 }
01108 
01109 
01110 nsresult 
01111 nsMsgFolderDataSource::createFolderNameNode(nsIMsgFolder *folder,
01112                                             nsIRDFNode **target, PRBool sort)
01113 {
01114   nsresult rv;
01115   if (sort) 
01116   {
01117     PRUint8 *sortKey=nsnull;
01118     PRUint32 sortKeyLength;
01119     rv = folder->GetSortKey(&sortKey, &sortKeyLength);
01120     NS_ENSURE_SUCCESS(rv, rv);
01121     createBlobNode(sortKey, sortKeyLength, target, getRDFService());
01122     PR_Free(sortKey);
01123   }
01124   else 
01125   {
01126     nsXPIDLString name;
01127     rv = folder->GetName(getter_Copies(name));
01128     if (NS_FAILED(rv)) 
01129       return rv;
01130     createNode(name.get(), target, getRDFService());
01131   }
01132     
01133   return NS_OK;
01134 }
01135 
01136 nsresult nsMsgFolderDataSource::GetFolderDisplayName(nsIMsgFolder *folder, PRUnichar **folderName)
01137 {
01138   return folder->GetAbbreviatedName(folderName);
01139 }
01140 
01141 nsresult 
01142 nsMsgFolderDataSource::createFolderTreeNameNode(nsIMsgFolder *folder,
01143                                                 nsIRDFNode **target)
01144 {
01145   nsXPIDLString name;
01146   nsresult rv = GetFolderDisplayName(folder, getter_Copies(name));
01147   if (NS_FAILED(rv)) return rv;
01148   nsAutoString nameString(name);
01149   PRInt32 unreadMessages;
01150 
01151   rv = folder->GetNumUnread(PR_FALSE, &unreadMessages);
01152   if(NS_SUCCEEDED(rv)) 
01153     CreateUnreadMessagesNameString(unreadMessages, nameString);       
01154 
01155   createNode(nameString.get(), target, getRDFService());
01156   return NS_OK;
01157 }
01158 
01159 nsresult nsMsgFolderDataSource::createFolderTreeSimpleNameNode(nsIMsgFolder * folder, nsIRDFNode **target)
01160 {
01161   nsXPIDLString name;
01162   nsresult rv = GetFolderDisplayName(folder, getter_Copies(name));
01163   if (NS_FAILED(rv)) return rv;
01164 
01165   createNode(name.get(), target, getRDFService());
01166   return NS_OK;
01167 }
01168 
01169 nsresult nsMsgFolderDataSource::CreateUnreadMessagesNameString(PRInt32 unreadMessages, nsAutoString &nameString)
01170 {
01171   //Only do this if unread messages are positive
01172   if(unreadMessages > 0)
01173   {
01174     nameString.Append(NS_LITERAL_STRING(" (").get());
01175     nameString.AppendInt(unreadMessages);
01176     nameString.Append(NS_LITERAL_STRING(")").get());
01177   }
01178   return NS_OK;
01179 }
01180 
01181 nsresult
01182 nsMsgFolderDataSource::createFolderSpecialNode(nsIMsgFolder *folder,
01183                                                nsIRDFNode **target)
01184 {
01185   PRUint32 flags;
01186   nsresult rv = folder->GetFlags(&flags);
01187   if(NS_FAILED(rv)) 
01188     return rv;
01189   
01190   nsAutoString specialFolderString;
01191   if (flags & MSG_FOLDER_FLAG_INBOX)
01192     specialFolderString.AssignLiteral("Inbox");
01193   else if (flags & MSG_FOLDER_FLAG_TRASH)
01194     specialFolderString.AssignLiteral("Trash");
01195   else if (flags & MSG_FOLDER_FLAG_QUEUE)
01196     specialFolderString.AssignLiteral("Unsent Messages");
01197   else if (flags & MSG_FOLDER_FLAG_SENTMAIL)
01198     specialFolderString.AssignLiteral("Sent");
01199   else if (flags & MSG_FOLDER_FLAG_DRAFTS)
01200     specialFolderString.AssignLiteral("Drafts");
01201   else if (flags & MSG_FOLDER_FLAG_TEMPLATES)
01202     specialFolderString.AssignLiteral("Templates");
01203   else if (flags & MSG_FOLDER_FLAG_JUNK)
01204     specialFolderString.AssignLiteral("Junk");
01205   else if (flags & MSG_FOLDER_FLAG_VIRTUAL)
01206     specialFolderString.AssignLiteral("Virtual");
01207   else {
01208     // XXX why do this at all? or just ""
01209     specialFolderString.AssignLiteral("none");
01210   }
01211   
01212   createNode(specialFolderString.get(), target, getRDFService());
01213   return NS_OK;
01214 }
01215 
01216 nsresult
01217 nsMsgFolderDataSource::createFolderServerTypeNode(nsIMsgFolder* folder,
01218                                                   nsIRDFNode **target)
01219 {
01220   nsresult rv;
01221   nsCOMPtr<nsIMsgIncomingServer> server;
01222   rv = folder->GetServer(getter_AddRefs(server));
01223   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01224 
01225   nsXPIDLCString serverType;
01226   rv = server->GetType(getter_Copies(serverType));
01227   if (NS_FAILED(rv)) return rv;
01228 
01229   createNode(NS_ConvertASCIItoUCS2(serverType).get(), target, getRDFService());
01230   return NS_OK;
01231 }
01232 
01233 nsresult
01234 nsMsgFolderDataSource::createServerIsDeferredNode(nsIMsgFolder* folder,
01235                                                   nsIRDFNode **target)
01236 {
01237   PRBool isDeferred = PR_FALSE;
01238   nsCOMPtr <nsIMsgIncomingServer> incomingServer;
01239   folder->GetServer(getter_AddRefs(incomingServer));
01240   if (incomingServer)
01241   {
01242     nsCOMPtr <nsIPop3IncomingServer> pop3Server = do_QueryInterface(incomingServer);
01243     if (pop3Server)
01244     {
01245       nsXPIDLCString deferredToServer;
01246       pop3Server->GetDeferredToAccount(getter_Copies(deferredToServer));
01247       isDeferred = !deferredToServer.IsEmpty();
01248     }
01249   }
01250   *target = (isDeferred) ? kTrueLiteral : kFalseLiteral;
01251   NS_IF_ADDREF(*target);
01252   return NS_OK;
01253 }
01254 
01255 nsresult
01256 nsMsgFolderDataSource::createFolderRedirectorTypeNode(nsIMsgFolder* folder,
01257                                                   nsIRDFNode **target)
01258 {
01259   nsresult rv;
01260   nsCOMPtr<nsIMsgIncomingServer> server;
01261   rv = folder->GetServer(getter_AddRefs(server));
01262   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01263 
01264   nsXPIDLCString redirectorType;
01265   rv = server->GetRedirectorType(getter_Copies(redirectorType));
01266   if (NS_FAILED(rv)) return rv;
01267 
01268   createNode(NS_ConvertASCIItoUCS2(redirectorType).get(), target, getRDFService());
01269   return NS_OK;
01270 }
01271 
01272 nsresult
01273 nsMsgFolderDataSource::createFolderCanCreateFoldersOnServerNode(nsIMsgFolder* folder,
01274                                                                  nsIRDFNode **target)
01275 {
01276   nsresult rv;
01277 
01278   nsCOMPtr<nsIMsgIncomingServer> server;
01279   rv = folder->GetServer(getter_AddRefs(server));
01280   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01281   
01282   PRBool canCreateFoldersOnServer;
01283   rv = server->GetCanCreateFoldersOnServer(&canCreateFoldersOnServer);
01284   if (NS_FAILED(rv)) return rv;
01285 
01286   if (canCreateFoldersOnServer)
01287     *target = kTrueLiteral;
01288   else
01289     *target = kFalseLiteral;
01290   NS_IF_ADDREF(*target);
01291 
01292   return NS_OK;
01293 }
01294 
01295 nsresult
01296 nsMsgFolderDataSource::createFolderCanFileMessagesOnServerNode(nsIMsgFolder* folder,
01297                                                                  nsIRDFNode **target)
01298 {
01299   nsresult rv;
01300 
01301   nsCOMPtr<nsIMsgIncomingServer> server;
01302   rv = folder->GetServer(getter_AddRefs(server));
01303   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01304 
01305   PRBool canFileMessagesOnServer;
01306   rv = server->GetCanFileMessagesOnServer(&canFileMessagesOnServer);
01307   if (NS_FAILED(rv)) return rv;
01308   
01309   *target = (canFileMessagesOnServer) ? kTrueLiteral : kFalseLiteral;
01310   NS_IF_ADDREF(*target);
01311 
01312   return NS_OK;
01313 }
01314 
01315 
01316 nsresult
01317 nsMsgFolderDataSource::createFolderIsServerNode(nsIMsgFolder* folder,
01318                                                   nsIRDFNode **target)
01319 {
01320   nsresult rv;
01321   PRBool isServer;
01322   rv = folder->GetIsServer(&isServer);
01323   if (NS_FAILED(rv)) return rv;
01324 
01325   *target = nsnull;
01326 
01327   if (isServer)
01328     *target = kTrueLiteral;
01329   else
01330     *target = kFalseLiteral;
01331   NS_IF_ADDREF(*target);
01332   return NS_OK;
01333 }
01334 
01335 nsresult
01336 nsMsgFolderDataSource::createFolderNoSelectNode(nsIMsgFolder* folder,
01337                                                   nsIRDFNode **target)
01338 {
01339   nsresult rv;
01340   PRBool noSelect;
01341   rv = folder->GetNoSelect(&noSelect);
01342   if (NS_FAILED(rv)) return rv;
01343 
01344   *target = (noSelect) ? kTrueLiteral : kFalseLiteral;
01345   NS_IF_ADDREF(*target);
01346   return NS_OK;
01347 }
01348 
01349 nsresult
01350 nsMsgFolderDataSource::createInVFEditSearchScopeNode(nsIMsgFolder* folder,
01351                                                   nsIRDFNode **target)
01352 {
01353   PRBool inVFEditSearchScope = PR_FALSE;
01354   folder->GetInVFEditSearchScope(&inVFEditSearchScope);
01355 
01356   *target = inVFEditSearchScope ? kTrueLiteral : kFalseLiteral;
01357   NS_IF_ADDREF(*target);
01358   return NS_OK;
01359 }
01360 
01361 nsresult
01362 nsMsgFolderDataSource::createFolderVirtualNode(nsIMsgFolder* folder,
01363                                                   nsIRDFNode **target)
01364 {
01365   PRUint32 folderFlags;
01366   folder->GetFlags(&folderFlags);
01367 
01368   *target = (folderFlags & MSG_FOLDER_FLAG_VIRTUAL) ? kTrueLiteral : kFalseLiteral;
01369   NS_IF_ADDREF(*target);
01370   return NS_OK;
01371 }
01372 
01373 
01374 nsresult
01375 nsMsgFolderDataSource::createFolderImapSharedNode(nsIMsgFolder* folder,
01376                                                   nsIRDFNode **target)
01377 {
01378   nsresult rv;
01379   PRBool imapShared; 
01380   rv = folder->GetImapShared(&imapShared);
01381   if (NS_FAILED(rv)) return rv;
01382 
01383   *target = (imapShared) ? kTrueLiteral : kFalseLiteral;
01384   NS_IF_ADDREF(*target);
01385   return NS_OK;
01386 }
01387 
01388 
01389 nsresult
01390 nsMsgFolderDataSource::createFolderSynchronizeNode(nsIMsgFolder* folder,
01391                                                   nsIRDFNode **target)
01392 {
01393   nsresult rv;
01394   PRBool sync;
01395   rv = folder->GetFlag(MSG_FOLDER_FLAG_OFFLINE, &sync);        
01396   if (NS_FAILED(rv)) return rv;
01397 
01398   *target = nsnull;
01399 
01400   *target = (sync) ? kTrueLiteral : kFalseLiteral;
01401   NS_IF_ADDREF(*target);
01402   return NS_OK;
01403 }
01404 
01405 nsresult
01406 nsMsgFolderDataSource::createFolderSyncDisabledNode(nsIMsgFolder* folder,
01407                                                   nsIRDFNode **target)
01408 {
01409   
01410   nsresult rv;
01411   PRBool isServer;
01412   nsCOMPtr<nsIMsgIncomingServer> server;
01413 
01414   rv = folder->GetIsServer(&isServer);
01415   if (NS_FAILED(rv)) return rv;
01416     
01417   rv = folder->GetServer(getter_AddRefs(server));
01418   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01419 
01420   nsXPIDLCString serverType;
01421   rv = server->GetType(getter_Copies(serverType));
01422   if (NS_FAILED(rv)) return rv;
01423 
01424   *target = nsnull;
01425 
01426   if (nsCRT::strcasecmp(serverType, "none")==0 || nsCRT::strcasecmp(serverType, "pop3")==0
01427       || isServer)
01428     *target = kTrueLiteral;
01429   else
01430     *target = kFalseLiteral;
01431   NS_IF_ADDREF(*target);
01432   return NS_OK;
01433 }
01434 
01435 nsresult
01436 nsMsgFolderDataSource::createCanSearchMessages(nsIMsgFolder* folder,
01437                                                                  nsIRDFNode **target)
01438 {
01439   nsresult rv;
01440 
01441   nsCOMPtr<nsIMsgIncomingServer> server;
01442   rv = folder->GetServer(getter_AddRefs(server));
01443   if (NS_FAILED(rv) || !server) return NS_ERROR_FAILURE;
01444 
01445   PRBool canSearchMessages;
01446   rv = server->GetCanSearchMessages(&canSearchMessages);
01447   if (NS_FAILED(rv)) return rv;
01448   
01449   *target = (canSearchMessages) ? kTrueLiteral : kFalseLiteral;
01450   NS_IF_ADDREF(*target);
01451 
01452   return NS_OK;
01453 }
01454 
01455 nsresult
01456 nsMsgFolderDataSource::createFolderOpenNode(nsIMsgFolder *folder, nsIRDFNode **target)
01457 {
01458   NS_ENSURE_ARG_POINTER(target);
01459 
01460   // call GetSubFolders() to ensure mFlags is set correctly 
01461   // from the folder cache on startup
01462   nsCOMPtr<nsIEnumerator> subFolders;
01463   nsresult rv = folder->GetSubFolders(getter_AddRefs(subFolders));
01464   if (NS_FAILED(rv))
01465     return NS_RDF_NO_VALUE;
01466 
01467   PRBool closed;
01468   rv = folder->GetFlag(MSG_FOLDER_FLAG_ELIDED, &closed);              
01469   if (NS_FAILED(rv)) 
01470     return rv;
01471 
01472   *target = (closed) ? kFalseLiteral : kTrueLiteral;
01473 
01474   NS_IF_ADDREF(*target);
01475   return NS_OK;
01476 }
01477 
01478 nsresult
01479 nsMsgFolderDataSource::createFolderIsSecureNode(nsIMsgFolder* folder,
01480                                                   nsIRDFNode **target)
01481 {
01482   nsresult rv;
01483   PRBool isSecure = PR_FALSE;
01484 
01485   nsCOMPtr<nsIMsgIncomingServer> server;
01486   rv = folder->GetServer(getter_AddRefs(server));
01487 
01488   if (NS_SUCCEEDED(rv) && server) {
01489     nsCOMPtr<nsINntpIncomingServer> nntpIncomingServer = do_QueryInterface(server);
01490 
01491     if(nntpIncomingServer)  
01492       rv = server->GetIsSecure(&isSecure);
01493     else {
01494       PRInt32 socketType;
01495       rv = server->GetSocketType(&socketType);
01496       if (NS_SUCCEEDED(rv) && (socketType == nsIMsgIncomingServer::alwaysUseTLS || 
01497                               socketType == nsIMsgIncomingServer::useSSL))
01498         isSecure = PR_TRUE;
01499     }
01500   }
01501 
01502   *target = (isSecure) ? kTrueLiteral : kFalseLiteral;
01503   NS_IF_ADDREF(*target);
01504   return NS_OK;
01505 }
01506 
01507 
01508 nsresult
01509 nsMsgFolderDataSource::createFolderCanSubscribeNode(nsIMsgFolder* folder,
01510                                                   nsIRDFNode **target)
01511 {
01512   nsresult rv;
01513   PRBool canSubscribe;
01514   rv = folder->GetCanSubscribe(&canSubscribe);
01515   if (NS_FAILED(rv)) return rv;
01516 
01517   *target = (canSubscribe) ? kTrueLiteral : kFalseLiteral;
01518   NS_IF_ADDREF(*target);
01519   return NS_OK;
01520 }
01521 
01522 nsresult
01523 nsMsgFolderDataSource::createFolderSupportsOfflineNode(nsIMsgFolder* folder,
01524                                                   nsIRDFNode **target)
01525 {
01526   nsresult rv;
01527   PRBool supportsOffline;
01528   rv = folder->GetSupportsOffline(&supportsOffline);
01529   NS_ENSURE_SUCCESS(rv,rv);
01530  
01531   *target = (supportsOffline) ? kTrueLiteral : kFalseLiteral;
01532   NS_IF_ADDREF(*target);
01533   return NS_OK;
01534 }
01535 
01536 nsresult
01537 nsMsgFolderDataSource::createFolderCanFileMessagesNode(nsIMsgFolder* folder,
01538                                                   nsIRDFNode **target)
01539 {
01540   nsresult rv;
01541   PRBool canFileMessages;
01542   rv = folder->GetCanFileMessages(&canFileMessages);
01543   if (NS_FAILED(rv)) return rv;
01544 
01545   *target = (canFileMessages) ? kTrueLiteral : kFalseLiteral;
01546   NS_IF_ADDREF(*target);
01547   return NS_OK;
01548 }
01549 
01550 nsresult
01551 nsMsgFolderDataSource::createFolderCanCreateSubfoldersNode(nsIMsgFolder* folder,
01552                                                   nsIRDFNode **target)
01553 {
01554   nsresult rv;
01555   PRBool canCreateSubfolders;
01556   rv = folder->GetCanCreateSubfolders(&canCreateSubfolders);
01557   if (NS_FAILED(rv)) return rv;
01558 
01559   *target = (canCreateSubfolders) ? kTrueLiteral : kFalseLiteral;
01560   NS_IF_ADDREF(*target);
01561   return NS_OK;
01562 }
01563 
01564 nsresult
01565 nsMsgFolderDataSource::createFolderCanRenameNode(nsIMsgFolder* folder,
01566                                                   nsIRDFNode **target)
01567 {
01568   PRBool canRename;
01569   nsresult rv = folder->GetCanRename(&canRename);
01570   if (NS_FAILED(rv)) return rv;
01571 
01572   *target = (canRename) ? kTrueLiteral : kFalseLiteral;
01573   NS_IF_ADDREF(*target);
01574   return NS_OK;
01575 }
01576 
01577 nsresult
01578 nsMsgFolderDataSource::createFolderCanCompactNode(nsIMsgFolder* folder,
01579                                                   nsIRDFNode **target)
01580 {
01581   PRBool canCompact;
01582   nsresult rv = folder->GetCanCompact(&canCompact);
01583   if (NS_FAILED(rv)) return rv;
01584 
01585   *target = (canCompact) ? kTrueLiteral : kFalseLiteral;
01586   NS_IF_ADDREF(*target);
01587   return NS_OK;
01588 }
01589 
01590 
01591 nsresult
01592 nsMsgFolderDataSource::createTotalMessagesNode(nsIMsgFolder *folder,
01593                                                nsIRDFNode **target)
01594 {
01595 
01596   PRBool isServer;
01597   nsresult rv = folder->GetIsServer(&isServer);
01598   if (NS_FAILED(rv)) return rv;
01599   
01600   PRInt32 totalMessages;
01601   if(isServer)
01602     totalMessages = kDisplayBlankCount;
01603   else
01604   {
01605     rv = folder->GetTotalMessages(PR_FALSE, &totalMessages);
01606     if(NS_FAILED(rv)) return rv;
01607   }
01608   GetNumMessagesNode(totalMessages, target);
01609   
01610   return rv;
01611 }
01612 
01613 nsresult
01614 nsMsgFolderDataSource::createFolderSizeNode(nsIMsgFolder *folder, nsIRDFNode **target)
01615 {
01616   PRBool isServer;
01617   nsresult rv = folder->GetIsServer(&isServer);
01618   NS_ENSURE_SUCCESS(rv, rv);
01619   
01620   PRInt32 folderSize;
01621   if(isServer)
01622     folderSize = kDisplayBlankCount;
01623   else
01624   {
01625     // XXX todo, we are asserting here for news
01626     // for offline news, we'd know the size on disk, right?
01627     rv = folder->GetSizeOnDisk((PRUint32 *) &folderSize);
01628     NS_ENSURE_SUCCESS(rv, rv);
01629   }
01630   GetFolderSizeNode(folderSize, target);
01631   
01632   return rv;
01633 }
01634 
01635 nsresult
01636 nsMsgFolderDataSource::createCharsetNode(nsIMsgFolder *folder, nsIRDFNode **target)
01637 {
01638   nsXPIDLCString charset;
01639   nsresult rv = folder->GetCharset(getter_Copies(charset));
01640   if (NS_SUCCEEDED(rv))
01641     createNode(NS_ConvertASCIItoUCS2(charset).get(), target, getRDFService());
01642   else
01643     createNode(EmptyString().get(), target, getRDFService());
01644   return NS_OK;
01645 }
01646 
01647 nsresult
01648 nsMsgFolderDataSource::createBiffStateNodeFromFolder(nsIMsgFolder *folder, nsIRDFNode **target)
01649 {
01650   PRUint32 biffState;
01651   nsresult rv = folder->GetBiffState(&biffState);
01652   if(NS_FAILED(rv)) return rv;
01653 
01654   rv = createBiffStateNodeFromFlag(biffState, target);
01655   NS_ENSURE_SUCCESS(rv,rv);
01656 
01657   return NS_OK;
01658 }
01659 
01660 nsresult
01661 nsMsgFolderDataSource::createBiffStateNodeFromFlag(PRUint32 flag, nsIRDFNode **target)
01662 {
01663   const PRUnichar *biffStateStr;
01664 
01665   switch (flag) {
01666     case nsIMsgFolder::nsMsgBiffState_NewMail:
01667       biffStateStr = NS_LITERAL_STRING("NewMail").get();
01668       break;
01669     case nsIMsgFolder::nsMsgBiffState_NoMail:
01670       biffStateStr = NS_LITERAL_STRING("NoMail").get();
01671       break;
01672     default:
01673       biffStateStr = NS_LITERAL_STRING("UnknownMail").get();
01674       break;
01675   }
01676 
01677   createNode(biffStateStr, target, getRDFService());
01678   return NS_OK;
01679 }
01680 
01681 nsresult 
01682 nsMsgFolderDataSource::createUnreadMessagesNode(nsIMsgFolder *folder,
01683                                                                                     nsIRDFNode **target)
01684 {
01685   PRBool isServer;
01686   nsresult rv = folder->GetIsServer(&isServer);
01687   if (NS_FAILED(rv)) return rv;
01688   
01689   PRInt32 totalUnreadMessages;
01690   if(isServer)
01691     totalUnreadMessages = kDisplayBlankCount;
01692   else
01693   {
01694     rv = folder->GetNumUnread(PR_FALSE, &totalUnreadMessages);
01695     if(NS_FAILED(rv)) return rv;
01696   }
01697   GetNumMessagesNode(totalUnreadMessages, target);
01698   
01699   return NS_OK;
01700 }
01701 
01702 nsresult
01703 nsMsgFolderDataSource::createHasUnreadMessagesNode(nsIMsgFolder *folder, PRBool aIncludeSubfolders, nsIRDFNode **target)
01704 {
01705   PRBool isServer;
01706   nsresult rv = folder->GetIsServer(&isServer);
01707   if (NS_FAILED(rv)) return rv;
01708 
01709   *target = kFalseLiteral;
01710 
01711   PRInt32 totalUnreadMessages;
01712   if(!isServer)
01713   {
01714     rv = folder->GetNumUnread(aIncludeSubfolders, &totalUnreadMessages);
01715     if(NS_FAILED(rv)) return rv;
01716     // if we're including sub-folders, we're trying to find out if child folders
01717     // have unread. If so, we subtract the unread msgs in the current folder.
01718     if (aIncludeSubfolders)
01719     {
01720       PRInt32 numUnreadInFolder;
01721       rv = folder->GetNumUnread(PR_FALSE, &numUnreadInFolder);
01722       NS_ENSURE_SUCCESS(rv, rv);
01723       // don't subtract if numUnread is negative (which means we don't know the unread count)
01724       if (numUnreadInFolder > 0) 
01725         totalUnreadMessages -= numUnreadInFolder;
01726     }
01727     *target = (totalUnreadMessages > 0) ? kTrueLiteral : kFalseLiteral;
01728   }
01729 
01730   NS_IF_ADDREF(*target);
01731   return NS_OK;
01732 }
01733 
01734 nsresult
01735 nsMsgFolderDataSource::OnUnreadMessagePropertyChanged(nsIRDFResource *folderResource, PRInt32 oldValue, PRInt32 newValue)
01736 {
01737   nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(folderResource);
01738   if(folder)
01739   {
01740     //First send a regular unread message changed notification
01741     nsCOMPtr<nsIRDFNode> newNode;
01742 
01743     GetNumMessagesNode(newValue, getter_AddRefs(newNode));
01744     NotifyPropertyChanged(folderResource, kNC_TotalUnreadMessages, newNode);
01745        
01746     //Now see if hasUnreadMessages has changed
01747     if(oldValue <=0 && newValue >0)
01748     {
01749       NotifyPropertyChanged(folderResource, kNC_HasUnreadMessages, kTrueLiteral);
01750       NotifyAncestors(folder, kNC_SubfoldersHaveUnreadMessages, kTrueLiteral);
01751     }
01752     else if(oldValue > 0 && newValue <= 0)
01753     {
01754       NotifyPropertyChanged(folderResource, kNC_HasUnreadMessages, kFalseLiteral);
01755       // this isn't quite right - parents could still have other children with 
01756       // unread messages. NotifyAncestors will have to figure that out...
01757       NotifyAncestors(folder, kNC_SubfoldersHaveUnreadMessages, kFalseLiteral);
01758     }
01759 
01760     //We will have to change the folderTreeName if the unread column is hidden
01761     NotifyFolderTreeNameChanged(folder, folderResource, newValue);
01762   }
01763   return NS_OK;
01764 }
01765 
01766 nsresult
01767 nsMsgFolderDataSource::NotifyFolderNameChanged(nsIMsgFolder* aFolder, nsIRDFResource *folderResource)
01768 {
01769   nsXPIDLString name;
01770   nsresult rv = aFolder->GetName(getter_Copies(name));
01771 
01772   if (NS_SUCCEEDED(rv)) {
01773     nsCOMPtr<nsIRDFNode> newNameNode;
01774     createNode(name.get(), getter_AddRefs(newNameNode), getRDFService());
01775     NotifyPropertyChanged(folderResource, kNC_Name, newNameNode);
01776   }
01777   return NS_OK;
01778 }
01779 
01780 nsresult
01781 nsMsgFolderDataSource::NotifyFolderTreeSimpleNameChanged(nsIMsgFolder* aFolder, nsIRDFResource *folderResource)
01782 {
01783   nsXPIDLString abbreviatedName;
01784   nsresult rv = GetFolderDisplayName(aFolder, getter_Copies(abbreviatedName));
01785   if (NS_SUCCEEDED(rv)) {
01786     nsCOMPtr<nsIRDFNode> newNameNode;
01787     createNode(abbreviatedName.get(), getter_AddRefs(newNameNode), getRDFService());
01788     NotifyPropertyChanged(folderResource, kNC_FolderTreeSimpleName, newNameNode);
01789   }
01790 
01791   return NS_OK;
01792 }
01793 
01794 nsresult
01795 nsMsgFolderDataSource::NotifyFolderTreeNameChanged(nsIMsgFolder* aFolder,
01796                                                    nsIRDFResource* aFolderResource,
01797                                                    PRInt32 aUnreadMessages)
01798 {
01799   nsXPIDLString name;
01800   nsresult rv = GetFolderDisplayName(aFolder, getter_Copies(name));
01801   if (NS_SUCCEEDED(rv)) {
01802     nsAutoString newNameString(name);
01803                      
01804     CreateUnreadMessagesNameString(aUnreadMessages, newNameString);   
01805                      
01806     nsCOMPtr<nsIRDFNode> newNameNode;
01807     createNode(newNameString.get(), getter_AddRefs(newNameNode), getRDFService());
01808     NotifyPropertyChanged(aFolderResource, kNC_FolderTreeName, newNameNode);
01809   }
01810   return NS_OK;
01811 }
01812 
01813 nsresult 
01814 nsMsgFolderDataSource::NotifyAncestors(nsIMsgFolder *aFolder, nsIRDFResource *aPropertyResource, nsIRDFNode *aNode)
01815 {
01816   PRBool isServer = PR_FALSE;
01817   nsresult rv = aFolder->GetIsServer(&isServer);
01818   NS_ENSURE_SUCCESS(rv,rv);
01819  
01820   if (isServer)
01821     // done, stop
01822     return NS_OK;
01823   
01824   nsCOMPtr <nsIMsgFolder> parentMsgFolder;
01825   rv = aFolder->GetParentMsgFolder(getter_AddRefs(parentMsgFolder));
01826   NS_ENSURE_SUCCESS(rv,rv);
01827   if (!parentMsgFolder)
01828     return NS_OK;
01829 
01830   rv = parentMsgFolder->GetIsServer(&isServer);
01831   NS_ENSURE_SUCCESS(rv,rv);
01832  
01833   // don't need to notify servers either.
01834   if (isServer) 
01835     // done, stop
01836     return NS_OK;
01837 
01838   nsCOMPtr<nsIRDFResource> parentFolderResource = do_QueryInterface(parentMsgFolder,&rv);
01839   NS_ENSURE_SUCCESS(rv,rv);
01840 
01841   // if we're setting the subFoldersHaveUnreadMessages property to false, check
01842   // if the folder really doesn't have subfolders with unread messages.
01843   if (aPropertyResource == kNC_SubfoldersHaveUnreadMessages && aNode == kFalseLiteral)
01844   {
01845     nsCOMPtr <nsIRDFNode> unreadMsgsNode;
01846     createHasUnreadMessagesNode(parentMsgFolder, PR_TRUE, getter_AddRefs(unreadMsgsNode));
01847     aNode = unreadMsgsNode;
01848   }
01849   NotifyPropertyChanged(parentFolderResource, aPropertyResource, aNode);
01850 
01851   return NotifyAncestors(parentMsgFolder, aPropertyResource, aNode);
01852 }
01853 
01854 // New Messages
01855 
01856 nsresult
01857 nsMsgFolderDataSource::createNewMessagesNode(nsIMsgFolder *folder, nsIRDFNode **target)
01858 {
01859   
01860   nsresult rv;
01861   
01862   PRBool isServer;
01863   rv = folder->GetIsServer(&isServer);
01864   if (NS_FAILED(rv)) return rv;
01865   
01866   *target = kFalseLiteral;
01867   
01868   //PRInt32 totalNewMessages;
01869   PRBool isNewMessages;
01870   if(!isServer)
01871   {
01872     rv = folder->GetHasNewMessages(&isNewMessages);
01873     if(NS_FAILED(rv)) return rv;
01874     *target = (isNewMessages) ? kTrueLiteral : kFalseLiteral;
01875   }
01876   NS_IF_ADDREF(*target);
01877   return NS_OK;
01878 }
01879 
01913 nsresult
01914 nsMsgFolderDataSource::OnFolderSizePropertyChanged(nsIRDFResource *folderResource, PRInt32 oldValue, PRInt32 newValue)
01915 {
01916   nsCOMPtr<nsIRDFNode> newNode;
01917   GetFolderSizeNode(newValue, getter_AddRefs(newNode));
01918   NotifyPropertyChanged(folderResource, kNC_FolderSize, newNode);
01919   return NS_OK;
01920 }
01921 
01922 nsresult
01923 nsMsgFolderDataSource::OnTotalMessagePropertyChanged(nsIRDFResource *folderResource, PRInt32 oldValue, PRInt32 newValue)
01924 {
01925   nsCOMPtr<nsIRDFNode> newNode;
01926   GetNumMessagesNode(newValue, getter_AddRefs(newNode));
01927   NotifyPropertyChanged(folderResource, kNC_TotalMessages, newNode);
01928   return NS_OK;
01929 }
01930 
01931 nsresult 
01932 nsMsgFolderDataSource::GetNumMessagesNode(PRInt32 aNumMessages, nsIRDFNode **node)
01933 {
01934   PRUint32 numMessages = aNumMessages;
01935   if(numMessages == kDisplayQuestionCount)
01936     createNode(NS_LITERAL_STRING("???").get(), node, getRDFService());
01937   else if (numMessages == kDisplayBlankCount || numMessages == 0)
01938     createNode(EmptyString().get(), node, getRDFService());
01939   else
01940     createIntNode(numMessages, node, getRDFService());
01941   return NS_OK;
01942 }
01943 
01944 #define DIVISIONWITHCEIL(num, div) (num/div+((num%div>0)?1:0))
01945 
01946 nsresult 
01947 nsMsgFolderDataSource::GetFolderSizeNode(PRInt32 aFolderSize, nsIRDFNode **aNode)
01948 {
01949   PRUint32 folderSize = aFolderSize;
01950   if (folderSize == kDisplayBlankCount || folderSize == 0)
01951     createNode(EmptyString().get(), aNode, getRDFService());
01952   else if(folderSize == kDisplayQuestionCount)
01953     createNode(NS_LITERAL_STRING("???").get(), aNode, getRDFService());
01954   else
01955   {
01956     nsAutoString sizeString;
01957     // use Round or Ceil - bug #251202
01958     folderSize = DIVISIONWITHCEIL(folderSize, 1024);  // normalize into k;
01959     PRBool sizeInMB = (folderSize > 999); // 999, not 1024 - bug #251204
01960 
01961     // kKiloByteString/kMegaByteString are localized strings that we use
01962     // to get the right format to add on the "KB"/"MB" or equivalent
01963     nsTextFormatter::ssprintf(sizeString,
01964                               (sizeInMB) ? kMegaByteString : kKiloByteString,
01965                               (sizeInMB) ? DIVISIONWITHCEIL(folderSize, 1024) : folderSize);
01966     createNode(sizeString.get(), aNode, getRDFService());
01967   }
01968   return NS_OK;
01969 }
01970 
01971 nsresult
01972 nsMsgFolderDataSource::createFolderChildNode(nsIMsgFolder *folder,
01973                                              nsIRDFNode **target)
01974 {
01975   nsCOMPtr<nsIEnumerator> subFolders;
01976   nsresult rv = folder->GetSubFolders(getter_AddRefs(subFolders));
01977   if (NS_FAILED(rv))
01978     return NS_RDF_NO_VALUE;
01979   
01980   rv = subFolders->First();
01981   if (NS_SUCCEEDED(rv)) 
01982   {
01983     nsCOMPtr<nsISupports> firstFolder;
01984     rv = subFolders->CurrentItem(getter_AddRefs(firstFolder));
01985     if (NS_SUCCEEDED(rv)) 
01986       firstFolder->QueryInterface(NS_GET_IID(nsIRDFResource), (void**)target);
01987   }
01988   return NS_FAILED(rv) ? NS_RDF_NO_VALUE : rv;
01989 }
01990 
01991 
01992 nsresult nsMsgFolderDataSource::DoCopyToFolder(nsIMsgFolder *dstFolder, nsISupportsArray *arguments,
01993                                                                                 nsIMsgWindow *msgWindow, PRBool isMove)
01994 {
01995   nsresult rv;
01996   PRUint32 itemCount;
01997   rv = arguments->Count(&itemCount);
01998   if (NS_FAILED(rv)) return rv;
01999   
02000   //need source folder and at least one item to copy
02001   if(itemCount < 2)
02002     return NS_ERROR_FAILURE;
02003   
02004   
02005   nsCOMPtr<nsIMsgFolder> srcFolder(do_QueryElementAt(arguments, 0));
02006   if(!srcFolder)
02007     return NS_ERROR_FAILURE;
02008   
02009   arguments->RemoveElementAt(0);
02010   itemCount--;
02011   
02012   nsCOMPtr<nsISupportsArray> messageArray;
02013   NS_NewISupportsArray(getter_AddRefs(messageArray));
02014   
02015   for(PRUint32 i = 0; i < itemCount; i++)
02016   {
02017     
02018     nsCOMPtr<nsISupports> supports = getter_AddRefs(arguments->ElementAt(i));
02019     nsCOMPtr<nsIMsgDBHdr> message(do_QueryInterface(supports));
02020     if (message)
02021     {
02022       messageArray->AppendElement(supports);
02023     }
02024     
02025   }
02026   
02027   //Call copyservice with dstFolder, srcFolder, messages, isMove, and txnManager
02028   nsCOMPtr<nsIMsgCopyService> copyService = 
02029     do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
02030   NS_ENSURE_SUCCESS(rv,rv);
02031   
02032   return copyService->CopyMessages(srcFolder, messageArray, dstFolder, isMove, 
02033     nsnull, msgWindow, PR_TRUE/* allowUndo */);
02034 }
02035 
02036 nsresult nsMsgFolderDataSource::DoFolderCopyToFolder(nsIMsgFolder *dstFolder, nsISupportsArray *arguments,
02037                                                      nsIMsgWindow *msgWindow, PRBool isMoveFolder)
02038 {
02039   nsresult rv;
02040   PRUint32 itemCount;
02041   rv = arguments->Count(&itemCount);
02042   if (NS_FAILED(rv)) return rv;
02043   
02044   //need at least one item to copy
02045   if(itemCount < 1)
02046     return NS_ERROR_FAILURE;
02047   
02048   if (!isMoveFolder)   // copy folder not on the same server
02049   {
02050     //Call copyservice with dstFolder, srcFolder, folders and isMoveFolder
02051     nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv); 
02052     if(NS_SUCCEEDED(rv))
02053     {
02054       rv = copyService->CopyFolders(arguments, dstFolder, isMoveFolder, 
02055         nsnull, msgWindow);
02056       
02057     }
02058   }
02059   else    //within the same server therefore no need for copy service 
02060   {
02061     
02062     nsCOMPtr<nsIMsgFolder> msgFolder;
02063     for (PRUint32 i=0;i< itemCount; i++)
02064     {
02065       msgFolder = do_QueryElementAt(arguments, i, &rv);
02066       if (NS_SUCCEEDED(rv))
02067       {
02068         rv = dstFolder->CopyFolder(msgFolder, isMoveFolder , msgWindow, nsnull);
02069         NS_ASSERTION((NS_SUCCEEDED(rv)),"Copy folder failed.");
02070       }
02071     }
02072   }
02073   
02074   return rv;
02075   //return NS_OK;
02076 }
02077 
02078 nsresult nsMsgFolderDataSource::DoDeleteFromFolder(
02079                                                    nsIMsgFolder *folder, nsISupportsArray *arguments, 
02080                                                    nsIMsgWindow *msgWindow, PRBool reallyDelete)
02081 {
02082   nsresult rv = NS_OK;
02083   PRUint32 itemCount;
02084   rv = arguments->Count(&itemCount);
02085   if (NS_FAILED(rv)) return rv;
02086   
02087   nsCOMPtr<nsISupportsArray> messageArray, folderArray;
02088   NS_NewISupportsArray(getter_AddRefs(messageArray));
02089   NS_NewISupportsArray(getter_AddRefs(folderArray));
02090   
02091   //Split up deleted items into different type arrays to be passed to the folder
02092   //for deletion.
02093   for(PRUint32 item = 0; item < itemCount; item++)
02094   {
02095     nsCOMPtr<nsISupports> supports = getter_AddRefs(arguments->ElementAt(item));
02096     nsCOMPtr<nsIMsgDBHdr> deletedMessage(do_QueryInterface(supports));
02097     nsCOMPtr<nsIMsgFolder> deletedFolder(do_QueryInterface(supports));
02098     if (deletedMessage)
02099     {
02100       messageArray->AppendElement(supports);
02101     }
02102     else if(deletedFolder)
02103     {
02104       folderArray->AppendElement(supports);
02105     }
02106   }
02107   PRUint32 cnt;
02108   rv = messageArray->Count(&cnt);
02109   if (NS_FAILED(rv)) return rv;
02110   if (cnt > 0)
02111     rv = folder->DeleteMessages(messageArray, msgWindow, reallyDelete, PR_FALSE, nsnull, PR_TRUE /*allowUndo*/);
02112   
02113   rv = folderArray->Count(&cnt);
02114   if (NS_FAILED(rv)) return rv;
02115   if (cnt > 0)
02116   {
02117     nsCOMPtr<nsIMsgFolder> folderToDelete = do_QueryElementAt(folderArray, 0);
02118     PRUint32 folderFlags = 0;
02119     if (folderToDelete)
02120     {
02121       folderToDelete->GetFlags(&folderFlags);
02122       if (folderFlags & MSG_FOLDER_FLAG_VIRTUAL)
02123       {
02124         NS_ENSURE_ARG_POINTER(msgWindow);
02125         nsCOMPtr<nsIStringBundleService> sBundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
02126         nsCOMPtr<nsIStringBundle> sMessengerStringBundle;
02127         nsXPIDLString confirmMsg;
02128 
02129         if (NS_SUCCEEDED(rv) && sBundleService) 
02130           rv = sBundleService->CreateBundle(MESSENGER_STRING_URL, getter_AddRefs(sMessengerStringBundle));
02131         NS_ENSURE_SUCCESS(rv, rv);
02132         sMessengerStringBundle->GetStringFromName(NS_LITERAL_STRING("confirmSavedSearchDeleteMessage").get(), getter_Copies(confirmMsg));
02133 
02134         nsCOMPtr<nsIPrompt> dialog;
02135         rv = msgWindow->GetPromptDialog(getter_AddRefs(dialog));
02136         if (NS_SUCCEEDED(rv))
02137         {
02138           PRBool dialogResult;
02139           rv = dialog->Confirm(nsnull, confirmMsg, &dialogResult);
02140           if (!dialogResult)
02141             return NS_OK;
02142         }
02143       }
02144     }
02145     rv = folder->DeleteSubFolders(folderArray, msgWindow);
02146   }
02147   return rv;
02148 }
02149 
02150 nsresult nsMsgFolderDataSource::DoNewFolder(nsIMsgFolder *folder, nsISupportsArray *arguments, nsIMsgWindow *window)
02151 {
02152   nsresult rv = NS_OK;
02153   nsCOMPtr<nsIRDFLiteral> literal = do_QueryElementAt(arguments, 0, &rv);
02154   if(NS_SUCCEEDED(rv))
02155   {
02156     nsXPIDLString name;
02157     literal->GetValue(getter_Copies(name));
02158     
02159     rv = folder->CreateSubfolder(name, window);
02160     
02161   }
02162   return rv;
02163 }
02164 
02165 nsresult nsMsgFolderDataSource::DoFolderAssert(nsIMsgFolder *folder, nsIRDFResource *property, nsIRDFNode *target)
02166 {
02167   nsresult rv = NS_ERROR_FAILURE;
02168 
02169   if((kNC_Charset == property))
02170   {
02171     nsCOMPtr<nsIRDFLiteral> literal(do_QueryInterface(target));
02172     if(literal)
02173     {
02174       const PRUnichar* value;
02175       rv = literal->GetValueConst(&value);
02176       if(NS_SUCCEEDED(rv))
02177         rv = folder->SetCharset(NS_LossyConvertUCS2toASCII(value).get());
02178     }
02179     else
02180       rv = NS_ERROR_FAILURE;
02181   }
02182   else if (kNC_Open == property && target == kTrueLiteral)
02183       rv = folder->ClearFlag(MSG_FOLDER_FLAG_ELIDED);
02184 
02185   return rv;
02186 }
02187 
02188 nsresult nsMsgFolderDataSource::DoFolderUnassert(nsIMsgFolder *folder, nsIRDFResource *property, nsIRDFNode *target)
02189 {
02190   nsresult rv = NS_ERROR_FAILURE;
02191 
02192   if((kNC_Open == property) && target == kTrueLiteral)
02193       rv = folder->SetFlag(MSG_FOLDER_FLAG_ELIDED);
02194 
02195   return rv;
02196 }
02197 
02198 nsresult nsMsgFolderDataSource::DoFolderHasAssertion(nsIMsgFolder *folder,
02199                                                      nsIRDFResource *property,
02200                                                      nsIRDFNode *target,
02201                                                      PRBool tv,
02202                                                      PRBool *hasAssertion)
02203 {
02204   nsresult rv = NS_OK;
02205   if(!hasAssertion)
02206     return NS_ERROR_NULL_POINTER;
02207   
02208   //We're not keeping track of negative assertions on folders.
02209   if(!tv)
02210   {
02211     *hasAssertion = PR_FALSE;
02212     return NS_OK;
02213   }
02214   
02215   if((kNC_Child == property))
02216   {
02217     nsCOMPtr<nsIMsgFolder> childFolder(do_QueryInterface(target, &rv));
02218     if(NS_SUCCEEDED(rv))
02219     {
02220       nsCOMPtr<nsIMsgFolder> childsParent;
02221       rv = childFolder->GetParent(getter_AddRefs(childsParent));
02222       *hasAssertion = (NS_SUCCEEDED(rv) && childsParent && folder
02223         && (childsParent.get() == folder));
02224     }
02225   }
02226   else if ((kNC_Name == property) ||
02227     (kNC_Open == property) ||
02228     (kNC_FolderTreeName == property) ||
02229     (kNC_FolderTreeSimpleName == property) ||
02230     (kNC_SpecialFolder == property) ||
02231     (kNC_ServerType == property) ||
02232     (kNC_IsDeferred == property) ||
02233     (kNC_RedirectorType == property) ||
02234     (kNC_CanCreateFoldersOnServer == property) ||
02235     (kNC_CanFileMessagesOnServer == property) ||
02236     (kNC_IsServer == property) ||
02237     (kNC_IsSecure == property) ||
02238     (kNC_CanSubscribe == property) ||
02239     (kNC_SupportsOffline == property) ||
02240     (kNC_CanFileMessages == property) ||
02241     (kNC_CanCreateSubfolders == property) ||
02242     (kNC_CanRename == property) ||
02243     (kNC_CanCompact == property) ||
02244     (kNC_TotalMessages == property) ||
02245     (kNC_TotalUnreadMessages == property) ||
02246     (kNC_FolderSize == property) ||
02247     (kNC_Charset == property) ||
02248     (kNC_BiffState == property) ||
02249     (kNC_HasUnreadMessages == property) ||
02250     (kNC_NoSelect == property)  ||
02251     (kNC_Synchronize == property) ||
02252     (kNC_SyncDisabled == property) ||
02253     (kNC_VirtualFolder == property) ||
02254     (kNC_CanSearchMessages == property))
02255   {
02256     nsCOMPtr<nsIRDFResource> folderResource(do_QueryInterface(folder, &rv));
02257     
02258     if(NS_FAILED(rv))
02259       return rv;
02260     
02261     rv = GetTargetHasAssertion(this, folderResource, property, tv, target, hasAssertion);
02262   }
02263   else 
02264     *hasAssertion = PR_FALSE;
02265   
02266   return rv;
02267   
02268   
02269 }
02270 
02271 nsMsgFlatFolderDataSource::nsMsgFlatFolderDataSource()
02272 {
02273 }
02274 
02275 nsMsgFlatFolderDataSource::~nsMsgFlatFolderDataSource()
02276 {
02277 }
02278 
02279 nsresult nsMsgFlatFolderDataSource::Init()
02280 {
02281   nsIRDFService* rdf = getRDFService();
02282   NS_ENSURE_TRUE(rdf, NS_ERROR_FAILURE);
02283   nsCOMPtr<nsIRDFResource> source;
02284   nsCAutoString dsUri(m_dsName);
02285   dsUri.Append(":/");
02286   rdf->GetResource(dsUri, getter_AddRefs(m_rootResource));
02287 
02288   return nsMsgFolderDataSource::Init();
02289 }
02290 
02291 void nsMsgFlatFolderDataSource::Cleanup()
02292 {
02293   m_folders.Clear();
02294   nsMsgFolderDataSource::Cleanup();
02295 }
02296 
02297 NS_IMETHODIMP nsMsgFlatFolderDataSource::GetTarget(nsIRDFResource* source,
02298                        nsIRDFResource* property,
02299                        PRBool tv,
02300                        nsIRDFNode** target)
02301 {
02302   return (property == kNC_Child) 
02303     ? NS_RDF_NO_VALUE
02304     : nsMsgFolderDataSource::GetTarget(source, property, tv, target);
02305 }
02306 
02307 
02308 NS_IMETHODIMP nsMsgFlatFolderDataSource::GetTargets(nsIRDFResource* source,
02309                                                 nsIRDFResource* property,    
02310                                                 PRBool tv,
02311                                                 nsISimpleEnumerator** targets)
02312 {
02313   if (kNC_Child != property)
02314     return nsMsgFolderDataSource::GetTargets(source, property, tv, targets);
02315 
02316   nsresult rv = NS_RDF_NO_VALUE;
02317   if(!targets)
02318     return NS_ERROR_NULL_POINTER;
02319 
02320   if (ResourceIsOurRoot(source))
02321   {
02322     // need an enumerator that gives all folders with unread
02323     nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
02324     NS_ENSURE_SUCCESS(rv,rv);
02325 
02326     nsCOMPtr<nsISupportsArray> allServers;
02327     rv = accountManager->GetAllServers(getter_AddRefs(allServers));
02328     nsCOMPtr <nsISupportsArray> allFolders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);;
02329     if (NS_SUCCEEDED(rv) && allServers)
02330     {
02331       PRUint32 count = 0;
02332       allServers->Count(&count);
02333       PRUint32 i;
02334       for (i = 0; i < count; i++) 
02335       {
02336         nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(allServers, i);
02337         if (server)
02338         {
02339           nsCOMPtr <nsIMsgFolder> rootFolder;
02340           server->GetRootFolder(getter_AddRefs(rootFolder));
02341           if (rootFolder)
02342           {
02343             nsCOMPtr<nsIEnumerator> subFolders;
02344             rv = rootFolder->GetSubFolders(getter_AddRefs(subFolders));
02345 
02346             PRUint32 lastEntry;
02347             allFolders->Count(&lastEntry);
02348             rv = rootFolder->ListDescendents(allFolders);
02349             PRUint32 newLastEntry;
02350             allFolders->Count(&newLastEntry);
02351             for (PRUint32 newEntryIndex = lastEntry; newEntryIndex < newLastEntry;)
02352             {
02353               nsCOMPtr <nsIMsgFolder> curFolder = do_QueryElementAt(allFolders, newEntryIndex);
02354               if (!WantsThisFolder(curFolder))
02355               {
02356                 allFolders->RemoveElementAt(newEntryIndex);
02357                 newLastEntry--;
02358               }
02359               else
02360               {
02361                 // unfortunately, we need a separate array for this since
02362                 // ListDescendents takes an nsISupportsArray. But we want
02363                 // to use an nsCOMArrray for the DS since that's the 
02364                 // preferred mechanism.
02365                 m_folders.AppendObject(curFolder);
02366                 newEntryIndex++;
02367               }
02368             }
02369           }
02370         }
02371       }
02372       return NS_NewArrayEnumerator(targets, allFolders);
02373     }
02374   }
02375   nsSingletonEnumerator* cursor = new nsSingletonEnumerator(property);
02376   if (cursor == nsnull)
02377     return NS_ERROR_OUT_OF_MEMORY;
02378   NS_ADDREF(*targets = cursor);
02379   return NS_OK;
02380 }
02381 
02382 
02383 NS_IMETHODIMP nsMsgFlatFolderDataSource::GetURI(char* *aUri)
02384 {
02385   nsCAutoString uri("rdf:");
02386   uri.Append(m_dsName);
02387   return (*aUri = ToNewCString(uri))
02388     ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
02389 }
02390 
02391 NS_IMETHODIMP nsMsgFlatFolderDataSource::HasAssertion(nsIRDFResource* source,
02392                             nsIRDFResource* property,
02393                             nsIRDFNode* target,
02394                             PRBool tv,
02395                             PRBool* hasAssertion)
02396 {
02397   nsresult rv;
02398   
02399   nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
02400   // we need to check if the folder belongs in this datasource.
02401   if (NS_SUCCEEDED(rv) && property != kNC_Open && property != kNC_Child)
02402   {
02403     if (WantsThisFolder(folder) && (kNC_Child != property))
02404       return DoFolderHasAssertion(folder, property, target, tv, hasAssertion);
02405   }
02406   else if (property == kNC_Child && ResourceIsOurRoot(source)) // check if source is us
02407   {
02408     folder = do_QueryInterface(target);
02409     if (folder)
02410     {
02411       nsCOMPtr<nsIMsgFolder> parentMsgFolder;
02412       folder->GetParentMsgFolder(getter_AddRefs(parentMsgFolder));
02413       // a folder without a parent must be getting deleted as part of
02414       // the rename operation and is thus a folder we are 
02415       // no longer interested in
02416       if (parentMsgFolder && WantsThisFolder(folder))
02417       {
02418         *hasAssertion = PR_TRUE;
02419         return NS_OK;
02420       }
02421     }
02422   }
02423   *hasAssertion = PR_FALSE;
02424   return NS_OK;
02425 }
02426 
02427 nsresult nsMsgFlatFolderDataSource::OnItemAddedOrRemoved(nsIRDFResource *parentItem, nsISupports *item, PRBool added)
02428 {
02429   // When a folder is added or removed, parentItem is the parent folder and item is the folder being
02430   // added or removed. In a flat data source, there is no arc in the graph between the parent folder
02431   // and the folder being added or removed. Our flat data source root (i.e. mailnewsunreadfolders:/) has 
02432   // an arc with the child property to every folder in the data source.  We must change parentItem
02433   // to be our data source root before calling nsMsgFolderDataSource::OnItemAddedOrRemoved. This ensures
02434   // that datasource listeners such as the template builder properly handle add and remove 
02435   // notifications on the flat datasource.
02436   return nsMsgFolderDataSource::OnItemAddedOrRemoved(m_rootResource, item, added);
02437 }
02438 
02439 PRBool nsMsgFlatFolderDataSource::ResourceIsOurRoot(nsIRDFResource *resource)
02440 {
02441   return m_rootResource.get() == resource;
02442 }
02443 
02444 PRBool nsMsgFlatFolderDataSource::WantsThisFolder(nsIMsgFolder *folder)
02445 {
02446   NS_ASSERTION(PR_FALSE, "must be overridden");
02447   return PR_FALSE;
02448 }
02449 
02450 nsresult nsMsgFlatFolderDataSource::GetFolderDisplayName(nsIMsgFolder *folder, PRUnichar **folderName)
02451 {
02452   nsXPIDLString curFolderName;
02453   folder->GetName(getter_Copies(curFolderName));
02454   PRUint32 foldersCount = m_folders.Count();
02455   nsXPIDLString otherFolderName;
02456   for (PRUint32 index = 0; index < foldersCount; index++)
02457   {
02458     if (folder == m_folders[index]) // ignore ourselves.
02459       continue;
02460     m_folders[index]->GetName(getter_Copies(otherFolderName));
02461     if (otherFolderName.Equals(curFolderName))
02462     {
02463       nsCOMPtr <nsIMsgIncomingServer> server;
02464       folder->GetServer(getter_AddRefs(server));
02465       if (server)
02466       {
02467         nsXPIDLString serverName;
02468         server->GetPrettyName(getter_Copies(serverName));
02469         curFolderName.Append(NS_LITERAL_STRING(" - "));
02470         curFolderName.Append(serverName);
02471         *folderName = ToNewUnicode(curFolderName);
02472         return (*folderName) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
02473       }
02474     }
02475   }
02476   // check if folder name is unique - if not, append account name
02477   return folder->GetAbbreviatedName(folderName);
02478 }
02479 
02480 
02481 PRBool nsMsgUnreadFoldersDataSource::WantsThisFolder(nsIMsgFolder *folder)
02482 {
02483   PRInt32 numUnread;
02484   folder->GetNumUnread(PR_FALSE, &numUnread);
02485   return numUnread > 0;
02486 }
02487 
02488 nsresult nsMsgUnreadFoldersDataSource::NotifyPropertyChanged(nsIRDFResource *resource, 
02489                     nsIRDFResource *property, nsIRDFNode *newNode, 
02490                     nsIRDFNode *oldNode)
02491 {
02492   // check if it's the has unread property that's changed; if so, see if we need
02493   // to add this folder to the view.
02494   // Then, call base class.
02495   if (kNC_HasUnreadMessages == property)
02496   {
02497     nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(resource));
02498     if (folder)
02499     {
02500       PRInt32 numUnread;
02501       folder->GetNumUnread(PR_FALSE, &numUnread);
02502       if (numUnread > 0)
02503       {
02504         if (m_folders.IndexOf(folder) == kNotFound)
02505           m_folders.AppendObject(folder);
02506         NotifyObservers(kNC_UnreadFolders, kNC_Child, resource, nsnull, PR_TRUE, PR_FALSE);
02507       }
02508     }
02509   }
02510   return nsMsgFolderDataSource::NotifyPropertyChanged(resource, property, 
02511                                                 newNode, oldNode);
02512 }
02513 
02514 PRBool nsMsgFavoriteFoldersDataSource::WantsThisFolder(nsIMsgFolder *folder)
02515 {
02516   PRUint32 folderFlags;
02517   folder->GetFlags(&folderFlags);
02518   return folderFlags & MSG_FOLDER_FLAG_FAVORITE;
02519 }
02520 
02521 
02522 void nsMsgRecentFoldersDataSource::Cleanup()
02523 {
02524   m_builtRecentFolders = PR_FALSE;
02525   m_cutOffDate = 0;
02526   nsMsgFlatFolderDataSource::Cleanup();
02527 }
02528 
02529 
02530 PRBool nsMsgRecentFoldersDataSource::WantsThisFolder(nsIMsgFolder *folder)
02531 {
02532   if (!m_builtRecentFolders)
02533   {
02534     nsresult rv;
02535     nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
02536     NS_ENSURE_SUCCESS(rv,rv);
02537 
02538     nsCOMPtr<nsISupportsArray> allServers;
02539     rv = accountManager->GetAllServers(getter_AddRefs(allServers));
02540     nsCOMPtr <nsISupportsArray> allFolders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);;
02541     if (NS_SUCCEEDED(rv) && allServers)
02542     {
02543       PRUint32 count = 0;
02544       allServers->Count(&count);
02545       PRUint32 i;
02546       for (i = 0; i < count; i++) 
02547       {
02548         nsCOMPtr<nsIMsgIncomingServer> server = do_QueryElementAt(allServers, i);
02549         if (server)
02550         {
02551           nsCOMPtr <nsIMsgFolder> rootFolder;
02552           server->GetRootFolder(getter_AddRefs(rootFolder));
02553           if (rootFolder)
02554           {
02555             nsCOMPtr<nsIEnumerator> subFolders;
02556             rv = rootFolder->GetSubFolders(getter_AddRefs(subFolders));
02557 
02558             PRUint32 lastEntry;
02559             allFolders->Count(&lastEntry);
02560             rv = rootFolder->ListDescendents(allFolders);
02561             PRUint32 newLastEntry;
02562             allFolders->Count(&newLastEntry);
02563             for (PRUint32 newEntryIndex = lastEntry; newEntryIndex < newLastEntry; newEntryIndex++)
02564             {
02565               nsCOMPtr <nsIMsgFolder> curFolder = do_QueryElementAt(allFolders, newEntryIndex);
02566               nsXPIDLCString dateStr;
02567               PRInt32 err;
02568               curFolder->GetStringProperty(MRU_TIME_PROPERTY, getter_Copies(dateStr));
02569               PRUint32 curFolderDate = (PRUint32) dateStr.ToInteger(&err);
02570               if (err)
02571                 curFolderDate = 0;
02572               if (curFolderDate > m_cutOffDate)
02573               {
02574                 // if m_folders is "full", replace oldest folder with this folder,
02575                 // and adjust m_cutOffDate so that it's the mrutime 
02576                 // of the "new" oldest folder.
02577                 PRUint32 curFaveFoldersCount = m_folders.Count();
02578                 if (curFaveFoldersCount > m_maxNumFolders)
02579                 {
02580                   PRUint32 indexOfOldestFolder = 0;
02581                   PRUint32 oldestFaveDate = 0;
02582                   PRUint32 newOldestFaveDate = 0;
02583                   for (PRUint32 index = 0; index < curFaveFoldersCount; )
02584                   {
02585                     nsXPIDLCString curFaveFolderDateStr;
02586                     m_folders[index]->GetStringProperty(MRU_TIME_PROPERTY, getter_Copies(curFaveFolderDateStr));
02587                     PRUint32 curFaveFolderDate = (PRUint32) curFaveFolderDateStr.ToInteger(&err);
02588                     if (!oldestFaveDate || curFaveFolderDate < oldestFaveDate)
02589                     {
02590                       indexOfOldestFolder = index;
02591                       newOldestFaveDate = oldestFaveDate;
02592                       oldestFaveDate = curFaveFolderDate;
02593                     }
02594                     if (!newOldestFaveDate || (index != indexOfOldestFolder
02595                                                 && curFaveFolderDate < newOldestFaveDate))
02596                       newOldestFaveDate = curFaveFolderDate;
02597                     index++;
02598                   }
02599                   if (curFolderDate > oldestFaveDate && m_folders.IndexOf(curFolder) == kNotFound)
02600                     m_folders.ReplaceObjectAt(curFolder, indexOfOldestFolder);
02601 
02602                   NS_ASSERTION(newOldestFaveDate >= m_cutOffDate, "cutoff date should be getting bigger");
02603                   m_cutOffDate = newOldestFaveDate;
02604                 }
02605                 else if (m_folders.IndexOf(curFolder) == kNotFound)
02606                   m_folders.AppendObject(curFolder);
02607               }
02608 #ifdef DEBUG_David_Bienvenu
02609               else
02610               {
02611                 for (PRUint32 index = 0; index < m_folders.Count(); index++)
02612                 {
02613                   nsXPIDLCString curFaveFolderDateStr;
02614                   m_folders[index]->GetStringProperty(MRU_TIME_PROPERTY, getter_Copies(curFaveFolderDateStr));
02615                   PRUint32 curFaveFolderDate = (PRUint32) curFaveFolderDateStr.ToInteger(&err);
02616                   NS_ASSERTION(curFaveFolderDate > curFolderDate, "folder newer then faves but not added");
02617                 }
02618               }
02619 #endif
02620             }
02621           }
02622         }
02623       }
02624     }
02625   }
02626   m_builtRecentFolders = PR_TRUE;
02627   return m_folders.IndexOf(folder) != kNotFound;
02628 }
02629 
02630 NS_IMETHODIMP nsMsgRecentFoldersDataSource::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
02631 {
02632   // if we've already built the recent folder array, we should add this item to the array
02633   // since just added items are by definition new.
02634   // I think this means newly discovered imap folders (ones w/o msf files) will
02635   // get added, but maybe that's OK.
02636   if (m_builtRecentFolders)
02637   {
02638     nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(item));
02639     if (folder && m_folders.IndexOf(folder) == kNotFound)
02640     {
02641       m_folders.AppendObject(folder);
02642       nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(item);
02643       NotifyObservers(kNC_RecentFolders, kNC_Child, resource, nsnull, PR_TRUE, PR_FALSE);
02644     }
02645   }
02646   return nsMsgFlatFolderDataSource::OnItemAdded(parentItem, item);
02647 }
02648 
02649 
02650 nsresult nsMsgRecentFoldersDataSource::NotifyPropertyChanged(nsIRDFResource *resource, 
02651                     nsIRDFResource *property, nsIRDFNode *newNode, 
02652                     nsIRDFNode *oldNode)
02653 {
02654   // check if it's the has new property that's changed; if so, see if we need
02655   // to add this folder to the view.
02656   // Then, call base class.
02657   if (kNC_NewMessages == property)
02658   {
02659     nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(resource));
02660     if (folder)
02661     {
02662       PRBool hasNewMessages;
02663       folder->GetHasNewMessages(&hasNewMessages);
02664       if (hasNewMessages > 0)
02665       {
02666         if (m_folders.IndexOf(folder) == kNotFound)
02667         {
02668           m_folders.AppendObject(folder);
02669           NotifyObservers(kNC_RecentFolders, kNC_Child, resource, nsnull, PR_TRUE, PR_FALSE);
02670         }
02671       }
02672     }
02673   }
02674   return nsMsgFolderDataSource::NotifyPropertyChanged(resource, property, 
02675                                                 newNode, oldNode);
02676 }