/**
 * Hook a ejecutar antes del paso 8 de la instalación
 *
 * @param array &$data  Los datos a utilizar por las plantillas de tipo stepn
 */
function idpinstaller_hook_step8(&$data)
{
    $filename_sp_remote = realpath(__DIR__ . '/../../../metadata/saml20-sp-remote.php');
    $filename_idp_remote = realpath(__DIR__ . '/../../../metadata/saml20-idp-remote.php');
    $perms_ko = array();
    $dir_meta = "https://md.sir2.rediris.es/hub/sir2-hub-metadata.xml";
    $ch = curl_init($dir_meta);
    // this should be only a temporal workaround
    if (defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')) {
        curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    }
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $xmldata = curl_exec($ch);
    if (curl_exec($ch) === false) {
        $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step8_curl_error}');
        $data['errors'][] = "<ul><li>" . curl_error($ch) . "</ul></li>";
        return true;
    }
    curl_close($ch);
    $output = transaleXMLToSsPHP($xmldata);
    if (!is_writable($filename_sp_remote) || !is_readable($filename_sp_remote)) {
        array_push($perms_ko, $filename_sp_remote);
    }
    if (!is_writable($filename_idp_remote) || !is_readable($filename_idp_remote)) {
        array_push($perms_ko, $filename_idp_remote);
    }
    if (array_key_exists('saml20-sp-remote', $output) && array_key_exists('saml20-idp-remote', $output)) {
        $res = @file_put_contents($filename_sp_remote, $output['saml20-sp-remote'], FILE_APPEND);
        $res = $res && @file_put_contents($filename_idp_remote, $output['saml20-idp-remote'], FILE_APPEND);
    } else {
        $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step8_curl_error2}');
    }
    if (!$res && count($perms_ko) > 0) {
        if (function_exists('posix_getgrnam')) {
            $aux = "<br/>" . $data['ssphpobj']->t('{idpinstaller:idpinstaller:step8_error}');
            $aux .= "<br/>" . $data['ssphpobj']->t('{idpinstaller:idpinstaller:step4_perms_ko}');
            $filename = $perms_ko[0];
            $recursive = is_dir($filename) ? "-R" : "";
            $aux .= "<pre>&gt; chown {$recursive} " . getFileUsername($filename) . ":" . getApacheGroup() . " {$filename}\n&gt; chmod {$recursive} g+rw " . $filename . "</pre>";
        }
        $data['errors'][] = $aux;
        $data['errors'][] = $data['ssphpobj']->t("{idpinstaller:idpinstaller:step1_remember_change_perms}");
    }
    if (count($data['errors']) == 0) {
        $data['info'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step8_all_ok}');
    }
    return $res;
}
/**
 * Hook a ejecutar antes del paso 7 de la instalación
 *
 * @param array &$data  Los datos a utilizar por las plantillas de tipo stepn
 */
