#! /usr/bin/env perl

use warnings;
use strict;

use LWP::Simple; # apt install libwww-perl

# Must be passed full path to config file
#
# This is a simple script to use the postrun. To enable it, store it in the same directory as sysinf-client, then add the following
# to your configuration file
# postRunScript:
#   'script name': postrunscript.pl
#
# you will also need to add the some additional values to the above
#
# Script is designed to download an executable from some web server defined in $configuration{'postRunScript'}{'URL'}
# It will first download a checksum file from there. If that checksum is different from the one in this directory, it will 
# then download the executable  and run it.
# 
# values to look for in the configuration file:
# $configuration{'postRunScript'}{'URL'};
# $configuration{'postRunScript'}{'checksum'};
# $configuration{'postRunScript'}{'update script'};
#
# The YAML equivilent is
# postRunScript:
#   'script name': postrunscript.pl
#    URL: https://example.com/
#    checksum: sysinfo_update.cksum
#    'update script': sysinfo_update
#
# this script will try to download https://example.com/sysinfo_update.cksum. If it exists it will compare the contents
# to sysinfo_update.cksum in the directory this script is in. If they are different (or there is no file in the script directory)
# the contents will be written, then https://example.com/sysinfo_update will be downloaded. sysinfo_update will be changed to mod
# 0500, then executed the file
#
# NOTE: the checksum file doesn't really need a checksum (no checking is made). It just have different contents than what is 
# on disk


# find our location and use it for searching for libraries
BEGIN {
   use FindBin;
   use File::Spec;
   use lib File::Spec->catdir($FindBin::Bin);
   eval( 'use YAML::Tiny;' );
   eval( 'use Data::Dumper;' );
}

# contains the directory our script is in
my $scriptDir = File::Spec->catdir($FindBin::Bin);
$scriptDir .= '/' unless substr( $scriptDir, -1 ) eq '/';

#######################################################
#
# loadConfigurationFile($confFile)
#
# I just wrote is simple instead of using the library since it just does a YAML read
#
# Parameters:
#    $fileName - name of file to look for
# Returns
# reference to hash of configuration information
#
#######################################################

sub loadConfigurationFile {   
   my ( $fileName ) = @_;
   my $yaml = YAML::Tiny->read( $fileName );
   return $yaml->[0];
   die "Can not find $fileName\n";
}

#######################################################
# getWriteFile
# 
# Probably doesn't even need to be a sub it is so simple. Download $filename from $url, 
# and store it in $dir/$filename
#
# Parameters:
#   $dir - the local directory to store the downloaded file
#   $url - the URL (withou the file name) to download from
#   $filename - The name of the file, bot at URL and stored in $dir
#
#######################################################
sub getWriteFile {
   my ($dir, $url, $filename) = @_;
   return getstore("$url$filename", "$dir$filename");
}

### Main ###
# get the config file name from the command line
my $configFile = $ARGV[0];
die "Usage: $0 configFileName\n" unless $configFile;
# load the configuration file
my %configuration = %{ &loadConfigurationFile( $configFile) };

die "Configuration does not contain postRunScript URL\n" unless defined $configuration{'postRunScript'}{'URL'};

# get the values we need
my $URL = $configuration{'postRunScript'}{'URL'};
my $checksum = $configuration{'postRunScript'}{'checksum'};
my $update = $configuration{'postRunScript'}{'update script'};

# check for a current checksum file and get the value if it exists (one line only)
my $currentChecksum = '';
if ( -f "$scriptDir$checksum" ) {
   open CK, "<$scriptDir$checksum" or warn "could not read $scriptDir$checksum: $!\n";
   $currentChecksum = <CK>;
   close CK;
}

# download checksum from URL, storing in $data
my $data = get( $URL . $checksum );
if ( $data && $data ne $currentChecksum ) { # checksums different, so we have to do something
   # grab it again, but save it this time
   my $response = getstore( "$URL$checksum", "$scriptDir$checksum" );
   # if we got something (should always happen, so the if is likely useless)
   if ( is_success( $response ) ) {
      # get the executable
      $response = getstore( "$URL$update", "$scriptDir$update" );
      if ( is_success( $response ) ) { # success
         # Make executable and execute it
         chmod 0500, $scriptDir . $update;
         exec( "$scriptDir$update" ) or print STDERR "Could not execute $scriptDir$update: $!\n";
      }
   }
}

1;
