<?php

function usage()
{
    echo "USAGE: panel_info.php <compatible|bootstrapper> [options]\n";
    echo "       panel_info.php compatible\n";
    echo "       panel_info.php checkkey <Plesk getkeyinfo script>\n";
    echo "       panel_info.php bootstrapper pkgname <Plesk config url>\n";
    echo "       panel_info.php bootstrapper filename <Plesk config url>\n";
    echo "       panel_info.php bootstrapper execute  [prep|pkgs|post] <Plesk config url>\n";
    echo "       panel_info.php bootstrapper rollback [prep|pkgs|post] <Plesk config url>\n";
    echo "       panel_info.php bootstrapper commit   [prep|pkgs|post] <Plesk config url>\n\n";
    exit(1);
}

function _die($msg)
{
    echo "$msg\n";
    exit(1);
}

function do_compatible()
{
    echo "PLESK_10_4_4 PLESK_11_0_9 PLESK_11_5_30 PLESK_12_0_18\n";
}

/**
 * Make xmlrpc query to KA server and gets upgrade available status.
 * See:
 *     https://support.parallels.com/Ticket/Display.html?id=1834123
 *
 * Format:
 *
 * <?xml version="1.0" encoding="UTF-8"?>
 * <methodCall>
 *     <methodName>pkp13.isUpgradeAvailable</methodName>
 *     <params>
 *         <param><value><string>***ProductLogin***</string></value></param>
 *         <param><value><string>***ProductPassword***</string></value></param>
 *         <param><value><struct>
 *         <member>
 *             <name>keyNumber</name>
 *             <value><string>***PLSK123456780000***</string></value>
 *         </member>
 *             <member>
 *                 <name>updatePassword</name>
 *                 <value><string>***wpww8o12345kyefo7n-zlj2y2ji01231***</string></value>
 *             </member>
 *         </struct></value></param>
 *         <param><value><string>***12.0.10***</string></value></param>
 *         <param><value><struct></struct></value></param>
 *     </params>
 * </methodCall>
 *
*/

function do_checkkey()
{
    if ($_SERVER['argc'] < 3)
        usage;

    exec($_SERVER['argv'][2], $output, $res);
    if ($res)
        _die("Command '$command' exited with errors");

    if (!isset($output[6]))
        _die("Failed to check whether a new license key is available.");

    if (isset($output[7]))
        _die("Incorrect output from the getkeyinfo utility.");

    $output_id = $output[0];
    $product_login = $output[1];
    $product_passwd = $output[2];
    $product_version = '11.5.30';
    $ka_url = $output[3];
    $key_number = $output[4];
    $key_password = $output[5];

    // Do xml-rpc request
    $query  = "<?xml version='1.0' encoding='UTF-8'?>";
    $query .= "<methodCall><methodName>pkp13.isUpgradeAvailable</methodName>";
    $query .= "<params><param><value><string>$product_login</string></value></param>";
    $query .= "<param><value><string>$product_passwd</string></value></param>";
    $query .= "<param><value><struct><member><name>keyNumber</name>";
    $query .= "<value><string>$key_number</string></value></member>";
    $query .= "<member><name>updatePassword</name>";
    $query .= "<value><string>$key_password</string></value></member>";
    $query .= "</struct></value></param>";
    $query .= "<param><value><string>$product_version</string></value></param>";
    $query .= "<param><value><struct></struct></value></param></params></methodCall>";

    $stream_options = array(
        'http' => array(
           'method'  => 'POST',
           'header'  => "accept: */*\r\n" .
                        "content-type: text/xml\r\n" .
                        "content-length: " . strlen($query) . "\r\n",
           'content' => $query,
        ),
    );

    $resultCode = 0;
    $resultDescr = '';

    try {
        $context  = stream_context_create($stream_options);

        $response = @file_get_contents($ka_url, null, $context);
        if (!$response)
            _die("Unable to get data from KA server");

        $xml = new SimpleXMLElement($response, LIBXML_NOBLANKS);
        if ($xml->params->param->value->struct->member) {
            foreach ($xml->params->param->value->struct->member as $data) {
                if ((string)$data->name == "resultCode")
                    $resultCode = (int)$data->value->int;

                if ((string)$data->name == "resultDesc")
                    $resultDescr = (string)$data->value;
            }
        }
    } catch (Exception $e) {
        _die("Unable to get data from KA server: " . $e->getMessage());
    }

    echo "$resultDescr\n";
    exit($resultCode);
}

function do_bootstrapper()
{
    if ($_SERVER['argc'] < 4)
        usage();

    $mode=$_SERVER['argv'][2];

    if ($_SERVER['argc'] > 4)
        $cfg_url=$_SERVER['argv'][4];
    else
        $cfg_url=$_SERVER['argv'][3];

    $content = @file_get_contents($cfg_url);
        if (!$content) _die("Unable to get a file '$cfg_url'");

    $xml = new SimpleXMLElement($content, LIBXML_NOBLANKS);
    if (!$xml->bootstrapper)
        _die("Bootstrapper's parameters are not found in config file '$cfg_url'");

    $func = "get_bootstrapper_" . $mode;
    if (!function_exists($func)) usage();

    $func($xml->bootstrapper);
}

function get_bootstrapper_filename($xml)
{
    if (!$xml->package)
        _die("Bootstrapper's package description is not found.");
    echo $xml->package->attributes()->file . "\n";
}

function get_bootstrapper_pkgname($xml)
{
    if (!$xml->package)
        _die("Bootstrapper's package description is not found.");
    echo $xml->package->attributes()->name . "\n";
}

function get_bootstrapper_execute($xml)
{
    get_bootstrapper_action($xml, "execute");
}

function get_bootstrapper_rollback($xml)
{
    get_bootstrapper_action($xml, "rollback");
}

function get_bootstrapper_commit($xml)
{
    get_bootstrapper_action($xml, "commit");
}

function get_bootstrapper_action($xml, $stage)
{
    if ($_SERVER['argc'] < 5)
        usage();

    $sequence=$_SERVER['argv'][3];

    if (!$xml->action)
        _die("Bootstrapper's package description is not found.");

    $result = array();

    foreach ($xml->action as $action => $data) {
        $attrs = $data->attributes();
        if (!$attrs->stage || (string)$attrs->stage != $stage)
            continue;

        if ((string)$attrs->sequence != $sequence)
            continue;

        // Actually AI config has yet another parameter 'sequence-order'
        // But we don't rely on it because it is really not used yet.
        $cmd_string   = "exec-cmd";
        $arr = explode(';', $attrs->$cmd_string);
        foreach ($arr as $cmd)
                echo $cmd . "\n";
        return 0;
    }
    echo "";
    return 0;
}

if ($_SERVER['argc'] < 2)
    usage();

$command=$_SERVER['argv'][1];

$func="do_" . $command;
$func();
