#!/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; }