15 April 2006

LDIF to VCARD

Here is a modified version of the LDIF to VCARD script by Scott Barninger at http://www.barninger.com/ldif_to_vcard/.

Its adds a lot more fields, its adds some escaping of special characters:
$VERSION = "0.2.0";
use Net::LDAP::LDIF;

# declarations
my(
$common_name,$first_name,$last_name,$org_name,$email,$url,$homephone,$workphone,$mobilephone,$fax,$address,$city,$state,$postcode,$country,$categories,$note,$ldif,$entry,$line,$sysdate,$systime
);

$ldif = Net::LDAP::LDIF->new(\*STDIN);

while($entry = $ldif->read()) {
$common_name = &escape($entry->get_value('cn'));
$first_name = &escape($entry->get_value('givenName'));
$last_name = &escape($entry->get_value('sn'));
$org_name = &escape($entry->get_value('o'));

$email = &escape($entry->get_value('mail'));
$url = &escape($entry->get_value('url'));

$homephone = &escape($entry->get_value('homePhone'));
$workphone = &escape($entry->get_value('telephoneNumber'));
$mobilephone = &escape($entry->get_value('mobile'));
$fax = &escape($entry->get_value('facsimileTelephoneNumber'));

$address = $entry->get_value('postalAddress');
$address =~ s/\\/\\\\/g;
$address =~ s/;/\\;/g;
$address =~ s/\r\n|\n|\r/\\, /g;
$city = &escape($entry->get_value('l'));
$state = &escape($entry->get_value('st'));
$postcode = &escape($entry->get_value('postalCode'));
$country = &escape($entry->get_value('c'));

$categories = $entry->get_value('categories');
# ldap contains semi-colon seperated list, vcard requires comma seperated list
$categories =~ s/,/\\,/g;
$categories =~ s/;/,/g;

$note = $entry->get_value('description');
$note =~ s/\\/\\\\/g;
$note =~ s/\r\n|\n|\r/\\n/g;

($sysdate,$systime) = &sys_date;

# only output relevant records, should really check objectclass
# if($homephone || $workphone || $mobilephone) {
print "BEGIN:VCARD\r\n";
print "VERSION:3.0\r\n";

print "FN:$common_name\r\n";
if($first_name || $last_name){
print "N:$last_name;$first_name\r\n";
}else{
# print "N:;$common_name\r\n";
}
if($org_name){
print "ORG:$org_name\r\n";
}

if($email){
print "EMAIL;TYPE=INTERNET,PREF:$email\r\n";
}

if($url){
if($org_name){
print "URL;TYPE=WORK:$url\r\n";
} else {
print "URL;TYPE=HOME:$url\r\n";
}

}

if($workphone){
print "TEL;TYPE=WORK:$workphone\r\n";
}
if($homephone){
print "TEL;TYPE=HOME:$homephone\r\n";
}
if($mobilephone){
print "TEL;TYPE=CELL:$mobilephone\r\n";
}
if($fax){
print "TEL;TYPE=FAX:$fax\r\n";
}

if($address || $city || $state || $postcode || $country){
if($org_name){
print "ADR;TYPE=WORK:;;$address;$city;$state;$postcode;$country\r\n";
} else {
print "ADR;TYPE=HOME:;;$address;$city;$state;$postcode;$country\r\n";
}
}

if($categories){
print "CATEGORIES:$categories\r\n";
}

if($note){
print "NOTE:$note\r\n";
}

print "REV:$sysdate" . "T$systime\r\n";

print "END:VCARD\r\n";
# }
}

$ldif->done();
exit;

sub escape {
local($a) = ($_[0]);
$a =~ s/\\/\\\\/g;
$a =~ s/;/\\;/g;
$a =~ s/,/\\,/g;
return $a
}

sub sys_date {
# get the system date
# usage: my($sysdate,$systime) = &sys_date;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
if (length ($min) == 1) {$min = '0'.$min;}
if (length ($sec) == 1) {$sec = '0'.$sec;}
# since localtime returns the month as 0-11
$mon = $mon + 1;
if (length ($mon) == 1) {$mon = '0'.$mon;}
if (length ($mday) == 1) {$mday = '0'.$mday;}
# since localtime returns the year as the number of years since 1900
# ie year is 100 in the year 2000 (so is y2k OK)
$year = $year + 1900;
my $date = "$year-$mon-$mday";
my $time = "$hour:$min:$sec";
return($date,$time);
}