#!/usr/bin/perl

use warnings;
use strict;

use IO::Socket;	#to get IP address
use File::Find;
#use File::Path qw(make_path);
use File::Path qw(mkpath);

# IMPORTANT:
# After loading the debconf module DO NOT output anything to STDOUT
# use STDERR instead.
use Debconf::Client::ConfModule ':all';

our $IDP_CONF_BASE      = "/etc/shibboleth-identity-provider";
our $IDP_CONF_SKEL_BASE = "/usr/share/shibboleth-identity-provider/skel";

our $IDP_CONF_SKEL = "$IDP_CONF_SKEL_BASE/idp-conf";
our $CRED_DIR     = "$IDP_CONF_BASE/credentials";
our $CONF_DIR     = "$IDP_CONF_BASE/conf";
our $CRT_NAME      = "$CRED_DIR/idp.crt";
our $KEY_NAME      = "$CRED_DIR/idp.key";

our $TOMCAT_SKEL = "$IDP_CONF_SKEL_BASE/tomcat-conf";
our $TOMCAT_BASE = "$IDP_CONF_BASE/tomcat-conf";

my $server_fqdn = (get('shibboleth-identity-provider/server_fqdn'))[1];
my $server_path = (get('shibboleth-identity-provider/server_path'))[1];
my $server_scop = (get('shibboleth-identity-provider/server_scop'))[1];
my $server_ladr = (get('shibboleth-identity-provider/server_ladr'))[1];
my $server_jvmr = (get('shibboleth-identity-provider/server_jvmr'))[1];
my $shib_url    = $server_path . "/shibboleth";
my $entity_id   = "https://" . $server_fqdn . $shib_url;
# create the directory to hold the credentials...
if (!-d $CRED_DIR) {
  mkpath($CRED_DIR);
}

# check whether the cert files exist
if (!-e $CRT_NAME && !-e $KEY_NAME ) {
  print STDERR "No credentials found! \n";
  print STDERR "Add credentials (key and certificate) to \n$CRED_DIR \nand execute shibboleth-identity-provider-configure again.\n";
  print STDERR "Or create credentials with \n cert-generator -hostname $server_fqdn \n  -url $shib_url \n  -certfile $CRT_NAME \n  -keyfile  $KEY_NAME ";
  die "No credentials.", "\n";
} else {
  print STDERR "Credentials exist.", "\n";
}

our %replacement;
$replacement{'IDP_ENTITY_ID'}   = $entity_id;
$replacement{'IDP_SCOPE'}       = $server_scop;
$replacement{'IDP_HOSTNAME'}    = $server_fqdn;
$replacement{'IDP_PATH'}        = $server_path;
$replacement{'IDP_LADR'}        = $server_ladr;
$replacement{'IDP_JVMR'}        = $server_jvmr;
$replacement{'IDP_CONF'}        = $IDP_CONF_BASE;
$replacement{'IDP_LOG'}         = "/var/log/shibboleth-identity-provider";
$replacement{'IDP_CERTIFICATE'} = "";

my $fh;
open($fh, "<", $CRT_NAME);
while (<$fh>) {
  next if (/^-----(BEGIN|END)/);
  $replacement{'IDP_CERTIFICATE'} .= $_;
}
close($fh);

print STDERR "processing idp conf...";
find(sub { copy_filter($IDP_CONF_SKEL, $CONF_DIR); }, @{ [$IDP_CONF_SKEL] });
print STDERR "done", "\n";
print STDERR "processing tomcat conf...";
find(sub { copy_filter_overwrite($TOMCAT_SKEL, $TOMCAT_BASE); }, @{ [$TOMCAT_SKEL] });
print STDERR "done", "\n";

sub copy_filter {
  -d && return;    # ignore directories
  my ($src_base, $dst_base) = @_;
  my $src      = $File::Find::name;
  my $rel_path = File::Spec->abs2rel($src, $src_base);
  my $dst      = File::Spec->rel2abs($rel_path, $dst_base);
  #print STDERR $src, " -> ", $dst, "\n";
  my $dst_dir = (File::Spec->splitpath($dst))[1];

  if (!-d $dst_dir) {
    mkpath($dst_dir);
  }
  if (-e $dst) {
    if( $dst =~ /\.properties$/ 
        || (index($dst, "attribute-resolver") != -1) 
        || (index($dst, "attribute-filter") != -1) 
        || (index($dst, "relying-party") != -1) 
        || (index($dst, "metadata-providers") != -1)){
      print STDERR $dst, " already exists. ";
      $dst .= ".dpkg-new";
      print STDERR "Using ", $dst, " instead.\n";
    } else {
      print STDERR $dst, " already exists. ";
      my $dst_old = $dst.".dpkg-old";
      if(-e $dst_old) {
	  unlink($dst_old);
      }
      rename($dst, $dst_old);
      print STDERR "Saved old version in ", $dst_old, ".\n";    
    }
  }
  my ($in, $out);
  open($in,  "<", $src);
  open($out, ">", $dst);
  while (<$in>) {
    # remove the 8443 port from the hostname
    #s/\$:8443/\$/g;
    s{/idp/}{\$IDP_PATH\$/}g;
    while (/\$([A-Z\_]+)\$/) {
      my $tok = $1;
      if (!defined $replacement{$tok}) {
        die "replacement for ",$tok, " not defined\n";
      }
      #print STDERR $tok, " => ", $replacement{$tok}, "\n";
      s/\$\Q$tok\E\$/$replacement{$tok}/g;
    }
    print $out $_;
  }
  close $in;
  close $out;
} ## end sub copy_filter

sub copy_filter_overwrite {
  -d && return;    # ignore directories
  my ($src_base, $dst_base) = @_;
  my $src      = $File::Find::name;
  my $rel_path = File::Spec->abs2rel($src, $src_base);
  my $dst      = File::Spec->rel2abs($rel_path, $dst_base);
  #print STDERR $src, " -> ", $dst, "\n";
  my $dst_dir = (File::Spec->splitpath($dst))[1];

  if (!-d $dst_dir) {
    mkpath($dst_dir);
  }
  if (-e $dst) {
    print STDERR $dst, " already exists. ";
	my $dst_old = $dst.".dpkg-old";
    if(-e $dst_old) {
	  unlink($dst_old);
	}
	rename($dst, $dst_old);
    print STDERR "Saved old version in ", $dst_old, ".\n";
  }
  my ($in, $out);
  open($in,  "<", $src);
  open($out, ">", $dst);
  while (<$in>) {
    # remove the 8443 port from the hostname
    #s/\$:8443/\$/g;
    s{/idp/}{\$IDP_PATH\$/}g;
    while (/\$([A-Z\_]+)\$/) {
      my $tok = $1;
      if (!defined $replacement{$tok}) {
        die "replacement for ",$tok, " not defined\n";
      }
      #print STDERR $tok, " => ", $replacement{$tok}, "\n";
      s/\$\Q$tok\E\$/$replacement{$tok}/g;
    }
    print $out $_;
  }
  close $in;
  close $out;
} ## end sub copy_filter