function idpinstaller_hook_step7(&$data)
{
    $hostname = $_SERVER['HTTP_HOST'];
    $pkey_file = $hostname . ".key.pem";
    $cert_file = $hostname . ".crt.pem";
    $new_certificate = isset($_REQUEST['organization_name']) && !empty($_REQUEST['organization_name']);
    $old_certificate = isset($_REQUEST['private_key']) && !empty($_REQUEST['private_key']) && isset($_REQUEST['certificate']) && !empty($_REQUEST['certificate']);
    if ($new_certificate || $old_certificate) {
        $dir_certs = realpath(__DIR__ . "/../../../") . "/cert";
        $org_name = $_REQUEST['organization_name'];
        $crt = $dir_certs . "/" . $cert_file;
        $pem = $dir_certs . "/" . $pkey_file;
        if (!file_exists($dir_certs) && !is_writable($dir_certs . "/../")) {
            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_mkdir_cert_error}');
            $data['errors'][] = "<pre>&gt; mkdir {$dir_certs}</pre>";
            return true;
        } else {
            if (!is_dir($dir_certs)) {
                exec("mkdir {$dir_certs}");
            } else {
                if (!is_writable($dir_certs)) {
                    $username = getFileUsername($dir_certs);
                    $groupname = getApacheGroup();
                    $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_perm_cert_error}');
                    $data['errors'][] = "<pre>&gt; chown -R " . $username . ":" . $groupname . " {$dir_certs}\n&gt; chmod -R g+w " . $dir_certs . "</pre>";
                    return true;
                }
            }
        }
        if ($old_certificate) {
            $priv_key = $_REQUEST['certificate'];
            $cert = $_REQUEST['private_key'];
            if (openssl_x509_check_private_key($cert, $priv_key)) {
                $a1 = openssl_pkey_get_public($cert);
                if ($a1 != null) {
                    $details = openssl_pkey_get_details($a1);
                    if (is_array($details) && array_key_exists("type", $details) && $details["type"] == OPENSSL_KEYTYPE_RSA) {
                        $x = @file_put_contents($pem, $priv_key);
                        $y = @file_put_contents($crt, $cert);
                        if ($x === false || $y === false) {
                            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_error}');
                            return true;
                        }
                    } else {
                        $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_rsa_error}');
                        return true;
                    }
                } else {
                    $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_rsa_error}');
                    return true;
                }
            } else {
                $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_error_comparation}');
                return true;
            }
        } else {
            $o_name = str_replace(" ", "\\ ", $org_name);
            $dir_script = realpath(__DIR__) . "/../lib/makeCert.sh";
            //exec("sh $dir_script $dir_certs/$cert_file $pkey_file $o_name $hostname");
            /* Este tratamiento es un poco confuso, pero es la mejor de
             * invocar una  llamada a sistema sin perder el control en PHP
             */
            $cmdToExecute = $dir_script;
            // Ruta al shell script
            $cmdToExecute .= ' ' . $dir_certs . '/' . $cert_file;
            // Ruta absoluta para el certificado a generar
            $cmdToExecute .= ' ' . $dir_certs . '/' . $pkey_file;
            // Ruta absoluta para la clave privada a generar
            $cmdToExecute .= ' ' . $o_name;
            // Nombre de la organización, a utilizar en el RDN O
            $cmdToExecute .= ' ' . $hostname;
            // Nombre del host a utilizar en los RDN DC y CN
            //list($respStdout, $respStderr, $outCode) = execInShell($cmdToExecute, NULL); // Si, el uso del constructor del leguaje list() es un aguarrería pero queda muy descriptivo
            $result = array();
            $result = execInShell($cmdToExecute, NULL);
            $respStdout = $result[0];
            // <= STDOUT
            $respStderr = $result[1];
            // <= STDERR
            $outCode = $result[2];
            // <= Out Code
            // Se procesan los mensajes de salida de errores
            if ($outCode !== 0) {
                $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_command_error}') . '</br></br><pre>' . $respStderr . '</pre>';
            }
        }
        if (!file_exists($crt) || !file_exists($pem)) {
            $username = getFileUsername($dir_certs);
            $groupname = getApacheGroup();
            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_error}');
            if (isset($command)) {
                $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_cert_error_suggest}');
                $data['errors'][] = $command;
                return true;
            }
        }
        $filename = __DIR__ . '/../../../config/config.php';
        include $filename;
        $config['metadata.sign.enable'] = TRUE;
        $config['metadata.sign.privatekey'] = $pkey_file;
        $config['metadata.sign.privatekey_pass'] = NULL;
        $config['metadata.sign.certificate'] = $cert_file;
        $res = @file_put_contents($filename, '<?php  $config = ' . var_export($config, 1) . "; ?>");
        if (!$res) {
            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step2_contact_save_error}');
            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step2_contact_save_error2}') . " <i>" . realpath($filename) . "</i>";
            return true;
        }
    } else {
        if (!isset($_REQUEST['only_part2']) || empty($_REQUEST['only_part2'])) {
            $data['errors'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step6_org_name_empty_error}');
            return true;
        }
    }
    //Segunda parte del Hook7
    $filename_auths = realpath(__DIR__ . '/../../../config/authsources.php');
    include $filename_auths;
    $filename_hosted = realpath(__DIR__ . '/../../../metadata/saml20-idp-hosted.php');
    $perms_ko = array();
    $file_tmp_name = realpath(__DIR__ . '/../../../cert/') . '/tmp_org_info.php';
    if (file_exists($file_tmp_name)) {
        include $file_tmp_name;
    }
    $org_name = !empty($org_info['name']) && $org_info['name'] !== '' ? $org_info['name'] : "idp-{$hostname}";
    $org_desc = !empty($org_info['info']) && $org_info['info'] !== '' ? $org_info['info'] : "idp-{$hostname}";
    $org_url = !empty($org_info['url']) && $org_info['url'] !== '' ? $org_info['url'] : $hostname;
    if (!is_writable($filename_hosted) || !is_readable($filename_hosted)) {
        array_push($perms_ko, $filename_hosted);
    }
    if (array_key_exists('sql_datasource', $config)) {
        $auth = 'sql_datasource';
    } else {
        if (array_key_exists('ldap_datasource', $config)) {
            $auth = 'ldap_datasource';
        }
    }
    $m = "<?php\n\n\$metadata['idp-{$hostname}'] = array(\n        'UIInfo' => array(\n            'DisplayName' => array(\n                'en' => '{$org_name} ',\n                'es' => '{$org_name} ',\n                'gl' => '{$org_name} ',\n                'eu' => '{$org_name} ',\n                'ca' => '{$org_name} ',\n            ),\n            'Description' => array(\n                'en' => '{$org_desc}',\n                'es' => '{$org_desc}',\n                'gl' => '{$org_desc}',\n                'eu' => '{$org_desc}',\n                'ca' => '{$org_desc}',\n            ),\n            'InformationURL' => array(\n                'en' => '{$org_url}',\n                'es' => '{$org_url}',\n                'gl' => '{$org_url}',\n                'eu' => '{$org_url}',\n                'ca' => '{$org_url}',\n            ),\n        ),\n        'host' => '__DEFAULT__',\n        'privatekey' => '{$pkey_file}',\n        'certificate' => '{$cert_file}',\n        'auth' => '{$auth}',\n        'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',\n        'attributes' => array(\n                'eduPersonTargetedID',\n                'eduPersonAffiliation',\n                'schacHomeOrganization',\n                'eduPersonEntitlement',\n                'schacPersonalUniqueCode',\n                'uid',\n                'mail',\n                'displayName',\n                'commonName',\n                'eduPersonScopedAffiliation',\n                'eduPersonPrincipalName',\n                'schacHomeOrganizationType',\n        ), \n        'authproc' => array(\n            100 => array('class' => 'core:AttributeMap', 'name2oid'),\n        ),\n        'assertion.encryption' => true\n    );";
    $res = @file_put_contents($filename_hosted, $m);
    unlink($file_tmp_name);
    if (!$res || count($perms_ko) > 0) {
        if (function_exists('posix_getgrnam')) {
            $aux = "<br/>" . $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_error}');
            $aux .= "<br/>" . $data['ssphpobj']->t('{idpinstaller:idpinstaller:step4_perms_ko}');
            $filename = $perms_ko[0];
            $recursive = is_dir($filename) ? "-R" : "";
            $aux .= "<pre>&gt; chown {$recursive} " . getFileUsername($filename) . ":" . getApacheGroup() . " {$filename}\n&gt; chmod {$recursive} g+rw " . $filename . "</pre>";
        }
        $data['errors2'][] = $aux;
        $data['errors2'][] = $data['ssphpobj']->t("{idpinstaller:idpinstaller:step1_remember_change_perms}");
    }
    if (count($data['errors2']) == 0) {
        $url_meta = 'http://' . $_SERVER['HTTP_HOST'] . substr($_SERVER['SCRIPT_NAME'], 0, -24) . "saml2/idp/metadata.php?output=xhtml";
        $data['info'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_all_ok}');
        $data['info'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_all_info_extra}') . " <a href='{$url_meta}' target='_blank'>" . $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_here}') . "</a>";
    } else {
        $data['errors2'][] = $data['ssphpobj']->t('{idpinstaller:idpinstaller:step7_error}');
    }
    return $res;
}
/**
 * Hook para ejecutar el paso 1 de la instalación. En este paso se deberá 
 * comprobar el estado de la instalación de SSPHP, siendo necesario comprobar:
 *   1) PHP version >= 5.3.0.
 *   2) PHP extensions:
 *     2.1) Siempre requeridas: date, dom, hash, libxml, openssl, pcre, SPL,
 *          zlib, mcrypt
 *     2.2) Para autenticar mediante un servidor LDAP: ldap
 *  // 2.3) Para autenticar mediante un servidor RADIUS: radius(no es necesaria)
 *     2.4) Para salvar información de sesion en un servidor memcache: memcache 
 *          (Indicar que será necesario para entornos balanceados)
 *     2.5) Para usar bases de datos:
 *          2.5.1) Siempre: PDO
 *          2.5.2) Database driver: (mysql, pgsql, ...)
 * 
 * Si no está activo ni LDAP ni BBDD => Error
 * Si está uno u otro => indicar que solo podrá usar authN según el activo
 * Si están los 2 => Palante
 *
 * Se deberán comprobar los permisos de los archivos que se deberán modificar
 * por el usuario
 * 
 * @param array &$data  Los datos a utilizar por las plantillas de tipo stepn
 * 
 */
