Back to index

lightning-sunbird  0.9+nobinonly
nsOEAddressIterator.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 /*
00040 
00041   A sample of XPConnect. This file contains an implementation of
00042   nsISample.
00043 
00044 */
00045 #include "nscore.h"
00046 #include "nsCRT.h"
00047 #include "nsCOMPtr.h"
00048 #include "nsString.h"
00049 #include "nsReadableUtils.h"
00050 #include "nsIComponentManager.h"
00051 #include "nsIServiceManager.h"
00052 #include "nsIImportService.h"
00053 #include "nsIImportFieldMap.h"
00054 #include "nsABBaseCID.h"
00055 #include "nsIAbCard.h"
00056 
00057 #include "nsOEAddressIterator.h"
00058 
00059 #include "OEDebugLog.h"
00060 
00061 typedef struct {
00062        PRInt32              mozField;
00063        PRInt32              multiLine;
00064        ULONG         mapiTag;
00065 } MAPIFields;
00066 
00067 enum {
00068     ieidPR_DISPLAY_NAME = 0,
00069     ieidPR_ENTRYID,
00070        ieidPR_OBJECT_TYPE,
00071     ieidMax
00072 };
00073 
00074 /*
00075        Fields in MAPI, not in Mozilla
00076        PR_OFFICE_LOCATION
00077        FIX - PR_BIRTHDAY - stored as PT_SYSTIME - FIX to extract for moz address book birthday
00078        PR_DISPLAY_NAME_PREFIX - Mr., Mrs. Dr., etc.
00079        PR_SPOUSE_NAME
00080        PR_GENDER - integer, not text
00081        FIX - PR_CONTACT_EMAIL_ADDRESSES - multiuline strings for email addresses, needs
00082               parsing to get secondary email address for mozilla
00083 */
00084 
00085 #define kIsMultiLine -2
00086 #define       kNoMultiLine  -1
00087 
00088 static MAPIFields    gMapiFields[] = {
00089        { 35, kIsMultiLine, PR_COMMENT},
00090        { 6, kNoMultiLine, PR_BUSINESS_TELEPHONE_NUMBER},
00091        { 7, kNoMultiLine, PR_HOME_TELEPHONE_NUMBER},
00092        { 25, kNoMultiLine, PR_COMPANY_NAME},
00093        { 23, kNoMultiLine, PR_TITLE},
00094        { 10, kNoMultiLine, PR_CELLULAR_TELEPHONE_NUMBER},
00095        { 9, kNoMultiLine, PR_PAGER_TELEPHONE_NUMBER},
00096        { 8, kNoMultiLine, PR_BUSINESS_FAX_NUMBER},
00097        { 8, kNoMultiLine, PR_HOME_FAX_NUMBER},
00098        { 22, kNoMultiLine, PR_COUNTRY},
00099        { 19, kNoMultiLine, PR_LOCALITY},
00100        { 20, kNoMultiLine, PR_STATE_OR_PROVINCE},
00101        { 17, 18, PR_STREET_ADDRESS},
00102        { 21, kNoMultiLine, PR_POSTAL_CODE},
00103        { 27, kNoMultiLine, PR_PERSONAL_HOME_PAGE},
00104        { 26, kNoMultiLine, PR_BUSINESS_HOME_PAGE},
00105        { 13, kNoMultiLine, PR_HOME_ADDRESS_CITY},
00106        { 16, kNoMultiLine, PR_HOME_ADDRESS_COUNTRY},
00107        { 15, kNoMultiLine, PR_HOME_ADDRESS_POSTAL_CODE},
00108        { 14, kNoMultiLine, PR_HOME_ADDRESS_STATE_OR_PROVINCE},
00109        { 11, 12, PR_HOME_ADDRESS_STREET},
00110        { 24, kNoMultiLine, PR_DEPARTMENT_NAME}
00111 };
00112 
00113 nsOEAddressIterator::nsOEAddressIterator( CWAB *pWab, nsIAddrDatabase *database)
00114 {
00115   m_pWab = pWab;
00116   m_database = database;
00117   NS_IF_ADDREF( m_database);
00118 }
00119 
00120 nsOEAddressIterator::~nsOEAddressIterator()
00121 {
00122   m_listRows.Reset();
00123   NS_IF_RELEASE( m_database);
00124 }
00125 
00126 nsresult nsOEAddressIterator::EnumUser( const PRUnichar * pName, LPENTRYID pEid, ULONG cbEid)
00127 {
00128   IMPORT_LOG1( "User: %S\n", pName);
00129   nsresult    rv = NS_OK;
00130   
00131   if (m_database) {
00132     LPMAILUSER       pUser = m_pWab->GetUser( cbEid, pEid);
00133     if (pUser) {
00134       // Get a new row from the database!
00135       nsCOMPtr <nsIMdbRow> newRow;
00136       rv = m_database->GetNewRow(getter_AddRefs(newRow));
00137       NS_ENSURE_SUCCESS(rv, rv);
00138       if (newRow && BuildCard( pName, newRow, pUser))
00139       {
00140         rv = m_database->AddCardRowToDB(newRow);
00141         NS_ENSURE_SUCCESS(rv, rv);
00142         IMPORT_LOG0( "* Added entry to address book database\n");
00143         nsString  eMail;
00144 
00145         LPSPropValue pProp = m_pWab->GetUserProperty( pUser, PR_EMAIL_ADDRESS);
00146         if (pProp) 
00147         {
00148           m_pWab->GetValueString( pProp, eMail);
00149           SanitizeValue( eMail);
00150           m_pWab->FreeProperty( pProp);
00151           nsStringKey hashKey(eMail);
00152           m_listRows.Put(&hashKey, newRow);
00153         }
00154       }
00155       m_pWab->ReleaseUser( pUser);
00156     }
00157   }    
00158   
00159   return(rv);
00160 }
00161 
00162 void nsOEAddressIterator::FindListRow(nsString &eMail, nsIMdbRow **cardRow)
00163 {
00164   nsStringKey hashKey(eMail);
00165   *cardRow = (nsIMdbRow *) m_listRows.Get(&hashKey);
00166 }
00167 
00168 nsresult nsOEAddressIterator::EnumList( const PRUnichar * pName, LPENTRYID pEid, ULONG cbEid, LPMAPITABLE lpTable)
00169 {
00170   // If no name provided then we're done.
00171   if (!pName || !(*pName))
00172     return NS_OK;
00173 
00174   nsresult rv = NS_ERROR_FAILURE;
00175   HRESULT hr = E_FAIL;
00176   // Make sure we have db to work with.
00177   if (!m_database)
00178     return rv;
00179 
00180   nsCOMPtr <nsIMdbRow>  listRow;
00181   rv = m_database->GetNewListRow(getter_AddRefs(listRow));
00182   NS_ENSURE_SUCCESS(rv, rv);
00183 
00184   rv = m_database->AddListName(listRow, NS_ConvertUCS2toUTF8(pName).get());
00185   NS_ENSURE_SUCCESS(rv, rv);
00186   rv = m_database->AddCardRowToDB(listRow);
00187   NS_ENSURE_SUCCESS(rv, rv);
00188   rv = m_database->AddListDirNode(listRow);
00189   NS_ENSURE_SUCCESS(rv, rv);
00190 
00191   LPSRowSet   lpRowAB = NULL;
00192   ULONG             lpcbEID = 0;
00193   LPENTRYID   lpEID = NULL;
00194   ULONG             rowCount = 0;
00195   int         cNumRows = 0;
00196   int         numListElems = 0;
00197   nsAutoString    uniStr;
00198 
00199   hr = lpTable->GetRowCount( 0, &rowCount);
00200   //
00201   hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL );
00202 
00203   if(HR_FAILED(hr))
00204     return NS_ERROR_FAILURE;
00205 
00206   // Read all the rows of the table one by one
00207   do 
00208   {
00209     hr = lpTable->QueryRows(1, 0, &lpRowAB);
00210   
00211     if(HR_FAILED(hr))
00212       break;
00213   
00214     if(lpRowAB)
00215     {
00216       cNumRows = lpRowAB->cRows;
00217       if (cNumRows)
00218       {
00219         LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
00220         LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
00221         ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb;
00222       
00223         // There are 2 kinds of objects - the MAPI_MAILUSER contact object
00224         // and the MAPI_DISTLIST contact object
00225         // For distribution lists, we will only consider MAILUSER
00226         // objects since we can't nest lists yet.
00227         if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER)
00228         {
00229           LPMAILUSER pUser = m_pWab->GetUser( cbEID, lpEID);
00230           LPSPropValue pProp = m_pWab->GetUserProperty( pUser, PR_EMAIL_ADDRESS);
00231          nsString  eMail;
00232 
00233           nsCOMPtr <nsIMdbRow> cardRow;
00234 
00235          m_pWab->GetValueString( pProp, eMail);
00236          SanitizeValue( eMail);
00237           FindListRow(eMail, getter_AddRefs(cardRow));
00238           if (cardRow)
00239           {
00240             nsCOMPtr <nsIAbCard> userCard;
00241             nsCOMPtr <nsIAbCard> newCard;
00242             userCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv);
00243             NS_ENSURE_SUCCESS(rv, rv);
00244             m_database->InitCardFromRow(userCard,cardRow);
00245 
00246             m_database->AddListCardColumnsToRow(userCard, listRow, ++numListElems,
00247                                         getter_AddRefs(newCard),PR_TRUE);
00248           }
00249          m_pWab->FreeProperty( pProp);
00250           m_pWab->ReleaseUser( pUser);
00251         }
00252       }
00253       m_pWab->FreeProws(lpRowAB );        
00254     }
00255   } while (SUCCEEDED(hr) && cNumRows && lpRowAB);
00256 
00257   m_database->SetListAddressTotal(listRow, numListElems);
00258   return rv;
00259 }
00260 
00261 void nsOEAddressIterator::SanitizeValue( nsString& val)
00262 {
00263        val.ReplaceSubstring(NS_LITERAL_STRING("\x0D\x0A").get(),
00264                          NS_LITERAL_STRING(", ").get());
00265        val.ReplaceChar( 13, ',');
00266        val.ReplaceChar( 10, ',');
00267 }
00268 
00269 void nsOEAddressIterator::SplitString( nsString& val1, nsString& val2)
00270 {
00271   nsString    temp;
00272   
00273   // Find the last line if there is more than one!
00274   PRInt32 idx = val1.RFind( "\x0D\x0A");
00275   PRInt32     cnt = 2;
00276   if (idx == -1) {
00277     cnt = 1;
00278     idx = val1.RFindChar( 13);
00279   }
00280   if (idx == -1)
00281     idx= val1.RFindChar( 10);
00282   if (idx != -1) {
00283     val1.Right( val2, val1.Length() - idx - cnt);
00284     val1.Left( temp, idx);
00285     val1 = temp;
00286     SanitizeValue( val1);
00287   }
00288 }
00289 
00290 PRBool nsOEAddressIterator::BuildCard( const PRUnichar * pName, nsIMdbRow *newRow, LPMAILUSER pUser)
00291 {
00292   
00293   nsString           lastName;
00294   nsString           firstName;
00295   nsString           eMail;
00296   nsString           nickName;
00297   nsString           middleName;
00298   
00299   LPSPropValue       pProp = m_pWab->GetUserProperty( pUser, PR_EMAIL_ADDRESS);
00300   if (pProp) {
00301     m_pWab->GetValueString( pProp, eMail);
00302     SanitizeValue( eMail);
00303     m_pWab->FreeProperty( pProp);
00304   }
00305   pProp = m_pWab->GetUserProperty( pUser, PR_GIVEN_NAME);
00306   if (pProp) {
00307     m_pWab->GetValueString( pProp, firstName);
00308     SanitizeValue( firstName);
00309     m_pWab->FreeProperty( pProp);
00310   }
00311   pProp = m_pWab->GetUserProperty( pUser, PR_SURNAME);
00312   if (pProp) {
00313     m_pWab->GetValueString( pProp, lastName);
00314     SanitizeValue( lastName);
00315     m_pWab->FreeProperty( pProp);
00316   }
00317   pProp = m_pWab->GetUserProperty( pUser, PR_MIDDLE_NAME);
00318   if (pProp) {
00319     m_pWab->GetValueString( pProp, middleName);
00320     SanitizeValue( middleName);
00321     m_pWab->FreeProperty( pProp);
00322   }
00323   pProp = m_pWab->GetUserProperty( pUser, PR_NICKNAME);
00324   if (pProp) {
00325     m_pWab->GetValueString( pProp, nickName);
00326     SanitizeValue( nickName);
00327     m_pWab->FreeProperty( pProp);
00328   }
00329   
00330   // The idea here is that firstName and lastName cannot both be empty!
00331   if (firstName.IsEmpty() && lastName.IsEmpty())
00332     firstName = pName;
00333   
00334   nsString    displayName;
00335   pProp = m_pWab->GetUserProperty( pUser, PR_DISPLAY_NAME);
00336   if (pProp) {
00337     m_pWab->GetValueString( pProp, displayName);
00338     SanitizeValue( displayName);
00339     m_pWab->FreeProperty( pProp);
00340   }
00341   if (displayName.IsEmpty()) {
00342     if (firstName.IsEmpty())
00343       displayName = pName;
00344     else {
00345       displayName = firstName;
00346       if (!middleName.IsEmpty()) {
00347         displayName.Append(PRUnichar(' '));
00348         displayName.Append( middleName);
00349       }
00350       if (!lastName.IsEmpty()) {
00351         displayName.Append(PRUnichar(' '));
00352         displayName.Append( lastName);
00353       }
00354     }
00355   }
00356   
00357   // We now have the required fields
00358   // write them out followed by any optional fields!
00359   if (!displayName.IsEmpty()) {
00360     m_database->AddDisplayName( newRow, NS_ConvertUCS2toUTF8(displayName).get());
00361   }
00362   if (!firstName.IsEmpty()) {
00363     m_database->AddFirstName( newRow, NS_ConvertUCS2toUTF8(firstName).get());
00364   }
00365   if (!lastName.IsEmpty()) {
00366     m_database->AddLastName( newRow, NS_ConvertUCS2toUTF8(lastName).get());
00367   }
00368   if (!nickName.IsEmpty()) {
00369     m_database->AddNickName( newRow, NS_ConvertUCS2toUTF8(nickName).get());
00370   }
00371   if (!eMail.IsEmpty()) {
00372     m_database->AddPrimaryEmail( newRow, NS_ConvertUCS2toUTF8(eMail).get());
00373   }
00374   
00375   // Do all of the extra fields!
00376   
00377   nsString    value;
00378   nsString    line2;
00379   nsresult    rv;
00380   // Create a field map
00381   
00382   nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv));
00383   if (NS_SUCCEEDED( rv)) {
00384     nsIImportFieldMap *            pFieldMap = nsnull;
00385     rv = impSvc->CreateNewFieldMap( &pFieldMap);
00386     if (NS_SUCCEEDED( rv) && pFieldMap) {
00387       int max = sizeof( gMapiFields) / sizeof( MAPIFields);
00388       for (int i = 0; i < max; i++) {
00389         pProp = m_pWab->GetUserProperty( pUser, gMapiFields[i].mapiTag);
00390         if (pProp) {
00391           m_pWab->GetValueString( pProp, value);
00392           m_pWab->FreeProperty( pProp);
00393           if (!value.IsEmpty()) {
00394             if (gMapiFields[i].multiLine == kNoMultiLine) {
00395               SanitizeValue( value);
00396               pFieldMap->SetFieldValue( m_database, newRow, gMapiFields[i].mozField, value.get());
00397             }
00398             else if (gMapiFields[i].multiLine == kIsMultiLine) {
00399               pFieldMap->SetFieldValue( m_database, newRow, gMapiFields[i].mozField, value.get());
00400             }
00401             else {
00402               line2.Truncate();
00403               SplitString( value, line2);
00404               if (!value.IsEmpty())
00405                 pFieldMap->SetFieldValue( m_database, newRow, gMapiFields[i].mozField, value.get());
00406               if (!line2.IsEmpty())
00407                 pFieldMap->SetFieldValue( m_database, newRow, gMapiFields[i].multiLine, line2.get());
00408             }
00409           }
00410         }
00411       }
00412       // call fieldMap SetFieldValue based on the table of fields
00413       
00414       NS_RELEASE( pFieldMap);
00415     }
00416   }
00417   return( PR_TRUE);
00418 }