#!/usr/bin/perl -w

# Skrypt wysyłający SMS-y na wszystkie polskie sieci przez bramkę
# www.orange.pl, portal "mbox" (tj. z koniecznością logowania).
# https://www.orange.pl/portal/map/map
# Napisany w Perlu. 
# Wymaga: perl + LWP + SSL (RPM-y dla RedHat: perl-libwww, perl-crypt-SSLeay).
#
# (c) 2003 Jacek Fiok <jfiok@jfiok.org>; http://sms.jfiok.org
#
# wysyła wiadomości: do 640 znaków; wszystkie polskie sieci.
#
# Podziękowania dla:
# - Spley <sms@spley.home.pl>
# - Maciej Krzyzanowski <spider@popnet.pl>
# - Łukasz Górowski <lukasz@gorowski.com>
# - Krzysztof Zembrowski <krzysztof@zembrowski.pl>
#
# Przerobka skryptu Ideii, po przemianowaniu sieci na Orange:
# - Rafal 'RaV.' Matczak <rafal.matczak.orangutan.poczta.finemedia.pl>

use strict;
use HTTP::Request::Common;
use HTTP::Cookies;
use LWP::UserAgent;
use Crypt::SSLeay;
# use LWP::Debug qw(+ -conns);
# LWP::Debug::trace('send()');

# ----------------------- pomocnicze -------------------------
my $debug = 0;				# czy "tryb gadatliwy"
my $mode = 0;				# czy pracujemy z raportami doręczenia
my $wait_secs = 0;			# opóźnienie oczekiwania na raport

sub debug { if ($debug) { print "[", shift, "]\n"; } }

sub zakoncz {
  my ($tekst, $ret) = @_;
  print "$tekst\n";
  exit $ret;
}

# format struktury danych:
# string który możemy znaleźć w odpowiedzi z serwera =>
# [co należy z niego wywnioskować-opis, kod powrotu ze skryptu ]
my %odpowiedzi = (
	"Skrzynka wiadomości" => ["Wszystko OK", 0],
	"Zły numer" => ["Zły numer!", 2],
	"został wyczerpany" => ["Limit wiadomości na dziś przekroczony!", 3]
);

# główna procedurka analizująca odpowiedź serwera
# jeśli nie umiemy nic wywnioskować -> rzucamy [Nieznana Odpowiedz, 127]
sub analizujWynik {
	my $res = $_[0];
	my $searchString;
	my @val;
	while ( ($searchString, @val) = each (%odpowiedzi) ) {
	  if ($res =~ /$searchString/ ) {
		  print $odpowiedzi{$searchString}[0], "\n";
		  exit $odpowiedzi{$searchString}[1];
	  }		  
	}
	# jeśli nie znaleziono w opisach
	print "Nieznana odpowiedź:\n$res\n";
	exit 127;
}

# getCookie ($nazwa) -> wartość cookie; wymaga: $cookie_jar.
my $ckey = "";
my $cval = "";
my $cookie_jar = HTTP::Cookies->new;
# zwraca wartość ciasteczka dla podanej nazwy klucza
sub cookieScanner {
	# my $i; for ($i=0; $i<5; $i++) { print $i, " : ", $_[$i], "\n"; }
	($ckey eq $_[1]) and $cval = $_[2]; 
}
sub getCookie {
	$cval = "";
	$ckey = shift;
	$cookie_jar->scan (\&cookieScanner);
	return $cval;
}

my $ua = new LWP::UserAgent;
$ua->timeout(30);
$ua->agent("Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20021216");
$ua->env_proxy();
$ua->cookie_jar($cookie_jar);

# odwiedza stronę $_[0]; w razie błędu wychodzi z tekstem $_[1] i kodem $_[2].
# w zmiennej globalnej $res ląduje HTML -- wynik zapytania.
my $res; my $req;
sub visit {
        $res = $ua->request (GET $_[0]);
        if (!($res->is_success)) { zakoncz($_[1], $_[2]); }
}
# ----------------------- main() -----------------------------

select(STDERR); $| = 1;     # make unbuffered
select(STDOUT); $| = 1;     # make unbuffered

