#!/usr/bin/perl -w
#
#  LMS version 1.11-git
#
#  Copyright (C) 2001-2015 LMS Developers
#
#  Please, see the doc/AUTHORS for more information about authors!
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License Version 2 as
#  published by the Free Software Foundation.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.
#
#  $Id$

use strict;
use DBI;
use Config::IniFiles;
use Getopt::Long;
use vars qw($configfile $quiet $help $version);

my $_version = '1.11-git';

my %options = (
	"--config-file|C=s"	=>	\$configfile,
	"--quiet|q"		=>	\$quiet,
	"--help|h"		=>	\$help,
	"--version|v"		=>	\$version,
);

Getopt::Long::config("no_ignore_case");
GetOptions(%options);

if($help)
{
	print STDERR <<EOF;
lms-smstools, version $_version
(C) 2001-2015 LMS Developers

-C, --config-file=/etc/lms/lms.ini	alternate config file (default: /etc/lms/lms.ini);
-h, --help			print this help and exit;
-v, --version			print version info and exit;
-q, --quiet			suppress any output, except errors;

EOF
	exit 0;
}

if($version)
{
	print STDERR <<EOF;
lms-smstools, version $_version
(C) 2001-2015 LMS Developers

EOF
	exit 0;
}

if(!$configfile)
{
	$configfile = "/etc/lms/lms.ini";
}

if(!$quiet)
{
	print STDOUT "lms-smstools, version $_version\n";
	print STDOUT "(C) Copyright 2001-2015 LMS Developers\n";
	print STDOUT "Using file $configfile as config.\n";
}

if(! -r $configfile)
{
	print STDERR "Fatal error: Unable to read configuration file $configfile, exiting.\n";
	exit 1;
}

my $ini = new Config::IniFiles -file => $configfile;
print @Config::IniFiles::errors;

my $dbtype = $ini->val('database', 'type') || 'mysql';
my $dbhost = $ini->val('database', 'host') || 'localhost';
my $dbuser = $ini->val('database', 'user') || 'root';
my $dbpasswd = $ini->val('database', 'password') || '';
my $dbname = $ini->val('database', 'database') || 'lms';

# Set 'sent' and 'failed' options in smsd config
# Also 'keep_filename' must be set to 'yes'
my $sent_dir = $ini->val('smstools', 'sent_dir') || '/var/spool/sms/sent';
my $failed_dir = $ini->val('smstools', 'failed_dir') || '/var/spool/sms/failed';
my $incoming_dir = $ini->val('smstools', 'incoming_dir') || '/var/spool/sms/incoming';
my $failed_prefix = $ini->val('smstools', 'failed_prefix') || 'ERR';

if(! -r $sent_dir)
{
	print STDERR "Fatal error: unable to read sent_dir: $sent_dir, exiting!\n";
	exit 1;
}
if(! -r $failed_dir)
{
	print STDERR "Fatal error: unable to read failed_dir: $failed_dir, exiting!\n";
	exit 1;
}

my $dbase;
my $utsfmt;

if($dbtype =~ /mysql/)
{
	$dbase = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
	$dbase->do("SET NAMES utf8");
	$utsfmt = "UNIX_TIMESTAMP()";
}
elsif($dbtype eq "postgres")
{
	$dbase = DBI->connect("DBI:Pg:dbname=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
	$utsfmt = "EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))";
}
else
{
	print STDERR "Fatal error: unsupported database type: $dbtype, exiting.\n";
	exit 1;
}

my @files;
my $dbq = $dbase->prepare("UPDATE messageitems
	SET status = ?, lastdate = $utsfmt, error = ?, externalmsgid = ?
	WHERE messageid = ? AND destination = ? AND status = 1");

# sent
opendir(DIR, $sent_dir);
@files = grep(/^lms-[0-9-]+$/, readdir(DIR));
closedir(DIR);
foreach my $file (@files)
{
	$file =~ /^lms-([0-9]+)-([0-9]+)$/;
	my $id=$1;
	my $dest=$2;
	$dest=~s/^48//;
	my $filename = $sent_dir . '/' . $file;

	print "[sms sent] $file\n" if not $quiet;
	open(FILE,$sent_dir.'/'.$file);
	my $message_id=0;
	while (<FILE>)
	{
		if (/^Message_id: ([0-9]+)$/)
		{
			$message_id=$1;
		}
	}
	close FILE;

	$dbq->execute(2, undef, $message_id, $id, $dest);

	if ($dbq->rows)
	{
		unlink($filename) or print STDERR "Unable to delete file $filename\n";
	}
}

#  delivered/undelivered
$dbq = $dbase->prepare("UPDATE messageitems
	SET status = ?, lastdate = $utsfmt, error = ?
	WHERE externalmsgid = ?");

opendir(DIR, $incoming_dir);
@files = grep(/^[^\.]/,readdir(DIR));
closedir(DIR);
foreach my $file (@files)
{
	open(FILE,$incoming_dir.'/'.$file);
	my $message_id=0;
	my $error_code=0;
	my $error='';
	while (<FILE>)
	{
		if (/^Message_id: ([0-9]+)$/)
		{
			$message_id=$1;
		}
		elsif (/^status: ([0-9]+),[a-z]+,([a-z\ ]+)$/i)
		{
			$error_code=$1;
			$error=$2;
		}
	}
	close FILE;
	if ($message_id)
	{
		my $status=5;
		if ($error_code) { $status=3; }
		$dbq->execute($status, $error, $message_id);
		if ($dbq->rows)
		{
			if ($status==5)
			{
				print "[sms delivered] $file\n" if not $quiet;
			}
			else
			{
				print "[sms undelivered with '$error'] $file\n" if not $quiet;
			}
			my $filename=$incoming_dir.'/'.$file;
			unlink($filename) or print STDERR "Unable to delete file $filename\n";
		}
	}
}

# failed
opendir(DIR, $failed_dir);
@files = grep(/^$failed_prefix\.lms-[0-9-]+$/, readdir(DIR));
closedir(DIR);
foreach my $file (@files)
{
	print "[sms failed] $file\n" if not $quiet;
	
	$dbq->execute(3, 'Sending failed', $1, $2);
	
	if ($dbq->rows)
	{
		my $filename = $failed_dir . '/' . $file;
		unlink($filename) or print STDERR "Unable to delete file $filename\n";
	}
}

$dbq->finish();
$dbase->disconnect();
