ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Net-XMPP2/lib/Net/XMPP2/Ext/Disco.pm
Revision: 1.10
Committed: Thu Jul 26 19:45:46 2007 UTC (19 years, 2 months ago) by elmex
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +3 -2 lines
Log Message:
fixing up for release of 0.04

File Contents

# User Rev Content
1 elmex 1.3 package Net::XMPP2::Ext::Disco;
2 elmex 1.1 use Net::XMPP2::Namespaces qw/xmpp_ns/;
3 elmex 1.9 use Net::XMPP2::Util qw/simxml/;
4 elmex 1.3 use Net::XMPP2::Ext::Disco::Items;
5     use Net::XMPP2::Ext::Disco::Info;
6 elmex 1.6 use Net::XMPP2::Ext;
7    
8     our @ISA = qw/Net::XMPP2::Ext/;
9 elmex 1.1
10     =head1 NAME
11    
12 elmex 1.5 Net::XMPP2::Ext::Disco - Service discovery manager class for XEP-0030
13 elmex 1.1
14     =head1 SYNOPSIS
15    
16 elmex 1.3 use Net::XMPP2::Ext::Disco;
17 elmex 1.1
18     my $con = Net::XMPP2::IM::Connection->new (...);
19 elmex 1.7 $con->add_extension (my $disco = Net::XMPP2::Ext::Disco->new);
20 elmex 1.1 $disco->request_items ('romeo@montague.net',
21 elmex 1.8 sub {
22     my ($disco, $items, $error) = @_;
23 elmex 1.1 if ($error) { print "ERROR".$error->string."\n" }
24     else {
25 elmex 1.8 ... do something with the $items ...
26 elmex 1.1 }
27     }
28     );
29    
30     =head1 DESCRIPTION
31    
32     This module represents a service discovery manager class.
33     You make instances of this class and get a handle to send
34     discovery requests like described in XEP-0030.
35    
36     It also allows you to setup a disco-info/items tree
37     that others can walk and also lets you publish disco information.
38    
39 elmex 1.6 This class is derived from L<Net::XMPP2::Ext> and can be added as extension to
40     objects that implement the L<Net::XMPP2::Extendable> interface or derive from
41     it.
42    
43 elmex 1.1 =head1 METHODS
44    
45 elmex 1.4 =over 4
46    
47     =item B<new (%args)>
48 elmex 1.1
49 elmex 1.6 Creates a new disco handle.
50 elmex 1.1
51     =cut
52    
53     sub new {
54     my $this = shift;
55     my $class = ref($this) || $this;
56     my $self = bless { @_ }, $class;
57     $self->init;
58     $self
59     }
60    
61     sub init {
62     my ($self) = @_;
63    
64     $self->set_identity (client => console => 'Net::XMPP2');
65 elmex 1.9 $self->enable_feature (xmpp_ns ('disco_info'));
66     $self->enable_feature (xmpp_ns ('disco_items'));
67 elmex 1.1
68 elmex 1.6 $self->reg_cb (
69     iq_get_request_xml => sub {
70 elmex 1.9 my ($self, $con, $node) = @_;
71 elmex 1.1
72 elmex 1.6 if ($self->handle_disco_query ($con, $node)) {
73 elmex 1.9 return 1;
74 elmex 1.6 }
75 elmex 1.1
76 elmex 1.9 ()
77 elmex 1.6 }
78     );
79 elmex 1.1 }
80    
81 elmex 1.4 =item B<set_identity ($category, $type, $name)>
82 elmex 1.1
83     This sets the identity of the top info node.
84     The default is: C<$category = "client">, C<$type = "console">
85     and C<$name = "Net::XMPP2">.
86    
87     C<$name> is optional and can be undef.
88    
89     For a list of valid identites look at:
90    
91     http://www.xmpp.org/registrar/disco-categories.html
92    
93     Valid identity types for C<$category = "client"> may be:
94    
95     bot
96     console
97     handheld
98     pc
99     phone
100     web
101    
102     =cut
103    
104     sub set_identity {
105     my ($self, $category, $type, $name) = @_;
106     $self->{iden}->{cat} = $category;
107     $self->{iden}->{type} = $type;
108     $self->{iden}->{name} = $name;
109     }
110    
111    
112 elmex 1.4 =item B<enable_feature ($uri)>
113 elmex 1.1
114     This method enables the feature C<$uri>, where C<$uri>
115     should be one of the values from the B<Name> column on:
116    
117     http://www.xmpp.org/registrar/disco-features.html
118    
119     These features are enabled by default:
120    
121     http://jabber.org/protocol/disco#info
122     http://jabber.org/protocol/disco#items
123    
124     =cut
125    
126     sub enable_feature {
127     my ($self, $feature) = @_;
128     $self->{feat}->{$feature} = 1
129     }
130    
131 elmex 1.4 =item B<disable_feature ($uri)>
132 elmex 1.1
133     This method enables the feature C<$uri>, where C<$uri>
134     should be one of the values from the B<Name> column on:
135    
136     http://www.xmpp.org/registrar/disco-features.html
137    
138     These features are enabled by default:
139    
140     http://jabber.org/protocol/disco#info
141     http://jabber.org/protocol/disco#items
142    
143     =cut
144    
145     sub disable_feature {
146     my ($self, $feature) = @_;
147     delete $self->{feat}->{$feature}
148     }
149    
150     sub write_feature {
151     my ($self, $w, $var) = @_;
152    
153     $w->emptyTag ([xmpp_ns ('disco_info'), 'feature'], var => $var);
154     }
155    
156     sub write_identity {
157     my ($self, $w, $cat, $type, $name) = @_;
158    
159     $w->emptyTag ([xmpp_ns ('disco_info'), 'identity'],
160     category => $cat,
161     type => $type,
162     (defined $name ? (name => $name) : ())
163     );
164     }
165    
166     sub handle_disco_query {
167 elmex 1.6 my ($self, $con, $node) = @_;
168 elmex 1.1
169 elmex 1.10 my $q;
170     if (($q) = $node->find_all ([qw/disco_info query/])) {
171 elmex 1.6 $con->reply_iq_result (
172 elmex 1.1 $node, sub {
173     my ($w) = @_;
174    
175 elmex 1.9 if ($q->attr ('node')) {
176     simxml ($w, defns => 'disco_info', node => {
177     ns => 'disco_info', name => 'query',
178     attrs => [ node => $q->attr ('node') ]
179     });
180 elmex 1.1
181     } else {
182     $w->addPrefix (xmpp_ns ('disco_info'), '');
183     $w->startTag ([xmpp_ns ('disco_info'), 'query']);
184     $self->write_identity ($w,
185     $self->{iden}->{cat},
186     $self->{iden}->{type},
187     $self->{iden}->{name},
188     );
189 elmex 1.9 for (sort grep { $self->{feat}->{$_} } keys %{$self->{feat}}) {
190     $self->write_feature ($w, $_);
191     }
192 elmex 1.1 $w->endTag;
193     }
194 elmex 1.6 },
195     to => $node->attr ('from')
196 elmex 1.1 );
197    
198     return 1
199    
200 elmex 1.10 } elsif (($q) = $node->find_all ([qw/disco_items query/])) {
201 elmex 1.6 $con->reply_iq_result (
202 elmex 1.1 $node, sub {
203     my ($w) = @_;
204    
205 elmex 1.9 if ($q->attr ('node')) {
206     simxml ($w, defns => 'disco_items', node => {
207     ns => 'disco_items',
208     name => 'query',
209     attrs => [ node => $q->attr ('node') ]
210     });
211 elmex 1.1
212     } else {
213 elmex 1.9 simxml ($w, defns => 'disco_items', node => {
214     ns => 'disco_items',
215     name => 'query'
216     });
217 elmex 1.1 }
218 elmex 1.6 },
219     to => $node->attr ('from')
220 elmex 1.1 );
221    
222     return 1
223     }
224    
225     0
226     }
227    
228     sub DESTROY {
229     my ($self) = @_;
230     $self->{connection}->unreg_cb ($self->{cb_id})
231     }
232    
233 elmex 1.2
234 elmex 1.6 =item B<request_items ($con, $dest, $node, $cb)>
235 elmex 1.2
236     This method does send a items request to the JID entity C<$from>.
237     C<$node> is the optional node to send the request to, which can be
238     undef.
239 elmex 1.6 C<$con> must be an instance of L<Net::XMPP2::Connection> or a subclass of it.
240 elmex 1.2 The callback C<$cb> will be called when the request returns with 3 arguments:
241 elmex 1.3 the disco handle, an L<Net::XMPP2::Ext::Disco::Items> object (or undef)
242 elmex 1.2 and an L<Net::XMPP2::Error::IQ> object when an error occured and no items
243     were received.
244    
245 elmex 1.6 $disco->request_items ($con, 'a@b.com', undef, sub {
246 elmex 1.2 my ($disco, $items, $error) = @_;
247     die $error->string if $error;
248    
249     # do something with the items here ;_)
250     });
251    
252     =cut
253    
254     sub request_items {
255 elmex 1.6 my ($self, $con, $dest, $node, $cb) = @_;
256 elmex 1.2
257 elmex 1.6 $con->send_iq (
258 elmex 1.2 get => sub {
259     my ($w) = @_;
260     $w->addPrefix (xmpp_ns ('disco_items'), '');
261     $w->emptyTag ([xmpp_ns ('disco_items'), 'query'],
262     (defined $node ? (node => $node) : ())
263     );
264     },
265     sub {
266     my ($xmlnode, $error) = @_;
267     my $items;
268    
269     if ($xmlnode) {
270     my (@query) = $xmlnode->find_all ([qw/disco_items query/]);
271 elmex 1.3 $items = Net::XMPP2::Ext::Disco::Items->new (
272 elmex 1.2 jid => $dest,
273     node => $node,
274     xmlnode => $query[0]
275     )
276     }
277    
278     $cb->($self, $items, $error)
279     },
280     to => $dest
281     );
282     }
283    
284 elmex 1.6 =item B<request_info ($con, $dest, $node, $cb)>
285 elmex 1.2
286     This method does send a info request to the JID entity C<$from>.
287     C<$node> is the optional node to send the request to, which can be
288     undef.
289 elmex 1.6 C<$con> must be an instance of L<Net::XMPP2::Connection> or a subclass of it.
290 elmex 1.2 The callback C<$cb> will be called when the request returns with 3 arguments:
291 elmex 1.3 the disco handle, an L<Net::XMPP2::Ext::Disco::Info> object (or undef)
292 elmex 1.2 and an L<Net::XMPP2::Error::IQ> object when an error occured and no items
293     were received.
294    
295     $disco->request_info ('a@b.com', undef, sub {
296     my ($disco, $info, $error) = @_;
297     die $error->string if $error;
298    
299     # do something with info here ;_)
300     });
301    
302     =cut
303    
304     sub request_info {
305 elmex 1.6 my ($self, $con, $dest, $node, $cb) = @_;
306 elmex 1.2
307 elmex 1.6 $con->send_iq (
308 elmex 1.2 get => sub {
309     my ($w) = @_;
310     $w->addPrefix (xmpp_ns ('disco_info'), '');
311     $w->emptyTag ([xmpp_ns ('disco_info'), 'query'],
312     (defined $node ? (node => $node) : ())
313     );
314     },
315     sub {
316     my ($xmlnode, $error) = @_;
317     my $info;
318    
319     if ($xmlnode) {
320     my (@query) = $xmlnode->find_all ([qw/disco_info query/]);
321 elmex 1.3 $info = Net::XMPP2::Ext::Disco::Info->new (
322 elmex 1.2 jid => $dest,
323     node => $node,
324     xmlnode => $query[0]
325     )
326     }
327    
328     $cb->($self, $info, $error)
329     },
330     to => $dest
331     );
332     }
333    
334 elmex 1.4 =back
335    
336 elmex 1.1 =head1 AUTHOR
337    
338 elmex 1.4 Robin Redeker, C<< <elmex at ta-sa.org> >>, JID: C<< <elmex at jabber.org> >>
339 elmex 1.1
340     =head1 COPYRIGHT & LICENSE
341    
342     Copyright 2007 Robin Redeker, all rights reserved.
343    
344     This program is free software; you can redistribute it and/or modify it
345     under the same terms as Perl itself.
346    
347     =cut
348    
349     1;