#!/usr/bin/perl
#
#
#
use strict;
use Getopt::Std;
use LWP::UserAgent;
use JSON;
no warnings 'utf8';


my %opts;
getopts('hInvDQrc:e:f:L:q:s:H:P:R:',\%opts);

help_exit() if $opts{h};

my $container = $opts{c} || 'BennoContainer';
my $secret    = $opts{s} || fetchSecret('/etc/benno/rest.secret','/etc/benno/benno.xml');
my $query     = $opts{q};
my $filter    = $opts{f};
my $host      = $opts{H} || 'localhost';
my $port      = $opts{P} || 21080;
my $first     = $opts{F} || 0;
my $limit     = $opts{L} || 20;
my $verbose   = $opts{v};
my $quiet     = $opts{Q};
my $reporturl = $opts{R} || 'https://www.benno-mailarchiv.de/report';
my $report    = $opts{r};

$verbose += 2 if $opts{D} ;

help_exit() unless $secret;

if (!$opts{I}) {
    # wait random time (0-200s) to send request
    my $wait = rand() * 1000; $wait = $wait % 200;
    sleep $wait;
}

my $infoquery = $query || 'NOT HEADER-X-SPAM-FLAG:YES ';
my $filterquery = $filter || 'SortableDate:['.ts2date(time-90*86400).
                              ' TO '.ts2date(time).']';



my $proto = 'http';
my $showmails = 1 unless $quiet;
my $params = { 'archive'       => $container,
               'showmails'     => $showmails,
               'mincount'      => $limit,
               'query'         => $infoquery,
               'filterQuery'   => $filterquery,
             };
my $path  = '/stats/';

my $uri = $proto.'://'.'benno2:'.$secret.'@'.$host.':'.$port.$path;
my $UA = LWP::UserAgent->new;

my $Rest = $UA->post($uri,$params);

my $repdata;
if ($Rest ->is_success) {
    $repdata = $Rest->decoded_content;
}
else {
    print STDERR "Response status: ",$Rest->status_line,"\n";
    print STDERR $Rest->content,"\n";
    exit 1;
}

# Response returned JSON data
my $JSON = JSON->new->allow_nonref;
my $j_data;
eval {
    $j_data = $JSON->decode($repdata);
};
if ($@) {
    print STDERR "Return value not JSON.\n";
    print STDERR "  $@\n" if $verbose;
    exit;
}

my $send_data;
$j_data->{anonymized} = 0;
if ($verbose) {
    $send_data = $JSON->encode($j_data);
}
else {
    $send_data = $JSON->encode(anonymize($j_data));
}

print "\n$send_data\n";
if (!$report) {
    exit 0;
}

my $EXT = LWP::UserAgent->new;
$EXT->env_proxy();
my $BennoReport = $EXT->post($reporturl,{'restinfo' => $send_data});
if (!$BennoReport->is_success) {
    print STDERR "Report post failure: ",$BennoReport->status_line,"\n";
    print STDERR $Rest->content,"\n";
    exit 1;
}




### SUBS ###
### print help and exit
sub help_exit
{
    print "Usage: $0 [-h] [-V] -s <secret> [-H <hostname>] [-c <container>] [-P <port>] [-q <query>] [-r]\n";
    print "    -c '<container>'    archive container\n";
    print "    -D                  debug mode\n";
    print "    -f '<lucene query>' lucene filter string or file with filter\n";
    print "    -H <hostname>       (localhost)\n";
    print "    -I                  immediate request (don't sleep random)\n";
    print "    -L '<num>'          limit response list to <num> mails\n";
    print "    -P <port>           (21080)\n";
    print "    -q '<lucene query>' lucene query string or file with filter\n";
    print "    -Q                  quiet mode (suppress info messages)\n";
    print "    -r                  report (send) resultlist\n";
    print "    -R '<url>'          report url (default: https://www.benno-mailarchiv.de/report\n";
    print "    -s <secret>         shared secret\n";
    print "                        (search header as \"HEADER-<HEADER-NAME>\")\n";
    print "    -v                  verbose\n";
    print "\n";
    
    exit 1;
}

### print and format debug messages
sub verbose
{
    my ($level,$string) = @_;
    return if $quiet;
    if ($verbose >= $level) {
        print STDERR $string,"\n";
    }   
}


### fetch password from config file
sub fetchSecret
{
    my $sfile    = shift;
    my $bennoxml = shift;
    my $secret;

    if (open SF, $sfile) {
        $secret = <SF>;
        chomp $secret;
        close SF;
        return $secret; 
    }

    open XMLFILE, $bennoxml;
    foreach my $line (<XMLFILE>) {
        chomp $line;
        ($secret) = $line =~ m!<sharedSecret>(.+)</sharedSecret>!;
        last if $secret;
    }
    return $secret;
}


### read first line from file
sub read_first_line
{
    my $filename = shift;

    if (!open FILE, $filename) {
        print STDERR "Cannot open file $filename. $!\n";
        exit 2;
    }
    my $line = <FILE>;
    chomp $line;

    return $line;
}


### anonymize
sub anonymize
{
    my ($data) = @_;

    my $ccount = 1;
    foreach my $entry (@{$data->{containerList}}) {
        next if $entry->{name} eq 'SYSDATA';
        $entry->{name} = $ccount;
        $ccount++;
    }

    my $mcount = 1;
    foreach my $entry (@{$data->{addressList}}) {
        $entry->{SenderAddress} = $mcount;
        $mcount++;
    }
    $data->{'anonymized'} = 1;

    return $data;
}


### ts2date
sub ts2date
{
    my ($ts) = @_;

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($ts);
    #                          0-11,+1900,0-6  ,0-366,SZ=(+)
    #                                    ,So-Sa,0-366,WZ=0,NA=(-)

    $year += 1900;
    $mon  += 1; $mon = sprintf("%02d",$mon);
    $mday = sprintf("%02d",$mday);
    $hour = sprintf("%02d",$hour);
    $min  = sprintf("%02d",$min);
    $sec  = sprintf("%02d",$sec);

    return $year.$mon.$mday.$hour.$min;
}
