CNAM (CallerID with Name) on Asterisk using Reverse Phone number lookup

Tom Keating : VoIP & Gadgets Blog
Tom Keating
CTO
| VoIP & Gadgets blog - Latest news in VoIP & gadgets, wireless, mobile phones, reviews, & opinions

CNAM (CallerID with Name) on Asterisk using Reverse Phone number lookup

CallerID is cool, but CallerID with Name (CNAM), -- also known as Calling NAMe -- is where it's at. When you go with a traditional phone provider (non-VoIP) they'll often offer you CallerID with Name for an additional fee. But penny-pinching Asterisk & VoIP fans want CallerID with Name too. Unfortunately, too often the SIP trunks or traditional PSTN trunks (analog, T1/E1) connected to your Asterisk IP-PBX don't provide CallerID with Name - just regular CallerID (number only). So how do we solve this dilemma?

Well, Asterisk sits on an IP network, which of course means it can access the Internet. With access to the Internet, "in theory" a special Asterisk script can take the CallerID number, perform a reverse lookup on AnyWho, Google, and 411.com and then change the CallerID data string before it gets passed to the Asterisk extension.

Well, theory is all well and good, but has it been done? Oh yes it has!

Check out this Perl script I found on Team Forrest's website that leverages AGI (Asterisk Gateway Interface), a powerful interface that lets your programmatically control Asterisk.

Calling the CallerID with Name Perl script (calleridname.pl) is as simple as calling this single line of code:
exten => s,n(getname),AGI(calleridname.pl,${CALLERID(NUM)})

Here's the calleridname.pl script:
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
$|=1;
sub trim($);

my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; my $result = ""; my $cidnum = ""; my $cidname = "";
my $npa = ""; my $nxx = ""; my $station = ""; my $name = "";

$cidnum = $ARGV[0];

while(<STDIN>) {
    chomp;
    last unless length($_);
    if (/^agi_(\w+)\:\s+(.*)$/) {
        $AGI{$1} = $2;
    }
}

my $AnyWho = '1' ;
my $Google = '1' ;
my $www411 = '1' ;


if(substr($cidnum,0,1) eq '1'){
$cidnum=substr($cidnum,1);
}

if(substr($cidnum,0,2) eq '+1'){
$cidnum=substr($cidnum,2);
}

if ($cidnum =~ /^(\d{3})(\d{3})(\d{4})$/) {
    $npa = $1;
    $nxx = $2;
    $station = $3;
    }
elsif($cidnum =~/\<(\d{3})(\d{3})(\d{4})\>/){
    $npa = $1;
    $nxx = $2;
    $station = $3;
    }
else {
    print qq(VERBOSE "ERROR: unable to parse caller id" 2\n);
    exit(0);
}


if ($AnyWho > '0') {
    print qq(VERBOSE "STATUS: checking AnyWho for name lookup" 2\n);
    if ($name = &anywho_lookup ($npa, $nxx, $station)) {
        $cidname = $name;
        print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
        print qq(VERBOSE "STATUS: AnyWho said name was $cidname " 2\n);
        exit(0);
        }
    else {
        print qq(VERBOSE "STATUS: unable to find name with AnyWho" 2\n);
        }
    }
else {
    print qq(VERBOSE "STATUS: AnyWho lookup disabled" 2\n);
}

if ($Google > '0') {
    print qq(VERBOSE "STATUS: checking Google for name lookup" 2\n);
    if ($name = &google_lookup ($npa, $nxx, $station)) {
        $cidname = $name;
        print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
        print qq(VERBOSE "STATUS: Google said name was $cidname " 2\n);
        exit(0);
        }
    else {
        print qq(VERBOSE "STATUS: unable to find name with Google" 2\n);
        }
    }
else {
    print qq(VERBOSE "STATUS: Google lookup disabled" 2\n);
}

if ($www411 > '0') {
    print qq(VERBOSE "STATUS: checking www411 for name lookup" 2\n);
    if ($name = &www411_lookup ($npa, $nxx, $station)) {
        $cidname = $name;
        print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
        print qq(VERBOSE "STATUS: www411 said name was $cidname " 2\n);
        exit(0);
        }
    else {
        print qq(VERBOSE "STATUS: unable to find name with www411" 2\n);
        }
    }
else {
    print qq(VERBOSE "STATUS: www411 lookup disabled" 2\n);
}

print qq(SET VARIABLE CALLERID\(name\) "$cidnum"\n);
print qq(VERBOSE "STATUS: Unknown name for $cidnum " 2\n);
exit(0);

sub anywho_lookup {
    my ($npa, $nxx, $station) = @_;
    my $ua = LWP::UserAgent->new( timeout => 45);
    my $URL = 'http://www.anywho.com/qry/wp_rl';
    $URL .= '?npa=' . $npa . '&telephone=' . $nxx . $station;
    $ua->agent('AsteriskAGIQuery/1');
    my $req = new HTTP::Request GET => $URL;
    my $res = $ua->request($req);
    if ($res->is_success()) {
        if ($res->content =~ /<!-- listing -->(.*)<!-- \/listing -->/s) {
            my $listing = $1;
            if ($listing =~ /<B>(.*)<\/B>/) {
                my $clidname = $1;
                return $clidname;
            }
        }
    }
    return "";
}

sub google_lookup {
  my ($npa, $nxx, $station) = @_;
  my $ua = LWP::UserAgent->new( timeout => 45);
  my $URL = 'http://www.google.com/search?rls=en&q=phonebook:' .  $npa . $nxx . $station . '&ie=UTF-8&oe=UTF-8';
  $ua->agent('AsteriskAGIQuery/1');
  my $req = new HTTP::Request GET => $URL;
  my $res = $ua->request($req);
  if ($res->is_success()) {
    if ($res->content =~ /<font size=-2><br><\/font><font size=-1>(.+)<font color=green>/) {
      my $temp = $1;
      my $clidname = "";
      if ( $temp =~ /(.+)<font color=green>/o ) {
        $clidname = substr($1, 0, -3);
      } else {
        $clidname = substr($temp, 0, -3);
      }
      if ($clidname =~ /<a href(.+)\//) {
        $clidname = $1 ;
        if ($clidname =~ />(.+)</) {
          $clidname = $1 ;
        }
      }
      return $clidname;
    }
  }
  return "";
}

sub www411_lookup {
  my ($npa, $nxx, $station) = @_;
  my $ua = LWP::UserAgent->new( timeout => 45);
  my $URL = 'http://www.411.com/search/Reverse_Phone?phone=' .  $npa . $nxx . $station;
  $ua->agent('AsteriskAGIQuery/1');
  my $req = new HTTP::Request GET => $URL;
  my $res = $ua->request($req);
  if ($res->is_success()) {
    if ($res->content =~ /Location: <strong>(.*)<\/strong>/s) {
      my $temp = $1;
      my $clidname = "";
      $temp =~ s/&amp\;/&/g;
      $temp =~ s/%20/ /g;
                        $clidname = $temp;
            return $clidname;
     }
  }
  return "";
}


For more details, head on over here.


Related Articles to 'CNAM (CallerID with Name) on Asterisk using Reverse Phone number lookup'
ezcallerid-cnam-service.jpg
first-blood-knife-rambo.jpg
skype-bcp-sip-call-report.jpg
hiperpbx-cp-3000.png

Featured Events