Sendxmpp and openfire

Hi,

Does anybody know how to make sendxmpp working with openfire? I get error:

Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/XML/Stream.pm line 1424.

Use of uninitialized value in hash element at /usr/share/perl5/XML/Stream.pm line 1425.

Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/XML/Stream.pm line 1425.

Use of uninitialized value in hash element at /usr/share/perl5/XML/Stream.pm line 1427.

Use of uninitialized value in numeric eq (==) at /usr/share/perl5/XML/Stream.pm line 1427.

Use of uninitialized value in hash element at /usr/share/perl5/XML/Stream.pm line 1427.

Use of uninitialized value in numeric eq (==) at /usr/share/perl5/XML/Stream.pm line 1491.

Use of uninitialized value in subtraction at /usr/share/perl5/XML/Stream.pm line 1492.

Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/XML/Stream.pm line 1637.

Use of uninitialized value in numeric eq (==) at /usr/share/perl5/XML/Stream.pm line 1641.

Can’'t use an undefined value as a HASH reference at /usr/share/perl5/XML/Stream.pm line 1165.

Please help

Message was edited by: archon

Message was edited by: archon

Hi There,

I too am experiencing this issue on several installations.

I am also unable to use a basic script Net::Jabber to send a message.

Does anyone have any ideas? I have not tested with another Jabber server yet but it seems to be server related.

Any help would be appreciated.

Cheers,

Alan

