#!/usr/bin/python
#
# Dump LDAP phone entries to a vCard file.
# Borrowed some ideas from a PHONE_LDAP plugin for MoinMoin.
#
# Win Treese
# treese@acm.org
#
# Created: 6 February 2009

"""
ldap2vcard

Dump an LDAP phone list to vCards.

"""

import sys
import ldap
import vobject

##########################################################################
# Customize your setup here.
#
# If you understand LDAP, the URI and baseDN part should be obvious.
# The search filter is used to select which users to include. In this
# example, we want all users with group ID (gid) 100 (our local
# convention for regular user accounts). We exclude those with a login
# set to /bin/false, those whose accounts have expired, and those with
# telephone numbers set to XXX.
##########################################################################

ldap_uri = "ldap://ldap.example.com"
baseDN = "ou=people,dc=example,dc=com"
searchFilter = '(&(gidNumber=100)(!(loginShell=/bin/false))(!(shadowExpire=*))' \
               '(objectClass=*)(sn=*)(givenName=*)(employeeType=*)' \
               '(!(telephoneNumber=XXX)))'

# Finally, customize the phone number if needed. For example, our
# server stores just the extension for most people, so we write the
# full phone number out.

def localize_phone(phnum):
    return phnum
    # if phnum != None and len(phnum) == 3:
    #     phnum = "800-555-1212 x%s" % phnum
    # return phnum

##########################################################################
# End of normal customization
##########################################################################

def get_ldap_data():
    searchScope = ldap.SCOPE_SUBTREE
    retrieveAttributes = None

    try:
        l = ldap.initialize(ldap_uri)
        l.protocol_version = ldap.VERSION3	
        ldap_result_id = l.search(baseDN, searchScope, searchFilter,
                                  retrieveAttributes)
        rlist = []
        (rtype, rdata) = l.result(ldap_result_id, 1)
        if rtype != ldap.RES_SEARCH_RESULT:
            print "Error!"
        return rdata
    except ldap.LDAPError, e:
	print e
        sys.exit(1)

class MyCard(object):
    def __init__(self):
        self.v = vobject.vCard()
    def add_name(self, first, last):
        """Add the required name field to a vCard"""
        self.v.add('n')
        self.v.n.value = vobject.vcard.Name(given=first, family=last)
        self.v.add('fn')
        self.v.fn.value = "%s %s" % (first, last)
    def add(self, val, field, ftype=None):
        """Add a field to a vCard.
           For convenience, if val is None, nothing is done."""
        if val == None:
            return
        x = self.v.add(field)
        x.value = val
        if ftype != None:
            x.type_param = ftype
    def get_vcard(self):
        return self.v
    
def make_vcard(ldata):
    (dn, data) = ldata
    for key in data:
        if len(data[key]) == 1:
            data[key] = data[key][0]
            
    card = MyCard()
    card.add_name(data['givenName'], data['sn'])
    card.add(data.get('mail'), 'email', 'WORK')
    card.add(data.get('homePhone'), 'tel', 'HOME')
    card.add(data.get('mobile'), 'tel', 'CELL')
    card.add(localize_phone(data.get('telephoneNumber')), 'tel', 'WORK')
    return card.get_vcard()

for person in get_ldap_data():
    v = make_vcard(person)
    print v.serialize()
    
