source: perl/modules/jabber.pl @ a55abb3

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