#!/usr/bin/perl -w
# FritzBox Phone Callmonitor
# by uha, V0.01
# changes by teus $Id: fbfcall.pl,v 1.24 2006/05/06 19:36:16 mythtv Exp $

# all of these settings should go into an etc/fbfcall.conf file
# FritzBox Phone

# do not run this program as root, create an account e.g. fritz for this

# README:
# put this script into /usr/local/bin as fbfcall.pl
# create the /usr/local/etc/fbfcall.conf config file (see the example data)
# create the /etc/init.d/fbfcall deamon file (see example)
# have a look at monitor program possibilities (VDR)
# have a look how to convert a phone number to a name, street. town
# for countries as germany, hollan d this is tested
# make sure log files can be written/read by this script

# defaut values
my $FBF_IP	= "fritz.box";		# IP-Adresse
my $FBF_PORT	= 1012;			# Portnummer (Server aktiv mit #96*5*)
# fbfcall configuration file
my $CONFIGFILE	= "/usr/local/etc/fbfcall.conf";

# Telefon-Konfig (should be read from Fritz!Box)
# phone number with regional code and leading zero
# number needs not to be the same amount
# mapping of the internal msn numbers. This is defined in FritzBox
my %MSN = (
	'0213456789' => 'string1',
        '0132456789' => 'string2',
        '0134256789' => 'string3',
        '0124356789' => 'string4',
        '0123546798' => 'string5',
        '0123465789' => 'string6',
        '0123457689' => 'string7',
        '0123456879' => 'string8',
);

# mapping of the names of lines (depends on frameware) used by FritzBox
my %LINES = (
        'ISDN'    => 'ISDN',
        'ANALOG'  => 'analoog',
        'SIP0'    => 'VoIP',
        'SIP1'    => 'VoIP',
        'SIP2'    => 'VoIP',
        'SIP3'    => 'VoIP',
        'SIP4'    => 'VoIP',
        'SIP5'    => 'VoIP',
        'SIP6'    => 'VoIP',
        'SIP7'    => 'VoIP',
        'SIP8'    => 'VoIP',
        'SIP9'    => 'VoIP',
);

# VDR-Konfig
my $VDR_IP	= "localhost";		# IP-Adresse
my $VDR_PORT	= 2001;			# IP-Port
#not used my $VDR_SEND	= "/usr/local/vdr/svdrpsend.pl"; # display log on line
#not used my $SLIMPPRGM	= "/usr/local/bin/tell_slimp3"; # display number on slim device
my $TIME2DISPLAY = "120";

# Files Make sure you have write permission on these files
my $LOGFILE	= "/var/log/fbfcall.log";
my $RUNPIDFILE	= "/var/run/fbfcall.pid";

my $MONITORFILE	= "/var/log/Tel_Numbers"; # logging dates + tel numbers
# format cache file: number,name,street,town # should have date entered field (TTL)
# could have read in and attach latest date of calling and
# dumping out the file regularly
my $CACHFILE	= "/village/ptt/Collected_numbers"; # comma separated database

my $COUNTRY	= "31"; # default country tel code
my $TOWN	= "79"; # defualt regional code

#
# ---------------------------------------
#

use Getopt::Std;
# options:
# -d sets debug flag
# -f sets running in foreground
# -l sets logfile
# -m monitor file
# -t time display
# -p pid file
# -C country
# -P caching phone file
# -T regional phone number
# -c fbfcall config file
# -i read from std input iso telnet socket to fritz!box
# -h help

