#!/usr/bin/perl
#BEGIN LICENSE
#Copyright (c) 2008 Barry Coughlan
#Permission is hereby granted, free of charge, to any person
#obtaining a copy of this software and associated documentation
#files (the "Software"), to deal in the Software without
#restriction, including without limitation the rights to use,
#copy, modify, merge and/or distribute copies of the Software,
#and to permit persons to whom the Software is furnished to do so,
#subject to the following conditions:
#
#The above copyright notice and this permission notice shall be
#included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
#OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#OTHER DEALINGS IN THE SOFTWARE.
#END OF LICENSE
require HTTP::Cookies;
require LWP;
require Getopt::Long;
# Import command lines, get the message to send, set up cookies for site
init();
# Order: URL, form method, parameters, regular expression to match so we know we're on the right page,
# reference to function that handles this result, ref to function that handles it if expression doesn't match
@url = (
# Page is for logging in
['https://www.mymeteor.ie/go/mymeteor-login-manager',
"POST",
'username=' . $username . '&userpass=' . $password . '&dologin=1&returnTo=/mymeteor/login.cfm',
"stat=success",
\&callback_login,
\&callback_loginfailed,
],
# Page is for getting SMS info (free texts left)
['https://www.mymeteor.ie/go/freewebtext',
"GET",
"",
'Free web texts left .*Group web texts left as_string =~ m/(login\.cfm\?stat=req.*\n)/) {
print STDERR "\nYou have entered a wrong PIN\nLog in to www.mymeteor.ie manually then log out. Then run the program with the -n (or --newcookies) option and it should work.";
exit 0;
}
if($res->as_string !~ m/(stat=stui|stat=invalid)/) {
print STDERR "\nERROR: Epic Fail while trying to log in, didn't receive either login failed, login succeeded or CAPTCHA page\n";
exit 0;
}
print STDERR "\nERROR: Login failed - incorrect username or password\n";
exit 0;
}
sub callback_smsinfo {
print "\nFree web texts left: " . $1 . ", Group web texts left: " . $2 . "\n";
if ($1 == 0) {
print "\nNo free web texts left. This program does not support group texts.\n";
}
}
sub callback_smsinfofailed {
print STDERR "\nERROR: Could not get SMS info page\n";
exit 0;
}
sub callback_addrecipient {
print "\nSuccessfully added receipient...\n";
}
sub callback_addrecipientfailed {
print "\nERROR: Could not add recipient\n";
exit 0;
}
sub callback_sent {
print "\nMessage sent.\n";
}
sub callback_sentfailed {
print "\nERROR: Message sending failed\n";
exit 0;
}
#####################################################
#Begin main program structure
#####################################################
print "Attempting login...\n";
HTTPrequest->(@url[0]);
print "Attempting to get SMS page...\n";
HTTPrequest->(@url[1]);
foreach (@recipients) {
print "Adding recipient $_...";
$url[2][2] =~ s/%7C/%7C$_/; #Add recipient to URL string
HTTPrequest->(@url[2]);
}
print "Sending text...";
HTTPrequest->(@url[3]);
#####################################################
# Unlikely you will have to make changes beyond this point
# ###################################################
sub HTTPrequest {
# Log in to meteor
$req = HTTP::Request->new($_[0][1], $_[0][0]);
if($login[1] == "POST") { $req->content_type('application/x-www-form-urlencoded'); }
$req->content($_[0][2]);
$res = $ua->request($req) or die("HTTP error\b");
$cookie_jar->extract_cookies($res);
print $req->as_string . "\n\n" if defined $debug;
print $res->as_string if defined $dump;
# Check if it worked
if($res->as_string !~ m/$_[0][3]/s) {
$_[0][5]->();
}
else {
$_[0][4]->();
}
}
sub init() {
$ua = LWP::UserAgent->new;
$message = "";
#Import command line
Getopt::Long::GetOptions ("username|u=s" => \$username, "password|p=s" => \$password,
'recipients|recipient|r=s@{1,}' => \@recipients, "message|m=s" => \$message, "newcookies|n!" => \$newcookies, "debug|d!" => \$debug, "dump|dd!" => \$dump);
usage() if (!(defined $username && defined $password && defined @recipients));
chomp($username);
if ($username !~ m/^[0-9]*$/) {
print "Username \"$username\" must contain only numbers\n$0";
exit;
}
foreach (@recipients) {
chomp($_);
if($_ !~ m/^[0-9]*$/) {
print "Recipient \"$_\" must contain only numbers\n";
exit;
}
}
# No message? Read it from STDIN until CTRL+D or . on a line of its own is received
if ($message eq "") {
while($line = ) {
$message .= $line;
last if ($message =~ s/^.$//m)
}
}
# Set up cookies
$cookie_jar = HTTP::Cookies->new(
file => "$ENV{'HOME'}/.meteor_cookies",
autosave => 1);
if(!defined $newcookies) {
$ua->cookie_jar($cookie_jar);
}
else {
$ua->cookie_jar( {} );
}
}
sub usage()
{
print STDERR << "EOF";
Send SMS with the specified provider. Currently only meteor is supported.
usage: $0 -u username -p password -r recipient1 recipient2 etc. [-m message] [-d] [-dd]
If no message given, input is taken from stdin.
Long forms:
-u --username
-p --password
-r --recipients
-m --message
-n --newcookies don't reuse old cookies
-d --debug (PRINTS HTTP HEADERS SENT)
-dd --dump (PRINTS HTTP RESPONSE)
EOF
exit;
}