1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "msgCore.h"
7 #include "nsDBFolderInfo.h"
8 #include "nsMsgDatabase.h"
9 #include "nsMsgFolderFlags.h"
10 #include "nsIPrefService.h"
11 #include "nsIPrefBranch.h"
12 #include "nsIPrefLocalizedString.h"
13 #include "nsIObserver.h"
14 #include "nsIObserverService.h"
15 #include "nsIMsgDBView.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsImapCore.h"
18 #include "mozilla/Services.h"
19 
20 static const char* kDBFolderInfoScope = "ns:msg:db:row:scope:dbfolderinfo:all";
21 static const char* kDBFolderInfoTableKind = "ns:msg:db:table:kind:dbfolderinfo";
22 
23 struct mdbOid gDBFolderInfoOID;
24 
25 static const char* kNumMessagesColumnName = "numMsgs";
26 // have to leave this as numNewMsgs even though it's numUnread Msgs
27 static const char* kNumUnreadMessagesColumnName = "numNewMsgs";
28 static const char* kFlagsColumnName = "flags";
29 static const char* kFolderSizeColumnName = "folderSize";
30 static const char* kExpungedBytesColumnName = "expungedBytes";
31 static const char* kFolderDateColumnName = "folderDate";
32 static const char* kHighWaterMessageKeyColumnName = "highWaterKey";
33 
34 static const char* kImapUidValidityColumnName = "UIDValidity";
35 static const char* kTotalPendingMessagesColumnName = "totPendingMsgs";
36 static const char* kUnreadPendingMessagesColumnName = "unreadPendingMsgs";
37 static const char* kMailboxNameColumnName = "mailboxName";
38 static const char* kKnownArtsSetColumnName = "knownArts";
39 static const char* kExpiredMarkColumnName = "expiredMark";
40 static const char* kVersionColumnName = "version";
41 static const char* kLocaleColumnName = "locale";
42 
43 NS_IMPL_ADDREF(nsDBFolderInfo)
NS_IMPL_RELEASE(nsDBFolderInfo)44 NS_IMPL_RELEASE(nsDBFolderInfo)
45 
46 NS_IMETHODIMP
47 nsDBFolderInfo::QueryInterface(REFNSIID iid, void** result) {
48   if (!result) return NS_ERROR_NULL_POINTER;
49 
50   *result = nullptr;
51   if (iid.Equals(NS_GET_IID(nsIDBFolderInfo)) ||
52       iid.Equals(NS_GET_IID(nsISupports))) {
53     *result = static_cast<nsIDBFolderInfo*>(this);
54     AddRef();
55     return NS_OK;
56   }
57   return NS_NOINTERFACE;
58 }
59 
nsDBFolderInfo(nsMsgDatabase * mdb)60 nsDBFolderInfo::nsDBFolderInfo(nsMsgDatabase* mdb)
61     : m_flags(0), m_expiredMark(0), m_expiredMarkColumnToken(0) {
62   m_mdbTable = NULL;
63   m_mdbRow = NULL;
64   m_version = 1;                 // for upgrading...
65   m_IMAPHierarchySeparator = 0;  // imap path separator
66   // mail only (for now)
67   m_folderSize = 0;
68   m_folderDate = 0;
69   m_expungedBytes = 0;  // sum of size of deleted messages in folder
70   m_highWaterMessageKey = 0;
71 
72   m_numUnreadMessages = 0;
73   m_numMessages = 0;
74   // IMAP only
75   m_ImapUidValidity = kUidUnknown;
76   m_totalPendingMessages = 0;
77   m_unreadPendingMessages = 0;
78 
79   m_mdbTokensInitialized = false;
80 
81   m_mdb = mdb;
82   if (mdb) {
83     nsresult err;
84 
85     err = m_mdb->GetStore()->StringToToken(mdb->GetEnv(), kDBFolderInfoScope,
86                                            &m_rowScopeToken);
87     if (NS_SUCCEEDED(err)) {
88       err = m_mdb->GetStore()->StringToToken(
89           mdb->GetEnv(), kDBFolderInfoTableKind, &m_tableKindToken);
90       if (NS_SUCCEEDED(err)) {
91         gDBFolderInfoOID.mOid_Scope = m_rowScopeToken;
92         gDBFolderInfoOID.mOid_Id = 1;
93       }
94     }
95     InitMDBInfo();
96   }
97 }
98 
~nsDBFolderInfo()99 nsDBFolderInfo::~nsDBFolderInfo() {
100   // nsMsgDatabase strictly owns nsDBFolderInfo, so don't ref-count db.
101   ReleaseExternalReferences();
102 }
103 
104 // Release any objects we're holding onto. This needs to be safe
105 // to call multiple times.
ReleaseExternalReferences()106 void nsDBFolderInfo::ReleaseExternalReferences() {
107   if (m_mdb) {
108     if (m_mdbTable) {
109       NS_RELEASE(m_mdbTable);
110       m_mdbTable = nullptr;
111     }
112     if (m_mdbRow) {
113       NS_RELEASE(m_mdbRow);
114       m_mdbRow = nullptr;
115     }
116     m_mdb = nullptr;
117   }
118 }
119 
120 // this routine sets up a new db to know about the dbFolderInfo stuff...
AddToNewMDB()121 nsresult nsDBFolderInfo::AddToNewMDB() {
122   nsresult ret = NS_OK;
123   if (m_mdb && m_mdb->GetStore()) {
124     nsIMdbStore* store = m_mdb->GetStore();
125     // create the unique table for the dbFolderInfo.
126     nsresult err =
127         store->NewTable(m_mdb->GetEnv(), m_rowScopeToken, m_tableKindToken,
128                         true, nullptr, &m_mdbTable);
129 
130     // create the singleton row for the dbFolderInfo.
131     err = store->NewRowWithOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &m_mdbRow);
132 
133     // add the row to the singleton table.
134     if (m_mdbRow && NS_SUCCEEDED(err))
135       err = m_mdbTable->AddRow(m_mdb->GetEnv(), m_mdbRow);
136 
137     ret = err;  // what are we going to do about nsresult's?
138   }
139   return ret;
140 }
141 
InitFromExistingDB()142 nsresult nsDBFolderInfo::InitFromExistingDB() {
143   nsresult ret = NS_OK;
144   if (m_mdb && m_mdb->GetStore()) {
145     nsIMdbStore* store = m_mdb->GetStore();
146     if (store) {
147       mdb_pos rowPos;
148       mdb_count outTableCount;  // current number of such tables
149       mdb_bool mustBeUnique;    // whether port can hold only one of these
150       mdb_bool hasOid;
151       ret = store->GetTableKind(m_mdb->GetEnv(), m_rowScopeToken,
152                                 m_tableKindToken, &outTableCount, &mustBeUnique,
153                                 &m_mdbTable);
154       // NS_ASSERTION(mustBeUnique && outTableCount == 1, "only one global db
155       // info allowed");
156 
157       if (m_mdbTable) {
158         // find singleton row for global info.
159         ret = m_mdbTable->HasOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &hasOid);
160         if (NS_SUCCEEDED(ret)) {
161           nsIMdbTableRowCursor* rowCursor;
162           rowPos = -1;
163           ret = m_mdbTable->GetTableRowCursor(m_mdb->GetEnv(), rowPos,
164                                               &rowCursor);
165           if (NS_SUCCEEDED(ret)) {
166             ret = rowCursor->NextRow(m_mdb->GetEnv(), &m_mdbRow, &rowPos);
167             NS_RELEASE(rowCursor);
168             if (!m_mdbRow) ret = NS_ERROR_FAILURE;
169             if (NS_SUCCEEDED(ret)) LoadMemberVariables();
170           }
171         }
172       } else
173         ret = NS_ERROR_FAILURE;
174     }
175   }
176   return ret;
177 }
178 
InitMDBInfo()179 nsresult nsDBFolderInfo::InitMDBInfo() {
180   nsresult ret = NS_OK;
181   if (!m_mdbTokensInitialized && m_mdb && m_mdb->GetStore()) {
182     nsIMdbStore* store = m_mdb->GetStore();
183     nsIMdbEnv* env = m_mdb->GetEnv();
184 
185     store->StringToToken(env, kNumMessagesColumnName,
186                          &m_numMessagesColumnToken);
187     store->StringToToken(env, kNumUnreadMessagesColumnName,
188                          &m_numUnreadMessagesColumnToken);
189     store->StringToToken(env, kFlagsColumnName, &m_flagsColumnToken);
190     store->StringToToken(env, kFolderSizeColumnName, &m_folderSizeColumnToken);
191     store->StringToToken(env, kExpungedBytesColumnName,
192                          &m_expungedBytesColumnToken);
193     store->StringToToken(env, kFolderDateColumnName, &m_folderDateColumnToken);
194 
195     store->StringToToken(env, kHighWaterMessageKeyColumnName,
196                          &m_highWaterMessageKeyColumnToken);
197     store->StringToToken(env, kMailboxNameColumnName,
198                          &m_mailboxNameColumnToken);
199 
200     store->StringToToken(env, kImapUidValidityColumnName,
201                          &m_imapUidValidityColumnToken);
202     store->StringToToken(env, kTotalPendingMessagesColumnName,
203                          &m_totalPendingMessagesColumnToken);
204     store->StringToToken(env, kUnreadPendingMessagesColumnName,
205                          &m_unreadPendingMessagesColumnToken);
206     store->StringToToken(env, kExpiredMarkColumnName,
207                          &m_expiredMarkColumnToken);
208     store->StringToToken(env, kVersionColumnName, &m_versionColumnToken);
209     m_mdbTokensInitialized = true;
210   }
211 
212   return ret;
213 }
214 
LoadMemberVariables()215 nsresult nsDBFolderInfo::LoadMemberVariables() {
216   // it's really not an error for these properties to not exist...
217   GetInt32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
218   GetInt32PropertyWithToken(m_numUnreadMessagesColumnToken,
219                             m_numUnreadMessages);
220   GetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
221   GetInt64PropertyWithToken(m_folderSizeColumnToken, m_folderSize);
222   GetUint32PropertyWithToken(m_folderDateColumnToken, m_folderDate);
223   GetInt32PropertyWithToken(m_imapUidValidityColumnToken, m_ImapUidValidity,
224                             kUidUnknown);
225   GetUint32PropertyWithToken(m_expiredMarkColumnToken, m_expiredMark);
226   GetInt64PropertyWithToken(m_expungedBytesColumnToken, m_expungedBytes);
227   GetUint32PropertyWithToken(m_highWaterMessageKeyColumnToken,
228                              m_highWaterMessageKey);
229   int32_t version;
230 
231   GetInt32PropertyWithToken(m_versionColumnToken, version);
232   m_version = (uint16_t)version;
233 
234   return NS_OK;
235 }
236 
SetVersion(uint32_t version)237 NS_IMETHODIMP nsDBFolderInfo::SetVersion(uint32_t version) {
238   m_version = version;
239   return SetUint32PropertyWithToken(m_versionColumnToken, (uint32_t)m_version);
240 }
241 
GetVersion(uint32_t * version)242 NS_IMETHODIMP nsDBFolderInfo::GetVersion(uint32_t* version) {
243   *version = m_version;
244   return NS_OK;
245 }
246 
AdjustHighWater(nsMsgKey highWater,bool force)247 nsresult nsDBFolderInfo::AdjustHighWater(nsMsgKey highWater, bool force) {
248   if (force || m_highWaterMessageKey < highWater) {
249     m_highWaterMessageKey = highWater;
250     SetUint32PropertyWithToken(m_highWaterMessageKeyColumnToken, highWater);
251   }
252 
253   return NS_OK;
254 }
255 
SetHighWater(nsMsgKey highWater)256 NS_IMETHODIMP nsDBFolderInfo::SetHighWater(nsMsgKey highWater) {
257   return AdjustHighWater(highWater, true);
258 }
259 
OnKeyAdded(nsMsgKey aNewKey)260 NS_IMETHODIMP nsDBFolderInfo::OnKeyAdded(nsMsgKey aNewKey) {
261   return AdjustHighWater(aNewKey, false);
262 }
263 
264 NS_IMETHODIMP
GetFolderSize(int64_t * size)265 nsDBFolderInfo::GetFolderSize(int64_t* size) {
266   NS_ENSURE_ARG_POINTER(size);
267   *size = m_folderSize;
268   return NS_OK;
269 }
270 
SetFolderSize(int64_t size)271 NS_IMETHODIMP nsDBFolderInfo::SetFolderSize(int64_t size) {
272   m_folderSize = size;
273   return SetInt64Property(kFolderSizeColumnName, m_folderSize);
274 }
275 
276 NS_IMETHODIMP
GetFolderDate(uint32_t * folderDate)277 nsDBFolderInfo::GetFolderDate(uint32_t* folderDate) {
278   NS_ENSURE_ARG_POINTER(folderDate);
279   *folderDate = m_folderDate;
280   return NS_OK;
281 }
282 
SetFolderDate(uint32_t folderDate)283 NS_IMETHODIMP nsDBFolderInfo::SetFolderDate(uint32_t folderDate) {
284   m_folderDate = folderDate;
285   return SetUint32PropertyWithToken(m_folderDateColumnToken, folderDate);
286 }
287 
GetHighWater(nsMsgKey * result)288 NS_IMETHODIMP nsDBFolderInfo::GetHighWater(nsMsgKey* result) {
289   // Sanity check highwater - if it gets too big, other code
290   // can fail. Look through last 100 messages to recalculate
291   // the highwater mark.
292   *result = m_highWaterMessageKey;
293   if (m_highWaterMessageKey > 0xFFFFFF00 && m_mdb) {
294     nsCOMPtr<nsIMsgEnumerator> hdrs;
295     nsresult rv = m_mdb->ReverseEnumerateMessages(getter_AddRefs(hdrs));
296     if (NS_FAILED(rv)) return rv;
297     bool hasMore = false;
298     nsCOMPtr<nsIMsgDBHdr> pHeader;
299     nsMsgKey recalculatedHighWater = 1;
300     int32_t i = 0;
301     while (i++ < 100 && NS_SUCCEEDED(rv = hdrs->HasMoreElements(&hasMore)) &&
302            hasMore) {
303       (void)hdrs->GetNext(getter_AddRefs(pHeader));
304       if (pHeader) {
305         nsMsgKey msgKey;
306         pHeader->GetMessageKey(&msgKey);
307         if (msgKey > recalculatedHighWater) recalculatedHighWater = msgKey;
308       }
309     }
310     NS_ASSERTION(m_highWaterMessageKey >= recalculatedHighWater,
311                  "highwater incorrect");
312     m_highWaterMessageKey = recalculatedHighWater;
313   }
314   *result = m_highWaterMessageKey;
315   return NS_OK;
316 }
317 
SetExpiredMark(nsMsgKey expiredKey)318 NS_IMETHODIMP nsDBFolderInfo::SetExpiredMark(nsMsgKey expiredKey) {
319   m_expiredMark = expiredKey;
320   return SetUint32PropertyWithToken(m_expiredMarkColumnToken, expiredKey);
321 }
322 
GetExpiredMark(nsMsgKey * result)323 NS_IMETHODIMP nsDBFolderInfo::GetExpiredMark(nsMsgKey* result) {
324   *result = m_expiredMark;
325   return NS_OK;
326 }
327 
328 // The size of the argument depends on the maximum size of a single message
ChangeExpungedBytes(int32_t delta)329 NS_IMETHODIMP nsDBFolderInfo::ChangeExpungedBytes(int32_t delta) {
330   return SetExpungedBytes(m_expungedBytes + delta);
331 }
332 
SetMailboxName(const nsAString & newBoxName)333 NS_IMETHODIMP nsDBFolderInfo::SetMailboxName(const nsAString& newBoxName) {
334   return SetPropertyWithToken(m_mailboxNameColumnToken, newBoxName);
335 }
336 
GetMailboxName(nsAString & boxName)337 NS_IMETHODIMP nsDBFolderInfo::GetMailboxName(nsAString& boxName) {
338   return GetPropertyWithToken(m_mailboxNameColumnToken, boxName);
339 }
340 
ChangeNumUnreadMessages(int32_t delta)341 NS_IMETHODIMP nsDBFolderInfo::ChangeNumUnreadMessages(int32_t delta) {
342   m_numUnreadMessages += delta;
343   // m_numUnreadMessages can never be set to negative.
344   if (m_numUnreadMessages < 0) {
345 #ifdef DEBUG_bienvenu1
346     NS_ASSERTION(false, "Hardcoded assertion");
347 #endif
348     m_numUnreadMessages = 0;
349   }
350   return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken,
351                                     m_numUnreadMessages);
352 }
353 
ChangeNumMessages(int32_t delta)354 NS_IMETHODIMP nsDBFolderInfo::ChangeNumMessages(int32_t delta) {
355   m_numMessages += delta;
356   // m_numMessages can never be set to negative.
357   if (m_numMessages < 0) {
358 #ifdef DEBUG_bienvenu
359     NS_ASSERTION(false, "num messages can't be < 0");
360 #endif
361     m_numMessages = 0;
362   }
363   return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
364 }
365 
GetNumUnreadMessages(int32_t * result)366 NS_IMETHODIMP nsDBFolderInfo::GetNumUnreadMessages(int32_t* result) {
367   *result = m_numUnreadMessages;
368   return NS_OK;
369 }
370 
SetNumUnreadMessages(int32_t numUnreadMessages)371 NS_IMETHODIMP nsDBFolderInfo::SetNumUnreadMessages(int32_t numUnreadMessages) {
372   m_numUnreadMessages = numUnreadMessages;
373   return SetUint32PropertyWithToken(m_numUnreadMessagesColumnToken,
374                                     m_numUnreadMessages);
375 }
376 
GetNumMessages(int32_t * result)377 NS_IMETHODIMP nsDBFolderInfo::GetNumMessages(int32_t* result) {
378   *result = m_numMessages;
379   return NS_OK;
380 }
381 
SetNumMessages(int32_t numMessages)382 NS_IMETHODIMP nsDBFolderInfo::SetNumMessages(int32_t numMessages) {
383   m_numMessages = numMessages;
384   return SetUint32PropertyWithToken(m_numMessagesColumnToken, m_numMessages);
385 }
386 
GetExpungedBytes(int64_t * result)387 NS_IMETHODIMP nsDBFolderInfo::GetExpungedBytes(int64_t* result) {
388   *result = m_expungedBytes;
389   return NS_OK;
390 }
391 
SetExpungedBytes(int64_t expungedBytes)392 NS_IMETHODIMP nsDBFolderInfo::SetExpungedBytes(int64_t expungedBytes) {
393   m_expungedBytes = expungedBytes;
394   return SetInt64PropertyWithToken(m_expungedBytesColumnToken, m_expungedBytes);
395 }
396 
GetFlags(int32_t * result)397 NS_IMETHODIMP nsDBFolderInfo::GetFlags(int32_t* result) {
398   *result = m_flags;
399   return NS_OK;
400 }
401 
SetFlags(int32_t flags)402 NS_IMETHODIMP nsDBFolderInfo::SetFlags(int32_t flags) {
403   nsresult ret = NS_OK;
404 
405   if (m_flags != flags) {
406     NS_ASSERTION((m_flags & nsMsgFolderFlags::Inbox) == 0 ||
407                      (flags & nsMsgFolderFlags::Inbox) != 0,
408                  "lost inbox flag");
409     m_flags = flags;
410     ret = SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
411   }
412   return ret;
413 }
414 
OrFlags(int32_t flags,int32_t * result)415 NS_IMETHODIMP nsDBFolderInfo::OrFlags(int32_t flags, int32_t* result) {
416   m_flags |= flags;
417   *result = m_flags;
418   return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
419 }
420 
AndFlags(int32_t flags,int32_t * result)421 NS_IMETHODIMP nsDBFolderInfo::AndFlags(int32_t flags, int32_t* result) {
422   m_flags &= flags;
423   *result = m_flags;
424   return SetInt32PropertyWithToken(m_flagsColumnToken, m_flags);
425 }
426 
GetImapUidValidity(int32_t * result)427 NS_IMETHODIMP nsDBFolderInfo::GetImapUidValidity(int32_t* result) {
428   *result = m_ImapUidValidity;
429   return NS_OK;
430 }
431 
SetImapUidValidity(int32_t uidValidity)432 NS_IMETHODIMP nsDBFolderInfo::SetImapUidValidity(int32_t uidValidity) {
433   m_ImapUidValidity = uidValidity;
434   return SetUint32PropertyWithToken(m_imapUidValidityColumnToken,
435                                     m_ImapUidValidity);
436 }
437 
TestFlag(int32_t flags)438 bool nsDBFolderInfo::TestFlag(int32_t flags) { return (m_flags & flags) != 0; }
439 
440 NS_IMETHODIMP
GetLocale(nsAString & result)441 nsDBFolderInfo::GetLocale(nsAString& result) {
442   GetProperty(kLocaleColumnName, result);
443   return NS_OK;
444 }
445 
SetLocale(const nsAString & locale)446 NS_IMETHODIMP nsDBFolderInfo::SetLocale(const nsAString& locale) {
447   return SetProperty(kLocaleColumnName, locale);
448 }
449 
450 NS_IMETHODIMP
GetImapTotalPendingMessages(int32_t * result)451 nsDBFolderInfo::GetImapTotalPendingMessages(int32_t* result) {
452   NS_ENSURE_ARG_POINTER(result);
453   *result = m_totalPendingMessages;
454   return NS_OK;
455 }
456 
ChangeImapTotalPendingMessages(int32_t delta)457 void nsDBFolderInfo::ChangeImapTotalPendingMessages(int32_t delta) {
458   m_totalPendingMessages += delta;
459   SetInt32PropertyWithToken(m_totalPendingMessagesColumnToken,
460                             m_totalPendingMessages);
461 }
462 
463 NS_IMETHODIMP
GetImapUnreadPendingMessages(int32_t * result)464 nsDBFolderInfo::GetImapUnreadPendingMessages(int32_t* result) {
465   NS_ENSURE_ARG_POINTER(result);
466   *result = m_unreadPendingMessages;
467   return NS_OK;
468 }
469 
SetImapUnreadPendingMessages(int32_t numUnreadPendingMessages)470 NS_IMETHODIMP nsDBFolderInfo::SetImapUnreadPendingMessages(
471     int32_t numUnreadPendingMessages) {
472   m_unreadPendingMessages = numUnreadPendingMessages;
473   return SetUint32PropertyWithToken(m_unreadPendingMessagesColumnToken,
474                                     m_unreadPendingMessages);
475 }
476 
SetImapTotalPendingMessages(int32_t numTotalPendingMessages)477 NS_IMETHODIMP nsDBFolderInfo::SetImapTotalPendingMessages(
478     int32_t numTotalPendingMessages) {
479   m_totalPendingMessages = numTotalPendingMessages;
480   return SetUint32PropertyWithToken(m_totalPendingMessagesColumnToken,
481                                     m_totalPendingMessages);
482 }
483 
ChangeImapUnreadPendingMessages(int32_t delta)484 void nsDBFolderInfo::ChangeImapUnreadPendingMessages(int32_t delta) {
485   m_unreadPendingMessages += delta;
486   SetInt32PropertyWithToken(m_unreadPendingMessagesColumnToken,
487                             m_unreadPendingMessages);
488 }
489 
490 /* attribute nsMsgViewTypeValue viewType; */
GetViewType(nsMsgViewTypeValue * aViewType)491 NS_IMETHODIMP nsDBFolderInfo::GetViewType(nsMsgViewTypeValue* aViewType) {
492   uint32_t viewTypeValue;
493   nsresult rv = GetUint32Property("viewType", nsMsgViewType::eShowAllThreads,
494                                   &viewTypeValue);
495   *aViewType = viewTypeValue;
496   return rv;
497 }
SetViewType(nsMsgViewTypeValue aViewType)498 NS_IMETHODIMP nsDBFolderInfo::SetViewType(nsMsgViewTypeValue aViewType) {
499   return SetUint32Property("viewType", aViewType);
500 }
501 
502 /* attribute nsMsgViewFlagsTypeValue viewFlags; */
GetViewFlags(nsMsgViewFlagsTypeValue * aViewFlags)503 NS_IMETHODIMP nsDBFolderInfo::GetViewFlags(
504     nsMsgViewFlagsTypeValue* aViewFlags) {
505   nsMsgViewFlagsTypeValue defaultViewFlags;
506   nsresult rv = m_mdb->GetDefaultViewFlags(&defaultViewFlags);
507   NS_ENSURE_SUCCESS(rv, rv);
508 
509   uint32_t viewFlagsValue;
510   rv = GetUint32Property("viewFlags", defaultViewFlags, &viewFlagsValue);
511   *aViewFlags = viewFlagsValue;
512   return rv;
513 }
SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)514 NS_IMETHODIMP nsDBFolderInfo::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags) {
515   return SetUint32Property("viewFlags", aViewFlags);
516 }
517 
518 /* attribute nsMsgViewSortTypeValue sortType; */
GetSortType(nsMsgViewSortTypeValue * aSortType)519 NS_IMETHODIMP nsDBFolderInfo::GetSortType(nsMsgViewSortTypeValue* aSortType) {
520   nsMsgViewSortTypeValue defaultSortType;
521   nsresult rv = m_mdb->GetDefaultSortType(&defaultSortType);
522   NS_ENSURE_SUCCESS(rv, rv);
523 
524   uint32_t sortTypeValue;
525   rv = GetUint32Property("sortType", defaultSortType, &sortTypeValue);
526   *aSortType = sortTypeValue;
527   return rv;
528 }
SetSortType(nsMsgViewSortTypeValue aSortType)529 NS_IMETHODIMP nsDBFolderInfo::SetSortType(nsMsgViewSortTypeValue aSortType) {
530   return SetUint32Property("sortType", aSortType);
531 }
532 
533 /* attribute nsMsgViewSortOrderValue sortOrder; */
GetSortOrder(nsMsgViewSortOrderValue * aSortOrder)534 NS_IMETHODIMP nsDBFolderInfo::GetSortOrder(
535     nsMsgViewSortOrderValue* aSortOrder) {
536   nsMsgViewSortOrderValue defaultSortOrder;
537   nsresult rv = m_mdb->GetDefaultSortOrder(&defaultSortOrder);
538   NS_ENSURE_SUCCESS(rv, rv);
539 
540   uint32_t sortOrderValue;
541   rv = GetUint32Property("sortOrder", defaultSortOrder, &sortOrderValue);
542   *aSortOrder = sortOrderValue;
543   return rv;
544 }
545 
SetSortOrder(nsMsgViewSortOrderValue aSortOrder)546 NS_IMETHODIMP nsDBFolderInfo::SetSortOrder(nsMsgViewSortOrderValue aSortOrder) {
547   return SetUint32Property("sortOrder", aSortOrder);
548 }
549 
SetKnownArtsSet(const char * newsArtSet)550 NS_IMETHODIMP nsDBFolderInfo::SetKnownArtsSet(const char* newsArtSet) {
551   return m_mdb->SetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet);
552 }
553 
GetKnownArtsSet(char ** newsArtSet)554 NS_IMETHODIMP nsDBFolderInfo::GetKnownArtsSet(char** newsArtSet) {
555   return m_mdb->GetProperty(m_mdbRow, kKnownArtsSetColumnName, newsArtSet);
556 }
557 
558 // get arbitrary property, aka row cell value.
GetProperty(const char * propertyName,nsAString & resultProperty)559 NS_IMETHODIMP nsDBFolderInfo::GetProperty(const char* propertyName,
560                                           nsAString& resultProperty) {
561   return m_mdb->GetPropertyAsNSString(m_mdbRow, propertyName, resultProperty);
562 }
563 
SetCharProperty(const char * aPropertyName,const nsACString & aPropertyValue)564 NS_IMETHODIMP nsDBFolderInfo::SetCharProperty(
565     const char* aPropertyName, const nsACString& aPropertyValue) {
566   return m_mdb->SetProperty(m_mdbRow, aPropertyName,
567                             PromiseFlatCString(aPropertyValue).get());
568 }
569 
GetCharProperty(const char * propertyName,nsACString & resultProperty)570 NS_IMETHODIMP nsDBFolderInfo::GetCharProperty(const char* propertyName,
571                                               nsACString& resultProperty) {
572   nsCString result;
573   nsresult rv =
574       m_mdb->GetProperty(m_mdbRow, propertyName, getter_Copies(result));
575   if (NS_SUCCEEDED(rv)) resultProperty.Assign(result);
576   return rv;
577 }
578 
SetUint32Property(const char * propertyName,uint32_t propertyValue)579 NS_IMETHODIMP nsDBFolderInfo::SetUint32Property(const char* propertyName,
580                                                 uint32_t propertyValue) {
581   return m_mdb->SetUint32Property(m_mdbRow, propertyName, propertyValue);
582 }
583 
SetInt64Property(const char * propertyName,int64_t propertyValue)584 NS_IMETHODIMP nsDBFolderInfo::SetInt64Property(const char* propertyName,
585                                                int64_t propertyValue) {
586   return m_mdb->SetUint64Property(m_mdbRow, propertyName,
587                                   (uint64_t)propertyValue);
588 }
589 
SetProperty(const char * propertyName,const nsAString & propertyStr)590 NS_IMETHODIMP nsDBFolderInfo::SetProperty(const char* propertyName,
591                                           const nsAString& propertyStr) {
592   return m_mdb->SetPropertyFromNSString(m_mdbRow, propertyName, propertyStr);
593 }
594 
SetPropertyWithToken(mdb_token aProperty,const nsAString & propertyStr)595 nsresult nsDBFolderInfo::SetPropertyWithToken(mdb_token aProperty,
596                                               const nsAString& propertyStr) {
597   return m_mdb->SetNSStringPropertyWithToken(m_mdbRow, aProperty, propertyStr);
598 }
599 
SetUint32PropertyWithToken(mdb_token aProperty,uint32_t propertyValue)600 nsresult nsDBFolderInfo::SetUint32PropertyWithToken(mdb_token aProperty,
601                                                     uint32_t propertyValue) {
602   return m_mdb->UInt32ToRowCellColumn(m_mdbRow, aProperty, propertyValue);
603 }
604 
SetInt64PropertyWithToken(mdb_token aProperty,int64_t propertyValue)605 nsresult nsDBFolderInfo::SetInt64PropertyWithToken(mdb_token aProperty,
606                                                    int64_t propertyValue) {
607   return m_mdb->UInt64ToRowCellColumn(m_mdbRow, aProperty,
608                                       (uint64_t)propertyValue);
609 }
610 
SetInt32PropertyWithToken(mdb_token aProperty,int32_t propertyValue)611 nsresult nsDBFolderInfo::SetInt32PropertyWithToken(mdb_token aProperty,
612                                                    int32_t propertyValue) {
613   nsAutoString propertyStr;
614   propertyStr.AppendInt(propertyValue, 16);
615   return SetPropertyWithToken(aProperty, propertyStr);
616 }
617 
GetPropertyWithToken(mdb_token aProperty,nsAString & resultProperty)618 nsresult nsDBFolderInfo::GetPropertyWithToken(mdb_token aProperty,
619                                               nsAString& resultProperty) {
620   return m_mdb->RowCellColumnTonsString(m_mdbRow, aProperty, resultProperty);
621 }
622 
GetUint32PropertyWithToken(mdb_token aProperty,uint32_t & propertyValue,uint32_t defaultValue)623 nsresult nsDBFolderInfo::GetUint32PropertyWithToken(mdb_token aProperty,
624                                                     uint32_t& propertyValue,
625                                                     uint32_t defaultValue) {
626   return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty, propertyValue,
627                                       defaultValue);
628 }
629 
GetInt32PropertyWithToken(mdb_token aProperty,int32_t & propertyValue,int32_t defaultValue)630 nsresult nsDBFolderInfo::GetInt32PropertyWithToken(mdb_token aProperty,
631                                                    int32_t& propertyValue,
632                                                    int32_t defaultValue) {
633   return m_mdb->RowCellColumnToUInt32(m_mdbRow, aProperty,
634                                       (uint32_t&)propertyValue, defaultValue);
635 }
636 
GetUint32Property(const char * propertyName,uint32_t defaultValue,uint32_t * propertyValue)637 NS_IMETHODIMP nsDBFolderInfo::GetUint32Property(const char* propertyName,
638                                                 uint32_t defaultValue,
639                                                 uint32_t* propertyValue) {
640   return m_mdb->GetUint32Property(m_mdbRow, propertyName, propertyValue,
641                                   defaultValue);
642 }
643 
GetInt64Property(const char * propertyName,int64_t defaultValue,int64_t * propertyValue)644 NS_IMETHODIMP nsDBFolderInfo::GetInt64Property(const char* propertyName,
645                                                int64_t defaultValue,
646                                                int64_t* propertyValue) {
647   return m_mdb->GetUint64Property(m_mdbRow, propertyName,
648                                   (uint64_t*)&propertyValue, defaultValue);
649 }
650 
GetInt64PropertyWithToken(mdb_token aProperty,int64_t & propertyValue,int64_t defaultValue)651 nsresult nsDBFolderInfo::GetInt64PropertyWithToken(mdb_token aProperty,
652                                                    int64_t& propertyValue,
653                                                    int64_t defaultValue) {
654   return m_mdb->RowCellColumnToUInt64(m_mdbRow, aProperty,
655                                       (uint64_t*)&propertyValue, defaultValue);
656 }
657 
GetBooleanProperty(const char * propertyName,bool defaultValue,bool * propertyValue)658 NS_IMETHODIMP nsDBFolderInfo::GetBooleanProperty(const char* propertyName,
659                                                  bool defaultValue,
660                                                  bool* propertyValue) {
661   uint32_t defaultUint32Value = (defaultValue) ? 1 : 0;
662   uint32_t returnValue;
663   nsresult rv = m_mdb->GetUint32Property(m_mdbRow, propertyName, &returnValue,
664                                          defaultUint32Value);
665   *propertyValue = (returnValue != 0);
666   return rv;
667 }
SetBooleanProperty(const char * propertyName,bool propertyValue)668 NS_IMETHODIMP nsDBFolderInfo::SetBooleanProperty(const char* propertyName,
669                                                  bool propertyValue) {
670   return m_mdb->SetUint32Property(m_mdbRow, propertyName,
671                                   propertyValue ? 1 : 0);
672 }
673 
GetFolderName(nsACString & folderName)674 NS_IMETHODIMP nsDBFolderInfo::GetFolderName(nsACString& folderName) {
675   return GetCharProperty("folderName", folderName);
676 }
677 
SetFolderName(const nsACString & folderName)678 NS_IMETHODIMP nsDBFolderInfo::SetFolderName(const nsACString& folderName) {
679   return SetCharProperty("folderName", folderName);
680 }
681 
682 class nsTransferDBFolderInfo : public nsDBFolderInfo {
683  public:
684   nsTransferDBFolderInfo();
685   virtual ~nsTransferDBFolderInfo();
686   // parallel arrays of properties and values
687   nsTArray<nsCString> m_properties;
688   nsTArray<nsCString> m_values;
689 };
690 
nsTransferDBFolderInfo()691 nsTransferDBFolderInfo::nsTransferDBFolderInfo() : nsDBFolderInfo(nullptr) {}
692 
~nsTransferDBFolderInfo()693 nsTransferDBFolderInfo::~nsTransferDBFolderInfo() {}
694 
695 /* void GetTransferInfo (out nsIDBFolderInfo transferInfo); */
GetTransferInfo(nsIDBFolderInfo ** transferInfo)696 NS_IMETHODIMP nsDBFolderInfo::GetTransferInfo(nsIDBFolderInfo** transferInfo) {
697   NS_ENSURE_ARG_POINTER(transferInfo);
698 
699   nsTransferDBFolderInfo* newInfo = new nsTransferDBFolderInfo;
700   NS_ADDREF(*transferInfo = newInfo);
701 
702   mdb_count numCells;
703   mdbYarn cellYarn;
704   mdb_column cellColumn;
705   char columnName[100];
706   mdbYarn cellName = {columnName, 0, sizeof(columnName), 0, 0, nullptr};
707 
708   NS_ASSERTION(m_mdbRow, "null row in getTransferInfo");
709   m_mdbRow->GetCount(m_mdb->GetEnv(), &numCells);
710   // iterate over the cells in the dbfolderinfo remembering attribute names and
711   // values.
712   for (mdb_count cellIndex = 0; cellIndex < numCells; cellIndex++) {
713     nsresult err = m_mdbRow->SeekCellYarn(m_mdb->GetEnv(), cellIndex,
714                                           &cellColumn, nullptr);
715     if (NS_SUCCEEDED(err)) {
716       err = m_mdbRow->AliasCellYarn(m_mdb->GetEnv(), cellColumn, &cellYarn);
717       if (NS_SUCCEEDED(err)) {
718         m_mdb->GetStore()->TokenToString(m_mdb->GetEnv(), cellColumn,
719                                          &cellName);
720         newInfo->m_values.AppendElement(
721             Substring((const char*)cellYarn.mYarn_Buf,
722                       (const char*)cellYarn.mYarn_Buf + cellYarn.mYarn_Fill));
723         newInfo->m_properties.AppendElement(
724             Substring((const char*)cellName.mYarn_Buf,
725                       (const char*)cellName.mYarn_Buf + cellName.mYarn_Fill));
726       }
727     }
728   }
729 
730   return NS_OK;
731 }
732 
733 /* void InitFromTransferInfo (in nsIDBFolderInfo transferInfo); */
InitFromTransferInfo(nsIDBFolderInfo * aTransferInfo)734 NS_IMETHODIMP nsDBFolderInfo::InitFromTransferInfo(
735     nsIDBFolderInfo* aTransferInfo) {
736   NS_ENSURE_ARG(aTransferInfo);
737 
738   nsTransferDBFolderInfo* transferInfo =
739       static_cast<nsTransferDBFolderInfo*>(aTransferInfo);
740 
741   for (uint32_t i = 0; i < transferInfo->m_values.Length(); i++)
742     SetCharProperty(transferInfo->m_properties[i].get(),
743                     transferInfo->m_values[i]);
744 
745   LoadMemberVariables();
746   return NS_OK;
747 }
748