#!/usr/bin/perl -w
eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
- if 0; # not running under some shell
-#-*-mode:perl-*-
-#Time-stamp: <2005-05-07 19:24:09 (djcb)>
+if 0; # not running under some shell
+#
# script to send message using xmpp (aka jabber),
-# somewhat resembling mail(1)
-
+# somewhat resembling mail(1)
+#
# Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
-# Copyright (c) 2004,2005 Dirk-Jan C. Binnema
-
+# Copyright (c) 2004, 2005 Dirk-Jan C. Binnema
+#
+# Maintainer: Lubomir Host 'rajo' <rajo AT platon.sk>
+# Homepage: http://sendxmpp.platon.sk
+#
# Released under the terms of the GNU General Public License v2
+#
use Net::XMPP;
use Getopt::Long;
use strict;
+use open ':utf8';
+use open ':std';
+
# subroutines decls
sub xmpp_login($$$$$$$);
sub xmpp_send ($$$);
+sub xmpp_send_raw_xml($$);
sub xmpp_send_message($$$$);
sub xmpp_send_chatroom_message($$$$$);
sub xmpp_logout($);
usage() unless (scalar(@ARGV));
my ($subject,$file,$resource,$jserver,$port,$username,$password,
- $message,$chatroom,$debug,$tls,$interactive,$help,$verbose);
+ $message, $chatroom, $debug, $tls, $interactive, $help, $raw, $verbose);
my $res = GetOptions ('subject|s=s' => \$subject,
'file|f=s' => \$file,
'resource|r=s' => \$resource,
'interactive|i' => \$interactive,
'help|usage|h' => \$help,
'debug|d' => \$debug,
+ 'raw|w' => \$raw,
'verbose|v' => \$verbose);
- usage ()
- if ($help);
+ usage () if ($help);
- my $rcpt = $ARGV[0]
- or error_exit "no recipient specified";
-
- if ($message && $interactive) {
- error_exit "cannot have both -m (--message) and -i (--interactive)\n";
- }
-
- if ($jserver && $jserver =~ /(.*):(\d+)/) {
- $jserver = $1;
- $port = $2;
- }
-
+ my @rcpt = @ARGV;
+
+ if (defined($raw) && scalar(@rcpt) > 0) {
+ error_exit "You must give a recipient or --raw (but not both)";
+ }
+ if ($raw && $subject) {
+ error_exit("You cannot specify a subject in raw XML mode");
+ }
+ if ($raw && $chatroom) {
+ error_exit("The chatroom option is pointless in raw XML mode");
+ }
+
+ if ($message && $interactive) {
+ error_exit "Cannot have both -m (--message) and -i (--interactive)";
+ }
+
+ if ($jserver && $jserver =~ /(.*):(\d+)/) {
+ $jserver = $1;
+ $port = $2;
+ }
+
my %dict = ('subject' => ($subject or ''),
+ 'message' => ($message or ''),
'resource' => ($resource or $RESOURCE),
'jserver' => ($jserver or ''),
'port' => ($port or 0),
'tls' => ($tls or 0),
'debug' => ($debug or 0),
'verbose' => ($verbose or 0),
+ 'raw' => ($raw or 0),
'file' => ($file or ($ENV{'HOME'}.'/.sendxmpprc')),
- 'recipient' => $rcpt);
+ 'recipient' => \@rcpt);
if ($DEBUG || $VERBOSE) {
while (my ($key,$val) = each %dict) {
unless ($cnx);
my @res;
- if (!$port) {
- @res = $cnx->Connect(hostname=>$host,tls=>$tls);
- } else {
- @res = $cnx->Connect(hostname=>$host,port=>$port,tls=>$tls);
- }
+ if (!$port) {
+ @res = $cnx->Connect(hostname => $host, tls => $tls);
+ error_exit ("Could not connect to server '$host': $@") unless @res;
+ } else {
+ @res = $cnx->Connect(hostname => $host, port => $port, tls => $tls);
+ error_exit ("Could not connect to '$host' on port $port: $@") unless @res;
+ }
xmpp_check_result("Connect",\@res,$cnx);
my ($cnx, $cmdline, $txt) = @_;
- unless ($$cmdline{'chatroom'}) {
- xmpp_send_message ($cnx,
- $$cmdline{'recipient'},
- $$cmdline{'subject'},
- $txt);
- } else {
- xmpp_send_chatroom_message ($cnx,
- $$cmdline{'resource'},
- $$cmdline{'subject'},
- $$cmdline{'recipient'},
- $txt);
- }
+ unless ($$cmdline{'chatroom'}) {
+ unless ($$cmdline{'raw'}) {
+ map {
+ xmpp_send_message ($cnx,
+ $_, #$$cmdline{'recipient'},
+ $$cmdline{'subject'},
+ $txt)
+ } @{$$cmdline{'recipient'}};
+ }
+ else {
+ xmpp_send_raw_xml ($cnx, $txt);
+ }
+ }
+ else {
+ map {
+ xmpp_send_chatroom_message ($cnx,
+ $$cmdline{'resource'},
+ $$cmdline{'subject'},
+ $_, # $$cmdline{'recipient'},
+ $txt)
+ } @{$$cmdline{'recipient'}};
+ }
}
+#
+# xmpp_send_raw_xml: send a raw XML packet
+# input: connection,packet
+#
+sub xmpp_send_raw_xml ($$) {
+
+ my ($cnx,$packet) = @_;
+
+ # for some reason, Send does not return anything
+ $cnx->Send($packet);
+ xmpp_check_result('Send',0,$cnx);
+}
+
+
#
# xmpp_send_message: send a message to some xmpp user
# input: connection,recipient,subject,msg
sub usage () {
print STDERR
- "sendxmpp version $VERSION, Copyright (c) 2004,2005 Dirk-Jan C. Binnema\n" .
- "usage: sendxmpp [options] <recipient>\n" .
+ "sendxmpp version $VERSION, Copyright (c) 2004, 2005 Dirk-Jan C. Binnema\n" .
+ "usage: sendxmpp [options] <recipient1> [<recipient2> ...]\n" .
"or refer to the the sendxmpp manpage\n";
exit 0;
=head1 SYNOPSIS
-sendxmpp [options] <recipient>
+sendxmpp [options] <recipient1> [<recipient2> ...]
+
+sendxmpp --raw [options]
=head1 DESCRIPTION
=head1 OPTIONS
-B<-f>,B<--file> <file>
-use <file> configuration file instead of ~/.sendxmpprc
+=over
+
+=item B<-f>,B<--file> I<file>
+
+Use I<file> configuration file instead of F<~/.sendxmpprc>
+
+=item B<-u>,B<--username> I<user>
+
+Use I<user> instead of the one in the configuration file
+
+=item B<-p>,B<--password> I<password>
+
+Use I<password> instead of the one in the configuration file
+
+=item B<-j>,B<--jserver> I<server>
+
+Use jabber I<server> instead of the one in the configuration file.
+
+=item B<-r>,B<--resource> I<res>
+
+Use resource I<res> for the sender [default: 'sendxmpp']; when sending to a chatroom, this determines the 'alias'
-B<-u>,B<--username> <user>
-use <user> instead of the one in the configuration file
+=item B<-t>,B<--tls>
-B<-p>,B<--password> <password>
-use <password> instead of the one in the configuration file
+Connect securely, using TLS
-B<-j>,B<--jserver> <server>
-use jabber server <server> instead of the one in the configuration file. Note that you can add :<port> to use a non-default port, ie. B<-j myjabber.org:1234>
+=item B<-c>,B<--chatroom>
-B<-r>,B<--resource> <res>
-use resource <res> for the sender [default: 'sendxmpp']; when sending to a chatroom, this determines the 'alias'
+Send the message to a chatroom
-B<-t>,B<--tls>
-connect securely, using TLS
+=item B<-s>,B<--subject> I<subject>
-B<-c>,B<--chatroom>
-send the message to a chatroom
+Set the subject for the message to I<subject> [default: '']; when sending to a chatroom, this will set the subject for the chatroom
-B<-s>,B<--subject> <subject>
-set the subject for the message to <subject> [default: '']; when sending to a chatroom,
-this will set the subject for the chatroom
+=item B<-m>,B<--message> I<message>
-B<-m>,B<--message> <message>
-read the message from <message> (a file) instead of stdin
+Read the message from I<message> (a file) instead of stdin
-B<-i>,B<--interactive>
-work in interactive mode, reading lines from stdin and sending the one-at-time
+=item B<-i>,B<--interactive>
-B<-v>,B<--verbose>
-give verbose output about what is happening
+Work in interactive mode, reading lines from stdin and sending the one-at-time
-B<-h>,B<--help>,B<--usage>
-show a 'Usage' message
+=item B<-w>,B<--raw>
-B<-d>,B<--debug>
-show debugging info while running. B<WARNING>: This will include passwords etc. so be careful with the output!
+Send raw XML message to jabber server
+
+=item B<-v>,B<--verbose>
+
+Give verbose output about what is happening
+
+=item B<-h>,B<--help>,B<--usage>
+
+Show a 'Usage' message
+
+=item B<-d>,B<--debug>
+
+Show debugging info while running. B<WARNING>: This will include passwords etc. so be careful with the output!
+
+=back
=head1 CONFIGURATION FILE
-You may define a '~/.sendxmpprc' file with the necessary data for your
+You may define a 'F<~/.sendxmpprc>' file with the necessary data for your
xmpp-account, with a line of the format:
- <user>@<host> <password>
+=over
+
+I<user>@I<server> I<password>
+
+=back
e.g.:
# my account
alice@jabber.org secret
-('#' and newlines are allowed like in shellscripts). You can add :<port> to
-the <host> if you need an alternative port, ie.
+('#' and newlines are allowed like in shellscripts). You can add a I<host> (or IP address) if it is different from the I<server> part of your JID:
+
+ # account with specific connection host
+ alice@myjabberserver.com;foo.com secret
+
+You can also add a I<port> if it is not the standard XMPP port:
# account with weird port number
- alice@myjabberhost.com:1234 secret
-
+ alice@myjabberserver.com:1234 secret
+
+Of course, you may also mix the two:
+
+ # account with a specific host and port
+ alice@myjabberserver.com;foo.com:1234 secret
+
B<NOTE>: for your security, sendxmpp demands that the configuration
file is owned by you and has file permissions 600.
Documentation for the L<Net::XMPP> module
-The jabber homepage: http://www.jabber.org/
+The jabber homepage: L<http://www.jabber.org/>
-The sendxmpp homepage: http://www.djcbsoftware.nl/code/sendxmpp
+The sendxmpp homepage: L<http://sendxmpp.platon.sk>
=head1 AUTHOR
sendxmpp has been written by Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>, and uses
-the L<Net::XMPP> modules written by Ryan Eatmon.
+the L<Net::XMPP> modules written by Ryan Eatmon. Current maintainer is
+Lubomir Host 'rajo' <rajo AT platon.sk>, L<http://rajo.platon.sk>
=cut