summaryrefslogtreecommitdiffstats
path: root/mailnews/import/oexpress/nsOEAddressIterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/import/oexpress/nsOEAddressIterator.cpp')
-rw-r--r--mailnews/import/oexpress/nsOEAddressIterator.cpp396
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;
+}