Back to index

lightning-sunbird  0.9+nobinonly
PalmSyncImp.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *                 Rajiv Dayal (rdayal@netscape.com)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * 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 #ifdef MOZ_LOGGING
00039 // sorry, this has to be before the pre-compiled header
00040 #define FORCE_PR_LOG /* Allow logging in the release build */
00041 #endif
00042 
00043 #include "nsString.h"
00044 #include "nsCOMPtr.h"
00045 #include "nsISupports.h"
00046 
00047 #include "IPalmSync.h"
00048 #include "PalmSyncImp.h"
00049 #include "PalmSyncFactory.h"
00050 
00051 #include "nsAbPalmSync.h"
00052 #include "nsMsgI18N.h"
00053 #include "nsUnicharUtils.h"
00054 #include "nsRDFResource.h"
00055 #include "nsRDFCID.h"
00056 #include "nsIRDFService.h"
00057 #include "nsIAbDirectory.h"
00058 
00059 #include "nsIPrefService.h"
00060 #include "nsIPrefBranch.h"
00061 
00062 #include "nspr.h"
00063 PRLogModuleInfo *PALMSYNC;
00064 
00065 #define kPABDirectory  2  // defined in nsDirPrefs.h
00066 #define kMAPIDirectory 3
00067 
00068 CPalmSyncImp::CPalmSyncImp()
00069 : m_cRef(1),
00070   m_PalmHotSync(nsnull)
00071 {
00072   if (!PALMSYNC)
00073     PALMSYNC = PR_NewLogModule("PALMSYNC");
00074 
00075 
00076 }
00077 
00078 CPalmSyncImp::~CPalmSyncImp() 
00079 { 
00080 
00081 }
00082 
00083 STDMETHODIMP CPalmSyncImp::QueryInterface(const IID& aIid, void** aPpv)
00084 {    
00085     if (aIid == IID_IUnknown)
00086     {
00087         *aPpv = static_cast<IPalmSync*>(this); 
00088     }
00089     else if (aIid == IID_IPalmSync)
00090     {
00091         *aPpv = static_cast<IPalmSync*>(this);
00092     }
00093     else
00094     {
00095         *aPpv = nsnull;
00096         return E_NOINTERFACE;
00097     }
00098 
00099     reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
00100     return S_OK;
00101 }
00102 
00103 STDMETHODIMP_(ULONG) CPalmSyncImp::AddRef()
00104 {
00105     return PR_AtomicIncrement(&m_cRef);
00106 }
00107 
00108 STDMETHODIMP_(ULONG) CPalmSyncImp::Release() 
00109 {
00110     PRInt32 temp;
00111     temp = PR_AtomicDecrement(&m_cRef);
00112     if (m_cRef == 0)
00113     {
00114         delete this;
00115         return 0;
00116     }
00117 
00118     return temp;
00119 }
00120 
00121 STDMETHODIMP CPalmSyncImp::IsValid()
00122 {
00123     return S_OK;
00124 }
00125 
00126 // Get the list of Address Books for the currently logged in user profile
00127 STDMETHODIMP CPalmSyncImp::nsGetABList(BOOL aIsUnicode, short * aABListCount,
00128                         lpnsMozABDesc * aABList, long ** aABCatIndexList, BOOL ** aDirFlagsList)
00129 {
00130   if (!aABListCount || !aABList || !aABCatIndexList ||!aDirFlagsList)
00131         return E_FAIL;
00132   *aABListCount = 0;
00133 
00134   nsresult rv;
00135   nsCOMPtr<nsIRDFService> rdfService = do_GetService (NS_RDF_CONTRACTID "/rdf-service;1", &rv);
00136   if(NS_FAILED(rv)) return E_FAIL;
00137 
00138   // Parent nsIABDirectory is "moz-abdirectory://".
00139   nsCOMPtr <nsIRDFResource> resource;
00140   rv = rdfService->GetResource(NS_LITERAL_CSTRING("moz-abdirectory://"), getter_AddRefs(resource));
00141   if(NS_FAILED(rv)) return E_FAIL;
00142 
00143   nsCOMPtr <nsIAbDirectory> directory = do_QueryInterface(resource, &rv);
00144   if(NS_FAILED(rv)) return E_FAIL;
00145 
00146   nsCOMPtr<nsISimpleEnumerator> subDirectories;
00147   if (NS_SUCCEEDED(directory->GetChildNodes(getter_AddRefs(subDirectories))) && subDirectories)
00148   {
00149     // Get the total number of addrbook.
00150     PRInt16 count=0;
00151     nsCOMPtr<nsISupports> item;
00152     PRBool hasMore;
00153     while (NS_SUCCEEDED(rv = subDirectories->HasMoreElements(&hasMore)) && hasMore)
00154     {
00155         if (NS_SUCCEEDED(subDirectories->GetNext(getter_AddRefs(item))))
00156         {
00157           nsCOMPtr <nsIAbDirectory> subDirectory = do_QueryInterface(item, &rv);
00158           if (NS_SUCCEEDED(rv))
00159           {
00160               nsCOMPtr <nsIAbDirectoryProperties> properties;
00161               nsXPIDLCString fileName;
00162               rv = subDirectory->GetDirectoryProperties(getter_AddRefs(properties));
00163               if(NS_FAILED(rv)) 
00164                 continue;
00165               rv = properties->GetFileName(getter_Copies(fileName));
00166               if(NS_FAILED(rv)) 
00167                 continue;
00168               PRUint32 dirType;
00169               rv = properties->GetDirType(&dirType);
00170               nsCAutoString prefName;
00171               subDirectory->GetDirPrefId(prefName);
00172               prefName.Append(".disablePalmSync");
00173               PRBool disableThisAB = GetBoolPref(prefName.get(), PR_FALSE);
00174               // Skip/Ignore 4.X addrbooks (ie, with ".na2" extension), and non personal AB's
00175               if (disableThisAB || ((fileName.Length() > kABFileName_PreviousSuffixLen) && 
00176                    strcmp(fileName.get() + fileName.Length() - kABFileName_PreviousSuffixLen, kABFileName_PreviousSuffix) == 0) ||
00177                     (dirType != kPABDirectory && dirType != kMAPIDirectory))
00178                     continue;
00179           }
00180         }
00181         count++;
00182     }
00183 
00184     if (!count)
00185       return E_FAIL;  // should not happen but just in case.
00186 
00187     lpnsMozABDesc serverDescList = (lpnsMozABDesc) CoTaskMemAlloc(sizeof(nsMozABDesc) * count);
00188     BOOL *dirFlagsList = (BOOL *) CoTaskMemAlloc(sizeof(BOOL) * count);
00189     long *catIndexList = (long *) CoTaskMemAlloc(sizeof(long) * count);
00190 
00191     *aABListCount = count;
00192     *aABList = serverDescList;
00193     *aDirFlagsList = dirFlagsList;
00194     *aABCatIndexList = catIndexList;
00195 
00196     directory->GetChildNodes(getter_AddRefs(subDirectories)); // reset enumerator
00197     // For each valid addrbook collect info.
00198     while (NS_SUCCEEDED(rv = subDirectories->HasMoreElements(&hasMore)) && hasMore)
00199     {
00200       if (NS_SUCCEEDED(subDirectories->GetNext(getter_AddRefs(item))))
00201       {
00202         directory = do_QueryInterface(item, &rv);
00203         if (NS_SUCCEEDED(rv))
00204         {
00205           // We don't have to skip mailing list since there's no mailing lists at the top level.
00206           nsCOMPtr <nsIAbDirectoryProperties> properties;
00207           rv = directory->GetDirectoryProperties(getter_AddRefs(properties));
00208           if(NS_FAILED(rv)) return E_FAIL;
00209 
00210           nsXPIDLCString fileName, uri;
00211           nsAutoString description;
00212           PRUint32 dirType, palmSyncTimeStamp;
00213           PRInt32 palmCategoryIndex;
00214 
00215           rv = properties->GetDescription(description);
00216           if(NS_FAILED(rv)) return E_FAIL;
00217           rv = properties->GetFileName(getter_Copies(fileName));
00218           if(NS_FAILED(rv)) return E_FAIL;
00219           rv = properties->GetURI(getter_Copies(uri));
00220           if(NS_FAILED(rv)) return E_FAIL;
00221           rv = properties->GetDirType(&dirType);
00222           if(NS_FAILED(rv)) return E_FAIL;
00223           rv = properties->GetSyncTimeStamp(&palmSyncTimeStamp);
00224           if(NS_FAILED(rv)) return E_FAIL;
00225           rv = properties->GetCategoryId(&palmCategoryIndex);
00226           if(NS_FAILED(rv)) return E_FAIL;
00227           nsCAutoString prefName;
00228           directory->GetDirPrefId(prefName);
00229           prefName.Append(".disablePalmSync");
00230           PRBool disableThisAB = GetBoolPref(prefName.get(), PR_FALSE);
00231           // Skip/Ignore 4.X addrbooks (ie, with ".na2" extension), and non personal AB's
00232           if (disableThisAB || ((fileName.Length() > kABFileName_PreviousSuffixLen) && 
00233                strcmp(fileName.get() + fileName.Length() - kABFileName_PreviousSuffixLen, kABFileName_PreviousSuffix) == 0) ||
00234                 (dirType != kPABDirectory && dirType != kMAPIDirectory))
00235           {
00236             continue;
00237           }
00238 
00239           if(aIsUnicode) 
00240           {
00241             // convert uri to Unicode
00242             nsAutoString abUrl;
00243             rv = ConvertToUnicode("UTF-8", uri, abUrl);
00244             if (NS_FAILED(rv))
00245               break;
00246             // add to the list
00247             CopyUnicodeString(&(serverDescList->lpszABName), description);
00248             CopyUnicodeString(&(serverDescList->lpszABUrl), abUrl);
00249           }
00250           else {
00251             // we need to convert uri to Unicode and then to ASCII
00252             nsAutoString abUUrl;
00253 
00254             rv = ConvertToUnicode("UTF-8", uri, abUUrl);
00255             if (NS_FAILED(rv))
00256               break;
00257 
00258             CopyCString(&(serverDescList->lpszABName),
00259                         NS_ConvertUTF16toUTF8(description));
00260             CopyCString(&(serverDescList->lpszABUrl),
00261                         NS_ConvertUTF16toUTF8(abUUrl));
00262           }
00263           serverDescList++;
00264 
00265           PRUint32 dirFlag = 0;
00266           if (palmSyncTimeStamp <= 0)
00267             dirFlag |= kFirstTimeSyncDirFlag;
00268           // was this the pab?
00269           if (prefName.Equals("ldap_2.servers.pab.disablePalmSync"))
00270             dirFlag |= kIsPabDirFlag;
00271           *dirFlagsList = (BOOL) dirFlag;
00272           dirFlagsList++;
00273 
00274           *catIndexList = palmCategoryIndex;
00275           catIndexList++;
00276         }
00277       }
00278     }
00279 
00280     // assign member variables to the beginning of the list
00281     serverDescList = *aABList;
00282     dirFlagsList = *aDirFlagsList;
00283     catIndexList = *aABCatIndexList;
00284 
00285     if(NS_FAILED(rv))
00286       return E_FAIL;
00287   }
00288   return S_OK;
00289 }
00290 
00291 // Synchronize the Address Book represented by the aCategoryIndex and/or corresponding aABName in Mozilla
00292 STDMETHODIMP CPalmSyncImp::nsSynchronizeAB(BOOL aIsUnicode, long aCategoryIndex,
00293                     long aCategoryId, LPTSTR aABName,
00294                     int aModRemoteRecCount, lpnsABCOMCardStruct aModRemoteRecList,
00295                     int * aModMozRecCount, lpnsABCOMCardStruct * aModMozRecList)
00296 {
00297     // let the already continuing sync complete
00298     if(m_PalmHotSync)
00299         return E_FAIL;
00300 
00301     m_PalmHotSync = (nsAbPalmHotSync *) new nsAbPalmHotSync(aIsUnicode, aABName, (char*)aABName, aCategoryIndex, aCategoryId);
00302     if(!m_PalmHotSync)
00303         return E_FAIL;
00304 
00305     nsresult rv = ((nsAbPalmHotSync *)m_PalmHotSync)->Initialize();
00306     if (NS_SUCCEEDED(rv))
00307         rv = ((nsAbPalmHotSync *)m_PalmHotSync)->DoSyncAndGetUpdatedCards(aModRemoteRecCount, aModRemoteRecList, aModMozRecCount, aModMozRecList);
00308 
00309     if (NS_FAILED(rv))
00310         return E_FAIL;
00311 
00312     return S_OK;
00313 }
00314 
00315 // All records from a AB represented by aCategoryIndex and aABName into a new Mozilla AB
00316 STDMETHODIMP CPalmSyncImp::nsAddAllABRecords(BOOL aIsUnicode, BOOL replaceExisting, long aCategoryIndex, LPTSTR aABName,
00317                             int aRemoteRecCount, lpnsABCOMCardStruct aRemoteRecList)
00318 {
00319     // since we are not returning any data we don't need to keep the nsAbPalmHotSync reference
00320     // in order to free the returned data in its destructor. Just create a local nsAbPalmHotSync var.
00321     nsAbPalmHotSync palmHotSync(aIsUnicode, aABName, (const char*)aABName, aCategoryIndex, -1);
00322 
00323     nsresult rv = palmHotSync.AddAllRecordsToAB(replaceExisting, aRemoteRecCount, aRemoteRecList);
00324 
00325     if (NS_FAILED(rv))
00326         return E_FAIL;
00327 
00328     return S_OK;
00329 }
00330 
00331 STDMETHODIMP CPalmSyncImp::nsGetABDeleted(LPTSTR aABName, BOOL *abDeleted)
00332 {
00333   nsCAutoString prefName("ldap_2.servers.");
00334   prefName.Append((const char *)aABName);
00335   prefName.Append(".position");
00336   PRInt32 position = GetIntPref(prefName.get(), -1);
00337   *abDeleted = (position == 0);
00338   return S_OK;
00339 }
00340 
00341 
00342 // Get All records from a Mozilla AB
00343 STDMETHODIMP CPalmSyncImp::nsGetAllABCards(BOOL aIsUnicode, long aCategoryIndex, LPTSTR aABName,
00344                             int * aMozRecCount, lpnsABCOMCardStruct * aMozRecList)
00345 {
00346     // if sync is already going on wait for AckSyncDone to be called
00347     if(m_PalmHotSync)
00348         return E_FAIL;
00349 
00350     m_PalmHotSync = (nsAbPalmHotSync *) new nsAbPalmHotSync(aIsUnicode, aABName, (char*)aABName, aCategoryIndex, -1);
00351     if(!m_PalmHotSync)
00352         return E_FAIL;
00353 
00354     nsresult rv = ((nsAbPalmHotSync *)m_PalmHotSync)->Initialize();
00355     if (NS_SUCCEEDED(rv))
00356         rv = ((nsAbPalmHotSync *)m_PalmHotSync)->GetAllCards(aMozRecCount, aMozRecList);
00357 
00358     if (NS_FAILED(rv))
00359         return E_FAIL;
00360 
00361     return S_OK;
00362 }
00363 
00364 // Send an ack for sync done on the remote AB to Mozilla, 
00365 // now we delete the data returned to the calling app.
00366 STDMETHODIMP CPalmSyncImp::nsAckSyncDone(BOOL aIsSuccess, long aCatIndex, int aNewRecCount, unsigned long * aNewPalmRecIDList)
00367 {
00368     nsAbPalmHotSync * tempPalmHotSync = (nsAbPalmHotSync *) m_PalmHotSync;
00369     if(tempPalmHotSync) {
00370         if(aNewRecCount && (aCatIndex > -1))
00371             tempPalmHotSync->Done(aIsSuccess, aCatIndex, aNewRecCount, aNewPalmRecIDList);
00372         delete tempPalmHotSync;
00373     }
00374     m_PalmHotSync = nsnull;
00375 
00376     return S_OK;
00377 }
00378 
00379 // Update the category id and mod tiem for the Address Book in Mozilla
00380 STDMETHODIMP CPalmSyncImp::nsUpdateABSyncInfo(BOOL aIsUnicode, long aCategoryIndex, LPTSTR aABName)
00381 {
00382   nsresult rv;
00383   if(m_PalmHotSync)
00384     rv = ((nsAbPalmHotSync *)m_PalmHotSync)->UpdateSyncInfo(aCategoryIndex);
00385   else
00386   {
00387     // Launch another ABpalmHotSync session.
00388     nsAbPalmHotSync palmHotSync(aIsUnicode, aABName, (const char*)aABName, aCategoryIndex, -1);
00389     rv = palmHotSync.Initialize();
00390     if (NS_SUCCEEDED(rv))
00391       rv = palmHotSync.UpdateSyncInfo(aCategoryIndex);
00392   }
00393 
00394   if (NS_FAILED(rv))
00395     return E_FAIL;
00396 
00397   return S_OK;
00398 }
00399 
00400 // Delete an Address Book in Mozilla
00401 STDMETHODIMP CPalmSyncImp::nsDeleteAB(BOOL aIsUnicode, long aCategoryIndex, LPTSTR aABName, LPTSTR aABUrl)
00402 {
00403   // This is an independent operation so use a local nsAbPalmHotSync var
00404   // (ie the callers don't need to call AckSyncdone after this is done).
00405   nsAbPalmHotSync palmHotSync(aIsUnicode, aABName, (const char*)aABName, aCategoryIndex, -1);
00406 
00407   nsresult rv = palmHotSync.DeleteAB(aCategoryIndex, (const char*)aABUrl);
00408 
00409   if (NS_FAILED(rv))
00410       return E_FAIL;
00411 
00412   return S_OK;
00413 }
00414 
00415 // Rename an Address Book in Mozilla
00416 STDMETHODIMP CPalmSyncImp::nsRenameAB(BOOL aIsUnicode, long aCategoryIndex, LPTSTR aABName, LPTSTR aABUrl)
00417 {
00418   // This is an independent operation so use a local nsAbPalmHotSync var
00419   // (ie the callers don't need to call AckSyncdone after this is done).
00420   nsAbPalmHotSync palmHotSync(aIsUnicode, aABName, (const char*)aABName, aCategoryIndex, -1);
00421 
00422   nsresult rv = palmHotSync.RenameAB(aCategoryIndex, (const char*)aABUrl);
00423 
00424   if (NS_FAILED(rv))
00425     return E_FAIL;
00426 
00427   return S_OK;
00428 }
00429 
00430 void CPalmSyncImp::CopyUnicodeString(LPTSTR *destStr, const nsAFlatString& srcStr)
00431 {
00432   if (!destStr)
00433     return;
00434 
00435   PRInt32 length = srcStr.Length()+1;
00436   *destStr = (LPTSTR) CoTaskMemAlloc(sizeof(PRUnichar) * length);
00437   wcsncpy(*destStr, srcStr.get(), length-1);
00438   (*destStr)[length-1] = '\0';
00439 }
00440 
00441 void CPalmSyncImp::CopyCString(LPTSTR *destStr, const nsAFlatCString& srcStr)
00442 {
00443   if (!destStr)
00444     return;
00445 
00446   // these strings are defined as wide in the idl, so we need to add up to 3
00447   // bytes of 0 byte padding at the end (if the string is an odd number of
00448   // bytes long, we need one null byte to pad out the last char to a wide char
00449   // and then  two more nulls as a wide null terminator. 
00450   PRInt32 length = sizeof(char) * (srcStr.Length()+3);
00451   *destStr = (LPTSTR) CoTaskMemAlloc(length);
00452   char *sp = (char *)*destStr;
00453   strncpy(sp, srcStr.get(), length-1); // this will null fill the end of destStr
00454   sp[length-1] = '\0';
00455 }
00456 
00457 
00458 /* static */PRBool CPalmSyncImp::GetBoolPref(const char *prefName, PRBool defaultVal)
00459 {
00460   PRBool boolVal = defaultVal;
00461   
00462   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
00463   if (prefBranch)
00464     prefBranch->GetBoolPref(prefName, &boolVal);
00465   return boolVal;
00466 }
00467 
00468 /* static */PRInt32 CPalmSyncImp::GetIntPref(const char *prefName, PRInt32 defaultVal)
00469 {
00470   PRInt32 intVal = defaultVal;
00471   
00472   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
00473   if (prefBranch)
00474     prefBranch->GetIntPref(prefName, &intVal);
00475   return intVal;
00476 }
00477 
00478 
00479 STDMETHODIMP CPalmSyncImp::nsUseABHomeAddressForPalmAddress(BOOL *aUseHomeAddress)
00480 {
00481   *aUseHomeAddress = nsUseABHomeAddressForPalmAddress();
00482   return S_OK;
00483 }
00484 
00485 STDMETHODIMP CPalmSyncImp::nsPreferABHomePhoneForPalmPhone(BOOL *aPreferHomePhone)
00486 {
00487   *aPreferHomePhone = nsPreferABHomePhoneForPalmPhone();
00488   return S_OK;
00489 }
00490 
00491 /* static */ PRBool CPalmSyncImp::nsUseABHomeAddressForPalmAddress()
00492 {
00493   static PRBool gGotAddressPref = PR_FALSE;
00494   static PRBool gUseHomeAddress;
00495   if (!gGotAddressPref)
00496   {
00497     gUseHomeAddress = GetBoolPref("mail.palmsync.useHomeAddress", PR_TRUE);
00498     gGotAddressPref = PR_TRUE;
00499   }
00500   return gUseHomeAddress;
00501 }
00502 
00503 /* static */ PRBool CPalmSyncImp::nsPreferABHomePhoneForPalmPhone()
00504 {
00505   static PRBool gGotPhonePref = PR_FALSE;
00506   static PRBool gPreferHomePhone;
00507   if (!gGotPhonePref)
00508   {
00509     gPreferHomePhone = GetBoolPref("mail.palmsync.preferHomePhone", PR_TRUE);
00510     gGotPhonePref = PR_TRUE;
00511   }
00512   return gPreferHomePhone;
00513 }