port to iPhone: lots of hacks and debug output, none of the multiprops supported yet (use unknown format in API)
git-svn-id: https://zeitsenke.de/svn/SyncEvolution/trunk@399 15ad00c4-1369-45f4-8270-35d70d36bdcd
This commit is contained in:
parent
691090fbcc
commit
4aa5372687
16
HACKING
16
HACKING
|
@ -153,3 +153,19 @@ that address book syncing uses the default libraries):
|
|||
apt-cache showpkg libecal-dev libedata-cal-dev
|
||||
ver=1.4.1-0zoh4; for i in libecal-dev libecal libedata-cal libedata-cal-dev; do wget http://maemo.o-hand.com/packages/mistral/${i}_${ver}_armel.deb; done
|
||||
dpkg --force-depends -i *.deb
|
||||
|
||||
- compiling for iPhone:
|
||||
Requires iPhone toolchain and libcurl, ideally configured as small as possible
|
||||
and statically (to avoid packaging problems):
|
||||
./configure --prefix=/usr/local/iphone --host=arm-apple-darwin --disable-shared \
|
||||
--disable-crypto-auth --without-gnutls --without-ssl --without-zlib \
|
||||
--without-libssh2 --disable-ipv6 --disable-manual --disable-telnet \
|
||||
--disable-tftp --disable-ldap --disable-file --disable-ftp
|
||||
manually set HAVE_POSIX_STRERROR_R in lib/config.h
|
||||
|
||||
Potential problems with toolchain:
|
||||
std++ not found: ln -s libstdc++.6.dylib /usr/local/iphone-filesystem/usr/lib/libstdc++.dylib
|
||||
AddressBook framework must be added to iphone-dev/include/install-headers.sh.in
|
||||
|
||||
Compile with curl-config in the PATH:
|
||||
PATH=/usr/local/iphone/bin/:$PATH ~/projects/sync4jevolution/configure --host=arm-apple-darwin --with-sync4j-src=/home/patrick/projects/native CXXFLAGS=-g --disable-ecal --disable-ebook --enable-addressbook
|
15
configure.in
15
configure.in
|
@ -222,6 +222,7 @@ AC_SUBST(SQLITE_LIBS)
|
|||
|
||||
dnl hard-coded settings for Mac OS X AddressBook
|
||||
ADDRESSBOOK_CFLAGS=
|
||||
|
||||
ADDRESSBOOK_LIBS="-framework AddressBook -framework CoreFoundation"
|
||||
AC_SUBST(ADDRESSBOOK_CFLAGS)
|
||||
AC_SUBST(ADDRESSBOOK_LIBS)
|
||||
|
@ -285,9 +286,6 @@ PKG_CHECK_MODULES(GLIB, "glib-2.0", GLIBFOUND=yes, GLIBFOUND=no)
|
|||
if test "x${GLIBFOUND}" = "xno"; then
|
||||
PKG_CHECK_MODULES(GLIB, "glib", GLIBFOUND=yes, GLIBFOUND=no)
|
||||
fi
|
||||
if test "x${GLIBFOUND}" = "xyes"; then
|
||||
AC_DEFINE(HAVE_GLIB, 1, [glib found])
|
||||
fi
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
|
@ -310,6 +308,17 @@ if test "$enable_addressbook" == "yes"; then
|
|||
SYNCEVOLUTION_MODULES="$SYNCEVOLUTION_MODULES syncaddressbook.la"
|
||||
fi
|
||||
|
||||
dnl glib initialization is done only for libebook and libecal, not needed
|
||||
dnl otherwise even if found
|
||||
if test "$enable_ebook" != "yes" && test "$enable_ecal" != "yes"; then
|
||||
GLIB_CFLAGS=
|
||||
GLIB_LIBS=
|
||||
else
|
||||
if test "x${GLIBFOUND}" = "xyes"; then
|
||||
AC_DEFINE(HAVE_GLIB, 1, [glib found])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl figure out whether we link all code statically or as modules
|
||||
if test "$enable_shared" == "yes"; then
|
||||
SYNCEVOLUTION_LTLIBRARIES="$SYNCEVOLUTION_MODULES"
|
||||
|
|
|
@ -19,10 +19,17 @@
|
|||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
/** constants missing from AddressBook framework on iPhone */
|
||||
/**
|
||||
* constants missing from AddressBook framework on iPhone: use strings
|
||||
* as found in SQLite database on iPhone
|
||||
*
|
||||
* kABTitleProperty is also missing, but the ABRecord constants which
|
||||
* are CFStrings on Mac OS seem to be numeric constants on the iPhone so
|
||||
* we cannot guess it might be (if it exists at all), so not supported.
|
||||
*/
|
||||
|
||||
#ifdef __arm__
|
||||
CFStringRef kABCAIMInstantProperty;
|
||||
// CFStringRef kABCAIMInstantProperty;
|
||||
CFStringRef kABCAddressCityKey;
|
||||
CFStringRef kABCAddressCountryKey;
|
||||
CFStringRef kABCAddressHomeLabel;
|
||||
|
@ -34,14 +41,14 @@ CFStringRef kABCAssistantLabel;
|
|||
CFStringRef kABCEmailHomeLabel;
|
||||
CFStringRef kABCEmailWorkLabel;
|
||||
CFStringRef kABCHomePageLabel;
|
||||
CFStringRef kABCHomePageProperty;
|
||||
CFStringRef kABCICQInstantProperty;
|
||||
// CFStringRef kABCHomePageProperty;
|
||||
// CFStringRef kABCICQInstantProperty;
|
||||
CFStringRef kABCJabberHomeLabel;
|
||||
CFStringRef kABCJabberInstantProperty;
|
||||
// CFStringRef kABCJabberInstantProperty;
|
||||
CFStringRef kABCJabberWorkLabel;
|
||||
CFStringRef kABCMSNInstantProperty;
|
||||
// CFStringRef kABCMSNInstantProperty;
|
||||
CFStringRef kABCManagerLabel;
|
||||
CFStringRef kABCOtherDatesProperty;
|
||||
// CFStringRef kABCOtherDatesProperty;
|
||||
CFStringRef kABCPhoneHomeFAXLabel;
|
||||
CFStringRef kABCPhoneHomeLabel;
|
||||
CFStringRef kABCPhoneMainLabel;
|
||||
|
@ -50,16 +57,16 @@ CFStringRef kABCPhonePagerLabel;
|
|||
CFStringRef kABCPhoneWorkFAXLabel;
|
||||
CFStringRef kABCPhoneWorkLabel;
|
||||
CFStringRef kABCSpouseLabel;
|
||||
CFStringRef kABCTitleProperty;
|
||||
CFStringRef kABCURLsProperty;
|
||||
CFStringRef kABCYahooInstantProperty;
|
||||
// CFStringRef kABCTitleProperty;
|
||||
// CFStringRef kABCURLsProperty;
|
||||
// CFStringRef kABCYahooInstantProperty;
|
||||
#endif
|
||||
|
||||
class constants {
|
||||
public:
|
||||
constants() {
|
||||
#ifdef __arm__
|
||||
kABCAIMInstantProperty = CFStringCreateWithCString(NULL, "AIMInstant", kCFStringEncodingUTF8);
|
||||
// kABCAIMInstantProperty = CFStringCreateWithCString(NULL, "AIMInstant", kCFStringEncodingUTF8);
|
||||
kABCAddressCityKey = CFStringCreateWithCString(NULL, "City", kCFStringEncodingUTF8);
|
||||
kABCAddressCountryKey = CFStringCreateWithCString(NULL, "Country", kCFStringEncodingUTF8);
|
||||
kABCAddressHomeLabel = CFStringCreateWithCString(NULL, "_$!<Home>!$_", kCFStringEncodingUTF8);
|
||||
|
@ -71,14 +78,14 @@ public:
|
|||
kABCEmailHomeLabel = CFStringCreateWithCString(NULL, "_$!<Home>!$_", kCFStringEncodingUTF8);
|
||||
kABCEmailWorkLabel = CFStringCreateWithCString(NULL, "_$!<Work>!$_", kCFStringEncodingUTF8);
|
||||
kABCHomePageLabel = CFStringCreateWithCString(NULL, "_$!<HomePage>!$_", kCFStringEncodingUTF8);
|
||||
kABCHomePageProperty = CFStringCreateWithCString(NULL, "HomePage", kCFStringEncodingUTF8);
|
||||
kABCICQInstantProperty = CFStringCreateWithCString(NULL, "ICQInstant", kCFStringEncodingUTF8);
|
||||
// kABCHomePageProperty = CFStringCreateWithCString(NULL, "HomePage", kCFStringEncodingUTF8);
|
||||
// kABCICQInstantProperty = CFStringCreateWithCString(NULL, "ICQInstant", kCFStringEncodingUTF8);
|
||||
kABCJabberHomeLabel = CFStringCreateWithCString(NULL, "_$!<Home>!$_", kCFStringEncodingUTF8);
|
||||
kABCJabberInstantProperty = CFStringCreateWithCString(NULL, "JabberInstant", kCFStringEncodingUTF8);
|
||||
// kABCJabberInstantProperty = CFStringCreateWithCString(NULL, "JabberInstant", kCFStringEncodingUTF8);
|
||||
kABCJabberWorkLabel = CFStringCreateWithCString(NULL, "_$!<Work>!$_", kCFStringEncodingUTF8);
|
||||
kABCMSNInstantProperty = CFStringCreateWithCString(NULL, "MSNInstant", kCFStringEncodingUTF8);
|
||||
// kABCMSNInstantProperty = CFStringCreateWithCString(NULL, "MSNInstant", kCFStringEncodingUTF8);
|
||||
kABCManagerLabel = CFStringCreateWithCString(NULL, "_$!<Manager>!$_", kCFStringEncodingUTF8);
|
||||
kABCOtherDatesProperty = CFStringCreateWithCString(NULL, "ABDate", kCFStringEncodingUTF8);
|
||||
// kABCOtherDatesProperty = CFStringCreateWithCString(NULL, "ABDate", kCFStringEncodingUTF8);
|
||||
kABCPhoneHomeFAXLabel = CFStringCreateWithCString(NULL, "_$!<HomeFAX>!$_", kCFStringEncodingUTF8);
|
||||
kABCPhoneHomeLabel = CFStringCreateWithCString(NULL, "_$!<Home>!$_", kCFStringEncodingUTF8);
|
||||
kABCPhoneMainLabel = CFStringCreateWithCString(NULL, "_$!<Main>!$_", kCFStringEncodingUTF8);
|
||||
|
@ -87,9 +94,9 @@ public:
|
|||
kABCPhoneWorkFAXLabel = CFStringCreateWithCString(NULL, "_$!<WorkFAX>!$_", kCFStringEncodingUTF8);
|
||||
kABCPhoneWorkLabel = CFStringCreateWithCString(NULL, "_$!<Work>!$_", kCFStringEncodingUTF8);
|
||||
kABCSpouseLabel = CFStringCreateWithCString(NULL, "_$!<Spouse>!$_", kCFStringEncodingUTF8);
|
||||
kABCTitleProperty = CFStringCreateWithCString(NULL, "Title", kCFStringEncodingUTF8);
|
||||
kABCURLsProperty = CFStringCreateWithCString(NULL, "URLs", kCFStringEncodingUTF8);
|
||||
kABCYahooInstantProperty = CFStringCreateWithCString(NULL, "YahooInstant", kCFStringEncodingUTF8);
|
||||
// kABCTitleProperty = CFStringCreateWithCString(NULL, "Title", kCFStringEncodingUTF8);
|
||||
// kABCURLsProperty = CFStringCreateWithCString(NULL, "URLs", kCFStringEncodingUTF8);
|
||||
// kABCYahooInstantProperty = CFStringCreateWithCString(NULL, "YahooInstant", kCFStringEncodingUTF8);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
@ -122,7 +129,7 @@ public:
|
|||
printconstant(kABPhoneWorkFAXLabel);
|
||||
printconstant(kABPhoneWorkLabel);
|
||||
printconstant(kABSpouseLabel);
|
||||
printconstant(kABTitleProperty);
|
||||
// printconstant(kABTitleProperty);
|
||||
printconstant(kABURLsProperty);
|
||||
printconstant(kABYahooInstantProperty);
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,77 @@ using namespace std;
|
|||
|
||||
#ifdef ENABLE_ADDRESSBOOK
|
||||
|
||||
#ifdef __arm__
|
||||
// On the iPhone the API is different, but the changes mostly seem to
|
||||
// consist of renames. Some constants and the vcard conversion
|
||||
// functions are missing. Unique IDs are integers, not string references.
|
||||
|
||||
# define ABAddRecord ABCAddRecord
|
||||
# define ABCopyArrayOfAllPeople ABCCopyArrayOfAllPeople
|
||||
# define ABGetSharedAddressBook ABCGetSharedAddressBook
|
||||
# define ABMultiValueAdd ABCMultiValueAdd
|
||||
# define ABMultiValueCopyLabelAtIndex ABCMultiValueCopyLabelAtIndex
|
||||
# define ABMultiValueCopyValueAtIndex ABCMultiValueCopyValueAtIndex
|
||||
# define ABMultiValueCount ABCMultiValueGetCount
|
||||
# define ABMultiValueCreateMutable ABCMultiValueCreateMutable
|
||||
# define ABPersonCopyImageData ABCPersonCopyImageData
|
||||
# define PersonCreateWrapper(_addressbook) ABCPersonCreateNewPerson(_addressbook)
|
||||
# define ABPersonSetImageData ABCPersonSetImageData
|
||||
# define ABRecordCopyValue ABCRecordCopyValue
|
||||
# define ABRecordRemoveValue ABCRecordRemoveValue
|
||||
# define ABRecordSetValue ABCRecordSetValue
|
||||
# define ABRemoveRecord ABCRemoveRecord
|
||||
# define ABSave ABCSave
|
||||
# define kABAIMInstantProperty kABCAIMInstantProperty
|
||||
# define kABAddressCityKey kABCAddressCityKey
|
||||
# define kABAddressCountryKey kABCAddressCountryKey
|
||||
# define kABAddressHomeLabel kABCAddressHomeLabel
|
||||
# define kABAddressProperty kABCAddressProperty
|
||||
# define kABAddressStateKey kABCAddressStateKey
|
||||
# define kABAddressStreetKey kABCAddressStreetKey
|
||||
# define kABAddressWorkLabel kABCAddressWorkLabel
|
||||
# define kABAddressZIPKey kABCAddressZIPKey
|
||||
# define kABAssistantLabel kABCAssistantLabel
|
||||
# define kABBirthdayProperty kABCBirthdayProperty
|
||||
# define kABCreationDateProperty kABCCreationDateProperty
|
||||
# define kABDepartmentProperty kABCDepartmentProperty
|
||||
# define kABEmailHomeLabel kABCEmailHomeLabel
|
||||
# define kABEmailProperty kABCEmailProperty
|
||||
# define kABEmailWorkLabel kABCEmailWorkLabel
|
||||
# define kABFirstNameProperty kABCFirstNameProperty
|
||||
# define kABHomePageLabel kABCHomePageLabel
|
||||
/* # define kABHomePageProperty kABCHomePageProperty */
|
||||
# define kABICQInstantProperty kABCICQInstantProperty
|
||||
# define kABJabberHomeLabel kABCJabberHomeLabel
|
||||
# define kABJabberInstantProperty kABCJabberInstantProperty
|
||||
# define kABJabberWorkLabel kABCJabberWorkLabel
|
||||
# define kABJobTitleProperty kABCJobTitleProperty
|
||||
# define kABLastNameProperty kABCLastNameProperty
|
||||
# define kABMSNInstantProperty kABCMSNInstantProperty
|
||||
# define kABManagerLabel kABCManagerLabel
|
||||
# define kABMiddleNameProperty kABCMiddleNameProperty
|
||||
# define kABModificationDateProperty kABCModificationDateProperty
|
||||
# define kABNicknameProperty kABCNicknameProperty
|
||||
# define kABNoteProperty kABCNoteProperty
|
||||
# define kABOrganizationProperty kABCOrganizationProperty
|
||||
# define kABOtherDatesProperty kABCOtherDatesProperty
|
||||
# define kABPhoneHomeFAXLabel kABCPhoneHomeFAXLabel
|
||||
# define kABPhoneHomeLabel kABCPhoneHomeLabel
|
||||
# define kABPhoneMainLabel kABCPhoneMainLabel
|
||||
# define kABPhoneMobileLabel kABCPhoneMobileLabel
|
||||
# define kABPhonePagerLabel kABCPhonePagerLabel
|
||||
# define kABPhoneProperty kABCPhoneProperty
|
||||
# define kABPhoneWorkFAXLabel kABCPhoneWorkFAXLabel
|
||||
# define kABPhoneWorkLabel kABCPhoneWorkLabel
|
||||
# define kABRelatedNamesProperty kABCRelatedNamesProperty
|
||||
# define kABSpouseLabel kABCSpouseLabel
|
||||
# define kABSuffixProperty kABCSuffixProperty
|
||||
// # define kABTitleProperty kABCTitleProperty
|
||||
// # define kABURLsProperty kABCURLsProperty
|
||||
# define kABYahooInstantProperty kABCYahooInstantProperty
|
||||
#else
|
||||
# #define PersonCreateWrapper(_addressbook) ABPersonCreate()
|
||||
#endif
|
||||
#include "AddressBookSource.h"
|
||||
|
||||
#include <common/base/Log.h>
|
||||
|
@ -62,6 +133,30 @@ static CFStringRef Std2CFString(const string &str)
|
|||
return cfstring.release();
|
||||
}
|
||||
|
||||
#ifdef __arm__
|
||||
|
||||
extern "C" const CFStringRef kABCHomePageProperty;
|
||||
extern "C" const CFStringRef kABCURLProperty;
|
||||
|
||||
extern "C" ABPersonRef ABCPersonCreateNewPerson(ABAddressBookRef addressbook);
|
||||
|
||||
extern "C" ABRecordRef ABCPersonGetRecordForUniqueID(ABAddressBookRef addressBook, SInt32 uid);
|
||||
extern "C" ABRecordRef ABCopyRecordForUniqueId(ABAddressBookRef addressBook, CFStringRef uniqueId)
|
||||
{
|
||||
SInt32 uid = CFStringGetIntValue(uniqueId);
|
||||
return ABCPersonGetRecordForUniqueID(addressBook, uid);
|
||||
}
|
||||
|
||||
extern "C" SInt32 ABCRecordGetUniqueId(ABRecordRef record);
|
||||
extern "C" CFStringRef ABRecordCopyUniqueId(ABRecordRef record)
|
||||
{
|
||||
SInt32 uid = ABCRecordGetUniqueId(record);
|
||||
return CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), uid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* a strtok_r() which does no skip delimiters at the start and end and does
|
||||
* not merge consecutive delimiters, i.e. returned string may be empty
|
||||
|
@ -108,21 +203,39 @@ public:
|
|||
// Remove all properties from person that we might set:
|
||||
// those still found in the vCard will be recreated.
|
||||
// Properties that we do not support are left untouched.
|
||||
LOG.debug("removing values");
|
||||
for (int mapindex = 0;
|
||||
m_mapping[mapindex].m_vCardProp;
|
||||
mapindex++) {
|
||||
printf(" mapindex %d\n", mapindex);
|
||||
const mapping &map = m_mapping[mapindex];
|
||||
if (map.m_abPersonProp) {
|
||||
if (!ABRecordRemoveValue(m_person, map.m_abPersonProp)) {
|
||||
throw runtime_error("removing old value " + CFString2Std(map.m_abPersonProp) + " failed");
|
||||
if (!ABRecordRemoveValue(m_person, *map.m_abPersonProp)) {
|
||||
throw runtime_error("removing old value "
|
||||
#ifndef __arm__
|
||||
+ CFString2Std(*map.m_abPersonProp) + " " +
|
||||
#endif
|
||||
"failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int multi = 0; multi < MAX_MULTIVALUE; multi++) {
|
||||
printf(" multi %d\n", multi);
|
||||
if (!ABRecordRemoveValue(m_person, *m_multiProp[multi])) {
|
||||
throw runtime_error("removing old value "
|
||||
#ifndef __arm__
|
||||
+ CFString2Std(**m_multiProp[multi]) + " " +
|
||||
#endif
|
||||
"failed");
|
||||
}
|
||||
}
|
||||
|
||||
// walk through all properties and handle them
|
||||
int propindex = 0;
|
||||
VProperty *vprop;
|
||||
LOG.debug("storing properties in contact");
|
||||
while ((vprop = vobj->getProperty(propindex)) != NULL) {
|
||||
LOG.debug("property %s", vprop->getName());
|
||||
for (int mapindex = 0;
|
||||
m_mapping[mapindex].m_vCardProp;
|
||||
mapindex++) {
|
||||
|
@ -133,6 +246,7 @@ public:
|
|||
handler = &vCard2ABPerson::toPersonString;
|
||||
}
|
||||
(this->*handler)(map, *vprop);
|
||||
LOG.debug("property %s handled", vprop->getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -140,12 +254,14 @@ public:
|
|||
}
|
||||
|
||||
// now copy all those values to the person which did not map directly
|
||||
LOG.debug("set multiprops");
|
||||
for (int multi = 0; multi < MAX_MULTIVALUE; multi++) {
|
||||
if (m_multi[multi]) {
|
||||
setPersonProp(m_multiProp[multi], m_multi[multi]);
|
||||
setPersonProp(*m_multiProp[multi], m_multi[multi]);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("set photo");
|
||||
VProperty *photo = vobj->getProperty("PHOTO");
|
||||
if (photo) {
|
||||
int len;
|
||||
|
@ -155,6 +271,8 @@ public:
|
|||
throw runtime_error("cannot set photo data");
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("contact done");
|
||||
}
|
||||
|
||||
void fromPerson() {
|
||||
|
@ -162,7 +280,7 @@ public:
|
|||
const unsigned char *text;
|
||||
|
||||
// VObject is so broken that it neither as a reset nor
|
||||
// an assignment operator - no I didn't write it :-/
|
||||
// an assignment operator - no, I didn't write it :-/
|
||||
//
|
||||
// Reseting m_vobj was supposed to allow repeated calls
|
||||
// to fromPerson, but this is not really necessary.
|
||||
|
@ -177,14 +295,24 @@ public:
|
|||
m_mapping[mapindex].m_vCardProp;
|
||||
mapindex++ ) {
|
||||
const mapping &map = m_mapping[mapindex];
|
||||
printf("%d: ", mapindex);
|
||||
printf("%s prop %p = %p\n",
|
||||
map.m_vCardProp,
|
||||
map.m_abPersonProp,
|
||||
map.m_abPersonProp ? *map.m_abPersonProp : 0);
|
||||
if (map.m_abPersonProp) {
|
||||
ref<CFTypeRef> value(ABRecordCopyValue(m_person, map.m_abPersonProp));
|
||||
ref<CFTypeRef> value(ABRecordCopyValue(m_person, *map.m_abPersonProp));
|
||||
printf("got %p\n", (CFTypeRef)value);
|
||||
if (value) {
|
||||
ref<CFStringRef> descr(CFCopyDescription(value));
|
||||
printf(" = %s\n",
|
||||
CFString2Std(descr).c_str());
|
||||
fromPerson_t handler = map.m_fromPerson;
|
||||
if (!handler) {
|
||||
handler = &vCard2ABPerson::fromPersonString;
|
||||
}
|
||||
(this->*handler)(map, value);
|
||||
printf(" handled\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,10 +353,11 @@ public:
|
|||
m_vobj.fromNativeEncoding();
|
||||
arrayptr<char> finalstr(m_vobj.toString(), "VOCL string");
|
||||
m_vcard = (char *)finalstr;
|
||||
LOG.debug("extracted %s",
|
||||
(char *)finalstr);
|
||||
}
|
||||
|
||||
private:
|
||||
string m_errorPrefix;
|
||||
string &m_vcard;
|
||||
ABPersonRef m_person;
|
||||
VObject m_vobj;
|
||||
|
@ -252,21 +381,27 @@ private:
|
|||
|
||||
/** intermediate storage for multi-value data later passed to ABPerson - keep in sync with m_multiProp */
|
||||
enum {
|
||||
URLS,
|
||||
EMAILS,
|
||||
PHONES,
|
||||
#ifndef __arm__
|
||||
DATES,
|
||||
NAMES,
|
||||
ADDRESSES,
|
||||
AIM,
|
||||
JABBER,
|
||||
MSN,
|
||||
YAHOO,
|
||||
ICQ,
|
||||
#endif
|
||||
NAMES,
|
||||
ADDRESSES,
|
||||
MAX_MULTIVALUE
|
||||
};
|
||||
ref<ABMutableMultiValueRef> m_multi[MAX_MULTIVALUE];
|
||||
static const CFStringRef m_multiProp[MAX_MULTIVALUE];
|
||||
/**
|
||||
* the ABPerson property which corresponds to the m_multi array:
|
||||
* a pointer because the tool chain for the iPhone did not properly
|
||||
* handle the constants
|
||||
*/
|
||||
static const CFStringRef *m_multiProp[MAX_MULTIVALUE];
|
||||
|
||||
struct mapping;
|
||||
typedef void (vCard2ABPerson::*toPerson_t)(const mapping &map, VProperty &vprop);
|
||||
|
@ -281,10 +416,12 @@ private:
|
|||
setPersonProp(property, cfstring);
|
||||
}
|
||||
void setPersonProp(CFStringRef property, CFTypeRef cftype) {
|
||||
ref<CFStringRef> descr(CFCopyDescription(cftype));
|
||||
LOG.debug("setting property %p to %s", property, CFString2Std(descr).c_str());
|
||||
if (!ABRecordSetValue(m_person, property, cftype)) {
|
||||
ref<CFStringRef> descr(CFCopyDescription(cftype));
|
||||
throwError("setting " + CFString2Std(property) + " to '" + CFString2Std(descr) + "'");
|
||||
}
|
||||
LOG.debug("setting done");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -293,8 +430,8 @@ private:
|
|||
static const struct mapping {
|
||||
/** the name of the vCard property, e.g. "ADDR" */
|
||||
const char *m_vCardProp;
|
||||
/** the predefined string reference for an ABPerson property */
|
||||
CFStringRef m_abPersonProp;
|
||||
/** address of ABPerson property, NULL pointer if none matches directly */
|
||||
const CFStringRef *m_abPersonProp;
|
||||
/** called when the property is found in the VObject: default is to copy string */
|
||||
toPerson_t m_toPerson;
|
||||
/** called when the property is found in the ABPerson: default is to copy string */
|
||||
|
@ -315,7 +452,8 @@ private:
|
|||
if (!value) {
|
||||
value = "";
|
||||
}
|
||||
setPersonProp(map.m_abPersonProp, value);
|
||||
// assert(map.m_abPersonProp);
|
||||
setPersonProp(*map.m_abPersonProp, value);
|
||||
}
|
||||
|
||||
void fromPersonStoreString(const mapping &map, CFTypeRef cftype) {
|
||||
|
@ -342,12 +480,15 @@ private:
|
|||
date.day = day;
|
||||
ref<CFDateRef> cfdate(CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(date, NULL)));
|
||||
if (cfdate) {
|
||||
setPersonProp(map.m_abPersonProp, cfdate);
|
||||
// assert(map.m_abPersonProp);
|
||||
setPersonProp(*map.m_abPersonProp, cfdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fromPersonURLs(const mapping &map, CFTypeRef cftype) {
|
||||
#ifndef __arm__
|
||||
// TODO: figure out what kABCURLProperty stands for
|
||||
int index = ABMultiValueCount((ABMultiValueRef)cftype) - 1;
|
||||
while (index >= 0) {
|
||||
ref<CFStringRef> label((CFStringRef)ABMultiValueCopyLabelAtIndex((ABMultiValueRef)cftype, index), "label");
|
||||
|
@ -364,6 +505,7 @@ private:
|
|||
|
||||
index--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void fromPersonEMail(const mapping &map, CFTypeRef cftype) {
|
||||
|
@ -389,6 +531,8 @@ private:
|
|||
}
|
||||
}
|
||||
void toPersonEMail(const mapping &map, VProperty &vprop) {
|
||||
#ifndef __arm__
|
||||
// TODO: crashes on iPhone
|
||||
const char *value = vprop.getValue();
|
||||
arrayptr<char> buffer(wstrdup(value ? value : ""));
|
||||
char *saveptr, *endptr;
|
||||
|
@ -416,6 +560,7 @@ private:
|
|||
} else {
|
||||
ref<CFStringRef> cfres(res);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void fromPersonAddr(const mapping &map, CFTypeRef cftype) {
|
||||
|
@ -571,6 +716,8 @@ private:
|
|||
}
|
||||
}
|
||||
void toPersonPhone(const mapping &map, VProperty &vprop) {
|
||||
#ifndef __arm__
|
||||
// TODO: crashes on iPhone
|
||||
const char *value = vprop.getValue();
|
||||
arrayptr<char> buffer(wstrdup(value ? value : ""));
|
||||
char *saveptr, *endptr;
|
||||
|
@ -612,6 +759,7 @@ private:
|
|||
} else {
|
||||
ref<CFStringRef> cfres(res);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void fromPersonChat(const mapping &map, CFTypeRef cftype) {
|
||||
|
@ -688,7 +836,9 @@ private:
|
|||
if (!prefix) {
|
||||
return;
|
||||
}
|
||||
#ifndef __arm__
|
||||
setPersonProp(kABTitleProperty, prefix);
|
||||
#endif
|
||||
|
||||
char *suffix = my_strtok_r(NULL, VObject::SEMICOLON_REPLACEMENT, &saveptr, &endptr);
|
||||
if (!suffix) {
|
||||
|
@ -747,58 +897,66 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
const CFStringRef vCard2ABPerson::m_multiProp[MAX_MULTIVALUE] = {
|
||||
(CFStringRef)kABURLsProperty,
|
||||
kABEmailProperty,
|
||||
kABPhoneProperty,
|
||||
kABOtherDatesProperty,
|
||||
kABRelatedNamesProperty,
|
||||
kABAddressProperty,
|
||||
kABAIMInstantProperty,
|
||||
kABJabberInstantProperty,
|
||||
kABMSNInstantProperty,
|
||||
kABYahooInstantProperty,
|
||||
kABICQInstantProperty
|
||||
const CFStringRef *vCard2ABPerson::m_multiProp[MAX_MULTIVALUE] = {
|
||||
&kABEmailProperty,
|
||||
&kABPhoneProperty,
|
||||
#ifndef __arm__
|
||||
&kABOtherDatesProperty,
|
||||
&kABAIMInstantProperty,
|
||||
&kABJabberInstantProperty,
|
||||
&kABMSNInstantProperty,
|
||||
&kABYahooInstantProperty,
|
||||
&kABICQInstantProperty,
|
||||
#endif
|
||||
&kABRelatedNamesProperty,
|
||||
&kABAddressProperty
|
||||
};
|
||||
|
||||
const vCard2ABPerson::mapping vCard2ABPerson::m_mapping[] = {
|
||||
{ "", kABFirstNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, FIRST_NAME },
|
||||
{ "", kABLastNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, LAST_NAME },
|
||||
{ "", kABMiddleNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, MIDDLE_NAME },
|
||||
{ "", kABTitleProperty, NULL, &vCard2ABPerson::fromPersonStoreString, TITLE },
|
||||
{ "", kABSuffixProperty, NULL, &vCard2ABPerson::fromPersonStoreString, SUFFIX },
|
||||
{ "", &kABFirstNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, FIRST_NAME },
|
||||
{ "", &kABLastNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, LAST_NAME },
|
||||
{ "", &kABMiddleNameProperty, NULL, &vCard2ABPerson::fromPersonStoreString, MIDDLE_NAME },
|
||||
#ifndef __arm__
|
||||
{ "", &kABTitleProperty, NULL, &vCard2ABPerson::fromPersonStoreString, TITLE },
|
||||
#endif
|
||||
{ "", &kABSuffixProperty, NULL, &vCard2ABPerson::fromPersonStoreString, SUFFIX },
|
||||
{ "N", 0, &vCard2ABPerson::toPersonName },
|
||||
/* "FN" */
|
||||
/* kABFirstNamePhoneticProperty */
|
||||
/* kABLastNamePhoneticProperty */
|
||||
/* kABMiddleNamePhoneticProperty */
|
||||
{ "BDAY", kABBirthdayProperty, &vCard2ABPerson::toPersonDate, &vCard2ABPerson::fromPersonDate },
|
||||
{ "BDAY", &kABBirthdayProperty, &vCard2ABPerson::toPersonDate, &vCard2ABPerson::fromPersonDate },
|
||||
|
||||
{ "", kABOrganizationProperty, NULL, &vCard2ABPerson::fromPersonStoreString, ORGANIZATION },
|
||||
{ "", kABDepartmentProperty, NULL, &vCard2ABPerson::fromPersonStoreString, DEPARTMENT },
|
||||
{ "", &kABOrganizationProperty, NULL, &vCard2ABPerson::fromPersonStoreString, ORGANIZATION },
|
||||
{ "", &kABDepartmentProperty, NULL, &vCard2ABPerson::fromPersonStoreString, DEPARTMENT },
|
||||
{ "ORG", 0, &vCard2ABPerson::toPersonOrg },
|
||||
|
||||
{ "TITLE", kABJobTitleProperty },
|
||||
{ "TITLE", &kABJobTitleProperty },
|
||||
/* "ROLE" */
|
||||
|
||||
#ifdef __arm__
|
||||
// TODO: { "", &kABCURLProperty, NULL, &vCard2ABPerson::fromPersonURLs },
|
||||
#else
|
||||
/**
|
||||
* bug in the header files for kABHomePageProperty and kABURLsProperty,
|
||||
* typecast required
|
||||
*/
|
||||
{ "URL", (CFStringRef)kABHomePageProperty },
|
||||
{ "", (CFStringRef)kABURLsProperty, NULL, &vCard2ABPerson::fromPersonURLs },
|
||||
{ "URL", (CFStringRef *)&kABHomePageProperty },
|
||||
{ "", (CFStringRef *)&kABURLsProperty, NULL, &vCard2ABPerson::fromPersonURLs },
|
||||
#endif
|
||||
#if 0
|
||||
kABHomePageLabel
|
||||
#endif
|
||||
|
||||
{ "EMAIL", kABEmailProperty, &vCard2ABPerson::toPersonEMail, &vCard2ABPerson::fromPersonEMail, EMAILS },
|
||||
#ifndef __arm__
|
||||
{ "EMAIL", &kABEmailProperty, &vCard2ABPerson::toPersonEMail, &vCard2ABPerson::fromPersonEMail, EMAILS },
|
||||
#if 0
|
||||
kABEmailWorkLabel
|
||||
kABEmailHomeLabel
|
||||
#endif
|
||||
|
||||
|
||||
{ "ADR", kABAddressProperty, &vCard2ABPerson::toPersonAddr, &vCard2ABPerson::fromPersonAddr, ADDRESSES },
|
||||
{ "ADR", &kABAddressProperty, &vCard2ABPerson::toPersonAddr, &vCard2ABPerson::fromPersonAddr, ADDRESSES },
|
||||
#if 0
|
||||
kABAddressWorkLabel
|
||||
kABAddressHomeLabel
|
||||
|
@ -812,7 +970,9 @@ kABAddressCountryCodeKey
|
|||
#endif
|
||||
/* LABEL */
|
||||
|
||||
{ "TEL", kABPhoneProperty, &vCard2ABPerson::toPersonPhone, &vCard2ABPerson::fromPersonPhone, PHONES },
|
||||
{ "TEL", &kABPhoneProperty, &vCard2ABPerson::toPersonPhone, &vCard2ABPerson::fromPersonPhone, PHONES },
|
||||
#endif // __arm__
|
||||
|
||||
#if 0
|
||||
kABPhoneWorkLabel
|
||||
kABPhoneHomeLabel
|
||||
|
@ -822,18 +982,22 @@ kABPhoneHomeFAXLabel
|
|||
kABPhoneWorkFAXLabel
|
||||
kABPhonePagerLabel
|
||||
#endif
|
||||
{ "X-AIM", kABAIMInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, AIM },
|
||||
{ "X-JABBER", kABJabberInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, JABBER },
|
||||
{ "X-MSN", kABMSNInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, MSN },
|
||||
{ "X-YAHOO", kABYahooInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, YAHOO },
|
||||
{ "X-ICQ", kABICQInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, ICQ },
|
||||
#ifndef __arm__
|
||||
{ "X-AIM", &kABAIMInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, AIM },
|
||||
{ "X-JABBER", &kABJabberInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, JABBER },
|
||||
{ "X-MSN", &kABMSNInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, MSN },
|
||||
{ "X-YAHOO", &kABYahooInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, YAHOO },
|
||||
{ "X-ICQ", &kABICQInstantProperty, &vCard2ABPerson::toPersonStore, &vCard2ABPerson::fromPersonChat, ICQ },
|
||||
#endif
|
||||
/* "X-GROUPWISE */
|
||||
{ "NOTE", kABNoteProperty },
|
||||
{ "NICKNAME", kABNicknameProperty },
|
||||
{ "NOTE", &kABNoteProperty },
|
||||
{ "NICKNAME", &kABNicknameProperty },
|
||||
|
||||
/* kABMaidenNameProperty */
|
||||
/* kABOtherDatesProperty */
|
||||
{ "", kABRelatedNamesProperty, NULL, &vCard2ABPerson::fromPersonNames },
|
||||
#ifndef __arm__
|
||||
{ "", &kABRelatedNamesProperty, NULL, &vCard2ABPerson::fromPersonNames },
|
||||
#endif
|
||||
#if 0
|
||||
kABMotherLabel
|
||||
kABFatherLabel
|
||||
|
@ -865,9 +1029,13 @@ kABManagerLabel
|
|||
};
|
||||
|
||||
|
||||
|
||||
double AddressBookSource::getModTime(ABRecordRef record)
|
||||
{
|
||||
double absolute;
|
||||
#ifdef __arm__
|
||||
absolute = (double)(int)ABRecordCopyValue(record,
|
||||
kABModificationDateProperty);
|
||||
#else
|
||||
ref<CFDateRef> itemModTime((CFDateRef)ABRecordCopyValue(record,
|
||||
kABModificationDateProperty));
|
||||
if (!itemModTime) {
|
||||
|
@ -877,12 +1045,13 @@ double AddressBookSource::getModTime(ABRecordRef record)
|
|||
if (!itemModTime) {
|
||||
throwError("cannot extract time stamp");
|
||||
}
|
||||
absolute = CFDateGetAbsoluteTime(itemModTime);
|
||||
#endif
|
||||
|
||||
// round up to next full second:
|
||||
// together with a sleep of 1 second in endSyncThrow() this ensures
|
||||
// that our time stamps are always >= the stored time stamp even if
|
||||
// the time stamp is rounded in the database
|
||||
double absolute = CFDateGetAbsoluteTime(itemModTime);
|
||||
return ceil(absolute);
|
||||
}
|
||||
|
||||
|
@ -912,7 +1081,10 @@ EvolutionSyncSource::sources AddressBookSource::getSyncBackends()
|
|||
|
||||
void AddressBookSource::open()
|
||||
{
|
||||
m_addressbook.set(ABGetSharedAddressBook(), "address book");
|
||||
m_addressbook = ABGetSharedAddressBook();
|
||||
if (!m_addressbook) {
|
||||
throwError("could not open address book");
|
||||
}
|
||||
m_modTimes.set(new spdm::DeviceManagementNode(m_modNodeName.c_str()), "change management node");
|
||||
m_modTimes->setAutosave(FALSE);
|
||||
}
|
||||
|
@ -976,37 +1148,60 @@ void AddressBookSource::endSyncThrow()
|
|||
resetItems();
|
||||
|
||||
if (m_addressbook && !hasFailed()) {
|
||||
LOG.debug("flushing address book");
|
||||
|
||||
// store changes persistently
|
||||
if (!ABSave(m_addressbook)) {
|
||||
throwError("could not save address book");
|
||||
}
|
||||
|
||||
fprintf(stderr, "saved address book\n");
|
||||
|
||||
m_modTimes->update(FALSE);
|
||||
|
||||
// time stamps are rounded to next second,
|
||||
// so to prevent changes in that range of inaccurracy
|
||||
// sleep a bit before returning control
|
||||
sleep(2);
|
||||
|
||||
LOG.debug("done with address book");
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBookSource::close()
|
||||
{
|
||||
printf("close\n");
|
||||
endSyncThrow();
|
||||
printf("free addressbook\n");
|
||||
m_addressbook = NULL;
|
||||
printf("free mod times\n");
|
||||
m_modTimes = NULL;
|
||||
printf("closed\n");
|
||||
}
|
||||
|
||||
void AddressBookSource::exportData(ostream &out)
|
||||
{
|
||||
LOG.debug("getting list of all people");
|
||||
|
||||
ref<CFArrayRef> allPersons(ABCopyArrayOfAllPeople(m_addressbook), "list of all people");
|
||||
|
||||
LOG.debug("got list");
|
||||
LOG.debug("%d persons", (int)CFArrayGetCount(allPersons));
|
||||
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(allPersons); i++) {
|
||||
ref<CFStringRef> cfuid(ABRecordCopyUniqueId((ABRecordRef)CFArrayGetValueAtIndex(allPersons, i)), "reading UID");
|
||||
ABRecordRef person = (ABRecordRef)CFArrayGetValueAtIndex(allPersons, i);
|
||||
CFStringRef descr = CFCopyDescription(person);
|
||||
LOG.debug("at index foo %s", CFString2Std(descr).c_str());
|
||||
LOG.debug("before copy");
|
||||
ref<CFStringRef> cfuid(ABRecordCopyUniqueId(person), "reading UID");
|
||||
LOG.debug("after copy");
|
||||
string uid(CFString2Std(cfuid));
|
||||
eptr<SyncItem> item(createItem(uid, SYNC_STATE_NONE), "sync item");
|
||||
|
||||
out << (char *)item->getData() << "\n";
|
||||
}
|
||||
|
||||
LOG.debug("done with list of all people");
|
||||
}
|
||||
|
||||
SyncItem *AddressBookSource::createItem( const string &uid, SyncState state )
|
||||
|
@ -1074,7 +1269,9 @@ int AddressBookSource::insertItem(SyncItem &item, const char *uid)
|
|||
person.set((ABPersonRef)ABCopyRecordForUniqueId(m_addressbook, cfuid), "contact");
|
||||
} else {
|
||||
// new contact
|
||||
person.set(ABPersonCreate(), "contact");
|
||||
LOG.debug("before creating contact");
|
||||
person.set(PersonCreateWrapper(m_addressbook), "contact");
|
||||
LOG.debug("after creating contact");
|
||||
}
|
||||
try {
|
||||
LOG.debug("storing vCard for %s:\n%s",
|
||||
|
@ -1082,6 +1279,7 @@ int AddressBookSource::insertItem(SyncItem &item, const char *uid)
|
|||
data.c_str());
|
||||
vCard2ABPerson converter(data, person);
|
||||
converter.toPerson();
|
||||
LOG.debug("person set");
|
||||
} catch (const std::exception &ex) {
|
||||
throwError(string("storing vCard for ") + (uid ? uid : "new contact") + " failed: " + ex.what());
|
||||
}
|
||||
|
@ -1090,22 +1288,39 @@ int AddressBookSource::insertItem(SyncItem &item, const char *uid)
|
|||
|
||||
// make sure we have a modification time stamp, otherwise the address book
|
||||
// sets one at random times
|
||||
LOG.debug("create time");
|
||||
CFAbsoluteTime nowabs = CFAbsoluteTimeGetCurrent();
|
||||
LOG.debug("setting absolute time %f", nowabs);
|
||||
#ifdef __arm__
|
||||
void *now = (void *)(int)round(nowabs);
|
||||
#else
|
||||
ref<CFDateRef> now(CFDateCreate(NULL, nowabs), "current time");
|
||||
#endif
|
||||
if (!ABRecordSetValue(person, kABModificationDateProperty, now)) {
|
||||
throwError("setting mod time");
|
||||
}
|
||||
LOG.debug("time set\n");
|
||||
|
||||
// existing contacts do not have to (and cannot) be added (?)
|
||||
if (uid || ABAddRecord(m_addressbook, person)) {
|
||||
printf("inserted contact\n");
|
||||
|
||||
#ifdef __arm__
|
||||
/* need to save to get UID? */
|
||||
ABSave(m_addressbook);
|
||||
#endif
|
||||
|
||||
ref<CFStringRef> cfuid(ABRecordCopyUniqueId(person), "uid");
|
||||
string uid(CFString2Std(cfuid));
|
||||
item.setKey(uid.c_str());
|
||||
string uidstr(CFString2Std(cfuid));
|
||||
item.setKey(uidstr.c_str());
|
||||
|
||||
char buffer[80];
|
||||
sprintf(buffer, "%.8f", getModTime(person));
|
||||
m_modTimes->setPropertyValue(uid.c_str(), buffer);
|
||||
LOG.debug("inserted contact %s with modification time %s",
|
||||
uidstr.c_str(), buffer);
|
||||
m_modTimes->setPropertyValue(uidstr.c_str(), buffer);
|
||||
} else {
|
||||
printf("error adding contact\n");
|
||||
throwError("storing new contact");
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ template<class T> class ref {
|
|||
*/
|
||||
void set( T pointer, const char *objectName = NULL )
|
||||
{
|
||||
fprintf(stderr, "ref %p: %p -> %p\n", this, m_pointer, pointer);
|
||||
if (m_pointer) {
|
||||
CFRelease(m_pointer);
|
||||
}
|
||||
|
@ -155,7 +156,7 @@ class AddressBookSource : public EvolutionSyncSource
|
|||
|
||||
private:
|
||||
/** valid after open(): the address book that this source references */
|
||||
ref<ABAddressBookRef> m_addressbook;
|
||||
ABAddressBookRef m_addressbook;
|
||||
|
||||
/**
|
||||
* Stores the modification time of all items sent to or received from the server.
|
||||
|
|
Loading…
Reference in a new issue