I had troubles getting Net::Jabber working too, but Net::XMPP seems to work ok. I even got sendxmpp (from http://www.djcbsoftware.nl/code/sendxmmp) working without problems.

That error seems like you are dealing with different versions of Net::XMMP and what it depends on. You might want to double check your perl module installations.

Hi Slushpupie,

What versions of Perl modules and Openfire are you using?

I have the latest versions for Net:XMPP, Net:Jabber and XML::Stream.

I also just tried the same scripts (sendxmpp and custom script) against talk.google.com and that worked a treat!

Do you have a sample script you can post?

Cheers,

Alan

Net::XMPP version 1.0-2

Well, here is what I use. Its a modified version of the sendxmpp command

#!/usr/bin/perl -w
#-*-mode:perl-*-
#Time-stamp: <2004-12-01 14:52:47 (djcb)> # script to send message using xmpp (aka jabber), #   somewhat resembling mail(1) # author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
# copyright (c) 2004, Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
#
# released under the terms of the GNU General Public License v2 use Net::XMPP;
use Mail::Internet;
use Getopt::Long;
use strict; # subroutines decls
sub xmpp_login($$$$$$);
sub xmpp_send_message($$$$$);
sub xmpp_send_chatroom_message($$$$$);
sub xmpp_logout($);
sub xmpp_presence_callback($$);
sub xmpp_check_result;
sub parse_cmdline();
sub error_exit;
sub debug_print;
sub read_config_file($);
sub push_hash($$);
sub main (); my # MakeMaker
$VERSION     = ''0.0.5'';
my $RESOURCE = ''sendxmpp'';
my $VERBOSE  = 0;
my $DEBUG    = 0;
my %STATUS;
             # start!
&main; #
# main: main routine
#
sub main () {     my $cmdline = parse_cmdline();
        $DEBUG   = 1 if ($$cmdline{''debug''});
    $VERBOSE = 1 if ($$cmdline{''verbose''});     my $config = read_config_file ($$cmdline{''file''})
        unless ($$cmdline{''jserver''} && $$cmdline{''username''} && $$cmdline{''password''} && $$cmdline{''online''});
        # login to xmpp
    my $cnx =  xmpp_login ($$cmdline{''jserver''}  || $$config{''jserver''},
                           $$cmdline{''username''} || $$config{''username''},
                           $$cmdline{''password''} || $$config{''password''},
                           $$cmdline{''resource''},
                           $$cmdline{''tls''},
                           $$cmdline{''debug''})
        or error_exit("cannot login: $!");
            unless ($$cmdline{''chatroom''}) {
        xmpp_send_message ($cnx,
                           $$cmdline{''recipient''},
                           $$cmdline{''subject''},
                           $$cmdline{''online''},
                           $$cmdline{''message''});
    } else {
        xmpp_send_chatroom_message ($cnx,
                                 $$cmdline{''resource''},
                                 $$cmdline{''subject''},
                                 $$cmdline{''recipient''},
                                 $$cmdline{''message''});
    }     xmpp_logout($cnx);
    exit(0);
} sub mail_parse_msg {
    # Read and parse email
    my $mail = Mail::Internet->new(*STDIN);
    my $msg  = $mail->body();
    my @m    = @{$msg}[0..5];
        # Extract header info
    my $header = $mail->head()->header_hashref();
    chomp $header->{$_}[0] foreach keys(%{$header});
        # Create message body
    my $body  = "Incoming Email: \n";
    $body .= "From: $header->{From}[0]\n";
    $body .= "To: ".join(", ",@{$header->{To}})."\n";
    if($header->{CC}) {
        $body .= "Cc: ".join(", ",@{$header->{CC}})."\n";
    }
    $body .= "Subject: $header->{Subject}[0]\n";
    $body .= "Date: $header->{Date}[0]\n";
    $body .= "\n";
    $body .= join(" ",@m);
    print("Message: $body");
    return $body;
} #
# read_config_file: read the configuration file
# input: filename
# output: hash with ''user'', ''jserver'' and ''password'' keys
#
sub read_config_file ($) {
       # check permissions
    my $cfg_file = shift;
    error_exit ("cannot read $cfg_file: $!")         unless (-r $cfg_file);        my $owner  = (stat($cfg_file))[4];
    error_exit ("you must own $cfg_file")
        unless ($owner == $>);     my $mode = (stat($cfg_file))[2] & 07777;
    error_exit ("$cfg_file must have mode 0600")
        unless ($mode == 0600);
        open (CFG,"<$cfg_file")
        or error_exit("cannot open $cfg_file for reading: $!");     my %config;
    my $line = 0;
    while (<CFG>) {         ++$line;         next if (/^\s*$/);     # ignore empty lines
        next if (/^\s*\#.*/);  # ignore comment lines         s/\#.*$//; # ignore comments in lines         if (/([-\.\w]+)@([-\.\w]+)\s+(\S+)\s*$/) {
            %config = (''username''=>$1,
                       ''jserver''=>$2,                        ''password''=>$3);         } else {
            close(CFG);
            error_exit ("syntax error in line $line of $cfg_file");
        }
    }     close(CFG);
        error_exit ("no correct config found in $cfg_file")         unless (scalar(%config));           if ($DEBUG || $VERBOSE) {
        while (my ($key,$val) = each %config) {
            debug_print ("config: ''$key'' => ''$val''");
        }
    }           return \%config;               } #
# parse_cmdline: parse commandline options
# output: hash with commandline options
#
sub parse_cmdline () {
       usage() unless (scalar(@ARGV));
                my ($subject,$file,$resource,$jserver,$username,$password,
        $message,$chatroom,$online,$debug,$tls,$help,$verbose);
    my $res = GetOptions (''subject|s=s''    => \$subject,
                          ''file|f=s''       => \$file,
                          ''resource|r=s''   => \$resource,
                          ''jserver|j=s''    => \$jserver,
                          ''username|u=s''   => \$username,
                          ''password|p=s''   => \$password,
                          ''chatroom|c''     => \$chatroom,
                          ''online|o''       => \$online,
                          ''tls|t''          => \$tls,
                          ''help|usage|h''   => \$help,
                          ''debug|d''        => \$debug,
                          ''verbose|v''      => \$verbose);
    usage ()         if ($help);          my $rcpt = $ARGV[0]
        or error_exit("no recipient specified");     ## read message from STDIN
    my $txt = mail_parse_msg();
       my %dict = (''subject''    => ($subject  or ''''),
                ''message''    => ($txt or ''''),
                ''resource''   => ($resource or $RESOURCE),
                ''jserver''    => ($jserver or ''''),
                ''username''   => ($username or ''''),
                ''password''   => ($password or ''''),
                ''chatroom''   => ($chatroom or 0),
                ''online''     => ($online or 0),
                ''tls''        => ($tls or 0),
                ''debug''      => ($debug or 0),
                ''verbose''    => ($verbose or 0),
                ''file''       => ($file or ($ENV{''HOME''}.''/.sendxmpprc'')),
                ''recipient''  => $rcpt);    if ($DEBUG || $VERBOSE) {
       while (my ($key,$val) = each %dict) {
           debug_print ("cmdline: ''$key'' => ''$val''");
       }
   }               return \%dict;    } #
# xmpp_login: login to the xmmp (jabber) server
# input: hostname,username,password,resource,tls,debug
# output: an XMPP connection object
#
sub xmpp_login ($$$$$$) {     my ($host,$user,$pw,$res,$tls,$debug) = @_;
    my $cnx = new Net::XMPP::Client(debuglevel=>($debug?2:0));
    #$STATUS = new Net::XMPP::Roster(connection=>$cnx);
    $cnx->SetPresenceCallBacks(available=>\&xmpp_presence_callback);
    error_exit ("could not create XMPP client object: $!")
        unless ($cnx);        my @res = $cnx->Connect(hostname=>$host,tls=>$tls);
    xmpp_check_result("Connect",\@res,$cnx);         @res = $cnx->AuthIQAuth(''hostname''=>$host,
                          ''username''=>$user,
                          ''password''=>$pw,
                          ''resource''=>$res);
    xmpp_check_result(''AuthSend'',\@res,$cnx);
           @res = $cnx->PresenceSend(type=>''available'');
    xmpp_check_result("PresenceSend",\@res,$cnx);         return $cnx;    } #
# xmmp_send_message: send a message to some xmmp user
# input: connection,recipient,subject,online,msg
#
sub xmpp_send_message ($$$$$) {
        my ($cnx,$rcpt,$subject,$online,$msg) = @_;     if($online) {
        debug_print("checking if $rcpt is online");
        $cnx->Process(1);
        if($STATUS{$rcpt}) {
            debug_print("$rcpt is online");
        } else {
            debug_print("$rcpt is not online");
            return;
        }
    }
            # for some reason, MessageSend does not return anything
    $cnx->MessageSend(''to''=>$rcpt,
                      ''subject''=>$subject,
                      ''body''=>$msg);
        xmpp_check_result(''MessageSend'',0,$cnx);
}
        #
# xmpp_send_chatroom_message: send a message to a chatroom
# input: connection,resource,subject,recipient,message
#
sub xmpp_send_chatroom_message ($$$$$) {     my ($cnx,$resource,$subject,$rcpt,$msg) =  @_;
        # set the presence
    my $pres = new Net::XMPP::Presence;
    my $res = $pres->SetTo("$rcpt/$resource");     $cnx->Send($pres);     # create/send the message
    my $groupmsg = new Net::XMPP::Message;
    $groupmsg->SetMessage(to=>$rcpt,                           body=>$msg,
                          subject=>$subject,
                          type=>''groupchat'');     $res = $cnx->Send($groupmsg);
    xmpp_check_result (''Send'',$res,$cnx);         # leave the group
    $pres->SetPresence (Type=>''unavailable'',To=>$rcpt);
} #
# xmmp_logout: log out from the xmpp server
# input: connection
#
sub xmpp_logout($) {
        # HACK
    # messages may not be received if we log out too quickly...
    sleep 1;         my $cnx = shift;
    $cnx->Disconnect();
    xmpp_check_result (''Disconnect'',0); # well, nothing to check, really
} #
# xmpp_check_result: check the return value from some xmpp function execution
# input: text, result, [connection]                   #
sub xmpp_check_result {     my ($txt,$res,$cnx)=@_;
        error_exit ("Error ''$txt'': result undefined")
        unless (defined $res);      # res may be 0
    if ($res == 0) {
        debug_print "$txt";
    # result can be true or ''ok''     } elsif ((@$res == 1 && $$res[0]) || $$res[0] eq ''ok'') {
        debug_print "$txt: " .  $$res[0];
    # otherwise, there is some error
    } else {
        my $errmsg = $cnx->GetErrorCode() || ''?'';
        error_exit ("Error ''$txt'': " . join ('': '',@$res) . "[$errmsg]", $cnx);
    }
} sub xmpp_presence_callback ($$) {
    my $sid = shift;
    my $presence = shift;
    my $jid = $presence->GetFrom("jid")->GetJID("base");
    my $status = $presence->GetStatus();
    if($status eq "") { $status = "online";}
    debug_print("got status from $jid:  $status");
    $STATUS{$jid} = $status;
} #
# debug_print: print the data if defined and DEBUG || VERBOSE is TRUE
# input: [array of strings]
#
sub debug_print {
    print STDERR "sendxmpp: " . (join '' '',@_) . "\n"
        if (@_ && ($DEBUG ||$VERBOSE));
} #
# error_exit: print error message and exit the program
#             logs out if there is a connection # input: error, [connection]
#
sub error_exit {
        my ($err,$cnx) = @_;
    print STDERR "$err\n";       xmpp_logout ($cnx)         if ($cnx);     exit 1;
} #
# usage: print short usage message and exit
#
sub usage () {
       print         "sendxmpp version $VERSION, (c) 2004 Dirk-Jan C. Binnema\n" .
        "usage: sendxmpp [options] <recipient>\n" .
        "or refer to the the sendxmpp manpage\n";
        exit 0;
}

You run it like this:

cat mailmsg | sendxmpp.pl -u username -p password -j servername -o recipient-JID@someserver

This is on Debian 4.0 using the packages from the default repositories.

Hmm sounds like same version of Net::XMPP - what about your version of OpenFire?

Cheers,

Alan

Its been working with every version since 2.X up to the most recent (SVN trunk, when it isnt broken).

I found a solution at http://www.jase.org/book/print/25.

-snip-

Under your site_perl directory there is a file in Net/XMPP/Protocol.pm, search for “AuthSASL” and comment out the following lines as shown below:

  1. if($self-> && $self->->GetStreamFeature($self->GetStreamID(

),“xmpp-sasl”))

  1. {

  2. return $self->AuthSASL(%args);

  3. }

-snip-

This makes it work for me (although not with TLS, but one can probably use port 5223 and stunnel).

FWIW, this bug is described here:

http://rt.cpan.org/Public/Bug/Display.html?id=17484

And the attached patch to XML::Stream allows it to work (without TLS, which hangs sendxmpp for some reason I’'ve yet to determine).

I also had this problem and I used the bug referenced, however in my situation I had to change line 1165 in Stream.pm from:

delete($self->->{$currsid}); to: delete($self->->{$currsid}) unless ($currsid eq $sid);

…effectively “unpatching” the patch that supposedly fixes this.

-Greg