File Coverage

blib/lib/Text/SimpleVcard.pm
Criterion Covered Total %
statement 105 117 89.7
branch 21 32 65.6
condition 2 6 33.3
subroutine 15 17 88.2
pod 6 7 85.7
total 149 179 83.2


line stmt bran cond sub pod time code
1             # ===========================================================================
2             # Text::SimpleVproperty - a package to manage a single vCard-property
3             # ===========================================================================
4             package Text::SimpleVproperty;
5              
6 3     3   79198 use warnings;
  3         8  
  3         108  
7 3     3   18 use strict;
  3         7  
  3         106  
8              
9 3     3   3984 use MIME::QuotedPrint();
  3         7999  
  3         1904  
10              
11             # ---------------------------------------------------------------------------
12             # Check if a value is element of an array
13             # ---------------------------------------------------------------------------
14             sub isIn {
15 49     49   55 my $val = shift;
16 49         450 return( scalar grep( /^$val$/, @_) > 0);
17             }
18              
19             sub new {
20 28     28   36 my( $class, $data) = @_;
21 28         37 my $self = {};
22 28         38 my $enc = "";
23              
24 28         122 my ( $meta, $val) = ( $data =~ /(.*?):(.*)/);
25 28         82 my @meta = split( /;/, $meta);
26 28         65 $self->{ name} = uc( shift( @meta));
27              
28 28         50 foreach( @meta){
29 18         27 my( $key, $val) = ( "TYPE", $_);
30            
31 18 100       44 if( $val =~ /=/) {
32 8         35 ( $key, $val) = split( /\s*=\s*/);
33             }
34 18 100       41 if( $key eq "ENCODING") {
35 2         4 $enc = $val;
36 2         4 next;
37             }
38              
39 16 50       47 if( $key =~ /TYPE/i) {
40 16 50       18 push( @{$self->{ types}}, $val) if( !isIn( $val, @{$self->{ types}}));
  16         87  
  16         59  
41             } else {
42 0         0 ${ $self->{ param}}{ $key} = $val;
  0         0  
43             }
44             }
45 28 100       59 if( $enc eq "QUOTED-PRINTABLE") {
46 2         18 $self->{ val} = MIME::QuotedPrint::decode_qp( $val);
47             } else {
48 26         93 $self->{ val} = $val;
49             }
50              
51 28         88 bless( $self, $class);
52             }
53              
54             sub hasType {
55 33     33   43 my( $class, $typ) = @_;
56              
57 33         33 return isIn( uc( $typ), @{ $class->{ types}});
  33         76  
58             }
59              
60             sub sprint {
61 14     14   17 my( $class) = @_;
62 14         21 my $res = "$class->{ name}";
63              
64 14         12 foreach( @{ $class->{ types}}) {
  14         29  
65 6         12 $res .= ";TYPE=$_";
66             }
67 14         19 foreach( keys %{ $class->{ param}}) {
  14         41  
68 0         0 my $val = ${ $class->{ param}}{ $_};
  0         0  
69 0 0       0 $res .= ";$_" . ( defined( $val) ? "=$val" : "");
70             }
71 14         32 $res .= ":$class->{ val}";
72 14         48 return $res;
73             }
74              
75             sub print {
76 0     0   0 my( $class, $hdr) = @_;
77              
78 0 0       0 print $hdr if( $hdr);
79 0         0 print $class->sprint() . "\n";
80             }
81              
82             # ===========================================================================
83             # Text::SimpleVcard - a package to manage a single vCard
84             # ===========================================================================
85             package Text::SimpleVcard;
86              
87 3     3   25 use warnings;
  3         6  
  3         105  
88 3     3   23 use strict;
  3         11  
  3         3477  
