#!/usr/bin/perl

# ---------------------------------------------------------------
# Prontus CMS
# http://www.prontus.cl
# by Altavoz.net
#
# licensed under LGPL license.
# http://www.prontus.cl/license.html
# ---------------------------------------------------------------

# -------------------------------COMENTARIO GLOBAL---------------
# ---------------------------------------------------------------
# PROPOSITO.
# -----------
# Carga usuarios desde un archivo txt de prontus antiguo
# ---------------------------------------------------------------
# LLAMADAS A ARCHIVOS EXTERNOS.
# ------------------------------
# lee un archivo de texto indicado con lineas con formato:
# 1|Administrador|admin|$2a$10$XxLFaljiTzHiRhW0YhHuOeNSR9yjtv9czA2tlonawxCyG1bm9TNxgS|A|ealarcon@altavoz.net|0|0
# ---------------------------------------------------------------
# INVOCACIONES ACEPTADAS.
# ------------------------
# Por linea de comando
# ---------------------------------------------------------------

# ---------------------------------------------------------------
# DIRECTIVAS DE COMPILACION.
# ---------------------------
use utf8;
use strict;

BEGIN {
    use FindBin qw($Bin);
    my $pathLibsProntus = $Bin;
    unshift(@INC,$pathLibsProntus);
    $pathLibsProntus =~ s/\/[^\/]+\/?$//;
    unshift(@INC,$pathLibsProntus);
}

use sigtrap 'handler' => \&signal_catch, 'INT';
use sigtrap 'handler' => \&signal_catch, 'TERM';
use sigtrap 'handler' => \&signal_catch, 'KILL';

use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash en_base64);
use Encode qw(decode);
use Data::Dumper;

use lib_stdlog;
&lib_stdlog::set_stdlog($0, 51200);
use glib_fildir_03;
use prontus_varglb; &prontus_varglb::init();
use glib_html_03;
use lib_prontus;
use lib_setbd;
use prontus_auth;

my $ERROR = '';

