land OSX AB integration on the trunk, NPOB yet, patch by peterv, 203927

This commit is contained in:
bienvenu%nventure.com 2007-05-03 16:20:31 +00:00
Родитель 04ff180ea4
Коммит 05a705475d
8 изменённых файлов: 1873 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAbOSXCard_h___
#define nsAbOSXCard_h___
#include "nsAbCardProperty.h"
#include "nsRDFResource.h"
#define NS_ABOSXCARD_URI_PREFIX NS_ABOSXCARD_PREFIX "://"
#define NS_IABOSXCARD_IID \
{ 0xa7e5b697, 0x772d, 0x4fb5, \
{ 0x81, 0x16, 0x23, 0xb7, 0x5a, 0xac, 0x94, 0x56 } }
class nsIAbOSXCard : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABOSXCARD_IID)
virtual nsresult Update(PRBool aNotify) = 0;
};
class nsAbOSXCard : public nsRDFResource,
public nsAbCardProperty,
public nsIAbOSXCard
{
public:
NS_DECL_ISUPPORTS_INHERITED
// nsIRDFResource method
NS_IMETHOD Init(const char *aUri);
nsresult Update(PRBool aNotify);
// this is needed so nsAbOSXUtils.mm can get at nsAbCardProperty
friend class nsAbOSXUtils;
};
#endif // nsAbOSXCard_h___

Просмотреть файл