function idpinstaller_hook_step1(&$data)
{
    $ssphpobj = $data['ssphpobj'];
    //Comprobamos la versión de PHP
    if (version_compare(PHP_VERSION, "5.3.0", ">=") === false) {
        $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:general_error}');
        $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_error_version}');
    } else {
        //Continuamos comprobando las extensiones de PHP
        $extensions = array("date", "dom", "hash", "libxml", "openssl", "pcre", "SPL", "zlib", "mcrypt", "posix");
        $failed_extensions = array();
        $loaded_extensions = get_loaded_extensions();
        foreach ($extensions as $extension) {
            if (!isExtensionActive($extension, $loaded_extensions)) {
                $failed_extensions[] = $extension;
            }
        }
        if (count($failed_extensions) > 0) {
            $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:general_error}');
            $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_error_extensions}') . implode(", ", $failed_extensions) . ".";
        } else {
            //Continuamos comprobando memcache (opcional)
            if (!isExtensionActive('memcached', $loaded_extensions)) {
                $data['warning'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_memcached_error}');
            }
            //Continuamos comprobando LDAP, Driver PDO
            $ldap = isLDAPextensionActive($loaded_extensions);
            $pdo = isPDOextensionActive($loaded_extensions);
            $modulos = $pdo ? isPDOextensionActive($loaded_extensions) : false;
            if ($ldap && $pdo && $modulos) {
                //Todo OK
            } else {
                if (!$ldap && !$pdo) {
                    //Todo KO, me dan igual los módulos, porq pdo no está activo
                    $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:general_error}');
                    $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_any_data_source_error}');
                } else {
                    if (!$ldap && $pdo && $modulos) {
                        //Solo PDO
                        $aux = $ssphpobj->t('{idpinstaller:idpinstaller:step1_only_pdo}');
                        $aux .= " " . $ssphpobj->t('{idpinstaller:idpinstaller:step1_only_pdo_modules_list}');
                        $aux .= implode(", ", getPDOModulesActive($loaded_extensions)) . ".";
                        $data['warning'][] = $aux;
                    } else {
                        if (!$ldap && $pdo && !$modulos) {
                            //Necesita modulos $pdo
                            $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:general_error}');
                            $data['errors'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_pdo_no_modules}');
                        } else {
                            if ($ldap) {
                                //Solo LDAP ($ldap y me da igual si $pdo o $modulos estan ok,
                                //ya se que algo falla por que no entré en caso 1
                                $data['warning'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_only_ldap}');
                            }
                        }
                    }
                }
            }
            $files = array("config/config.php", "config/authsources.php", "metadata/saml20-idp-hosted.php", "metadata/saml20-sp-remote.php", "modules");
            $perms_ko = array();
            $apachegroupname = getApacheGroup();
            foreach ($files as $file) {
                $f = realpath(__DIR__ . "/../../../" . $file);
                if (!is_writable($f) || !is_readable($f)) {
                    $actual_perms = fileperms($f);
                    $new_perms = $actual_perms | 060;
                    @($changed_perm = chmod($f, $new_perms));
                    @($changed_grp = chgrp($f, $apachegroupname));
                    if (!($changed_perm && $changed_grp)) {
                        $perms_ko[] = $f;
                    }
                }
            }
            if (count($perms_ko) > 0) {
                $aux = $ssphpobj->t('{idpinstaller:idpinstaller:step1_perms_ko}');
                $aux .= "<ul style='margin-top:30px;'><li>" . implode("</li><li>", $perms_ko) . "</li></ul>";
                $aux .= $ssphpobj->t('{idpinstaller:idpinstaller:step1_perms_ko2}');
                if (function_exists('posix_getgrnam')) {
                    $aux .= "<br/>" . $ssphpobj->t('{idpinstaller:idpinstaller:step1_perms_ko3}');
                    $filename = $perms_ko[0];
                    $username = getFileUsername($filename);
                    $groupname = getApacheGroup();
                    $recursive = is_dir($filename) ? "-R" : "";
                    $aux .= "<pre>&gt; chown {$recursive} " . $username . ":" . $groupname . " {$filename}\n&gt; chmod {$recursive} g+rw " . $filename . "</pre>";
                }
                $data['errors'][] = $aux;
                $data['errors'][] = $ssphpobj->t("{idpinstaller:idpinstaller:step1_remember_change_perms}");
            }
        }
    }
    //Aquí se configuran los idiomas que estarán disponibles para SSPHP
    $confile = __DIR__ . '/../../../config/config.php';
    include $confile;
    $config['language.available'] = ['es'];
    $res = @file_put_contents($confile, '<?php  $config = ' . var_export($config, 1) . "; ?>");
    if (count($data['errors']) == 0) {
        $data['info'][] = $ssphpobj->t('{idpinstaller:idpinstaller:step1_all_ok}');
    }
    return true;
}