getopts('difhl:m:t:P:p:C:c:T:u:');
if ( defined $opt_l and $opt_l ne "" ) { $LOGFILE = $opt_l }
if ( defined $opt_m and $opt_m ne "" ) { $MONITORFILE = $opt_m }
if ( defined $opt_t and $opt_t ne "" ) { $TIME2DISPLAY = $opt_t }
if ( defined $opt_p and $opt_p ne "" ) { $RUNPIDFILE = $opt_p }
if ( defined $opt_C and $opt_C ne "" ) { $COUNTRY = $opt_C }
if ( defined $opt_P and $opt_P ne "" ) { $CACHFILE = $opt_P }
if ( defined $opt_c and $opt_c ne "" ) { $CONFIGFILE = $opt_c }
if ( defined $opt_T and $opt_T ne "" ) { $TOWN = $opt_T }
if ( defined $opt_h and $opt_h ne "" ) {
	print "fbfcall: argument options:\n" ;
	print " -d sets debug flag\n" ;
	print " -f sets flag running in foreground\n" ;
	print " -l <logfile>\n" ;
	print " -m <monitor file>\n" ;
	print " -t <seconds> to display monitoring message\n" ;
	print " -p <pid file>\n" ;
	print " -C <country code>\n" ;
 	print " -P <caching phone file>\n" ;
	print " -T <regionalphone number>\n" ;
 	print " -c <fbfcall config file>\n" ;
	print " -i read records from std input iso fritz!box\n" ;
 	print " -h this help message and exit\n" ;
	print " -u [<country code>]<region><local number> check reverse phone number lookup url\n" ;
	exit 0;
}

if ( defined $opt_u and $opt_u>0 ) {
    my $cntry = "";
    my $number = "";
    $_ = $opt_u;
    s/^/0/ if /^[1-9]/;
    $cntry = "31" if /^0[1-9][0-9]{8}$/; # Holland has 10 digits (others ??)
    $number = $opt_u if /^0[1-9][0-9]{8}$/; # may change this for other cntries
    if( /^\+/ ) {
        s/^.//; $cntry = $_; $cntry =~ s/(^..).*/$1/; s/^../0/;
    }
    if( /^00/ ) {
        s/^00//; $cntry = $_; $cntry =~ s/(^..).*/$1/; s/^../0/;
    }
    s/.*([0-9]+).*/$1/; # allow only digits
    $cntry = $COUNTRY if not $cntry; # default
    $number = $_ if not $number ;
    if ( $number ) {
        printf ("Trial reverse lookup for $opt_u returned record:\n\t\"%s\"\n",reverse_lookup($cntry,$number));
    }
    exit 0;
}

$opt_f = 0 if defined $opt_i;
$opt_f = 0 if defined $opt_d;
if ( not defined $opt_f ) { # deamonize
    FORK: {
        if ( $pid = fork ) {
            open (LOG, ">>$RUNPIDFILE");
            printf LOG ("%d\n", $pid);
            close (LOG);
            exit 0; # let my child go on it's own
        }
        elsif (defined $pid) { # child here
	    $0 = "fbfcall" ; # this might not work on all systems
            close STDIN ; close STDOUT; close STDERR;
        }
        elsif ( $! =~ /No more processs/) {
            sleep 20;
            redo FORK;
        } else {
            die "Cannot deamonize\n";
        }
    }
}

# next should go for fedora core systems into /etc/init.d/fbfcall
##!/bin/sh
##
## $Id: fbfcall.pl,v 1.24 2006/05/06 19:36:16 mythtv Exp $
## Startup script for the Linux Infrared Remote Control.
##
## chkconfig: - 90 10
## description: Enables infrared controls through LIRC.
##
## config: /usr/local/etc/fbfcall.conf
#
## Source 'em up
#. /etc/init.d/functions
#
#[ -x /usr/local/bin/fbfcall.pl ]  || exit 1
## USER="--user=fritz"  # do not run this as root
#
#[ -f /etc/sysconfig/fbfcall ] && . /etc/sysconfig/fbfcall
#
#RETVAL=0
#
#start(){
#		echo -n $"Starting Fritz!Box phone monitor deamon: "
#		deamon $USER /usr/local/bin/fbfcall.pl $FBF_OPTIONS
#		RETVAL=$?
#		echo
#	return $RETVAL
#}
#
#stop(){
#		echo -n $"Stopping Firtz!box monitoring deamon: "
#		killproc /usr/local/bin/fbfcall
#		echo
#	RETVAL=$?
#	/bin/rm -f /var/lock/subsys/fbfcall /var/run/fbfcall.pid
#	return $RETVAL
#}
#
#restart(){
#	stop
#	start
#}
#
#
## See how we were called.
#case "$1" in
#	start)
#		start
#		;;
#	stop)
#		stop
#		;;
#	restart)
#		restart
#		;;
#	status)
#		# status fbfcall
#		;;
#	condrestart)
#		[ -e /var/lock/subsys/fbfcall ] && restart
#		;;
#	*)
#		echo $"Usage: $0 {start|stop|status|restart|condrestart}"
#		RETVAL=1
#esac
#
#exit $RETVAL
## EOF file /etc/init.d/fbfcall