@ -0,0 +1,351 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAbOSXCard.h"
#include "nsAbOSXDirectory.h"
#include "nsAbOSXUtils.h"
#include "nsAutoPtr.h"
#include "nsIAddrBookSession.h"
#include "nsServiceManagerUtils.h"
#include <AddressBook/AddressBook.h>
NS_IMPL_ISUPPORTS_INHERITED2(nsAbOSXCard,
nsRDFResource,
nsIAbCard,
nsIAbOSXCard)
#ifdef DEBUG
static ABPropertyType
GetPropertType(ABRecord *aCard, NSString *aProperty)
{
ABPropertyType propertyType = kABErrorInProperty;
if ([aCard isKindOfClass:[ABPerson class]])
propertyType = [ABPerson typeOfProperty:aProperty];
else if ([aCard isKindOfClass:[ABGroup class]])
propertyType = [ABGroup typeOfProperty:aProperty];
return propertyType;
}
#endif
static void
SetStringProperty(nsAbOSXCard *aCard, nsString &aValue, nsString &aMember,
const char *aMemberName, PRBool aNotify,
nsIAddrBookSession *aSession)
{
if (!aNotify) {
aMember = aValue;
}
else if (!aMember.Equals(aValue)) {
nsString oldValue(aMember);
aMember = aValue;
nsISupports *supports = NS_ISUPPORTS_CAST(nsRDFResource*, aCard);
aSession->NotifyItemPropertyChanged(supports, aMemberName,
oldValue.get(), aMember.get());
}
}
static void
SetStringProperty(nsAbOSXCard *aCard, NSString *aValue, nsString &aMember,
const char *aMemberName, PRBool aNotify,
nsIAddrBookSession *aSession)
{
nsAutoString value;
if (aValue)
AppendToString(aValue, value);
SetStringProperty(aCard, value, aMember, aMemberName, aNotify, aSession);
}
static void
MapStringProperty(nsAbOSXCard *aCard, ABRecord *aOSXCard, NSString *aProperty,
nsString &aMember, const char *aMemberName, PRBool aNotify,
nsIAddrBookSession *aSession)
{
NS_ASSERTION(aProperty, "This is bad! You asked for an unresolved symbol.");
NS_ASSERTION(GetPropertType(aOSXCard, aProperty) == kABStringProperty,
"Wrong type!");
SetStringProperty(aCard, [aOSXCard valueForProperty:aProperty], aMember,
aMemberName, aNotify, aSession);
}
static ABMutableMultiValue*
GetMultiValue(ABRecord *aCard, NSString *aProperty)
{
NS_ASSERTION(aProperty, "This is bad! You asked for an unresolved symbol.");
NS_ASSERTION(GetPropertType(aCard, aProperty) & kABMultiValueMask,
"Wrong type!");
return [aCard valueForProperty:aProperty];
}
static void
MapDate(nsAbOSXCard *aCard, NSDate *aDate, nsString &aYear,
const char *aYearName, nsString &aMonth, const char *aMonthName,
nsString &aDay, const char *aDayName, PRBool aNotify,
nsIAddrBookSession *aSession)
{
// XXX Should we pass a format and timezone?
NSCalendarDate *date = [aDate dateWithCalendarFormat:nil timeZone:nil];
nsAutoString value;
value.AppendInt([date yearOfCommonEra]);
SetStringProperty(aCard, value, aYear, aYearName, aNotify, aSession);
value.AppendInt([date monthOfYear]);
SetStringProperty(aCard, value, aMonth, aMonthName, aNotify, aSession);
value.AppendInt([date dayOfWeek]);
SetStringProperty(aCard, value, aDay, aDayName, aNotify, aSession);
}
static PRBool
MapMultiValue(nsAbOSXCard *aCard, ABRecord *aOSXCard,
const nsAbOSXPropertyMap &aMap, PRBool aNotify,
nsIAddrBookSession *aSession)
{
ABMultiValue *value = GetMultiValue(aOSXCard, aMap.mOSXProperty);
if (value) {
unsigned int j;
unsigned int count = [value count];
for (j = 0; j < count; ++j) {
if ([[value labelAtIndex:j] isEqualToString:aMap.mOSXLabel]) {
NSString *stringValue = (aMap.mOSXKey)
? [[value valueAtIndex:j] objectForKey:aMap.mOSXKey]
: [value valueAtIndex:j];
SetStringProperty(aCard, stringValue, aCard->*(aMap.mProperty),
aMap.mPropertyName, aNotify, aSession);
return PR_TRUE;
}
}
}
return PR_FALSE;
}
NS_IMETHODIMP
nsAbOSXCard::Init(const char *aUri)
{
if (strncmp(aUri, NS_ABOSXCARD_URI_PREFIX,
sizeof(NS_ABOSXCARD_URI_PREFIX) - 1) != 0)
return NS_ERROR_FAILURE;
nsresult rv = nsRDFResource::Init(aUri);
NS_ENSURE_SUCCESS(rv, rv);
return Update(PR_FALSE);
}
nsresult
nsAbOSXCard::Update(PRBool aNotify)
{
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
const char *uid = &((mURI.get())[16]);
ABRecord *card = [addressBook recordForUniqueId:[NSString stringWithUTF8String:uid]];
NS_ENSURE_TRUE(card, NS_ERROR_FAILURE);
nsCOMPtr<nsIAddrBookSession> abSession;
nsresult rv;
if (aNotify) {
abSession = do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
if ([card isKindOfClass:[ABGroup class]]) {
m_IsMailList = PR_TRUE;
m_MailListURI.AssignLiteral(NS_ABOSXDIRECTORY_URI_PREFIX);
m_MailListURI.Append(uid);
MapStringProperty(this, card, kABGroupNameProperty, m_DisplayName,
"DisplayName", aNotify, abSession);
return NS_OK;
}
PRBool foundHome = PR_FALSE, foundWork = PR_FALSE;
PRUint32 i;
for (i = 0; i < nsAbOSXUtils::kPropertyMapSize; ++i) {
const nsAbOSXPropertyMap &propertyMap = nsAbOSXUtils::kPropertyMap[i];
if (!propertyMap.mOSXProperty)
continue;
if (propertyMap.mOSXLabel) {
if (MapMultiValue(this, card, propertyMap, aNotify,
abSession) && propertyMap.mOSXProperty == kABAddressProperty) {
if (propertyMap.mOSXLabel == kABAddressHomeLabel)
foundHome = PR_TRUE;
else
foundWork = PR_TRUE;
}
}
else {
MapStringProperty(this, card, propertyMap.mOSXProperty,
this->*(propertyMap.mProperty),
propertyMap.mPropertyName, aNotify, abSession);
}
}
int flags = 0;
if (kABPersonFlags)
flags = [[card valueForProperty:kABPersonFlags] intValue];
#define SET_STRING(_value, _name, _notify, _session) \
SetStringProperty(this, _value, m_##_name, #_name, _notify, _session)
// If kABShowAsCompany is set we use the company name as display name.
if (flags & kABShowAsCompany) {
SET_STRING(m_Company, DisplayName, aNotify, abSession);
}
else {
// Use the order used in the OS X address book to set DisplayName.
int order = flags & kABNameOrderingMask;
if (order == kABDefaultNameOrdering) {
order = [addressBook defaultNameOrdering];
}
nsAutoString displayName;
if (order == kABFirstNameFirst) {
displayName.Append(m_FirstName);
displayName.Append(' ');
displayName.Append(m_LastName);
}
else {
displayName.Append(m_LastName);
displayName.Append(' ');
displayName.Append(m_FirstName);
}
SET_STRING(displayName, DisplayName, aNotify, abSession);
}
ABMultiValue *value = GetMultiValue(card, kABEmailProperty);
if (value) {
unsigned int count = [value count];
if (count > 0) {
unsigned int j = [value indexForIdentifier:[value primaryIdentifier]];
if (j < count)
SET_STRING([value valueAtIndex:j], PrimaryEmail, aNotify,
abSession);
// If j is 0 (first in the list) we want the second in the list
// (index 1), if j is anything else we want the first in the list
// (index 0).
j = (j == 0);
if (j < count)
SET_STRING([value valueAtIndex:j], SecondEmail, aNotify,
abSession);
}
}
// We map the first home address we can find and the first work address
// we can find. If we find none, we map the primary address to the home
// address.
if (!foundHome && !foundWork) {
value = GetMultiValue(card, kABAddressProperty);
if (value) {
unsigned int count = [value count];
unsigned int j = [value indexForIdentifier:[value primaryIdentifier]];
if (j < count) {
NSDictionary *address = [value valueAtIndex:j];
if (address) {
SET_STRING([address objectForKey:kABAddressStreetKey],
HomeAddress, aNotify, abSession);
SET_STRING([address objectForKey:kABAddressCityKey],
HomeCity, aNotify, abSession);
SET_STRING([address objectForKey:kABAddressStateKey],
HomeState, aNotify, abSession);
SET_STRING([address objectForKey:kABAddressZIPKey],
HomeZipCode, aNotify, abSession);
SET_STRING([address objectForKey:kABAddressCountryKey],
HomeCountry, aNotify, abSession);
}
}
}
}
value = GetMultiValue(card, kABAIMInstantProperty);
if (value) {
unsigned int count = [value count];
if (count > 0) {
unsigned int j = [value indexForIdentifier:[value primaryIdentifier]];
if (j < count)
SET_STRING([value valueAtIndex:j], AimScreenName, aNotify,
abSession);
}
}
#define MAP_DATE(_date, _name, _notify, _session) \
MapDate(this, _date, m_##_name##Year, #_name"Year", m_##_name##Month, \
#_name"Month", m_##_name##Day, #_name"Day", _notify, _session)
NSDate *date = [card valueForProperty:kABBirthdayProperty];
if (date)
MAP_DATE(date, Birth, aNotify, abSession);
if (kABOtherDatesProperty) {
value = GetMultiValue(card, kABOtherDatesProperty);
if (value) {
unsigned int j, count = [value count];
for (j = 0; j < count; ++j) {
if ([[value labelAtIndex:j] isEqualToString:kABAnniversaryLabel]) {
date = [value valueAtIndex:j];
if (date) {
MAP_DATE(date, Anniversary, aNotify, abSession);
break;
}
}
}
}
}
#undef MAP_DATE
#undef SET_STRING
date = [card valueForProperty:kABModificationDateProperty];
if (date)
m_LastModDate = PRUint32([date timeIntervalSince1970]);
// XXX No way to notify about this?
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAbOSXDirFactory.h"
#include "nsAbBaseCID.h"
#include "nsEnumeratorUtils.h"
#include "nsIAbDirectory.h"
#include "nsIRDFService.h"
#include "rdf.h"
#include "nsString.h"
#include "nsServiceManagerUtils.h"
#include "nsAbOSXDirectory.h"
NS_IMPL_ISUPPORTS1(nsAbOSXDirFactory, nsIAbDirFactory)
NS_IMETHODIMP
nsAbOSXDirFactory::CreateDirectory(nsIAbDirectoryProperties *aProperties,
nsISimpleEnumerator **aDirectories)
{
NS_ENSURE_ARG_POINTER(aProperties);
NS_ENSURE_ARG_POINTER(aDirectories);
*aDirectories = nsnull;
nsAutoString description;
nsresult rv = aProperties->GetDescription(description);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRDFService> rdf =
do_GetService(NS_RDF_CONTRACTID "/rdf-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// We hardcode the root to "moz-abosxdirectory:///".
nsCOMPtr<nsIRDFResource> resource;
rv = rdf->GetResource(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX "/"),
getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAbDirectory> directory = do_QueryInterface(resource, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = directory->SetDirName(description.get());
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
do_QueryInterface(directory, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = osxDirectory->AssertChildNodes();
NS_ENSURE_SUCCESS(rv, rv);
return NS_NewSingletonEnumerator(aDirectories, directory);
}
// No actual deletion, since you cannot create the address books from Mozilla.
NS_IMETHODIMP
nsAbOSXDirFactory::DeleteDirectory(nsIAbDirectory *aDirectory)
{
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAbOSXDirFactory_h___
#define nsAbOSXDirFactory_h___
#include "nsIAbDirFactory.h"
class nsAbOSXDirFactory : public nsIAbDirFactory
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIABDIRFACTORY
};
#endif // nsAbOSXDirFactory_h___

Просмотреть файл

@ -0,0 +1,183 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAbOSXDirectory_h___
#define nsAbOSXDirectory_h___
#include "nsAbBaseCID.h"
#include "nsAbDirectoryRDFResource.h"
#include "nsAbDirProperty.h"
#include "nsIAbDirectoryQuery.h"
#include "nsIAbDirectorySearch.h"
#include "nsAbDirSearchListener.h"
#include "nsTHashtable.h"
class nsIAddrBookSession;
#define NS_ABOSXDIRECTORY_URI_PREFIX NS_ABOSXDIRECTORY_PREFIX "://"
class nsIAbCardHashKey : public PLDHashEntryHdr
{
public:
typedef nsIAbCard* KeyType;
typedef const nsIAbCard* KeyTypePointer;
nsIAbCardHashKey(const nsIAbCard* key)
: mCard(NS_CONST_CAST(nsIAbCard*, key))
{
}
nsIAbCardHashKey(const nsIAbCardHashKey& toCopy)
: mCard(toCopy.mCard)
{
}
~nsIAbCardHashKey()
{
}
KeyType GetCard() const
{
return mCard;
}
KeyTypePointer GetKeyPointer() const
{
return mCard;
}
PRBool KeyEquals(KeyTypePointer aKey) const
{
return aKey == mCard;
}
static KeyTypePointer KeyToPointer(KeyType aKey)
{
return aKey;
}
static PLDHashNumber HashKey(KeyTypePointer aKey)
{
return NS_PTR_TO_INT32(aKey) >> 2;
}
enum { ALLOW_MEMMOVE = PR_TRUE };
private:
nsCOMPtr<nsIAbCard> mCard;
};
#define NS_IABOSXDIRECTORY_IID \
{ 0x87ee4bd9, 0x8552, 0x498f, \
{ 0x80, 0x85, 0x34, 0xf0, 0x2a, 0xbb, 0x56, 0x16 } }
class nsIAbOSXDirectory : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABOSXDIRECTORY_IID)
virtual nsresult AssertChildNodes() = 0;
virtual nsresult Update() = 0;
virtual nsresult AssertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory) = 0;
virtual nsresult AssertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard) = 0;
virtual nsresult UnassertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory) = 0;
virtual nsresult UnassertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard) = 0;
virtual void GetURI(nsACString &aURI) = 0;
};
class nsAbOSXDirectory : public nsAbDirectoryRDFResource,
public nsAbDirProperty,
public nsAbDirSearchListenerContext,
public nsIAbOSXDirectory
{
public:
~nsAbOSXDirectory();
NS_DECL_ISUPPORTS_INHERITED
// nsAbDirectoryRDFResource method
NS_IMETHOD Init(const char *aUri);
// nsAbDirProperty methods
NS_IMETHOD GetOperations(PRInt32 *aOperations);
NS_IMETHOD GetChildCards(nsIEnumerator **aCards);
NS_IMETHOD GetChildNodes(nsISimpleEnumerator **aNodes);
NS_IMETHOD HasCard(nsIAbCard *aCard, PRBool *aHasCard);
NS_IMETHOD HasDirectory(nsIAbDirectory *aDirectory, PRBool *aHasDirectory);
// nsAbDirSearchListenerContext methods
nsresult OnSearchFinished(PRInt32 aResult);
nsresult OnSearchFoundCard(nsIAbCard *aCard);
// nsIAbOSXDirectory
nsresult AssertChildNodes();
nsresult AssertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory);
nsresult AssertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard);
nsresult UnassertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory);
nsresult UnassertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard);
nsresult Update();
void GetURI(nsACString &aURI)
{
aURI = mURI;
}
private:
static nsresult GetEnumerator(nsISupportsArray *aArray,
nsIEnumerator **aEnumerator)
{
nsIBidirectionalEnumerator *enumerator;
nsresult rv = NS_NewISupportsArrayEnumerator(aArray,
&enumerator);
NS_ENSURE_SUCCESS(rv, rv);
*aEnumerator = enumerator;
return NS_OK;
}
nsresult FallbackSearch(nsIAbBooleanExpression *aExpression,
nsIEnumerator **aCards);
nsTHashtable<nsIAbCardHashKey> mCardList;
};
#endif // nsAbOSXDirectory_h___

