Back to index

lightning-sunbird  0.9+nobinonly
nsMsgAccount.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; 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) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include "prprf.h"
00040 #include "plstr.h"
00041 #include "prmem.h"
00042 #include "nsISupportsObsolete.h"
00043 #include "nsIComponentManager.h"
00044 #include "nsIServiceManager.h"
00045 
00046 #include "nsCOMPtr.h"
00047 #include "nsXPIDLString.h"
00048 #include "nsReadableUtils.h"
00049 
00050 #include "nsIPrefService.h"
00051 #include "nsIPrefBranch.h"
00052 #include "nsMsgBaseCID.h"
00053 #include "nsMsgAccount.h"
00054 #include "nsIMsgAccount.h"
00055 #include "nsIMsgAccountManager.h"
00056 
00057 NS_IMPL_ISUPPORTS1(nsMsgAccount, nsIMsgAccount)
00058 
00059 nsMsgAccount::nsMsgAccount()
00060 {
00061 }
00062 
00063 nsMsgAccount::~nsMsgAccount()
00064 {
00065 }
00066 
00067 NS_IMETHODIMP 
00068 nsMsgAccount::Init()
00069 {
00070        NS_ASSERTION(!m_identities, "don't call Init twice!");
00071        if (m_identities) return NS_ERROR_FAILURE;
00072 
00073        return createIdentities();
00074 }
00075 
00076 nsresult
00077 nsMsgAccount::getPrefService() 
00078 {
00079   if (m_prefs) 
00080     return NS_OK;
00081 
00082   nsresult rv;
00083   m_prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
00084   if (NS_FAILED(rv))
00085     m_prefs = nsnull;
00086 
00087   return rv;
00088 }
00089 
00090 NS_IMETHODIMP
00091 nsMsgAccount::GetIncomingServer(nsIMsgIncomingServer * *aIncomingServer)
00092 {
00093   NS_ENSURE_ARG_POINTER(aIncomingServer);
00094 
00095   // create the incoming server lazily
00096   if (!m_incomingServer) {
00097     // ignore the error (and return null), but it's still bad so assert
00098     nsresult rv = createIncomingServer();
00099     NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't lazily create the server\n");
00100   }
00101   
00102   NS_IF_ADDREF(*aIncomingServer = m_incomingServer);
00103 
00104   return NS_OK;
00105 }
00106 
00107 nsresult
00108 nsMsgAccount::createIncomingServer()
00109 {
00110   if (!(const char*)m_accountKey) return NS_ERROR_NOT_INITIALIZED;
00111   // from here, load mail.account.myaccount.server
00112   // Load the incoming server
00113   //
00114   // ex) mail.account.myaccount.server = "myserver"
00115 
00116   nsresult rv = getPrefService();
00117   if (NS_FAILED(rv)) return rv;
00118 
00119   // get the "server" pref
00120   nsCAutoString serverKeyPref("mail.account.");
00121   serverKeyPref += m_accountKey;
00122   serverKeyPref += ".server";
00123   nsXPIDLCString serverKey;
00124   rv = m_prefs->GetCharPref(serverKeyPref.get(), getter_Copies(serverKey));
00125   if (NS_FAILED(rv)) return rv;
00126     
00127 #ifdef DEBUG_alecf
00128   printf("\t%s's server: %s\n", (const char*)m_accountKey, (const char*)serverKey);
00129 #endif
00130 
00131   // get the server from the account manager
00132   nsCOMPtr<nsIMsgAccountManager> accountManager = 
00133            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00134   NS_ENSURE_SUCCESS(rv, rv);
00135     
00136   nsCOMPtr<nsIMsgIncomingServer> server;
00137   rv = accountManager->GetIncomingServer(serverKey, getter_AddRefs(server));
00138   NS_ENSURE_SUCCESS(rv, rv);
00139   
00140   // store the server in this structure
00141   m_incomingServer = server;
00142   accountManager->NotifyServerLoaded(server);
00143 
00144   return NS_OK;
00145 }
00146 
00147 
00148 NS_IMETHODIMP
00149 nsMsgAccount::SetIncomingServer(nsIMsgIncomingServer * aIncomingServer)
00150 {
00151   nsresult rv;
00152   
00153   nsXPIDLCString key;
00154   rv = aIncomingServer->GetKey(getter_Copies(key));
00155   
00156   if (NS_SUCCEEDED(rv)) {
00157     nsCAutoString serverPrefName("mail.account.");
00158     serverPrefName.Append(m_accountKey);
00159     serverPrefName.Append(".server");
00160     m_prefs->SetCharPref(serverPrefName.get(), key);
00161   }
00162 
00163   m_incomingServer = aIncomingServer;
00164 
00165   PRBool serverValid;
00166   (void) aIncomingServer->GetValid(&serverValid);
00167   // only notify server loaded if server is valid so 
00168   // account manager only gets told about finished accounts.
00169   if (serverValid) 
00170   {
00171   nsCOMPtr<nsIMsgAccountManager> accountManager =
00172     do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00173     if (NS_SUCCEEDED(rv))
00174     accountManager->NotifyServerLoaded(aIncomingServer);
00175   }
00176   return NS_OK;
00177 }
00178 
00179 /* nsISupportsArray GetIdentities (); */
00180 NS_IMETHODIMP
00181 nsMsgAccount::GetIdentities(nsISupportsArray **_retval)
00182 {
00183   if (!_retval) return NS_ERROR_NULL_POINTER;
00184 
00185   NS_ASSERTION(m_identities,"you never called Init()");
00186   if (!m_identities) return NS_ERROR_FAILURE;
00187 
00188   *_retval = m_identities;
00189   NS_ADDREF(*_retval);
00190 
00191   return NS_OK;
00192 }
00193 
00194 /*
00195  * set up the m_identities array
00196  * do not call this more than once or we'll leak.
00197  */
00198 nsresult
00199 nsMsgAccount::createIdentities()
00200 {
00201   NS_ASSERTION(!m_identities, "only call createIdentities() once!");
00202   if (m_identities) return NS_ERROR_FAILURE;
00203 
00204   NS_ENSURE_TRUE((const char*)m_accountKey, NS_ERROR_NOT_INITIALIZED);
00205   
00206   NS_NewISupportsArray(getter_AddRefs(m_identities));
00207 
00208   // get the pref
00209   // ex) mail.account.myaccount.identities = "joe-home,joe-work"
00210   nsCAutoString identitiesKeyPref("mail.account.");
00211   identitiesKeyPref.Append(m_accountKey);
00212   identitiesKeyPref.Append(".identities");
00213   
00214   nsXPIDLCString identityKey;
00215   nsresult rv;
00216   rv = getPrefService();
00217   if (NS_FAILED(rv)) return rv;
00218   
00219   rv = m_prefs->GetCharPref(identitiesKeyPref.get(), getter_Copies(identityKey));
00220 
00221   if (NS_FAILED(rv)) return rv;
00222   if (identityKey.IsEmpty())    // not an error if no identities, but 
00223     return NS_OK;               // nsCRT::strtok will be unhappy
00224   
00225 #ifdef DEBUG_alecf
00226   printf("%s's identities: %s\n",
00227          (const char*)m_accountKey,
00228          (const char*)identityKey);
00229 #endif
00230   
00231   // get the server from the account manager
00232   nsCOMPtr<nsIMsgAccountManager> accountManager = 
00233            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00234   if (NS_FAILED(rv)) return rv;
00235 
00236   // const-casting because nsCRT::strtok whacks the string,
00237   // but safe because identityKey is a copy
00238   char* newStr;
00239   char* rest = identityKey.BeginWriting();
00240   char* token = nsCRT::strtok(rest, ",", &newStr);
00241 
00242   // temporaries used inside the loop
00243   nsCOMPtr<nsIMsgIdentity> identity;
00244   nsCAutoString key;
00245 
00246   // iterate through id1,id2, etc
00247   while (token) {
00248     key = token;
00249     key.StripWhitespace();
00250     
00251     // create the account
00252     rv = accountManager->GetIdentity(key.get(), getter_AddRefs(identity));
00253     if (NS_SUCCEEDED(rv)) {
00254       // ignore error from addIdentityInternal() - if it fails, it fails.
00255       rv = addIdentityInternal(identity);
00256       NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create identity");
00257     }
00258 
00259     // advance to next key, if any
00260     token = nsCRT::strtok(newStr, ",", &newStr);
00261   }
00262     
00263   return rv;
00264 }
00265 
00266 
00267 /* attribute nsIMsgIdentity defaultIdentity; */
00268 NS_IMETHODIMP
00269 nsMsgAccount::GetDefaultIdentity(nsIMsgIdentity * *aDefaultIdentity)
00270 {
00271   if (!aDefaultIdentity) return NS_ERROR_NULL_POINTER;
00272   nsresult rv;
00273   if (!m_identities) {
00274     rv = Init();
00275     if (NS_FAILED(rv)) return rv;
00276   }
00277 
00278   nsISupports* idsupports;
00279   rv = m_identities->GetElementAt(0, &idsupports);
00280   if (NS_FAILED(rv)) return rv;
00281   
00282   if (idsupports) {
00283       rv = idsupports->QueryInterface(NS_GET_IID(nsIMsgIdentity),
00284                                           (void **)aDefaultIdentity);
00285       NS_RELEASE(idsupports);
00286   }
00287   return rv;
00288 }
00289 
00290 // todo - make sure this is in the identity array!
00291 NS_IMETHODIMP
00292 nsMsgAccount::SetDefaultIdentity(nsIMsgIdentity * aDefaultIdentity)
00293 {
00294   NS_ASSERTION(m_identities,"you never called Init()");
00295   if (!m_identities) return NS_ERROR_FAILURE;  
00296   
00297   NS_ASSERTION(m_identities->IndexOf(aDefaultIdentity) != -1, "Where did that identity come from?!");
00298   if (m_identities->IndexOf(aDefaultIdentity) == -1)
00299     return NS_ERROR_UNEXPECTED;
00300   
00301   m_defaultIdentity = aDefaultIdentity;
00302   return NS_OK;
00303 }
00304 
00305 // add the identity to m_identities, but don't fiddle with the
00306 // prefs. The assumption here is that the pref for this identity is
00307 // already set.
00308 nsresult
00309 nsMsgAccount::addIdentityInternal(nsIMsgIdentity *identity)
00310 {
00311   NS_ASSERTION(m_identities,"you never called Init()");
00312   if (!m_identities) return NS_ERROR_FAILURE;  
00313 
00314   return m_identities->AppendElement(identity);
00315 }
00316 
00317 
00318 /* void addIdentity (in nsIMsgIdentity identity); */
00319 NS_IMETHODIMP
00320 nsMsgAccount::AddIdentity(nsIMsgIdentity *identity)
00321 {
00322   // hack hack - need to add this to the list of identities.
00323   // for now just treat this as a Setxxx accessor
00324   // when this is actually implemented, don't refcount the default identity
00325   nsresult rv;
00326   
00327   nsXPIDLCString key;
00328   rv = identity->GetKey(getter_Copies(key));
00329 
00330   if (NS_SUCCEEDED(rv)) {
00331 
00332     nsCAutoString identitiesKeyPref("mail.account.");
00333     identitiesKeyPref.Append(m_accountKey);
00334     identitiesKeyPref.Append(".identities");
00335       
00336     nsXPIDLCString identityList;
00337     m_prefs->GetCharPref(identitiesKeyPref.get(),
00338                          getter_Copies(identityList));
00339 
00340     nsCAutoString newIdentityList(identityList);
00341     
00342     nsCAutoString testKey;      // temporary to strip whitespace
00343     PRBool foundIdentity = PR_FALSE; // if the input identity is found
00344 
00345     // nsCRT::strtok will be unhappy with an empty string
00346     if (!identityList.IsEmpty()) {
00347       
00348       // const-casting because nsCRT::strtok whacks the string,
00349       // but safe because identityList is a copy
00350       char *newStr;
00351       char *rest = identityList.BeginWriting();
00352       char *token = nsCRT::strtok(rest, ",", &newStr);
00353       
00354       // look for the identity key that we're adding
00355       while (token) {
00356         testKey = token;
00357         testKey.StripWhitespace();
00358 
00359         if (testKey.Equals(key))
00360           foundIdentity = PR_TRUE;
00361 
00362         token = nsCRT::strtok(newStr, ",", &newStr);
00363       }
00364     }
00365 
00366     // if it didn't already exist, append it
00367     if (!foundIdentity) {
00368       if (newIdentityList.IsEmpty())
00369         newIdentityList = key;
00370       else {
00371         newIdentityList.Append(',');
00372         newIdentityList.Append(key);
00373       }
00374     }
00375     
00376     m_prefs->SetCharPref(identitiesKeyPref.get(), newIdentityList.get());
00377   }
00378 
00379   // now add it to the in-memory list
00380   rv = addIdentityInternal(identity);
00381   
00382   if (!m_defaultIdentity)
00383     SetDefaultIdentity(identity);
00384   
00385   return rv;
00386 }
00387 
00388 /* void removeIdentity (in nsIMsgIdentity identity); */
00389 NS_IMETHODIMP
00390 nsMsgAccount::RemoveIdentity(nsIMsgIdentity * aIdentity)
00391 {
00392   NS_ENSURE_TRUE(m_identities, NS_ERROR_FAILURE);
00393   NS_ENSURE_ARG_POINTER(aIdentity);
00394 
00395   PRUint32 count =0;
00396   m_identities->Count(&count);
00397 
00398   NS_ENSURE_TRUE(count > 1, NS_ERROR_FAILURE); // you must have at least one identity
00399 
00400   nsXPIDLCString key;
00401   nsresult rv = aIdentity->GetKey(getter_Copies(key));
00402 
00403   // remove our identity
00404   m_identities->RemoveElement(aIdentity);
00405   count--;
00406 
00407   // clear out the actual pref values associated with the identity
00408   aIdentity->ClearAllValues();
00409 
00410   // if we just deleted the default identity, clear it out so we pick a new one
00411   if (m_defaultIdentity == aIdentity)
00412     m_defaultIdentity = nsnull;
00413 
00414   // now rebuild the identity pref
00415   nsCAutoString identitiesKeyPref("mail.account.");
00416   identitiesKeyPref.Append(m_accountKey);
00417   identitiesKeyPref.Append(".identities");
00418       
00419   nsCAutoString newIdentityList;
00420 
00421   // iterate over the remaining identities
00422   for (PRUint32 index = 0; index < count; index++)
00423   {
00424     nsCOMPtr<nsIMsgIdentity> identity = do_QueryElementAt(m_identities, index, &rv);
00425     if (identity)
00426     {
00427       identity->GetKey(getter_Copies(key));
00428 
00429       if (!index)
00430         newIdentityList = key;
00431       else
00432       {
00433         newIdentityList.Append(',');
00434         newIdentityList.Append(key);
00435       }
00436     }
00437   }
00438 
00439   m_prefs->SetCharPref(identitiesKeyPref.get(), newIdentityList.get());
00440  
00441   return rv;
00442 }
00443 
00444 NS_IMPL_GETTER_STR(nsMsgAccount::GetKey, m_accountKey)
00445 
00446 nsresult
00447 nsMsgAccount::SetKey(const char *accountKey)
00448 {
00449   if (!accountKey) return NS_ERROR_NULL_POINTER;
00450 
00451   // need the prefs service to do anything
00452   nsresult rv = getPrefService();
00453   if (NS_FAILED(rv)) return rv;
00454 
00455   m_accountKey.Assign(accountKey);
00456   
00457   return Init();
00458 }
00459 
00460 NS_IMETHODIMP
00461 nsMsgAccount::ToString(PRUnichar **aResult)
00462 {
00463   nsAutoString val;
00464   val.AssignLiteral("[nsIMsgAccount: ");
00465   AppendASCIItoUTF16(m_accountKey, val);
00466   val.Append(']');
00467   *aResult = ToNewUnicode(val);
00468   return NS_OK;
00469 }
00470 
00471 
00472 NS_IMETHODIMP
00473 nsMsgAccount::ClearAllValues()
00474 {
00475     nsresult rv;
00476     nsCAutoString rootPref("mail.account.");
00477     rootPref += m_accountKey;
00478     rootPref += '.';
00479 
00480     rv = getPrefService();
00481     if (NS_FAILED(rv))
00482         return rv;
00483 
00484     PRUint32 cntChild, i;
00485     char **childArray;
00486  
00487     rv = m_prefs->GetChildList(rootPref.get(), &cntChild, &childArray);
00488     if (NS_SUCCEEDED(rv)) {
00489         for (i = 0; i < cntChild; i++)
00490             m_prefs->ClearUserPref(childArray[i]);
00491 
00492         NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(cntChild, childArray);
00493     }
00494 
00495     return rv;
00496 }