summaryrefslogtreecommitdiff
path: root/mailnews/addrbook/src/nsAbCardProperty.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/addrbook/src/nsAbCardProperty.cpp')
-rw-r--r--mailnews/addrbook/src/nsAbCardProperty.cpp1193
1 files changed, 1193 insertions, 0 deletions
diff --git a/mailnews/addrbook/src/nsAbCardProperty.cpp b/mailnews/addrbook/src/nsAbCardProperty.cpp
new file mode 100644
index 0000000000..2c40a40343
--- /dev/null
+++ b/mailnews/addrbook/src/nsAbCardProperty.cpp
@@ -0,0 +1,1193 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "nsAbCardProperty.h"
+#include "nsAbBaseCID.h"
+#include "nsIPrefService.h"
+#include "nsIAddrDatabase.h"
+#include "plbase64.h"
+#include "nsIStringBundle.h"
+#include "plstr.h"
+#include "nsMsgUtils.h"
+#include "nsINetUtil.h"
+#include "nsComponentManagerUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsMemory.h"
+#include "nsVCardObj.h"
+#include "nsIMutableArray.h"
+#include "nsArrayUtils.h"
+#include "mozITXTToHTMLConv.h"
+#include "nsIAbManager.h"
+
+#include "nsVariant.h"
+#include "nsIProperty.h"
+#include "nsCOMArray.h"
+#include "nsArrayEnumerator.h"
+#include "prmem.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Services.h"
+using namespace mozilla;
+
+#define PREF_MAIL_ADDR_BOOK_LASTNAMEFIRST "mail.addr_book.lastnamefirst"
+
+const char sAddrbookProperties[] = "chrome://messenger/locale/addressbook/addressBook.properties";
+
+enum EAppendType {
+ eAppendLine,
+ eAppendLabel,
+ eAppendCityStateZip
+};
+
+struct AppendItem {
+ const char *mColumn;
+ const char* mLabel;
+ EAppendType mAppendType;
+};
+
+static const AppendItem NAME_ATTRS_ARRAY[] = {
+ {kDisplayNameProperty, "propertyDisplayName", eAppendLabel},
+ {kNicknameProperty, "propertyNickname", eAppendLabel},
+ {kPriEmailProperty, "", eAppendLine},
+#ifndef MOZ_THUNDERBIRD
+ {k2ndEmailProperty, "", eAppendLine},
+ {kScreenNameProperty, "propertyScreenName", eAppendLabel}
+#else
+ {k2ndEmailProperty, "", eAppendLine}
+#endif
+};
+
+static const AppendItem PHONE_ATTRS_ARRAY[] = {
+ {kWorkPhoneProperty, "propertyWork", eAppendLabel},
+ {kHomePhoneProperty, "propertyHome", eAppendLabel},
+ {kFaxProperty, "propertyFax", eAppendLabel},
+ {kPagerProperty, "propertyPager", eAppendLabel},
+ {kCellularProperty, "propertyCellular", eAppendLabel}
+};
+
+static const AppendItem HOME_ATTRS_ARRAY[] = {
+ {kHomeAddressProperty, "", eAppendLine},
+ {kHomeAddress2Property, "", eAppendLine},
+ {kHomeCityProperty, "", eAppendCityStateZip},
+ {kHomeCountryProperty, "", eAppendLine},
+ {kHomeWebPageProperty, "", eAppendLine}
+};
+
+static const AppendItem WORK_ATTRS_ARRAY[] = {
+ {kJobTitleProperty, "", eAppendLine},
+ {kDepartmentProperty, "", eAppendLine},
+ {kCompanyProperty, "", eAppendLine},
+ {kWorkAddressProperty, "", eAppendLine},
+ {kWorkAddress2Property, "", eAppendLine},
+ {kWorkCityProperty, "", eAppendCityStateZip},
+ {kWorkCountryProperty, "", eAppendLine},
+ {kWorkWebPageProperty, "", eAppendLine}
+};
+
+static const AppendItem CUSTOM_ATTRS_ARRAY[] = {
+ {kCustom1Property, "propertyCustom1", eAppendLabel},
+ {kCustom2Property, "propertyCustom2", eAppendLabel},
+ {kCustom3Property, "propertyCustom3", eAppendLabel},
+ {kCustom4Property, "propertyCustom4", eAppendLabel},
+ {kNotesProperty, "", eAppendLine}
+};
+
+#ifdef MOZ_THUNDERBIRD
+
+static const AppendItem CHAT_ATTRS_ARRAY[] = {
+ {kGtalkProperty, "propertyGtalk", eAppendLabel},
+ {kAIMProperty, "propertyAIM", eAppendLabel},
+ {kYahooProperty, "propertyYahoo", eAppendLabel},
+ {kSkypeProperty, "propertySkype", eAppendLabel},
+ {kQQProperty, "propertyQQ", eAppendLabel},
+ {kMSNProperty, "propertyMSN", eAppendLabel},
+ {kICQProperty, "propertyICQ", eAppendLabel},
+ {kXMPPProperty, "propertyXMPP", eAppendLabel},
+ {kIRCProperty, "propertyIRC", eAppendLabel}
+};
+#endif
+
+nsAbCardProperty::nsAbCardProperty()
+ : m_IsMailList(false)
+{
+ // Initialize some default properties
+ SetPropertyAsUint32(kPreferMailFormatProperty, nsIAbPreferMailFormat::unknown);
+ SetPropertyAsUint32(kPopularityIndexProperty, 0);
+ // Uninitialized...
+ SetPropertyAsUint32(kLastModifiedDateProperty, 0);
+}
+
+nsAbCardProperty::~nsAbCardProperty(void)
+{
+}
+
+NS_IMPL_ISUPPORTS(nsAbCardProperty, nsIAbCard, nsIAbItem)
+
+NS_IMETHODIMP nsAbCardProperty::GetUuid(nsACString &uuid)
+{
+ // If we have indeterminate sub-ids, return an empty uuid.
+ if (m_directoryId.Equals("") || m_localId.Equals(""))
+ {
+ uuid.Truncate();
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> manager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return manager->GenerateUUID(m_directoryId, m_localId, uuid);
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetDirectoryId(nsACString &dirId)
+{
+ dirId = m_directoryId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetDirectoryId(const nsACString &aDirId)
+{
+ m_directoryId = aDirId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetLocalId(nsACString &localId)
+{
+ localId = m_localId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetLocalId(const nsACString &aLocalId)
+{
+ m_localId = aLocalId;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP nsAbCardProperty::GetIsMailList(bool *aIsMailList)
+{
+ *aIsMailList = m_IsMailList;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetIsMailList(bool aIsMailList)
+{
+ m_IsMailList = aIsMailList;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetMailListURI(char **aMailListURI)
+{
+ if (aMailListURI)
+ {
+ *aMailListURI = ToNewCString(m_MailListURI);
+ return (*aMailListURI) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ else
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetMailListURI(const char *aMailListURI)
+{
+ if (aMailListURI)
+ {
+ m_MailListURI = aMailListURI;
+ return NS_OK;
+ }
+ else
+ return NS_ERROR_NULL_POINTER;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Property bag portion of nsAbCardProperty
+///////////////////////////////////////////////////////////////////////////////
+
+class nsAbSimpleProperty final : public nsIProperty {
+public:
+ nsAbSimpleProperty(const nsACString& aName, nsIVariant* aValue)
+ : mName(aName), mValue(aValue)
+ {
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROPERTY
+protected:
+ ~nsAbSimpleProperty() {}
+ nsCString mName;
+ nsCOMPtr<nsIVariant> mValue;
+};
+
+NS_IMPL_ISUPPORTS(nsAbSimpleProperty, nsIProperty)
+
+NS_IMETHODIMP
+nsAbSimpleProperty::GetName(nsAString& aName)
+{
+ aName.Assign(NS_ConvertUTF8toUTF16(mName));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbSimpleProperty::GetValue(nsIVariant* *aValue)
+{
+ NS_IF_ADDREF(*aValue = mValue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetProperties(nsISimpleEnumerator **props)
+{
+ nsCOMArray<nsIProperty> propertyArray(m_properties.Count());
+ for (auto iter = m_properties.Iter(); !iter.Done(); iter.Next()) {
+ propertyArray.AppendObject(new nsAbSimpleProperty(iter.Key(),
+ iter.UserData()));
+ }
+ return NS_NewArrayEnumerator(props, propertyArray);
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetProperty(const nsACString &name,
+ nsIVariant *defaultValue,
+ nsIVariant **value)
+{
+ if (!m_properties.Get(name, value))
+ NS_ADDREF(*value = defaultValue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetPropertyAsAString(const char *name, nsAString &value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIVariant> variant;
+ return m_properties.Get(nsDependentCString(name), getter_AddRefs(variant)) ?
+ variant->GetAsAString(value) : NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetPropertyAsAUTF8String(const char *name, nsACString &value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIVariant> variant;
+ return m_properties.Get(nsDependentCString(name), getter_AddRefs(variant)) ?
+ variant->GetAsAUTF8String(value) : NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetPropertyAsUint32(const char *name, uint32_t *value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIVariant> variant;
+ return m_properties.Get(nsDependentCString(name), getter_AddRefs(variant)) ?
+ variant->GetAsUint32(value) : NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetPropertyAsBool(const char *name, bool *value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIVariant> variant;
+ return m_properties.Get(nsDependentCString(name), getter_AddRefs(variant)) ?
+ variant->GetAsBool(value) : NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetProperty(const nsACString &name, nsIVariant *value)
+{
+ m_properties.Put(name, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetPropertyAsAString(const char *name, const nsAString &value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
+ variant->SetAsAString(value);
+ m_properties.Put(nsDependentCString(name), variant);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetPropertyAsAUTF8String(const char *name, const nsACString &value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
+ variant->SetAsAUTF8String(value);
+ m_properties.Put(nsDependentCString(name), variant);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetPropertyAsUint32(const char *name, uint32_t value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
+ variant->SetAsUint32(value);
+ m_properties.Put(nsDependentCString(name), variant);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetPropertyAsBool(const char *name, bool value)
+{
+ NS_ENSURE_ARG_POINTER(name);
+
+ nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
+ variant->SetAsBool(value);
+ m_properties.Put(nsDependentCString(name), variant);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::DeleteProperty(const nsACString &name)
+{
+ m_properties.Remove(name);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetFirstName(nsAString &aString)
+{
+ nsresult rv = GetPropertyAsAString(kFirstNameProperty, aString);
+ if (rv == NS_ERROR_NOT_AVAILABLE)
+ {
+ aString.Truncate();
+ return NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetFirstName(const nsAString &aString)
+{
+ return SetPropertyAsAString(kFirstNameProperty, aString);
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetLastName(nsAString &aString)
+{
+ nsresult rv = GetPropertyAsAString(kLastNameProperty, aString);
+ if (rv == NS_ERROR_NOT_AVAILABLE)
+ {
+ aString.Truncate();
+ return NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetLastName(const nsAString &aString)
+{
+ return SetPropertyAsAString(kLastNameProperty, aString);
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetDisplayName(nsAString &aString)
+{
+ nsresult rv = GetPropertyAsAString(kDisplayNameProperty, aString);
+ if (rv == NS_ERROR_NOT_AVAILABLE)
+ {
+ aString.Truncate();
+ return NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetDisplayName(const nsAString &aString)
+{
+ return SetPropertyAsAString(kDisplayNameProperty, aString);
+}
+
+NS_IMETHODIMP nsAbCardProperty::GetPrimaryEmail(nsAString &aString)
+{
+ nsresult rv = GetPropertyAsAString(kPriEmailProperty, aString);
+ if (rv == NS_ERROR_NOT_AVAILABLE)
+ {
+ aString.Truncate();
+ return NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsAbCardProperty::SetPrimaryEmail(const nsAString &aString)
+{
+ return SetPropertyAsAString(kPriEmailProperty, aString);
+}
+
+NS_IMETHODIMP nsAbCardProperty::HasEmailAddress(const nsACString &aEmailAddress,
+ bool *aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = false;
+
+ nsCString emailAddress;
+ nsresult rv = GetPropertyAsAUTF8String(kPriEmailProperty, emailAddress);
+ if (rv != NS_ERROR_NOT_AVAILABLE &&
+ emailAddress.Equals(aEmailAddress, nsCaseInsensitiveCStringComparator()))
+ {
+ *aResult = true;
+ return NS_OK;
+ }
+
+ rv = GetPropertyAsAUTF8String(k2ndEmailProperty, emailAddress);
+ if (rv != NS_ERROR_NOT_AVAILABLE &&
+ emailAddress.Equals(aEmailAddress, nsCaseInsensitiveCStringComparator()))
+ *aResult = true;
+
+ return NS_OK;
+}
+
+// This function may be overridden by derived classes for
+// nsAb*Card specific implementations.
+NS_IMETHODIMP nsAbCardProperty::Copy(nsIAbCard* srcCard)
+{
+ NS_ENSURE_ARG_POINTER(srcCard);
+
+ nsCOMPtr<nsISimpleEnumerator> properties;
+ nsresult rv = srcCard->GetProperties(getter_AddRefs(properties));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool hasMore;
+ nsCOMPtr<nsISupports> result;
+ while (NS_SUCCEEDED(rv = properties->HasMoreElements(&hasMore)) && hasMore)
+ {
+ rv = properties->GetNext(getter_AddRefs(result));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIProperty> property = do_QueryInterface(result, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString name;
+ property->GetName(name);
+ nsCOMPtr<nsIVariant> value;
+ property->GetValue(getter_AddRefs(value));
+
+ SetProperty(NS_ConvertUTF16toUTF8(name), value);
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isMailList;
+ srcCard->GetIsMailList(&isMailList);
+ SetIsMailList(isMailList);
+
+ nsCString mailListURI;
+ srcCard->GetMailListURI(getter_Copies(mailListURI));
+ SetMailListURI(mailListURI.get());
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::Equals(nsIAbCard *card, bool *result)
+{
+ *result = (card == this);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// The following methods are other views of a card
+////////////////////////////////////////////////////////////////////////////////
+
+// XXX: Use the category manager instead of this file to implement these
+NS_IMETHODIMP nsAbCardProperty::TranslateTo(const nsACString &type, nsACString &result)
+{
+ if (type.EqualsLiteral("base64xml"))
+ return ConvertToBase64EncodedXML(result);
+ else if (type.EqualsLiteral("xml"))
+ {
+ nsString utf16String;
+ nsresult rv = ConvertToXMLPrintData(utf16String);
+ NS_ENSURE_SUCCESS(rv, rv);
+ result = NS_ConvertUTF16toUTF8(utf16String);
+ return NS_OK;
+ }
+ else if (type.EqualsLiteral("vcard"))
+ return ConvertToEscapedVCard(result);
+
+ return NS_ERROR_ILLEGAL_VALUE;
+}
+//
+static VObject* myAddPropValue(VObject *o, const char *propName, const char16_t *propValue, bool *aCardHasData)
+{
+ if (aCardHasData)
+ *aCardHasData = true;
+ return addPropValue(o, propName, NS_ConvertUTF16toUTF8(propValue).get());
+}
+
+nsresult nsAbCardProperty::ConvertToEscapedVCard(nsACString &aResult)
+{
+ nsString str;
+ nsresult rv;
+ bool vCardHasData = false;
+ VObject* vObj = newVObject(VCCardProp);
+ VObject* t;
+
+ // [comment from 4.x]
+ // Big flame coming....so Vobject is not designed at all to work with an array of
+ // attribute values. It wants you to have all of the attributes easily available. You
+ // cannot add one attribute at a time as you find them to the vobject. Why? Because
+ // it creates a property for a particular type like phone number and then that property
+ // has multiple values. This implementation is not pretty. I can hear my algos prof
+ // yelling from here.....I have to do a linear search through my attributes array for
+ // EACH vcard property we want to set. *sigh* One day I will have time to come back
+ // to this function and remedy this O(m*n) function where n = # attribute values and
+ // m = # of vcard properties....
+
+ (void)GetDisplayName(str);
+ if (!str.IsEmpty()) {
+ myAddPropValue(vObj, VCFullNameProp, str.get(), &vCardHasData);
+ }
+
+ (void)GetLastName(str);
+ if (!str.IsEmpty()) {
+ t = isAPropertyOf(vObj, VCNameProp);
+ if (!t)
+ t = addProp(vObj, VCNameProp);
+ myAddPropValue(t, VCFamilyNameProp, str.get(), &vCardHasData);
+ }
+
+ (void)GetFirstName(str);
+ if (!str.IsEmpty()) {
+ t = isAPropertyOf(vObj, VCNameProp);
+ if (!t)
+ t = addProp(vObj, VCNameProp);
+ myAddPropValue(t, VCGivenNameProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kCompanyProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCOrgProp);
+ if (!t)
+ t = addProp(vObj, VCOrgProp);
+ myAddPropValue(t, VCOrgNameProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kDepartmentProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCOrgProp);
+ if (!t)
+ t = addProp(vObj, VCOrgProp);
+ myAddPropValue(t, VCOrgUnitProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkAddress2Property, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCPostalBoxProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkAddressProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCStreetAddressProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkCityProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCCityProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkStateProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCRegionProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkZipCodeProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCPostalCodeProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkCountryProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (!t)
+ t = addProp(vObj, VCAdrProp);
+ myAddPropValue(t, VCCountryNameProp, str.get(), &vCardHasData);
+ }
+ else
+ {
+ // only add this if VCAdrProp already exists
+ t = isAPropertyOf(vObj, VCAdrProp);
+ if (t)
+ {
+ addProp(t, VCDomesticProp);
+ }
+ }
+
+ (void)GetPrimaryEmail(str);
+ if (!str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCEmailAddressProp, str.get(), &vCardHasData);
+ addProp(t, VCInternetProp);
+ }
+
+ rv = GetPropertyAsAString(kJobTitleProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ myAddPropValue(vObj, VCTitleProp, str.get(), &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkPhoneProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCTelephoneProp, str.get(), &vCardHasData);
+ addProp(t, VCWorkProp);
+ }
+
+ rv = GetPropertyAsAString(kFaxProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCTelephoneProp, str.get(), &vCardHasData);
+ addProp(t, VCFaxProp);
+ }
+
+ rv = GetPropertyAsAString(kPagerProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCTelephoneProp, str.get(), &vCardHasData);
+ addProp(t, VCPagerProp);
+ }
+
+ rv = GetPropertyAsAString(kHomePhoneProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCTelephoneProp, str.get(), &vCardHasData);
+ addProp(t, VCHomeProp);
+ }
+
+ rv = GetPropertyAsAString(kCellularProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ t = myAddPropValue(vObj, VCTelephoneProp, str.get(), &vCardHasData);
+ addProp(t, VCCellularProp);
+ }
+
+ rv = GetPropertyAsAString(kNotesProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ myAddPropValue(vObj, VCNoteProp, str.get(), &vCardHasData);
+ }
+
+ uint32_t format;
+ rv = GetPropertyAsUint32(kPreferMailFormatProperty, &format);
+ if (NS_SUCCEEDED(rv) && format == nsIAbPreferMailFormat::html) {
+ myAddPropValue(vObj, VCUseHTML, u"TRUE", &vCardHasData);
+ }
+ else if (NS_SUCCEEDED(rv) && format == nsIAbPreferMailFormat::plaintext) {
+ myAddPropValue(vObj, VCUseHTML, u"FALSE", &vCardHasData);
+ }
+
+ rv = GetPropertyAsAString(kWorkWebPageProperty, str);
+ if (NS_SUCCEEDED(rv) && !str.IsEmpty())
+ {
+ myAddPropValue(vObj, VCURLProp, str.get(), &vCardHasData);
+ }
+
+ myAddPropValue(vObj, VCVersionProp, u"2.1", nullptr);
+
+ if (!vCardHasData) {
+ aResult.Truncate();
+ cleanVObject(vObj);
+ return NS_OK;
+ }
+
+ int len = 0;
+ char *vCard = writeMemVObject(0, &len, vObj);
+ if (vObj)
+ cleanVObject(vObj);
+
+ nsCString escResult;
+ MsgEscapeString(nsDependentCString(vCard), nsINetUtil::ESCAPE_URL_PATH, escResult);
+ aResult = escResult;
+ return NS_OK;
+}
+
+nsresult nsAbCardProperty::ConvertToBase64EncodedXML(nsACString &result)
+{
+ nsresult rv;
+ nsString xmlStr;
+
+ xmlStr.AppendLiteral("<?xml version=\"1.0\"?>\n"
+ "<?xml-stylesheet type=\"text/css\" href=\"chrome://messagebody/content/addressbook/print.css\"?>\n"
+ "<directory>\n");
+
+ // Get Address Book string and set it as title of XML document
+ nsCOMPtr<nsIStringBundle> bundle;
+ nsCOMPtr<nsIStringBundleService> stringBundleService =
+ mozilla::services::GetStringBundleService();
+ if (stringBundleService) {
+ rv = stringBundleService->CreateBundle(sAddrbookProperties, getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv)) {
+ nsString addrBook;
+ rv = bundle->GetStringFromName(u"addressBook", getter_Copies(addrBook));
+ if (NS_SUCCEEDED(rv)) {
+ xmlStr.AppendLiteral("<title xmlns=\"http://www.w3.org/1999/xhtml\">");
+ xmlStr.Append(addrBook);
+ xmlStr.AppendLiteral("</title>\n");
+ }
+ }
+ }
+
+ nsString xmlSubstr;
+ rv = ConvertToXMLPrintData(xmlSubstr);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ xmlStr.Append(xmlSubstr);
+ xmlStr.AppendLiteral("</directory>\n");
+
+ char *tmpRes = PL_Base64Encode(NS_ConvertUTF16toUTF8(xmlStr).get(), 0, nullptr);
+ result.Assign(tmpRes);
+ PR_Free(tmpRes);
+ return NS_OK;
+}
+
+nsresult nsAbCardProperty::ConvertToXMLPrintData(nsAString &aXMLSubstr)
+{
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ int32_t generatedNameFormat;
+ rv = prefBranch->GetIntPref(PREF_MAIL_ADDR_BOOK_LASTNAMEFIRST, &generatedNameFormat);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIStringBundleService> stringBundleService =
+ mozilla::services::GetStringBundleService();
+ NS_ENSURE_TRUE(stringBundleService, NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ rv = stringBundleService->CreateBundle(sAddrbookProperties, getter_AddRefs(bundle));
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsString generatedName;
+ rv = GenerateName(generatedNameFormat, bundle, generatedName);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsCOMPtr<mozITXTToHTMLConv> conv = do_CreateInstance(MOZ_TXTTOHTMLCONV_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsString xmlStr;
+ xmlStr.SetLength(4096); // to reduce allocations. should be enough for most cards
+ xmlStr.AssignLiteral("<GeneratedName>\n");
+
+ // use ScanTXT to convert < > & to safe values.
+ nsString safeText;
+ if (!generatedName.IsEmpty()) {
+ rv = conv->ScanTXT(generatedName.get(), mozITXTToHTMLConv::kEntities,
+ getter_Copies(safeText));
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+
+ if (safeText.IsEmpty()) {
+ nsAutoString primaryEmail;
+ GetPrimaryEmail(primaryEmail);
+
+ // use ScanTXT to convert < > & to safe values.
+ rv = conv->ScanTXT(primaryEmail.get(), mozITXTToHTMLConv::kEntities,
+ getter_Copies(safeText));
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ xmlStr.Append(safeText);
+
+ xmlStr.AppendLiteral("</GeneratedName>\n"
+ "<table><tr><td>");
+
+ rv = AppendSection(NAME_ATTRS_ARRAY, sizeof(NAME_ATTRS_ARRAY)/sizeof(AppendItem), EmptyString(), bundle, conv, xmlStr);
+
+ xmlStr.AppendLiteral("</td></tr><tr><td>");
+
+ rv = AppendSection(PHONE_ATTRS_ARRAY, sizeof(PHONE_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingPhone"), bundle, conv, xmlStr);
+
+ if (!m_IsMailList) {
+ rv = AppendSection(CUSTOM_ATTRS_ARRAY, sizeof(CUSTOM_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingOther"), bundle, conv, xmlStr);
+#ifdef MOZ_THUNDERBIRD
+ rv = AppendSection(CHAT_ATTRS_ARRAY, sizeof(CHAT_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingChat"), bundle, conv, xmlStr);
+#endif
+ }
+ else {
+ rv = AppendSection(CUSTOM_ATTRS_ARRAY, sizeof(CUSTOM_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingDescription"),
+ bundle, conv, xmlStr);
+
+ xmlStr.AppendLiteral("<section><sectiontitle>");
+
+ nsString headingAddresses;
+ rv = bundle->GetStringFromName(u"headingAddresses", getter_Copies(headingAddresses));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ xmlStr.Append(headingAddresses);
+ xmlStr.AppendLiteral("</sectiontitle>");
+
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr <nsIAbDirectory> mailList = nullptr;
+ rv = abManager->GetDirectory(m_MailListURI, getter_AddRefs(mailList));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMutableArray> addresses;
+ rv = mailList->GetAddressLists(getter_AddRefs(addresses));
+ if (addresses) {
+ uint32_t total = 0;
+ addresses->GetLength(&total);
+ if (total) {
+ uint32_t i;
+ nsAutoString displayName;
+ nsAutoString primaryEmail;
+ for (i = 0; i < total; i++) {
+ nsCOMPtr <nsIAbCard> listCard = do_QueryElementAt(addresses, i, &rv);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ xmlStr.AppendLiteral("<PrimaryEmail>\n");
+
+ rv = listCard->GetDisplayName(displayName);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ // use ScanTXT to convert < > & to safe values.
+ nsString safeText;
+ rv = conv->ScanTXT(displayName.get(), mozITXTToHTMLConv::kEntities,
+ getter_Copies(safeText));
+ NS_ENSURE_SUCCESS(rv,rv);
+ xmlStr.Append(safeText);
+
+ xmlStr.AppendLiteral(" &lt;");
+
+ listCard->GetPrimaryEmail(primaryEmail);
+
+ // use ScanTXT to convert < > & to safe values.
+ rv = conv->ScanTXT(primaryEmail.get(), mozITXTToHTMLConv::kEntities,
+ getter_Copies(safeText));
+ NS_ENSURE_SUCCESS(rv,rv);
+ xmlStr.Append(safeText);
+
+ xmlStr.AppendLiteral("&gt;</PrimaryEmail>\n");
+ }
+ }
+ }
+ xmlStr.AppendLiteral("</section>");
+ }
+
+ xmlStr.AppendLiteral("</td><td>");
+
+ rv = AppendSection(HOME_ATTRS_ARRAY, sizeof(HOME_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingHome"), bundle, conv, xmlStr);
+ rv = AppendSection(WORK_ATTRS_ARRAY, sizeof(WORK_ATTRS_ARRAY)/sizeof(AppendItem), NS_LITERAL_STRING("headingWork"), bundle, conv, xmlStr);
+
+ xmlStr.AppendLiteral("</td></tr></table>");
+
+ aXMLSubstr = xmlStr;
+
+ return NS_OK;
+}
+
+nsresult nsAbCardProperty::AppendSection(const AppendItem *aArray, int16_t aCount, const nsString& aHeading,
+ nsIStringBundle *aBundle,
+ mozITXTToHTMLConv *aConv,
+ nsString &aResult)
+{
+ nsresult rv = NS_OK;
+
+ aResult.AppendLiteral("<section>");
+
+ nsString attrValue;
+ bool sectionIsEmpty = true;
+
+ int16_t i = 0;
+ for (i=0;i<aCount;i++) {
+ rv = GetPropertyAsAString(aArray[i].mColumn, attrValue);
+ if (NS_SUCCEEDED(rv) && !attrValue.IsEmpty())
+ sectionIsEmpty = false;
+ }
+
+ if (!sectionIsEmpty && !aHeading.IsEmpty()) {
+ nsString heading;
+ rv = aBundle->GetStringFromName(aHeading.get(), getter_Copies(heading));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aResult.AppendLiteral("<sectiontitle>");
+ aResult.Append(heading);
+ aResult.AppendLiteral("</sectiontitle>");
+ }
+
+ for (i=0;i<aCount;i++) {
+ switch (aArray[i].mAppendType) {
+ case eAppendLine:
+ rv = AppendLine(aArray[i], aConv, aResult);
+ break;
+ case eAppendLabel:
+ rv = AppendLabel(aArray[i], aBundle, aConv, aResult);
+ break;
+ case eAppendCityStateZip:
+ rv = AppendCityStateZip(aArray[i], aBundle, aConv, aResult);
+ break;
+ default:
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("append item failed");
+ break;
+ }
+ }
+ aResult.AppendLiteral("</section>");
+
+ return rv;
+}
+
+nsresult nsAbCardProperty::AppendLine(const AppendItem &aItem,
+ mozITXTToHTMLConv *aConv,
+ nsString &aResult)
+{
+ NS_ENSURE_ARG_POINTER(aConv);
+
+ nsString attrValue;
+ nsresult rv = GetPropertyAsAString(aItem.mColumn, attrValue);
+
+ if (NS_FAILED(rv) || attrValue.IsEmpty())
+ return NS_OK;
+
+ aResult.Append(char16_t('<'));
+ aResult.Append(NS_ConvertUTF8toUTF16(aItem.mColumn));
+ aResult.Append(char16_t('>'));
+
+ // use ScanTXT to convert < > & to safe values.
+ nsString safeText;
+ rv = aConv->ScanTXT(attrValue.get(), mozITXTToHTMLConv::kEntities, getter_Copies(safeText));
+ NS_ENSURE_SUCCESS(rv,rv);
+ aResult.Append(safeText);
+
+ aResult.AppendLiteral("</");
+ aResult.Append(NS_ConvertUTF8toUTF16(aItem.mColumn));
+ aResult.Append(char16_t('>'));
+
+ return NS_OK;
+}
+
+nsresult nsAbCardProperty::AppendLabel(const AppendItem &aItem,
+ nsIStringBundle *aBundle,
+ mozITXTToHTMLConv *aConv,
+ nsString &aResult)
+{
+ NS_ENSURE_ARG_POINTER(aBundle);
+
+ nsresult rv;
+ nsString label, attrValue;
+
+ rv = GetPropertyAsAString(aItem.mColumn, attrValue);
+
+ if (NS_FAILED(rv) || attrValue.IsEmpty())
+ return NS_OK;
+
+ rv = aBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aItem.mLabel).get(), getter_Copies(label));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aResult.AppendLiteral("<labelrow><label>");
+
+ aResult.Append(label);
+ aResult.AppendLiteral(": </label>");
+
+ rv = AppendLine(aItem, aConv, aResult);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ aResult.AppendLiteral("</labelrow>");
+
+ return NS_OK;
+}
+
+nsresult nsAbCardProperty::AppendCityStateZip(const AppendItem &aItem,
+ nsIStringBundle *aBundle,
+ mozITXTToHTMLConv *aConv,
+ nsString &aResult)
+{
+ NS_ENSURE_ARG_POINTER(aBundle);
+
+ nsresult rv;
+ AppendItem item;
+ const char *statePropName, *zipPropName;
+
+ if (strcmp(aItem.mColumn, kHomeCityProperty) == 0) {
+ statePropName = kHomeStateProperty;
+ zipPropName = kHomeZipCodeProperty;
+ }
+ else {
+ statePropName = kWorkStateProperty;
+ zipPropName = kWorkZipCodeProperty;
+ }
+
+ nsAutoString cityResult, stateResult, zipResult;
+
+ rv = AppendLine(aItem, aConv, cityResult);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ item.mColumn = statePropName;
+ item.mLabel = "";
+
+ rv = AppendLine(item, aConv, stateResult);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ item.mColumn = zipPropName;
+
+ rv = AppendLine(item, aConv, zipResult);
+ NS_ENSURE_SUCCESS(rv,rv);
+
+ nsString formattedString;
+
+ if (!cityResult.IsEmpty() && !stateResult.IsEmpty() && !zipResult.IsEmpty()) {
+ const char16_t *formatStrings[] = { cityResult.get(), stateResult.get(), zipResult.get() };
+ rv = aBundle->FormatStringFromName(u"cityAndStateAndZip", formatStrings, ArrayLength(formatStrings), getter_Copies(formattedString));
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ else if (!cityResult.IsEmpty() && !stateResult.IsEmpty() && zipResult.IsEmpty()) {
+ const char16_t *formatStrings[] = { cityResult.get(), stateResult.get() };
+ rv = aBundle->FormatStringFromName(u"cityAndStateNoZip", formatStrings, ArrayLength(formatStrings), getter_Copies(formattedString));
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ else if ((!cityResult.IsEmpty() && stateResult.IsEmpty() && !zipResult.IsEmpty()) ||
+ (cityResult.IsEmpty() && !stateResult.IsEmpty() && !zipResult.IsEmpty())) {
+ const char16_t *formatStrings[] = { cityResult.IsEmpty() ? stateResult.get() : cityResult.get(), zipResult.get() };
+ rv = aBundle->FormatStringFromName(u"cityOrStateAndZip", formatStrings, ArrayLength(formatStrings), getter_Copies(formattedString));
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ else {
+ if (!cityResult.IsEmpty())
+ formattedString = cityResult;
+ else if (!stateResult.IsEmpty())
+ formattedString = stateResult;
+ else
+ formattedString = zipResult;
+ }
+
+ aResult.Append(formattedString);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GenerateName(int32_t aGenerateFormat,
+ nsIStringBundle* aBundle,
+ nsAString &aResult)
+{
+ aResult.Truncate();
+
+ // Cache the first and last names
+ nsAutoString firstName, lastName;
+ GetFirstName(firstName);
+ GetLastName(lastName);
+
+ // No need to check for aBundle present straight away, only do that if we're
+ // actually going to use it.
+ if (aGenerateFormat == GENERATE_DISPLAY_NAME)
+ GetDisplayName(aResult);
+ else if (lastName.IsEmpty())
+ aResult = firstName;
+ else if (firstName.IsEmpty())
+ aResult = lastName;
+ else {
+ nsresult rv;
+ nsCOMPtr<nsIStringBundle> bundle(aBundle);
+ if (!bundle) {
+ nsCOMPtr<nsIStringBundleService> stringBundleService =
+ mozilla::services::GetStringBundleService();
+ NS_ENSURE_TRUE(stringBundleService, NS_ERROR_UNEXPECTED);
+
+ rv = stringBundleService->CreateBundle(sAddrbookProperties,
+ getter_AddRefs(bundle));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsString result;
+
+ if (aGenerateFormat == GENERATE_LAST_FIRST_ORDER) {
+ const char16_t *stringParams[2] = {lastName.get(), firstName.get()};
+
+ rv = bundle->FormatStringFromName(u"lastFirstFormat",
+ stringParams, 2, getter_Copies(result));
+ }
+ else {
+ const char16_t *stringParams[2] = {firstName.get(), lastName.get()};
+
+ rv = bundle->FormatStringFromName(u"firstLastFormat",
+ stringParams, 2, getter_Copies(result));
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aResult.Assign(result);
+ }
+
+ if (aResult.IsEmpty())
+ {
+ // The normal names have failed, does this card have a company name? If so,
+ // use that instead, because that is likely to be more meaningful than an
+ // email address.
+ //
+ // If this errors, the string isn't found and we'll fall into the next
+ // check.
+ (void) GetPropertyAsAString(kCompanyProperty, aResult);
+ }
+
+ if (aResult.IsEmpty())
+ {
+ // see bug #211078
+ // if there is no generated name at this point
+ // use the userid from the email address
+ // it is better than nothing.
+ GetPrimaryEmail(aResult);
+ int32_t index = aResult.FindChar('@');
+ if (index != -1)
+ aResult.SetLength(index);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GeneratePhoneticName(bool aLastNameFirst,
+ nsAString &aResult)
+{
+ nsAutoString firstName, lastName;
+ GetPropertyAsAString(kPhoneticFirstNameProperty, firstName);
+ GetPropertyAsAString(kPhoneticLastNameProperty, lastName);
+
+ if (aLastNameFirst)
+ {
+ aResult = lastName;
+ aResult += firstName;
+ }
+ else
+ {
+ aResult = firstName;
+ aResult += lastName;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbCardProperty::GenerateChatName(nsAString &aResult)
+{
+ aResult.Truncate();
+
+#define CHECK_CHAT_PROPERTY(aProtocol) \
+ if (NS_SUCCEEDED(GetPropertyAsAString(k##aProtocol##Property, aResult)) && \
+ !aResult.IsEmpty()) \
+ return NS_OK
+ CHECK_CHAT_PROPERTY(Gtalk);
+ CHECK_CHAT_PROPERTY(AIM);
+ CHECK_CHAT_PROPERTY(Yahoo);
+ CHECK_CHAT_PROPERTY(Skype);
+ CHECK_CHAT_PROPERTY(QQ);
+ CHECK_CHAT_PROPERTY(MSN);
+ CHECK_CHAT_PROPERTY(ICQ);
+ CHECK_CHAT_PROPERTY(XMPP);
+ CHECK_CHAT_PROPERTY(IRC);
+ return NS_OK;
+}