32#include <Carbon/Carbon.h>
33#include <AddressBook/ABAddressBookC.h>
35#include <com/sun/star/util/DateTime.hpp>
42void manageDuplicateHeaders(
macabfield **_headerNames,
const sal_Int32 _length)
50 for(i = _length-1;
i >= 0;
i--)
53 for( j = i-1; j >= 0; j--)
55 if(CFEqual(_headerNames[i]->
value, _headerNames[j]->
value))
66 CFRelease(_headerNames[i]->
value);
67 newName +=
" (" + OUString::number(count) +
")";
75MacabRecords::MacabRecords(
const ABAddressBookRef _addressBook,
MacabHeader *_header,
MacabRecord **_records, sal_Int32 _numRecords)
76 : recordsSize(_numRecords), currentRecord(_numRecords), recordType(kABPersonRecordType),
77 header(_header), records(_records), addressBook(_addressBook)
94 : recordsSize(_copy->recordsSize), currentRecord(0), recordType(kABPersonRecordType),
95 header(nullptr), records(new
MacabRecord *[recordsSize]), addressBook(_copy->addressBook),
105 : recordsSize(0), currentRecord(0), recordType(kABPersonRecordType),
106 header(nullptr), records(nullptr), addressBook(_addressBook)
138 CFArrayRef allRecords;
139 if(CFStringCompare(
recordType, kABPersonRecordType, 0) == kCFCompareEqualTo)
146 recordsSize =
static_cast<sal_Int32
>(CFArrayGetCount(allRecords));
155 record =
const_cast<ABRecordRef
>(CFArrayGetValueAtIndex(allRecords,
i));
160 CFRelease(allRecords);
212 oldRecord =
records[_location];
213 records[_location] = _newRecord;
240 if(_columnNumber < 0 || _columnNumber >= record->
getSize())
243 return record->
get(_columnNumber);
253 if(columnNumber == -1)
256 return getField(_recordNumber, columnNumber);
293 {CFNumberGetTypeID(), kABIntegerProperty},
294 {CFStringGetTypeID(), kABStringProperty},
295 {CFDateGetTypeID(), kABDateProperty},
296 {CFArrayGetTypeID(), kABArrayProperty},
297 {CFDictionaryGetTypeID(), kABDictionaryProperty},
298 {CFDataGetTypeID(), kABDataProperty}};
309 kABTitleProperty, kABFirstNameProperty, kABLastNameProperty, kABOrganizationProperty,
310 kABAddressProperty, kABPhoneProperty, kABEmailProperty};
338 CFArrayRef allProperties = ABCopyArrayOfPropertiesForRecordType(
addressBook, _recordType);
339 CFStringRef *nonRequiredProperties;
340 sal_Int32 numRecords =
static_cast<sal_Int32
>(CFArrayGetCount(_records));
341 sal_Int32 numProperties =
static_cast<sal_Int32
>(CFArrayGetCount(allProperties));
368 nonRequiredProperties =
new CFStringRef[numNonRequiredProperties];
371 bFoundRequiredProperties[
i] =
false;
374 for(sal_Int32
i = 0;
i < numProperties;
i++)
376 bool bFoundProperty =
false;
377 property =
static_cast<CFStringRef
>(CFArrayGetValueAtIndex(allProperties,
i));
382 bFoundProperty =
true;
383 bFoundRequiredProperties[j] =
true;
391 if(k == numNonRequiredProperties)
396 nonRequiredProperties[k] =
property;
404 OSL_ENSURE(k == numNonRequiredProperties,
"MacabRecords::createHeaderForRecordType: Found an unexpected number of non-required properties");
409 if(bFoundRequiredProperties[
i])
422 for(sal_Int32 j = 0; j < numRecords; j++)
424 record =
const_cast<ABRecordRef
>(CFArrayGetValueAtIndex(_records, j));
426 if(headerDataForProperty !=
nullptr)
428 (*lcl_header) += headerDataForProperty;
429 delete headerDataForProperty;
436 OSL_FAIL(OString(
"MacabRecords::createHeaderForRecordType: could not find required property: " +
442 for(sal_Int32
i = 0;
i < numRecords;
i++)
444 record =
const_cast<ABRecordRef
>(CFArrayGetValueAtIndex(_records,
i));
446 for(sal_Int32 j = 0; j < numNonRequiredProperties; j++)
448 property = nonRequiredProperties[j];
450 if(headerDataForProperty !=
nullptr)
452 (*nonRequiredHeader) += headerDataForProperty;
453 delete headerDataForProperty;
460 (*lcl_header) += nonRequiredHeader;
461 delete nonRequiredHeader;
463 CFRelease(allProperties);
464 delete [] nonRequiredProperties;
477 CFStringRef localizedPropertyName;
478 CFTypeRef propertyValue;
479 ABPropertyType propertyType;
483 propertyValue = ABRecordCopyValue(_record,_propertyName);
484 if(propertyValue ==
nullptr && !_isPropertyRequired)
487 propertyType = ABTypeOfProperty(
addressBook, _recordType, _propertyName);
488 localizedPropertyName = ABCopyLocalizedPropertyOrLabel(_propertyName);
492 if(propertyValue !=
nullptr)
493 CFRelease(propertyValue);
508 switch(_propertyType)
511 case kABStringProperty:
512 case kABRealProperty:
513 case kABIntegerProperty:
514 case kABDateProperty:
518 headerNames[0]->
value = _propertyName;
519 headerNames[0]->
type = _propertyType;
523 case kABMultiIntegerProperty:
524 case kABMultiDateProperty:
525 case kABMultiStringProperty:
526 case kABMultiRealProperty:
527 case kABMultiDataProperty:
531 if(_propertyValue !=
nullptr)
535 sal_Int32 multiLength = ABMultiValueCount(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)));
536 CFStringRef multiLabel, localizedMultiLabel;
537 OUString multiLabelString;
538 OUString multiPropertyString;
539 OUString headerNameString;
540 ABPropertyType multiType =
static_cast<ABPropertyType
>(ABMultiValuePropertyType(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue))) - 0x100);
549 for(
i = 0;
i < multiLength;
i++)
551 multiLabel = ABMultiValueCopyLabelAtIndex(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)),
i);
552 localizedMultiLabel = ABCopyLocalizedPropertyOrLabel(multiLabel);
554 CFRelease(multiLabel);
555 CFRelease(localizedMultiLabel);
556 headerNameString = multiPropertyString +
": " +
fixLabel(multiLabelString);
559 headerNames[
i]->
type = multiType;
565 case kABMultiArrayProperty:
566 case kABMultiDictionaryProperty:
570 if(_propertyValue !=
nullptr)
575 sal_Int32 multiLengthFirstLevel = ABMultiValueCount(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)));
582 sal_Int32 multiLengthSecondLevel = 0;
584 CFStringRef multiLabel, localizedMultiLabel;
585 CFTypeRef multiValue;
586 OUString multiLabelString;
587 OUString multiPropertyString;
588 std::vector<std::unique_ptr<MacabHeader>> multiHeaders;
589 ABPropertyType multiType =
static_cast<ABPropertyType
>(ABMultiValuePropertyType(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue))) - 0x100);
599 for(
i = 0;
i < multiLengthFirstLevel;
i++)
602 multiLabel = ABMultiValueCopyLabelAtIndex(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)),
i);
603 multiValue = ABMultiValueCopyValueAtIndex(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)),
i);
604 std::unique_ptr<MacabHeader> hdr;
605 if(multiValue && multiLabel)
607 localizedMultiLabel = ABCopyLocalizedPropertyOrLabel(multiLabel);
609 CFRelease(multiLabel);
610 CFRelease(localizedMultiLabel);
614 hdr = std::make_unique<MacabHeader>();
615 multiLengthSecondLevel += hdr->getSize();
619 hdr = std::make_unique<MacabHeader>();
622 CFRelease(multiValue);
624 CFRelease(multiLabel);
625 multiHeaders.push_back(std::move(hdr));
633 length = multiLengthSecondLevel;
634 headerNames =
new macabfield *[multiLengthSecondLevel];
636 for(
i = 0, j = 0, k = 0;
i < multiLengthSecondLevel;
i++,k++)
638 while(multiHeaders[j]->getSize() == k)
644 headerNames[
i] = multiHeaders[j]->copy(k);
650 case kABDictionaryProperty:
654 if(_propertyValue !=
nullptr)
657 sal_Int32 numRecords =
static_cast<sal_Int32
>(CFDictionaryGetCount(
static_cast<CFDictionaryRef
>(_propertyValue)));
663 CFStringRef *dictKeys;
664 CFTypeRef *dictValues;
667 OUString dictKeyString, propertyNameString;
668 ABPropertyType dictType;
670 OUString dictLabelString;
671 CFStringRef dictLabel, localizedDictKey;
674 dictKeys =
static_cast<CFStringRef *
>(malloc(
sizeof(CFStringRef)*numRecords));
675 dictValues =
static_cast<CFTypeRef *
>(malloc(
sizeof(CFTypeRef)*numRecords));
676 CFDictionaryGetKeysAndValues(
static_cast<CFDictionaryRef
>(_propertyValue),
reinterpret_cast<const void **
>(dictKeys), dictValues);
690 for(
i = 0;
i < numRecords;
i++)
693 localizedDictKey = ABCopyLocalizedPropertyOrLabel(dictKeys[
i]);
695 dictLabelString = propertyNameString +
": " +
fixLabel(dictKeyString);
701 CFRelease(dictLabel);
702 CFRelease(localizedDictKey);
710 for(
i = 0, j = 0, k = 0;
i <
length;
i++,k++)
712 while(dictHeaders[j]->getSize() == k)
718 headerNames[
i] = dictHeaders[j]->
copy(k);
721 for(
i = 0;
i < numRecords;
i++)
722 delete dictHeaders[
i];
724 delete [] dictHeaders;
731 case kABArrayProperty:
735 if(_propertyValue !=
nullptr)
737 sal_Int32 arrLength =
static_cast<sal_Int32
>(CFArrayGetCount(
static_cast<CFArrayRef
>(_propertyValue)));
740 ABPropertyType arrType;
741 std::vector<std::unique_ptr<MacabHeader>> arrHeaders;
743 OUString arrLabelString;
744 CFStringRef arrLabel;
756 for(
i = 0;
i < arrLength;
i++)
758 arrValue = CFArrayGetValueAtIndex(
static_cast<CFArrayRef
>(_propertyValue),
i);
760 arrLabelString = propertyNameString + OUString::number(
i);
764 hdr = std::make_unique<MacabHeader>();
767 arrHeaders.push_back(std::move(hdr));
771 for(
i = 0, j = 0, k = 0;
i <
length;
i++,k++)
773 while(arrHeaders[j]->getSize() == k)
779 headerNames[
i] = arrHeaders[j]->copy(k);
797 manageDuplicateHeaders(headerNames,
length);
800 delete headerNames[
i];
801 delete [] headerNames;
823 CFArrayRef recordProperties = ABCopyArrayOfPropertiesForRecordType(
addressBook, _recordType);
824 sal_Int32 numProperties =
static_cast<sal_Int32
>(CFArrayGetCount(recordProperties));
828 CFTypeRef propertyValue;
829 ABPropertyType propertyType;
831 CFStringRef propertyName, localizedPropertyName;
832 OUString propertyNameString;
833 for(
i = 0;
i < numProperties;
i++)
835 propertyName =
static_cast<CFStringRef
>(CFArrayGetValueAtIndex(recordProperties,
i));
836 localizedPropertyName = ABCopyLocalizedPropertyOrLabel(propertyName);
838 CFRelease(localizedPropertyName);
841 propertyValue = ABRecordCopyValue(_abrecord,propertyName);
842 if(propertyValue !=
nullptr)
844 propertyType = ABTypeOfProperty(
addressBook, _recordType, propertyName);
845 if(propertyType != kABErrorInProperty)
848 CFRelease(propertyValue);
851 CFRelease(recordProperties);
863 CFTypeID cf_type = CFGetTypeID(_propertyValue);
866 if(ab_type != kABErrorInProperty)
877 if(_propertyValue ==
nullptr)
881 switch(_propertyType)
884 case kABStringProperty:
885 case kABRealProperty:
886 case kABIntegerProperty:
887 case kABDateProperty:
907 bool bPlaced =
false;
916 if(columnNumber != -1)
919 if(_abrecord->
get(columnNumber) !=
nullptr)
923 columnName = _propertyName +
" (" + OUString::number(
i) +
")";
929 _abrecord->
insertAtColumn(_propertyValue, _propertyType, columnNumber);
937 case kABArrayProperty:
943 sal_Int32 arrLength =
static_cast<sal_Int32
>(CFArrayGetCount(
static_cast<CFArrayRef
>(_propertyValue)));
945 OUString newPropertyName;
948 for(
i = 0;
i < arrLength;
i++)
950 const void *arrValue = CFArrayGetValueAtIndex(
static_cast<CFArrayRef
>(_propertyValue),
i);
951 newPropertyName = _propertyName + OUString::number(
i);
960 case kABDictionaryProperty:
972 sal_Int32 numRecords =
static_cast<sal_Int32
>(CFDictionaryGetCount(
static_cast<CFDictionaryRef
>(_propertyValue)));
973 OUString dictKeyString;
975 OUString newPropertyName;
981 CFStringRef *dictKeys;
982 CFStringRef localizedDictKey;
983 CFTypeRef *dictValues;
984 dictKeys =
static_cast<CFStringRef *
>(malloc(
sizeof(CFStringRef)*numRecords));
985 dictValues =
static_cast<CFTypeRef *
>(malloc(
sizeof(CFTypeRef)*numRecords));
986 CFDictionaryGetKeysAndValues(
static_cast<CFDictionaryRef
>(_propertyValue),
reinterpret_cast<const void **
>(dictKeys), dictValues);
989 for(
i = 0;
i < numRecords;
i++)
991 localizedDictKey = ABCopyLocalizedPropertyOrLabel(dictKeys[
i]);
993 CFRelease(localizedDictKey);
994 newPropertyName = _propertyName +
": " +
fixLabel(dictKeyString);
1004 case kABMultiIntegerProperty:
1005 case kABMultiDateProperty:
1006 case kABMultiStringProperty:
1007 case kABMultiRealProperty:
1008 case kABMultiDataProperty:
1009 case kABMultiDictionaryProperty:
1010 case kABMultiArrayProperty:
1022 sal_Int32 multiLength = ABMultiValueCount(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)));
1023 CFStringRef multiLabel, localizedMultiLabel;
1024 CFTypeRef multiValue;
1025 OUString multiLabelString, newPropertyName;
1026 ABPropertyType multiType =
static_cast<ABPropertyType
>(ABMultiValuePropertyType(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue))) - 0x100);
1029 for(
i = 0;
i < multiLength;
i++)
1032 multiLabel = ABMultiValueCopyLabelAtIndex(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)),
i);
1033 multiValue = ABMultiValueCopyValueAtIndex(
static_cast<ABMutableMultiValueRef
>(
const_cast<void *
>(_propertyValue)),
i);
1035 localizedMultiLabel = ABCopyLocalizedPropertyOrLabel(multiLabel);
1037 newPropertyName = _propertyName +
": " +
fixLabel(multiLabelString);
1041 CFRelease(multiLabel);
1042 CFRelease(localizedMultiLabel);
1043 CFRelease(multiValue);
1049 case kABErrorInProperty:
1050 case kABDataProperty:
1078 return static_cast<ABPropertyType
>(
i.ab);
1081 return kABErrorInProperty;
1130 return records->getRecord(
id);
constexpr sal_Int8 header[]
void insertAtColumn(CFTypeRef _value, ABPropertyType _type, const sal_Int32 _column)
macabfield * get(const sal_Int32 i) const
sal_Int32 getSize() const
macabfield * copy(const sal_Int32 i) const
bool operator!=(const sal_Int32 i) const
bool operator==(const sal_Int32 i) const
iterator & operator=(MacabRecords *_records)
MacabRecord * operator*() const
void bootstrap_CF_types()
void bootstrap_requiredProperties()
OUString const & getName() const
MacabRecords(const ABAddressBookRef _addressBook, MacabHeader *_header, MacabRecord **_records, sal_Int32 _numRecords)
MacabRecord * createMacabRecord(const ABRecordRef _abrecord, const MacabHeader *_header, const CFStringRef _recordType) const
void swap(const sal_Int32 _id1, const sal_Int32 _id2)
void setName(const OUString &_sName)
std::vector< lcl_CFType > lcl_CFTypes
void insertPropertyIntoMacabRecord(MacabRecord *_abrecord, const MacabHeader *_header, const OUString &_propertyName, const CFTypeRef _propertyValue) const
void setHeader(MacabHeader *_header)
sal_Int32 getFieldNumber(std::u16string_view _columnName) const
macabfield * getField(const sal_Int32 _recordNumber, const sal_Int32 _columnNumber) const
ABAddressBookRef addressBook
MacabHeader * getHeader() const
MacabHeader * createHeaderForRecordType(const CFArrayRef _records, const CFStringRef _recordType) const
MacabRecord * insertRecord(MacabRecord *_newRecord, const sal_Int32 _location)
MacabHeader * createHeaderForProperty(const ABRecordRef _record, const CFStringRef _propertyName, const CFStringRef _recordType, const bool _isPropertyRequired) const
ABPropertyType getABTypeFromCFType(const CFTypeID cf_type) const
MacabRecord * getRecord(const sal_Int32 _location) const
std::vector< CFStringRef > requiredProperties
OUString fixLabel(const OUString &_originalLabel)
CFStringRef OUStringToCFString(const OUString &aString)
OUString CFStringToOUString(const CFStringRef sOrig)
OUString newName(std::u16string_view aNewPrefix, std::u16string_view aOldPrefix, std::u16string_view old_Name)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)