#!/usr/bin/perl
#
#
#
use strict;
use Getopt::Std;
use Sys::Syslog;
use Benno;
no warnings 'utf8';

$main::VERSION = '2.10.0';

our(%opts);
getopts('dDehnvVc:E:H:i:p:P:R:s:u:',\%opts);

if ($opts{V}) { print "$main::VERSION\n"; exit; }

my %conf = Benno->config($opts{c}) if $opts{c};

my $delete          = $opts{d} || $conf{delete};
my $DEBUG           = $opts{D} || $conf{DEBUG};

my $emailregex      = $opts{E} || $conf{emailregex}   || '^.+\.eml$';
my $hostname        = $opts{H} || $conf{hostname};
my $inbox           = $opts{i} || $conf{inbox}        || '/srv/benno/inbox';
my $noverifycert    = $opts{n} || $conf{noverifycert};
my $password        = $opts{p} || $conf{password};
my $port            = $opts{P} || $conf{port}         || 21543;
my $runuser         = $opts{R} || $conf{runuser}      || 'benno';
my $username        = $opts{u} || $conf{username};
my $suffix          = $opts{s} || $conf{suffix};
my $errfile         = $opts{e} || $conf{errorfile};
my $verbose         = $opts{v};

my $path            = '/rest/inbox';

help_exit() if $opts{h};
help_exit('Hostname not set.') if ! $hostname;

Benno->run_as($runuser);
openlog('benno-send2rest','nowait,pid','mail');


my $uri = 'https://'.$hostname.':'.$port.$path;
print "Send to $uri\n" if $verbose;
my $RC = new Benno::REST::Client($uri,$username,$password,$noverifycert);


## READ FROM STDIN AND EXIT ####################################################
if ($inbox eq '--') {
    my $msg = "Read files from STDIN";
    syslog('INFO',$msg);
    print "$msg\n" if $verbose;

    eval {
        my $return = $RC->send('--',$DEBUG);
        syslog('INFO',"Email archived: $return");
        print "Email archived: $return\n" if $verbose;
    };
    if ($@) {
        my $err = $@;
        syslog('ERR',"Cannot send file: $err");
        print "Cannot send file: $err";
    } 
    closelog;
    exit;
}
## /READ FROM STDIN AND EXIT ###################################################


## READ FILES FROM DIRECTORY ###################################################
my $msg = "Read files from \"$inbox\"";
$msg .= ' and delete after sent'    if $delete;

syslog('INFO',$msg);
print "$msg\n" if $verbose;

# read directory and process files
opendir my $dh, $inbox or die "Cannot read directory \"$inbox\": $!";
my $return;
foreach my $filename (readdir $dh) {
    next if $filename =~ /^\./;
    next if $filename !~ /$emailregex/;
    chomp $filename;
    my $file = "$inbox/$filename";

    eval {
        $return = $RC->send($file,$DEBUG);
        syslog('INFO',"Email \"$filename\" archived: $return");
        print "Email \"$filename\" archived: $return\n" if $verbose;
        if ($suffix) {
            my $ufile = $file.".".$suffix;
            rename $file, $ufile or die "Cannot rename $file to $ufile: $!\n";
        }
    };
    if ($@) {
        my $err = $@;
        syslog('ERR',"Cannot send file \"$file\": $err");
        print "Cannot send file \"$file\": $err";
        if ($errfile) {
            my $errfile = $file.'.err';
            link $file, $errfile or warn "Cannot rename $filename to $errfile: $!\n";
            unlink $file;
        }
        # do not remove file
        next;
    }
    unlink $file if $delete;
    print "Delete $file from $inbox.\n" if ($verbose && $delete);
}
closedir $dh;
closelog;
## /READ FILES FROM DIRECTORY ##################################################



### SUBS ###
###
# read configuration from file
#
sub read_config
{
  my $configfile = shift;
  my %config;
  # _very_ simple config file parser
  #
  # Config format:   var = val
  #
  open CONF, "$configfile" or die "Cannot open config file $configfile. $!\n";
  foreach my $line (<CONF>) {
      next if $line =~ /^$/;
      next if $line =~ /^#/;
      chomp $line;
      my ($var,$val) = split(/=/, $line,2);
      # strip ws
      $var =~ s/\s//g;
      $val =~ s/^\s+//g;
      $val =~ s/\s+$//g;
      $config{$var} = $val;
  }
  close CONF;
  return %config;
}


