#!/usr/bin/perl -w # $Id: optus-websms,v 1.5 2008/05/17 07:00:42 suter Exp $ # Copyright (C) 2003 Mark Suter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =head1 NAME optus-websms - send a SMS using Optus' http://www.optuszoo.com.au/ website =head1 SYNOPSIS echo message | optus-websms B =head1 ARGUMENTS =over 8 =item B Arguments should contain only digits. No spaces, hyphens or other punctuation should be used. You may give several mobile numbers. The Optus Web SMS allows sending to many networks, including Optus, Telstra, Orange and Vodafone within Australia and many networks outside Australia. See http://www.optuszoo.com.au/ for more details. =item B The message is accepted from standard input and/or from the B<--message> option and is then filtered: =over 8 =item Only printable characters and spaces are accepted =item Repeated spaces are suppressed. =item Other characters are silently ignored. =back =back =head1 OPTIONS =over 8 =item B<--message=B> Use the provided string as the message. Anything from standard input will be placed after this string (unless B<--no-stdin> is given). =item B<--no-stdin> Ignore standard input completely. =item B<--maxchars>=B<> The maximum number of characters in the message. The default of 160 is the common size for a single SMS "segment". Larger numbers are supported by the Optus Web SMS; however, they may incur higher charges and/or result in multiple SMSes. =item B<--truncate> Silently trucate the message at the maximum length rather then exiting with an error message. =item B<--test> Don't send the message, just display the character count and the message as it would have been sent. =item B<--rc=B> Use the named files for our config. See B below. =item B<--version> Print the version string and exit. =item B<--man> Print the manual page and exit. =item B<--help> Print a brief help message and exit. =back =head1 DESCRIPTION B is a simple interface to the Optus Web SMS service available to authorized users from the http://www.optuszoo.com.au/ website. The Optus Web SMS service has Terms and Conditions and you should understand these before your configure this tool to use your account. =head1 EXIT CODES B will exit with a zero exit status upon success. No output is produced on stdout. B will exit with a non-zero exit status if there was an error, with details on standard error. =head1 FILES If no file is given with the B<--rc> option, the following locations are checked (in order) and the first match is used. =over 8 =item B<$HOME/.optus-websmsrc> =item B =item B =back This two line file must contain your phone number (all digits, no spaces) on the first line and your password (accepted as-is) on the second line. =head1 EXAMPLES Send a congratulatory message to the author: echo Congratulations, Mark | optus-websms 0411262316 Same as above, but using --message option: optus-websms --message "Congratulations, Mark" 0411262316 Announce a meeting to a three phones: echo Meeting at 2pm in room 42 | optus-websms 0411111111 0422222222 0433333333 Report a disk space problem to the sysadmin, with part of the df output, truncated to fit in a single SMS: df | optus-websms --truncate --message "Space low: " 0411111111 See what that message would look like: df | optus-websms --test --truncate --message "Space low: " 0411111111 =head1 SEE ALSO http://www.optuszoo.com.au/ =head1 THANKS =over 8 =item Brian Meilak Very good suggestions for improving this documentation. =item AusCERT staff Several features, including the --message and ---rc options. =item Garth Douglass Updates to the script when Optus changed their site. =back =head1 COPYRIGHT AND AUTHOR Copyright (C) 2003 Mark Suter EFE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or from http://www.gnu.org/licenses/gpl.txt =cut ## ## Main program ## use strict; use Getopt::Long; use Pod::Usage; use WWW::Mechanize; ## Where we get the authentication details (also see --rc=file option) my @rc = ( "$ENV{HOME}/.optus-websmsrc", "/usr/local/etc/optus-websmsrc", "/etc/optus-websmsrc"); ## ## Process our input ## sub process_input() { my ($mobile, $password, $recipients, $message); my %opt = (version => 0, man => 0, help => 0, message => undef, stdin => 1, maxchars => 160, truncate => 0, test => 0, rc => undef); GetOptions(\%opt, "version", "man", "help", "message=s", "stdin!", "maxchars=i", "truncate", "test", "rc=s") or pod2usage(0); $opt{version} and do { print "optus-websms version ", (qw$Revision: 1.5 $)[-1], "\n"; exit; }; $opt{man} and pod2usage(-exitval => 0, -verbose => 2); $opt{help} and pod2usage(0); ## Pick which config file to use my $rc = "no-rc-file-found"; if (defined $opt{rc}) { $rc = $opt{rc}; } else { foreach (@rc) { -e $_ and do { $rc = $_; last }; } } ## Read $rc to get mobile number and password for http://www.optuszoo.com.au/ open RC, "$rc" or die "$0: Can't open \"$rc\": $!\n"; chomp ($mobile = ); $mobile =~ m{^ \d+ $}x or die "$0: Value \"$mobile\" from file $rc doesn't look like a mobile number.\n"; chomp ($password = ); close RC or die "$0: error closing file: $!\n"; ## Get the list of recipients scalar @ARGV >= 1 or pod2usage(1); $recipients = join ",", map { /^(\d{6,})$/ or die "$0: Argument \"$_\" is not a phone number.\n"; $1 } @ARGV; ## Filter a message fragment sub clean($) { my ($string) = @_; $string =~ s/[^[:print:][:space:]]+//go; # Only allow safe characters $string =~ s/[[:space:]]+/ /go; # Squash duplicate spaces return $string; } ## Get the text of the message, starting with the option $message = defined($opt{message}) ? clean $opt{message} : ""; if ($opt{stdin}) { while (read STDIN, my $buffer, $opt{maxchars}) { $message .= clean $buffer; last if length $message >= $opt{maxchars}; } } ## Check the length if (length $message > $opt{maxchars}) { $opt{truncate} or die "$0: your message exceeds $opt{maxchars} characters. Consider --maxchars or --truncate options.\n"; $message = substr($message, 0, $opt{maxchars}); } ## Is this for real? if ($opt{test}) { print "Message is ", length $message, " characters:\n$message\n"; exit; } return $mobile, $password, $recipients, $message; } ## ## Send the message immediately ## sub send_sms_now($$$$) { my ($mobile, $password, $recipients, $message) = @_; eval { ## Ready the UserAgent for use my $ua = WWW::Mechanize->new(autocheck => 1, keep_alive => undef, timeout => 30); $ua->agent_alias("Windows IE 6"); ## Login $ua->get("http://www.optuszoo.com.au/"); $ua->form_number(1); # The first form on the page $ua->set_visible($mobile, $password); $ua->submit(); $ua->content =~ /being validated/i or die "login failed\n"; ## Login part two: An JavaScript submitting intermediate page $ua->submit(); $ua->content =~ /You are here: Optus Zoo Home/i or die "login part two failed\n"; ## Goto the right page $ua->follow_link(text_regex => qr/Text from your PC/i); $ua->content =~ /Enter mobile phone numbers/i or die "goto sms page failed\n"; ## Send our SMS $ua->form_name("send_sms"); $ua->set_fields(mobile_phone => $recipients, message => $message); { local $^W = 0; $ua->field(finish => "Send"); # JavaScript changes the hidden variable } $ua->submit(); $ua->content =~ /SMS was successfully sent/i or die "SMS may not have been sent\n"; ## Logout $ua->follow_link(url_regex => qr/logout\.xml/i); $ua->content =~ /please wait/i or die "logout failed\n"; ## Logout part two $ua->submit(); $ua->content =~ /You have successfully logged out/i or die "logout part two failed\n"; ## Report any errors from inside the eval { }; }; $@ and do { chomp $@; die "$0: $@ - Manually login to http://www.optuszoo.com.au/ and check.\n" }; } ## Main program (called from the very bottom to bring in prototypes) my ($mobile, $password, $recipients, $message) = process_input(); send_sms_now $mobile, $password, $recipients, $message; ## Notice weird things like "no space on device" END { close STDOUT or die "$0: can't close stdout: $!\n" }