89              
90             =head1 NAME
91              
92             Text::SimpleVcard - a package to manage a single vCard
93              
94             =head1 VERSION
95              
96             Version 0.05
97              
98             =cut
99              
100             our $VERSION = '0.05';
101              
102             =head1 SYNOPSIS
103              
104             simplevCard - This package provides an API to reading a single vCard. A vCard is an
105             electronic business card. You will find that many applications (KDE Address book,
106             Apple Address book, MS Outlook, Evolution, etc.) use and can export and import vCards.
107              
108             This module offers only basic vcard features (folding, ...). Grouping, etc. is not yet
109             supported. Further enhancements are always welcome.
110              
111             SimpleVcard has a minimum of dependencies (actually only 'MIME::QuotedPrint'), it
112             should work with every installation.
113              
114             use Text::SimpleVcard;
115              
116             open FH, "< std.vcf"; # 'std.vcf' contains a single vcard-entry
117             my $vCard = Text::SimpleVcard->new( join( '', ));
118             $vCard->print();
119             print "FN=" . $vCard->getSimpleValue( 'FN') . "\n";
120             print "fullname=" . $vCard->getFullName() . "\n";
121             my %h = $vCard->getValuesAsHash( 'TEL', [qw( WORK HOME)]);
122              
123             print "phone-numbers are:\n";
124             foreach( keys %h) {
125             print "Got number $_ ($h{$_})\n";
126             }
127              
128             =head1 FUNCTIONS
129              
130             =head2 new()
131              
132             my $vCard = simpleVcard->new( $dat);
133              
134             The method will create a C object from vcard data (e.g. from
135             a vCard-File (see example above)). Nested vCards will be ignored.
136              
137             =cut
138              
139             sub new {
140 2     2 1 31 my( $class, $data) = @_;
141 2         5 my $self = {};
142              
143 2         20 $data =~ s/[\r\n]+ +//gm; # lines starting with space belong to last line (unfolding)
144 2         35 my @data = split( /[\r\n]+/, $data);
145 2         7 my( $fl, $ll) = ( shift( @data), pop( @data)); # chop enclosing BEGIN-, END-lines
146              
147 2 50 33     11 if( $fl ne "BEGIN:VCARD" and $ll ne "END:VCARD") { # check if they are syntactically correct
148 0         0 warn "vcard should begin with VCARD:BEGIN and end with VCARD:END";
149 0         0 return;
150             }
151              
152 2         4 my $vCardCnt = 0;
153 2         6 foreach( @data) {
154 28 50       66 $vCardCnt++ if( /^BEGIN:VCARD/); #
155 28 50       54 $vCardCnt-- if( /^END:VCARD/); # skip nested vcards
156 28 50 33     120 next if( $vCardCnt != 0 or /^END:VCARD/); #
157 28         73 my $p = Text::SimpleVproperty->new( $_); # push new property on the array behind the ...
158 28         37 push( @{ $self->{ $p->{ name}}}, $p); # ... hash-value of the key with the property-name
  28         113  
159             }
160 2         13 bless( $self, $class);
161             }
162              
163             =head2 print()
164              
165             $vCard->print();
166             $vCard->sprint();
167              
168             The method will print a C-object to stdout or, in case of C to a string
169              
170             =cut
171              
172             sub sprint {
173 1     1 0 28 my( $class) = @_;
174 1         2 my $res = '';
175              
176 1         5 foreach my $propKey ( keys %$class) {
177 11         15 foreach my $prop ( @{ $class->{ $propKey}}) {
  11         23  
178 14         27 $res .= $prop->sprint() . "\n";
179             }
180             }
181 1         5 chomp( $res);
182 1         20 return $res;
183             }
184              
185             sub print {
186 0     0 1 0 my( $class) = @_;
187              
188 0         0 print $class->sprint() . "\n";
189             }
190              
191             =head2 getSimpleValue()
192              
193             $vCard->getSimpleValue( $prop);
194             $vCard->getSimpleValue( $prop, $n);
195              
196             The method will fetch the first (or, if an index is provided, the n'th) value
197             of the specified property. If the property or the index doesn't exist, it returns
198             undef
199              
200             =cut
201              
202             sub getSimpleValue {
203 8     8 1 27 my( $class, $prop, $ndx) = ( @_, 0); # setting ndx=0 if not provided
204              
205 8         41 my $aryRef = $class->{ uc( $prop)};
206 8 100       19 return undef if( ! defined( $aryRef)); # property-name does not exist
207              
208 7         13 my @ary = @$aryRef; # using aryRef directly works under perl 5.8 but not under 5.10
209 7         31 my $propRef = $ary[ $ndx];
210 7 100       17 return undef if( ! defined( $propRef)); # no index '$ndx' for the requested property
211              
212 6         20 return $propRef->{ val};
213             }
214              
215             =head2 getSimpleValueOfType()
216              
217             $vCard->getSimpleValueOfType( $prop, [qw( WORK HOME)]]);
218             $vCard->getSimpleValueOfType( $prop, [qw( WORK HOME)]], $n);
219              
220             The method will fetch the first (or, if an index is provided, the n'th) value
221             of the specified property of the desired type. If the property or the index doesn't exist,
222             it returns undef
223              
224             =cut
225              
226             sub getSimpleValueOfType {
227 1     1 1 8 my( $class, $prop, $types, $ndx) = ( @_, 0); # setting ndx=0 if not provided
228 1         528 my %h = $class->getValuesAsHash( $prop, $types);
229              
230 1         5 return ( keys %h)[ $ndx];
231             }
232              
233             =head2 getFullName()
234              
235             $vCard->getFullName();
236              
237             The method will fetch the value of the property C, and get rid off
238             any backslashes found in that value
239              
240             =cut
241              
242             sub getFullName {
243 2     2 1 13 my( $class) = @_;
244              
245 2         10 my $fn = $class->getSimpleValue( 'FN');
246 2 50       11 $fn =~ s/\\//g if( defined( $fn));
247 2         6 return $fn;
248             }
249              
250             =head2 getValuesAsHash()
251              
252             $vCard->getValuesAsHash( 'TEL', [qw( WORK HOME)]]);
253              
254             The method will return a hash returning the values of the provided property.
255             The value will contain a CSV-list of the matching types. if no types are provided,
256             it will return all types found.
257              
258             =cut
259              
260             sub getValuesAsHash {
261 5     5 1 26 my( $class, $props, $types) = @_;
262 5         8 my %res = (); # key=prop-value (e.g. '(07071) 82479')
263              
264 5         7 foreach my $prop ( @{ $class->{ $props}}) { # e.g all entries with name='TEL'
  5         12  
265 16 100       608 my @types = $types ? @$types : @{ $prop->{ types}};# take all types, if none required
  7         17  
266 16         21 foreach my $type ( @types) { # loop over all requested types
267 33 100       78 if( $prop->hasType( uc( $type))) {
268 16         18 push( @{ $res{ $prop->{ val}}}, $type); # push entry in val-part of 'res'
  16         68  
269             }
270             }
271             }
272              
273 5         18 foreach ( keys %res) { # replace arrays with CSV-value (string)
274 12         14 my $str = "";
275              
276 12         12 foreach ( @{ $res{ $_}}) {
  12         27  
277 16         31 $str .= "$_,";
278             }
279 12         17 chop( $str);
280 12         31 $res{ $_} = $str;
281             }
282 5         30 return %res;
283             }
284              
285              
286             =head1 AUTHOR
287              
288             Michael Tomuschat, C<< >>
289              
290             =head1 SEE ALSO
291              
292             Text::SimpleAdrbook - A module that can read several C-files
293              
294             =head1 BUGS
295              
296             Please report any bugs or feature requests to C, or through
297             the web interface at L. I will
298             be notified, and then you'll automatically be notified of progress on your bug as I make changes.
299              
300             =head1 SUPPORT
301              
302             You can find documentation for this module with the perldoc command.
303              
304             perldoc Text::SimpleVcard
305              
306              
307             You can also look for information at:
308              
309             =over 4
310              
311             =item * RT: CPAN's request tracker
312              
313             L
314              
315             =item * AnnoCPAN: Annotated CPAN documentation
316              
317             L
318              
319             =item * CPAN Ratings
320              
321             L
322              
323             =item * Search CPAN
324              
325             L
326              
327             =back
328              
329             =head1 COPYRIGHT & LICENSE
330              
331             Copyright 2008-2009 Michael Tomuschat, all rights reserved.
332              
333             This program is free software; you can redistribute it and/or modify it
334             under the same terms as Perl itself.
335              
336              
337             =cut
338              
339             1; # End of Text::SimpleVcard