File Coverage

blib/lib/Net/XMPP3/Roster.pm
Criterion Covered Total %
statement 200 257 77.8
branch 88 164 53.6
condition 11 30 36.6
subroutine 21 29 72.4
pod 0 25 0.0
total 320 505 63.3


line stmt bran cond sub pod time code
1             ##############################################################################
2             #
3             # This library is free software; you can redistribute it and/or
4             # modify it under the terms of the GNU Library General Public
5             # License as published by the Free Software Foundation; either
6             # version 2 of the License, or (at your option) any later version.
7             #
8             # This library is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11             # Library General Public License for more details.
12             #
13             # You should have received a copy of the GNU Library General Public
14             # License along with this library; if not, write to the
15             # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16             # Boston, MA 02111-1307, USA.
17             #
18             # Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
19             #
20             ##############################################################################
21              
22             package Net::XMPP3::Roster;
23              
24             =head1 NAME
25              
26             Net::XMPP3::Roster - XMPP Roster Object
27              
28             =head1 SYNOPSIS
29              
30             Net::XMPP3::Roster is a module that provides a developer an easy
31             interface to an XMPP roster. It provides high level functions to
32             query, update, and manage a user's roster.
33              
34             =head1 DESCRIPTION
35              
36             The Roster object seeks to provide an easy to use API for interfacing
37             with a user's roster. When you instantiate it, it automatically
38             registers with the connection to receivce the correct packets so
39             that it can track all roster updates, and presence packets.
40              
41             =head2 Basic Functions
42              
43             my $Client = new Net::XMPP3::Client(...);
44              
45             my $Roster = new Net::XMPP3::Roster(connection=>$Client);
46             or
47             my $Roster = $Client->Roster();
48              
49             $Roster->clear();
50              
51             if ($Roster->exists('bob@jabber.org')) { ... }
52             if ($Roster->exists(Net::XMPP3::JID)) { ... }
53              
54             if ($Roster->groupExists("Friends")) { ... }
55              
56             my @groups = $Roster->groups();
57              
58             my @jids = $Roster->jids();
59             my @friends = $Roster->jids("group","Friends");
60             my @unfiled = $Roster->jids("nogroup");
61              
62             if ($Roster->online('bob@jabber.org')) { ... }
63             if ($Roster->online(Net::XMPP3::JID)) { ... }
64              
65             my %hash = $Roster->query('bob@jabber.org');
66             my %hash = $Roster->query(Net::XMPP3::JID);
67              
68             my $name = $Roster->query('bob@jabber.org',"name");
69             my $ask = $Roster->query(Net::XMPP3::JID,"ask");
70              
71             my $resource = $Roster->resource('bob@jabber.org');
72             my $resource = $Roster->resource(Net::XMPP3::JID);
73              
74             my %hash = $Roster->resourceQuery('bob@jabber.org',"Home");
75             my %hash = $Roster->resourceQuery(Net::XMPP3::JID,"Club");
76              
77             my $show = $Roster->resourceQuery('bob@jabber.org',"Home","show");
78             my $status = $Roster->resourceQuery(Net::XMPP3::JID,"Work","status");
79              
80             my @resource = $Roster->resources('bob@jabber.org');
81             my @resource = $Roster->resources(Net::XMPP3::JID);
82              
83             $Roster->resourceStore('bob@jabber.org',"Home","gpgkey",key);
84             $Roster->resourceStore(Net::XMPP3::JID,"logged on","2004/04/07 ...");
85              
86             $Roster->store('bob@jabber.org',"avatar",avatar);
87             $Roster->store(Net::XMPP3::JID,"display_name","Bob");
88              
89             =head2 Advanced Functions
90              
91             These functions are only needed if you want to manually control
92             the Roster.
93              
94             $Roster->add('bob@jabber.org',
95             name=>"Bob",
96             groups=>["Friends"]
97             );
98             $Roster->add(Net::XMPP3::JID);
99              
100             $Roster->addResource('bob@jabber.org',
101             "Home",
102             show=>"dnd",
103             status=>"Working"
104             );
105             $Roster->addResource(Net::XMPP3::JID,"Work");
106              
107             $Roster->remove('bob@jabber.org');
108             $Roster->remove(Net::XMPP3::JID);
109              
110             $Roster->removeResource('bob@jabber.org',"Home");
111             $Roster->removeResource(Net::XMPP3::JID,"Work");
112              
113             $Roster->handler(Net::XMPP3::IQ);
114             $Roster->handler(Net::XMPP3::Presence);
115              
116             =head1 METHODS
117              
118             =head2 Basic Functions
119              
120              
121             new(connection=>object) - This creates and initializes the Roster
122             object. The connection object is required
123             so that the Roster can interact with the
124             main connection object. It needs to be an
125             object that inherits from
126             Net::XMPP3::Connection.
127              
128             clear() - removes everything from the database.
129              
130             exists(jid) - return 1 if the JID exists in the database, undef
131             otherwise. The jid can either be a string, or a
132             Net::XMPP3::JID object.
133              
134             groupExists(group) - return 1 if the group exists in the database,
135             undef otherwise.
136              
137             groups() - returns a list of all of the roster groups.
138              
139             jids([type, - returns a list of all of the matching JIDs. The valid
140             [group]]) types are:
141              
142             all - return all JIDs in the roster. (default)
143             nogroup - return all JIDs not in a roster group.
144             group - return all of the JIDs in the specified
145             roster group.
146              
147             online(jid) - return 1 if the JID is online, undef otherwise. The
148             jid can either be a string, or a Net::XMPP3::JID object.
149              
150             query(jid, - return a hash representing all of the data in the
151             [key]) DB for this JID. The jid can either be a string,
152             or a Net::XMPP3::JID object. If you specify a key,
153             then only the value for that key is returned.
154              
155             resource(jid) - return the string representing the resource with the
156             highest priority for the JID. The jid can either be
157             a string, or a Net::XMPP3::JID object.
158              
159             resourceQuery(jid, - return a hash representing all of the data
160             resource, the DB for the resource for this JID. The
161             [key]) jid can either be a string, or a
162             Net::XMPP3::JID object. If you specify a
163             key, then only the value for that key is
164             returned.
165              
166             resources(jid) - returns the list of resources for the JID in order
167             of highest priority to lowest priority. The jid can
168             either be a string, or a Net::XMPP3::JID object.
169              
170             resourceStore(jid, - store the specified value in the DB under
171             resource, the specified key for the resource for this
172             key, JID. The jid can either be a string, or a
173             value) Net::XMPP3::JID object.
174              
175             store(jid, - store the specified value in the DB under the
176             key, specified key for this JID. The jid can either
177             value) be a string, or a Net::XMPP3::JID object.
178              
179              
180              
181             =head2 Advanced Functions
182              
183             add(jid, - Manually adds the JID to the Roster with the
184             ask=>string, specified roster item settings. This does not
185             groups=>arrayref handle subscribing to other users, only
186             name=>string, manipulating the Roster object. The jid
187             subscription=>string) can either be a string or a Net::XMPP3::JID.
188              
189             addResource(jid, - Manually add the resource to the JID in the
190             resource, Roster with the specified presence settings.
191             priority=>int, This does not handle subscribing to other
192             show=>string, users, only manipulating the Roster object.
193             status=>string) The jid can either be a string or a
194             Net::XMPP3::JID.
195              
196             remove(jid) - Removes all reference to the JID from the Roster object.
197             The jid can either be a string or a Net::XMPP3::JID.
198              
199             removeResource(jid, - Removes the resource from the jid in the
200             resource) Roster object. The jid can either be a string
201             or a Net::XMPP3::JID.
202              
203             handler(packet) - Take either a Net::XMPP3::IQ or Net::XMPP3::Presence
204             packet and parse them according to the rules of the
205             Roster object. Note, that it will only waste CPU time
206             if you pass in IQs or Presences that are not roster
207             related.
208              
209             =head1 AUTHOR
210              
211             Ryan Eatmon
212              
213             =head1 COPYRIGHT
214              
215             This module is free software, you can redistribute it and/or modify it
216             under the LGPL.
217              
218             =cut
219              
220 11     11   65 use strict;
  11         17  
  11         391  