### print help and exit
sub help_exit
{
    my $msg = shift;

    if ($msg) {
        print $msg,"\n\n";
    }

    print "Usage: $0 [-h] <-H <hostname> [<options>]\n";
    print "\n";
    print "     -c <configfile> configuration file\n";
    print "     -d              delete email after processing\n";
    print "     -H <hostname>   hostname of benno-import-rest server\n";
    print "     -P <port>       port (default: 21543)\n";
    print "\n";
    print "     -u <username>   username\n";
    print "     -p <password>   password\n";
    print "\n";
    print "     -e              rename upload file to .err on errors (default: leave unchanged)\n";
    print "     -s <extension>  append <extension> to uploaded file (default: leave unchanged)\n";
    print "     -i <importdir>  read eml-files from this dir\n";
    print "     -n              no verification of server certficate\n";
    print "     -E <emailregex> email name regex (default: \"^.+\.eml\")\n";
    print "     -R <username>   run as user (default: benno)\n";
    print "\n";
    print "     -V              print version\n";
    print "     -v              verbose\n";
    print "     -h              print this help\n";
    print "\n";
    
    exit 1;
}


### EOP ###
1;

package Benno::REST::Client;
use LWP::UserAgent;
use MIME::Base64;

sub new {
    my $class = shift;
    my ($uri,$username,$password,$noverifycert) = @_;

    my $UA;
    if ($noverifycert) {
        $UA = LWP::UserAgent->new(
               ssl_opts => {
                verify_hostname => 0, # will be removed in LWP::UserAgeng > 6.06
                SSL_verify_mode => 0, # LWP::UserAgent >= 6.05
                });
    }
    else {
        $UA = LWP::UserAgent->new();
    }

    my $self = {
        UA          => $UA,
        uri         => $uri,
        authstring  => encode_base64($username.':'.$password),

    };
    bless $self, $class;

    return $self;
}


sub send
{
    my ($self,$filename,$DEBUG) = @_;

    my $Response;
    {
        local $/ = undef;
        my $fh;
        if ($filename eq '--') {
            $fh = \*STDIN;
        }
        else {
            open $fh, $filename or die "Error read $filename: $!\n";
        }
        $Response = $self->{UA}->put(
            $self->{uri},  
            Authorization   => 'Basic '.$self->{authstring},
            Content         => <$fh>
        );
        close $fh;

        if ($DEBUG) {
            print "---- REQUEST DATA ----\n";
            $Response->request->dump;
            print "\n";
            print "---- REQUEST DATA ----\n";
        }
    }
    my $return;
    if ($Response->is_success) {
        $return = $Response->decoded_content;
        $return =~ s/\r//g;
        if ($DEBUG) {
            print "---- RETURN DATA ----\n";
            print "$return\n";
            print "---- RETURN DATA ----\n";
        }
        if ($return =~ /^OK\s(.+?)$/) {
            return $1;
        }
        else {
            die "Error decoding return value: $return";
        }
    }
    else {
        die 'ERROR '.$Response->status_line,"\n";
    }
}



### EOP ###
1;



package LWs::SingleInstance;

use strict;

use Fcntl ':flock';

#
# Exit program if more than one instance is runningg
#
INIT {
    if (tell(*main::DATA) == -1) {
        # __DATA__ handle not available
        print STDERR "$0 needs an __END__ literal at the end of the file.\n";
        exit 2;
    }
    elsif (!flock main::DATA, LOCK_EX | LOCK_NB) {
        use Sys::Syslog;
        openlog('benno-send2rest','nowait,pid','mail');
        # cannot lock __DATA__ "file"
        print STDERR "An instance of $0 is already running.\n" if -t;
        syslog('ERR',"An instance of $0 is already running.\n");
        exit 1;
    }
}

### EOP ###
1;



__END__

