#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - scripts/whmcs_config_generator          Copyright 2020 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

package scripts::whmcs_config_generator;

use strict;
use warnings;

use Cpanel::FileUtils::Write ();
use Cpanel::PHP              ();
use Cpanel::Rand::Get        ();
use Getopt::Long             ();
use Pod::Usage               ();

my $NOT_IN_CONFIG = 0;
my $NOT_IN_STDIN  = 1;
my $OK            = 2;

# Required fields.
my $required = {
    db_host     => $NOT_IN_CONFIG,
    db_port     => $NOT_IN_CONFIG,
    db_username => $NOT_IN_CONFIG,
    db_password => $NOT_IN_CONFIG,
    db_name     => $NOT_IN_CONFIG,
};

=head1 DESCRIPTION

This script generates a configuration file for whmcs

=head1 USAGE

whmcs_config_generator --dir={string} --order={csv string}

Where:

=over

=item * --dir={string} - the install directory for whmcs on the file system.

=item * --order={string} - the order parameters are sent via STDIN. Use a comma delimited string.

=item * --domain={string} - the domain for the WHMCS installation

Example:

  db_host,db_port,db_username,db_password,db_name

All of the following must be provided, but any order is fine. Make sure to send the parameters to STDIN in the order you select.

=over

=item * db_host - the database hostname. If on the same server use 'localhost', otherwise it must be a resolvable hostname.

=item * db_port - the port the database listens on. May be blank for the default.

=item * db_username - the username with permission to access the database.

=item * db_password - the password for the above database user.

=item * db_name - the name of the database where whmcs data is stored.

=back

=back

=cut

exit( __PACKAGE__->run(@ARGV) ) if !caller;

sub run {
    my ( $self, @args ) = @_;
    my ( $help, $man, $dir, $order, $domain, $verbose, $debug ) = ( 0, 0, '', '', '', 0, 0 );

    Getopt::Long::GetOptionsFromArray(
        \@args,
        'help|?'    => \$help,
        'man'       => \$man,
        'dir=s'     => \$dir,
        'order=s'   => \$order,
        'domain=s'  => \$domain,
        'verbose|v' => \$verbose,
        'debug'     => \$debug,
    ) or Pod::Usage::pod2usage(2);
    Pod::Usage::pod2usage(1) if $help;
    Pod::Usage::pod2usage( -exitval => 0, -verbose => 2 ) if $man;

    if ( !$dir ) {
        die 'You must pass an install directory parameter to this script: --dir';
    }

    if ( !$order ) {
        die 'You must pass the configuration order parameter to this script: --order';
    }

    if ( !$domain ) {
        die 'You must pass the domain parameter to this script: --domain';
    }

    my @props = split( m{,}, $order );
    foreach my $props (@props) {
        $required->{$props} = $NOT_IN_STDIN;
    }

    if ( my @missing = grep { $required->{$_} == $NOT_IN_CONFIG } keys %$required ) {
        die "You did not provide some required keys in the --order argument: " . join( ', ', @missing );
    }

    my $license_key = _get_license_key($domain) || 'UNKNOWN';

    my $config_text = <<EOM;
<?php
\$license = '$license_key';
\$templates_compiledir = 'templates_c';
\$mysql_charset = 'utf8';
EOM

    my $cc_encryption_hash = Cpanel::Rand::Get::getranddata( 64, [ 'A' .. 'Z', 'a' .. 'z', '0' .. '9' ] );
    $config_text .= "\$cc_encryption_hash = '" . Cpanel::PHP::escape_single_quotes($cc_encryption_hash) . "';\n";

    my @stdin;
    {
        local $/;
        @stdin = split( m{\n}, readline( \*STDIN ) );
    }

    foreach my $prop (@props) {
        if ( !@stdin ) {
            my @not_provided = grep { $required->{$_} == $NOT_IN_STDIN } keys %$required;
            die "You did not send the values for the following options via STDIN: " . join( ', ', @not_provided );
        }

        my $val = shift @stdin;
        if ( $prop eq 'db_host' ) {
            $val ||= 'localhost';
        }

        $config_text .= "\$$prop = '" . Cpanel::PHP::escape_single_quotes($val) . "';\n";
        $required->{$prop} = $OK;
    }

    if ($verbose) {
        print "Saving configuration to $dir/configuration.php\n";
    }
    if ($debug) {
        print $config_text . "\n";
    }

    Cpanel::FileUtils::Write::overwrite( "$dir/configuration.php", $config_text, 0644 );

    return 0;

}

sub _get_license_key {
    my ($domain) = @_;

    my $retrieval_func = eval {
        require Cpanel::Market::Provider::cPStore::Utils;
        Cpanel::Market::Provider::cPStore::Utils->can('get_session_data');
    };
    if ( !$retrieval_func ) {    # This will happen on cPanel & WHM versions before this license lookup was implemented.
        print "The license key cannot be automatically retrieved on this system. You will need to enter your license key manually.\n";
        return undef;
    }

    my $license_key = eval { $retrieval_func->()->{license}{$domain} };
    if ( !$license_key ) {
        print "The license information from the cPanel Store was not available or did not match the expected format. You will need to enter your license key manually.\n";
        return undef;
    }

    return $license_key;
}

1;