221 11     11   64 use Carp;
  11         24  
  11         37519  
222              
223             sub new
224             {
225 1     1 0 1716 my $proto = shift;
226 1         3 my $self = { };
227              
228 1         2 my %args;
229 1         10 while($#_ >= 0) { $args{ lc(pop(@_)) } = pop(@_); }
  1         6  
230              
231 1 50 33     12 if (!exists($args{connection}) ||
232             !$args{connection}->isa("Net::XMPP3::Connection"))
233             {
234 0         0 croak("You must pass Net::XMPP3::Roster a valid connection object.");
235             }
236              
237 1         4 $self->{CONNECTION} = $args{connection};
238              
239 1         2 bless($self, $proto);
240              
241 1         5 $self->init();
242              
243 1         4 return $self;
244             }
245              
246              
247             ##############################################################################
248             #
249             # init - initialize the module to use the roster database
250             #
251             ##############################################################################
252             sub init
253             {
254 1     1 0 2 my $self = shift;
255              
256 1     0   20 $self->{CONNECTION}-> SetXPathCallBacks('/iq[@type="result" or @type="set"]/query[@xmlns="jabber:iq:roster"]'=>sub{ $self->handler(@_) });
  0         0  
257 1     0   9 $self->{CONNECTION}-> SetXPathCallBacks('/presence'=>sub{ $self->handler(@_) });
  0         0  
258             }
259              
260              
261             ##############################################################################
262             #
263             # add - adds the entry to the Roster DB.
264             #
265             ##############################################################################
266             sub add
267             {
268 2     2 0 6 my $self = shift;
269 2         10 my ($jid,%item) = @_;
270              
271 2 50       17 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
272              
273 2         9 $self->{JIDS}->{$jid} = \%item;
274              
275 2 100       133 if (exists($item{groups}))
276             {
277 1         4 foreach my $group (@{$item{groups}})
  1         4  
278             {
279 2         11 $self->{GROUPS}->{$group}->{$jid} = 1;
280             }
281             }
282             }
283              
284              
285              
286             ##############################################################################
287             #
288             # addResource - adds the resource to the JID in the Roster DB.
289             #
290             ##############################################################################
291             sub addResource
292             {
293 2     2 0 5 my $self = shift;
294 2         4 my $jid = shift;
295 2         3 my $resource = shift;
296 2         7 my (%item) = @_;
297              
298 2 50       17 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
299              
300 2         5 my $priority = $item{priority};
301 2 100       5 $priority = 0 unless defined($priority);
302              
303 2         38 $self->{CONNECTION}->{DEBUG}->Log3("Roster::addResource: add $jid/$resource with priority $priority to the DB");
304              
305 2         7 my $loc = -1;
306 2 50       15 $self->{JIDS}->{$jid}->{priorities}->{$priority} = []
307             unless exists($self->{JIDS}->{$jid}->{priorities}->{$priority});
308 2         3 foreach my $index (0..$#{$self->{JIDS}->{$jid}->{priorities}->{$priority}})
  2         10  
309             {
310 0 0       0 $loc = $index
311             if ($self->{JIDS}->{$jid}->{priorities}->{$priority}->[$index]->{resource} eq $resource);
312             }
313 2 50       7 $loc = $#{$self->{JIDS}->{$jid}->{priorities}->{$priority}} + 1 if ($loc == -1);
  2         7  
314              
315 2         12 $self->{JIDS}->{$jid}->{resources}->{$resource}->{priority} = $priority;
316 2 100       9 $self->{JIDS}->{$jid}->{resources}->{$resource}->{status} = $item{status}
317             if exists($item{status});
318 2 100       7 $self->{JIDS}->{$jid}->{resources}->{$resource}->{show} = $item{show}
319             if exists($item{show});
320 2         11 $self->{JIDS}->{$jid}->{priorities}->{$priority}->[$loc]->{resource} = $resource;
321             }
322              
323              
324             ###############################################################################
325             #
326             # clear - delete all of the JIDs from the DB completely.
327             #
328             ###############################################################################
329             sub clear
330             {
331 1     1 0 3 my $self = shift;
332              
333 1         8 $self->{CONNECTION}->{DEBUG}->Log3("Roster::clear: clearing the database");
334 1         5 foreach my $jid ($self->jids())
335             {
336 1         4 $self->remove($jid);
337             }
338 1         9 $self->{CONNECTION}->{DEBUG}->Log3("Roster::clear: database is empty");
339             }
340              
341              
342             ##############################################################################
343             #
344             # exists - allows you to query if the JID exists in the Roster DB.
345             #
346             ##############################################################################
347             sub exists
348             {
349 68     68 0 1052 my $self = shift;
350 68         106 my ($jid) = @_;
351              
352 68 50       828 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
353              
354 68 100       186 return unless exists($self->{JIDS});
355 64 100       206 return unless exists($self->{JIDS}->{$jid});
356 62         380 return 1;
357             }
358              
359              
360             sub fetch
361             {
362 0     0 0 0 my $self = shift;
363              
364 0         0 my %newroster = $self->{CONNECTION}->RosterGet();
365              
366 0         0 $self->handleRoster(\%newroster);
367             }
368              
369              
370             ##############################################################################
371             #
372             # groupExists - allows you to query if the group exists in the Roster
373             # DB.
374             #
375             ##############################################################################
376             sub groupExists
377             {
378 8     8 0 127 my $self = shift;
379 8         15 my ($group) = @_;
380              
381 8 100       38 return unless exists($self->{GROUPS});
382 4 50       12 return unless exists($self->{GROUPS}->{$group});
383 4         21 return 1;
384             }
385              
386              
387             ##############################################################################
388             #
389             # groups - returns a list of the current groups in your roster.
390             #
391             ##############################################################################
392             sub groups
393             {
394 0     0 0 0 my $self = shift;
395              
396 0 0       0 return () unless exists($self->{GROUPS});
397 0 0       0 return () if (scalar(keys(%{$self->{GROUPS}})) == 0);
  0         0  
398 0         0 return keys(%{$self->{GROUPS}});
  0         0  
399             }
400              
401              
402             ##############################################################################
403             #
404             # handler - takes a packet and calls the correct handler.
405             #
406             ##############################################################################
407             sub handler
408             {
409 0     0 0 0 my $self = shift;
410 0         0 my $sid = shift;
411 0         0 my $packet = shift;
412              
413 0 0       0 $self->handleIQ($packet) if ($packet->GetTag() eq "iq");
414 0 0       0 $self->handlePresence($packet) if ($packet->GetTag() eq "presence");
415             }
416              
417              
418             ##############################################################################
419             #
420             # handleIQ - takes an iq packet that contains roster, parses it, and puts
421             # the roster into the Roster DB.
422             #
423             ##############################################################################
424             sub handleIQ
425             {
426 0     0 0 0 my $self = shift;
427 0         0 my $iq = shift;
428              
429 0         0 print "handleIQ: iq(",$iq->GetXML(),")\n";
430              
431 0         0 my $type = $iq->GetType();
432 0 0 0     0 return unless (($type eq "set") || ($type eq "result"));
433              
434 0         0 my %newroster = $self->{CONNECTION}->RosterParse($iq);
435              
436 0         0 $self->handleRoster(\%newroster);
437             }
438              
439              
440             sub handleRoster
441             {
442 0     0 0 0 my $self = shift;
443 0         0 my $roster = shift;
444              
445 0         0 foreach my $jid (keys(%{$roster}))
  0         0  
446             {
447 0         0 $self->remove($jid);
448              
449 0 0       0 if ($roster->{$jid}->{subscription} ne "remove")
450             {
451 0         0 $self->add($jid, %{$roster->{$jid}});
  0         0  
452             }
453             }
454             }
455              
456              
457             ##############################################################################
458             #
459             # handlePresence - takes a presence packet and groks the presence.
460             #
461             ##############################################################################
462             sub handlePresence
463             {
464 0     0 0 0 my $self = shift;
465 0         0 my $presence = shift;
466              
467 0         0 print "handlePresence: presence(",$presence->GetXML(),")\n";
468              
469 0         0 my $type = $presence->GetType();
470 0 0       0 $type = "" unless defined($type);
471 0 0 0     0 return unless (($type eq "") ||
      0        
472             ($type eq "available") ||
473             ($type eq "unavailable"));
474              
475 0         0 my $jid = $presence->GetFrom("jid");
476              
477 0         0 my $resource = $jid->GetResource();
478 0 0       0 $resource = " " unless ($resource ne "");
479              
480 0         0 $jid = $jid->GetJID();
481 0 0       0 $jid = "" unless defined($jid);
482              
483 0 0       0 return unless $self->exists($jid);
484             #XXX if it doesn't exist... is it us?
485             #XXX is this a presence based roster?
486              
487 0         0 $self->{CONNECTION}->{DEBUG}->Log3("Roster::PresenceDBParse: fromJID(",$presence->GetFrom(),") resource($resource) type($type)");
488 0         0 $self->{CONNECTION}->{DEBUG}->Log4("Roster::PresenceDBParse: xml(",$presence->GetXML(),")");
489              
490 0         0 $self->removeResource($jid,$resource);
491              
492 0 0 0     0 if (($type eq "") || ($type eq "available"))
493             {
494 0         0 my %item;
495              
496 0         0 $item{priority} = $presence->GetPriority();
497 0 0       0 $item{priority} = 0 unless defined($item{priority});
498              
499 0         0 $item{show} = $presence->GetShow();
500 0 0       0 $item{show} = "" unless defined($item{show});
501              
502 0         0 $item{status} = $presence->GetStatus();
503 0 0       0 $item{status} = "" unless defined($item{status});
504              
505 0         0 $self->addResource($jid,$resource,%item);
506             }
507             }
508              
509              
510             ##############################################################################
511             #
512             # jids - returns a list of all of the JIDs in your roster.
513             #
514             ##############################################################################
515             sub jids
516             {
517 8     8 0 256 my $self = shift;
518 8         13 my $type = shift;
519 8         12 my $group = shift;
520              
521 8 100       23 $type = "all" unless defined($type);
522              
523 8         10 my @jids;
524              
525 8 100 100     33 if (($type eq "all") || ($type eq "nogroup"))
526             {
527 6 100       24 return () unless exists($self->{JIDS});
528 5         8 foreach my $jid (keys(%{$self->{JIDS}}))
  5         19  
529             {
530 1         9 next if (($type eq "nogroup") &&
531             exists($self->{JIDS}->{$jid}->{groups}) &&
532 8 100 100     36 ($#{$self->{JIDS}->{$jid}->{groups}} > -1));
      66        
533              
534 7         32 push(@jids,new Net::XMPP3::JID($jid));
535             }
536             }
537              
538 7 100       22 if ($type eq "group")
539             {
540 2 50       8 return () unless exists($self->{GROUPS});
541 2 50 33     11 if (defined($group) && $self->groupExists($group))
542             {
543 2         3 foreach my $jid (keys(%{$self->{GROUPS}->{$group}}))
  2         9  
544             {
545 2         8 push(@jids,new Net::XMPP3::JID($jid));
546             }
547             }
548             }
549              
550 7         47 return @jids;
551             }
552              
553              
554             ###############################################################################
555             #
556             # online - returns if the jid is online or not.
557             #
558             ###############################################################################
559             sub online
560             {
561 12     12 0 3262 my $self = shift;
562 12         31 my $jid = shift;
563              
564 12 50       122 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
565              
566 12 50       38 return unless $self->exists($jid);
567              
568 12         122 my @resources = $self->resources($jid);
569              
570 12         73 return ($#resources > -1);
571             }
572              
573              
574             ##############################################################################
575             #
576             # priority - return the highest priority for the jid, or for the specified
577             # resource.
578             #
579             ##############################################################################
580             sub priority
581             {
582 6     6 0 19 my $self = shift;
583 6         10 my $jid = shift;
584 6         10 my $resource = shift;
585              
586 6 50       116 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
587              
588 6 100       14 if (defined($resource))
589             {
590 2 50       6 return unless $self->resourceExists($jid,$resource);
591 2 50       12 return unless exists($self->{JIDS}->{$jid}->{resources}->{$resource}->{priority});
592 2         11 return $self->{JIDS}->{$jid}->{resources}->{$resource}->{priority};
593             }
594              
595 4 50       16 return unless exists($self->{JIDS}->{$jid}->{priorities});
596 4         5 my @priorities = sort{ $b <=> $a } keys(%{$self->{JIDS}->{$jid}->{priorities}});
  1         6  
  4         19  
597 4         11 return $priorities[0];
598             }
599              
600              
601             ##############################################################################
602             #
603             # query - allows you to get one of the pieces of info from the Roster DB.
604             #
605             ##############################################################################
606             sub query
607             {
608 9     9 0 1078 my $self = shift;
609 9         13 my $jid = shift;
610 9         15 my $key = shift;
611              
612 9 50       68 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
613              
614 9 50       22 return unless $self->exists($jid);
615 9 100       24 if (defined($key))
616             {
617 7 100       31 return unless exists($self->{JIDS}->{$jid}->{$key});
618 5         36 return $self->{JIDS}->{$jid}->{$key};
619             }
620 2         3 return %{$self->{JIDS}->{$jid}};
  2         15  
621             }
622              
623              
624             ##############################################################################
625             #
626             # remove - removes the JID from the Roster DB.
627             #
628             ##############################################################################
629             sub remove
630             {
631 2     2 0 228 my $self = shift;
632 2         4 my $jid = shift;
633              
634 2 100       22 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
635              
636 2 50       7 if ($self->exists($jid))
637             {
638 2         22 $self->{CONNECTION}->{DEBUG}->Log3("Roster::remove: deleting $jid from the DB");
639              
640 2 100       8 if (defined($self->query($jid,"groups")))
641             {
642 1         2 foreach my $group (@{$self->query($jid,"groups")})
  1         4  
643             {
644 2         7 delete($self->{GROUPS}->{$group}->{$jid});
645 2         11 delete($self->{GROUPS}->{$group})
646 2 50       3 if (scalar(keys(%{$self->{GROUPS}->{$group}})) == 0);
647 2         12 delete($self->{GROUPS})
648 2 100       4 if (scalar(keys(%{$self->{GROUPS}})) == 0);
649             }
650             }
651              
652 2         11 delete($self->{JIDS}->{$jid});
653 2 100       4 delete($self->{JIDS}) if (scalar(keys(%{$self->{JIDS}})) == 0);
  2         12  
654             }
655             }
656              
657              
658             ##############################################################################
659             #
660             # removeResource - removes the resource from the JID from the Roster DB.
661             #
662             ##############################################################################
663             sub removeResource
664             {
665 2     2 0 6 my $self = shift;
666 2         4 my $jid = shift;
667 2         4 my $resource = shift;
668              
669 2 50       17 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
670              
671 2 50       8 if ($self->resourceExists($jid,$resource))
672             {
673 2         27 $self->{CONNECTION}->{DEBUG}->Log3("Roster::removeResource: remove $jid/$resource from the DB");
674              
675 2         9 my $oldPriority = $self->priority($jid,$resource);
676 2 50       7 $oldPriority = "" unless defined($oldPriority);
677              
678 2 50       10 if (exists($self->{JIDS}->{$jid}->{priorities}->{$oldPriority}))
679             {
680 2         5 my $loc = 0;
681 2         5 foreach my $index (0..$#{$self->{JIDS}->{$jid}->{priorities}->{$oldPriority}})
  2         10  
682             {
683 2 50       13 $loc = $index
684             if ($self->{JIDS}->{$jid}->{priorities}->{$oldPriority}->[$index]->{resource} eq $resource);
685             }
686              
687 2         5 splice(@{$self->{JIDS}->{$jid}->{priorities}->{$oldPriority}},$loc,1);
  2         8  
688              
689 2         17 delete($self->{JIDS}->{$jid}->{priorities}->{$oldPriority})
690             if (exists($self->{JIDS}->{$jid}->{priorities}->{$oldPriority}) &&
691 2 50 33     14 ($#{$self->{JIDS}->{$jid}->{priorities}->{$oldPriority}} == -1));
692             }
693              
694 2         12 delete($self->{JIDS}->{$jid}->{resources}->{$resource});
695              
696             }
697             }
698              
699              
700             ###############################################################################
701             #
702             # resource - retrieve the resource with the highest priority.
703             #
704             ###############################################################################
705             sub resource
706             {
707 4     4 0 10 my $self = shift;
708 4         5 my $jid = shift;
709              
710 4 50       31 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
711              
712 4 50       126 return unless $self->exists($jid);
713              
714 4         12 my $priority = $self->priority($jid);
715              
716 4 100       15 return unless defined($priority);
717              
718 3         20 return $self->{JIDS}->{$jid}->{priorities}->{$priority}->[0]->{resource};
719             }
720              
721              
722             ##############################################################################
723             #
724             # resourceExists - check that the specified resource exists.
725             #
726             ##############################################################################
727             sub resourceExists
728             {
729 12     12 0 15 my $self = shift;
730 12         17 my $jid = shift;
731 12         15 my $resource = shift;
732              
733 12 50       67 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
734              
735 12 50       26 return unless $self->exists($jid);
736 12 50       39 return unless exists($self->{JIDS}->{$jid}->{resources});
737 12 50       64 return unless exists($self->{JIDS}->{$jid}->{resources}->{$resource});
738             }
739              
740              
741             ##############################################################################
742             #
743             # resourceQuery - allows you to get one of the pieces of info from the Roster
744             # DB.
745             #
746             ##############################################################################
747             sub resourceQuery
748             {
749 7     7 0 1260 my $self = shift;
750 7         9 my $jid = shift;
751 7         11 my $resource = shift;
752 7         9 my $key = shift;
753              
754 7 50       50 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
755              
756 7 50       18 return unless $self->resourceExists($jid,$resource);
757 7 100       20 if (defined($key))
758             {
759 4 100       19 return unless exists($self->{JIDS}->{$jid}->{resources}->{$resource}->{$key});
760 3         17 return $self->{JIDS}->{$jid}->{resources}->{$resource}->{$key};
761             }
762 3         4 return %{$self->{JIDS}->{$jid}->{resources}->{$resource};}
  3         26  
763             }
764              
765              
766             ###############################################################################
767             #
768             # resources - returns a list of the resources from highest priority to lowest.
769             #
770             ###############################################################################
771             sub resources
772             {
773 16     16 0 1097 my $self = shift;
774 16         20 my $jid = shift;
775              
776 16 50       102 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
777              
778 16 50       41 return () unless $self->exists($jid);
779              
780 16         31 my @resources;
781              
782 16         26 foreach my $priority (sort {$b cmp $a} keys(%{$self->{JIDS}->{$jid}->{priorities}}))
  3         12  
  16         93  
783             {
784 9         15 foreach my $index (0..$#{$self->{JIDS}->{$jid}->{priorities}->{$priority}})
  9         32  
785             {
786 9 50       35 next if ($self->{JIDS}->{$jid}->{priorities}->{$priority}->[$index]->{resource} eq " ");
787 9         43 push(@resources,$self->{JIDS}->{$jid}->{priorities}->{$priority}->[$index]->{resource});
788             }
789             }
790 16         141 return @resources;
791             }
792              
793              
794             ##############################################################################
795             #
796             # resourceStore - allows you to store anything on the item that you want to.
797             # The only drawback is that when the item is removed, the data
798             # is not kept. You must restore it in the DB.
799             #
800             ##############################################################################
801             sub resourceStore
802             {
803 1     1 0 3 my $self = shift;
804 1         3 my $jid = shift;
805 1         3 my $resource = shift;
806 1         2 my $key = shift;
807 1         3 my $value = shift;
808              
809 1 50       10 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
810              
811 1 50       4 return unless defined($key);
812 1 50       5 return unless defined($value);
813 1 50       3 return unless $self->resourceExists($jid,$resource);
814              
815 1         5 $self->{JIDS}->{$jid}->{resources}->{$resource}->{$key} = $value;
816             }
817              
818              
819             ##############################################################################
820             #
821             # store - allows you to store anything on the item that you want to. The
822             # only drawback is that when the item is removed, the data is not
823             # kept. You must restore it in the DB.
824             #
825             ##############################################################################
826             sub store
827             {
828 1     1 0 4 my $self = shift;
829 1         2 my $jid = shift;
830 1         4 my $key = shift;
831 1         2 my $value = shift;
832              
833 1 50       9 $jid = $jid->GetJID() if $jid->isa("Net::XMPP3::JID");
834              
835 1 50       4 return unless defined($key);
836 1 50       5 return unless defined($value);
837 1 50       5 return unless $self->exists($jid);
838              
839 1         5 $self->{JIDS}->{$jid}->{$key} = $value;
840             }
841              
842              
843             1;
844