# the FBFCALL CONFIG FILE should be in /usr/local/etc/fbfcall.conf
## $Id: fbfcall.pl,v 1.24 2006/05/06 19:36:16 mythtv Exp $ EXAMPLE
## configuration filr for Fritz!Box Phone monitoring program fbfcall
## configuration for localhost@domain.nl
## installed April 2006
##
#FBFCALL
#
#[init]
#    # Frits!Box access details
#	FBF_IP      = fritz.box
#	FBF_PORT    = 1012
#    # VDR stuff (display somewhere somehow)
#	VDR_IP      = localhost
#	VDR_PORT    = 2001
#	VDR_SEND  = /usr/local/vdr/svdrpsend.pl
#    # special for slim device display and music box
#	SLIMPPRGM   = /usr/local/bin/tell_slimp3
#	TIME2DISPLAY = 120 # seconds for on line display
#    # logging files
#	LOGFILE     = /var/log/fbfcall.log
#	MONITORFILE = /var/log/Tel_Numbers
#	CACHFILE    = /village/ptt/Collected_numbers
#    # phone number country and regional stuff
#	COUNTRY     = 31 # my country code
#	TOWN        = 98 # my regional code
#    # place to put the PID of deamon (fbfcall)
#	RUNPIDFILE  = /var/run/fbfcall.pid
#	
## mapping of internal msn numbers to names
#[msn]
#	3207051	= string
#	3270502	= string
#	3702054	= string
#	3270503	= string
##	3206110	= string
#	3201761	= string
#	3201763	= string
##	3271602	= string
#
## mapping of line numbers to types
#[line]
##	ISDN	= ISDN
#	ANALOG	= analoog
#	SIP0	= VoIP
##	SIP1	= VoIP
#	SIP2	= VoIP
#	SIP3	= VoIP
#	SIP4	= VoIP
##	SIP5	= VoIP
#	SIP6	= VoIP
##	SIP7	= VoIP
#	SIP8	= VoIP
#	SIP9	= VoIP
#
### EOF file /usr/local/etc/fbfcall.conf