if ($#ARGV != 3 ) { die "Zła ilość parametrów - podaj numer i treść sms-a"; }

my $numer = $ARGV[0];
my $tresc = $ARGV[1];
my $username = $ARGV[2];
my $password = $ARGV[3];
 
$numer =~ s/^\+48//;
$numer =~ s/^00//;

push @{ $ua->requests_redirectable }, 'POST';

# --------- konwersacja -----------

# 1. get sms-index
visit ("http://www.orange.pl/portal/map/map/signin", 
       "Błąd przy otwieraniu formularza [1]", 1);

# 2. send the POST login form
my $par1 = 'https://www.orange.pl/portal/map/map/signin?_DARGS=/gear/static/home/login.jsp.loginFormId';

debug ("Logging in: ".$par1);
$req = POST $par1, [
	"_dyncharset"=>"UTF-8",
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.loginErrorURL"=>"http://www.orange.pl/portal/map/map/signin",
	"_D:/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.loginErrorURL"=>" ",
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.loginSuccessURL"=>"http://www.orange.pl/portal/map/map/pim",
	"_D:/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.loginSuccessURL"=>" ",
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.login"=>$username,
	"_D:/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.login"=>" ",
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.password"=>$password,
	"_D:/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.value.password"=>" ",
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login.x"=>0,
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login.y"=>0,
	"/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login"=>" ",
	"_D:/amg/ptk/map/core/formhandlers/AdvancedProfileFormHandler.login"=>" ",
	"_DARGS" => "/gear/static/signIn.jsp",
];


$req->referer ("http://www.orange.pl/portal/map/map/signin");
$res = $ua->request($req);
if (! ($res->is_success)) { zakoncz("Błąd przy logowaniu [2]", 1); }
#if (($res->content =~ /Nieprawidłowe hasło/) or (!($res->content =~ /Dziś jest/))) { zakoncz("Błąd przy logowaniu - nieprawidłowe hasło? [2]", 1); } 
# wczesna, przedswiateczna, grudniowa zmiana 2007 --> "witaj" [KZ]
if (! ($res->content =~ /witaj/) ) { zakoncz("Błąd przy logowaniu - nieprawidłowe hasło? [2]", 1); } 

debug ("zalogowany");

#$req = GET 'http://www.orange.pl/portal/map/map/message_box';

#my $stamp;
#if ($res->content =~ /mbox_view=newsms\&mbox_edit=new\&stamp=([0-9]+)\" /) { $stamp = eval ($1); }
#print "XXX: $stamp\n\n\n\n\n\n\n";

$req = GET 'http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new';


$res = $ua->request($req);

# [debug] print($res->content);

# odczytaj ilosc pozostalych smsow (orange zmienia to co jakis czas, zostawiamy 2 rozne regexpy, tak ze zamatchuje sie czy beda pisali z extra z doladowan, czy bez)
my $sms_zostalo = 666;
#if ($res->content =~ /<div class=\"label\">darmowe:.*>([0-9]+)<.*?z do..adowa..:.*>([0-9]+)</sm) { 
#if ($res->content =~ /<span class=\"label\">darmowe:<\/span>
#		    <span class=\"value\">([0-9]+)</span>/) { 
#	$sms_zostalo = eval ($1) + eval ($2); 
#} elsif ($res->content =~ /<div class=\"label\">darmowe:.*>([0-9]+)<\/div/sm) {
#	$sms_zostalo = eval ($1);
#}
# if ($res->content =~ /SMSy darmowe:.*?>([0-9]+)</sm) { $sms_zostalo = eval ($1) ; }

#if ($res->content =~ /darmowe:.*\n[^>]+>([^<]+)</) { $sms_zostalo = eval ($1); }


#print $res->content;
#exit;

# ---- tutaj zmiana ----------------
# if ($res->content =~ /<span class=\"label\">darmowe:<\/span>\n.*<span class=\"value\">([0-9]+)<\/span>/) { $sms_zostalo = eval ($1); }
if ($res->content =~ /<span class=\"label\">bezp..atne :<\/span>\n<span class=\"value\">([0-9]+)<\/span>/) { $sms_zostalo = eval ($1); }
#<span class="label">bezp..atne :</span>
#<span class="value">28</span>
# ----------------------------------

#print $sms_zostalo;
#exit;

if ($sms_zostalo == 666) { zakoncz ("Nie mogę odczytać ilości dostępnych SMSów !!!", 1); }
if ($sms_zostalo == 0) { zakoncz ("Limit wiadomości na ten miesiąc przekroczony", 3); }

#---------- tutaj zmiana --------- [alo i nie]
#visit ('http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new', "Błąd przy otwarciu skrzynki SMS [3]", 1);
#visit ('http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new', "Błąd przy otwarciu formularza SMS [4]", 1);
#my $stamp;
#if ($res->content =~ /mbox_view=newsms\&mbox_edit=new\&stamp=([0-9]+)\" /) { $stamp = eval ($1); }
#print "XXX: $stamp\n\n\n\n\n\n\n";

#visit ('http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new&stamp=$stamp', "Błąd przy otwarciu formularza SMS [4]", 1);
visit ('http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new', "Błąd przy otwarciu formularza SMS [4]", 1);
#---------------------------------

debug ("przed wysłaniem POST");

# _DARGS=/gear/mapmessagebox/smsform.jsp na WWW jest i w GET string i w POST :)
$req = POST 'http://www.orange.pl/portal/map/map/message_box??_DARGS=/gear/mapmessagebox/smsform.jsp', [
'_dyncharset' => "UTF-8",
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.type' => "sms",
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.type' => " ",
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.errorURL' => '/portal/map/map/message_box?mbox_view=newsms',
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.errorURL'  => " ",
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.successURL' => '/portal/map/map/message_box?mbox_view=messageslist',
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.successURL' => " ",
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.to' => $numer,
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.to' => " ",
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.body' => " ",
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.body' => $tresc,
'counter' => (640 - length($tresc)),
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.x' => 0,
'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.y' => 0,
'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create' => " ",
'_DARGS' => '/gear/mapmessagebox/smsform.jsp'
];
$req->referer('http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new');

debug ("dotarłem OK do końca procedury, wysyłam...");

$res = $ua->request($req);
if (!($res->is_success)) { zakoncz("Błąd przy ostatecznym wysyłaniu SMS [5]", 1);
}
# analizujWynik ($res->content);

# podobnie jak przy sprawdzaniu pierwotnym, probujemy zamatchowac napis ze strony wynikowej na 2 sposoby.
my $sms_zostalo2 = 666;

#if ($res->content =~ /<div class=\"label\">darmowe:.*>([0-9]+)<.*?z do..adowa..:.*>([0-9]+)</sm) {
#        $sms_zostalo2 = eval ($1) + eval ($2);
#} elsif ($res->content =~ /<div class=\"label\">darmowe:.*>([0-9]+)<\/div/sm) {
#        $sms_zostalo2 = eval ($1);
#}

#---------- tutaj zmiana ------ [bezplatne :]
# ddd if ($res->content =~ /<span class=\"label\">darmowe:<\/span>\n.*<span class=\"value\">([0-9]+)<\/span>/) { $sms_zostalo2 = eval ($1); }
if ($res->content =~ /<span class=\"label\">bezp..atne :<\/span>\n.*<span class=\"value\">([0-9]+)<\/span>/) { $sms_zostalo2 = eval ($1); }
#------------------------------

if ($sms_zostalo2 == 666) { zakoncz ("Nie mogę odczytać ilości dostępnych SMSów", 1); }
# ugly hack z kropkami - x2, bo strona przychodzi w UTF8
if ($res->content =~ /Nie mo..esz wys..a.. SMS..w poza sie.. Orange/) { zakoncz ("Nieprawidłowy numer - bramka wysyła SMSy tylko do Orange (pozostały limit: ".$sms_zostalo2.")", 2); }

if ($sms_zostalo > $sms_zostalo2) {
	zakoncz ("Wszystko OK; pozostały limit wiadomości: ".$sms_zostalo2, 0); 
} else {
	zakoncz ("Wiadomość wysłana, ale STATUS NIEZNANY (raportowane limity: przed wysłaniem: ".$sms_zostalo.", po wysłaniu: ".$sms_zostalo2.").", 0);
}

# TODO: to obsługuje raporty doręczenia!!!
# http://www.orange.pl/portal/map/map/message_box?mbox_view=sentmessageslist

