source: perl/modules/jabber.pl @ 6a6dd47

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 6a6dd47 was 6a6dd47, checked in by Alejandro R. Sedeño <asedeno@mit.edu>, 17 years ago
jabber.pl: * Multiple connections now possible. * Password-based authentication now possible. * jabberlogin now requires a login jid. * jabberlogin now uses _xmpp-client._tcp srv record for lookup. If no record exists, server part of jid is used with port 5222. * Eliminated various globals. Current globals are: $connections -> Holds all the client and roster objects, indexed by full jid. $connections->{JID}->{client} $connections->{JID}->{roster} %vars -> used to pass data around between functions and related callbacks. * New dependences: Getopt::Long, Net::DNS README: added a readme. It probably wants more in it.
  • Property mode set to 100644
File size: 19.3 KB
Line 
1package owl_jabber;
2use Authen::SASL qw(Perl);
3use Net::Jabber;
4use Net::DNS;
5use Getopt::Long;
6
7################################################################################
8# owl perl jabber support
9#
10# XXX Todo:
11# Rosters for MUCs
12# More user feedback
13#  * joining MUC
14#  * parting MUC
15#  * presence (Roster and MUC)
16# Implementing formatting and logging callbacks for C
17# Appropriate callbacks for presence subscription messages.
18#  * Current behavior => auto-accept (default for Net::Jabber)
19#
20################################################################################
21
22our $connections;
23our %vars;
24
25sub onStart
26{
27    if(eval{\&owl::queue_message}) 
28    {
29        register_owl_commands();
30        push @::onMainLoop, sub { owl_jabber::onMainLoop(@_) };
31        push @::onGetBuddyList, sub { owl_jabber::onGetBuddyList(@_) };
32    }
33    else
34    {
35        # Our owl doesn't support queue_message. Unfortunately, this
36        # means it probably *also* doesn't support owl::error. So just
37        # give up silently.
38    }
39}
40push @::onStartSubs, sub { owl_jabber::onStart(@_) };
41
42sub onMainLoop
43{
44    return if (!connected());
45   
46    foreach my $jid (keys %$connections)
47    {
48        my $client = \$connections->{$jid}->{client};
49
50        my $status = $$client->Process(0);
51        if ($status == 0     # No data received
52        || $status == 1) # Data received
53        {
54        }
55        else #Error
56        {
57            do_logout($jid);
58            return;
59        }
60       
61        if ($::shutdown)
62        {
63            do_logout($jid);
64            return;
65        }
66    }
67}
68
69sub blist_listBuddy
70{
71    my $roster = shift;
72    my $buddy = shift;
73    my $blistStr .= "    ";
74    my %jq = $$roster->query($buddy);
75    my $res = $$roster->resource($buddy);
76
77    $blistStr .= $jq{name} ? $jq{name} : $buddy->GetJID();
78   
79    if ($res)
80    {
81        my %rq = $$roster->resourceQuery($buddy, $res);
82        $blistStr .= " [".($rq{show} ? $rq{show} : 'online')."]";
83        $blistStr .= " ".$rq{status} if $rq{status};
84        $blistStr = boldify($blistStr);
85    }
86    else
87    {
88        $blistStr .= $jq{ask} ? " [pending]" : " [offline]";
89    }
90
91    return $blistStr."\n";
92}
93
94sub onGetBuddyList
95{
96    my $blist = "";
97    foreach my $jid (keys %{$connections})
98    {
99        my $roster = \$connections->{$jid}->{roster};
100        if ($$roster)
101        {
102            $blist .= "\n".boldify("Jabber Roster for $jid\n");
103           
104            foreach my $group ($$roster->groups())
105            {
106                $blist .= "  Group: $group\n";
107                foreach my $buddy ($$roster->jids('group',$group))
108                {
109                    $blist .= blist_listBuddy($roster, $buddy);
110                }
111            }
112           
113            my @unsorted = $$roster->jids('nogroup');
114            if (@unsorted)
115            {
116                $blist .= "  [unsorted]\n";
117                foreach my $buddy (@unsorted)
118                {
119                    $blist .= blist_listBuddy($roster, $buddy);
120                }
121            }
122        }
123    }
124    return $blist;
125}
126
127################################################################################
128### Owl Commands
129sub register_owl_commands()
130{
131    owl::new_command(
132        jabberlogin => \&cmd_login,
133        { summary => "Log into jabber", }
134    );
135    owl::new_command(
136        jabberlogout => \&cmd_logout,
137        { summary => "Log out of jabber" }
138    );
139    owl::new_command(
140        jwrite => \&cmd_jwrite,
141        {
142            summary     => "Send a Jabber Message",
143            usage       => "jwrite JID [-g] [-t thread] [-s subject]"
144        }
145    );
146    owl::new_command(
147        jlist => \&cmd_jlist,
148        {
149            summary     => "Show your Jabber roster.",
150            usage       => "jlist"
151        }
152    );
153    owl::new_command(
154        jmuc => \&cmd_jmuc,
155        {
156            summary     => "Jabber MUC related commands.",
157            description => "jmuc sends jabber commands related to muc.\n\n".
158                "The following commands are available\n\n".
159                "join {muc}  Join a muc.\n\n".
160                "part [muc]  Part a muc.".
161                "            The muc is taken from the current message if not supplied.\n\n".
162                "invite {jid} [muc]\n\n".
163                "            Invite {jid} to [muc].\n".
164                "            The muc is taken from the current message if not supplied.\n\n",
165            usage       => "jmuc {command} {args}"
166        }
167    );
168}
169
170sub cmd_login
171{
172    my $cmd = shift;
173    my $jid = new Net::XMPP::JID;
174    $jid->SetJID(shift);
175   
176    my $uid = $jid->GetUserID();
177    my $componentname = $jid->GetServer();
178    my $resource = $jid->GetResource() || 'owl';
179    $jid->SetResource($resource);
180    my $jidStr = $jid->GetJID('full');
181
182    if (!$uid || !$componentname)
183    {
184        owl::error("usage: $cmd {jid}");
185        return;
186    }
187
188    if ($connections->{$jidStr})
189    {
190        owl::error("Already logged in as $jidStr.");
191        return;
192    }
193
194    my ($server, $port) = getServerFromJID($jid);
195
196    $connections->{$jidStr}->{client} = Net::Jabber::Client->new();
197    my $client = \$connections->{$jidStr}->{client};
198    $connections->{$jidStr}->{roster} = $connections->{$jidStr}->{client}->Roster();
199
200    #XXX Todo: Add more callbacks.
201    # MUC presence handlers
202    $$client->SetMessageCallBacks(chat => sub { owl_jabber::process_incoming_chat_message(@_) },
203                                  error => sub { owl_jabber::process_incoming_error_message(@_) },
204                                  groupchat => sub { owl_jabber::process_incoming_groupchat_message(@_) },
205                                  headline => sub { owl_jabber::process_incoming_headline_message(@_) },
206                                  normal => sub { owl_jabber::process_incoming_normal_message(@_) });
207
208    $vars{jlogin_connhash} = {hostname => $server,
209                          tls => 1,
210                          port => $port,
211                          componentname => $componentname};
212
213    my $status = $$client->Connect(%{$vars{jlogin_connhash}});
214
215    if (!$status)
216    {
217        delete $connections->{$jidStr};
218        delete $vars{jlogin_connhash};
219        owl::error("We failed to connect");
220        return "";
221    }
222
223
224    $vars{jlogin_authhash} = {username => $uid, resource => $resource, password => ''};
225    my @result = $$client->AuthSend(%{$vars{jlogin_authhash}});
226    if($result[0] ne 'ok') 
227    {
228        if ($result[1] = "401")
229        {
230            $vars{jlogin_jid} = $jidStr;
231            delete $connections->{$jidStr};
232            owl::start_password("Password for $jidStr: ", \&do_login_with_pw);
233            return "";
234        }
235        owl::error("Error in connect: " . join(" ", $result[1..$#result]));
236        do_logout($jidStr);
237        delete $vars{jlogin_connhash};
238        delete $vars{jlogin_authhash};
239        return "";
240    }
241    $connections->{$jidStr}->{roster}->fetch();
242    $$client->PresenceSend(priority => 1);
243    queue_admin_msg("Connected to jabber as $jidStr");
244    delete $vars{jlogin_connhash};
245    delete $vars{jlogin_authhash};
246    return "";
247}
248
249sub do_login_with_pw
250{
251    $vars{jlogin_authhash}->{password} = shift;
252    my $jidStr = delete $vars{jlogin_jid};
253    if (!$jidStr)
254    {
255        owl::error("Got password but have no jid!");
256    }
257
258    $connections->{$jidStr}->{client} = Net::Jabber::Client->new();
259    my $client = \$connections->{$jidStr}->{client};
260    $connections->{$jidStr}->{roster} = $connections->{$jidStr}->{client}->Roster();
261
262    $$client->SetMessageCallBacks(chat => sub { owl_jabber::process_incoming_chat_message(@_) },
263                                  error => sub { owl_jabber::process_incoming_error_message(@_) },
264                                  groupchat => sub { owl_jabber::process_incoming_groupchat_message(@_) },
265                                  headline => sub { owl_jabber::process_incoming_headline_message(@_) },
266                                  normal => sub { owl_jabber::process_incoming_normal_message(@_) });
267
268    my $status = $$client->Connect(%{$vars{jlogin_connhash}});
269    if (!$status)
270    {
271        delete $connections->{$jidStr};
272        delete $vars{jlogin_connhash};
273        delete $vars{jlogin_authhash};
274        owl::error("We failed to connect");
275        return "";
276    }
277
278    my @result = $$client->AuthSend(%{$vars{jlogin_authhash}});
279
280    if($result[0] ne 'ok') 
281    {
282        owl::error("Error in connect: " . join(" ", $result[1..$#result]));
283        do_logout($jidStr);
284        delete $vars{jlogin_connhash};
285        delete $vars{jlogin_authhash};
286        return "";
287    }
288
289    $connections->{$jidStr}->{roster}->fetch();
290    $$client->PresenceSend(priority => 1);
291    queue_admin_msg("Connected to jabber as $jidStr");
292    delete $vars{jlogin_connhash};
293    delete $vars{jlogin_authhash};
294    return "";
295}
296
297sub do_logout
298{
299    my $jid = shift;
300    $connections->{$jid}->{client}->Disconnect();
301    delete $connections->{$jid};
302    queue_admin_msg("Jabber disconnected ($jid).");
303}
304
305sub cmd_logout
306{
307    # Logged into multiple accounts
308    if (connected() > 1)
309    {
310        # Logged into multiple accounts, no accout specified.
311        if (!$_[1])
312        {
313            my $errStr = "You are logged into multiple accounts. Please specify an account to log out of.\n";
314            foreach my $jid (keys %$connections)
315            {
316                $errStr .= "\t$jid\n";
317            }
318            queue_admin_msg($errStr);
319        }
320        # Logged into multiple accounts, account specified.
321        else
322        {
323            if ($_[1] = '-a') #All accounts.
324            {
325                foreach my $jid (keys %$connections)
326                {
327                    do_logout($jid);
328                }
329            }
330            else #One account.
331            {
332                my $jid = resolveJID($_[1]);
333                do_logout($jid) if ($jid ne '');
334            }
335        }
336    }
337    else # Only one account logged in.
338    {
339       
340        do_logout((keys %$connections)[0]);
341    }
342    return "";
343}
344
345sub cmd_jlist
346{
347    if (!(scalar keys %$connections))
348    {
349        owl::error("You are not logged in to Jabber.");
350        return;
351    }
352    owl::popless_ztext(onGetBuddyList());
353}
354
355sub cmd_jwrite
356{
357    if (!connected())
358    {
359        owl::error("You are not logged in to Jabber.");
360        return;
361    }
362
363    my $jwrite_to = "";
364    my $jwrite_from = "";
365    my $jwrite_thread = "";
366    my $jwrite_subject = "";
367    my $jwrite_type = "chat";
368
369    my @args = @_;
370    shift;
371    local @::ARGV = @_;
372    my $gc;
373    GetOptions('thread=s' => \$jwrite_thread,
374               'subject=s' => \$jwrite_subject,
375               'account=s' => \$jwrite_from,
376               'groupchat' => \$gc);
377    $jwrite_type = 'groupchat' if $gc;
378
379    if (scalar @::ARGV != 1)
380    {
381        owl::error("Usage: jwrite JID [-g] [-t thread] [-s 'subject'] [-a account]");
382        return;
383    }
384    else
385    {
386        $jwrite_to = @::ARGV[0];
387    }
388
389    if (!$jwrite_from)
390    {
391        if (connected() == 1)
392        {
393            $jwrite_from = (keys %$connections)[0];
394        }
395        else
396        {
397            owl::error("Please specify an account with -a {jid}");
398            return;
399        }
400    }
401    else
402    {
403        $jwrite_from = resolveJID($jwrite_from);
404        return unless $jwrite_from;
405    }
406   
407    $vars{jwrite} = {to => $jwrite_to, 
408                     from => $jwrite_from,
409                     subject => $jwrite_subject,
410                     thread => $jwrite_thread,
411                     type => $jwrite_type};
412
413    owl::message("Type your message below.  End with a dot on a line by itself.  ^C will quit.");
414    owl::start_edit_win(join(' ', @args), \&process_owl_jwrite);
415}
416
417#XXX Todo: Split off sub-commands into their own subroutines.
418# It'll make them more managable.
419sub cmd_jmuc
420{
421    if (!connected())
422    {
423        owl::error("You are not logged in to Jabber.");
424        return;
425    }
426   
427    my $ocmd = shift;
428    my $cmd = shift;   
429    if (!$cmd)
430    {
431        #XXX TODO: Write general usage for jmuc command.
432        return;
433    }
434
435    if ($cmd eq 'join')
436    {
437        local @::ARGV = @_;
438        my $password;
439        my $jid;
440        GetOptions('password=s' => \$password,
441                   'account=s' => \$jid);
442
443        my $muc;
444        if (scalar @::ARGV != 1)
445        {
446            owl::error('Usage: jmuc join {muc} [-p password] [-a account]');
447            return;
448        }
449        else
450        {
451            $muc = @::ARGV[0];
452        }
453
454        if (!$jid)
455        {
456            if (connected() == 1)
457            {
458                $jid = (keys %$connections)[0];
459            }
460            else
461            {
462                owl::error("Please specify an account with -a {jid}");
463                return;
464            }
465        }
466        else
467        {
468            $jid = resolveJID($jid);
469            return unless $jid;
470        }
471
472        my $x = new XML::Stream::Node('x');
473        $x->put_attrib(xmlns => 'http://jabber.org/protocol/muc');
474        $x->add_child('history')->put_attrib(maxchars => '0');
475       
476        if ($jmuc_password)
477        {
478            $x->add_child('password')->add_cdata($jmuc_password);
479        }
480
481        my $presence = new Net::Jabber::Presence;
482        $presence->SetPresence(to => $muc);
483        $presence->AddX($x);
484        $connections->{$jid}->{client}->Send($presence);
485    }
486    elsif ($cmd eq 'part')
487    {
488        my $muc;
489        my $jid;
490        if (!$_[0])
491        {
492            my $m = owl::getcurmsg();
493            if ($m->is_jabber && $m->{jtype} eq 'groupchat')
494            {
495                $muc = $m->{room};
496                $jid = $m->{to};
497            }
498            else
499            {
500                owl::error('Usage: jmuc part {muc} [-a account]');
501                return;
502            }
503        }
504        else
505        {
506            local @::ARGV = @_;
507            GetOptions('account=s' => \$jid);
508            if (scalar @::ARGV != 1)
509            {
510                owl::error('Usage: jmuc part {muc} [-a account]');
511                return;
512            }
513            else
514            {
515                $muc = @::ARGV[0];
516            }
517            if (!$jid)
518            {
519                if (connected() == 1)
520                {
521                    $jid = (keys %$connections)[0];
522                }
523                else
524                {
525                    owl::error("Please specify an account with -a {jid}");
526                    return;
527                }
528            }
529            else
530            {
531                $jid = resolveJID($jid);
532                return unless $jid;
533            }
534        }
535        $connections->{$jid}->{client}->PresenceSend(to => $muc, type => 'unavailable');
536        queue_admin_msg("$jid has left $muc.");
537    }
538    elsif ($cmd eq 'invite')
539    {
540        my $jid;
541        my $invite_jid;
542        my $muc;
543
544        owl::error('Usage: jmuc invite {jid} [muc] [-a account]') if (!$_[0]);
545        $invite_jid = $_[0];
546       
547        if (!@_[1])
548        {       
549            my $m = owl::getcurmsg();
550            if ($m->is_jabber && $m->{jtype} eq 'groupchat')
551            {
552                $muc = $m->{room};
553                $jid = $m->{to};
554            }
555            else
556            {
557                owl::error('Usage: jmuc invite {jid} [muc] [-a account]');
558                return;
559            }
560        }
561        else
562        {
563            local @::ARGV = @_;
564            GetOptions('account=s' => \$jid);
565            if (scalar @::ARGV != 2)
566            {
567                owl::error('Usage: jmuc invite {jid} [muc] [-a account]');
568                return;
569            }
570            else
571            {
572                ($muc, $invite_jid) = @::ARGV;
573            }
574            if (!$jid)
575            {
576                if (connected() == 1)
577                {
578                    $jid = (keys %$connections)[0];
579                }
580                else
581                {
582                    owl::error("Please specify an account with -a {jid}");
583                    return;
584                }
585            }
586            else
587            {
588                $jid = resolveJID($jid);
589                return unless $jid;
590            }
591        }
592       
593        my $x = new XML::Stream::Node('x');
594        $x->put_attrib(xmlns => 'http://jabber.org/protocol/muc#user');
595        $x->add_child('invite')->put_attrib(to => $invite_jid);
596       
597        my $message = new Net::Jabber::Message;
598        $message->SetTo($muc);
599        $message->AddX($x);
600        $connections->{$jid}->{client}->Send($message);
601        queue_admin_msg("$jid has invited $invite_jid to $muc.");
602    }
603    else
604    {
605        owl::error('jmuc: unrecognized command.');
606    }
607    return "";
608}
609
610################################################################################
611### Owl Callbacks
612sub process_owl_jwrite
613{
614    my $body = shift;
615
616    my $j = new Net::XMPP::Message;
617    $body =~ s/\n\z//;
618    $j->SetMessage(to => $vars{jwrite}{to},
619                   from => $vars{jwrite}{from},
620                   type => $vars{jwrite}{type},
621                   body => $body
622                   );
623    $j->SetThread($vars{jwrite}{thread}) if ($vars{jwrite}{thread});
624    $j->SetSubject($vars{jwrite}{subject}) if ($vars{jwrite}{subject});
625   
626    my $m = j2o($j, 'out');
627    if ($vars{jwrite}{type} ne 'groupchat')
628    {
629        #XXX TODO: Check for displayoutgoing.
630        owl::queue_message($m);
631    }
632    $connections->{$vars{jwrite}{from}}->{client}->Send($j);
633    delete $vars{jwrite};
634}
635
636### XMPP Callbacks
637
638sub process_incoming_chat_message
639{
640    my ($session, $j) = @_;
641    owl::queue_message(j2o($j, 'in'));
642}
643
644sub process_incoming_error_message
645{
646    my ($session, $j) = @_;
647    my %jhash = j2hash($j, 'in');
648    $jhash{type} = 'admin';
649    owl::queue_message(owl::Message->new(%jhash));
650}
651
652sub process_incoming_groupchat_message
653{
654    my ($session, $j) = @_;
655    # HACK IN PROGRESS (ignoring delayed messages)
656    return if ($j->DefinedX('jabber:x:delay') && $j->GetX('jabber:x:delay'));
657    owl::queue_message(j2o($j, 'in'));
658}
659
660sub process_incoming_headline_message
661{
662    my ($session, $j) = @_;
663    owl::queue_message(j2o($j, 'in'));
664}
665
666sub process_incoming_normal_message
667{
668    my ($session, $j) = @_;
669    my %props = j2hash($j, 'in');
670
671    # XXX TODO: handle things such as MUC invites here.
672
673#    if ($j->HasX('http://jabber.org/protocol/muc#user'))
674#    {
675#       my $x = $j->GetX('http://jabber.org/protocol/muc#user');
676#       if ($x->HasChild('invite'))
677#       {
678#           $props         
679#       }
680#    }
681#   
682    owl::queue_message(owl::Message->new(%props));
683}
684
685sub process_muc_presence
686{
687    my ($session, $p) = @_;
688    return unless ($p->HasX('http://jabber.org/protocol/muc#user'));
689   
690}
691
692
693### Helper functions
694
695sub j2hash
696{
697    my $j = shift;
698    my $dir = shift;
699
700    my %props = (type => 'jabber',
701                 direction => $dir);
702
703    my $jtype = $props{jtype} = $j->GetType();
704    my $from  = $j->GetFrom('jid');
705    my $to    = $j->GetTo('jid');
706
707    $props{from} = $from->GetJID('full');
708    $props{to}   = $to->GetJID('full');
709
710    $props{recipient}  = $to->GetJID('base');
711    $props{sender}     = $from->GetJID('base');
712    $props{subject}    = $j->GetSubject() if ($j->DefinedSubject());
713    $props{thread}     = $j->GetThread() if ($j->DefinedThread());
714    $props{body}       = $j->GetBody() if ($j->DefinedBody());
715    $props{error}      = $j->GetError() if ($j->DefinedError());
716    $props{error_code} = $j->GetErrorCode() if ($j->DefinedErrorCode());
717    $props{xml}        = $j->GetXML();
718
719    if ($jtype eq 'chat')
720    {
721        $props{replycmd} = "jwrite ".(($dir eq 'in') ? $props{from} : $props{to});
722        $props{replycmd} .= " -a ".(($dir eq 'out') ? $props{from} : $props{to});
723        $props{isprivate} = 1;
724    }
725    elsif ($jtype eq 'groupchat')
726    {
727        my $nick = $props{nick} = $from->GetResource();
728        my $room = $props{room} = $from->GetJID('base');
729        $props{replycmd} = "jwrite -g $room";
730        $props{replycmd} .= " -a ".(($dir eq 'out') ? $props{from} : $props{to});
731       
732        $props{sender} = $nick || $room;
733        $props{recipient} = $room;
734
735        if ($props{subject} && !$props{body})
736        {
737            $props{body} = '['.$nick." has set the topic to: ".$props{subject}."]"
738        }
739    }
740    elsif ($jtype eq 'normal')
741    {
742        $props{replycmd} = undef;
743        $props{isprivate} = 1;
744    }
745    elsif ($jtype eq 'headline')
746    {
747        $props{replycmd} = undef;
748    }
749    elsif ($jtype eq 'error')
750    {
751        $props{replycmd} = undef;
752        $props{body} = "Error ".$props{error_code}." sending to ".$props{from}."\n".$props{error};
753    }
754   
755    $props{replysendercmd} = $props{replycmd};
756    return %props;
757}
758
759sub j2o
760{
761    return owl::Message->new(j2hash(@_));
762}
763
764sub queue_admin_msg
765{
766    my $err = shift;
767    my $m = owl::Message->new(type => 'admin',
768                              direction => 'none',
769                              body => $err);
770    owl::queue_message($m);
771}
772
773sub boldify($)
774{
775    $str = shift;
776
777    return '@b('.$str.')' if ( $str !~ /\)/ );
778    return '@b<'.$str.'>' if ( $str !~ /\>/ );
779    return '@b{'.$str.'}' if ( $str !~ /\}/ );
780    return '@b['.$str.']' if ( $str !~ /\]/ );
781
782    my $txt = "\@b($str";
783    $txt =~ s/\)/\)\@b\[\)\]\@b\(/g;
784    return $txt.')';
785}
786
787sub getServerFromJID
788{
789    my $jid = shift;
790    my $res = new Net::DNS::Resolver;
791    my $packet = $res->search('_xmpp-client._tcp.'.$jid->GetServer(), 'srv');
792
793    if ($packet) # Got srv record.
794    {
795        my @answer = $packet->answer;
796        return $answer[0]{target},
797                $answer[0]{port};
798    }
799
800    return $jid->GetServer(), 5222;
801}
802
803sub connected
804{
805    return scalar keys %$connections;
806}
807
808sub resolveJID
809{
810    my $givenJidStr = shift;
811    my $givenJid = new Net::XMPP::JID;
812    $givenJid->SetJID($givenJidStr);
813   
814    # Account fully specified.
815    if ($givenJid->GetResource())
816    {
817        # Specified account exists
818        if (defined $connections->{$givenJidStr})
819        {
820            return $givenJidStr;
821        }
822        else #Specified account doesn't exist
823        {
824            owl::error("Invalid account: $givenJidStr");
825        }
826    }
827    # Disambiguate.
828    else
829    {
830        my $matchingJid = "";
831        my $errStr = "Ambiguous account reference. Please specify a resource.\n";
832        my $ambiguous = 0;
833       
834        foreach my $jid (keys %$connections)
835        {
836            my $cJid = new Net::XMPP::JID;
837            $cJid->SetJID($jid);
838            if ($givenJidStr eq $cJid->GetJID('base'))
839            {
840                $ambiguous = 1 if ($matchingJid ne "");
841                $matchingJid = $jid;
842                $errStr .= "\t$jid\n";
843            }
844        }
845        # Need further disambiguation.
846        if ($ambiguous)
847        {
848            queue_admin_msg($errStr);
849        }
850        # Not one of ours.
851        elsif ($matchingJid eq "")
852        {
853            owl::error("Invalid account: $givenJidStr");
854          }
855        # Log out this one.
856        else
857        {
858            return $matchingJid;
859        }
860    }
861    return "";
862}
Note: See TracBrowser for help on using the repository browser.