Prompted by one of my rants and the need to have some sort of basic LDAP server to store all my contact info, I've hacked together a simple LDAP server that would allow me to point the Mac OS X Address Book applet at it and retrieve contact information stored as vCard files.

The basic requirements were:

  • Read-only LDAP access from Address Book, Mozilla and Outlook
  • Brainless setup (this is going to be the tricky bit)
  • Storage is to be simply a directory filled with vCard files (no indexing, no format conversion, nothing) - simple to maintain, simple to update
  • Support for any differences that arise between Mac OS X vCards and Outlook vCards

To this purpose, I picked up a simple LDAP daemon written in Perl and have been slowly figuring out how the CPAN Net::LDAP bundle works. I had initially thought of writing this in Python, but ASN.1 support in Python seems to be a bit crufty still.

For actually parsing the vCard files, I'm using Net::vFile.


After a few months in limbo, I picked this up again and ran some traces of Address Book against an Exchange directory. At this point in time, the code parses an entire directory of vCard files on demand and returns matching entries' name, e-mail and default phone number, but only work-related ones (because that's what Address Book is limited to displaying).

I'm committed to writing a platform-agnostic Perl daemon rather than a Mac OS X-only thing, since other folk have asked me for Windows support (seems like there is a demand for simple, limited, zero-configuration LDAP servers to create shared address books).

But based on this discussion, it looks like I am right when stating that Address Book has severe limitations where it regards obtaining full contact data from LDAP - I considered returning multiple LDAP records for each vCard and be done with it, but that's not entirely trivial and breaks contact importing to Address Book (i.e., you have to drag multiple LDAP cards and merge them to get all contact info for the same person in one card).

Main Issues:

  • Address Book doesn't seem to understand multiple mail and telephoneNumber attributes in LDAP entries (it just displays the first one I send back and tags it as "(work)", probably assuming the LDAP server it's talking to is a corporate directory). It understands mobile and pager (which it displays correctly), but there seems to be no way to define "home" e-mail and phone numbers.
  • There seems to be no reference listing the LDAP fields it actually understands (see below).

Both of these issues are jointly filed on Radar as #4270821. After sniffing at the traffic with Ethereal in an attempt to figure out what is actually happening, I found that Address Book issues a query for the following attributes:

Lightweight Directory Access Protocol
    LDAP Message, Search Request
        Message Id: 2
        Message Type: Search Request (0x03)
        Message Length: 291
        Response In: 8
        Base DN: (null)
        Scope: Subtree (0x02)
        Dereference: Never (0x00)
        Size Limit: 0
        Time Limit: 30
        Attributes Only: False
        Filter: (|(givenname=carmo)(sn=carmo)(cn=carmo)(mail=carmo))
        Attribute: givenName
        Attribute: sn
        Attribute: cn
        Attribute: mail
        Attribute: telephoneNumber
        Attribute: facsimileTelephoneNumber
        Attribute: o
        Attribute: title
        Attribute: ou
        Attribute: buildingName
        Attribute: street
        Attribute: l
        Attribute: st
        Attribute: postalCode
        Attribute: c
        Attribute: jpegPhoto
        Attribute: mobile
        Attribute: co
        Attribute: pager
        Attribute: destinationIndicator
        Attribute: labeledURI
        Attribute: IMHandle

...which explains why it doesn't like mailAlternateAddress and other common variations on the "standard" schema, but that doesn't shed any light on how it is supposed to handle multi-valued fields.

It would be extremely nice if it supported more or less the same set of fields on LDAP as it does on standard vCards, even if it deviated from the standard schemas to do so - all that's really necessary is some sort of published reference...

Source Code

Source code was in my (now extinct) CVS Repository, but is available on request.