line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Data::Microformat::hCard; |
2
|
13
|
|
|
13
|
|
5826
|
use base qw(Data::Microformat); |
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
5354
|
|
3
|
|
|
|
|
|
|
|
4
|
13
|
|
|
13
|
|
141
|
use strict; |
|
13
|
|
|
|
|
24
|
|
|
13
|
|
|
|
|
440
|
|
5
|
13
|
|
|
13
|
|
66
|
use warnings; |
|
13
|
|
|
|
|
29
|
|
|
13
|
|
|
|
|
616
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = "0.04"; |
8
|
|
|
|
|
|
|
|
9
|
13
|
|
|
13
|
|
7742
|
use Data::Microformat::adr; |
|
13
|
|
|
|
|
29
|
|
|
13
|
|
|
|
|
344
|
|
10
|
13
|
|
|
13
|
|
6297
|
use Data::Microformat::geo; |
|
13
|
|
|
|
|
27
|
|
|
13
|
|
|
|
|
283
|
|
11
|
13
|
|
|
13
|
|
6672
|
use Data::Microformat::hCard::type; |
|
13
|
|
|
|
|
27
|
|
|
13
|
|
|
|
|
333
|
|
12
|
13
|
|
|
13
|
|
6837
|
use Data::Microformat::hCard::name; |
|
13
|
|
|
|
|
39
|
|
|
13
|
|
|
|
|
279
|
|
13
|
13
|
|
|
13
|
|
6943
|
use Data::Microformat::hCard::organization; |
|
13
|
|
|
|
|
28
|
|
|
13
|
|
|
|
|
30700
|
|
14
|
|
|
|
|
|
|
|
15
|
40
|
|
|
40
|
1
|
110
|
sub class_name { "vcard" } |
16
|
44
|
|
|
44
|
1
|
272
|
sub singular_fields { qw(fn n bday tz geo sort_string uid class) } |
17
|
44
|
|
|
44
|
1
|
272
|
sub plural_fields { qw(adr agent category email key label logo mailer nickname note org photo rev role sound tel title url) } |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub is_representative |
20
|
|
|
|
|
|
|
{ |
21
|
7
|
|
|
7
|
1
|
12
|
my $self = shift; |
22
|
7
|
100
|
|
|
|
15
|
if ($self->{_representative}) |
23
|
|
|
|
|
|
|
{ |
24
|
3
|
|
|
|
|
11
|
return 1; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
else |
27
|
|
|
|
|
|
|
{ |
28
|
4
|
|
|
|
|
15
|
return 0; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub from_tree |
33
|
|
|
|
|
|
|
{ |
34
|
17
|
|
|
17
|
1
|
39
|
my $class = shift; |
35
|
17
|
|
|
|
|
34
|
my $tree = shift; |
36
|
|
|
|
|
|
|
|
37
|
17
|
|
|
|
|
31
|
my $representative_url = shift; |
38
|
17
|
100
|
|
|
|
68
|
if ($representative_url) |
39
|
|
|
|
|
|
|
{ |
40
|
4
|
|
|
|
|
11
|
$representative_url = _normalize_url($representative_url); |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
44
|
17
|
|
|
|
|
41
|
my $rel_me = ""; |
45
|
|
|
|
|
|
|
|
46
|
17
|
|
|
|
|
26
|
my @all_cards; |
47
|
17
|
|
|
|
|
171
|
my @cards = $tree->look_down("class", qr/vcard/); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
#First: build the list of things we recognize; |
50
|
17
|
|
|
|
|
3151
|
my $recognized_regex = "("; |
51
|
17
|
|
|
|
|
152
|
foreach my $field ( ( Data::Microformat::adr->singular_fields, |
52
|
|
|
|
|
|
|
Data::Microformat::adr->plural_fields, |
53
|
|
|
|
|
|
|
Data::Microformat::adr->class_name, |
54
|
|
|
|
|
|
|
Data::Microformat::geo->singular_fields, |
55
|
|
|
|
|
|
|
Data::Microformat::geo->plural_fields, |
56
|
|
|
|
|
|
|
Data::Microformat::geo->class_name, |
57
|
|
|
|
|
|
|
Data::Microformat::hCard::name->singular_fields, |
58
|
|
|
|
|
|
|
Data::Microformat::hCard::name->plural_fields, |
59
|
|
|
|
|
|
|
Data::Microformat::hCard::name->class_name, |
60
|
|
|
|
|
|
|
Data::Microformat::hCard::organization->singular_fields, |
61
|
|
|
|
|
|
|
Data::Microformat::hCard::organization->plural_fields, |
62
|
|
|
|
|
|
|
Data::Microformat::hCard::organization->class_name, |
63
|
|
|
|
|
|
|
Data::Microformat::hCard::type->singular_fields, |
64
|
|
|
|
|
|
|
Data::Microformat::hCard::type->plural_fields, |
65
|
|
|
|
|
|
|
Data::Microformat::hCard::type->class_name, |
66
|
|
|
|
|
|
|
Data::Microformat::hCard->singular_fields, |
67
|
|
|
|
|
|
|
Data::Microformat::hCard->plural_fields, |
68
|
|
|
|
|
|
|
Data::Microformat::hCard->class_name, )) |
69
|
|
|
|
|
|
|
{ |
70
|
884
|
|
|
|
|
1023
|
$field =~ s/\_/\-/; |
71
|
884
|
|
|
|
|
1200
|
$recognized_regex .= '(^|\s)'.$field.'($|\s)|'; |
72
|
|
|
|
|
|
|
} |
73
|
17
|
|
|
|
|
96
|
chop($recognized_regex); |
74
|
17
|
|
|
|
|
29
|
$recognized_regex .= ")"; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
17
|
|
|
|
|
39
|
foreach my $card_tree (@cards) |
78
|
|
|
|
|
|
|
{ |
79
|
|
|
|
|
|
|
# Walk the tree looking for useless bits |
80
|
|
|
|
|
|
|
# Where class is undefined |
81
|
23
|
|
|
|
|
84
|
my @useless = $card_tree->look_down("class", undef); |
82
|
23
|
|
|
|
|
1986
|
foreach my $element (@useless) |
83
|
|
|
|
|
|
|
{ |
84
|
7
|
|
|
|
|
58
|
my @kids = $element->detach_content; |
85
|
7
|
|
|
|
|
85
|
my $parent = $element->detach; |
86
|
7
|
100
|
|
|
|
112
|
if (@kids) |
87
|
|
|
|
|
|
|
{ |
88
|
5
|
|
|
|
|
16
|
$parent->push_content(@kids); |
89
|
|
|
|
|
|
|
} |
90
|
7
|
|
|
|
|
139
|
$element->delete; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
@useless = $card_tree->look_down(sub{ |
94
|
230
|
100
|
|
230
|
|
11232
|
if ($_[0]->attr('class')) |
95
|
|
|
|
|
|
|
{ |
96
|
229
|
|
|
|
|
2126
|
return $_[0]->attr('class') !~ m/$recognized_regex/; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
else |
99
|
|
|
|
|
|
|
{ |
100
|
1
|
|
|
|
|
11
|
return 1; |
101
|
23
|
|
|
|
|
183
|
}}); |
102
|
|
|
|
|
|
|
|
103
|
23
|
|
|
|
|
676
|
foreach my $element (@useless) |
104
|
|
|
|
|
|
|
{ |
105
|
1
|
|
|
|
|
4
|
my @kids = $element->detach_content; |
106
|
1
|
|
|
|
|
7
|
my $parent = $element->detach; |
107
|
1
|
50
|
|
|
|
7
|
if (@kids) |
108
|
|
|
|
|
|
|
{ |
109
|
0
|
|
|
|
|
0
|
$parent->push_content(@kids); |
110
|
|
|
|
|
|
|
} |
111
|
1
|
|
|
|
|
3
|
$element->delete; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
23
|
|
|
|
|
202
|
my $card = Data::Microformat::hCard->new; |
115
|
23
|
|
|
|
|
116
|
$card->{_no_dupe_keys} = 1; |
116
|
|
|
|
|
|
|
|
117
|
23
|
|
|
|
|
92
|
my @bits = $card_tree->content_list; |
118
|
|
|
|
|
|
|
|
119
|
23
|
|
|
|
|
191
|
foreach my $bit (@bits) |
120
|
|
|
|
|
|
|
{ |
121
|
155
|
100
|
|
|
|
367
|
if (ref($bit) eq "HTML::Element") |
122
|
|
|
|
|
|
|
{ |
123
|
130
|
|
|
|
|
127
|
my $nested_goes_here; |
124
|
130
|
|
|
|
|
323
|
my $hcard_class = $bit->attr('class'); |
125
|
130
|
50
|
|
|
|
1182
|
next unless $hcard_class; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
#Check for nested vcard. |
128
|
130
|
100
|
|
|
|
292
|
if ($hcard_class =~ m/vcard/) |
129
|
|
|
|
|
|
|
{ |
130
|
|
|
|
|
|
|
#We have a nested class in here. Mark where it needs to go. |
131
|
1
|
|
|
|
|
1
|
my $temp_hcard_class = $hcard_class; |
132
|
1
|
|
|
|
|
4
|
$temp_hcard_class =~ s/vcard//; |
133
|
1
|
|
|
|
|
5
|
$temp_hcard_class = $class->_trim($temp_hcard_class); |
134
|
1
|
|
|
|
|
4
|
my @types = split(" ", $temp_hcard_class); |
135
|
1
|
50
|
|
|
|
5
|
if (scalar @types > 0) |
136
|
|
|
|
|
|
|
{ |
137
|
1
|
|
|
|
|
2
|
$nested_goes_here = $types[0]; |
138
|
1
|
|
|
|
|
12
|
$hcard_class =~ s/$nested_goes_here//; |
139
|
1
|
|
|
|
|
4
|
$hcard_class = $class->_trim($hcard_class); |
140
|
|
|
|
|
|
|
#We do this so that if the type is, for instance, |
141
|
|
|
|
|
|
|
# "agent vcard," that we just put the vcard in |
142
|
|
|
|
|
|
|
# agent, and not anywhere else. |
143
|
|
|
|
|
|
|
# vcard *MUST* have another class, otherwise we''ll |
144
|
|
|
|
|
|
|
# discard it. |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
130
|
|
|
|
|
298
|
my @types = split(" ", $hcard_class); |
148
|
130
|
|
|
|
|
195
|
foreach my $type (@types) |
149
|
|
|
|
|
|
|
{ |
150
|
143
|
|
|
|
|
201
|
$type =~ s/\-/\_/; |
151
|
143
|
|
|
|
|
496
|
$type = $class->_trim($type); |
152
|
|
|
|
|
|
|
|
153
|
143
|
|
|
|
|
149
|
my $data; |
154
|
143
|
|
|
|
|
436
|
my @cons = $bit->content_list; |
155
|
|
|
|
|
|
|
|
156
|
143
|
100
|
|
|
|
1127
|
unless (scalar @cons > 1) |
157
|
|
|
|
|
|
|
{ |
158
|
114
|
|
|
|
|
327
|
$data = $class->_trim($cons[0]); |
159
|
114
|
100
|
66
|
|
|
336
|
if ($bit->tag eq "abbr" && $bit->attr('title')) |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
160
|
|
|
|
|
|
|
{ |
161
|
9
|
|
|
|
|
209
|
$data = $class->_trim($bit->attr('title')); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
elsif ($bit->tag eq "a" && $bit->attr('href')) |
164
|
|
|
|
|
|
|
{ |
165
|
38
|
100
|
|
|
|
940
|
if ($type =~ m/(photo|logo|agent|sound|url)/) |
166
|
|
|
|
|
|
|
{ |
167
|
28
|
|
|
|
|
74
|
$data = $class->_trim($class->_url_decode($bit->attr('href'))); |
168
|
28
|
100
|
66
|
|
|
77
|
if ($bit->attr('rel') && $bit->attr('rel') eq "me") |
169
|
|
|
|
|
|
|
{ |
170
|
1
|
|
|
|
|
23
|
$rel_me = $data; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
elsif ($bit->tag eq "object" && $bit->attr('data')) |
175
|
|
|
|
|
|
|
{ |
176
|
2
|
100
|
|
|
|
57
|
if ($type =~ m/(photo|logo|agent|sound|url)/) |
177
|
|
|
|
|
|
|
{ |
178
|
1
|
|
|
|
|
3
|
$data = $class->_trim($bit->attr('data')); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
elsif ($bit->tag eq "img") |
182
|
|
|
|
|
|
|
{ |
183
|
2
|
100
|
66
|
|
|
52
|
if ($type =~ m/(photo|logo|agent|sound|url)/ && $bit->attr('src')) |
|
|
50
|
|
|
|
|
|
184
|
|
|
|
|
|
|
{ |
185
|
1
|
|
|
|
|
13
|
$data = $class->_trim($bit->attr('src')); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
elsif ($bit->attr('alt')) |
188
|
|
|
|
|
|
|
{ |
189
|
1
|
|
|
|
|
9
|
$data = $class->_trim($bit->attr('alt')); |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
143
|
100
|
|
|
|
2452
|
if ($type eq "vcard") |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
195
|
|
|
|
|
|
|
{ |
196
|
1
|
|
|
|
|
27
|
my $nestedcard = $class->from_tree($bit); |
197
|
1
|
50
|
|
|
|
3
|
if ($nested_goes_here) |
198
|
|
|
|
|
|
|
{ |
199
|
1
|
|
|
|
|
9
|
$card->$nested_goes_here($nestedcard); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
elsif ($type eq "tel") |
203
|
|
|
|
|
|
|
{ |
204
|
10
|
|
|
|
|
61
|
my $tel = Data::Microformat::hCard::type->from_tree($bit); |
205
|
10
|
|
|
|
|
66
|
$card->tel($tel); |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
elsif ($type eq "email") |
208
|
|
|
|
|
|
|
{ |
209
|
7
|
|
|
|
|
34
|
my $email = Data::Microformat::hCard::type->from_tree($bit); |
210
|
7
|
|
|
|
|
50
|
$card->email($email); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
elsif ($type eq "n") |
213
|
|
|
|
|
|
|
{ |
214
|
2
|
|
|
|
|
12
|
my $name = Data::Microformat::hCard::name->from_tree($bit); |
215
|
2
|
|
|
|
|
13
|
$card->n($name); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
elsif ($type eq "adr") |
218
|
|
|
|
|
|
|
{ |
219
|
7
|
|
|
|
|
61
|
my $adr = Data::Microformat::adr->from_tree($bit); |
220
|
7
|
|
|
|
|
47
|
$card->adr($adr); |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
elsif ($type eq "geo") |
223
|
|
|
|
|
|
|
{ |
224
|
4
|
|
|
|
|
28
|
my $geo = Data::Microformat::geo->from_tree($bit); |
225
|
4
|
|
|
|
|
29
|
$card->geo($geo); |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
elsif ($type eq "org") |
228
|
|
|
|
|
|
|
{ |
229
|
6
|
|
|
|
|
29
|
my $org = Data::Microformat::hCard::organization->from_tree($bit); |
230
|
6
|
|
|
|
|
40
|
$card->org($org); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
else |
233
|
|
|
|
|
|
|
{ |
234
|
106
|
|
|
|
|
311
|
eval { $card->$type($data); }; |
|
106
|
|
|
|
|
741
|
|
235
|
106
|
50
|
|
|
|
478
|
if ($@) |
236
|
|
|
|
|
|
|
{ |
237
|
0
|
|
|
|
|
0
|
print STDERR "Didn't recognize type $type.\n"; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Check: Implied N Optimization? |
247
|
23
|
100
|
100
|
|
|
146
|
if (!$card->n && $card->fn && (!$card->org || (!$card->fn eq $card->org))) |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
248
|
|
|
|
|
|
|
{ |
249
|
7
|
|
|
|
|
50
|
my $n = Data::Microformat::hCard::name->new; |
250
|
7
|
|
|
|
|
36
|
my @arr = split(" ", $card->fn); |
251
|
7
|
50
|
|
|
|
30
|
if ($arr[1]) |
252
|
|
|
|
|
|
|
{ |
253
|
7
|
|
|
|
|
17
|
$arr[1] =~ s/\.//; |
254
|
|
|
|
|
|
|
} |
255
|
7
|
50
|
33
|
|
|
42
|
if ($arr[0] =~ m/\,/ && length $arr[1] == 1) |
256
|
|
|
|
|
|
|
{ |
257
|
0
|
|
|
|
|
0
|
$arr[0] =~ s/\,//; |
258
|
0
|
|
|
|
|
0
|
$n->family_name($class->_trim($arr[0])); |
259
|
0
|
|
|
|
|
0
|
$n->given_name($class->_trim($arr[1])); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
else |
262
|
|
|
|
|
|
|
{ |
263
|
7
|
|
|
|
|
30
|
$n->family_name($class->_trim($arr[1])); |
264
|
7
|
|
|
|
|
35
|
$n->given_name($class->_trim($arr[0])); |
265
|
|
|
|
|
|
|
} |
266
|
7
|
|
|
|
|
41
|
$card->n($n); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# Check: Org? |
270
|
23
|
100
|
100
|
|
|
125
|
if (($card->org) && (($card->fn || "") eq $card->org->organization_name)) |
|
|
|
100
|
|
|
|
|
271
|
|
|
|
|
|
|
{ |
272
|
2
|
|
|
|
|
18
|
my $name = Data::Microformat::hCard::name->new; |
273
|
2
|
|
|
|
|
25
|
$name->family_name(" "); |
274
|
2
|
|
|
|
|
15
|
$name->given_name(" "); |
275
|
2
|
|
|
|
|
15
|
$name->additional_name(" "); |
276
|
2
|
|
|
|
|
14
|
$name->honorific_prefix(" "); |
277
|
2
|
|
|
|
|
24
|
$name->honorific_suffix(" "); |
278
|
2
|
|
|
|
|
15
|
$card->n($name); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# Check: Nickname Optimization? |
282
|
23
|
100
|
|
|
|
122
|
if ($card->fn) |
283
|
|
|
|
|
|
|
{ |
284
|
10
|
|
|
|
|
52
|
my @words = split(" ", $card->fn); |
285
|
10
|
0
|
66
|
|
|
73
|
if (($card->org && (!$card->org->organization_name eq $card->fn)) && (!$card->n) && (scalar @words == 1)) |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
286
|
|
|
|
|
|
|
{ |
287
|
0
|
|
|
|
|
0
|
$card->nickname($card->fn); |
288
|
0
|
|
|
|
|
0
|
my $name = Data::Microformat::hCard::name->new; |
289
|
0
|
|
|
|
|
0
|
$name->family_name(""); |
290
|
0
|
|
|
|
|
0
|
$name->given_name(""); |
291
|
0
|
|
|
|
|
0
|
$name->additional_name(""); |
292
|
0
|
|
|
|
|
0
|
$name->honorific_prefix(""); |
293
|
0
|
|
|
|
|
0
|
$name->honorific_suffix(""); |
294
|
0
|
|
|
|
|
0
|
$card->n($name); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
} |
297
|
23
|
|
|
|
|
56
|
$card->{_no_dupe_keys} = 0; |
298
|
23
|
|
|
|
|
101
|
push (@all_cards, $card); |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
17
|
|
|
|
|
95
|
$tree->delete; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Check: Representative hCard? |
304
|
17
|
100
|
|
|
|
3874
|
if ($representative_url) |
305
|
|
|
|
|
|
|
{ |
306
|
4
|
100
|
|
|
|
7
|
if (scalar @all_cards == 1) |
307
|
|
|
|
|
|
|
{ |
308
|
1
|
|
|
|
|
3
|
$all_cards[0]->{_representative} = 1; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
else |
311
|
|
|
|
|
|
|
{ |
312
|
3
|
|
|
|
|
4
|
my $found_one = 0; |
313
|
3
|
|
|
|
|
5
|
foreach my $card (@all_cards) |
314
|
|
|
|
|
|
|
{ |
315
|
5
|
100
|
66
|
|
|
19
|
if ($card->url && $card->uid && $card->url eq $card->uid && _normalize_url($card->url) eq _normalize_url($representative_url)) |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
316
|
|
|
|
|
|
|
{ |
317
|
1
|
|
|
|
|
2
|
$card->{_representative} = 1; |
318
|
1
|
|
|
|
|
2
|
$found_one = 1; |
319
|
1
|
|
|
|
|
1
|
last; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} |
322
|
3
|
100
|
|
|
|
8
|
if (!$found_one) |
323
|
|
|
|
|
|
|
{ |
324
|
2
|
|
|
|
|
5
|
foreach my $card (@all_cards) |
325
|
|
|
|
|
|
|
{ |
326
|
4
|
100
|
66
|
|
|
14
|
if ($card->url && $card->url eq $rel_me) |
327
|
|
|
|
|
|
|
{ |
328
|
1
|
|
|
|
|
2
|
$card->{_representative} = 1; |
329
|
1
|
|
|
|
|
2
|
last; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
17
|
100
|
|
|
|
63
|
if (wantarray) |
337
|
|
|
|
|
|
|
{ |
338
|
4
|
|
|
|
|
21
|
return @all_cards; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
else |
341
|
|
|
|
|
|
|
{ |
342
|
13
|
|
|
|
|
88
|
return $all_cards[0]; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub _normalize_url |
347
|
|
|
|
|
|
|
{ |
348
|
6
|
|
|
6
|
|
8
|
my $url = shift; |
349
|
6
|
|
|
|
|
13
|
$url =~ s/[A-Z]/[a-z]/; |
350
|
6
|
|
|
|
|
9
|
$url =~ s/\/$//; |
351
|
6
|
|
|
|
|
15
|
return $url; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
1; |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
__END__ |