Limit the number of simultaneous connect attempts passed to libpurple.
[thrasher.git] / perl / lib / Thrasher / Plugin / Vcard.pm
blobd8fb1c950d252e47131fc263c877dbd9939e4dc4
1 package Thrasher::Plugin::Vcard;
2 # The Perl module standard and the capitalization of vCard are in
3 # conflict. I like Perl better. Perl wins!
5 use strict;
6 use warnings;
8 =pod
10 =head1 NAME
12 Thrasher::Plugin::Vcard - implements vCard support for transport
13 users, including avatar support.
15 =head1 DESCRIPTION
17 This module replies when a user's vcard is requested, filling in their
18 avatar, and possibly other things. This module is intended to be
19 filled out, as more things that can be stuck in vCards are
20 implemented.
22 In the meantime, you get conventional avatars this way, including
23 full XEP-0153 support for avatar hash advertising.
25 =cut
27 use Thrasher::Log qw(log);
28 use Thrasher::Plugin qw(:all);
29 use Thrasher::XML qw(strip_resource);
30 use Thrasher::Constants qw(:all);
32 use Digest::SHA1 qw(sha1_hex);
33 use Carp qw(confess);
34 use Thrasher::Component qw(strip_resource);
36 # $user_jid -> $legacy_jid -> avatar sha1_hex
37 my %AVATARS;
39 register_plugin({client_iq_handlers =>
40 {$NS_VCARD => { get => \&return_vcard }},
41 component_iq_handlers =>
42 {$NS_VCARD => { get => \&return_component_vcard}},
43 features => [$NS_VCARD, $NS_VCARD_UPDATE],
44 callbacks => {
45 presence_out => { vcard => \&presence_hook },
46 avatar_changed => { vcard => \&avatar_update }
48 });
51 sub avatar_update {
52 my $component = shift;
53 my $user_jid = shift;
54 my $legacy_jid = shift;
55 my $raw_binary_data = shift;
56 my $base64_data = shift;
57 my $image = shift;
59 my $hash = sha1_hex($raw_binary_data);
60 my $old_hash = $AVATARS{$user_jid}->{$legacy_jid};
61 $AVATARS{$user_jid}->{$legacy_jid} = $hash;
63 if (!$old_hash || $hash ne $old_hash) {
64 my $session = $component->session_for($user_jid);
65 my $presence_info =
66 $session->{component}->{presence}->{strip_resource($user_jid)}->{strip_resource($legacy_jid)};
67 if (ref($presence_info) eq 'ARRAY') {
68 my ($type, $show, $status) = @$presence_info;
69 $component->send_presence_xml
70 ($user_jid, $type, $legacy_jid,
71 $show, $status);
76 sub presence_hook {
77 my $component = shift;
78 my $presence_tag = shift;
80 my $component_name = $component->{component_name};
82 my $user_jid = $presence_tag->[1]->{to};
83 my $legacy_jid = $presence_tag->[1]->{from};
85 if ($legacy_jid && $user_jid &&
86 $legacy_jid =~ /$component_name$/) {
87 my @children;
89 my $avatar_hash = $AVATARS{$user_jid}->{$legacy_jid};
90 if ($avatar_hash) {
91 push(@children, [[$NS_VCARD_UPDATE, 'photo'], {}, $avatar_hash]);
94 push(@{$presence_tag->[2]},
95 [[$NS_VCARD_UPDATE, 'x'], {}, \@children]);
98 return 1;
101 sub return_component_vcard {
102 my $component = shift;
103 my $iq_params = shift;
104 my $iq_tag = shift;
106 my $vcard = [[$NS_VCARD, 'vCard'], {},
108 [[$NS_VCARD, 'EMAIL'], {},
109 [[[$NS_VCARD, 'USERID'], {},
110 [$component->{component_name}]]]]]];
111 $component->iq_reply($iq_params, $vcard);
114 sub return_vcard {
115 my $component = shift;
116 my $iq_params = shift;
117 my $iq_tag = shift;
119 my $vcard_target = strip_resource($iq_params->{to});
120 my $request_from = strip_resource($iq_params->{from});
122 my $avatar =
123 $component->{protocol}->{backend}->get_avatar($request_from,
124 $vcard_target);
126 my $vcard;
127 if ($avatar) {
128 $vcard = [[$NS_VCARD, 'vCard'], {},
130 [[$NS_VCARD, 'PHOTO'], {},
132 [[$NS_VCARD, 'TYPE'], {}, ['image/png']],
133 [[$NS_VCARD, 'BINVAL'], {}, [$avatar]]
136 } else {
137 $vcard = [[$NS_VCARD, 'vCard'], {}, []];
140 $component->iq_reply($iq_params, $vcard);