#!/usr/bin/perl
# reverse lookup for de,at,ch numbers from Asterisk dialplan.
# found name is stored in asterisk variable ${RESULTREV}
# usage: <script> number 1 (for cached lookups, works only in asterisk)
# <script> number (for normal lookups)
# caching can be also enabled via variable
use warnings;
use strict;
use utf8; #disable if page doesnt use utf8
$|=1; # do not buffer output
#use Asterisk::AGI; # needed for caching in AstDB, install as root: cpan install "Asterisk::AGI"
#my $AGI = new Asterisk::AGI;
use HTML::TreeBuilder 5 -weak; # parses the html page, debian sid unstable: libhtml-tree-perl
use LWP::UserAgent;
use Encode;
use DBI;
###########################
# user defined variables #
my $countryprefix = "00"; #usually 00 or +
my $cache = 1; #can be enabled permanently, but also be controlled over 2nd start parameter
my $family = "cidcache"; # AstDB family used for caching name of reverse lookups (will be disabled if mysql is used)
my $mysql = 1; #mysql will be used for caching if opion is enabled (disables astdb)
my $mysql_phonebook = 1; #use mysql phonebook for additional searching of name and address
my $mysql_db = "asteriskpb";
my $mysql_table = "phonebook";
my $mysql_tablecache = "cdrcache";
my $mysql_host = "localhost";
my $mysql_user = "asterisk";
my $mysql_pwd = "password";
#############################
my $ua = LWP::UserAgent->new();
my ($reverseresult,$reversestreet,$reverseareacode,$reversecity) = "" ; #data for actual reverse lookup
my ($cachename,$cachestreet,$cacheareacode,$cachecity) = "" ; #data for mysql caching
my ($phonename,$phonestreet,$phoneareacode,$phonecity) = "" ; #data for mysql phonebook
my $number = $ARGV[0];
my $searchnotfound = "Can not find predefined html tag or number was not found!\n";
if (! $ARGV[0]) {
print "Missing argument: number!\n";
exit;
}
if (defined $ARGV[1]) { #use as 2nd parameter if found
$cache = $ARGV[1];
}
my %countrylist = ('at' => 43, 'ch' => 41, 'de' => 49); #sub reverselookup has to be changed if modified
my $countlist = keys %countrylist; #this is currently only used to display error if country was not defined
my $i = 0;
if ($cache == 1) {
if ($mysql == 1) { # use MySQL
my $dbh = DBI->connect("DBI:mysql:database=$mysql_db;host=$mysql_host",$mysql_user,$mysql_pwd,
{ RaiseError => 1}
);
# get data from caching table
my $sth = $dbh->prepare("SELECT name,street,areacode,city from $mysql_tablecache WHERE number = ?");
$sth->execute($number);
my $result = $sth->fetchrow_hashref();
$cachename = $result->{name};
$cachestreet = $result->{street};
$cacheareacode = $result->{areacode};
$cachecity = $result->{city};
$sth->finish();
if ($mysql_phonebook == 1) {
#get data from phonebook
$sth = $dbh->prepare("SELECT name,street,areacode,city from $mysql_table WHERE number = ?");
$sth->execute($number);
$result = $sth->fetchrow_hashref();
$phonename = $result->{name};
$phonestreet = $result->{street};
$phoneareacode = $result->{areacode};
$phonecity = $result->{city};
$sth->finish();
}
if ($phonename ne "") {
print "No reverse lookup to be done because name already in phone book\n";
if ((length($phonestreet) > 1) || ( length($phoneareacode) > 1 ) || ( length($phonecity) > 1 )) {
print "SET VARIABLE RESULTREV \"${phonename} ${phonestreet} ${phoneareacode} ${phonecity}\"";
} else {
print "SET VARIABLE RESULTREV \"${phonename}\"";
}
} elsif ($cachename ne ""){
print "No reverse lookup to be done because name already cached\n";
if ((length($cachestreet) > 1) || ( length($cacheareacode) > 1 ) || ( length($cachecity) > 1 )) {
print "SET VARIABLE RESULTREV \"${cachename} ${cachestreet} ${cacheareacode} ${cachecity}\"";
} else {
print "SET VARIABLE RESULTREV \"${cachename}\"";
}
} else {
print "Number not found in phone book or cache, do reverse lookup\n";
reverselookup();
#store result in mysql for caching
if ((length($reversestreet) > 1) || ( length($reverseareacode) > 1 ) || ( length($reversecity) > 1 )) {
## store to mysql with address
$sth = $dbh->prepare("INSERT INTO $mysql_tablecache (number, name, street, areacode, city) VALUES ('$number', '$reverseresult', '$reversestreet', '$reverseareacode', '$reversecity') ON DUPLICATE KEY UPDATE name=VALUES(name),street=VALUES(street),areacode=VALUES(areacode),city=VALUES(city)");
} else {
## store to mysql w/o address
$sth = $dbh->prepare("INSERT INTO $mysql_tablecache (number, name) VALUES ('$number', '$reverseresult') ON DUPLICATE KEY UPDATE name=VALUES(name)");
}
$sth->execute();
$sth->finish();
}
$dbh->disconnect();
} else { # use AstDB
my $astdbget = $AGI->database_get($family,$number);
if (! $astdbget) {
print "Number not found in cache, do reverse lookup\n";
reverselookup();
my $astdbstore = $AGI->database_put($family,$number,$reverseresult);
} else {
print "No reverse lookup to be done because name already cached\n";
print "SET VARIABLE RESULTREV \"${astdbget}\"";
}
}
} else { # no caching
print "\nDo uncached reverse lookup, use 1 as second option if you want cached lookups\n";
reverselookup();
}
sub reverselookup {
if ( grep {/^$countryprefix/} $number ) { #if call from other country
while ( (my $key, my $value) = each %countrylist ) { #iterate through hash
if ( grep {/^$countryprefix$countrylist{$key}/} $number ) { #grep country prefix + country code in beginning of phone number
print "Call from country ",$key,"\n";
if ($key eq "at") {
telefonabc($number);
} elsif ($key eq "ch") {
telsearch($number);
} elsif ($key eq "de") {
oert($number);
}
} else {
$i = $i+1;
if ($i == $countlist) {
print "Country not defined";
}
}
}
} else { #if landline number
oert($number);
if (!defined $reverseresult ) { #do klicktel if oertliches did not find
klick($number);
}
}
}
## german numbers (de) ##
sub oert {
my $urloert = "http://www1.dasoertliche.de/?form_name=search_inv&ph=".$number;
my $responseoert = $ua->get($urloert);
$responseoert->is_success or die "\nHTTP to Oertliches failed\n", $responseoert->status_line, "\n";
my $htmloert = HTML::TreeBuilder->new_from_content( $responseoert->content );
if ( defined $htmloert ) {
$reverseresult = $htmloert->look_down(
_tag => 'a',
class => 'preview iname');
my $reverselocation = $htmloert->look_down(
class => 'strasse');
if (defined $reverseresult ) {
#print "Das Oertliche: [", $reverseresult->as_trimmed_text(extra_chars => '[:space:]'), "]\n";
$reverseresult = $reverseresult->as_trimmed_text;
chop($reverseresult);
$reverselocation=$reverselocation->as_trimmed_text;
($reversestreet, $reverseareacode, $reversecity) = $reverselocation =~ /([^,]+\d+),.(\d+).(\S+)/; #split address into 3 variables
if ((length($reversestreet) > 1) || ( length($reverseareacode) > 1 ) || ( length($reversecity) > 1 )) {
print "SET VARIABLE RESULTREV \"${reverseresult} ${reversestreet} ${reverseareacode} ${reversecity}\"";
} else {
print "SET VARIABLE RESULTREV \"${reverseresult}\"";
}
} else {
print "oert: $searchnotfound";
}
} else {
print "\nTreebuilder cannot read page!\n";
}
}
sub klick {
my $urlklick = "http://www.klicktel.de/inverssuche/index/search?_dvform_posted=1&phoneNumber=".$number;
my $responseklick = $ua->get($urlklick);
$responseklick->is_success or die "\nHTTP to Klicktel failed\n", $responseklick->status_line, "\n";
my $htmlklick = HTML::TreeBuilder->new_from_content( encode_utf8 $responseklick->content );
if (defined $htmlklick ) {
$reverseresult = $htmlklick->look_down(
_tag => 'div',
class => 'results direct');
if (defined $reverseresult ) {
#print "Klicktel: [", $reverseresult->as_trimmed_text(extra_chars => '[:space:]'), "]\n";
print "SET VARIABLE RESULTREV \"" . $reverseresult->as_trimmed_text . "\"";
} else {
print "klick: $searchnotfound";
}
} else {
print "\nTreebuilder cannot read page!\n";
}
}
## austria numbers (at) ##
sub telefonabc {
my $urltelefonabc = "http://www.telefonabc.at/result.aspx?what=".$number;
my $responsetelefonabc = $ua->get($urltelefonabc);
$responsetelefonabc->is_success or die "\nHTTP to telefonabc.at failed\n", $responsetelefonabc->status_line, "\n";
my $htmltelefonabc = HTML::TreeBuilder->new_from_content ( $responsetelefonabc->content );
if ( defined $htmltelefonabc ) {
$reverseresult = $htmltelefonabc->look_down(
_tag => 'span',
class => 'given-name');
if (defined $reverseresult ) {
$reverseresult = $reverseresult->as_trimmed_text;
print "SET VARIABLE RESULTREV \"${reverseresult}\"";
} else {
print "telefonabc: $searchnotfound";
}
} else {
print "\nTreebuilder cannot read page!\n";
}
}
## swiss numbers (ch) ##
sub telsearch {
my $urltelsearch = "http://tel.search.ch/?was=".$number;
my $responsetelsearch = $ua->get($urltelsearch);
$responsetelsearch->is_success or die "\nHTTP to tel.search.ch failed\n", $responsetelsearch->status_line, "\n";
my $htmltelsearch = HTML::TreeBuilder->new_from_content ( $responsetelsearch->content );
if ( defined $htmltelsearch ) {
$reverseresult = $htmltelsearch->look_down(
_tag => 'h4',
class => 'category');
if (defined $reverseresult ) {
$reverseresult = $reverseresult->as_trimmed_text;
print "SET VARIABLE RESULTREV \"${reverseresult}\"";
} else {
print "telsearch: $searchnotfound";
}
} else {
print "\nTreebuilder cannot read page!\n";
}
}