summaryrefslogtreecommitdiffstats
path: root/mailnews/addrbook/src/nsAbOSXDirectory.mm
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /mailnews/addrbook/src/nsAbOSXDirectory.mm
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/addrbook/src/nsAbOSXDirectory.mm')
-rw-r--r--mailnews/addrbook/src/nsAbOSXDirectory.mm1374
1 files changed, 1374 insertions, 0 deletions
diff --git a/mailnews/addrbook/src/nsAbOSXDirectory.mm b/mailnews/addrbook/src/nsAbOSXDirectory.mm
new file mode 100644
index 000000000..e195fe3a7
--- /dev/null
+++ b/mailnews/addrbook/src/nsAbOSXDirectory.mm
@@ -0,0 +1,1374 @@
+/* -*- 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 "nsAbOSXDirectory.h"
+#include "nsAbOSXCard.h"
+#include "nsAbOSXUtils.h"
+#include "nsAbQueryStringToExpression.h"
+#include "nsArrayEnumerator.h"
+#include "nsAutoPtr.h"
+#include "nsCOMArray.h"
+#include "nsEnumeratorUtils.h"
+#include "nsIAbDirectoryQueryProxy.h"
+#include "nsIAbManager.h"
+#include "nsObjCExceptions.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIMutableArray.h"
+#include "nsArrayUtils.h"
+#include "nsIAbBooleanExpression.h"
+#include "nsComponentManagerUtils.h"
+#include "nsISimpleEnumerator.h"
+
+#include <AddressBook/AddressBook.h>
+
+#define kABDeletedRecords (kABDeletedRecords? kABDeletedRecords : @"ABDeletedRecords")
+#define kABUpdatedRecords (kABUpdatedRecords ? kABUpdatedRecords : @"ABUpdatedRecords")
+#define kABInsertedRecords (kABInsertedRecords ? kABInsertedRecords : @"ABInsertedRecords")
+
+static nsresult
+GetOrCreateGroup(NSString *aUid, nsIAbDirectory **aResult)
+{
+ NS_ASSERTION(aUid, "No UID for group!.");
+
+ nsAutoCString uri(NS_ABOSXDIRECTORY_URI_PREFIX);
+ AppendToCString(aUid, uri);
+
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(uri, getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_IF_ADDREF(*aResult = directory);
+ return NS_OK;
+}
+
+static nsresult
+GetCard(ABRecord *aRecord, nsIAbCard **aResult, nsIAbOSXDirectory *osxDirectory)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ NSString *uid = [aRecord uniqueId];
+ NS_ASSERTION(uid, "No UID for card!.");
+ if (!uid)
+ return NS_ERROR_FAILURE;
+
+ nsAutoCString uri(NS_ABOSXCARD_URI_PREFIX);
+ AppendToCString(uid, uri);
+ nsCOMPtr<nsIAbOSXCard> osxCard;
+ nsresult rv = osxDirectory->GetCardByUri(uri, getter_AddRefs(osxCard));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbCard> card = do_QueryInterface(osxCard, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_IF_ADDREF(*aResult = card);
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+static nsresult
+CreateCard(ABRecord *aRecord, nsIAbCard **aResult)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ NSString *uid = [aRecord uniqueId];
+ NS_ASSERTION(uid, "No UID for card!.");
+ if (!uid)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsCOMPtr<nsIAbOSXCard> osxCard = do_CreateInstance(NS_ABOSXCARD_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString uri(NS_ABOSXCARD_URI_PREFIX);
+ AppendToCString(uid, uri);
+
+ rv = osxCard->Init(uri.get());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbCard> card = do_QueryInterface(osxCard, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_IF_ADDREF(*aResult = card);
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+static nsresult
+Sync(NSString *aUid)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
+ ABRecord *card = [addressBook recordForUniqueId:aUid];
+ if ([card isKindOfClass:[ABGroup class]])
+ {
+ nsCOMPtr<nsIAbDirectory> directory;
+ GetOrCreateGroup(aUid, getter_AddRefs(directory));
+ nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
+ do_QueryInterface(directory);
+
+ if (osxDirectory) {
+ osxDirectory->Update();
+ }
+ }
+ else {
+ nsCOMPtr<nsIAbCard> abCard;
+ nsresult rv;
+
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
+ do_QueryInterface(directory, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = GetCard(card, getter_AddRefs(abCard), osxDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbOSXCard> osxCard = do_QueryInterface(abCard);
+ osxCard->Update(true);
+ }
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+@interface ABChangedMonitor : NSObject
+-(void)ABChanged:(NSNotification *)aNotification;
+@end
+
+@implementation ABChangedMonitor
+-(void)ABChanged:(NSNotification *)aNotification
+{
+ NSDictionary *changes = [aNotification userInfo];
+
+ nsresult rv;
+ NSArray *inserted = [changes objectForKey:kABInsertedRecords];
+
+ if (inserted) {
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
+ do_QueryInterface(directory, &rv);
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ unsigned int i, count = [inserted count];
+ for (i = 0; i < count; ++i) {
+ ABAddressBook *addressBook =
+ [ABAddressBook sharedAddressBook];
+ ABRecord *card =
+ [addressBook recordForUniqueId:[inserted objectAtIndex:i]];
+ if ([card isKindOfClass:[ABGroup class]]) {
+ nsCOMPtr<nsIAbDirectory> directory;
+ GetOrCreateGroup([inserted objectAtIndex:i],
+ getter_AddRefs(directory));
+
+ rv = osxDirectory->AssertDirectory(abManager, directory);
+ NS_ENSURE_SUCCESS_VOID(rv);
+ }
+ else {
+ nsCOMPtr<nsIAbCard> abCard;
+ // Construct a card
+ nsresult rv = CreateCard(card, getter_AddRefs(abCard));
+ NS_ENSURE_SUCCESS_VOID(rv);
+ rv = osxDirectory->AssertCard(abManager, abCard);
+ NS_ENSURE_SUCCESS_VOID(rv);
+ }
+ }
+ }
+
+ NSArray *updated = [changes objectForKey:kABUpdatedRecords];
+ if (updated) {
+ unsigned int i, count = [updated count];
+ for (i = 0; i < count; ++i) {
+ NSString *uid = [updated objectAtIndex:i];
+ Sync(uid);
+ }
+ }
+
+ NSArray *deleted = [changes objectForKey:kABDeletedRecords];
+ if (deleted) {
+
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
+ do_QueryInterface(directory, &rv);
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ unsigned int i, count = [deleted count];
+ for (i = 0; i < count; ++i) {
+ NSString *deletedUid = [deleted objectAtIndex:i];
+
+ nsAutoCString uid;
+ AppendToCString(deletedUid, uid);
+
+ rv = osxDirectory->DeleteUid(uid);
+ NS_ENSURE_SUCCESS_VOID(rv);
+ }
+ }
+
+ if (!inserted && !updated && !deleted) {
+ // XXX This is supposed to mean "everything was updated", but we get
+ // this whenever something has changed, so not sure what to do.
+ }
+}
+@end
+
+static nsresult
+MapConditionString(nsIAbBooleanConditionString *aCondition, bool aNegate,
+ bool &aCanHandle, ABSearchElement **aResult)
+{
+ aCanHandle = false;
+
+ nsAbBooleanConditionType conditionType = 0;
+ nsresult rv = aCondition->GetCondition(&conditionType);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ABSearchComparison comparison;
+ switch (conditionType) {
+ case nsIAbBooleanConditionTypes::Contains:
+ {
+ if (!aNegate) {
+ comparison = kABContainsSubString;
+ aCanHandle = true;
+ }
+ break;
+ }
+ case nsIAbBooleanConditionTypes::DoesNotContain:
+ {
+ if (aNegate) {
+ comparison = kABContainsSubString;
+ aCanHandle = true;
+ }
+ break;
+ }
+ case nsIAbBooleanConditionTypes::Is:
+ {
+ comparison = aNegate ? kABNotEqual : kABEqual;
+ aCanHandle = true;
+ break;
+ }
+ case nsIAbBooleanConditionTypes::IsNot:
+ {
+ comparison = aNegate ? kABEqual : kABNotEqual;
+ aCanHandle = true;
+ break;
+ }
+ case nsIAbBooleanConditionTypes::BeginsWith:
+ {
+ if (!aNegate) {
+ comparison = kABPrefixMatch;
+ aCanHandle = true;
+ }
+ break;
+ }
+ case nsIAbBooleanConditionTypes::EndsWith:
+ {
+ //comparison = kABSuffixMatch;
+ break;
+ }
+ case nsIAbBooleanConditionTypes::LessThan:
+ {
+ comparison = aNegate ? kABGreaterThanOrEqual : kABLessThan;
+ aCanHandle = true;
+ break;
+ }
+ case nsIAbBooleanConditionTypes::GreaterThan:
+ {
+ comparison = aNegate ? kABLessThanOrEqual : kABGreaterThan;
+ aCanHandle = true;
+ break;
+ }
+ }
+
+ if (!aCanHandle)
+ return NS_OK;
+
+ nsCString name;
+ rv = aCondition->GetName(getter_Copies(name));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsString value;
+ rv = aCondition->GetValue(getter_Copies(value));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t length = value.Length();
+
+ uint32_t i;
+ for (i = 0; i < nsAbOSXUtils::kPropertyMapSize; ++i) {
+ if (name.Equals(nsAbOSXUtils::kPropertyMap[i].mPropertyName)) {
+ *aResult =
+ [ABPerson searchElementForProperty:nsAbOSXUtils::kPropertyMap[i].mOSXProperty
+ label:nsAbOSXUtils::kPropertyMap[i].mOSXLabel
+ key:nsAbOSXUtils::kPropertyMap[i].mOSXKey
+ value:[NSString stringWithCharacters:reinterpret_cast<const unichar*>(value.get()) length:length]
+ comparison:comparison];
+
+ return NS_OK;
+ }
+ }
+
+ if (name.EqualsLiteral("DisplayName") && comparison == kABContainsSubString) {
+ ABSearchElement *first =
+ [ABPerson searchElementForProperty:kABFirstNameProperty
+ label:nil
+ key:nil
+ value:[NSString stringWithCharacters:reinterpret_cast<const unichar*>(value.get()) length:length]
+ comparison:comparison];
+ ABSearchElement *second =
+ [ABPerson searchElementForProperty:kABLastNameProperty
+ label:nil
+ key:nil
+ value:[NSString stringWithCharacters:reinterpret_cast<const unichar*>(value.get()) length:length]
+ comparison:comparison];
+ ABSearchElement *third =
+ [ABGroup searchElementForProperty:kABGroupNameProperty
+ label:nil
+ key:nil
+ value:[NSString stringWithCharacters:reinterpret_cast<const unichar*>(value.get()) length:length]
+ comparison:comparison];
+
+ *aResult = [ABSearchElement searchElementForConjunction:kABSearchOr children:[NSArray arrayWithObjects:first, second, third, nil]];
+
+ return NS_OK;
+ }
+
+ aCanHandle = false;
+
+ return NS_OK;
+}
+
+static nsresult
+BuildSearchElements(nsIAbBooleanExpression *aExpression,
+ bool &aCanHandle,
+ ABSearchElement **aResult)
+{
+ aCanHandle = true;
+
+ nsCOMPtr<nsIArray> expressions;
+ nsresult rv = aExpression->GetExpressions(getter_AddRefs(expressions));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAbBooleanOperationType operation;
+ rv = aExpression->GetOperation(&operation);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t count;
+ rv = expressions->GetLength(&count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ASSERTION(count > 1 && operation != nsIAbBooleanOperationTypes::NOT,
+ "This doesn't make sense!");
+
+ NSMutableArray *array = nullptr;
+ if (count > 1)
+ array = [[NSMutableArray alloc] init];
+
+ uint32_t i;
+ nsCOMPtr<nsIAbBooleanConditionString> condition;
+ nsCOMPtr<nsIAbBooleanExpression> subExpression;
+ for (i = 0; i < count; ++i) {
+ ABSearchElement *element = nullptr;
+
+ condition = do_QueryElementAt(expressions, i);
+ if (condition) {
+ rv = MapConditionString(condition, operation == nsIAbBooleanOperationTypes::NOT, aCanHandle, &element);
+ if (NS_FAILED(rv))
+ break;
+ }
+ else {
+ subExpression = do_QueryElementAt(expressions, i);
+ if (subExpression) {
+ rv = BuildSearchElements(subExpression, aCanHandle, &element);
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+
+ if (!aCanHandle) {
+ // remember to free the array when returning early
+ [array release];
+ return NS_OK;
+ }
+
+ if (element) {
+ if (array)
+ [array addObject:element];
+ else
+ *aResult = element;
+ }
+ }
+
+ if (array) {
+ if (NS_SUCCEEDED(rv)) {
+ ABSearchConjunction conjunction = operation == nsIAbBooleanOperationTypes::AND ? kABSearchAnd : kABSearchOr;
+ *aResult = [ABSearchElement searchElementForConjunction:conjunction children:array];
+ }
+ [array release];
+ }
+
+ return rv;
+}
+
+static bool
+Search(nsIAbBooleanExpression *aExpression, NSArray **aResult)
+{
+ bool canHandle = false;
+ ABSearchElement *searchElement;
+ nsresult rv = BuildSearchElements(aExpression, canHandle, &searchElement);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ if (canHandle)
+ *aResult = [[ABAddressBook sharedAddressBook] recordsMatchingSearchElement:searchElement];
+
+ return canHandle;
+}
+
+static uint32_t sObserverCount = 0;
+static ABChangedMonitor *sObserver = nullptr;
+
+nsAbOSXDirectory::nsAbOSXDirectory()
+{
+}
+
+nsAbOSXDirectory::~nsAbOSXDirectory()
+{
+ if (--sObserverCount == 0) {
+ [[NSNotificationCenter defaultCenter] removeObserver:sObserver];
+ [sObserver release];
+ }
+}
+
+NS_IMPL_ISUPPORTS_INHERITED(nsAbOSXDirectory,
+ nsAbDirProperty,
+ nsIAbOSXDirectory,
+ nsIAbDirSearchListener)
+
+NS_IMETHODIMP
+nsAbOSXDirectory::Init(const char *aUri)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ nsresult rv;
+ rv = nsAbDirProperty::Init(aUri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
+ if (sObserverCount == 0) {
+ sObserver = [[ABChangedMonitor alloc] init];
+ [[NSNotificationCenter defaultCenter] addObserver:(ABChangedMonitor*)sObserver
+ selector:@selector(ABChanged:)
+ name:kABDatabaseChangedExternallyNotification
+ object:nil];
+ }
+ ++sObserverCount;
+
+ NSArray *cards;
+ nsCOMPtr<nsIMutableArray> cardList;
+ bool isRootOSXDirectory = false;
+
+ if (!mIsQueryURI && mURINoQuery.Length() <= sizeof(NS_ABOSXDIRECTORY_URI_PREFIX))
+ isRootOSXDirectory = true;
+
+ if (mIsQueryURI || isRootOSXDirectory)
+ {
+ m_DirPrefId.AssignLiteral("ldap_2.servers.osx");
+
+ cards = [[addressBook people] arrayByAddingObjectsFromArray:[addressBook groups]];
+ if (!mCardList)
+ mCardList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ else
+ rv = mCardList->Clear();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ cardList = mCardList;
+ }
+ else
+ {
+ nsAutoCString uid(Substring(mURINoQuery, sizeof(NS_ABOSXDIRECTORY_URI_PREFIX) - 1));
+ ABRecord *card = [addressBook recordForUniqueId:[NSString stringWithUTF8String:uid.get()]];
+ NS_ASSERTION([card isKindOfClass:[ABGroup class]], "Huh.");
+
+ m_IsMailList = true;
+ AppendToString([card valueForProperty:kABGroupNameProperty], m_ListDirName);
+
+ ABGroup *group = (ABGroup*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsAutoCString(Substring(mURINoQuery, 21)).get()]];
+ cards = [[group members] arrayByAddingObjectsFromArray:[group subgroups]];
+
+ if (!m_AddressList)
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ else
+ rv = m_AddressList->Clear();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ cardList = m_AddressList;
+ }
+
+
+ nsAutoCString ourUuid;
+ GetUuid(ourUuid);
+
+ unsigned int nbCards = [cards count];
+ nsCOMPtr<nsIAbCard> card;
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> rootOSXDirectory;
+ if (!isRootOSXDirectory)
+ {
+ rv = GetRootOSXDirectory(getter_AddRefs(rootOSXDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ for (unsigned int i = 0; i < nbCards; ++i)
+ {
+ // If we're a Group, it's likely that the cards we're going
+ // to create were already created in the root nsAbOSXDirectory,
+ if (!isRootOSXDirectory)
+ rv = GetCard([cards objectAtIndex:i], getter_AddRefs(card),
+ rootOSXDirectory);
+ else
+ {
+ // If we're not a Group, that means we're the root nsAbOSXDirectory,
+ // which means we have to create the cards from scratch.
+ rv = CreateCard([cards objectAtIndex:i], getter_AddRefs(card));
+ }
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // If we're not a query directory, we're going to want to
+ // tell the AB Manager that we've added some cards so that they
+ // show up in the address book views.
+ if (!mIsQueryURI)
+ AssertCard(abManager, card);
+
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetURI(nsACString &aURI)
+{
+ if (mURI.IsEmpty())
+ return NS_ERROR_NOT_INITIALIZED;
+
+ aURI = mURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetReadOnly(bool *aReadOnly)
+{
+ NS_ENSURE_ARG_POINTER(aReadOnly);
+
+ *aReadOnly = true;
+ return NS_OK;
+}
+
+static bool
+CheckRedundantCards(nsIAbManager *aManager, nsIAbDirectory *aDirectory,
+ nsIAbCard *aCard, NSMutableArray *aCardList)
+{
+ nsresult rv;
+ nsCOMPtr<nsIAbOSXCard> osxCard = do_QueryInterface(aCard, &rv);
+ NS_ENSURE_SUCCESS(rv, false);
+
+ nsAutoCString uri;
+ rv = osxCard->GetURI(uri);
+ NS_ENSURE_SUCCESS(rv, false);
+ NSString *uid = [NSString stringWithUTF8String:(uri.get() + 21)];
+
+ unsigned int i, count = [aCardList count];
+ for (i = 0; i < count; ++i) {
+ if ([[[aCardList objectAtIndex:i] uniqueId] isEqualToString:uid]) {
+ [aCardList removeObjectAtIndex:i];
+ break;
+ }
+ }
+
+ if (i == count) {
+ aManager->NotifyDirectoryItemDeleted(aDirectory, aCard);
+ return true;
+ }
+
+ return false;
+}
+
+nsresult
+nsAbOSXDirectory::GetRootOSXDirectory(nsIAbOSXDirectory **aResult)
+{
+ if (!mCacheTopLevelOSXAb)
+ {
+ // Attempt to get card from the toplevel directories
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
+ do_QueryInterface(directory, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mCacheTopLevelOSXAb = osxDirectory;
+ }
+
+ NS_IF_ADDREF(*aResult = mCacheTopLevelOSXAb);
+ return NS_OK;
+}
+
+nsresult
+nsAbOSXDirectory::Update()
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mIsQueryURI) {
+ return NS_OK;
+ }
+
+ ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
+ // Due to the horrible way the address book code works wrt mailing lists
+ // we have to use a different list depending on what we are. This pointer
+ // holds a reference to that list.
+ nsIMutableArray* cardList;
+ NSArray *groups, *cards;
+ if (m_IsMailList) {
+ ABGroup *group = (ABGroup*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsAutoCString(Substring(mURINoQuery, 21)).get()]];
+ groups = nil;
+ cards = [[group members] arrayByAddingObjectsFromArray:[group subgroups]];
+
+ if (!m_AddressList)
+ {
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ // For mailing lists, store the cards in m_AddressList
+ cardList = m_AddressList;
+ }
+ else {
+ groups = [addressBook groups];
+ cards = [[addressBook people] arrayByAddingObjectsFromArray:groups];
+
+ if (!mCardList)
+ {
+ mCardList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ // For directories, store the cards in mCardList
+ cardList = mCardList;
+ }
+
+ NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:cards];
+ uint32_t addressCount;
+ rv = cardList->GetLength(&addressCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ while (addressCount--)
+ {
+ nsCOMPtr<nsIAbCard> card(do_QueryElementAt(cardList, addressCount, &rv));
+ if (NS_FAILED(rv))
+ break;
+
+ if (CheckRedundantCards(abManager, this, card, mutableArray))
+ cardList->RemoveElementAt(addressCount);
+ }
+
+ NSEnumerator *enumerator = [mutableArray objectEnumerator];
+ ABRecord *card;
+ nsCOMPtr<nsIAbCard> abCard;
+ nsCOMPtr<nsIAbOSXDirectory> rootOSXDirectory;
+ rv = GetRootOSXDirectory(getter_AddRefs(rootOSXDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ while ((card = [enumerator nextObject]))
+ {
+ rv = GetCard(card, getter_AddRefs(abCard), rootOSXDirectory);
+ if (NS_FAILED(rv))
+ rv = CreateCard(card, getter_AddRefs(abCard));
+ NS_ENSURE_SUCCESS(rv, rv);
+ AssertCard(abManager, abCard);
+ }
+
+ card = (ABRecord*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsAutoCString(Substring(mURINoQuery, 21)).get()]];
+ NSString * stringValue = [card valueForProperty:kABGroupNameProperty];
+ if (![stringValue isEqualToString:WrapString(m_ListDirName)])
+ {
+ nsAutoString oldValue(m_ListDirName);
+ AssignToString(stringValue, m_ListDirName);
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(static_cast<nsIAbDirectory *>(this), &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ abManager->NotifyItemPropertyChanged(supports, "DirName",
+ oldValue.get(), m_ListDirName.get());
+ }
+
+ if (groups)
+ {
+ mutableArray = [NSMutableArray arrayWithArray:groups];
+ nsCOMPtr<nsIAbDirectory> directory;
+ // It is ok to use m_AddressList here as only top-level directories have
+ // groups, and they will be in m_AddressList
+ if (m_AddressList)
+ {
+ rv = m_AddressList->GetLength(&addressCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ while (addressCount--)
+ {
+ directory = do_QueryElementAt(m_AddressList, addressCount, &rv);
+ if (NS_FAILED(rv))
+ continue;
+
+ nsAutoCString uri;
+ directory->GetURI(uri);
+ uri.Cut(0, 21);
+ NSString *uid = [NSString stringWithUTF8String:uri.get()];
+
+ unsigned int j, arrayCount = [mutableArray count];
+ for (j = 0; j < arrayCount; ++j) {
+ if ([[[mutableArray objectAtIndex:j] uniqueId] isEqualToString:uid]) {
+ [mutableArray removeObjectAtIndex:j];
+ break;
+ }
+ }
+
+ if (j == arrayCount) {
+ UnassertDirectory(abManager, directory);
+ }
+ }
+ }
+
+ enumerator = [mutableArray objectEnumerator];
+ while ((card = [enumerator nextObject])) {
+ rv = GetOrCreateGroup([card uniqueId], getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ AssertDirectory(abManager, directory);
+ }
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult
+nsAbOSXDirectory::AssertChildNodes()
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ // Queries and mailing lists can't have childnodes.
+ if (mIsQueryURI || m_IsMailList) {
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> abManager =
+ do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NSArray *groups = [[ABAddressBook sharedAddressBook] groups];
+
+ unsigned int i, count = [groups count];
+
+ if (count > 0 && !m_AddressList) {
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ for (i = 0; i < count; ++i) {
+ rv = GetOrCreateGroup([[groups objectAtIndex:i] uniqueId],
+ getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = AssertDirectory(abManager, directory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+nsresult
+nsAbOSXDirectory::AssertDirectory(nsIAbManager *aManager,
+ nsIAbDirectory *aDirectory)
+{
+ uint32_t pos;
+ if (m_AddressList &&
+ NS_SUCCEEDED(m_AddressList->IndexOf(0, aDirectory, &pos)))
+ // We already have this directory, so no point in adding it again.
+ return NS_OK;
+
+ nsresult rv;
+ if (!m_AddressList) {
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = m_AddressList->AppendElement(aDirectory, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return aManager->NotifyDirectoryItemAdded(this, aDirectory);
+}
+
+nsresult
+nsAbOSXDirectory::AssertCard(nsIAbManager *aManager,
+ nsIAbCard *aCard)
+{
+ nsAutoCString ourUuid;
+ GetUuid(ourUuid);
+ aCard->SetDirectoryId(ourUuid);
+
+ nsresult rv = m_IsMailList ? m_AddressList->AppendElement(aCard, false) :
+ mCardList->AppendElement(aCard, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Get the card's URI and add it to our card store
+ nsCOMPtr<nsIAbOSXCard> osxCard = do_QueryInterface(aCard, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCString uri;
+ rv = osxCard->GetURI(uri);
+
+ nsCOMPtr<nsIAbOSXCard> retrievedCard;
+ if (!mCardStore.Get(uri, getter_AddRefs(retrievedCard)))
+ mCardStore.Put(uri, osxCard);
+
+ return aManager->NotifyDirectoryItemAdded(this, aCard);
+}
+
+nsresult
+nsAbOSXDirectory::UnassertCard(nsIAbManager *aManager,
+ nsIAbCard *aCard,
+ nsIMutableArray *aCardList)
+{
+ nsresult rv;
+ uint32_t pos;
+
+ if (NS_SUCCEEDED(aCardList->IndexOf(0, aCard, &pos)))
+ rv = aCardList->RemoveElementAt(pos);
+
+ return aManager->NotifyDirectoryItemDeleted(this, aCard);
+}
+
+nsresult
+nsAbOSXDirectory::UnassertDirectory(nsIAbManager *aManager,
+ nsIAbDirectory *aDirectory)
+{
+ NS_ENSURE_TRUE(m_AddressList, NS_ERROR_NULL_POINTER);
+
+ uint32_t pos;
+ if (NS_SUCCEEDED(m_AddressList->IndexOf(0, aDirectory, &pos)))
+ {
+ nsresult rv = m_AddressList->RemoveElementAt(pos);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return aManager->NotifyDirectoryItemDeleted(this, aDirectory);
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetChildNodes(nsISimpleEnumerator **aNodes)
+{
+ NS_ENSURE_ARG_POINTER(aNodes);
+
+ // Queries don't have childnodes.
+ if (mIsQueryURI || m_IsMailList || !m_AddressList)
+ return NS_NewEmptyEnumerator(aNodes);
+
+ return NS_NewArrayEnumerator(aNodes, m_AddressList);
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetChildCards(nsISimpleEnumerator **aCards)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+ NS_ENSURE_ARG_POINTER(aCards);
+
+ nsresult rv;
+ NSArray *cards;
+ if (mIsQueryURI)
+ {
+ nsCOMPtr<nsIAbBooleanExpression> expression;
+ rv = nsAbQueryStringToExpression::Convert(mQueryString,
+ getter_AddRefs(expression));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool canHandle = !m_IsMailList && Search(expression, &cards);
+ if (!canHandle)
+ return FallbackSearch(expression, aCards);
+
+ if (!mCardList)
+ mCardList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ else
+ mCardList->Clear();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // The uuid for initializing cards
+ nsAutoCString ourUuid;
+ GetUuid(ourUuid);
+
+ // Fill the results array and update the card list
+ unsigned int nbCards = [cards count];
+
+ unsigned int i;
+ nsCOMPtr<nsIAbCard> card;
+ nsCOMPtr<nsIAbOSXDirectory> rootOSXDirectory;
+ rv = GetRootOSXDirectory(getter_AddRefs(rootOSXDirectory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ for (i = 0; i < nbCards; ++i)
+ {
+ rv = GetCard([cards objectAtIndex:i], getter_AddRefs(card),
+ rootOSXDirectory);
+
+ if (NS_FAILED(rv))
+ rv = CreateCard([cards objectAtIndex:i],
+ getter_AddRefs(card));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+ card->SetDirectoryId(ourUuid);
+
+ mCardList->AppendElement(card, false);
+ }
+
+ return NS_NewArrayEnumerator(aCards, mCardList);
+ }
+
+ // Not a search, so just return the appropriate list of items.
+ return m_IsMailList ? NS_NewArrayEnumerator(aCards, m_AddressList) :
+ NS_NewArrayEnumerator(aCards, mCardList);
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetIsQuery(bool *aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = mIsQueryURI;
+ return NS_OK;
+}
+
+/* Recursive method that searches for a child card by URI. If it cannot find
+ * it within this directory, it checks all subfolders.
+ */
+NS_IMETHODIMP
+nsAbOSXDirectory::GetCardByUri(const nsACString &aUri, nsIAbOSXCard **aResult)
+{
+ nsCOMPtr<nsIAbOSXCard> osxCard;
+
+ // Base Case
+ if (mCardStore.Get(aUri, getter_AddRefs(osxCard)))
+ {
+ NS_IF_ADDREF(*aResult = osxCard);
+ return NS_OK;
+ }
+ // Search children
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ nsresult rv = this->GetChildNodes(getter_AddRefs(enumerator));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISupports> item;
+ bool hasMore = false;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore)
+ {
+ rv = enumerator->GetNext(getter_AddRefs(item));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbOSXDirectory> childDirectory;
+ childDirectory = do_QueryInterface(item, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = childDirectory->GetCardByUri(aUri, getter_AddRefs(osxCard));
+ if (NS_SUCCEEDED(rv))
+ {
+ NS_IF_ADDREF(*aResult = osxCard);
+ return NS_OK;
+ }
+ }
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetCardFromProperty(const char *aProperty,
+ const nsACString &aValue,
+ bool aCaseSensitive,
+ nsIAbCard **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = nullptr;
+
+ if (aValue.IsEmpty())
+ return NS_OK;
+
+ nsIMutableArray *list = m_IsMailList ? m_AddressList : mCardList;
+
+ if (!list)
+ return NS_OK;
+
+ uint32_t length;
+ nsresult rv = list->GetLength(&length);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbCard> card;
+ nsAutoCString cardValue;
+
+ for (uint32_t i = 0; i < length && !*aResult; ++i)
+ {
+ card = do_QueryElementAt(list, i, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = card->GetPropertyAsAUTF8String(aProperty, cardValue);
+ if (NS_SUCCEEDED(rv))
+ {
+#ifdef MOZILLA_INTERNAL_API
+ bool equal = aCaseSensitive ? cardValue.Equals(aValue) :
+ cardValue.Equals(aValue, nsCaseInsensitiveCStringComparator());
+#else
+ bool equal = aCaseSensitive ? cardValue.Equals(aValue) :
+ cardValue.Equals(aValue, CaseInsensitiveCompare);
+#endif
+ if (equal)
+ NS_IF_ADDREF(*aResult = card);
+ }
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::GetCardsFromProperty(const char *aProperty,
+ const nsACString &aValue,
+ bool aCaseSensitive,
+ nsISimpleEnumerator **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = nullptr;
+
+ if (aValue.IsEmpty())
+ return NS_NewEmptyEnumerator(aResult);
+
+ nsIMutableArray *list = m_IsMailList ? m_AddressList : mCardList;
+
+ if (!list)
+ return NS_NewEmptyEnumerator(aResult);
+
+ uint32_t length;
+ nsresult rv = list->GetLength(&length);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMArray<nsIAbCard> resultArray;
+ nsCOMPtr<nsIAbCard> card;
+ nsAutoCString cardValue;
+
+ for (uint32_t i = 0; i < length; ++i)
+ {
+ card = do_QueryElementAt(list, i, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = card->GetPropertyAsAUTF8String(aProperty, cardValue);
+ if (NS_SUCCEEDED(rv))
+ {
+#ifdef MOZILLA_INTERNAL_API
+ bool equal = aCaseSensitive ? cardValue.Equals(aValue) :
+ cardValue.Equals(aValue, nsCaseInsensitiveCStringComparator());
+#else
+ bool equal = aCaseSensitive ? cardValue.Equals(aValue) :
+ cardValue.Equals(aValue, CaseInsensitiveCompare);
+#endif
+ if (equal)
+ resultArray.AppendObject(card);
+ }
+ }
+ }
+
+ return NS_NewArrayEnumerator(aResult, resultArray);
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::CardForEmailAddress(const nsACString &aEmailAddress,
+ nsIAbCard **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = nullptr;
+
+ if (aEmailAddress.IsEmpty())
+ return NS_OK;
+
+ nsIMutableArray *list = m_IsMailList ? m_AddressList : mCardList;
+
+ if (!list)
+ return NS_OK;
+
+ uint32_t length;
+ nsresult rv = list->GetLength(&length);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbCard> card;
+
+ for (uint32_t i = 0; i < length && !*aResult; ++i)
+ {
+ card = do_QueryElementAt(list, i, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ bool hasEmailAddress = false;
+
+ rv = card->HasEmailAddress(aEmailAddress, &hasEmailAddress);
+ if (NS_SUCCEEDED(rv) && hasEmailAddress)
+ NS_IF_ADDREF(*aResult = card);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::HasCard(nsIAbCard *aCard, bool *aHasCard)
+{
+ NS_ENSURE_ARG_POINTER(aCard);
+ NS_ENSURE_ARG_POINTER(aHasCard);
+
+ nsresult rv = NS_OK;
+ uint32_t index;
+ if (m_IsMailList)
+ {
+ if (m_AddressList)
+ rv = m_AddressList->IndexOf(0, aCard, &index);
+ }
+ else if (mCardList)
+ rv = mCardList->IndexOf(0, aCard, &index);
+
+ *aHasCard = NS_SUCCEEDED(rv);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::HasDirectory(nsIAbDirectory *aDirectory,
+ bool *aHasDirectory)
+{
+ NS_ENSURE_ARG_POINTER(aDirectory);
+ NS_ENSURE_ARG_POINTER(aHasDirectory);
+
+ *aHasDirectory = false;
+
+ uint32_t pos;
+ if (m_AddressList && NS_SUCCEEDED(m_AddressList->IndexOf(0, aDirectory, &pos)))
+ *aHasDirectory = true;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::OnSearchFinished(int32_t aResult, const nsAString &aErrorMsg)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAbOSXDirectory::OnSearchFoundCard(nsIAbCard *aCard)
+{
+ nsresult rv;
+ if (!m_AddressList) {
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (!mCardList) {
+ mCardList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = m_AddressList->AppendElement(aCard, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mCardList->AppendElement(aCard, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString ourUuid;
+ GetUuid(ourUuid);
+ aCard->SetDirectoryId(ourUuid);
+
+ return NS_OK;
+}
+
+nsresult
+nsAbOSXDirectory::FallbackSearch(nsIAbBooleanExpression *aExpression,
+ nsISimpleEnumerator **aCards)
+{
+ nsresult rv;
+
+ if (mCardList)
+ rv = mCardList->Clear();
+ else
+ mCardList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (m_AddressList) {
+ m_AddressList->Clear();
+ }
+ else {
+ m_AddressList = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsCOMPtr<nsIAbDirectoryQueryArguments> arguments =
+ do_CreateInstance(NS_ABDIRECTORYQUERYARGUMENTS_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = arguments->SetExpression(aExpression);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Don't search the subdirectories. If the current directory is a mailing
+ // list, it won't have any subdirectories. If the current directory is an
+ // addressbook, searching both it and the subdirectories (the mailing
+ // lists), will yield duplicate results because every entry in a mailing
+ // list will be an entry in the parent addressbook.
+ rv = arguments->SetQuerySubDirectories(false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Get the directory without the query
+ nsCOMPtr<nsIAbManager> abManager = do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIAbDirectory> directory;
+ rv = abManager->GetDirectory(mURINoQuery, getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Initiate the proxy query with the no query directory
+ nsCOMPtr<nsIAbDirectoryQueryProxy> queryProxy =
+ do_CreateInstance(NS_ABDIRECTORYQUERYPROXY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = queryProxy->Initiate();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int32_t context = 0;
+ rv = queryProxy->DoQuery(directory, arguments, this, -1, 0, &context);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_NewArrayEnumerator(aCards, m_AddressList);
+}
+
+nsresult nsAbOSXDirectory::DeleteUid(const nsACString &aUid)
+{
+ if (!m_AddressList)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+ nsCOMPtr<nsIAbManager> abManager =
+ do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // At this stage we don't know if aUid represents a card or group. The OS X
+ // interfaces don't give us chance to find out, so we have to go through
+ // our lists to find it.
+
+ // First, we'll see if its in the group list as it is likely to be shorter.
+
+ // See if this item is in our address list
+ uint32_t addressCount;
+ rv = m_AddressList->GetLength(&addressCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString uri(NS_ABOSXDIRECTORY_URI_PREFIX);
+ uri.Append(aUid);
+
+ // Iterate backwards in case we remove something
+ while (addressCount--)
+ {
+ nsCOMPtr<nsIAbItem> abItem(do_QueryElementAt(m_AddressList,
+ addressCount, &rv));
+ if (NS_FAILED(rv))
+ continue;
+
+ nsCOMPtr<nsIAbDirectory> directory(do_QueryInterface(abItem, &rv));
+ if (NS_SUCCEEDED(rv))
+ {
+ nsAutoCString dirUri;
+ directory->GetURI(dirUri);
+ if (uri.Equals(dirUri))
+ return UnassertDirectory(abManager, directory);
+ } else {
+ nsCOMPtr<nsIAbOSXCard> osxCard(do_QueryInterface(abItem, &rv));
+ if (NS_SUCCEEDED(rv))
+ {
+ nsAutoCString cardUri;
+ osxCard->GetURI(cardUri);
+ if (uri.Equals(cardUri))
+ {
+ nsCOMPtr<nsIAbCard> card(do_QueryInterface(osxCard, &rv));
+ if (NS_SUCCEEDED(rv))
+ return UnassertCard(abManager, card, m_AddressList);
+ }
+ }
+ }
+ }
+
+ // Second, see if it is one of the cards.
+ if (!mCardList)
+ return NS_ERROR_FAILURE;
+
+ uri = NS_ABOSXCARD_URI_PREFIX;
+ uri.Append(aUid);
+
+ rv = mCardList->GetLength(&addressCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ while (addressCount--)
+ {
+ nsCOMPtr<nsIAbOSXCard> osxCard(do_QueryElementAt(mCardList, addressCount, &rv));
+ if (NS_FAILED(rv))
+ continue;
+
+ nsAutoCString cardUri;
+ osxCard->GetURI(cardUri);
+
+ if (uri.Equals(cardUri)) {
+ nsCOMPtr<nsIAbCard> card(do_QueryInterface(osxCard, &rv));
+ if (NS_SUCCEEDED(rv))
+ return UnassertCard(abManager, card, mCardList);
+ }
+ }
+ return NS_OK;
+}