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 |