diff options
Diffstat (limited to 'mailnews/import/oexpress/nsOEAddressIterator.cpp')
-rw-r--r-- | mailnews/import/oexpress/nsOEAddressIterator.cpp | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/mailnews/import/oexpress/nsOEAddressIterator.cpp b/mailnews/import/oexpress/nsOEAddressIterator.cpp new file mode 100644 index 000000000..bc33b45fb --- /dev/null +++ b/mailnews/import/oexpress/nsOEAddressIterator.cpp @@ -0,0 +1,396 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/* + + A sample of XPConnect. This file contains an implementation of + nsISample. + +*/ +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsStringGlue.h" +#include "nsMsgUtils.h" +#include "nsComponentManagerUtils.h" +#include "nsIServiceManager.h" +#include "nsIImportService.h" +#include "nsIImportFieldMap.h" +#include "nsABBaseCID.h" +#include "nsIAbCard.h" +#include "prprf.h" + +#include "nsOEAddressIterator.h" + +#include "OEDebugLog.h" + +typedef struct { + int32_t mozField; + int32_t multiLine; + ULONG mapiTag; +} MAPIFields; + +enum { + ieidPR_DISPLAY_NAME = 0, + ieidPR_ENTRYID, + ieidPR_OBJECT_TYPE, + ieidMax +}; + +/* + Fields in MAPI, not in Mozilla + PR_OFFICE_LOCATION + FIX - PR_BIRTHDAY - stored as PT_SYSTIME - FIX to extract for moz address book birthday + PR_DISPLAY_NAME_PREFIX - Mr., Mrs. Dr., etc. + PR_SPOUSE_NAME + PR_GENDER - integer, not text + FIX - PR_CONTACT_EMAIL_ADDRESSES - multiuline strings for email addresses, needs + parsing to get secondary email address for mozilla +*/ + +#define kIsMultiLine -2 +#define kNoMultiLine -1 + +static MAPIFields gMapiFields[] = { + { 35, kIsMultiLine, PR_COMMENT}, + { 6, kNoMultiLine, PR_BUSINESS_TELEPHONE_NUMBER}, + { 7, kNoMultiLine, PR_HOME_TELEPHONE_NUMBER}, + { 25, kNoMultiLine, PR_COMPANY_NAME}, + { 23, kNoMultiLine, PR_TITLE}, + { 10, kNoMultiLine, PR_CELLULAR_TELEPHONE_NUMBER}, + { 9, kNoMultiLine, PR_PAGER_TELEPHONE_NUMBER}, + { 8, kNoMultiLine, PR_BUSINESS_FAX_NUMBER}, + { 8, kNoMultiLine, PR_HOME_FAX_NUMBER}, + { 22, kNoMultiLine, PR_COUNTRY}, + { 19, kNoMultiLine, PR_LOCALITY}, + { 20, kNoMultiLine, PR_STATE_OR_PROVINCE}, + { 17, 18, PR_STREET_ADDRESS}, + { 21, kNoMultiLine, PR_POSTAL_CODE}, + { 27, kNoMultiLine, PR_PERSONAL_HOME_PAGE}, + { 26, kNoMultiLine, PR_BUSINESS_HOME_PAGE}, + { 13, kNoMultiLine, PR_HOME_ADDRESS_CITY}, + { 16, kNoMultiLine, PR_HOME_ADDRESS_COUNTRY}, + { 15, kNoMultiLine, PR_HOME_ADDRESS_POSTAL_CODE}, + { 14, kNoMultiLine, PR_HOME_ADDRESS_STATE_OR_PROVINCE}, + { 11, 12, PR_HOME_ADDRESS_STREET}, + { 24, kNoMultiLine, PR_DEPARTMENT_NAME} +}; + +nsOEAddressIterator::nsOEAddressIterator(CWAB *pWab, nsIAddrDatabase *database) +{ + m_pWab = pWab; + m_database = database; +} + +nsOEAddressIterator::~nsOEAddressIterator() +{ +} + +nsresult nsOEAddressIterator::EnumUser(const char16_t * pName, LPENTRYID pEid, ULONG cbEid) +{ + IMPORT_LOG1("User: %S\n", pName); + nsresult rv = NS_OK; + + if (m_database) { + LPMAILUSER pUser = m_pWab->GetUser(cbEid, pEid); + if (pUser) { + // Get a new row from the database! + nsCOMPtr <nsIMdbRow> newRow; + rv = m_database->GetNewRow(getter_AddRefs(newRow)); + NS_ENSURE_SUCCESS(rv, rv); + if (newRow && BuildCard(pName, newRow, pUser)) + { + rv = m_database->AddCardRowToDB(newRow); + NS_ENSURE_SUCCESS(rv, rv); + IMPORT_LOG0("* Added entry to address book database\n"); + nsString eMail; + + LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS); + if (pProp) + { + m_pWab->GetValueString(pProp, eMail); + SanitizeValue(eMail); + m_pWab->FreeProperty(pProp); + m_listRows.Put(eMail, newRow); + } + } + m_pWab->ReleaseUser(pUser); + } + } + + return rv; +} + +void nsOEAddressIterator::FindListRow(nsString &eMail, nsIMdbRow **cardRow) +{ + m_listRows.Get(eMail,cardRow); +} + +nsresult nsOEAddressIterator::EnumList(const char16_t * pName, LPENTRYID pEid, ULONG cbEid, LPMAPITABLE lpTable) +{ + // If no name provided then we're done. + if (!pName || !(*pName)) + return NS_OK; + + nsresult rv = NS_ERROR_FAILURE; + HRESULT hr = E_FAIL; + // Make sure we have db to work with. + if (!m_database) + return rv; + + nsCOMPtr <nsIMdbRow> listRow; + rv = m_database->GetNewListRow(getter_AddRefs(listRow)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = m_database->AddListName(listRow, NS_ConvertUTF16toUTF8(pName).get()); + NS_ENSURE_SUCCESS(rv, rv); + rv = m_database->AddCardRowToDB(listRow); + NS_ENSURE_SUCCESS(rv, rv); + rv = m_database->AddListDirNode(listRow); + NS_ENSURE_SUCCESS(rv, rv); + + LPSRowSet lpRowAB = NULL; + ULONG lpcbEID = 0; + LPENTRYID lpEID = NULL; + ULONG rowCount = 0; + int cNumRows = 0; + int numListElems = 0; + nsAutoString uniStr; + + hr = lpTable->GetRowCount(0, &rowCount); + // + hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL); + + if(HR_FAILED(hr)) + return NS_ERROR_FAILURE; + + // Read all the rows of the table one by one + do + { + hr = lpTable->QueryRows(1, 0, &lpRowAB); + + if(HR_FAILED(hr)) + break; + + if(lpRowAB) + { + cNumRows = lpRowAB->cRows; + if (cNumRows) + { + LPTSTR lpsz = lpRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA; + LPENTRYID lpEID = (LPENTRYID) lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb; + ULONG cbEID = lpRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb; + + // There are 2 kinds of objects - the MAPI_MAILUSER contact object + // and the MAPI_DISTLIST contact object + // For distribution lists, we will only consider MAILUSER + // objects since we can't nest lists yet. + if(lpRowAB->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) + { + LPMAILUSER pUser = m_pWab->GetUser(cbEID, lpEID); + LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS); + nsString eMail; + + nsCOMPtr <nsIMdbRow> cardRow; + + m_pWab->GetValueString(pProp, eMail); + SanitizeValue(eMail); + FindListRow(eMail, getter_AddRefs(cardRow)); + if (cardRow) + { + nsCOMPtr <nsIAbCard> userCard; + nsCOMPtr <nsIAbCard> newCard; + userCard = do_CreateInstance(NS_ABMDBCARD_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + m_database->InitCardFromRow(userCard,cardRow); + + m_database->AddListCardColumnsToRow(userCard, listRow, ++numListElems, + getter_AddRefs(newCard), + true, nullptr, nullptr); + } + m_pWab->FreeProperty(pProp); + m_pWab->ReleaseUser(pUser); + } + } + m_pWab->FreeProws(lpRowAB); + } + } while (SUCCEEDED(hr) && cNumRows && lpRowAB); + + m_database->SetListAddressTotal(listRow, numListElems); + return rv; +} + +void nsOEAddressIterator::SanitizeValue(nsString& val) +{ + MsgReplaceSubstring(val, NS_LITERAL_STRING("\r\n"), NS_LITERAL_STRING(", ")); + MsgReplaceChar(val, "\r\n", ','); +} + +void nsOEAddressIterator::SplitString(nsString& val1, nsString& val2) +{ + // Find the last line if there is more than one! + int32_t idx = val1.RFind("\x0D\x0A"); + int32_t cnt = 2; + if (idx == -1) { + cnt = 1; + idx = val1.RFindChar(13); + } + if (idx == -1) + idx= val1.RFindChar(10); + if (idx != -1) { + val2 = Substring(val1, idx + cnt); + val1.SetLength(idx); + SanitizeValue(val1); + } +} + +void nsOEAddressIterator::SetBirthDay(nsIMdbRow *newRow, PRTime& birthDay) +{ + PRExplodedTime exploded; + PR_ExplodeTime(birthDay, PR_LocalTimeParameters, &exploded); + + char stringValue[5]; + PR_snprintf(stringValue, sizeof(stringValue), "%04d", exploded.tm_year); + m_database->AddBirthYear(newRow, stringValue); + PR_snprintf(stringValue, sizeof(stringValue), "%02d", exploded.tm_month + 1); + m_database->AddBirthMonth(newRow, stringValue); + PR_snprintf(stringValue, sizeof(stringValue), "%02d", exploded.tm_mday); + m_database->AddBirthDay(newRow, stringValue); +} + +bool nsOEAddressIterator::BuildCard(const char16_t * pName, nsIMdbRow *newRow, LPMAILUSER pUser) +{ + + nsString lastName; + nsString firstName; + nsString eMail; + nsString nickName; + nsString middleName; + PRTime birthDay = 0; + + LPSPropValue pProp = m_pWab->GetUserProperty(pUser, PR_EMAIL_ADDRESS); + if (pProp) { + m_pWab->GetValueString(pProp, eMail); + SanitizeValue(eMail); + m_pWab->FreeProperty(pProp); + } + pProp = m_pWab->GetUserProperty(pUser, PR_GIVEN_NAME); + if (pProp) { + m_pWab->GetValueString(pProp, firstName); + SanitizeValue(firstName); + m_pWab->FreeProperty(pProp); + } + pProp = m_pWab->GetUserProperty(pUser, PR_SURNAME); + if (pProp) { + m_pWab->GetValueString(pProp, lastName); + SanitizeValue(lastName); + m_pWab->FreeProperty(pProp); + } + pProp = m_pWab->GetUserProperty(pUser, PR_MIDDLE_NAME); + if (pProp) { + m_pWab->GetValueString(pProp, middleName); + SanitizeValue(middleName); + m_pWab->FreeProperty(pProp); + } + pProp = m_pWab->GetUserProperty(pUser, PR_NICKNAME); + if (pProp) { + m_pWab->GetValueString(pProp, nickName); + SanitizeValue(nickName); + m_pWab->FreeProperty(pProp); + } + + // The idea here is that firstName and lastName cannot both be empty! + if (firstName.IsEmpty() && lastName.IsEmpty()) + firstName = pName; + + nsString displayName; + pProp = m_pWab->GetUserProperty(pUser, PR_DISPLAY_NAME); + if (pProp) { + m_pWab->GetValueString(pProp, displayName); + SanitizeValue(displayName); + m_pWab->FreeProperty(pProp); + } + if (displayName.IsEmpty()) { + if (firstName.IsEmpty()) + displayName = pName; + else { + displayName = firstName; + if (!middleName.IsEmpty()) { + displayName.Append(char16_t(' ')); + displayName.Append(middleName); + } + if (!lastName.IsEmpty()) { + displayName.Append(char16_t(' ')); + displayName.Append(lastName); + } + } + } + + pProp = m_pWab->GetUserProperty(pUser, PR_BIRTHDAY); + if (pProp) { + m_pWab->GetValueTime(pProp, birthDay); + m_pWab->FreeProperty(pProp); + } + + // We now have the required fields + // write them out followed by any optional fields! + if (!displayName.IsEmpty()) + m_database->AddDisplayName(newRow, NS_ConvertUTF16toUTF8(displayName).get()); + if (!firstName.IsEmpty()) + m_database->AddFirstName(newRow, NS_ConvertUTF16toUTF8(firstName).get()); + if (!lastName.IsEmpty()) + m_database->AddLastName(newRow, NS_ConvertUTF16toUTF8(lastName).get()); + if (!nickName.IsEmpty()) + m_database->AddNickName(newRow, NS_ConvertUTF16toUTF8(nickName).get()); + if (!eMail.IsEmpty()) + m_database->AddPrimaryEmail(newRow, NS_ConvertUTF16toUTF8(eMail).get()); + + if (birthDay) + SetBirthDay(newRow, birthDay); + + // Do all of the extra fields! + + nsString value; + nsString line2; + nsresult rv; + // Create a field map + + nsCOMPtr<nsIImportService> impSvc(do_GetService(NS_IMPORTSERVICE_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv)) { + nsIImportFieldMap * pFieldMap = nullptr; + rv = impSvc->CreateNewFieldMap(&pFieldMap); + if (NS_SUCCEEDED(rv) && pFieldMap) { + int max = sizeof(gMapiFields) / sizeof(MAPIFields); + for (int i = 0; i < max; i++) { + pProp = m_pWab->GetUserProperty(pUser, gMapiFields[i].mapiTag); + if (pProp) { + m_pWab->GetValueString(pProp, value); + m_pWab->FreeProperty(pProp); + if (!value.IsEmpty()) { + if (gMapiFields[i].multiLine == kNoMultiLine) { + SanitizeValue(value); + pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get()); + } + else if (gMapiFields[i].multiLine == kIsMultiLine) { + pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get()); + } + else { + line2.Truncate(); + SplitString(value, line2); + if (!value.IsEmpty()) + pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].mozField, value.get()); + if (!line2.IsEmpty()) + pFieldMap->SetFieldValue(m_database, newRow, gMapiFields[i].multiLine, line2.get()); + } + } + } + } + // call fieldMap SetFieldValue based on the table of fields + + NS_RELEASE(pFieldMap); + } + } + return true; +} |