main: {
    &lib_prontus::setUtf8();

    if (scalar @ARGV < 2) {
        print "Parámetros insuficientes. Modo de uso:\n";
        print "perl $0 <prontus_id> <archivo> <utf8=1, iso=0 o vacío>\n\n";
        exit;
    }

    $prontus_varglb::PRONTUS_ID = $ARGV[0];

    # path de cgis-cpn para ejecutar scripts
    my $path_cgicpn = "$prontus_varglb::DIR_SERVER/$prontus_varglb::DIR_CGI_CPAN";

    if (!lib_prontus::valida_prontus($prontus_varglb::PRONTUS_ID)) {
        print "Prontus ID no es válido\n";
        exit;
    }

    my $users_file = $ARGV[1];
    if (! -s $users_file) {
        print "[$users_file] No contiene información\n";
        exit;
    }
    my $path_data = '';
    # borra el nombre del archivo para obtener el path
    if ($users_file =~ /(.+\/)[^\/]+$/) {
        $path_data = $1;
    }

    my $utf8 = $ARGV[2] || 0;

    my $msg_load = &lib_prontus::load_config_by_id($prontus_varglb::PRONTUS_ID);
    if ($msg_load ne '') {
        print "Error al cargar configuracion: $msg_load\n";
        exit;
    }

    my $msg_err_bd = '';
    ($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $msg_err_bd) = &lib_prontus::conectar_prontus_bd();
    if (! ref($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID})) {
        print "ERROR al conectar a BD: $msg_err_bd\n";
        exit;
    }

    # crear tablas de usuarios
    my ($msg_ret, $hay_err) = &lib_setbd::crear_tabla_usuarios($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID});
    # drop table USERS, PROFILES, PORT_USERS, ART_USERS;
    if (!$hay_err || $msg_ret =~ /ya existe/) {
        print STDERR "[$prontus_varglb::PRONTUS_ID] tabla USERS existe \n";

        # hay que cargar los datos
        my %profiles = ('A' => 1, 'E' => 2, 'P' => 3 );
        if (open(my $DATA, '<', $users_file)) {
            binmode $DATA;
            while (<$DATA>) {
                $_ =~ s/\n$//;
                my ($users_id, $users_nom, $users_usr, $users_psw, $users_perfil, $users_email, $users_exp_days, $users_fec_exp) = split(/\|/, $_);
                if ($utf8) {
                    utf8::decode($users_nom);
                } else {
                    $users_nom = decode('iso-8859-1', $users_nom, Encode::FB_DEFAULT);
                }

                if (length($users_nom) > 50) {
                    $users_nom = substr($users_nom, 0, 50);
                }
                if (length($users_usr) > 32) {
                    $users_usr = substr($users_usr, 0, 32);
                }
                my $new_psw = '';
                if ($users_psw !~ /^\$2a\$\d{2}\$([A-Za-z0-9+\\.\/]{22})/) {
                    $new_psw = &gen_psw();
                    # print $new_psw , "\n";
                    $users_psw = prontus_auth::encrypt_password($new_psw);
                }
                if (length($users_email) > 255) {
                    $users_email = substr($users_email, 0, 255);
                }

                if ($users_id ne '' && $users_nom ne '' && $users_usr  ne '' && $users_psw ne '') {
                    $users_exp_days += 0;
                    $users_fec_exp += 0;
                    my $sql = "INSERT INTO USERS (USERS_ID, USERS_NOM, USERS_USR, USERS_PSW, USERS_PROFILE_ID, USERS_EMAIL, USERS_EXP_DAYS, USERS_FEC_EXP, USERS_RENEW_PSW, USERS_2FA, USERS_OIDC, USERS_DELETED) VALUES(?, ?, ?, ?, ?, ?, ?, ?, 1, 0, 0, 0)";
                    # perfil por defecto
                    my $perfil = 3;
                    if (defined($profiles{$users_perfil})) {
                        $perfil = $profiles{$users_perfil};
                    }
                    my @params = ($users_id, $users_nom, $users_usr, $users_psw, $perfil, $users_email, $users_exp_days, $users_fec_exp);
                    my $salida = &glib_dbi_03::ejecutar_sql_param($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $sql, \@params);

                    if ($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}->errstr) {
                        print "Error al guardar usuario:$users_id, $users_nom, $users_usr, $users_perfil, $users_email\n";
                    } else {
                        print "$users_id;$users_nom;$users_usr;$new_psw\n";
                    }
                }
            }
            close $DATA;
        } else {
            print STDERR "Error al abrir: $users_file\n";
        }
    } else {
        print STDERR "($msg_ret, $hay_err\n)";
    }

    ($msg_ret, $hay_err) = &lib_setbd::crear_tabla_port_users($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID});
    if (!$hay_err || $msg_ret =~ /ya existe/) {
        # cargar los datos
        if (-s $path_data."portusers.txt") {
            # PORTUSERS
            my ($port, $usr);
            if (open(my $DATA, '<', $path_data."portusers.txt")) {
                while (<$DATA>) {
                    $_ =~ s/\n$//;
                    ($port, $usr) = split(/\|/, $_);
                    if ($port ne '' && $usr ne '') {
                        $usr += 0;
                        my $sql = "insert into PORT_USERS values(?, ?, ?)";

                        my @params = ($usr, $port, $prontus_varglb::PRONTUS_ID);
                        my $salida = &glib_dbi_03::ejecutar_sql_param($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $sql, \@params);

                        if ($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}->errstr) {
                            print STDERR "Error actualizando la tabla PORT_USERS: sql[$sql][".$prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}->errstr."]\n";
                        }
                    }
                }
                close $DATA;
            } else {
                print STDERR "Error al abrir: $path_data/portusers.txt\n";
            }
        }
    } else {
        $ERROR = "($msg_ret, $hay_err)";
        exit;
    }

    ($msg_ret, $hay_err) = &lib_setbd::crear_tabla_art_users($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID});
    if (!$hay_err || $msg_ret =~ /ya existe/) {
        # cargar los datos
        if (-s $path_data."artusers.txt") {
            # ARTUSERS
            # carga los datos del prontus local
            if (open(my $DATA, '<', $path_data."artusers.txt")) {
                while (<$DATA>) {
                    $_ =~ s/\n$//;
                    my ($art, $usr) = split(/\|/, $_);
                    if ($art ne '' && $usr ne '') {
                        $usr += 0;
                        my $sql = "insert into ART_USERS values(?, ?, ?)";

                        my @params = ($usr, $art, $prontus_varglb::PRONTUS_ID);
                        my $salida = &glib_dbi_03::ejecutar_sql_param($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}, $sql, \@params);

                        if ($prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}->errstr) {
                            print STDERR "Error actualizando la tabla ART_USERS: sql[$sql][".$prontus_varglb::BD_CONN{$prontus_varglb::PRONTUS_ID}->errstr."]\n";
                        }
                    }
                }
                close $DATA;
            } else {
                print STDERR "Error al abrir: $prontus_varglb::DIR_SERVER$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_DBM'}/users/artusers.txt\n";
            }
        }
    } else {
        $ERROR = "($msg_ret, $hay_err)";
        exit;
    }
}
# ---------------------------------------------------------------
# funcion para capturar las señales INT y TERM y logearlas
sub signal_catch {
    print STDERR  "Terminado por signal @_\n";
    exit(0);
}

# genera password si no hay validas
sub gen_psw {
    my $strLength = int(($prontus_auth::PSW_MAX_LENGTH + $prontus_auth::PSW_MIN_LENGTH)/2);

    # validador regex password
    my $passCorrecta = 0;
    #expresión regular correcta
    my $regexCorrecta = '^(?=.*[A-Z])(?=.*[1-9])(?=.*[!%&@#$?_.*])\S{8,32}$';

    my @characters = (('A'..'Z'), ('a'..'z'), ('!','%','&','@','#','$','^','?','_','.','*'), (0..9));
    my $size = $#characters + 1;
    my $pwd = '';
    do{
        $pwd = '';
        for (1..$strLength) {
            $pwd .= $characters[int(rand($size))];
        }
        if ($pwd =~ /$regexCorrecta/) {
            $passCorrecta = 1;
        }

    } while(!$passCorrecta);

    return $pwd;
}
