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 "nsImapHostSessionList.h"
8 #include "nsImapBodyShell.h"
9 #include "nsImapNamespace.h"
10 #include "nsIImapIncomingServer.h"
11 #include "nsCOMPtr.h"
12 #include "nsIMsgIncomingServer.h"
13 #include "nsIObserverService.h"
14 #include "nsServiceManagerUtils.h"
15 #include "nsMsgUtils.h"
16 #include "mozilla/Services.h"
17
nsIMAPHostInfo(const char * serverKey,nsIImapIncomingServer * server)18 nsIMAPHostInfo::nsIMAPHostInfo(const char* serverKey,
19 nsIImapIncomingServer* server) {
20 fServerKey = serverKey;
21 NS_ASSERTION(server, "*** Fatal null imap incoming server...");
22 server->GetServerDirectory(fOnlineDir);
23 fNextHost = NULL;
24 fCapabilityFlags = kCapabilityUndefined;
25 fHierarchyDelimiters = NULL;
26 #ifdef DEBUG_bienvenu1
27 fHaveWeEverDiscoveredFolders =
28 true; // try this, see what bad happens - we'll need to
29 // figure out a way to make new accounts have it be false
30 #else
31 fHaveWeEverDiscoveredFolders = false; // try this, see what bad happens
32 #endif
33 fDiscoveryForHostInProgress = false;
34 fCanonicalOnlineSubDir = NULL;
35 fNamespaceList = nsImapNamespaceList::CreatensImapNamespaceList();
36 fUsingSubscription = true;
37 server->GetUsingSubscription(&fUsingSubscription);
38 fOnlineTrashFolderExists = false;
39 fShouldAlwaysListInbox = true;
40 fShellCache = nsImapBodyShellCache::Create();
41 fPasswordVerifiedOnline = false;
42 fDeleteIsMoveToTrash = true;
43 fShowDeletedMessages = false;
44 fGotNamespaces = false;
45 fHaveAdminURL = false;
46 fNamespacesOverridable = true;
47 server->GetOverrideNamespaces(&fNamespacesOverridable);
48 fTempNamespaceList = nsImapNamespaceList::CreatensImapNamespaceList();
49 }
50
~nsIMAPHostInfo()51 nsIMAPHostInfo::~nsIMAPHostInfo() {
52 PR_Free(fHierarchyDelimiters);
53 delete fNamespaceList;
54 delete fTempNamespaceList;
55 delete fShellCache;
56 }
57
NS_IMPL_ISUPPORTS(nsImapHostSessionList,nsIImapHostSessionList,nsIObserver,nsISupportsWeakReference)58 NS_IMPL_ISUPPORTS(nsImapHostSessionList, nsIImapHostSessionList, nsIObserver,
59 nsISupportsWeakReference)
60
61 nsImapHostSessionList::nsImapHostSessionList() {
62 gCachedHostInfoMonitor = PR_NewMonitor(/* "accessing-hostlist-monitor"*/);
63 fHostInfoList = nullptr;
64 }
65
~nsImapHostSessionList()66 nsImapHostSessionList::~nsImapHostSessionList() {
67 ResetAll();
68 PR_DestroyMonitor(gCachedHostInfoMonitor);
69 }
70
Init()71 nsresult nsImapHostSessionList::Init() {
72 nsCOMPtr<nsIObserverService> observerService =
73 mozilla::services::GetObserverService();
74 NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
75 observerService->AddObserver(this, "profile-before-change", true);
76 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
77 return NS_OK;
78 }
79
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * someData)80 NS_IMETHODIMP nsImapHostSessionList::Observe(nsISupports* aSubject,
81 const char* aTopic,
82 const char16_t* someData) {
83 if (!strcmp(aTopic, "profile-before-change"))
84 ResetAll();
85 else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
86 nsCOMPtr<nsIObserverService> observerService =
87 mozilla::services::GetObserverService();
88 NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
89 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
90 observerService->RemoveObserver(this, "profile-before-change");
91 }
92 return NS_OK;
93 }
94
FindHost(const char * serverKey)95 nsIMAPHostInfo* nsImapHostSessionList::FindHost(const char* serverKey) {
96 nsIMAPHostInfo* host;
97
98 // ### should also check userName here, if NON NULL
99 for (host = fHostInfoList; host; host = host->fNextHost) {
100 if (host->fServerKey.Equals(serverKey, nsCaseInsensitiveCStringComparator))
101 return host;
102 }
103 return host;
104 }
105
106 // reset any cached connection info - delete the lot of 'em
ResetAll()107 NS_IMETHODIMP nsImapHostSessionList::ResetAll() {
108 PR_EnterMonitor(gCachedHostInfoMonitor);
109 nsIMAPHostInfo* nextHost = NULL;
110 for (nsIMAPHostInfo* host = fHostInfoList; host; host = nextHost) {
111 nextHost = host->fNextHost;
112 delete host;
113 }
114 fHostInfoList = NULL;
115 PR_ExitMonitor(gCachedHostInfoMonitor);
116 return NS_OK;
117 }
118
119 NS_IMETHODIMP
AddHostToList(const char * serverKey,nsIImapIncomingServer * server)120 nsImapHostSessionList::AddHostToList(const char* serverKey,
121 nsIImapIncomingServer* server) {
122 nsIMAPHostInfo* newHost = NULL;
123 PR_EnterMonitor(gCachedHostInfoMonitor);
124 if (!FindHost(serverKey)) {
125 // stick it on the front
126 newHost = new nsIMAPHostInfo(serverKey, server);
127 if (newHost) {
128 newHost->fNextHost = fHostInfoList;
129 fHostInfoList = newHost;
130 }
131 }
132 PR_ExitMonitor(gCachedHostInfoMonitor);
133 return (newHost == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
134 }
135
GetPasswordForHost(const char * serverKey,nsString & result)136 NS_IMETHODIMP nsImapHostSessionList::GetPasswordForHost(const char* serverKey,
137 nsString& result) {
138 PR_EnterMonitor(gCachedHostInfoMonitor);
139 nsIMAPHostInfo* host = FindHost(serverKey);
140 if (host) result = host->fCachedPassword;
141 PR_ExitMonitor(gCachedHostInfoMonitor);
142 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
143 }
144
SetPasswordForHost(const char * serverKey,const nsAString & password)145 NS_IMETHODIMP nsImapHostSessionList::SetPasswordForHost(
146 const char* serverKey, const nsAString& password) {
147 PR_EnterMonitor(gCachedHostInfoMonitor);
148 nsIMAPHostInfo* host = FindHost(serverKey);
149 if (host) host->fCachedPassword = password;
150 PR_ExitMonitor(gCachedHostInfoMonitor);
151 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
152 }
153
SetPasswordVerifiedOnline(const char * serverKey)154 NS_IMETHODIMP nsImapHostSessionList::SetPasswordVerifiedOnline(
155 const char* serverKey) {
156 PR_EnterMonitor(gCachedHostInfoMonitor);
157 nsIMAPHostInfo* host = FindHost(serverKey);
158 if (host) host->fPasswordVerifiedOnline = true;
159 PR_ExitMonitor(gCachedHostInfoMonitor);
160 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
161 }
162
GetPasswordVerifiedOnline(const char * serverKey,bool & result)163 NS_IMETHODIMP nsImapHostSessionList::GetPasswordVerifiedOnline(
164 const char* serverKey, bool& result) {
165 PR_EnterMonitor(gCachedHostInfoMonitor);
166 nsIMAPHostInfo* host = FindHost(serverKey);
167 if (host) result = host->fPasswordVerifiedOnline;
168 PR_ExitMonitor(gCachedHostInfoMonitor);
169 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
170 }
171
GetOnlineDirForHost(const char * serverKey,nsString & result)172 NS_IMETHODIMP nsImapHostSessionList::GetOnlineDirForHost(const char* serverKey,
173 nsString& result) {
174 PR_EnterMonitor(gCachedHostInfoMonitor);
175 nsIMAPHostInfo* host = FindHost(serverKey);
176 if (host) CopyASCIItoUTF16(host->fOnlineDir, result);
177 PR_ExitMonitor(gCachedHostInfoMonitor);
178 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
179 }
180
SetOnlineDirForHost(const char * serverKey,const char * onlineDir)181 NS_IMETHODIMP nsImapHostSessionList::SetOnlineDirForHost(
182 const char* serverKey, const char* onlineDir) {
183 PR_EnterMonitor(gCachedHostInfoMonitor);
184 nsIMAPHostInfo* host = FindHost(serverKey);
185 if (host) {
186 if (onlineDir) host->fOnlineDir = onlineDir;
187 }
188 PR_ExitMonitor(gCachedHostInfoMonitor);
189 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
190 }
191
GetDeleteIsMoveToTrashForHost(const char * serverKey,bool & result)192 NS_IMETHODIMP nsImapHostSessionList::GetDeleteIsMoveToTrashForHost(
193 const char* serverKey, bool& result) {
194 PR_EnterMonitor(gCachedHostInfoMonitor);
195 nsIMAPHostInfo* host = FindHost(serverKey);
196 if (host) result = host->fDeleteIsMoveToTrash;
197 PR_ExitMonitor(gCachedHostInfoMonitor);
198 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
199 }
200
GetShowDeletedMessagesForHost(const char * serverKey,bool & result)201 NS_IMETHODIMP nsImapHostSessionList::GetShowDeletedMessagesForHost(
202 const char* serverKey, bool& result) {
203 PR_EnterMonitor(gCachedHostInfoMonitor);
204 nsIMAPHostInfo* host = FindHost(serverKey);
205 if (host) result = host->fShowDeletedMessages;
206 PR_ExitMonitor(gCachedHostInfoMonitor);
207 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
208 }
209
SetDeleteIsMoveToTrashForHost(const char * serverKey,bool isMoveToTrash)210 NS_IMETHODIMP nsImapHostSessionList::SetDeleteIsMoveToTrashForHost(
211 const char* serverKey, bool isMoveToTrash) {
212 PR_EnterMonitor(gCachedHostInfoMonitor);
213 nsIMAPHostInfo* host = FindHost(serverKey);
214 if (host) host->fDeleteIsMoveToTrash = isMoveToTrash;
215 PR_ExitMonitor(gCachedHostInfoMonitor);
216 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
217 }
218
SetShowDeletedMessagesForHost(const char * serverKey,bool showDeletedMessages)219 NS_IMETHODIMP nsImapHostSessionList::SetShowDeletedMessagesForHost(
220 const char* serverKey, bool showDeletedMessages) {
221 PR_EnterMonitor(gCachedHostInfoMonitor);
222 nsIMAPHostInfo* host = FindHost(serverKey);
223 if (host) host->fShowDeletedMessages = showDeletedMessages;
224 PR_ExitMonitor(gCachedHostInfoMonitor);
225 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
226 }
227
GetGotNamespacesForHost(const char * serverKey,bool & result)228 NS_IMETHODIMP nsImapHostSessionList::GetGotNamespacesForHost(
229 const char* serverKey, bool& result) {
230 PR_EnterMonitor(gCachedHostInfoMonitor);
231 nsIMAPHostInfo* host = FindHost(serverKey);
232 if (host) result = host->fGotNamespaces;
233 PR_ExitMonitor(gCachedHostInfoMonitor);
234 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
235 }
236
SetGotNamespacesForHost(const char * serverKey,bool gotNamespaces)237 NS_IMETHODIMP nsImapHostSessionList::SetGotNamespacesForHost(
238 const char* serverKey, bool gotNamespaces) {
239 PR_EnterMonitor(gCachedHostInfoMonitor);
240 nsIMAPHostInfo* host = FindHost(serverKey);
241 if (host) host->fGotNamespaces = gotNamespaces;
242 PR_ExitMonitor(gCachedHostInfoMonitor);
243 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
244 }
245
GetHostIsUsingSubscription(const char * serverKey,bool & result)246 NS_IMETHODIMP nsImapHostSessionList::GetHostIsUsingSubscription(
247 const char* serverKey, bool& result) {
248 PR_EnterMonitor(gCachedHostInfoMonitor);
249 nsIMAPHostInfo* host = FindHost(serverKey);
250 if (host) result = host->fUsingSubscription;
251 PR_ExitMonitor(gCachedHostInfoMonitor);
252 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
253 }
254
SetHostIsUsingSubscription(const char * serverKey,bool usingSubscription)255 NS_IMETHODIMP nsImapHostSessionList::SetHostIsUsingSubscription(
256 const char* serverKey, bool usingSubscription) {
257 PR_EnterMonitor(gCachedHostInfoMonitor);
258 nsIMAPHostInfo* host = FindHost(serverKey);
259 if (host) host->fUsingSubscription = usingSubscription;
260 PR_ExitMonitor(gCachedHostInfoMonitor);
261 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
262 }
263
GetHostHasAdminURL(const char * serverKey,bool & result)264 NS_IMETHODIMP nsImapHostSessionList::GetHostHasAdminURL(const char* serverKey,
265 bool& result) {
266 PR_EnterMonitor(gCachedHostInfoMonitor);
267 nsIMAPHostInfo* host = FindHost(serverKey);
268 if (host) result = host->fHaveAdminURL;
269 PR_ExitMonitor(gCachedHostInfoMonitor);
270 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
271 }
272
SetHostHasAdminURL(const char * serverKey,bool haveAdminURL)273 NS_IMETHODIMP nsImapHostSessionList::SetHostHasAdminURL(const char* serverKey,
274 bool haveAdminURL) {
275 PR_EnterMonitor(gCachedHostInfoMonitor);
276 nsIMAPHostInfo* host = FindHost(serverKey);
277 if (host) host->fHaveAdminURL = haveAdminURL;
278 PR_ExitMonitor(gCachedHostInfoMonitor);
279 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
280 }
281
GetHaveWeEverDiscoveredFoldersForHost(const char * serverKey,bool & result)282 NS_IMETHODIMP nsImapHostSessionList::GetHaveWeEverDiscoveredFoldersForHost(
283 const char* serverKey, bool& result) {
284 PR_EnterMonitor(gCachedHostInfoMonitor);
285 nsIMAPHostInfo* host = FindHost(serverKey);
286 if (host) result = host->fHaveWeEverDiscoveredFolders;
287 PR_ExitMonitor(gCachedHostInfoMonitor);
288 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
289 }
290
SetHaveWeEverDiscoveredFoldersForHost(const char * serverKey,bool discovered)291 NS_IMETHODIMP nsImapHostSessionList::SetHaveWeEverDiscoveredFoldersForHost(
292 const char* serverKey, bool discovered) {
293 PR_EnterMonitor(gCachedHostInfoMonitor);
294 nsIMAPHostInfo* host = FindHost(serverKey);
295 if (host) host->fHaveWeEverDiscoveredFolders = discovered;
296 PR_ExitMonitor(gCachedHostInfoMonitor);
297 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
298 }
299
GetDiscoveryForHostInProgress(const char * serverKey,bool & result)300 NS_IMETHODIMP nsImapHostSessionList::GetDiscoveryForHostInProgress(
301 const char* serverKey, bool& result) {
302 PR_EnterMonitor(gCachedHostInfoMonitor);
303 nsIMAPHostInfo* host = FindHost(serverKey);
304 if (host)
305 result = host->fDiscoveryForHostInProgress;
306 else
307 result = false;
308 PR_ExitMonitor(gCachedHostInfoMonitor);
309 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
310 }
311
SetDiscoveryForHostInProgress(const char * serverKey,bool inProgress)312 NS_IMETHODIMP nsImapHostSessionList::SetDiscoveryForHostInProgress(
313 const char* serverKey, bool inProgress) {
314 PR_EnterMonitor(gCachedHostInfoMonitor);
315 nsIMAPHostInfo* host = FindHost(serverKey);
316 if (host) host->fDiscoveryForHostInProgress = inProgress;
317 PR_ExitMonitor(gCachedHostInfoMonitor);
318 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
319 }
320
SetOnlineTrashFolderExistsForHost(const char * serverKey,bool exists)321 NS_IMETHODIMP nsImapHostSessionList::SetOnlineTrashFolderExistsForHost(
322 const char* serverKey, bool exists) {
323 PR_EnterMonitor(gCachedHostInfoMonitor);
324 nsIMAPHostInfo* host = FindHost(serverKey);
325 if (host) host->fOnlineTrashFolderExists = exists;
326 PR_ExitMonitor(gCachedHostInfoMonitor);
327 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
328 }
329
GetOnlineTrashFolderExistsForHost(const char * serverKey,bool & result)330 NS_IMETHODIMP nsImapHostSessionList::GetOnlineTrashFolderExistsForHost(
331 const char* serverKey, bool& result) {
332 PR_EnterMonitor(gCachedHostInfoMonitor);
333 nsIMAPHostInfo* host = FindHost(serverKey);
334 if (host) result = host->fOnlineTrashFolderExists;
335 PR_ExitMonitor(gCachedHostInfoMonitor);
336 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
337 }
338
AddNewNamespaceForHost(const char * serverKey,nsImapNamespace * ns)339 NS_IMETHODIMP nsImapHostSessionList::AddNewNamespaceForHost(
340 const char* serverKey, nsImapNamespace* ns) {
341 PR_EnterMonitor(gCachedHostInfoMonitor);
342 nsIMAPHostInfo* host = FindHost(serverKey);
343 if (host) host->fNamespaceList->AddNewNamespace(ns);
344 PR_ExitMonitor(gCachedHostInfoMonitor);
345 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
346 }
347
SetNamespaceFromPrefForHost(const char * serverKey,const char * namespacePref,EIMAPNamespaceType nstype)348 NS_IMETHODIMP nsImapHostSessionList::SetNamespaceFromPrefForHost(
349 const char* serverKey, const char* namespacePref,
350 EIMAPNamespaceType nstype) {
351 PR_EnterMonitor(gCachedHostInfoMonitor);
352 nsIMAPHostInfo* host = FindHost(serverKey);
353 if (host) {
354 if (namespacePref) {
355 int numNamespaces = host->fNamespaceList->UnserializeNamespaces(
356 namespacePref, nullptr, 0);
357 char** prefixes = (char**)PR_CALLOC(numNamespaces * sizeof(char*));
358 if (prefixes) {
359 int len = host->fNamespaceList->UnserializeNamespaces(
360 namespacePref, prefixes, numNamespaces);
361 for (int i = 0; i < len; i++) {
362 char* thisns = prefixes[i];
363 char delimiter = '/'; // a guess
364 if (PL_strlen(thisns) >= 1) delimiter = thisns[PL_strlen(thisns) - 1];
365 nsImapNamespace* ns =
366 new nsImapNamespace(nstype, thisns, delimiter, true);
367 if (ns) host->fNamespaceList->AddNewNamespace(ns);
368 PR_FREEIF(thisns);
369 }
370 PR_Free(prefixes);
371 }
372 }
373 }
374 PR_ExitMonitor(gCachedHostInfoMonitor);
375 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
376 }
377
GetNamespaceForMailboxForHost(const char * serverKey,const char * mailbox_name,nsImapNamespace * & result)378 NS_IMETHODIMP nsImapHostSessionList::GetNamespaceForMailboxForHost(
379 const char* serverKey, const char* mailbox_name, nsImapNamespace*& result) {
380 PR_EnterMonitor(gCachedHostInfoMonitor);
381 nsIMAPHostInfo* host = FindHost(serverKey);
382 if (host) result = host->fNamespaceList->GetNamespaceForMailbox(mailbox_name);
383 PR_ExitMonitor(gCachedHostInfoMonitor);
384 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
385 }
386
ClearPrefsNamespacesForHost(const char * serverKey)387 NS_IMETHODIMP nsImapHostSessionList::ClearPrefsNamespacesForHost(
388 const char* serverKey) {
389 PR_EnterMonitor(gCachedHostInfoMonitor);
390 nsIMAPHostInfo* host = FindHost(serverKey);
391 if (host) host->fNamespaceList->ClearNamespaces(true, false, true);
392 PR_ExitMonitor(gCachedHostInfoMonitor);
393 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
394 }
395
ClearServerAdvertisedNamespacesForHost(const char * serverKey)396 NS_IMETHODIMP nsImapHostSessionList::ClearServerAdvertisedNamespacesForHost(
397 const char* serverKey) {
398 PR_EnterMonitor(gCachedHostInfoMonitor);
399 nsIMAPHostInfo* host = FindHost(serverKey);
400 if (host) host->fNamespaceList->ClearNamespaces(false, true, true);
401 PR_ExitMonitor(gCachedHostInfoMonitor);
402 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
403 }
404
GetDefaultNamespaceOfTypeForHost(const char * serverKey,EIMAPNamespaceType type,nsImapNamespace * & result)405 NS_IMETHODIMP nsImapHostSessionList::GetDefaultNamespaceOfTypeForHost(
406 const char* serverKey, EIMAPNamespaceType type, nsImapNamespace*& result) {
407 PR_EnterMonitor(gCachedHostInfoMonitor);
408 nsIMAPHostInfo* host = FindHost(serverKey);
409 if (host) result = host->fNamespaceList->GetDefaultNamespaceOfType(type);
410 PR_ExitMonitor(gCachedHostInfoMonitor);
411 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
412 }
413
GetNamespacesOverridableForHost(const char * serverKey,bool & result)414 NS_IMETHODIMP nsImapHostSessionList::GetNamespacesOverridableForHost(
415 const char* serverKey, bool& result) {
416 PR_EnterMonitor(gCachedHostInfoMonitor);
417 nsIMAPHostInfo* host = FindHost(serverKey);
418 if (host) result = host->fNamespacesOverridable;
419 PR_ExitMonitor(gCachedHostInfoMonitor);
420 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
421 }
422
SetNamespacesOverridableForHost(const char * serverKey,bool overridable)423 NS_IMETHODIMP nsImapHostSessionList::SetNamespacesOverridableForHost(
424 const char* serverKey, bool overridable) {
425 PR_EnterMonitor(gCachedHostInfoMonitor);
426 nsIMAPHostInfo* host = FindHost(serverKey);
427 if (host) host->fNamespacesOverridable = overridable;
428 PR_ExitMonitor(gCachedHostInfoMonitor);
429 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
430 }
431
GetNumberOfNamespacesForHost(const char * serverKey,uint32_t & result)432 NS_IMETHODIMP nsImapHostSessionList::GetNumberOfNamespacesForHost(
433 const char* serverKey, uint32_t& result) {
434 int32_t intResult = 0;
435
436 PR_EnterMonitor(gCachedHostInfoMonitor);
437 nsIMAPHostInfo* host = FindHost(serverKey);
438 if (host) intResult = host->fNamespaceList->GetNumberOfNamespaces();
439 PR_ExitMonitor(gCachedHostInfoMonitor);
440 NS_ASSERTION(intResult >= 0, "negative number of namespaces");
441 result = (uint32_t)intResult;
442 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
443 }
444
GetNamespaceNumberForHost(const char * serverKey,int32_t n,nsImapNamespace * & result)445 NS_IMETHODIMP nsImapHostSessionList::GetNamespaceNumberForHost(
446 const char* serverKey, int32_t n, nsImapNamespace*& result) {
447 PR_EnterMonitor(gCachedHostInfoMonitor);
448 nsIMAPHostInfo* host = FindHost(serverKey);
449 if (host) result = host->fNamespaceList->GetNamespaceNumber(n);
450 PR_ExitMonitor(gCachedHostInfoMonitor);
451 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
452 }
453
SetNamespacesPrefForHost(nsIImapIncomingServer * aHost,EIMAPNamespaceType type,const char * pref)454 nsresult nsImapHostSessionList::SetNamespacesPrefForHost(
455 nsIImapIncomingServer* aHost, EIMAPNamespaceType type, const char* pref) {
456 if (type == kPersonalNamespace)
457 aHost->SetPersonalNamespace(nsDependentCString(pref));
458 else if (type == kPublicNamespace)
459 aHost->SetPublicNamespace(nsDependentCString(pref));
460 else if (type == kOtherUsersNamespace)
461 aHost->SetOtherUsersNamespace(nsDependentCString(pref));
462 else
463 NS_ASSERTION(false, "bogus namespace type");
464 return NS_OK;
465 }
466 // do we need this? What should we do about the master thing?
467 // Make sure this is running in the Mozilla thread when called
CommitNamespacesForHost(nsIImapIncomingServer * aHost)468 NS_IMETHODIMP nsImapHostSessionList::CommitNamespacesForHost(
469 nsIImapIncomingServer* aHost) {
470 NS_ENSURE_ARG_POINTER(aHost);
471 nsCString serverKey;
472 nsCOMPtr<nsIMsgIncomingServer> incomingServer = do_QueryInterface(aHost);
473 if (!incomingServer) return NS_ERROR_NULL_POINTER;
474
475 nsresult rv = incomingServer->GetKey(serverKey);
476 NS_ENSURE_SUCCESS(rv, rv);
477
478 PR_EnterMonitor(gCachedHostInfoMonitor);
479 nsIMAPHostInfo* host = FindHost(serverKey.get());
480 if (host) {
481 host->fGotNamespaces =
482 true; // so we only issue NAMESPACE once per host per session.
483 EIMAPNamespaceType type = kPersonalNamespace;
484 for (int i = 1; i <= 3; i++) {
485 switch (i) {
486 case 1:
487 type = kPersonalNamespace;
488 break;
489 case 2:
490 type = kPublicNamespace;
491 break;
492 case 3:
493 type = kOtherUsersNamespace;
494 break;
495 default:
496 type = kPersonalNamespace;
497 break;
498 }
499
500 int32_t numInNS = host->fNamespaceList->GetNumberOfNamespaces(type);
501 if (numInNS == 0)
502 SetNamespacesPrefForHost(aHost, type, "");
503 else if (numInNS >= 1) {
504 char* pref = PR_smprintf("");
505 for (int count = 1; count <= numInNS; count++) {
506 nsImapNamespace* ns =
507 host->fNamespaceList->GetNamespaceNumber(count, type);
508 if (ns) {
509 if (count > 1) {
510 // append the comma
511 char* tempPref = PR_smprintf("%s,", pref);
512 PR_FREEIF(pref);
513 pref = tempPref;
514 }
515 char* tempPref = PR_smprintf("%s\"%s\"", pref, ns->GetPrefix());
516 PR_FREEIF(pref);
517 pref = tempPref;
518 }
519 }
520 if (pref) {
521 SetNamespacesPrefForHost(aHost, type, pref);
522 PR_Free(pref);
523 }
524 }
525 }
526 // clear, but don't delete the entries in, the temp namespace list
527 host->fTempNamespaceList->ClearNamespaces(true, true, false);
528
529 // Now reset all of libmsg's namespace references.
530 // Did I mention this needs to be running in the mozilla thread?
531 aHost->ResetNamespaceReferences();
532 }
533 PR_ExitMonitor(gCachedHostInfoMonitor);
534 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
535 }
536
FlushUncommittedNamespacesForHost(const char * serverKey,bool & result)537 NS_IMETHODIMP nsImapHostSessionList::FlushUncommittedNamespacesForHost(
538 const char* serverKey, bool& result) {
539 PR_EnterMonitor(gCachedHostInfoMonitor);
540 nsIMAPHostInfo* host = FindHost(serverKey);
541 if (host) host->fTempNamespaceList->ClearNamespaces(true, true, true);
542 PR_ExitMonitor(gCachedHostInfoMonitor);
543 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
544 }
545
546 // Returns NULL if there is no personal namespace on the given host
GetOnlineInboxPathForHost(const char * serverKey,nsString & result)547 NS_IMETHODIMP nsImapHostSessionList::GetOnlineInboxPathForHost(
548 const char* serverKey, nsString& result) {
549 PR_EnterMonitor(gCachedHostInfoMonitor);
550 nsIMAPHostInfo* host = FindHost(serverKey);
551 if (host) {
552 nsImapNamespace* ns = NULL;
553 ns = host->fNamespaceList->GetDefaultNamespaceOfType(kPersonalNamespace);
554 if (ns) {
555 CopyASCIItoUTF16(nsDependentCString(ns->GetPrefix()), result);
556 result.AppendLiteral("INBOX");
557 }
558 } else
559 result.Truncate();
560 PR_ExitMonitor(gCachedHostInfoMonitor);
561 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
562 }
563
GetShouldAlwaysListInboxForHost(const char *,bool & result)564 NS_IMETHODIMP nsImapHostSessionList::GetShouldAlwaysListInboxForHost(
565 const char* /*serverKey*/, bool& result) {
566 result = true;
567
568 /*
569 PR_EnterMonitor(gCachedHostInfoMonitor);
570 nsIMAPHostInfo *host = FindHost(serverKey);
571 if (host)
572 ret = host->fShouldAlwaysListInbox;
573 PR_ExitMonitor(gCachedHostInfoMonitor);
574 */
575 return NS_OK;
576 }
577
SetShouldAlwaysListInboxForHost(const char * serverKey,bool shouldList)578 NS_IMETHODIMP nsImapHostSessionList::SetShouldAlwaysListInboxForHost(
579 const char* serverKey, bool shouldList) {
580 PR_EnterMonitor(gCachedHostInfoMonitor);
581 nsIMAPHostInfo* host = FindHost(serverKey);
582 if (host) host->fShouldAlwaysListInbox = shouldList;
583 PR_ExitMonitor(gCachedHostInfoMonitor);
584 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
585 }
586
587 NS_IMETHODIMP
SetNamespaceHierarchyDelimiterFromMailboxForHost(const char * serverKey,const char * boxName,char delimiter)588 nsImapHostSessionList::SetNamespaceHierarchyDelimiterFromMailboxForHost(
589 const char* serverKey, const char* boxName, char delimiter) {
590 PR_EnterMonitor(gCachedHostInfoMonitor);
591 nsIMAPHostInfo* host = FindHost(serverKey);
592 if (host) {
593 nsImapNamespace* ns = host->fNamespaceList->GetNamespaceForMailbox(boxName);
594 if (ns && !ns->GetIsDelimiterFilledIn()) ns->SetDelimiter(delimiter, true);
595 }
596 PR_ExitMonitor(gCachedHostInfoMonitor);
597 return (host) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
598 }
599
AddShellToCacheForHost(const char * serverKey,nsImapBodyShell * shell)600 NS_IMETHODIMP nsImapHostSessionList::AddShellToCacheForHost(
601 const char* serverKey, nsImapBodyShell* shell) {
602 nsresult rv = NS_OK;
603 PR_EnterMonitor(gCachedHostInfoMonitor);
604 nsIMAPHostInfo* host = FindHost(serverKey);
605 if (host) {
606 if (host->fShellCache) {
607 if (!host->fShellCache->AddShellToCache(shell)) rv = NS_ERROR_UNEXPECTED;
608 }
609 } else
610 rv = NS_ERROR_ILLEGAL_VALUE;
611
612 PR_ExitMonitor(gCachedHostInfoMonitor);
613 return rv;
614 }
615
FindShellInCacheForHost(const char * serverKey,const char * mailboxName,const char * UID,IMAP_ContentModifiedType modType,nsImapBodyShell ** shell)616 NS_IMETHODIMP nsImapHostSessionList::FindShellInCacheForHost(
617 const char* serverKey, const char* mailboxName, const char* UID,
618 IMAP_ContentModifiedType modType, nsImapBodyShell** shell) {
619 nsCString uidString(UID);
620
621 PR_EnterMonitor(gCachedHostInfoMonitor);
622 nsIMAPHostInfo* host = FindHost(serverKey);
623 if (host && host->fShellCache)
624 NS_IF_ADDREF(*shell = host->fShellCache->FindShellForUID(
625 uidString, mailboxName, modType));
626 PR_ExitMonitor(gCachedHostInfoMonitor);
627 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
628 }
629
630 NS_IMETHODIMP
ClearShellCacheForHost(const char * serverKey)631 nsImapHostSessionList::ClearShellCacheForHost(const char* serverKey) {
632 PR_EnterMonitor(gCachedHostInfoMonitor);
633 nsIMAPHostInfo* host = FindHost(serverKey);
634 if (host && host->fShellCache) host->fShellCache->Clear();
635 PR_ExitMonitor(gCachedHostInfoMonitor);
636 return (host == NULL) ? NS_ERROR_ILLEGAL_VALUE : NS_OK;
637 }
638