#!/usr/bin/perl
# ATSlog version 2.1.1 build 664 www.atslog.com
# Copyright (C) 2003 Denis CyxoB www.yamiyam.dp.ua
#

use Sys::Syslog qw(:DEFAULT setlogsock);# logging error messages to syslog
use DBI;# DataBase common class
use POSIX qw(locale_h); # For language settings
use POSIX 'setsid'; # used in daemonize

$prefix="/usr/local";
$config_file="${prefix}/etc/atslog.conf";
if(@ARGV[0] eq "--fastwrite"){
	$fastwrite=1;
} else{
	$fastwrite=0;
}

open(IN,$config_file) || die print("Can't open config file $config_file.\n");
while(<IN>) {
	next if /^#/;
	chomp;
	($key,$val) = ( /([^=]+)=(.*)/ );
	$key = lc($key);
	$vars{$key} = $val;
}
close(IN);

$langfileprefix=$vars{sharedir}."/".$vars{langdir}."/";
$langfile=$langfileprefix.setlocale(LC_CTYPE);

if ( ! -f $langfile){
	$langfile=$langfileprefix."en_US";
}

open(LN,$langfile) || die print("Can't open language file $langfile.\n");
while(<LN>) {
	next if /^#/;
	chomp;
	($key,$val) = ( /([^=]+)=\"(.*)\"/ );
	$key = lc($key);
	$vars{$key} = $val;
}
close(LN);

# Закоментрированное оставляю для отладки
#$stringnumber=0;
$callsCount=0;
$toexit=0;

# Разберёмся с уровнем для системного журнала
if($vars{syslogfacility}){
	$vars{syslogfacility} =~ /(.*)\.(.*)/;
	$sFas1 = $1;
	$sFas2 = $2;
}

# Опишем основные функции

# Функция выводит сообщения об ошибках в системный журнал и в STDERR
sub echoerrors(){
	if($vars{syslogfacility}){
		syslog("$sFas2", "$ERRORMESSAGE");
	} 
	warn ("$ERRORMESSAGE\n");
	$toexit=1;
}

# ampto24 with russian and english language support
sub AmPmTo24(){
	my $return24=$_[0]; # last choice, if no symbols found
	my $hour=$_[0];
	my $AmPm=$_[1];
	if ($AmPm eq 'PM' || $AmPm eq '▐▐'){
		if($hour < 12){
			$return24=$hour+12;
		}elsif($hour == 12){
			$return24=12;
		}
	}elsif($AmPm eq 'AM' || $AmPm eq '└▐'){
		if($hour < 12){
			$return24=$hour;
		}elsif($hour == 12){
			$return24=0;
		}
	}
	return $return24;
}

# Let`s go!
if($vars{syslogfacility}){
	setlogsock('unix'); # syslogd socket type
	openlog("atslogdb", 'pid, ndelay, cons', "$sFas1");#Откроем сокет на syslogd
}
if($vars{sqltype}  =~ /PostgreSQL/i){
	$sqltype=Pg;
}else{
	$sqltype=mysql;
}
$host="";                           
if($vars{sqlhost} ne "localhost"){
	$host = ";host=".$vars{sqlhost};
}

open(DATA,"$vars{libdir}/modules.lst") || die print("Can open module list");
$libname="$vars{libdir}/".getLibName($vars{model});
close(DATA);


# load library
if ( (-e $libname) && (-r $libname) ) 
{
	require $libname;
}else{
	$ERRORMESSAGE="$vars{msg31}";
	echoerrors();
	if($vars{syslogfacility}){	
		closelog();
	}	
	exit $toexit;
}

if(!connecttodb()){
	$toexit=1;
	exit $toexit;
}
# parsing calls
if(!$fastwrite){
	# pass stdin to the library
	open(PBX_DATA,"-");
	if( connecttodb() ){
		parsecurcalls();
	}
}
else {
	&daemonize;
	$pid = open(PBX_DATA, "-|");
	if ($pid) {   # parent
		if($vars{debug} =~ /yes/i){
			open(STDOUT, ">>$vars{logdir}/$vars{notwritelog}") || die "Can't redirect stdout";
			select(STDOUT); $| = 1;     # make unbuffered
		}
		if( connecttodb() ){
			parsecurcalls();
			if(!close(PBX_DATA))  {
				# warn "atslogd exited $?"
				$ERRORMESSAGE="\n$vars{atslogd} error code: $?";
				echoerrors();
			};
		}
	} else {      # child
		if($vars{port} !~ /r?tcp\:/i){
			$vars{port}='/dev/'.$vars{port};
		}
		# correcting port variable
		exec("$vars{bindir}/$vars{atslogd} $vars{atslogd_flags} -P $vars{pidfile} -o -f $vars{stopbits} -p $vars{parity} -c $vars{charsize} -s $vars{speed} -D $vars{logdir} -F $vars{callslogfile} -L $vars{logdir}/$vars{startlogfile} $vars{port}")
		|| die "can't exec program: $!";
		# NOTREACHED
	}
}

if($callsCount == 0){                                                          
	$ERRORMESSAGE="\n$vars{msg32}";
	echoerrors();
}
$dbh->disconnect;
if($vars{syslogfacility}){
	closelog();
}    
exit $toexit;

sub WriteRecord{
	my ($time_of_call, $fwd, $int, $co, $way, $number, $duration) = @_ ;
	my $query = "INSERT INTO calls ( timeofcall, forwarded, internally, co, way, number, duration ) VALUES ( ?, ?, ?, ?, ?, ?, ?)";
	my $sth = $dbh->prepare($query); 	
	$sth->execute($time_of_call, $fwd, $int, $co, $way, $number, $duration);
	if($sth->err){ # try to reconnect and send the query again
		$ERRORMESSAGE="\nError on sth->execute: ".$sth->errstr().", reconnecting\n";
		echoerrors();
		if(connecttodb()){
			my $sth = $dbh->prepare($query);
			$sth->execute($time_of_call, $fwd, $int, $co, $way, $number, $duration);
			if(!$sth->err) { # success
				return 0;
			}
		}
		# error on SQL query. We need to record sql server message to 
		# the syslog and failed record to the special file
		open(SQLFAIL,">>$vars{logdir}/sqlfail.log");
		$ERRORMESSAGE="\nError on sth->execute: ".$sth->errstr()."\n";
		print SQLFAIL $str;
		echoerrors();
		close(SQLFAIL); # we dont want to keep this file open
		return -1;
	}
	return 0;
}

sub connecttodb {
	if ($dbh = DBI->connect("dbi:$sqltype:dbname=$vars{sqldatabase}$host",$vars{sqlmasteruser},$vars{sqlmaspasswd},{PrintError=>0})){
		if($vars{sqltype} =~ /MySQL/i){
			$dbh->{mysql_auto_reconnect} = 1;
		}
		return 1;
	}else{
		$ERRORMESSAGE="$vars{msg33}:".$DBI::errstr;
		echoerrors();
		return 0;
	}
}

sub getLibName{
	my $model_name = $_[0];
	while ($string =<DATA>) {
		my @libarray=split(/:/,$string);
		my $libname=@libarray[0];
		my @models=split(/,/,@libarray[1]);
		if (grep (/^${model_name}$/i, @models)) {return $libname;}
	}
	return 0;
}

sub daemonize {
	chdir '/'		or die "Can't chdir to /: $!";
	open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
	open STDOUT, '>/dev/null'
	or die "Can't write to /dev/null: $!";
	defined(my $pid = fork)	or die "Can't fork: $!";
	exit if $pid;
	setsid			or die "Can't start a new session: $!";
	open STDERR, '>&STDOUT'	or die "Can't dup stdout: $!";
}
