#!/usr/bin/perl
#
# Script to talk to the web api of sendregning.no.
#
# Author: Petter Reinholdtsen
# License: GNU General Public License
# Changed to use WS with Basic authentication instead of SWS Kagee/Jonp  2017-12-30
#
# To use it, create a file ~/.swsconfig with this content:
#  $username = 'user@domain.no';
#  $password = 'secret';
# 2012-10-15 JESO - increased timeout from 10 to 20 

use strict;
use warnings;

require LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use LWP::ConnCache;
use Getopt::Std;

use vars qw($username $password);

#$username = "foo@bar.no";
#$passowrd = "secret";

if ( -f $ENV{HOME} . "/.swsconfig" ) {
    # Load $username and $password
    require $ENV{HOME} . "/.swsconfig" ;
}
unless ($username && $password) {
    print <<EOF;
error: Missing ~/.swsconfig or its content.
error: It is required to set username and password.
error: It should look something like this:
error:   \$username = 'foo\@bar.no'; \$password = 'secret';
EOF
    exit 1;
}

my $url = 'https://www.sendregning.no/sws/j_security_check';
my $butlerurl = 'https://www.sendregning.no/ws/butler.do';

my %opts;
getopts("a:dnt:u:x:X:", \%opts) || usage();

my $istesting = $opts{n};

$username = $opts{u} || $username;

my $action = $opts{a} || "select";
my $type = $opts{t} || "invoice";

print "A: $action T: $type\n" if $opts{d};

my $ua = sws_login($username, $password);

my $success;
if ("select" eq $action && "constants" eq $type) {
    $success = sws_get($ua, $action, $type);
} else {
    my $xmlref;
    if ($opts{X}) {
        $xmlref = [ $opts{X}, "input.xml",
                    Content_Type => 'text/xml',
                    ];
    } elsif ($opts{x}) {
        $xmlref = [ undef, "input.xml",
                    Content_Type => 'text/xml',
                    Content => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" .
                    $opts{x},
                    ];
    } else {
        $xmlref =
            [ undef, "input.xml",
              Content_Type => 'text/xml',
              Content =>
              "<?xml version=\"1.0\" encoding=\"UTF-8\"?><select>LAST 500</select>"
              ];

    }
    $success = sws_post($ua, $action, $type, $xmlref );
}

exit ($success ? 0 : 1);

sub usage {
    print <<EOF;
$0 [options]
  -n             enable test mode when talking to sendregning.no
  -d             enable debugging info
  -a action
  -t type
  -x xml-code
  -X xml-file
  -u username

The possible values for action and type as well the XML format is
documented by sendregning.no.
EOF
    exit 0;
}

sub sws_login {
    my ($username, $password) = @_;

    my $ua = LWP::UserAgent->new;
    #$ua->timeout(20);
    $ua->timeout(600);
    $ua->env_proxy;
    $ua->agent("NUUG-fakturascripter/0.1 ");

    # Allow redirects for push URLs.  This is required to get the sws
    # operations working.
    push @{ $ua->requests_redirectable }, 'POST';

    # Enable keepalive to speed up the communication.
    $ua->conn_cache(LWP::ConnCache->new());

    $ua->cookie_jar({}); # Enable cookies to store the session ID

    # First get the login page
    print $butlerurl if $opts{d};

    $ua->credentials( 'www.sendregning.no:443', 'SendRegning', $username, $password);

    my $response = $ua->get($butlerurl);

    if ($response->code == 401) {
        print "[ERROR] Feil brukernavn eller passord (401 Unauthorized)";
        exit 1;
    } elsif ($response->code != 400) {
        print "[ERROR] Unexpected return", $response->status_line, "\n";
        print $response->decoded_content;
        exit 2;
    }
    return $ua;
}

sub is_testurl {
    my $url = shift;
    $url .= "&test=true" if ($istesting);
    return $url;
}

sub sws_get {
    my ($ua, $action, $type) = @_;
    my $testurl = "$butlerurl?action=select&type=constant";
    $testurl = is_testurl($testurl);
    my $response = $ua->get($testurl);
    if ($response->is_success) {
        print $response->as_string;
        return 1;
    } else {
        print $response->as_string if $opts{d};
        return 0;
    }
}

sub sws_post {
    my ($ua, $action, $type, $xmlref) = @_;
    # This code do not work yet!
    # This is the error:
    #    The request sent by the client was syntactically incorrect
    #    (Parameter xml can't be omitted).
    my $testurl = "$butlerurl?action=$action&type=$type";
    $testurl = is_testurl($testurl);
    my $req = POST $testurl, Content_Type => 'form-data',
                             Content => [ "xml" => $xmlref ] ;

    print $req->as_string if $opts{d};

    my $response = $ua->request($req);
    if ($response->is_success) {
        if ($response->header("Content-Type") =~ m%^application/pdf;.*%) {
            print STDERR "Got PDF, saving as output.pdf\n";
            open(PDF, ">", "output.pdf") || die "Unable to write to output.pdf";
            print PDF $response->content;
            close(PDF);
        } else {
            print "HTTP post returned success\n";
            print $response->as_string;
        }
        return 1;
    } else {
        print $response->as_string if $opts{d};
        print STDERR "HTTP post returned failure\n";
        print STDERR $response->status_line . "\n";
        return 0;
    }
}
