summaryrefslogtreecommitdiffstats
path: root/mailnews/addrbook/src/nsAbLDAPCard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/addrbook/src/nsAbLDAPCard.cpp')
-rw-r--r--mailnews/addrbook/src/nsAbLDAPCard.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/mailnews/addrbook/src/nsAbLDAPCard.cpp b/mailnews/addrbook/src/nsAbLDAPCard.cpp
new file mode 100644
index 000000000..6dcfdedbb
--- /dev/null
+++ b/mailnews/addrbook/src/nsAbLDAPCard.cpp
@@ -0,0 +1,297 @@
+/* -*- 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 "nsAbLDAPCard.h"
+#include "nsIMutableArray.h"
+#include "nsCOMPtr.h"
+#include "nsILDAPModification.h"
+#include "nsILDAPBERValue.h"
+#include "nsILDAPMessage.h"
+#include "nsIAbLDAPAttributeMap.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsAbBaseCID.h"
+#include "nsAbUtils.h"
+#include "nsILDAPErrors.h"
+
+#include <stdio.h>
+
+#define kDNColumn "DN"
+
+nsAbLDAPCard::nsAbLDAPCard()
+{
+}
+
+nsAbLDAPCard::~nsAbLDAPCard()
+{
+}
+
+NS_IMPL_ISUPPORTS_INHERITED(nsAbLDAPCard, nsAbCardProperty, nsIAbLDAPCard)
+
+/* Retrieves the changes to the LDAP card and stores them in an LDAP
+ * update message.
+ *
+ * Calling this method changes the LDAP card, it updates the
+ * meta-properties (m_*) to reflect what the LDAP contents will be once
+ * the update has been performed. This allows you to do multiple (successful)
+ * consecutive edits on a card in a search result. If the meta-properties
+ * were not updated, incorrect assuptions would be made about what object
+ * classes to add, or what attributes to clear.
+ *
+ * XXX: We need to take care when integrating this code with the asynchronous
+ * update dialogs, as the current code in nsAbLDAPDirectory has a problem
+ * when an update fails: the modified card still gets stored and shown to
+ * the user instead of being discarded. There is one especially tricky case:
+ * when you do an update on a card which changes its DN, you have two
+ * operations (rename, then update the other attributes). If the rename
+ * operation succeeds and not the update of the attributes, you are
+ * "somewhere in between" the original card and the updated card.
+*/
+NS_IMETHODIMP nsAbLDAPCard::GetLDAPMessageInfo(
+ nsIAbLDAPAttributeMap *aAttributeMap,
+ const uint32_t aClassCount,
+ const char **aClasses,
+ int32_t aType,
+ nsIArray **aLDAPAddMessageInfo)
+{
+ NS_ENSURE_ARG_POINTER(aAttributeMap);
+ NS_ENSURE_ARG_POINTER(aClasses);
+ NS_ENSURE_ARG_POINTER(aLDAPAddMessageInfo);
+
+ nsresult rv;
+ nsCOMPtr<nsIMutableArray> modArray =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Add any missing object classes. We never remove any object
+ // classes: if an entry has additional object classes, it's probably
+ // for a good reason.
+ nsAutoCString oclass;
+ for (uint32_t i = 0; i < aClassCount; ++i)
+ {
+ oclass.Assign(nsDependentCString(aClasses[i]));
+ ToLowerCase(oclass);
+
+ if (!m_objectClass.Contains(oclass))
+ {
+ m_objectClass.AppendElement(oclass);
+ printf("LDAP : adding objectClass %s\n", oclass.get());
+ }
+ }
+
+ nsCOMPtr<nsILDAPModification> mod =
+ do_CreateInstance("@mozilla.org/network/ldap-modification;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMutableArray> values =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ for (uint32_t i = 0; i < m_objectClass.Length(); ++i)
+ {
+ nsCOMPtr<nsILDAPBERValue> value =
+ do_CreateInstance("@mozilla.org/network/ldap-ber-value;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = value->SetFromUTF8(m_objectClass.ElementAt(i));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = values->AppendElement(value, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = mod->SetUpModification(aType, NS_LITERAL_CSTRING("objectClass"), values);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ modArray->AppendElement(mod, false);
+
+ // Add card properties
+ CharPtrArrayGuard props;
+ rv = aAttributeMap->GetAllCardProperties(props.GetSizeAddr(),
+ props.GetArrayAddr());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString attr;
+ nsCString propvalue;
+ for (uint32_t i = 0; i < props.GetSize(); ++i)
+ {
+ // Skip some attributes that don't map to LDAP.
+ //
+ // BirthYear : by default this is mapped to 'birthyear',
+ // which is not part of mozillaAbPersonAlpha
+ //
+ // LastModifiedDate : by default this is mapped to 'modifytimestamp',
+ // which cannot be modified
+ //
+ // PreferMailFormat : by default this is mapped to 'mozillaUseHtmlMail',
+ // which is a boolean, not plaintext/html/unknown
+ if (!strcmp(props[i], kBirthYearProperty) ||
+ !strcmp(props[i], kLastModifiedDateProperty) ||
+ !strcmp(props[i], kPreferMailFormatProperty))
+ continue;
+
+ rv = aAttributeMap->GetFirstAttribute(nsDependentCString(props[i]),
+ attr);
+ NS_ENSURE_SUCCESS(rv, rv);
+ ToLowerCase(attr);
+
+ // If the property is not mapped to an attribute, skip it.
+ if (attr.IsEmpty())
+ continue;
+
+ nsCOMPtr<nsILDAPModification> mod =
+ do_CreateInstance("@mozilla.org/network/ldap-modification;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ size_t index = m_attributes.IndexOf(attr);
+
+ rv = GetPropertyAsAUTF8String(props[i], propvalue);
+
+ if (NS_SUCCEEDED(rv) &&!propvalue.IsEmpty())
+ {
+ // If the new value is not empty, add/update it
+ nsCOMPtr<nsILDAPBERValue> value =
+ do_CreateInstance("@mozilla.org/network/ldap-ber-value;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = value->SetFromUTF8(propvalue);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mod->SetUpModificationOneValue(aType, attr, value);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ printf("LDAP : setting attribute %s (%s) to '%s'\n", attr.get(),
+ props[i], propvalue.get());
+ modArray->AppendElement(mod, false);
+ if (index != m_attributes.NoIndex)
+ m_attributes.AppendElement(attr);
+
+ }
+ else if (aType == nsILDAPModification::MOD_REPLACE &&
+ index != m_attributes.NoIndex)
+ {
+ // If the new value is empty, we are performing an update
+ // and the attribute was previously set, clear it
+ nsCOMPtr<nsIMutableArray> novalues =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mod->SetUpModification(aType, attr, novalues);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ printf("LDAP : removing attribute %s (%s)\n", attr.get(), props[i]);
+ modArray->AppendElement(mod, false);
+ m_attributes.RemoveElementAt(index);
+ }
+ }
+
+ NS_ADDREF(*aLDAPAddMessageInfo = modArray);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbLDAPCard::BuildRdn(nsIAbLDAPAttributeMap *aAttributeMap,
+ const uint32_t aAttrCount,
+ const char **aAttributes,
+ nsACString &aRdn)
+{
+ NS_ENSURE_ARG_POINTER(aAttributeMap);
+ NS_ENSURE_ARG_POINTER(aAttributes);
+
+ nsresult rv;
+ nsCString attr;
+ nsAutoCString prop;
+ nsCString propvalue;
+
+ aRdn.Truncate();
+ for (uint32_t i = 0; i < aAttrCount; ++i)
+ {
+ attr.Assign(nsDependentCString(aAttributes[i]));
+
+ // Lookup the property corresponding to the attribute
+ rv = aAttributeMap->GetProperty(attr, prop);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Get the property value
+ rv = GetPropertyAsAUTF8String(prop.get(), propvalue);
+
+ // XXX The case where an attribute needed to build the Relative
+ // Distinguished Name is not set needs to be handled by the caller,
+ // so as to let the user know what is missing.
+ if (NS_FAILED(rv) || propvalue.IsEmpty())
+ {
+ NS_ERROR("nsAbLDAPCard::BuildRdn: a required attribute is not set");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ aRdn.Append(attr);
+ aRdn.AppendLiteral("=");
+ aRdn.Append(propvalue);
+ if (i < aAttrCount - 1)
+ aRdn.AppendLiteral("+");
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsAbLDAPCard::GetDn(nsACString &aDN)
+{
+ return GetPropertyAsAUTF8String(kDNColumn, aDN);
+}
+
+NS_IMETHODIMP nsAbLDAPCard::SetDn(const nsACString &aDN)
+{
+ SetLocalId(aDN);
+ return SetPropertyAsAUTF8String(kDNColumn, aDN);
+}
+
+NS_IMETHODIMP nsAbLDAPCard::SetMetaProperties(nsILDAPMessage *aMessage)
+{
+ NS_ENSURE_ARG_POINTER(aMessage);
+
+ // Get DN
+ nsAutoCString dn;
+ nsresult rv = aMessage->GetDn(dn);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ SetDn(dn);
+
+ // Get the list of set attributes
+ CharPtrArrayGuard attrs;
+ rv = aMessage->GetAttributes(attrs.GetSizeAddr(), attrs.GetArrayAddr());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString attr;
+ m_attributes.Clear();
+ for (uint32_t i = 0; i < attrs.GetSize(); ++i)
+ {
+ attr.Assign(nsDependentCString(attrs[i]));
+ ToLowerCase(attr);
+ m_attributes.AppendElement(attr);
+ }
+
+ // Get the objectClass values
+ m_objectClass.Clear();
+ PRUnicharPtrArrayGuard vals;
+ rv = aMessage->GetValues("objectClass", vals.GetSizeAddr(),
+ vals.GetArrayAddr());
+
+ // objectClass is not always included in search result entries and
+ // nsILDAPMessage::GetValues returns NS_ERROR_LDAP_DECODING_ERROR if the
+ // requested attribute doesn't exist.
+ if (rv == NS_ERROR_LDAP_DECODING_ERROR)
+ return NS_OK;
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString oclass;
+ for (uint32_t i = 0; i < vals.GetSize(); ++i)
+ {
+ oclass.Assign(NS_LossyConvertUTF16toASCII(nsDependentString(vals[i])));
+ ToLowerCase(oclass);
+ m_objectClass.AppendElement(oclass);
+ }
+
+ return NS_OK;
+}