# read the fbfcall config file
sub fbf_config {
    my $file = shift;
    my $config = 0;
    my $type = "";
    if ( not open FILE, $file ) {
	printf STDERR "$0: WARNING, cannot open config file \"$file\"\n";
	return
    }
    while (<FILE>) {
	chomp; s/\s*#.*//; next if /^$/;
    	s/^\s+//; s/\s+$//;
    	if ($config == 0 ) {
    	    die "$0: $file is not a FBFCALL configure file\n" if not /FBFCALL/i;
	    $config = 1;
	}
	if ( /^\s*\[.*\]/ ) {
	    $type = "";
	    s/\s*\[\s*//; s/\s*\].*//;
	    {
		/^INIT$/i and $type = "init", last ;
		/^MSN$/i  and $type = "msn", last ;
		/^LINES$/i and $type = "lines", last ;
		/^LINE$/i and $type = "lines", last ;
	    }
	}
	next if not $type;
	if ( $type eq "msn" ) {
	    if( not defined $m ) { $m = 0; %MSN = (); } # no defaults
	    if (/([1-9]\d*)\s*=\s*(\w+)/ ) { $MSN{standard_nr($1)} = $2; }
	}
	if ( $type eq "lines") {
	    if( not defined $l ) { $l = 0; %LINES = (); } # no defaults
	    if ( /(\w+)\s*=\s*(\w+)/ ) { $LINES{$1} = $2; }
	}
	if ( $type eq "init" and /([\w_]+)\s*=\s*([\w\/\._-][\w\/\. \t-_]*)/ ) {
		$file = $2; $_ = $1;
		{
		/^FBF_IP$/i	and $FBF_IP = $file, last;
		/^FBF_PORT$/i	and $FBF_PORT = $file, last;
		/^VDR_IP$/i	and $VDR_IP = $file, last;
		/^VDR_PORT$/i	and $VDR_PORT = $file, last;
		/^SLIMPPRGM$/i	and $SLIMPPRGM = $file, last;
		/^LOGFILE$/i	and $LOGFILE = $file, last;
		/^MONITORFILE$/i and $MONITORFILE = $file, last;
		/^CACHFILE$/i	and $CACHFILE = $file, last;
		/^COUNTRY$/i	and $COUNTRY = $file, last;
		/^TOWN$/i	and $TOWN = $file, last;
		/^TIME2DISPLAY$/i and $TIME2DISPLAY = $file, last;
		/^RUNPIDFILE$/i	and $RUNPIDFILE = $file, last;
		}
	}
    }
    close FILE;
}
fbf_config ($CONFIGFILE);

# make names start with a capital (this is very language dependent)
sub capitalize {
    $_ = shift;
    return "" if not $_ ;
    s/([a-zA-Z]\w+)/\u$1/g;
    s/(.*)/ $1 /;
    s/ ([a-z])/ \u$1/g; s/ ([A-Z]) / $1\. /g; s/ ([A-Z]) / $1\. /g;
    s/\b(\w\w)\b/\l$1/g; s/\bVan\b/van/g; s/\bDer\b/der/g;
    s/\bRegio\b/regio/;
    # standardize pcode (one might add NL- to the pcode)
    s/\b([0-9][0-9][0-9][0-9])\s+([A-Za-z][A-Z])\b/$1\U$2/;
    s/^ (.*) $/$1/;
    return $_;
}

sub phone_database {
    my $file = shift;
    if ( not open FILE, $file ) {
	printf STDERR "$0: WARNING, cannot open phone database file file \"$file\"\n";
	return
    }
    %COLLECTED = (); # empty my current databse
    while (<FILE>) {
	# fields: number.name.street,town[,date_inserted ([yy]yy/mm/dd)]
	s/\s*#.*//; next if /^$/;
	my @record = split(/,/,$_,5);
	for (my $index = 1; $index<4; $index++) {
		$record[$index] = capitalize($record[$index]);
        }
        if ( $record[4] ) {
	$COLLECTED{$record[0]} = "$record[0],$record[1],$record[2],$record[3],$record[4]";
	} else {
	$COLLECTED{$record[0]} = "$record[0],$record[1],$record[2],$record[3]";
	}
    }
    close FILE ;

    if( defined $opt_d and $opt_d > 1 ) {
	print "Content collected phone cache file:\n";
	my @keys = keys %COLLECTED;
	foreach my $elem (@keys) { print "$elem: $COLLECTED{$elem}\n" }
	print "\n"
    }
}

phone_database ( $CACHFILE );

# update with cur date current collected phone number records
# two arguments: phone_numer and value (nr,name,street,town[,entry_date])
# convert on the fly to yyyy/mm/dd date notition
sub update_cache {
    my $addit = shift;
    my $number = shift;
    my ($mday, $mon, $year) = (localtime(time()))[3,4,5]; $year += 1900;
    if ( not defined $COLLECTED{$number}) {
	$_ = shift;
	if ( $addit ) {
	    return "" if /\.\.\./;
	    s/,*$/,$year\/$mon\/$mday/;
            $COLLECTED{$number} = $_;
	    return $COLLECTED{$number}
	} else { return "" }
    }
    $_ = $COLLECTED{$number};
    my @record = split(/,/,$_,5);
    $record[4] = "9999/12/31" if not $record[4];
    my @recs = split(/\//,$record[4],3);
    if ( $recs[0] < 50 ) { $recs[0] += 2000 }
    elsif ( $recs[0] < 1900 ) { $recs[0] += 1900 }
    my $mydate = $recs[0]*10000+$recs[1]*100+$recs[2];
    my $curdate = $year*10000+$mon*100+$mday;
    if ( $mydate < $curdate ) {
        $COLLECTED{$number} = "$record[0],$record[1],$record[2],$record[3],$record[4]" 
    }
    return $COLLECTED{$number}
}
    
# set Signalhandler
$SIG{TERM} = \&terminate;
$SIG{ALRM} = \&timeout;
$SIG{HUP} = \&hup;

use IO::Socket;
use LWP::UserAgent;
chdir "/tmp"; # working directory, just when (wget) garbage is created
logger("fbfcall started ...\n");

# Mainloop
my $not_connected = 0;
while("true") {
    if  ( defined $opt_i ) { # read records from stdin
        $socket = STDIN ;
	exit 0 if $not_connected
    } else {
        $socket = IO::Socket::INET->new( 
	    PeerAddr => $FBF_IP,
            PeerPort => $FBF_PORT,
	    Proto => 'tcp');				     
    }
    if (!$socket) {
	logger("Can't connect to FritzBox Phone <$FBF_IP:$FBF_PORT> - $! -> END\n");
	if ( $not_connected++ < 10 ) { sleep 2*60; next }
        else {
	    die("Can't connect to FritzBox Phone <$FBF_IP:$FBF_PORT> - $!\n");
	}
	}
    else {
	$not_connected = 1;
	logger("Connected succesfully to FritzBox Phone '$FBF_IP:$FBF_PORT'\n");
	if( defined $opt_d and $opt_d>0 ) { print("Connected succesfully to FritzBox Phone '$FBF_IP:$FBF_PORT'\n"); }
    }

    while (defined($data=<$socket>)) {
	next if ( not $data =~ /;.*;/ );
	chop($data); chop($data);  # delete \n and ^M characters
	# nr of call in progrss -> cip id
	# record: <date time>;RING;<cip id>;<caller id>;<msn called>;<line id>^M
	# record: <date time>;CALL;<cip id>;<line>;<S0 caller id>;<nr dialed>;^M
	# record: <date time>;CONNECT;<cip id>;<line>;<nr dialed>;^M
	# record: <date time>;DISCONNECT;<cip id>;<seconds>;^M
	# port strings: analog: 1, 2, 3, 9 (all)
	# 		isdn: 50 (all), 51-59
	# <nr dialed> is as is provided by user>
	# <caller id> will have 0<region code><tel number>
        logger("from FritzBox Phone \"$data\"\n");
	my @fbfstr = split(/;/, $data, 7);
	# do something @ incomming call, RING
	if ($fbfstr[1] =~/RING/i) {
	# record: <date time>;RING;<cip id>;<caller id>;<msn called>;<line id>^M
	    # get who is calling and do name lookup via calling number
	    my @anruf = nr2string($fbfstr[3]);
	    # @anruf has 4 fields (... is empty field): number,name,street,town,pretext
	    # get MSN called
	    my $mymsn = my_msn( $fbfstr[4]);
	    # Line called
	    my $line = my_line( $fbfstr[5] );
	    #
	    monitor($fbfstr[0], "$anruf[0], $anruf[1], $anruf[3] called $fbfstr[4] ($mymsn/$line)\n");
	    if( defined $opt_d and $opt_d>0 ) { printf("$anruf[4] - Caller \"$anruf[1], $anruf[2], $anruf[3]\" ($anruf[0]) called $mymsn ($fbfstr[4])/$line ($fbfstr[5])\n"); }
	    # VDR-OSD
	    vdr_mesg($fbfstr[0], $anruf[0], $anruf[1], $anruf[3], $mymsn, $line);
	}
	elsif ($fbfstr[1] =~/CALL/i) {
	# record: <date time>;CALL;<cip id>;<line>;<S0 caller id>;<nr dialed>;^M
	    my @anruf = nr2string( standard_nr($fbfstr[5]) );
            my $mymsn = my_msn( $fbfstr[4]);
	    if ( $mymsn eq "?" ) { $mymsn = "$fbfstr[4]" }
            monitor($fbfstr[0], "$mymsn called $anruf[0], $anruf[1], $anruf[3]\n");
            if( defined $opt_d and $opt_d>0 ) { printf("$anruf[4] - Called \"$anruf[1], $anruf[2], $anruf[3]\" ($anruf[0]) by $mymsn ($fbfstr[4])\n"); }
            # VDR-OSD
            vdr_mesg($fbfstr[0], $anruf[0], $anruf[1], $anruf[3], $mymsn, "call");
	}
    }
    close $socket;
    logger( "Fritz!Box Phone monitoring ended\n");
}

# returns a lookup of internal line name
sub my_line {
    my $arg = shift;
    return "?" if not defined $arg;
    if ( defined $LINES{$arg} )  { return $LINES{$arg} }
    return "?";
}

sub standard_nr {
    my $number = shift;
    my @special = ("112");
    my $ll = 15; # country dependent std length phone number 0<TOWN><NUMBER>
    if( $COUNTRY eq "31" ) { $ll = 9 }
    foreach (@special) {
        if ($_ =~ /$number/i) {
            return $number;
        }
    }
    if ($number =~ /^[1-9]/ ) { # country dependent?
	return "0$number" if ( length($number) == $ll );
        return "0$TOWN$number" if ( length("$TOWN$number") == $ll );
    }
    return $number;
}

# returns a lookup of internal msn to string
sub my_msn {
    my $arg = standard_nr(shift) ;
    return $MSN{$arg} if defined $MSN{$arg} ;
    return "?" ;
}

# create from phone number an array of 5 string elements:
# number, name, street, pcode town, how found
sub nr2string {
    my $number = "???";
    my $arg = shift;
    my $country = $COUNTRY;
    my $town = $TOWN;
    if( $arg ) {
        # if provided we standardize the calling number
        $number = $arg;
        if ( $number =~ /^0031|^\+?31/ ) {
             $country = "31"; $number =~ s/^0031|^\+?31/0/;
        }
        if ( $number =~ /^0049|^\+?49/ ) {
             $country = "49"; $number =~ s/^0049|^\+?49/0/;
        }
	my $cnt = 9; if ( $country eq "49" ) { $cnt = 8 }
        if ($number =~ /^[1-9]{$cnt}/) {
             $number = "0$number";
        }
    }
    # look it up from the cache
    #my @anruf = split(/,/, number_cache(0, $number), 4);
    my @anruf = split(/,/, update_cache(0, $number), 4);
    my $pretext = "Cache found";
    if (not $anruf[0]) {       # New - ReverseLookup
        # not in the cache so try reverse lookup
        @anruf = split(/,/, reverse_lookup($country,$number), 4);
        #number_cache(1, "$anruf[0],$anruf[1],$anruf[2],$anruf[3]");
	for ( my $i=1; $i<4; $i++) { $anruf[$i]=capitalize($anruf[$i]) }
        update_cache(1, $anruf[0], "$anruf[0],$anruf[1],$anruf[2],$anruf[3]");
        $pretext = "Reverse Lookup";
    }
    return ($anruf[0],$anruf[1],$anruf[2],$anruf[3],$pretext);
}

sub monitor {
    if ( defined $opt_d and $opt_d>0 ) { return ; }
    my $timing = shift;
    my $text = shift;
    # my ($mday, $mon, $year) = (localtime(time()))[3,4,5]; $year += 1900;
    open (LOG, ">>$MONITORFILE");
    # printf LOG ("%d:%.2d:%.2d  %s,$year/$mon/$mday", $std, $min, $sec, $text);
    printf LOG ("%s  %s", $timing, $text);
    close (LOG);
}

sub logger {
    if ( defined $opt_d and $opt_d>0 ) { return ; }
    my $text = shift;
    my ($sec, $min, $hour, $mday, $mon) = (localtime(time()))[0,1,2,3,4];
    open LOG, ">>$LOGFILE";
    printf LOG ("%s %d %d:%.2d:%.2d  fbfcall: %s", (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon], $mday, $hour, $min, $sec, $text);
    close (LOG);
}

sub number_cache {
    # search
    if (shift == 0) {
	my $number = shift;
	my $nameadr = `/bin/grep \"^$number,\" $CACHFILE`;
	chop($nameadr);
	return($nameadr);
    }
    # write
    else {
	my $nameadr = shift;
	my @fields=split(/,/,$nameadr,4);
	if( $fields[1] ne "..." ) {
	    open CACHE, ">>$CACHFILE";
            my ($mday, $mon, $year) = (localtime(time()))[3,4,5]; $year += 1900;
	    printf CACHE ("$nameadr,$year/$mon/$mday");
	    close(CACHE);
	}
    }	
}

# the follwing subroutine can be used separately to check it
# hte URL used and search pattern is changed by the web provider
# at will, so check failure (I used etherreal to get the URL and pattern)

# use LWP::UserAgent;
sub reverse_lookup {
    my $country = shift;
    my $number = shift;
    if ( $country eq "49" ) { # Germany
	my $url = "http://www.dasoertliche.de/DB4Web/es/oetb2suche/home.htm?kw_invers=$number&main=Antwort&s=2";
        system("/usr/bin/wget -q --tries=1 --timeout=5 -O /tmp/reverse_lookup \"$url\"");
        my $nameadr = `grep \"</a><br>\" /tmp/reverse_lookup`;
	system("/bin/rm -f /tmp/reverse_lookup");
        if (index($nameadr, "<td ") != -1) {
	    $nameadr =~ s/^.*> //;		# delete all before
	    $nameadr =~ s/<\/td>.*//;	# delete all after (first?)
	    $nameadr =~ s/<\/a><br>/;/g;	# remove html-tags
	    return("$number,$nameadr");
        }
        # return("$number,...,...,...");
    }
    elsif ( $country eq "31" ) { # Holland
        my $rer=0;
        my $url="http://telefoongids.e2u.cc/zoeknummer.php?phonenumber=" . $number . "&maxrows=100&search=Zoeken";
        if ( $rer == 0 ) {
            my $ua = LWP::UserAgent->new;
            $ua->agent("Mozilla/8.0") ;
            my $req = HTTP::Request->new(GET => $url);
            $req->header('Accept' => 'text/html');
            # send request
            $res = $ua->request($req);
            # check outcome
            if ($res->is_success) {
                $_ = $res->content;
		if ( /<tr .*nbsp;<.td><td>([0-9]+)-([0-9]+)<.td><td>.nbsp;<.td><td>(.*)<.td><td>.nbsp;<.td><td>(.*)<.td><td>.nbsp;<.td><td>(.*)<.td><td>.nbsp;<.td><td>(.*)<.td>/ ){
                    my $tel_nr = $1.$2;
                    my $naam = $3;
                    my $straat = $4;
                    my $pcode = $5;
                    my $plaats = $6;
		    $naam =~ s/(.*), (.*)/$2 $1/;
		    $straat =~ s/,/-/g;
		    $pcode =~ s/ //;
                    return("$number,$naam,$straat,$pcode $plaats");
                }
                if ( /Geen vermeldingen gevonden/ ) {
                    # return ("$number,...,...,...";
                }
                if( defined $opt_d and $opt_d>0 ) { print $res->content ; }
            } else {
                if ( defined $opt_d and $opt_d>0 )
		    { print "ERROR, " . $res->status_line . "\n"; }
                # return("$number,...,...,...");
            }
	} else {
		logger "Reverse number lookup FAILURE, URL used: http://telefoongids.e2u.cc/zoeknummer.php?phonenumber=$number&maxrows=100&search=Zoeken";
	}
    }
    return("$number,...,...,...");
}

sub vdr_mesg {
    if ( defined $opt_d and $opt_d>0 ) { return ; }
    my @date = split(/ /,shift,2);
    my $number = shift;
    my $name = shift;
    my @timing = split(/:/,$date[1],3);
    my $town = shift;
    my $msn = shift;
    my $line = shift;
    $timing[0] = "$timing[0]h$timing[1]";
    my $text1 = "from ";
    my $text2 = "call";
    if( $line eq "call" ) {
        $text1 =~ s/from/call/; $text2 =~ s/call/from/;
    }
    if ($name eq "...") { $text1 = $text1 . "$number (unknown)"; }
    else {
	if ( $town ne "...") {
	    # delete pcode number if dutch pcode
	    $town =~ s/[0-9][0-9][0-9][0-9][a-zA-Z][a-zA-Z] //;
	    $text1 = $text1 . "$name, $town";
	    $text2 = "($number) call";
            if( $line eq "call" ) {
                $text2 =~ s/call/called/;
            }
	}
	else { $text1 = $text1 . "$name ($number)"; }
    }
    if ($msn ne "?") {
	if( $line eq "call" ) { $text2 = "$text2 from '$msn'"; }
        else { $text2 = "$text2 for '$msn'"; }
    }
    if ($line ne "?" and $line ne "call" ) { $text2 = "$text2 [$line]" ; }
    if( defined $VDR_SEND ) { # only active when defined
        system("$VDR_SEND -d$VDR_IP -p$VDR_PORT MESG \"$timing[0] $text1 $text2\" >/dev/null 2>&1");
    }
    if( defined $SLIMPPRGM ) { # only active when defined
	# seems that only if second line >40 chars display it starts scrolling
        # but resets the display time to 15 seconds
	if ( defined $opt_d and $opt_d>0 ) { printf("$SLIMPPRGM display \"$timing[0] $text2\" \"$text1\" $TIME2DISPLAY >/dev/null 2>&1\n"); }
        if ( length($text2) > 35 and length($text2) > length($text1) ) {
        system("$SLIMPPRGM display \"$timing[0] $text1\" \"$text2\" $TIME2DISPLAY >/dev/null 2>&1");
        } else {
        system("$SLIMPPRGM display \"$timing[0] $text2\" \"$text1\" $TIME2DISPLAY >/dev/null 2>&1");
        }
        system("/bin/rm -f status_header.html*"); # delete garbage
    }
    if ( defined $opt_d and $opt_d>0 ) { printf("VDR Send Message= $text1 $text2\n"); }
}

# Signal handlers

sub timeout {
    my $signame = shift;
    logger("fbfcall Timeout/SIG$signame received\n");
}

sub hup {
    my $signame = shift;
    my $elem;
    my ($sec, $min, $hour, $mday, $mon, $year) = (localtime(time()))[0,1,2,3,4,5];
    $year += 1900;
    logger("fbfcall on Hup/SIG$signame dumping collected phone numbers cache\n");
    if ( open FILE, ">$CACHFILE.new" ) {
	print FILE "# Created by fbfcall on $year/$mon/$mday $hour:$min:$sec\n";
	my @keys = keys %COLLECTED;
	foreach my $elem (@keys) { print FILE "$COLLECTED{$elem}" }
        close FILE;
        logger("fbfcall wrote collected phone numbers cache into $CACHFILE.new\n");
    }
}

sub terminate {
    my $signame = shift;
    logger("fbfcall ending, SIG$signame received\n");
    hup ($signame) ;
    exit;
}

# EOF