Просмотреть файл

@ -0,0 +1,897 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#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 "nsIAddrBookSession.h"
#include "nsIRDFService.h"
#include "nsServiceManagerUtils.h"
#include <AddressBook/AddressBook.h>
static nsresult
ConvertToGroupResource(nsIRDFService *aRDFService, NSString *aUid,
nsIAbDirectory **aResult)
{
NS_ASSERTION(aUid, "No UID for group!.");
*aResult = nsnull;
nsCAutoString uri(NS_ABOSXDIRECTORY_URI_PREFIX);
AppendToCString(aUid, uri);
nsCOMPtr<nsIRDFResource> resource;
nsresult rv = aRDFService->GetResource(uri, getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(resource, aResult);
}
static nsresult
ConvertToCard(nsIRDFService *aRDFService, ABRecord *aRecord,
nsIAbCard **aResult)
{
*aResult = nsnull;
NSString *uid = [aRecord uniqueId];
NS_ASSERTION(uid, "No UID for card!.");
if (!uid)
return NS_ERROR_FAILURE;
nsCAutoString uri(NS_ABOSXCARD_URI_PREFIX);
AppendToCString(uid, uri);
nsCOMPtr<nsIRDFResource> resource;
nsresult rv = aRDFService->GetResource(uri, getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(resource, aResult);
}
static nsresult
Update(nsIRDFService *aRDFService, NSString *aUid)
{
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
ABRecord *card = [addressBook recordForUniqueId:aUid];
if ([card isKindOfClass:[ABGroup class]]) {
nsCOMPtr<nsIAbDirectory> directory;
ConvertToGroupResource(aRDFService, aUid, getter_AddRefs(directory));
nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
do_QueryInterface(directory);
osxDirectory->Update();
}
else {
nsCOMPtr<nsIAbCard> abCard;
ConvertToCard(aRDFService, card, getter_AddRefs(abCard));
nsCOMPtr<nsIAbOSXCard> osxCard = do_QueryInterface(abCard);
osxCard->Update(PR_TRUE);
}
return NS_OK;
}
@interface ABChangedMonitor : NSObject
-(void)ABChanged:(NSNotification *)aNotification;
@end
@implementation ABChangedMonitor
-(void)ABChanged:(NSNotification *)aNotification
{
NSDictionary *changes = [aNotification userInfo];
nsresult rv;
nsCOMPtr<nsIRDFService> rdfService =
do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
NS_ENSURE_SUCCESS(rv, );
NSArray *inserted = [changes objectForKey:kABInsertedRecords];
if (inserted) {
nsCOMPtr<nsIRDFResource> resource;
rv = rdfService->GetResource(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, );
nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
do_QueryInterface(resource, &rv);
NS_ENSURE_SUCCESS(rv, );
nsCOMPtr<nsIAddrBookSession> abSession =
do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(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;
ConvertToGroupResource(rdfService, [inserted objectAtIndex:i],
getter_AddRefs(directory));
rv = osxDirectory->AssertDirectory(abSession, directory);
NS_ENSURE_SUCCESS(rv, );
}
else {
nsCOMPtr<nsIAbCard> abCard;
ConvertToCard(rdfService, card, getter_AddRefs(abCard));
rv = osxDirectory->AssertCard(abSession, abCard);
NS_ENSURE_SUCCESS(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];
Update(rdfService, uid);
}
}
NSArray *deleted = [changes objectForKey:kABDeletedRecords];
if (deleted) {
nsCOMPtr<nsIRDFResource> resource;
rv = rdfService->GetResource(NS_LITERAL_CSTRING(NS_ABOSXDIRECTORY_URI_PREFIX"/"),
getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, );
nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
do_QueryInterface(resource, &rv);
NS_ENSURE_SUCCESS(rv, );
nsCOMPtr<nsIAddrBookSession> abSession =
do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, );
unsigned int i, count = [deleted count];
for (i = 0; i < count; ++i) {
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
NSString *recordClass =
[addressBook recordClassFromUniqueId:[deleted objectAtIndex:i]];
if ([recordClass isEqualToString:@"ABGroup"]) {
nsCOMPtr<nsIAbDirectory> directory;
ConvertToGroupResource(rdfService, [deleted objectAtIndex:i],
getter_AddRefs(directory));
rv = osxDirectory->UnassertDirectory(abSession, directory);
NS_ENSURE_SUCCESS(rv, );
}
else {
nsCOMPtr<nsIAbCard> abCard;
ConvertToCard(rdfService, [deleted objectAtIndex:i],
getter_AddRefs(abCard));
rv = osxDirectory->UnassertCard(abSession, abCard);
NS_ENSURE_SUCCESS(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, PRBool aNegate,
PRBool &aCanHandle, ABSearchElement **aResult)
{
aCanHandle = PR_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 = PR_TRUE;
}
break;
}
case nsIAbBooleanConditionTypes::DoesNotContain:
{
if (aNegate) {
comparison = kABContainsSubString;
aCanHandle = PR_TRUE;
}
break;
}
case nsIAbBooleanConditionTypes::Is:
{
comparison = aNegate ? kABNotEqual : kABEqual;
aCanHandle = PR_TRUE;
break;
}
case nsIAbBooleanConditionTypes::IsNot:
{
comparison = aNegate ? kABEqual : kABNotEqual;
aCanHandle = PR_TRUE;
break;
}
case nsIAbBooleanConditionTypes::BeginsWith:
{
if (!aNegate) {
comparison = kABPrefixMatch;
aCanHandle = PR_TRUE;
}
break;
}
case nsIAbBooleanConditionTypes::EndsWith:
{
//comparison = kABSuffixMatch;
break;
}
case nsIAbBooleanConditionTypes::LessThan:
{
comparison = aNegate ? kABGreaterThanOrEqual : kABLessThan;
aCanHandle = PR_TRUE;
break;
}
case nsIAbBooleanConditionTypes::GreaterThan:
{
comparison = aNegate ? kABLessThanOrEqual : kABGreaterThan;
aCanHandle = PR_TRUE;
break;
}
}
if (!aCanHandle)
return NS_OK;
nsXPIDLCString name;
rv = aCondition->GetName(getter_Copies(name));
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLString value;
rv = aCondition->GetValue(getter_Copies(value));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 length = value.Length();
PRUint32 i;
for (i = 0; i < nsAbOSXUtils::kPropertyMapSize; ++i) {
if (name.EqualsASCII(nsAbOSXUtils::kPropertyMap[i].mPropertyName)) {
*aResult =
[ABPerson searchElementForProperty:nsAbOSXUtils::kPropertyMap[i].mOSXProperty
label:nsAbOSXUtils::kPropertyMap[i].mOSXLabel
key:nsAbOSXUtils::kPropertyMap[i].mOSXKey
value:[NSString stringWithCharacters: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:value.get() length:length]
comparison:comparison];
ABSearchElement *second =
[ABPerson searchElementForProperty:kABLastNameProperty
label:nil
key:nil
value:[NSString stringWithCharacters:value.get() length:length]
comparison:comparison];
ABSearchElement *third =
[ABGroup searchElementForProperty:kABGroupNameProperty
label:nil
key:nil
value:[NSString stringWithCharacters:value.get() length:length]
comparison:comparison];
*aResult = [ABSearchElement searchElementForConjunction:kABSearchOr children:[NSArray arrayWithObjects:first, second, third, nil]];
return NS_OK;
}
aCanHandle = PR_FALSE;
return NS_OK;
}
static nsresult
BuildSearchElements(nsIAbBooleanExpression *aExpression,
PRBool &aCanHandle,
ABSearchElement **aResult)
{
aCanHandle = PR_TRUE;
nsCOMPtr<nsISupportsArray> expressions;
nsresult rv = aExpression->GetExpressions(getter_AddRefs(expressions));
NS_ENSURE_SUCCESS(rv, rv);
nsAbBooleanOperationType operation;
rv = aExpression->GetOperation(&operation);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 count;
rv = expressions->Count(&count);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(count > 1 && operation != nsIAbBooleanOperationTypes::NOT,
"This doesn't make sense!");
NSMutableArray *array = nsnull;
if (count > 1)
array = [[NSMutableArray alloc] init];
PRUint32 i;
nsCOMPtr<nsIAbBooleanConditionString> condition;
nsCOMPtr<nsIAbBooleanExpression> subExpression;
for (i = 0; i < count; ++i) {
ABSearchElement *element = nsnull;
condition = do_QueryElementAt(expressions, i);
if (condition) {
rv = MapConditionString(condition, operation == nsIAbBooleanOperationTypes::NOT, aCanHandle, &element);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
subExpression = do_QueryElementAt(expressions, i);
if (subExpression) {
rv = BuildSearchElements(subExpression, aCanHandle, &element);
NS_ENSURE_SUCCESS(rv, rv);
}
}
if (!aCanHandle) {
return NS_OK;
}
if (element) {
if (array)
[array addObject:element];
else
*aResult = element;
}
}
if (array) {
ABSearchConjunction conjunction = operation == nsIAbBooleanOperationTypes::AND ? kABSearchAnd : kABSearchOr;
*aResult = [ABSearchElement searchElementForConjunction:conjunction children:array];
[array release];
}
return NS_OK;
}
static PRBool
Search(nsIAbBooleanExpression *aExpression, NSArray **aResult)
{
PRBool canHandle = PR_FALSE;
ABSearchElement *searchElement;
nsresult rv = BuildSearchElements(aExpression, canHandle, &searchElement);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (canHandle)
*aResult = [[ABAddressBook sharedAddressBook] recordsMatchingSearchElement:searchElement];
return canHandle;
}
static PRUint32 sObserverCount = 0;
static ABChangedMonitor *sObserver = nsnull;
nsAbOSXDirectory::~nsAbOSXDirectory()
{
if (--sObserverCount == 0) {
[[NSNotificationCenter defaultCenter] removeObserver:sObserver];
[sObserver release];
}
}
NS_IMPL_ISUPPORTS_INHERITED2(nsAbOSXDirectory,
nsAbDirectoryRDFResource,
nsIAbDirectory,
nsIAbOSXDirectory)
NS_IMETHODIMP
nsAbOSXDirectory::Init(const char *aUri)
{
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
if (sObserverCount == 0) {
sObserver = [[ABChangedMonitor alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:(ABChangedMonitor*)sObserver
selector:@selector(ABChanged:)
name:kABDatabaseChangedExternallyNotification
object:nil];
}
++sObserverCount;
nsresult rv = nsAbDirectoryRDFResource::Init(aUri);
NS_ENSURE_SUCCESS(rv, rv);
if (mURINoQuery.Length() > sizeof(NS_ABOSXDIRECTORY_URI_PREFIX)) {
nsCAutoString 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 = PR_TRUE;
AppendToString([card valueForProperty:kABGroupNameProperty], m_DirName);
}
return NS_OK;
}
NS_IMETHODIMP
nsAbOSXDirectory::GetOperations(PRInt32 *aOperations)
{
*aOperations = nsIAbDirectory::opRead |
nsIAbDirectory::opSearch;
return NS_OK;
}
struct nsEnumeratorData
{
NSMutableArray *mCards;
nsIAbDirectory *mDirectory;
nsIAddrBookSession *mSession;
};
PLDHashOperator
Enumerator(nsIAbCardHashKey *aKey, void *aUserArg)
{
nsEnumeratorData *data = NS_STATIC_CAST(nsEnumeratorData*, aUserArg);
nsIAbCard *abCard = aKey->GetCard();
nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(abCard);
const char* uri;
resource->GetValueConst(&uri);
NSString *uid = [NSString stringWithUTF8String:(uri + 21)];
unsigned int i, count = [data->mCards count];
for (i = 0; i < count; ++i) {
if ([[[data->mCards objectAtIndex:i] uniqueId] isEqualToString:uid]) {
[data->mCards removeObjectAtIndex:i];
break;
}
}
if (i == count) {
data->mSession->NotifyDirectoryItemDeleted(data->mDirectory, abCard);
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
}
nsresult
nsAbOSXDirectory::Update()
{
nsresult rv;
nsCOMPtr<nsIAddrBookSession> abSession = do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (mIsQueryURI) {
return NS_OK;
}
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
NSArray *groups, *cards;
if (m_IsMailList) {
ABGroup *group = (ABGroup*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsCAutoString(Substring(mURINoQuery, 21)).get()]];
groups = nil;
cards = [[group members] arrayByAddingObjectsFromArray:[group subgroups]];
}
else {
groups = [addressBook groups];
cards = [[addressBook people] arrayByAddingObjectsFromArray:groups];
}
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:cards];
if (mCardList.IsInitialized()) {
nsEnumeratorData data = { mutableArray, this, abSession };
mCardList.EnumerateEntries(Enumerator, &data);
}
NSEnumerator *enumerator = [mutableArray objectEnumerator];
ABRecord *card;
nsCOMPtr<nsIAbCard> abCard;
while ((card = [enumerator nextObject])) {
rv = ConvertToCard(gRDFService, card, getter_AddRefs(abCard));
NS_ENSURE_SUCCESS(rv, rv);
AssertCard(abSession, abCard);
}
card = (ABRecord*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsCAutoString(Substring(mURINoQuery, 21)).get()]];
NSString * stringValue = [card valueForProperty:kABGroupNameProperty];
if (![stringValue isEqualToString:WrapString(m_DirName)]) {
nsAutoString oldValue(m_DirName);
AssignToString(stringValue, m_DirName);
nsISupports *supports =
NS_ISUPPORTS_CAST(nsAbDirectoryRDFResource*, this);
abSession->NotifyItemPropertyChanged(supports, "DirName",
oldValue.get(), m_DirName.get());
}
if (groups) {
mutableArray = [NSMutableArray arrayWithArray:groups];
nsCOMPtr<nsIAbDirectory> directory;
if (m_AddressList) {
PRUint32 i, count;
m_AddressList->Count(&count);
for (i = 0; i < count; ++i) {
directory = do_QueryElementAt(m_AddressList, i);
nsCOMPtr<nsIAbOSXDirectory> osxDirectory =
do_QueryInterface(directory);
nsCAutoString uri;
osxDirectory->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(abSession, directory);
}
}
}
enumerator = [mutableArray objectEnumerator];
while ((card = [enumerator nextObject])) {
rv = ConvertToGroupResource(gRDFService, [card uniqueId],
getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
AssertDirectory(abSession, directory);
}
}
return NS_OK;
}
nsresult
nsAbOSXDirectory::AssertChildNodes()
{
// Queries and mailing lists can't have childnodes.
if (mIsQueryURI || m_IsMailList) {
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsIAddrBookSession> abSession =
do_GetService(NS_ADDRBOOKSESSION_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
NSArray *groups = [[ABAddressBook sharedAddressBook] groups];
unsigned int i, count = [groups count];
if (count > 0 && !m_AddressList) {
rv = NS_NewISupportsArray(getter_AddRefs(m_AddressList));
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIAbDirectory> directory;
for (i = 0; i < count; ++i) {
rv = ConvertToGroupResource(gRDFService, [[groups objectAtIndex:i] uniqueId],
getter_AddRefs(directory));
NS_ENSURE_SUCCESS(rv, rv);
rv = AssertDirectory(abSession, directory);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
nsAbOSXDirectory::AssertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory)
{
NS_ASSERTION(!m_AddressList || m_AddressList->IndexOf(aDirectory) < 0,
"Replacing?");
nsresult rv;
if (!m_AddressList) {
rv = NS_NewISupportsArray(getter_AddRefs(m_AddressList));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = m_AddressList->AppendElement(aDirectory);
NS_ENSURE_SUCCESS(rv, rv);
return aSession->NotifyDirectoryItemAdded(this, aDirectory);
}
nsresult
nsAbOSXDirectory::AssertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard)
{
NS_ASSERTION(!mCardList.IsInitialized() || !mCardList.GetEntry(aCard),
"Replacing?");
if (!mCardList.IsInitialized() && !mCardList.Init()) {
return NS_ERROR_OUT_OF_MEMORY;
}
mCardList.PutEntry(aCard);
return aSession->NotifyDirectoryItemAdded(this, aCard);
}
nsresult
nsAbOSXDirectory::UnassertDirectory(nsIAddrBookSession *aSession,
nsIAbDirectory *aDirectory)
{
NS_ASSERTION(m_AddressList->IndexOf(aDirectory) >= 0, "Not found?");
nsresult rv = m_AddressList->RemoveElement(aDirectory);
NS_ENSURE_SUCCESS(rv, rv);
return aSession->NotifyDirectoryItemDeleted(this, aDirectory);
}
nsresult
nsAbOSXDirectory::UnassertCard(nsIAddrBookSession *aSession,
nsIAbCard *aCard)
{
NS_ASSERTION(mCardList.GetEntry(aCard), "Not found?");
mCardList.RemoveEntry(aCard);
return aSession->NotifyDirectoryItemDeleted(this, aCard);
}
NS_IMETHODIMP
nsAbOSXDirectory::GetChildNodes(nsISimpleEnumerator **aNodes)
{
NS_ENSURE_ARG_POINTER(aNodes);
// Queries don't have childnodes.
if (mIsQueryURI || !m_AddressList) {
return NS_NewEmptyEnumerator(aNodes);
}
return NS_NewArrayEnumerator(aNodes, m_AddressList);
}
NS_IMETHODIMP
nsAbOSXDirectory::GetChildCards(nsIEnumerator **aCards)
{
NS_ENSURE_ARG_POINTER(aCards);
ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
nsresult rv;
NSArray *cards;
if (mIsQueryURI) {
nsCOMPtr<nsIAbBooleanExpression> expression;
rv = nsAbQueryStringToExpression::Convert(mQueryString.get(),
getter_AddRefs(expression));
NS_ENSURE_SUCCESS(rv, rv);
PRBool canHandle = !m_IsMailList && Search(expression, &cards);
if (!canHandle) {
return FallbackSearch(expression, aCards);
}
}
else {
if (m_IsMailList) {
ABGroup *group = (ABGroup*)[addressBook recordForUniqueId:[NSString stringWithUTF8String:nsCAutoString(Substring(mURINoQuery, 21)).get()]];
cards = [[group members] arrayByAddingObjectsFromArray:[group subgroups]];
}
else {
cards = [[addressBook people] arrayByAddingObjectsFromArray:[addressBook groups]];
}
}
// Fill the results array and update the card list
// Also update the address list and notify any changes.
unsigned int nbCards = [cards count];
if (nbCards > 0) {
if (mCardList.IsInitialized()) {
mCardList.Clear();
}
else if (!mCardList.Init()) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
nsCOMPtr<nsISupportsArray> cardList;
rv = NS_NewISupportsArray(getter_AddRefs(cardList));
NS_ENSURE_SUCCESS(rv, rv);
unsigned int i;
nsCOMPtr<nsIAbCard> card;
for (i = 0; i < nbCards; ++i) {
rv = ConvertToCard(gRDFService, [cards objectAtIndex:i],
getter_AddRefs(card));
NS_ENSURE_SUCCESS(rv, rv);
rv = cardList->AppendElement(card);
NS_ENSURE_SUCCESS(rv, rv);
mCardList.PutEntry(card);
}
return GetEnumerator(cardList, aCards);
}
NS_IMETHODIMP
nsAbOSXDirectory::HasCard(nsIAbCard *aCard, PRBool *aHasCard)
{
NS_ENSURE_ARG_POINTER(aCard);
NS_ENSURE_ARG_POINTER(aHasCard);
*aHasCard = mCardList.IsInitialized() && mCardList.GetEntry(aCard);
return NS_OK;
}
NS_IMETHODIMP
nsAbOSXDirectory::HasDirectory(nsIAbDirectory *aDirectory,
PRBool *aHasDirectory)
{
NS_ENSURE_ARG_POINTER(aDirectory);
NS_ENSURE_ARG_POINTER(aHasDirectory);
*aHasDirectory = m_AddressList && m_AddressList->IndexOf(aDirectory) >= 0;
return NS_OK;
}
nsresult
nsAbOSXDirectory::OnSearchFinished(PRInt32 aResult)
{
return NS_OK;
}
nsresult
nsAbOSXDirectory::OnSearchFoundCard(nsIAbCard *aCard)
{
nsresult rv;
if (!m_AddressList) {
rv = NS_NewISupportsArray(getter_AddRefs(m_AddressList));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!mCardList.IsInitialized() && !mCardList.Init()) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = m_AddressList->AppendElement(aCard);
NS_ENSURE_SUCCESS(rv, rv);
mCardList.PutEntry(aCard);
return NS_OK;
}
nsresult
nsAbOSXDirectory::FallbackSearch(nsIAbBooleanExpression *aExpression,
nsIEnumerator **aCards)
{
nsresult rv;
if (mCardList.IsInitialized())
mCardList.Clear();
else if (!mCardList.Init())
return NS_ERROR_OUT_OF_MEMORY;
if (m_AddressList) {
m_AddressList->Clear();
}
else {
rv = NS_NewISupportsArray(getter_AddRefs(m_AddressList));
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);
// Set the return properties to
// return nsIAbCard interfaces
const char* property = "card:nsIAbCard";
rv = arguments->SetReturnProperties(1, &property);
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(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Set the the query listener
nsCOMPtr<nsIAbDirectoryQueryResultListener> queryListener =
new nsAbDirSearchListener(this);
if (!queryListener)
return NS_ERROR_OUT_OF_MEMORY;
// Get the directory without the query
nsCOMPtr<nsIRDFResource> resource;
rv = gRDFService->GetResource(mURINoQuery, getter_AddRefs(resource));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAbDirectory> directory = do_QueryInterface(resource, &rv);
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(directory);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 context = 0;
rv = queryProxy->DoQuery(arguments, queryListener, -1, 0, &context);
NS_ENSURE_SUCCESS(rv, rv);
return GetEnumerator(m_AddressList, aCards);
}

Просмотреть файл

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAbOSXUtils_h___
#define nsAbOSXUtils_h___
#include <Foundation/NSString.h>
#include "nscore.h"
class nsString;
class nsCString;
class nsAbCardProperty;
NSString *WrapString(const nsString &aString);
void AppendToString(const NSString *aString, nsString &aResult);
void AssignToString(const NSString *aString, nsString &aResult);
void AppendToCString(const NSString *aString, nsCString &aResult);
struct nsAbOSXPropertyMap
{
NSString * const mOSXProperty;
NSString * const mOSXLabel;
NSString * const mOSXKey;
nsString nsAbCardProperty::*mProperty;
const char *mPropertyName;
};
class nsAbOSXUtils
{
public:
static const nsAbOSXPropertyMap kPropertyMap[];
static const PRUint32 kPropertyMapSize;
};
#endif // nsAbOSXUtils_h___

Просмотреть файл

@ -0,0 +1,147 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Peter Van der Beken.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Van der Beken <peterv@propagandism.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAbOSXUtils.h"
#include "nsString.h"
#include "nsAbOSXCard.h"
#include <AddressBook/AddressBook.h>
NSString*
WrapString(const nsString &aString)
{
PRUnichar* chars = NS_CONST_CAST(PRUnichar*, aString.get());
return [NSString stringWithCharacters:chars
length:aString.Length()];
}
void
AppendToString(const NSString *aString, nsString &aResult)
{
if (aString) {
const char *chars = [aString UTF8String];
if (chars) {
AppendUTF8toUTF16(chars, aResult);
}
}
}
void
AssignToString(const NSString *aString, nsString &aResult)
{
if (aString) {
const char *chars = [aString UTF8String];
if (chars) {
CopyUTF8toUTF16(chars, aResult);
}
}
}
void
AppendToCString(const NSString *aString, nsCString &aResult)
{
if (aString) {
const char *chars = [aString UTF8String];
if (chars) {
aResult.Append(chars);
}
}
}
// Some properties can't be easily mapped back and forth.
#define DONT_MAP(moz_name, osx_property, osx_label, osx_key)
#define DEFINE_PROPERTY(moz_name, osx_property, osx_label, osx_key) \
{ osx_property, osx_label, osx_key, &nsAbOSXCard::m_##moz_name, #moz_name },
const nsAbOSXPropertyMap nsAbOSXUtils::kPropertyMap[] = {
DEFINE_PROPERTY(FirstName, kABFirstNameProperty, nil, nil)
DEFINE_PROPERTY(LastName, kABLastNameProperty, nil, nil)
DONT_MAP("DisplayName", nil, nil, nil)
DEFINE_PROPERTY(PhoneticFirstName, kABFirstNamePhoneticProperty, nil, nil)
DEFINE_PROPERTY(PhoneticLastName, kABLastNamePhoneticProperty, nil, nil)
DEFINE_PROPERTY(NickName, kABNicknameProperty, nil, nil)
DONT_MAP(PrimaryEmail, kABEmailProperty, nil, nil)
DONT_MAP(SecondEmail, kABEmailProperty, nil, nil)
DEFINE_PROPERTY(WorkPhone, kABPhoneProperty, kABPhoneWorkLabel, nil)
DEFINE_PROPERTY(HomePhone, kABPhoneProperty, kABPhoneHomeLabel, nil)
DEFINE_PROPERTY(FaxNumber, kABPhoneProperty, kABPhoneWorkFAXLabel, nil)
DEFINE_PROPERTY(PagerNumber, kABPhoneProperty, kABPhonePagerLabel, nil)
DEFINE_PROPERTY(CellularNumber, kABPhoneProperty, kABPhoneMobileLabel, nil)
DEFINE_PROPERTY(HomeAddress, kABAddressProperty, kABAddressHomeLabel,
kABAddressStreetKey)
DEFINE_PROPERTY(HomeCity, kABAddressProperty, kABAddressHomeLabel,
kABAddressCityKey)
DEFINE_PROPERTY(HomeState, kABAddressProperty, kABAddressHomeLabel,
kABAddressStateKey)
DEFINE_PROPERTY(HomeZipCode, kABAddressProperty, kABAddressHomeLabel,
kABAddressZIPKey)
DEFINE_PROPERTY(HomeCountry, kABAddressProperty, kABAddressHomeLabel,
kABAddressCountryKey)
DEFINE_PROPERTY(WorkAddress, kABAddressProperty, kABAddressWorkLabel,
kABAddressStreetKey)
DEFINE_PROPERTY(WorkCity, kABAddressProperty, kABAddressWorkLabel,
kABAddressCityKey)
DEFINE_PROPERTY(WorkState, kABAddressProperty, kABAddressWorkLabel,
kABAddressStateKey)
DEFINE_PROPERTY(WorkZipCode, kABAddressProperty, kABAddressWorkLabel,
kABAddressZIPKey)
DEFINE_PROPERTY(WorkCountry, kABAddressProperty, kABAddressWorkLabel,
kABAddressCountryKey)
DEFINE_PROPERTY(JobTitle, kABJobTitleProperty, nil, nil)
DEFINE_PROPERTY(Department, kABDepartmentProperty, nil, nil)
DEFINE_PROPERTY(Company, kABOrganizationProperty, nil, nil)
DONT_MAP(_AimScreenName, kABAIMInstantProperty, nil, nil)
DEFINE_PROPERTY(WebPage1, kABHomePageProperty, nil, nil)
DONT_MAP(WebPage2, kABHomePageProperty, nil, nil)
DONT_MAP(BirthYear, "birthyear", nil, nil)
DONT_MAP(BirthMonth, "birthmonth", nil, nil)
DONT_MAP(BirthDay, "birthday", nil, nil)
DONT_MAP(Custom1, "custom1", nil, nil)
DONT_MAP(Custom2, "custom2", nil, nil)
DONT_MAP(Custom3, "custom3", nil, nil)
DONT_MAP(Custom4, "custom4", nil, nil)
DEFINE_PROPERTY(Note, kABNoteProperty, nil, nil)
DONT_MAP("PreferMailFormat", nil, nil, nil)
DONT_MAP("LastModifiedDate", modifytimestamp, nil, nil)
};
const PRUint32 nsAbOSXUtils::kPropertyMapSize =
NS_ARRAY_LENGTH(nsAbOSXUtils::kPropertyMap);