package BBDB::Export::vCard; use strict; our @ISA = qw(BBDB::Export); our $VERSION = do { my @r=(q$Revision: 0.2 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; use Data::Dumper; use Text::vFile::asData; # #_* To Do # # BDAY birthday # MAILER # TZ timezone # TITLE # ROLE # PRODID # REV # SORT-STRING # UID # URL # CLASS # NICKNAME # PHOTO # #_* config # # supported keys, in preferred order # TODO: make this configurable my @keys = qw( begin version fn n org note tel email end); # #_* process_record # sub process_record { my ( $self, $record ) = @_; my $vcard = Text::vFile::asData->new(); my $data; $data->{'properties'}->{'begin'} = [ { value => "vcard" } ]; $data->{'properties'}->{'version'} = [ { value => "3.0" } ]; $data->{'properties'}->{'fn'} = [ { value => $record->{'full'} } ]; $data->{'properties'}->{'n'} = [ { value => join ";", ( $record->{'last'}, $record->{'first'}, "", "", "" ) } ]; $data->{'properties'}->{'org'} = [ { value => $record->{'company'} } ]; $data->{'properties'}->{'note'} = [ { value => $record->{'notes'} } ]; $data->{'properties'}->{'tel'} = [ { value => $record->{'phone'}->{'home' }, param => { type => "home", } }, { value => $record->{'phone'}->{'work' }, param => { type => "work", } }, { value => $record->{'phone'}->{'mobile' }, param => { type => "mobile", } }, { value => $record->{'phone'}->{'fax' }, param => { type => "fax", } }, ]; if ( $record->{ 'net' } && ref $record->{ 'net' } eq "ARRAY" ) { for my $index ( 0 .. $#{ $record->{ 'net' } } ) { push @{ $data->{'properties'}->{'email'} }, { value => $record->{'net'}->[$index], param => { type => "internet", } }; } } $data->{'properties'}->{'end'} = [ { value => "vcard" } ]; my @lines = $self->generate_lines( $data ); my $return = join( "\n", @lines ); if ( my $dir = $self->{'data'}->{'output_dir'} ) { my $file = join ( "_", ( $record->{'first'}, $record->{'last'} ) ); $file =~ tr,A-Za-z\-_,,cd; $file = $dir . "/" . $file; $file .= ".vcf"; print "Writing file: $file\n"; open ( VCARD, ">$file" ) or die "Unable to write vcard: $file: $!"; print VCARD $return; print VCARD "\n"; close ( VCARD ) or die "Error writing vcard: $file: $!"; } return $return; } # #_* Text::vFile::asData::generate_lines needs a little work # sub generate_lines { my ( $self, $data ) = @_; my @lines; push @lines, "BEGIN:$data->{type}" if exists $data->{type}; if (exists $data->{properties}) { # TODO: handle properties that are not listed in global @keys for my $name ( @keys ) { next unless $data->{properties}->{ $name }; my $v = $data->{properties}->{ $name }; for my $value (@$v) { next unless $value->{'value'}; # XXX so we're taking params in preference to param, # let's be sure to document that when we document this # method my $param = join ';', '', map { my $hash = $_; map { "$_" . (defined $hash->{$_} ? "=" . $hash->{$_} : "") } keys %$hash } @{ $value->{params} || [ $value->{param} ] }; push @lines, "$name$param:$value->{value}"; } } } if (exists $data->{objects}) { push @lines, $self->generate_lines( $_ ) for @{ $data->{objects} } } push @lines, "END:$data->{type}" if exists $data->{type}; return @lines; } # #_* post_processing # # no post processing necessary for vcard since there is one entry per # file. sub post_processing { my ( $self, $output ) = @_; return $output; } 1;